Real-Time Rendering 翻译 4.变换【上】

来源:互联网 发布:淘宝网内衣专卖 编辑:程序博客网 时间:2024/05/16 00:34

变换是一种转换点、向量或者颜色的操作。对于计算机图形学的先驱来说,掌握变换极度重要。有着它,可以放置、形变和运动物体、光源和相机。你可以认为所有计算都是在同一坐标系下,然后以不同的方式投影到平面上。虽然变换只能完成一小部分操作,但是这些操作足以证明它在实时渲染中的重要地位,对所有的计算机图形学都如此。

线性变换包含,向量相加和标量与向量相乘。例如,

f(x)+f(y)=f(x+y)()
kf(x)=f(kx)( 4.1)

例如,f(x)=5x是一个变换,它将向量x的所有元素都乘以5。这种变换是线性的,任意两个向量乘以5再相加,等同于先将两个向量相加然后在乘以5。标量乘以向量完全满足线性变换的条件。这个函数称之为缩放变换,它改变了对象的尺寸。旋转变换也是一种线性变换,它将向量绕原点旋转。针对3元素的线性变换可以用3x3的矩阵表示,缩放和旋转变换也如此。

然而,3x3矩阵的维度还是不够。例如,x是3元素的向量,函数f(x)=x+(7,2,3)就不是一个线性变换。因为如果将此函数作用于两个向量上,最终的结果会把向量(7,2,3)相加两次,不满足相加性。将一个常向量加到另一个向量产生了位移变换,它将向量移动了一个常量。这种变换类型很有用,我们可以将各种操作组合起来,例如,我们可以将对象缩放到原来的一半,然后移动到另一个位置。如果使用函数的形式来表示变换非常的简单,然而不好组合各种变换。

线性变换和位移的组合称之为仿射变换。我们使用齐次坐标来表示4元素的向量,以此可以统一点和向量的表示方式。向量可以表示为v=(v0,v1,v2,0)T,点可以表示为v=(v0,v1,v2,1)T。本章我们会大量使用附录A中术语。你可以现在复习目录A.4(905页),关于齐次坐标的内容。

所有的位移、旋转、缩放、反射和裁剪矩阵都是仿射变换。仿射变换的主要特性是,经过变换后平行线依然平行,但是长度和角度会改变。仿射变换的任意顺序组合任然是仿射变换。

我们以最重要最基本的仿射变换开始本章。由于是最基本的内容,可以认为本节是一些简单变换的参考手册。也会描述一些特殊的矩阵,然后讨论四元数,一种非常有用的变换工具。接下来讨论顶点融合和变形,这两种操作虽然简单是对对网格动画非常有用。最后讨论投影矩阵。表4.1总结了很多矩阵的表示方式,表示函数和属性。

变换是操作几何体的基本工具。[2016/07/09]很多图像API已经包含了我们本章讨论的矩阵操作。然而,了解真正的变换矩阵和API之后的具体实现是值得的。了解API调用之后如何使用变换矩阵只是开始,真正了解每个矩阵的具体含义才能让你走的更远。例如,当你真正理解矩阵变换之后,你会知道正交矩阵的逆矩阵是它的转置矩阵,让你更快的求出它的逆矩阵。这种知识可以加速你的代码。

符号 名称 特点 T(t) 位移矩阵 移动一个点,仿射 Rx(ρ) 旋转矩阵 绕x轴旋转ρ弧度,同样的可以表示对y轴和z轴的旋转,正交和仿射 R 旋转矩阵 任意的旋转矩阵,正交和仿射 S(s) 缩放矩阵 根据向量s沿x,y,z轴缩放 Hij(s) 剪切矩阵 剪切,仿射变换 E(h,p,r) 欧拉变换 使用欧拉角(head,pitch,roll)的朝向矩阵,正交和仿射 Po(s) 正交投影 平行投影到平面,仿射 Pp(s) 透视投影 透视投影到平面 slerp(q,r,t) 插值变换 在四元数q和r之间使用参数t进行插值

表4.1 本章讨论的所有变换。

4.1 基本变换

本章讨论最基本的变换,例如位移、旋转、缩放、剪切、变换连接、刚体变换、法线变换和他们的逆。对有经验的肚子来说,这些内容时一份参考手册,队友新手而言,这是变换这个主题的引导。这些材料是接下来其他章节的背景知识。我们冲最简单的变换开始,位移变换。[2016/07/10]

这里写图片描述
图4.1 左边的正方形经过位移矩阵T(5,2,0)变换,向右移动5个单位,向上移动2个单位。

4.1.1 位移

从一个位置位移到另一个位置可以使用位移矩阵T来完成。这个矩阵将对象位移向量t=(tx,ty,tz)。矩阵T具体表示如公式4.2:

T(t)=T(tx,ty,tz)=100001000010txtytz1(4.2)

图4.1展示了位移变换的效果。[2016/07/11]上述公式表示点p=(px,py,pz,1)和T(t)的相乘结果,产生新的点p=(px+tx,py+ty,pz+tz,1)。注意向量v=(vx,vy,vz,0)与T(t)相乘后不变,因为方向向量不能位移(没有位移这个概念)。相反的,点和向量都收到其他的仿射变换所影响。位移矩阵的逆矩阵T1(t)=T(t),注意向量t取反。

4.1.2 旋转

旋转变换将向量(点或者方向向量)绕给点的轴(过圆心)旋转指定的角度。同位移矩阵一样,这是个刚体变换,点与点之间的距离保持不变,坐标系的左右手不变(不会从左手坐标系变为右手坐标系)。位移和旋转两种操作用来表示对象的位置和朝向。方向矩阵(orientation matrix)是一个旋转矩阵,用于定义相机或者物体在空间中的朝向。常用的旋转矩阵有Rx(ϕ),Ry(ϕ)Rz(ϕ),分别表示绕着x,y和z轴旋转ϕ弧度。具体表示如下所示:

Rx(ϕ)=10000cosϕsinϕ00sinϕcosϕ00001(4.3)

Ry(ϕ)=cosϕ0sinϕ00100sinϕ0cosϕ00001(4.4)

Rz(ϕ)=cosϕsinϕ00sinϕcosϕ0000100001(4.5)

对3x3的旋转矩阵而言,表示绕任意轴旋转ϕ弧度,矩阵的迹相对于轴独立,计算如下:

tr(R)=1+2cosϕ(4.6)

旋转矩阵的效果如图4.4所示。旋转矩阵Ri(ϕ)的特点是,所有在旋转轴i上的点不变,其他点绕轴i旋转ϕ弧度。记号R也可以表示绕任意轴旋转。上面三种旋转矩阵的结合可以完成绕任意轴的旋转操作。这个过程在4.2.1讨论。直接绕任意轴旋转的操作会在4.2.4讨论。

所有的旋转矩阵的行列式为1,并且是正交的,可以参考附录A中关于正交矩阵的定义来证明。任意多个旋转矩阵的连接也满足以上性质。旋转矩阵的逆矩阵如下:Ri1(ϕ)=Ri(ϕ),绕任意轴相反的方向。同样的,旋转矩阵的行列式为1,因为它是正交的。

例子:绕点旋转。[2016/07/19]假设我们绕z轴旋转ϕ弧度,旋转的中心为点p。转换矩阵是什么呢?这一转换过程详见图4.2。绕一点旋转的效果是,中心点本身不变,其他点绕中心点旋转。转换由位移变换开始,我们先将坐标系的原点移动至点p(中心点),可以使用变换T(p)。然后执行旋转变换:Rz(ϕ)。最后将坐标系原点移回原来的位置,使用位移矩阵T(p)。最后的变换矩阵X为:

X=T(p)Rz(ϕ)T(p)(4.7)

这里写图片描述
图4.2 绕点p旋转的过程

4.1.3 缩放

缩放矩阵,S(s)=S(sx,sy,sz),缩放因子为sx,sy,sz,分别为沿着x,y和z轴的缩放。意味着缩放矩阵可以放大或者缩小对象。缩放因子si,i{x,y,z}越大,在所在方向的缩放也就越大。将缩放因子s的任何部分设置为1意味着在此方向上不进行任何缩放。公式4.8为最终的缩放矩阵:

S(s)=sx0000sy0000sz00001(4.8)

图4.4展示了缩放矩阵的效果。如果sx=sy=sz则称之为uniform,其他称之为nonuniform。有时候也会使用术语isotropic和anisotropic来替代uniform和nonuniform。逆矩阵S1(s)=S(1/sx,1/sy,1/sz)

使用齐次坐标,还可以容易的实现以点(3,3)为中心的缩放矩阵。齐次坐标的w分量,也可以用来实现缩放矩阵。例如,使用缩放因子5来等比缩放,缩放矩阵的(0,0),(1,1)和(2,2)位置设置为5,或者也可以将矩阵的(3,3)设置为1/5。这两种矩阵如下所示:

S(s)=5000050000500001,S=1000010000100001/5(4.9)

不同于缩放矩阵S,使用矩阵S’必须最后进行齐次化(就是将x,y,z除以w)。使用矩阵S’可能不会高效,因为在齐次化过程中需要将各个分量除以w,如果S’位于(3,3)的值为1就不需要进行除法。如果系统不检测w是否为1,每次都进行齐次化,那么使用S’不需要额外的除法。[2016/07/24]

对角线上的元素变为负数就得到一个反射矩阵,也称之为镜面反射矩阵。如果对角线上的两个元素为-1,那么相对于旋转π弧度。反射矩阵一般需要特殊的对待。例如,一个逆时针定义顶点的三角形经过反射矩阵变换之后会得到一个顺时针定义顶点的三角形。这种变换会导致不正确的光照和背面剔除错误。验证某一变换矩阵是否包含反射操作,计算变换矩阵的左上的3x3子矩阵的行列式。如果为负数,那么这个矩阵包含反射操作变换。

例如:沿着一确定方向的缩放。缩放矩阵S只能沿着x,y或者z轴缩放。如果需要沿着其他方向缩放,那么需要一个复合变换。假设沿着一确定方向的缩放可以在一个正交的,右手坐标系完成,坐标系以fx,fy,fz为轴。我们可以先构造矩阵F如下:

S(s)=(fx0fy0fz001)(4.10)

基本思想是以新的轴为坐标系,然后在此坐标系中进行标准的缩放操作,然后再从新坐标系转换到原坐标系。第一步是乘以F的转置矩阵(正交矩阵的逆矩阵就是其转置)。然后执行缩放操作,最后再执行返原操作。变换公式如4.11

X=FS(s)FT(4.11)

4.1.4 剪切

另一类变换操作是剪切矩阵的集合。这种变换操作应用在游戏中来扭曲整个场景,产生迷幻的效果,或者创建模糊的反射效果。有六个基本的剪切矩阵,分别为Hxy(s),Hxz(s),Hyx(s),Hyz(s),Hzx(s),Hzy(s)。第一个下标表示受剪切矩阵影响的轴,第二个下标表示在此轴上进行剪切操作。公式4.12是剪切矩阵Hxz(s)。观察Hxz(s)的下标可以找到剪切参数s的位置,下标x(位置为0)表示第0行,下标z(位置为0)表示第二列,那么s的位置就可以轻松定位,如下公式所示:

S(s)=10000100s0100001(4.12)

将此矩阵乘到点p产生结果(px+spz,py,pz)T。图4.3展示了单位正方形的剪切效果。Hij(s)(在j轴上剪切i,i!=j)的逆操作就是在往相反的方向再执行剪切操作,那么H1ij(s)=Hij(s)

这里写图片描述
图4.3 单元正方形使用Hxz(s)剪切后的效果。y轴和z轴不会受到操作的影响,x是原来的x和s倍z值之和,导致正方形倾斜。

有些计算机图形系统中使用另一种剪切矩阵:
H1xy(s,t)=10000100st100001(4.13)

上述公式中的两个下标用来表示对象在两个轴上分别沿着第三个轴做剪切操作。着两个操作的组合为Hij(s,t)=Hik(s)Hjk(t),这里k指的是i,j之外的第三个轴。等式左边的部分更为常用,也被API所支持。

最后,任何剪切矩阵的行列式都为1,|H|=1

4.1.5 组合变换

由于矩阵乘法的不可交换性,矩阵相乘的顺序就非常重要了。变换的组合是顺序相关的。

一个顺序相关的例子,两个矩阵S和R,S(2, 0.5, 1)表示沿着x轴方向放大两倍,沿着y轴缩小一半。[2016/08/01]Rz(π/6)表示绕z轴逆时针旋转π/6弧度。这两个矩阵可以有两种不同的连接方式,产生的结果大不相同。如图4.4所示。

这里写图片描述
图4.4 展示了矩阵连接顺序的不同导致的结果不同。上面一行先进行旋转操作Rz(π/6),然后进行缩放操作S(s),s=(2,0.5,1)。组合矩阵为S(s)Rz(π/6)。下一行以相反的顺序执行操作,组合矩阵为Rz(π/6)S(s)。产生的结果完全不相同。一般来说,对矩阵M和N,MN!=NM。

将多个矩阵组合为一个的原因是为了效率。例如,有一个拥有几千个顶点的对象,需要缩放、旋转和位移。这就需要对每个顶点都乘以这三个矩阵,这三个矩阵可以连接为一个矩阵。然后将这个新的矩阵作用到每个顶点上。最终的组合矩阵为C=TRS。需要关注矩阵的顺序,首先乘以缩放矩阵S,然后从右到左顺序依次相乘。这样的顺序隐含着TRSp=(T(R(Sp)))。

需要注意的是矩阵的连接是顺序相关的,矩阵可以随意组合。例如TRSp变换可以先计算刚体变换TR。可以将这两个矩阵组合起来,(TR)(Sp),等同于TRSp。矩阵连接满足可分配性。

4.1.6 刚体变换

当一人抓起一个物体,例如从桌子上抓起一支笔,移动到另一个位置,比如他的口袋里,笔的朝向和位置发生了变化,然而笔的形状没有发生变化。这种只有位移和旋转的操作称之为刚体变换,保留原有对象的长度、角度和坐标系的属性(左手坐标系或者右手坐标系不变)。[2016/08/05]

任何刚体变换矩阵X都可以分解为位移矩阵T(t)和旋转矩阵R的连接。X为形如公式4.14的矩阵:
X=T(t)R=r00r10r200r01r11r210r02r12r220txtytz1(4.14)

X的逆矩阵可以这么计算,X1=(T(t)R)1=R1T(t)1=RTT(t)[2016/08/06]。那么,X的逆矩阵是,先计算左上3x3的R矩阵的转置,再计算T矩阵的逆矩阵(t取反)。然后R和T相乘最终产生X的逆矩阵。

另一种计算X的逆矩阵的方式如下,考虑R和X如下:

R¯¯¯=(r,0   r,1   r,2)=rT0rT1rT2(4.15)

X=R¯¯¯0Tt1()

上述公式中,0表示3x1的列向量,所有元素为0。经过简单的计算,X的逆矩阵如公式4.16所示:

X1=R¯¯¯T0R¯¯¯T1=r00r10r20R¯¯¯T1(4.16)

4.1.7 法线变换

上面的讨论的变换矩阵可以用于点,线,多边形和其他几何体的变换操作。同样的矩阵也可以用作切向量的变换操作,切向量沿着直线或者多边形表面的方向。然后上述的变换矩阵不能用于法线变换,即表面的法线。图4.5展示了上述矩阵用于法线变换的结果。

这里写图片描述
图4.5 左边是原始的几何体,一个多边形和其法线。中间展示了如果模型朝着x轴缩放0.5之后,再用相同的矩阵作用于法线之后的结果。右边展示了理想的法线变换结果。

不使用原始的变换矩阵,合适的方法是使用原始变换矩阵的伴随矩阵的逆矩阵。A.3.1介绍了如何计算伴随矩阵。伴随矩阵总是存在的。记过这种操作变化的法线不一定是单位向量,需要经过标准化。

法线变换的所使用的矩阵是原始变换矩阵的转置的逆。这种方式总是可行的。然而,有时候逆矩阵是不存在的。逆矩阵是伴随矩阵除以行列式。如果行列式为0,那么矩阵是奇异的,逆矩阵是不存在的。

计算4x4矩阵的伴随矩阵开销比较大,而且不是必要的。因为法线是向量,所以不受位移矩阵的影响。另外,大多数模型变换都是仿射变换。不会改变齐次坐标的w分量。这种情况下,只需要计算左上3x3矩阵的伴随矩阵,就能得到法线变换的矩阵。[2016/08/15]

甚至伴随矩阵的计算也是可以省略的。我们知道变换矩阵是位移矩阵、旋转矩阵和统一缩放矩阵(没有拉伸或者压缩)。法线不受到位移变换的影响。统一缩放操作只会改变法线的长度。由上面旋转矩阵可知,旋转矩阵(正交的)的逆矩阵是它的转置。这种情况下(位移、旋转和统一缩放),原始的变换矩阵可以直接中用于法线。

最后,变换后的法线不一定需要标准化。如果只有位移和旋转,变换后的法线向量的长度不会发生变化,不需要再经过标准化操作。如果变换操作中含有统一缩放,可以直接使用缩放因子来标准化法线。例如,我们知道原始变换操作中包含统一缩放操作,将对象放大5.2倍,那么我们可以使用原始变换作用于法线,最后再除以5.2得到标准化的法线。如果需要得结果为标准化法线的变换矩阵,可以将原始变换矩阵的左上3x3矩阵除以缩放因子,得到最终的法线变换矩阵。

注意法线变换矩阵在这里不是什么大问题,经过变换操作,面片的法线是从三角形数据中计算出来的(三角形变的点乘)。切线向量和法线不太相同,切线向量直接使用原始变换矩阵。

4.1.8 计算逆变换

很多情况下需要计算变换的逆,例如进行变换或者坐标系回退。依赖于原始变换的信息,有以下三种方法来计算矩阵的逆。

  • 如果变换矩阵是一些列简单变换矩阵的组合,那么逆矩阵是单个简单变换矩阵参数取反,并反序组合这些矩阵。例如M=T(t)R(ϕ),那么M1=R(ϕ)T(t)
  • 如果变换矩阵是正交矩阵,那么M1=MT,也就是它的转置矩阵就是它的逆矩阵。任意多个旋转矩阵的组合还是旋转矩阵,任然是正交的。
  • 如果不知道变换矩阵的任何信息,那么可以使用邻接矩阵、克莱默法则、LU分解或者高斯消除等方法来计算逆矩阵。克莱默法则和邻接矩阵的方法更好,因为他们的实现中分支操作较少(也就是if比较少),现代的计算机架构中,if操作越少越好。4.1.7展示了如何使用邻接矩阵来计算法线变换矩阵。[2016/08/18]

优化逆矩阵计算方式时,也需要考虑使用逆矩阵的目的。例如,如果逆矩阵是用来变换向量的,那么只需要计算变换矩阵的右上3x3子矩阵的逆。

4.2 特殊变换矩阵和操作

这节中,我们介绍一些实时渲染图形学中必备的矩阵变换和操作。首先,我们展示欧拉变换(包括他的参数提取),这是一种直观描述朝向的方式。然后涉及到如何从一个变换矩阵中抽取出一个个基本变换。最后,我们推导出绕任意轴旋转的变换矩阵。

4.2.1 欧拉变换

欧拉变换是一种直观的方式用来描述旋转自己或者旋转到特定的方向。名字来源于伟大的瑞士数学家欧拉。

这里写图片描述
图4.6 如图所示,在欧拉变换中,三种操作head,pitch和roll。默认的方向如图所示,观察方向为-z轴,向上方向为y轴。(左上坐标系,顺着旋转轴看,顺时针旋转)

首先,需要确定默认的观察方向。大多数观察方向为-z轴,头朝上方向为y轴,如图4.6所示。欧拉变换就是三个旋转矩阵的组合,每个矩阵命名如上图所示。欧拉变换矩阵表示为E,如公式4.17所示:

E(h,p,r)=Rz(r)Rx(p)Ry(h)(4.17)

因为E是旋转矩阵的组合,所以它是正交的。那么他的逆矩阵E1=ET=(RzRxRy)T=RTyRTxRTz, 所以E的逆矩阵就是它的转置.

欧拉角h, p和r分别表示旋转的次序和沿着head,pitch和roll的旋转角度。这种变换操作很直观,因此可以对外行解释清楚。例如,旋转head角可以让观察者摇头说“no”, 旋转pitch角让他点头,旋转roll角让他向两边倾斜头。我们使用head, pitch和roll来替代x,y和z轴。欧拉变换可以用在世界坐标系中或者局部坐标系中。

当你使用欧拉变换是,有时会产生万向锁结。当一个旋转自由度丢失时,这种现象就会发生。例如,旋转顺序是x/y/z。考虑如下情况,绕y轴旋转π/2弧度,也就是执行第二个旋转操作。[2016/08/21]执行了这个旋转操作之后,z轴就和x轴重合了,导致最终的绕z轴旋转是冗余的。直观解释详见https://www.youtube.com/watch?v=zc8b2Jo7mno

另一种观察万向锁结的方法就是设置p=π/2,然后计算欧拉旋转矩阵E(h,p,r):

E(h,π/2,r)=cosrsinr0sinrcosr00011000cos(π/2)sin(π/2)0sin(π/2)cos(π/2)cosh0sinh010sinh0cosh

=cosrcoshsinrsinhsinrcosh+cosrsinh0001cosrsinh+sinrcoshsinrsinhcosrcosh0=cos(r+h)sin(r+h)0000sin(r+h)cos(r+h)0(4.18)

因为最终的欧拉旋转矩阵只依赖于角度(r+h),我们可以推导出有一个自由度已经丢失。

模型系统中,欧拉角经常以x/y/z顺序出现,依次绕每个轴旋转,其他顺序也是可行的。例如,z/x/y顺序经常用于动画系统中,z/x/z可以用于动画和物理系统中。后一种顺序,z/x/z对某些应用来说很优秀。根据毛球理论,万向锁结不可避免,没有一种完美的顺序来避免出现万向锁结。

对于细小的角度或者朝向变化,欧拉角有些限制。很难结合两组欧拉角。例如,两组欧拉角之间的插值不能简单的通过对每个角度的插值来完成。事实上,两组不同的欧拉角可以表示同样的朝向,所以会导致插值出来的欧拉角根本不会旋转物体。有一些替代的方法来表示朝向,例如接下来要讨论的四元数。

4.2.2 从欧拉变换中抽取参数

在有些情况下,从正交欧拉变换矩阵中抽取欧拉角h,p和r很有用。抽取方法如公式4.19所示:

F=f00f10f20f01f11f21f02f12f22=Rz(r)Rx(p)Ry(h)=E(h,p,r)(4.19)

连接三个旋转矩阵的结果如公式4.19所示:

F=cosr coshsinr sinp sinhsinr cosh+cosr sinp sinhcosp sinhsinr cospcosr cospsinpcosr sinh+sinr sinp coshsinr sinhcosr sinp coshcosp cosh(4.20)

由上式可知,pitch角可由sinp=f21计算出。同样的,f01除以f11可以得到roll角,f20除以f22可以得到head角,具体计算如公式4.21所示:[2016/08/22]

f01f11=sinrcosr=tanr()
f20f22=sinhcosh=tanh(4.21)

那么,欧拉角的三个参数h,p,r可以由atan2(y,x)函数从矩阵F中计算出来,如公式4.22所示:

h=atan2(f20,f22)()
p=arcsin(f21)(4.22)
r=atan2(f01,f11)()

这里有一个特例需要处理。如果cosp=0,因为f01=f11=0时,atan2函数不能工作。如果cosp=0那么sinp=±1,F可以化简为公式4.23。

F=cos(r±h)sin(r±h)000±1sin(r±h)cos(r±h)0(4.23)

如果设置h=0,那么cosh=1,sinh=0,那么由公式4.20可得sinr/cosr=tanr=f10/f00,最终可得到r=atan2(f10,f00)

注意arcsin的定义,π/2pπ/2,这就意味着如果矩阵F的p处在[π/2,π/2]之外,那么原始的p值不能被抽取出来。那么h,p和r等数值不是唯一的,这也就意味着多个欧拉角参数可以表示同一个变换。Shoemake’s 1994有关于欧拉变换的更多信息。

4.2.3 矩阵分解

到此为止我们工作在这样的假设之下,我们知道我们所用的矩阵的原始值和变换过程。这种假设不总是成立的,例如一个对象的变换矩阵可能是多个矩阵的组合。从一个组合矩阵中分离出多个基本变换矩阵的操作称之为矩阵分解。

有很多原因需要分解组合矩阵,如下:

  • 抽取出缩放因子
  • 找到特定系统所需要的变换操作。例如VRML不能使用任意的4x4矩阵。
  • 检查模型的变换操作是否是刚体变换(只包含位移和旋转)。
  • 计算动画中关键帧的插值,关键帧中只包含对象的变换矩阵。
  • 从旋转矩阵中移除剪切

我们已经展示了两种分解方式,由位移和旋转矩阵派生出来的刚体变换,由正交矩阵派生出的欧拉变换。

正如我们所见,分解出位移矩阵非常简单,只需要看4x4矩阵的最后一列。也可以通过矩阵的行列式值是否为负来判断矩阵是否包含镜像操作。分离出旋转、缩放和剪切需要更多努力。[2016/08/29]

幸运的是,有很多关于矩阵分解的文章,也有很多代码。Thomas和GoldMan讨论了各种类型矩阵的分解方法。Shoemake在他们的基础上改进了仿射矩阵的分解方法,他的方法也可以做为独立参考,他还尝试从变换矩阵中抽取出刚体变换操作。

4.2.4 绕任意轴旋转

有时候需一个将对象绕任意轴旋转某个角度的方法。假设旋转的轴为rr为标准化向量,那么旋转矩阵可以通过绕r旋转α来定义。

为了构建这个旋转矩阵,我们需要找到任意的另外两个单位向量,这两个向量之间正交,并与r也正交。这就构成了一个基。基本的想法就是将标准基(标准坐标系)变换到这个新的基(由两个新的单位向量和r构成的新坐标系),然后绕x轴(就是之前的r轴)旋转α弧度,最后变换回标准基。这个过程如图4.7所示。

这里写图片描述
图4.7 绕任意轴r旋转,由寻找到的正交的标准基r,s,t来完成。我们将r作为新的标准基中的x轴。然后绕x轴旋转,最后变换回标准基。

第一步就是计算出新的标准基的轴。第一个轴为r,这就是我们围绕他旋转的轴。接下来专注于寻找第二个轴s,那么第三个轴t可以通过t=r\times s计算出来。一种数值稳定的方法就是寻找到r向量的最小分量(绝对值最小),然后将其置为0。然后交换剩余的两个分量,并将这两个分量中的第一个取反。数学表示如下:

\overline s=\left\{\begin{matrix}(0, -r_z, r_y),\ if\ |r_x|<|r_y|\ and\ |r_x|<|r_z|,\\ (-r_z, 0, r_x),\ if\ |r_y|<|r_x|\ and\ |r_y|<|r_z|,\\ (-r_y, r_x, 0),\ if\ |r_z|<|r_x|\ and\ |r_z|<|r_y|,\end{matrix}\right.

s=\overline s/||\overline s||, \tag{4.24}
t=r\times s

这种计算方式确保\overline sr是正交(垂直)的,(r,s,t)是一个正交基。我们以这三个向量作为矩阵的行,得到矩阵如下:

M=\begin{pmatrix}r^T \\ s^T \\ t^T \end{pmatrix}\tag{4.25}

这个矩阵将向量r转换为x(e_x)s转换为y轴,t转换为z轴。最后绕向量r旋转\alpha弧度的变换为:

X=M^TR_x(\alpha)M\tag{4.26}

换而言之,我们先将r变换到x轴(使用矩阵M),然后绕x轴旋转\alpha弧度,使用矩阵R_x{\alpha},最后使用M的逆变换回去,这里使用M^T因为M是正交的。

另一种绕任意标准轴r旋转\alpha弧度的表示方法由GoldMan提出。我们这里仅仅展现他的最终结果:

R=\begin{pmatrix}cos\phi+(1-cos\phi)r_x^2 && (1-cos\phi)r_xr_y-r_zsin\phi && (1-cos\phi)r_xr_z+r_ysin\phi\\(1-cos\phi)r_xr_y+r_zsin\phi && cos\phi+(1-cos\phi)r_y^2 && (1-cos\phi)r_yr_z-r_xsin\phi \\ (1-cos\phi)r_xr_z-r_ysin\phi && (1-cos\phi)r_yr_z+r_xsin\phi && cos\phi+(1-cos\phi)r_z^2 \end{pmatrix}\tag{4.27}

4.3.2节会讨论另一种解决此问题的方法,四元数。还会讨论其他相关的高效算法,例如由一个向量旋转到另一个向量。[2016/08/30]

0 0
原创粉丝点击