LearnGL - 06 - Matrix - 矩阵01 - 齐次坐标、缩放、旋转矩阵(欧拉 Euler 角)

本文深入探讨3D图形学中的矩阵变换,包括点在坐标系下的定位、矩阵的扩展与偏移、齐次坐标的概念及应用、缩放与旋转矩阵的理解。通过实例解析,阐述了矩阵在3D空间中如何实现坐标变换、缩放和旋转,以及如何避免万向锁问题。


LearnGL - 学习笔记目录

本人才疏学浅,如有什么错误,望不吝指出。

上一篇:LearnGL - 05.3 - 封装 Main.cpp 中重复 GLFW代码,让新建的项目更方便的开展。

这一篇:这篇我们在讲一丢丢关于矩阵的内容。


本来我不想写关于矩阵的内容。因为要排版很多内容(LaTex挺多),-_-!!!,但是想了一下,还是加上吧,因为这个是我自己以前看过的资料总结的,先暂时写这么多,后续有空再补上关于矩阵的其他内容。

这里推荐一下关于矩阵的完整系统教学,我也是参考了其他网站上关于 OpenGL 学习资料中的:变换,这篇文章里介绍的:

可汗学院

最近需要系统学习一下这方面资料,发现他这在线免费的教程资料太太太好了,忍不住要分享一下。

相比我之前在:网易公开课,里看的熟肉的质量好多了,因为我上面推荐的可汗学院的网站是官方网,虽然的内容是英文版,但是还好的是陌生单词不会很多。

可汗的故事以前看过,反正后来是比尔盖茨投资他继续为科学教育助力,因为比尔盖茨也是他的粉丝,而我,是比尔盖茨的粉丝。

在这里插入图片描述

看看:“A world class education for anyone, anywhere 100% free。”,这就是初心,感动人的工匠,这是造福人类啊。


OK,那么开始正文:

变换 这篇文章里排版什么的我是非常喜欢,看起来很舒服。

但里面刚好有一丢丢我会的内容没提到,我也在此基础上添加一丢丢笔记吧。

注意,什么是 向量标量向量相乘向量加减法向量点积向量乘积矩阵乘法 我都不再说明,因为 变换 说得足够的清晰了。

点在坐标系下的定位

我们先了解 点在坐标系下的定位

先看看坐标轴长什么样:
在这里插入图片描述
这些内容大家肯定了解,毕竟都是初中知识。

O是坐标系原点,X就是X轴,其他两个就是Y轴和Z轴。

它们看起来就像是 三个向量

没错,就是三个向量,OK,那么我们将它们每个轴的向量都标记上向量分量:
在这里插入图片描述
我们先给轴都定义一个标识符(字母上面加一个指向右的箭头)吧: X → \overrightarrow X X 表 X轴,以此类推 Y → 、 Z → \overrightarrow Y、\overrightarrow Z Y Z
然后原点是: O O O

X → = ( 1 , 0 , 0 ) \overrightarrow X=(1,0,0) X =(1,0,0)
Y → = ( 0 , 1 , 0 ) \overrightarrow Y=(0,1,0) Y =(0,1,0)
Z → = ( 0 , 0 , 1 ) \overrightarrow Z=(0,0,1) Z =(0,0,1)

从坐标轴长度可以看出来,都是 1的长度(单位化向量长度都是1)。
所以三个向量都是 单位向量(基向量)。
而且三个向量都是相互 垂直的(正交的)。
所以我们也可以叫:正交基向量,也叫 自然基标准化(归一化)基向量,叫法挺多,选一个方便我们理解的就好,暂时选用 正交基向量

如果我有任意一个点像在此坐标系下显示位置,我们如果处理呢?

假设我有一个点P,它就在原点O(0,0,0)的位置上,它和原点重合了,我们想让它右边(X轴正方向)移动0.5的位移量,好让我们看清这个点:

那么下面P点的位置变成了: O + 0.5 X → O+0.5 \overrightarrow X O+0.5X

就是在:原点 O O O基础上往 X → \overrightarrow X X 偏移0.5的量

O = ( 0 , 0 , 0 ) , X → = ( 1 , 0 , 0 ) O=(0,0,0), \overrightarrow X=(1,0,0) O=(0,0,0),X =(1,0,0)
P 点 = O + 0.5 X → P点=O+0.5\overrightarrow X P=O+0.5X
= ( 0 , 0 , 0 ) + 0.5 ⋅ ( 1 , 0 , 0 ) =(0,0,0)+0.5\cdot(1,0,0) =(0,0,0)+0.5(1,0,0)
= ( 0.5 , 0 , 0 ) =(0.5,0,0) =(0.5,0,0)

在这里插入图片描述
然后再向上(Y轴正方向)移动0.2个位移量: O + 0.5 X → + 0.2 Y → O+0.5\overrightarrow X+0.2\overrightarrow Y O+0.5X +0.2Y

就是在:原点 O O O基础上往 X → \overrightarrow X X 偏移0.5的量,再往 Y → \overrightarrow Y Y 偏移0.2的量

O = ( 0 , 0 , 0 ) , X → = ( 1 , 0 , 0 ) , Y → = ( 0 , 1 , 0 ) O=(0,0,0), \overrightarrow X=(1,0,0),\overrightarrow Y=(0,1,0) O=(0,0,0),X =(1,0,0),Y =(0,1,0)
P 点 = O + 0.5 X → + 0.2 Y → P点=O+0.5\overrightarrow X+0.2\overrightarrow Y P=O+0.5X +0.2Y
= ( 0 , 0 , 0 ) + 0.5 ⋅ ( 1 , 0 , 0 ) + 0.2 ⋅ ( 0 , 1 , 0 ) =(0,0,0)+0.5\cdot(1,0,0)+0.2\cdot(0,1,0) =(0,0,0)+0.5(1,0,0)+0.2(0,1,0)
= ( 0.5 , 0 , 0 ) + ( 0 , 0.2 , 0 ) =(0.5,0,0)+(0,0.2,0) =(0.5,0,0)+(0,0.2,0)
= ( 0.5 , 0.2 , 0 ) =(0.5,0.2,0) =(0.5,0.2,0)
在这里插入图片描述
然后再向前(Z轴正方向)移动0.5个位移量: O + 0.5 X → + 0.2 Y → + 0.5 Z → O+0.5\overrightarrow X+0.2\overrightarrow Y+0.5\overrightarrow Z O+0.5X +0.2Y +0.5Z

就是在:原点 O O O基础上往 X → \overrightarrow X X 偏移0.5的量,再往 Y → \overrightarrow Y Y 偏移0.2的量,再往 Z → \overrightarrow Z Z 偏移0.5的量

O = ( 0 , 0 , 0 ) , X → = ( 1 , 0 , 0 ) , Y → = ( 0 , 1 , 0 ) , Z → = ( 0 , 0 , 1 ) O=(0,0,0), \overrightarrow X=(1,0,0),\overrightarrow Y=(0,1,0),\overrightarrow Z=(0,0,1) O=(0,0,0),X =(1,0,0),Y =(0,1,0),Z =(0,0,1)
P 点 = O + 0.5 X → + 0.2 Y → + 0.5 Z → P点=O+0.5\overrightarrow X+0.2\overrightarrow Y+0.5\overrightarrow Z P=O+0.5X +0.2Y +0.5Z
= ( 0 , 0 , 0 ) + 0.5 ⋅ ( 1 , 0 , 0 ) + 0.2 ⋅ ( 0 , 1 , 0 ) + 0.5 ⋅ ( 0 , 0 , 1 ) =(0,0,0)+0.5\cdot(1,0,0)+0.2\cdot(0,1,0)+0.5\cdot(0,0,1) =(0,0,0)+0.5(1,0,0)+0.2(0,1,0)+0.5(0,0,1)
= ( 0.5 , 0 , 0 ) + ( 0 , 0.2 , 0 ) + ( 0 , 0 , 0.5 ) =(0.5,0,0)+(0,0.2,0)+(0,0,0.5) =(0.5,0,0)+(0,0.2,0)+(0,0,0.5)
= ( 0.5 , 0.2 , 0.5 ) =(0.5,0.2,0.5) =(0.5,0.2,0.5)
在这里插入图片描述

OK,这就是点 P ( 0.5 , 0.2 , 0.5 ) P(0.5,0.2,0.5) P(0.5,0.2,0.5)在此坐标系下的位置。

更重要的是,我们得出了一个式子: O + 0.5 X → + 0.2 Y → + 0.5 Z → O+0.5\overrightarrow X+0.2\overrightarrow Y+0.5\overrightarrow Z O+0.5X +0.2Y +0.5Z

再把: P ( 0.5 , 0.2 , 0.5 ) P(0.5,0.2,0.5) P(0.5,0.2,0.5),换成: P ( p x , p y , p z ) P(p_x,p_y,p_z) P(px,py,pz)

那么式子: O + 0.5 X → + 0.2 Y → + 0.5 Z → O+0.5\overrightarrow X+0.2\overrightarrow Y+0.5\overrightarrow Z O+0.5X +0.2Y +0.5Z

变成了: O + p x ⋅ X → + p y ⋅ Y → + p z ⋅ Z → O+p_x\cdot \overrightarrow X+p_y\cdot \overrightarrow Y+p_z\cdot \overrightarrow Z O+pxX +pyY +pzZ

其实这式子就是3D图形学中4x4矩阵的前身,因为这个式子可以表示一次变换。

注意:而使用矩阵的原因是因为矩阵数据集合本身可以修改。假设我们有一个矩阵变换(坐标系)A,只要我们用另一个矩阵变换 B 去修改它,那么它就相当于在原来的矩阵的变换(或是说坐标系)基础上,再次改变了坐标系的轴(旋转或缩放),变成了另一个新的坐标系:C C = B ⋅ A C = B\cdot A C=BA,这个 C 矩阵就相当于柔和了 A 和 B 矩阵变换的累积变换。


我就举个机械手臂的例子:
在这里插入图片描述

将他们的每个子矩阵变换,或者说是子坐标系,罗列一下可以有这么几个
在这里插入图片描述

有:

  • A A A 它是我们的肱二头肌
  • B B B 是手腕
  • C C C 是类似人类手掌
  • D 1 , D 2 D_1,D_2 D1,D2 是手指 D D D关节1、2
  • E 1 , E 2 E_1,E_2 E1,E2 是手指 E E E关节1、2
  • F 1 , F 2 F_1,F_2 F1,F2 是手指 F F F关节1、2
  • G G G 是我们的红球

其中 G 会比较特殊

A A A G G G都的坐标系之前的嵌套可以理解为:

	A
	|
	+--->B
		|
		+--->C
			|
			+--->D_1
			|	|
			|	+--->D2
			+--->E_1
			|	|
			|	+--->E_2
			+--->F_1
				|
				+--->F_2

G 呢?它没有属于机械手臂的坐标系吗?因为我们的机械手臂的D,E,F关节都是可以旋转而夹紧红球 G,并且 D,E,F 不再变换后,D,E,F,G都数据 C 的子坐标系。

只要 G 求没有东西固定它,它都属于世界坐标。

当然,我们上面通常是简单的游戏中的制作方法,更好的方法是直接使用物理系统来给球体、机械手臂添加物理刚体网格,让他们使用物理系统来驱动相应。

每一个关节都有一个坐标系,或是说:矩阵变换。

如果我们驱动 A 矩阵变换,那么其他所有的 子坐标 或是说 子矩阵变换 都一同跟着变换,如果我们驱动 B,那么 A 保持不动,B 下的所有 子矩阵变换 又会跟着变化。(有些系统是例外,如:实现IK动力学,是需要 子矩阵变换 来计算驱动 父级矩阵 如何变化的)

这些每个坐标系相对世界坐标系统( I , 单 位 矩 阵 , 对 角 都 是 1 , 其 余 都 为 0 I,单位矩阵,对角都是1,其余都为0 I10)来说,他们都可以这么表示:

  • I ⋅ A I\cdot A IA
  • I ⋅ A ⋅ B I\cdot A \cdot B IAB
  • I ⋅ A ⋅ B ⋅ C I\cdot A \cdot B \cdot C IABC
  • I ⋅ A ⋅ B ⋅ C ⋅ D 1 I\cdot A \cdot B \cdot C \cdot D_1 IABCD1
  • I ⋅ A ⋅ B ⋅ C ⋅ D 1 ⋅ D 2 I\cdot A \cdot B \cdot C \cdot D_1 \cdot D_2 IABCD1D2
  • I ⋅ A ⋅ B ⋅ C ⋅ E 1 I\cdot A \cdot B \cdot C \cdot E_1 IABCE1
  • I ⋅ A ⋅ B ⋅ C ⋅ E 1 ⋅ E 2 I\cdot A \cdot B \cdot C \cdot E_1 \cdot E_2 IABCE1E2
  • I ⋅ A ⋅ B ⋅ C ⋅ F 1 I\cdot A \cdot B \cdot C \cdot F_1 IABCF1
  • I ⋅ A ⋅ B ⋅ C ⋅ F 1 ⋅ F 2 I\cdot A \cdot B \cdot C \cdot F_1 \cdot F_2 IABCF1F2

继续上面的 坐标系下点的定位的 内容,我们可以将: O + p x ⋅ X → + p y ⋅ Y → + p z ⋅ Z → O+p_x\cdot \overrightarrow X+p_y\cdot \overrightarrow Y+p_z\cdot \overrightarrow Z O+pxX +pyY +pzZ 写成矩阵的方式:

首先是每个轴,我们都写成3x3中某个列的向量来表示:
X → = [ ∣ X → ∣ ] , Y → = [ ∣ Y → ∣ ] , Z → = [ ∣ Z → ∣ ] \overrightarrow X=\begin{bmatrix}|\\\overrightarrow X\\|\end{bmatrix},\overrightarrow Y=\begin{bmatrix}|\\\overrightarrow Y\\|\end{bmatrix},\overrightarrow Z=\begin{bmatrix}|\\\overrightarrow Z\\|\end{bmatrix} X =X ,Y =Y ,Z =Z
这样我们的三个 正交基向量 就构成了一个3x3矩阵: M M M
M = [ ∣ ∣ ∣ X → Y → Z → ∣ ∣ ∣ ] M=\begin{bmatrix} | & | & |\\ \overrightarrow X & \overrightarrow Y & \overrightarrow Z\\ | & | & | \end{bmatrix} M=X Y Z
然后是我们的点 P P P可以是表示为一个3x1的向量(矩阵):
( p x p y p z ) \left(\begin{matrix} p_x\\ p_y\\ p_z\end{matrix}\right) pxpypz

然后是点 P P P M M M坐标系(变换矩阵)中定位后(变换后)的坐标定义为: P 1 P1 P1,那么 P 1 P1 P1等于:
( p 1 x p 1 y p 1 z ) \left(\begin{matrix} p1_x\\ p1_y\\ p1_z\end{matrix}\right) p1xp1yp1z
P 1 = M ⋅ P → ( p 1 x p 1 y p 1 z ) = [ ∣ ∣ ∣ X → Y → Z → ∣ ∣ ∣ ] ⋅ ( p x p y p z ) → p x ⋅ X → + p y ⋅ Y → + p z ⋅ Z → P1=M\cdot P \rightarrow \left(\begin{matrix} p1_x\\ p1_y\\ p1_z\end{matrix}\right) =\begin{bmatrix} | & | & |\\ \overrightarrow X & \overrightarrow Y & \overrightarrow Z\\ | & | & | \end{bmatrix} \cdot \left(\begin{matrix} p_x\\ p_y\\ p_z\end{matrix}\right) \rightarrow p_x\cdot \overrightarrow X+p_y\cdot \overrightarrow Y+p_z\cdot \overrightarrow Z P1=MPp1xp1yp1z=X Y Z

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值