zoukankan      html  css  js  c++  java
  • 图形学 旋转与投影矩阵—1

    图形学 旋转与投影矩阵—1

    game101 第二次作业; webgl 实现

    使用 THREEJS 作为基础框架,构建各类矩阵,自定义矩阵运算,最终完成

    1. 正确构建模型矩阵
    2. 正确构建透视投影矩阵
    3. 看到变换后的三角形
    4. 按 A 和 D 三角形能够进行旋转
    5. 按 Q 和 E 三角形能够绕任意过原点的向量进行旋转

    最终效果

    第1次作业-最终效果

    基础变换

    以二维坐标系举例,变换分为三种,缩放变换:能够让图形宽高缩放指定倍数,旋转变换:让图形绕原点逆时针旋转任意角度,平移变换:让图像向某个方向移动指定的量。下文描述三种变换的矩阵形式。

    缩放变换

    \[\left[ \begin{matrix} x' \\ y ' \end{matrix} \right] = \left[ \begin{matrix} S_x & 0 \\ 0 & S_y \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \end{matrix} \right] \\ 公式一: 旋转矩阵变换 \]

    变换后的坐标简单写成 [x‘, y’] (实际上所有的坐标都是以列向量进行存储,这里特别说明),变换前的坐标为 [x, y]。变换时的数值运算如下

    \[\left\{ \begin{array}{} x'=S_x \times x \\ y'=S_y \times y \end{array} \right. \\ 公式一补充 \\ S_x: 表示宽缩放比例 \\ S_y: 表示高缩放比例 \]

    表示缩放就可以用 [Sx, Sy] ,对应矩阵为公式一中的旋转矩阵

    旋转变换

    旋转变换求解相对困难,此时可以采用代点求值,如下所示

    第二次作业-图一

    有个大小为 1*1 的正方形绕原点旋转 θ 角度得到第二个正方形,图上标示了两个红点,这两个红点就是可以代入进行计算的点,将旋转前的 [x, y] 与旋转后的 [x', y'] 代入下述方程中,解出旋转变换矩阵

    \[设置旋转矩阵的每个参数分别为\: a, b, c, d \\ 第一步: 列出方程\\ \left[ \begin{matrix} x' \\ y ' \end{matrix} \right] = \left[ \begin{matrix} a & b \\ c & d \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \end{matrix} \right] \\ \\ 第二步:代入两个代表点的变换\\ \left[ \begin{matrix} 1 \\ 0 \end{matrix} \right] = \left[ \begin{matrix} a & b \\ c & d \end{matrix} \right] \times \left[ \begin{matrix} \cos(\theta) \\ \sin(\theta) \end{matrix} \right] \\ \\ \left[ \begin{matrix} 0 \\ 1 \end{matrix} \right] = \left[ \begin{matrix} a & b \\ c & d \end{matrix} \right] \times \left[ \begin{matrix} -\sin(\theta) \\ \cos(\theta) \end{matrix} \right] \\ \\ 第三步: 得到结果 \\ \left[ \begin{matrix} a & b \\ c & d \end{matrix} \right] = \left[ \begin{matrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{matrix} \right] \\ \\ \left[ \begin{matrix} x' \\ y ' \end{matrix} \right] = \left[ \begin{matrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \end{matrix} \right] \]

    由于采用代入法求解,将 [0, 1] 和 [1, 0] 点代入方程,最终求得了旋转矩阵中 a, b, c, d 的值。旋转矩阵求解的问题就得到了解决。

    平移变换

    由前两节可以看出来,将一个点设为 [x, y],将其与 2*2 的矩阵相乘,是无法得到 [x+a, y+b] 的代数式,只能得到 [a*x, b*y] 这种形式的坐标

    针对 2*2 的矩阵无法求得 [x+a, y+b] 形式的坐标问题,有两种解决方法,思路如下

    \[思路一: \: \left[ \begin{matrix} x' \\ y ' \end{matrix} \right] = \left[ \begin{matrix} x \\ y \end{matrix} \right] + \left[ \begin{matrix} t_x \\ t_y \end{matrix} \right] \\ t_x: 在x轴上移动的距离 \\ t_y: 在y轴上移动的距离 \\ \\ 思路二: \: \left[ \begin{matrix} x' \\ y ' \\ 1 \end{matrix} \right] = \left[ \begin{matrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \\ 1 \end{matrix} \right] \\ 增加一个维度实现平移 \]

    由于第二个思路可以转换为矩阵相乘,与旋转和缩放形式类似,因此最好选用思路二,统一运算公式 变换后点坐标 = 变换矩阵 * 变换前坐标,选用思路二需要设定一些规则

    1. 点的表示 [x, y, 1]
    2. 向量的表示 [x, y, 0]

    这样做的好处就是不用单独为平移变换计算变换的公式,全部采用通用公式,虽然增加了一个维度,但是计算起来更加方便,可以看出如下几样好处

    1. 分辨出了点和向量的差别
    2. 点 + 向量 = [2x, 2y, 1],依然是点,符合要求,减法也一样
    3. 向量 + 向量 = [2x, 2y, 0],依然是向量,符合要求,减法也一样
    4. 点 + 点 = [2x, 2y, 2],第三个参数默认是 1,因此它被等效于 [x, y, 1],这时还可以发现,求出的是两点连线的中点,符合要求

    结论

    表示基础变换时,我们可以用矩阵表示 缩放 和 旋转 ,不能表示平移,为了能让公式统一,多用了一个维度表示点的信息,虽然多花费了一些空间,但是得到了更多的好处:分辨了点和向量,统一了计算公式

    由于想输出的太多,只写一篇文章应该会太长,因此大概分为三篇,第一篇讲在二维坐标下的矩阵变换,第二篇和第三篇讲在三维坐标下的变换,视图矩阵,投影矩阵的构造以及代码实现

    希望读者在看完后能提出意见, 点个赞, 鼓励一下, 我们一起进步. 加油 !!
  • 相关阅读:
    HTML-利用CSS和JavaScript制作一个切换图片的网页
    HTML-★★★格式与布局fixed/absolute/relative/z-index/float★★★
    HTML-CSS样式表-★★★常用属性★★★及基本概念、分类、选择器
    HTML-★★★★★表单★★★★★
    HTML-图片热点、网页内嵌、网页拼接、快速切图
    HTML-常用标签与表格标签
    HTML-基础及一般标签
    C#-★结构体★
    C#-函数的传值与传址
    C#-★★函数★★
  • 原文地址:https://www.cnblogs.com/xiaxiangx/p/15725208.html
Copyright © 2011-2022 走看看