《计算机图形学基础》之变换矩阵
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《计算机图形学基础》之变换矩阵相关的知识,希望对你有一定的参考价值。
参考技术A 缩放变换 是最基本的变换,可以改变向量的长度和方向。
错切 变换,在一个轴向上根据另一个轴上的值以一定比例移动,看图很容易明白。沿 轴和沿 轴上的错切矩阵分别如下:
沿 轴的错切也可以理解是沿 轴顺时针旋转 (与 轴的夹角):
旋转变换 ,证明过程 略 ,逆时针旋转 的矩阵为:
可以看到旋转矩阵是 正交矩阵 ,并且有两对正交向量,一对是第一行和第二行向量;一对是第一列和第二列向量。每一行会被带给标准基向量( ),标准基向量会被带给每一列。简单来说就是,对标准基向量进行一个 旋转变换,就会变成 的列向量,看下图的 点,变换后为 ,就是 的第二列(因为 相当于是 ,所以是第二列);对 的每一行做 的旋转变换,结果就是标准基向量,看下面的 ,变换后为 。
反射变换 是一种使用负数的缩放变换,下面分别是关于 轴的反射变换矩阵,和关于 轴的反射变换矩阵:
有人会认为矩阵的左上角和右下角都为 时,也是一种反射变换(关于原点的反射),但实际上那只是 的旋转变换而已。
我们经常需要对一个图案进行多种变换,这些变换可以通过将他们的变换矩阵连乘进行 合并 ,比如需要先对 进行 变换得到 ,然后再对 进行 变换得到 ,那么有以下转换:
有时候我们也需要将一个组合的变换进行 分解 ,所有的 2D 矩阵都可以通过 奇异值分解(SVD) 成为旋转、缩放、旋转的形式。下图是把一个错切变换进行 SVD 的过程:
我们可以把 当做是一次旋转,把 当成是一次缩放,那么其实就是一个组合变换,请结合下面的文字看图:
我们可以发现对于 对称矩阵 来说,变换的表现就是沿着一对基向量进行非均匀缩放,这一对基向量依然是正交的,跟标准基向量没什么不同,只是整体方向不一样。而这一对基向量正是 对称矩阵 的特征向量。
看一个例子:
对于非对称矩阵,我们可以使用 奇异值分解(SVD) ,对此有疑问的可以看 这里 。他与特征值分解基本一样,不同的是左右旋转矩阵不再是同一个,而是分为两个,特征值分解的结果是 ,而奇异值分解 写成 ,这里的 依然是一个正交矩阵,列是 左奇异向量 , 也是一个正交向量,列是 右奇异向量 , S 依然是对角矩阵,对角线上是奇异值。
还有一种旋转的分解叫做 Paeth 分解 ,这是将旋转分解成 错切 的方式,最大的好处就是不会在图像中出现间隙,下面是分解公式:
顺着笛卡尔坐标系的 缩放 矩阵为:
如何将一个点绕着 3D 中任意轴进行旋转呢?假设该点为 ,旋转轴为 (这里的 是起点为原点的向量,所以不涉及平移),那么如果能构建一组以 为 轴的基向量,并把 转换到该空间,进行旋转,再转回来就可以了。
第一步 :构建以 为 的一组正交基
首先我们将 进行归一化得到 :
第二步 :构建空间转换矩阵
假设我们有一组基向量, ,还有一个点 ,将 按行来摆好,写成 我们可以提前知道 在上述基向量中的坐标应该为 ,正是 的结果。下面是书上的证明过程,有兴趣的可以看一下,没兴趣就记着我们可以用任意的一组正交基,把 三个分量摆第一行,把 三个分量摆第二行,把 三个分量摆第三行,总而构建出转换到该空间下的转换矩阵。并且再次乘其转置,就可以再次变回来。
上面所说的变换都是方向或者点,还有一种特殊的向量叫做 法线 ,如果图形应用的变换矩阵我们称为 ,那么 经过 变换之后不再垂于表面,但切线 依然与表面相切。期望求出一个矩阵 ,使得 ,其中 。
以上所有的变换都是 线性变换 (原点不变,且直线变换后依然是直线),而 平移 变换并不满足。我们把一个线性变换 + 一次平移的操作叫做 仿射变换 ,通过增加一个维度的方式来实现,叫做 齐次坐标 。
我们把一个 2D 中的点 写成 ,把 的矩阵写成:
变换中一个比较重要的类叫做 刚体 ,他们只有旋转和平移组成,没有拉伸或者缩放。
我们知道了矩阵的几何意义之后,可以通过几何意义来进行逆操作,比如 的逆就是 ;比如旋转矩阵的逆就是角度变成相反的符号;平移矩阵的逆就是相反的方向。如果我们有一系列的变换 ,那么逆操作就是 。
不过,有些矩阵在代数上也是很好求的,比如说对于缩放矩阵,他是对角矩阵;第二重要的是旋转矩阵,他是正交矩阵,逆就是它的转置。所以使得求旋转和缸体的逆操作都变得简单。当然我们也需要知道,求完逆之后,原矩阵最下面一行不要动,比如是 的话,那逆的最下面一行也是 。
有趣的是,我们也可以使用奇异值分解来求逆,我们知道可以将一个矩阵分解成旋转——缩放——旋转的方式:
通常我们会在场景中有一个全局坐标系(世界坐标系),图中的 ,图中有另外一个坐标系 ,还有一个点 。
3D计算机图形学变换矩阵欧拉角四元数
【3D计算机图形学】变换矩阵、欧拉角、四元数
旋转矩阵、欧拉角、四元数主要用于:向量的旋转、坐标系之间的转换、角位移计算、方位的平滑插值计算。
一、变换矩阵:
首先要区分旋转矩阵和变换矩阵:
旋转矩阵:向量绕某一个轴旋转,用3x3的矩阵表示。
变换矩阵:向量的移动、旋转、缩放,用4x4的矩阵表示。
这里额外补充一个知识,就是三维坐标变换是用4x4矩阵(采用齐次坐标)而不是3x3矩阵的原因是:统一平移和缩放(本来是向量加法来描述)为矩阵乘法的形式来计算。所以旋转矩阵也扩展为4x4矩阵,这样一来,平移矩阵、缩放矩阵、旋转矩阵可以相乘最后结果为一个唯一的变换矩阵。
可以参考下面这篇文章,解释的很清楚:
http://www.tuicool.com/articles/jMzuIfA
旋转矩阵的推导过程网上有很多,这里不再赘述。可以参考如下文章:
http://blog.csdn.net/ningyaliuhebei/article/details/7481679
http://blog.chinaunix.net/uid-25296429-id-5133776.html
二、欧拉角:
欧拉角的基本思想是将角位移分解为绕三个互相垂直轴的三个旋转组成的序列。所以,欧拉旋转的三个角,可以对应于三个旋转矩阵。
Yaw(偏航):欧拉角向量的y轴
Pitch(俯仰):欧拉角向量的x轴
Roll(翻滚): 欧拉角向量的z轴
Unity3D中,欧拉旋转是按照ZYX的顺序旋转的。(不同的旋转顺序最终得到的结果是不一样的,要引起重视)
三、四元数:
四元数的定义:
一个四元数可以表示为q = w + xi + yj + zk,现在就来回答这样一个简单的式子是怎么和三维旋转结合在一起的。为了方便,我们下面使用q = ((x, y, z),w) = (v, w),其中v是向量,w是实数,这样的式子来表示一个四元数。
我们先来看问题的答案。我们可以使用一个四元数q=((x,y,z)sinθ2, cosθ2) 来执行一个旋转。具体来说,如果我们想要把空间的一个点P绕着单位向量轴u
= (x, y, z)表示的旋转轴旋转θ角度,我们首先把点P扩展到四元数空间,即四元数p = (P,
0)。那么,旋转后新的点对应的四元数(当然这个计算而得的四元数的实部为0,虚部系数就是新的坐标)为:
其中,q=(cosθ2, (x,y,z)sinθ2) ,q−1=q∗N(q)
当然,四元数不仅可以用来方便的进行向量旋转计算,还能够用于平滑插值计算等。
四元数更多的介绍参看下面的链接;
http://www.cnblogs.com/mengdd/archive/2013/08/05/3238223.html
四、旋转矩阵、欧拉角、四元数比较:
下面的总结来源于网络:http://blog.csdn.net/pizi0475/article/details/6278526
任务/性质 |
旋转矩阵 |
欧拉角 |
四元数 |
在坐标系间(物体和惯性)旋转点 |
能 |
不能(必须转换到矩阵) |
不能(必须转换到矩阵) |
连接或增量旋转 |
能,但经常比四元数慢,小心矩阵蠕变的情况 |
不能 |
能,比矩阵快 |
插值 |
基本上不能 |
能,但可能遭遇万向锁或其他问题 |
Slerp提供了平滑插值 |
易用程度 |
难 |
易 |
难 |
在内存或文件中存储 |
9个数 |
3个数 |
4个数 |
对给定方位的表达方式是否唯一 |
是 |
不是,对同一方位有无数多种方法 |
不是,有两种方法,它们互相为互 |
可能导致非法 |
矩阵蠕变 |
任意三个数都能构成合法的欧拉角 |
可能会出现误差积累,从而产生非法的四元数 |
不同的方位表示方法适用于不同的情况。下面是我们对合理选择格式的一些建议:
欧拉角最容易使用。当需要为世界中的物体指定方位时,欧拉角能大大的简化人机交互,
包括直接的键盘输入方位、在代码中指定方位(如为渲染设定摄像机)、在调试中测试。这个优点不应该被忽视,不要以”优化”为名义而牺牲易用性,除非你去顶这种优化的确有效果。
如果需要在坐标系之间转换响亮,那么就选择矩阵形式。当然,这并不意味着你就不能用其他格式来保存方位,并在需要的时候转换到矩阵格式。另一种方法是用欧拉角作为方位的”主拷贝”但同时维护一个旋转矩阵,当欧拉角发生改变时矩阵也要同时进行更新。
当需要大量保存方位数据(如:动画)时,就使用欧拉角或四元数。欧拉角将少占用25%的内存,但它在转换到矩阵时要稍微慢一些。如果动画数据需要嵌套坐标系之间的连接,四元数可能是最好的选择。
平滑的插值只能用四元数完成。如果你用其他形式,也可以先转换到四元数然后再插值,插值完毕后再转换回原来的形式。
五、欧拉角与四元数的转换:
参看下面一篇文章,讲的比较通俗易懂:
http://www.cnblogs.com/wqj1212/archive/2010/11/21/1883033.html
六、Unity3D中变换矩阵(平移、缩放、旋转)、欧拉角、四元数有关的类和相互之间的转换:
Quaternion:四元数类。
Matrix4x4:变换矩阵类。
Vector3:欧拉角用此表示就可以了。
四元数转欧拉角:
- public Quaternion rotation = Quaternion.identity;
- print(rotation.eulerAngles.x);
- print(rotation.eulerAngles.y);
- print(rotation.eulerAngles.z);
欧拉角转四元数:
- public Quaternion rotation = Quaternion.Euler(0, 30, 0);//Euler方法即通过一个Vector3的欧拉角返回一个四元数
四元数转变换矩阵:
- Quaternion q = Quaternion.LookRotation(new Vector3(0,0.5,1));
- Matrix4x4 rot = new Matrix4x4();
- rot.SetTRS(new Vector3(0,0,0),q,new Vector3(1,1,1));
变换矩阵转四元数:
- Matrix4x4 rot = new Matrix4x4();
- rot.SetTRS(new Vector3(0,0,0),q,new Vector3(1,1,1));
- Vector4 vy = rot.GetColumn(1);
- Vector4 vz = rot.GetColumn(2);
- Quaternion newQ = Quaternion.LookRotation(new Vector3(vz.x,vz.y,vz.z),new Vector3(vy.x,vy.y,vy.z));
以上是关于《计算机图形学基础》之变换矩阵的主要内容,如果未能解决你的问题,请参考以下文章