学习OpenGL——第六天

42 阅读3分钟

向量与矩阵基础知识笔记


向量

1. 点乘(Dot Product)

  • 点乘可以用来判断两个向量是否正交(即两向量成直角)或平行。
  • 通过点乘结果,可以计算两个非单位向量的夹角。具体方法是:点乘的结果除以两个向量长度的乘积,得到的就是夹角的余弦值(cosθ)。

cosθ=abab\cos \theta = \frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\| \|\mathbf{b}\|}


2. 叉乘(Cross Product)

  • 叉乘只在三维空间(3D)中有定义。
  • 叉乘需要两个不平行的向量作为输入,结果是一个正交于这两个向量的新向量。
  • 如果输入的两个向量本身就正交,则叉乘后会得到三个互相正交的向量。

a×b=(aybzazbyazbxaxbzaxbyaybx)\mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_y b_z - a_z b_y \\ a_z b_x - a_x b_z \\ a_x b_y - a_y b_x \end{pmatrix}


矩阵

  • 矩阵的每一项称为元素(Element)。
  • 矩阵通过 (i, j) 进行索引,i 表示行,j 表示列。例如,2×3 的矩阵有2行3列,称为“2×3矩阵”或矩阵的维度(Dimension)。
  • 注意:与2D图像索引的(x, y)顺序相反,矩阵中获取元素4的索引是(2, 1)(第二行,第一列)。

矩阵与向量的乘法

1. 缩放(Scaling)

  • 缩放是指改变向量的长度,但保持方向不变。
  • 在2D或3D中,分别对每个轴(x、y、z)进行缩放。例如,可以定义一个缩放向量(S1, S2, S3),每个分量对应一个轴。
  • OpenGL中,3D缩放时,2D的z轴可以设为1,保证z轴数值不变。
  • 非均匀缩放:各轴缩放因子不同;均匀缩放:所有轴缩放因子相同。
  • 缩放矩阵可表示为:

(sx0000sy0000sz00001)(xyzw)=(sxxsyyszzw)% 缩放变换 \begin{pmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x \\ y \\ z \\ w \end{pmatrix} = \begin{pmatrix} s_x x \\ s_y y \\ s_z z \\ w \end{pmatrix}


2. 位移(Translation)

  • 位移是指将原始向量加上另一个向量,从而获得一个新位置的向量。
  • 在4×4矩阵中,位移值位于第四列最上面的三个位置。如果位移向量为(Tx, Ty, Tz),则位移矩阵可定义为:

(100tx010ty001tz0001)(xyzw)=(x+txwy+tywz+tzww)% 位移变换 \begin{pmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x \\ y \\ z \\ w \end{pmatrix} = \begin{pmatrix} x + t_x w \\ y + t_y w \\ z + t_z w \\ w \end{pmatrix}

  • 位移需要用到向量的w分量(齐次坐标),否则无法实现。
  • 3×3矩阵无法实现位移操作,因为没有足够的空间存放位移值。

齐次坐标(Homogeneous Coordinates)

向量的w分量称为齐次坐标。

从齐次向量还原3D向量时,需要将x、y、z分别除以w。

齐次坐标的优点:允许在3D向量上进行位移。

如果w=0,则该向量为方向向量(不能位移)。


3. 旋转(Rotation)

  • 2D或3D空间中的旋转通过角度表示,可用角度制或弧度制。360°=2π弧度。
  • 常用角度与弧度互转公式:
    • 弧度转角度:角度 = 弧度 × (180.0f / π)
    • 角度转弧度:弧度 = 角度 × (π / 180.0f)
    • π ≈ 3.14159265359
  • 3D旋转需指定一个旋转轴和一个角度。旋转矩阵根据旋转轴不同而不同,记作θ:
    • 沿x轴旋转:

(10000cosθsinθ00sinθcosθ00001)(xyzw)=(xcosθysinθzsinθy+cosθzw)% 绕X轴旋转 \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta & 0 \\ 0 & \sin\theta & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x \\ y \\ z \\ w \end{pmatrix} = \begin{pmatrix} x \\ \cos\theta y - \sin\theta z \\ \sin\theta y + \cos\theta z \\ w \end{pmatrix}

    • 沿y轴旋转:

(cosθ0sinθ00100sinθ0cosθ00001)(xyzw)=(cosθx+sinθzysinθx+cosθzw)% 绕Y轴旋转 \begin{pmatrix} \cos\theta & 0 & \sin\theta & 0 \\ 0 & 1 & 0 & 0 \\ -\sin\theta & 0 & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x \\ y \\ z \\ w \end{pmatrix} = \begin{pmatrix} \cos\theta x + \sin\theta z \\ y \\ -\sin\theta x + \cos\theta z \\ w \end{pmatrix}

    • 沿z轴旋转:

(cosθsinθ00sinθcosθ0000100001)(xyzw)=(cosθxsinθysinθx+cosθyzw)% 绕Z轴旋转 \begin{pmatrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x \\ y \\ z \\ w \end{pmatrix} = \begin{pmatrix} \cos\theta x - \sin\theta y \\ \sin\theta x + \cos\theta y \\ z \\ w \end{pmatrix}


4. 矩阵组合(Matrix Composition)

  • 矩阵变换的强大之处在于,可以将多个变换通过矩阵乘法组合成一个矩阵。
  • 注意:矩阵乘法不满足交换律,顺序很重要。
    • 乘法顺序:最右边的矩阵先与向量相乘,推荐从右向左理解。
    • 通常建议:先缩放→再旋转→最后位移,否则变换效果会互相影响。

(100tx010ty001tz0001)(cosθsinθ00sinθcosθ0000100001)(sx0000sy0000sz00001)=(sxcosθsysinθ0txsxsinθsycosθ0ty00sztz0001)\begin{pmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} = \begin{pmatrix} s_x \cos\theta & -s_y \sin\theta & 0 & t_x \\ s_x \sin\theta & s_y \cos\theta & 0 & t_y \\ 0 & 0 & s_z & t_z \\ 0 & 0 & 0 & 1 \end{pmatrix}


GLM 简介

  • GLM(OpenGL Mathematics)是一个仅包含头文件的数学库,无需链接和编译,只需包含头文件即可。
  • 从0.9.9版本起,GLM矩阵类型默认初始化为零矩阵(所有元素为0),而不是单位矩阵(对角线为1,其余为0)。
    • 如果使用0.9.9及以上版本,建议初始化方式为:glm::mat4 mat = glm::mat4(1.0f);
  • 在GLSL中,矩阵可以直接作为mat4类型uniform变量传递给着色器。例如,在顶点着色器中用矩阵uniform乘以位置向量。

GLM三种主要变换操作

  • 缩放变换:glm::mat4 scale(glm::mat4 const& m, glm::vec3 const& v);
  • 旋转变换:glm::mat4 rotate(glm::mat4 const& m, float angle, glm::vec3 const& axis);
  • 平移变换:glm::mat4 translate(glm::mat4 const& m, glm::vec3 const& v);
函数名第一个参数第二个参数第三个参数返回值
translateglm::mat4glm::vec3-glm::mat4
rotateglm::mat4float(角度)glm::vec3(轴)glm::mat4
scaleglm::mat4glm::vec3-glm::mat4