计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 03.数学基础

1. 数学基础

1.1. 3D坐标系

名称坐标系
DirectX左手坐标系
OpenGL右手坐标系

1.2. 点

3D 坐标系中的点由三个坐标值组成,分别表示该点的 x、y、z 坐标。如(1, 2, 3)表示该点在 x 轴方向上 1 个单位,在 y 轴方向上 2 个单位,在 z 轴方向上 3 个单位。通常用vec3来表示一个点,如vec3(1, 2, 3)。 实际使用中,我们通常使用齐次坐标,即vec4来表示一个点,其中第四个分量通常为1.0f,表示该点位于三维空间中。如vec4(1, 2, 3, 1.0f)。

1.3. 矩阵

矩阵是矩形的值阵列,在3D 图形计算中要用到的矩阵通常为 4*4 的矩阵。矩阵可以用来表示平移、旋转、缩放等变换。矩阵的乘法满足结合律,即 (AB)C = A(BC)。
下图是一个 4*4 的矩阵的示例:
[ a b c d e f g h i j k l m n o p ] \begin{bmatrix} a & b & c & d \\ e & f & g & h \\ i & j & k & l \\ m & n & o & p \\ \end{bmatrix} aeimbfjncgkodhlp
我们用mat4来表示一个 4*4 的矩阵

mat4::identity()
单位矩阵,即对角线上的元素为1,其他元素为0的矩阵
[ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ] \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} 1000010000100001
任何矩阵与单位矩阵相乘,结果仍为该矩阵

转置矩阵
以主对角线为轴,将矩阵进行翻转,得到的矩阵称为转置矩阵
比如下面的矩阵:
[ a e i m b f j n c g k o d h l p ] \begin{bmatrix} a & e & i & m \\ b & f & j & n \\ c & g & k & o \\ d & h & l & p \\ \end{bmatrix} abcdefghijklmnop
转置矩阵为:
[ a b c d e f g h i j k l m n o p ] \begin{bmatrix} a & b & c & d \\ e & f & g & h \\ i & j & k & l \\ m & n & o & p \\ \end{bmatrix} aeimbfjncgkodhlp


注意右上角的T,表示转置矩阵。
GLM 库中提供了glm::transpose()函数,GLSL中提供了transpose()函数,用于计算矩阵的转置矩阵。

矩阵加法
矩阵加法满足交换律,即 A+B=B+A。

GLM 库中提供了glm::add()函数,GLSL中重载了+运算符,用于计算矩阵的加法。

矩阵乘法
矩阵乘法不满足交换律,即 AB≠BA。
3D图形学中,点与矩相乘通常从右向左,得到的是该点在矩阵变换后的新坐标,即得到的仍然是****。

此处的点采用了齐次坐标,即第四个分量通常为1.0f。

矩阵与矩阵相乘,得到的是**矩阵**。

GLM 、GLSL库中重载了*运算符,用于计算矩阵的乘法。

在3D图形学中,将大量使用 44矩阵 与44矩阵相乘,以进行矩阵的合并,从而得到一个变换矩阵。

逆矩阵
逆矩阵是矩阵的乘法逆运算,即 AB=BA=I,其中 I 为单位矩阵。
A 的逆矩阵记为 A − 1 A的逆矩阵记为A^{-1} A的逆矩阵记为A1
A − 1 的逆矩阵记为 ( A − 1 ) − 1 = A A^{-1}的逆矩阵记为(A^{-1})^{-1}=A A1的逆矩阵记为(A1)1=A

2.1. 变换矩阵

2.1.1. 平移矩阵

平移矩阵用于将点在 x、y、z 轴方向上平移一定的距离。

注意是从右向左相乘,得到的是该点在矩阵变换后的新坐标,即得到的仍然是****。
在GLM中,平移矩阵使用glm::translate()函数来创建。

2.1.2. 缩放矩阵

缩放矩阵用于将点在 x、y、z 轴方向上缩放一定的倍数。

在GLM中,缩放矩阵使用glm::scale()函数来创建。
可以通过缩放矩阵来将坐标系从右手坐标系转换为左手坐标系
其缩放矩阵为:
[ 1 0 0 0 0 1 0 0 0 0 − 1 0 0 0 0 1 ] \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} 1000010000100001

2.1.3. 旋转矩阵

旋转矩阵用于将点绕 x、y、z 轴旋转一定的角度。

在GLM中,旋转矩阵使用glm::rotate()函数来创建。
实际使用中,当3D空间中旋转轴没有穿过原点时,需要按以下方式进行:

  1. 先平移至原点
  2. 再进行旋转,即绕X,Y,Z轴旋转 。这就是欧拉角旋转,但这种方式在某些情况下会存在万向节锁的问题。所以建议使用四元数旋转。
  3. 最后再平移回原点。

2.2. 向量

向量是具有大小和方向的量,通常用箭头表示


向量 V ⃗ \vec{V} V 的两种表示方式 ,我们通常将向量的起点放在原点,即起点为(0,0,0),向量的终点为(x,y,z)。

V ⃗ = [ x y z ] \vec{V} = \begin{bmatrix} x \\ y \\ z \\ \end{bmatrix} V = xyz

向量的加减法

归一化
向量的模(长度)为:
x 2 + y 2 + z 2 \sqrt{x^2+y^2+z^2} x2+y2+z2
归一化就是将向量的模(长度)变为1,即:
V ⃗ x 2 + y 2 + z 2 \frac{\vec{V}}{\sqrt{x^2+y^2+z^2}} x2+y2+z2 V

在GLM中,使用glm::normalize()函数来对向量进行归一化。

向量的点积
点积是向量的一个重要运算,其结果是一个标量
A ⃗ ⋅ B ⃗ = A ⃗ × B ⃗ = x 1 x 2 + y 1 y 2 + z 1 z 2 \vec{A} \cdot \vec{B} = \vec{A} \times \vec{B} = x_1x_2+y_1y_2+z_1z_2 A B =A ×B =x1x2+y1y2+z1z2
在GLM中,使用glm::dot()函数来计算两个向量的点积。

采用向量的点积可以计算两个向量的夹角,即:
cos ⁡ θ = A ⃗ ⋅ B ⃗ x a 2 + y a 2 + z a 2 × x b 2 + y b 2 + z b 2 \cos{\theta} = \frac{\vec{A} \cdot \vec{B}}{\sqrt{xa^2+ya^2+za^2} \times \sqrt{xb^2+yb^2+zb^2}} cosθ=xa2+ya2+za2 ×xb2+yb2+zb2 A B
当两个向量均为单位向量时,点积等于两个向量的夹角的cos值:
A ⃗ ⋅ B ⃗ = cos ⁡ θ \vec{A} \cdot \vec{B} = \cos{\theta} A B =cosθ

实际使用中,我们通常将向量归一化
归一化向量点积的特点

  1. 点积等于两个向量夹角的cos值
  2. 如果向量正交,则点积等于0
  3. 如果向量平行且方向一致,则点积等于1
  4. 如果向量平行且方向相反,则点积等于-1
  5. 如果两个向量的夹角在-90度到90度之间,则点积为正数

向量的叉积
叉积是向量的另一个重要运算,其结果是一个向量
A ⃗ × B ⃗ = [ y 1 z 2 − y 2 z 1 z 1 x 2 − z 2 x 1 x 1 y 2 − x 2 y 1 ] \vec{A} \times \vec{B} = \begin{bmatrix} y_1z_2-y_2z_1 \\ z_1x_2-z_2x_1 \\ x_1y_2-x_2y_1 \\ \end{bmatrix} A ×B = y1z2y2z1z1x2z2x1x1y2x2y1
在GLM中,使用glm::cross()函数来计算两个向量的叉积。
叉积具有以下特点:

  1. 叉积的方向垂直于两个向量所在的平面
  2. 叉积生成的新向量与两个向量形成的坐标系是右手坐标系
  3. 叉积不满足交换律,即cross(A,B) != cross(B,A),坐标系不同,一个是右手坐标系,一个是左手坐标系

4.1. 局部坐标系和世界坐标系

局部坐标系:物体在局部坐标系中的位置和方向,也称为模型坐标系。
世界坐标系:世界坐标系是全局坐标系,是全局统一的坐标系

将物体从局部坐标系变换到世界坐标系的过程称为模型变换,模型变换包括平移、旋转和缩放。其使用的矩阵称为模型矩阵或M。

4.2. 视觉空间

视觉空间是观察者所看到的空间,也称为视口空间视口坐标系。视觉空间由观察者位置、观察方向和观察目标组成。

如上图所示,观察3D世界:

  1. 观察者位置:观察者所在的位置,即相机位置
  2. 观察方向:观察者所面向的方向,即相机方向,生成相机自身的坐标系UVN ,也称为相机坐标系或视觉空间
  3. 观察目标:观察者所观察的目标,即相机目标
  4. 定义一个视体
  5. 将视体内的对象投影到投影平面上

在OpenGL中,有一个固定在原点,面向z轴负方向的相机,即相机位置为(0,0,0),观察方向为(0,0,-1)

局部空间 → 世界空间 → 视觉空间(相机空间)→ 裁剪空间(投影空间) → 屏幕空间


从世界空间到视觉空间,需要使用视图矩阵V进行变化 ,其逻辑如下:

  1. 将P平移,其向量为负相机位置
  2. 将P旋转,其角度为负的相机旋转的欧拉角
    注:相机不需要缩放,也就没有缩放矩阵

上面的变换称为视图变换,其使用的矩阵称为视图矩阵或V。
注意:视图变换是针对世界坐标系进行的,而不是针对局部坐标系进行的。

由模型矩阵M、视图矩阵生成 模型-视图(MV)矩阵:
M V = V × M MV = V \times M MV=V×M

4.3. 投影空间

投影空间是投影平面上所显示的空间,也称为裁剪空间裁剪坐标系。投影空间由观察者位置、观察方向和观察目标组成。

4.3.1. 正交投影


正交投影是投影空间的一种,其投影平面与坐标轴平行,也称为平行投影。正交投影的投影平面称为视平面,其投影结果称为正交投影
在OpenGL中,使用glOrtho()函数来创建正交投影矩阵。

正交投影的特点:

  1. 远近裁剪面相等,远的物体和近的物体一样大
  2. 与我们眼睛所见的真实世界不同

我们在3D图形学中,通常使用透视投影,而不是正交投影。

4.3.2. 透视投影


透视投影是投影空间的一种,其投影平面与坐标轴不平行,近的物体显示得大,远的物体显示得小。通常使用透视矩阵P,需要的参数有:

  1. 宽高比
  2. 近裁剪面
  3. 远裁剪面
  4. Y方向视场角(FOV)

采用glm::perspective()函数来创建透视投影矩阵(4*4矩阵)。

4.4. LookAt矩阵


LookAt矩阵是视图矩阵的一种,用于定义观察者(相机)在3D空间中的视角。它将世界空间中的坐标转换到观察空间(相机空间)中。
构成要素
LookAt矩阵需要三个关键向量:

  1. 相机位置(Eye Position):观察者在世界空间中的位置坐标
  2. 观察目标(Target Position):相机看向的目标点
  3. 上方向向量(Up Vector):定义相机的上方向,通常是(0,1,0)

在OpenGL中,使用glm::lookAt()函数来创建LookAt矩阵。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值