3D空间中的一个点的坐标,可以用(x,y,z)来表示。

对这个点的坐标变换有三种操作:缩放、平移、旋转。 缩放之后,点的坐标变为(Sx*x,Sy*y,Sz*z);平移之后,点的坐标变为(Tx+x,Ty+y,Tz+z);旋转会比较麻烦一点,在后边的详细内容中描述。

上面的操作其实可以用矩阵运算来简单的表示,但是用矩阵表示变换的时候会有一个问题:用一个矩阵可以同时表示点的缩放、旋转,但是没办法表示平移了。 此时需要引入一个齐次坐标的表示方法,将点的(x,y,z)坐标表示为(x,y,z,1)

1.缩放矩阵

点在x、y、z轴的缩放分别为Sx、Sy、Sz,那么缩放可以用下面的矩阵来表示:

Sx 0 0 0
0 Sy 0 0
0 0 Sz 0
0 0 0 1

(x,y,z,1) * S = (Sx*x,Sy*y,Sz*z,1)

2.旋转矩阵

首先看一下点绕着x、y、z三个坐标轴旋转一定角度时,坐标的表示方法:

用矩阵来表示:

那么当点(x,y,z)绕x、y、z轴分别旋转Rx、Ry、Rz角度时,旋转矩阵R=Rx*Ry*Rz,得到矩阵如下:

cos(Rx)*cos(Rz) cos(x)*sin(z) -sin(y) 0
sin(x)*sin(y)*cos(z)-cos(x)*sin(z) sin(x)*sin(y)*sin(z)+cos(x)*cos(z) sin(x)*cos(y) 0
cos(x)*sin(y)*cos(z)+sin(x)*sin(z) cos(x)*sin(y)*sin(z)-sin(x)*cos(z) cos(x)*cos(y) 0
0 0 0 1

3.平移矩阵

点在x、y、z轴的平移分别为Tx、Ty、Tz,那么缩放可以用下面的矩阵来表示:

1 0 0 0
0 1 0 0
0 0 1 0
Tx Ty Tz 1

(x,y,z,1) * T = (Tx+x,Ty+y,Tz+z,1)

4.综合变换矩阵

综合上边的三个矩阵,可以得到最终的变换矩阵: M=S*R*T

Sx*cos(Rx)*cos(Rz) Sx*cos(Rx)*sin(Rz) -Sx*sin(Ry) 0
Sy*(sin(Rx)*sin(Ry)*cos(Rz)-cos(Rx)*sin(Rz)) Sy*(sin(Rx)*sin(Ry)*sin(z)+cos(Rx)*cos(Rz)) Sy*sin(Rx)*cos(Ry) 0
Sz*(cos(Rx)*sin(Ry)*cos(Rz)+sin(Rx)*sin(Rz)) Sz*(cos(Rx)*sin(Ry)*sin(Rz)-sin(Rx)*cos(Rz)) Sz*cos(Rx)*cos(Ry) 0
Tx Ty Tz 1

简写为

m00 m01 m02 0
m10 m11 m12 0
m20 m21 m22 0
Tx Ty Tz 1

不同的编译器在内存管理方式上的不同,会导致有的情况下使用行优先的写法较好,有的情况下使用列优先的写法较好。我这边实践的过程中接触的是列优先的写法:

m00 m10 m20 Tx
m01 m11 m21 Ty
m02 m12 m22 Tz
0 0 0 1

得到这样一个矩阵之后,围绕x、y、z三个轴所做的选择、缩放、平移操作,所影响的矩阵中的位置就一目了然了

4.1左右手系转换

假如我们得到了一个右手坐标系下的变换矩阵,需要把它转换为左手坐标系下的变换矩阵,那么可以将其绕一个平面翻转,假设选择绕xoy平面翻转。

分析一下翻转之后的结果:Tz变为-Tz;Rx变为-Rx;Ry变为-Ry;其他不变。

正弦和余弦函数的曲线:

将这些变化代入上面得到的最终版变换矩阵,可以得到

m02 = -m02; m12 = - m12; m20 = -m20; m21 = -m21; Tz = -Tz

将变换矩阵中这些位置的值都乘以-1,即可得到绕xoy平面翻转之后的左手系变化矩阵。

m00 m10 -m20 Tx
m01 m11 -m21 Ty
-m02 -m12 m22 -Tz
0 0 0 1

也可以换一种思路,当用右手系变换矩阵变换完成之后,将坐标沿着xoy平面做个翻转,这个翻转可以用一个缩放矩阵来表示:

1 0 0 0
0 1 0 0
0 0 -1 0
0 0 0 1

M*S 得到新的矩阵,转换为列优先的写法:

m00 m10 -m20 Tx
m01 m11 -m21 Ty
m02 m12 -m22 Tz
0 0 0 1

也就是说,把第三列都乘以-1就可以了

上面两种思路可以得到等价的坐标系转换结果。

☞ 参与评论