Real-Time Rendering 翻译 4.变换【上】
来源:互联网 发布:淘宝网内衣专卖 编辑:程序博客网 时间:2024/05/16 00:34
变换是一种转换点、向量或者颜色的操作。对于计算机图形学的先驱来说,掌握变换极度重要。有着它,可以放置、形变和运动物体、光源和相机。你可以认为所有计算都是在同一坐标系下,然后以不同的方式投影到平面上。虽然变换只能完成一小部分操作,但是这些操作足以证明它在实时渲染中的重要地位,对所有的计算机图形学都如此。
线性变换包含,向量相加和标量与向量相乘。例如,
例如,f(x)=5x是一个变换,它将向量x的所有元素都乘以5。这种变换是线性的,任意两个向量乘以5再相加,等同于先将两个向量相加然后在乘以5。标量乘以向量完全满足线性变换的条件。这个函数称之为缩放变换,它改变了对象的尺寸。旋转变换也是一种线性变换,它将向量绕原点旋转。针对3元素的线性变换可以用3x3的矩阵表示,缩放和旋转变换也如此。
然而,3x3矩阵的维度还是不够。例如,x是3元素的向量,函数f(x)=x+(7,2,3)就不是一个线性变换。因为如果将此函数作用于两个向量上,最终的结果会把向量(7,2,3)相加两次,不满足相加性。将一个常向量加到另一个向量产生了位移变换,它将向量移动了一个常量。这种变换类型很有用,我们可以将各种操作组合起来,例如,我们可以将对象缩放到原来的一半,然后移动到另一个位置。如果使用函数的形式来表示变换非常的简单,然而不好组合各种变换。
线性变换和位移的组合称之为仿射变换。我们使用齐次坐标来表示4元素的向量,以此可以统一点和向量的表示方式。向量可以表示为
所有的位移、旋转、缩放、反射和裁剪矩阵都是仿射变换。仿射变换的主要特性是,经过变换后平行线依然平行,但是长度和角度会改变。仿射变换的任意顺序组合任然是仿射变换。
我们以最重要最基本的仿射变换开始本章。由于是最基本的内容,可以认为本节是一些简单变换的参考手册。也会描述一些特殊的矩阵,然后讨论四元数,一种非常有用的变换工具。接下来讨论顶点融合和变形,这两种操作虽然简单是对对网格动画非常有用。最后讨论投影矩阵。表4.1总结了很多矩阵的表示方式,表示函数和属性。
变换是操作几何体的基本工具。[2016/07/09]很多图像API已经包含了我们本章讨论的矩阵操作。然而,了解真正的变换矩阵和API之后的具体实现是值得的。了解API调用之后如何使用变换矩阵只是开始,真正了解每个矩阵的具体含义才能让你走的更远。例如,当你真正理解矩阵变换之后,你会知道正交矩阵的逆矩阵是它的转置矩阵,让你更快的求出它的逆矩阵。这种知识可以加速你的代码。
表4.1 本章讨论的所有变换。
4.1 基本变换
本章讨论最基本的变换,例如位移、旋转、缩放、剪切、变换连接、刚体变换、法线变换和他们的逆。对有经验的肚子来说,这些内容时一份参考手册,队友新手而言,这是变换这个主题的引导。这些材料是接下来其他章节的背景知识。我们冲最简单的变换开始,位移变换。[2016/07/10]
图4.1 左边的正方形经过位移矩阵T(5,2,0)变换,向右移动5个单位,向上移动2个单位。
4.1.1 位移
从一个位置位移到另一个位置可以使用位移矩阵T来完成。这个矩阵将对象位移向量
图4.1展示了位移变换的效果。[2016/07/11]上述公式表示点
4.1.2 旋转
旋转变换将向量(点或者方向向量)绕给点的轴(过圆心)旋转指定的角度。同位移矩阵一样,这是个刚体变换,点与点之间的距离保持不变,坐标系的左右手不变(不会从左手坐标系变为右手坐标系)。位移和旋转两种操作用来表示对象的位置和朝向。方向矩阵(orientation matrix)是一个旋转矩阵,用于定义相机或者物体在空间中的朝向。常用的旋转矩阵有
对3x3的旋转矩阵而言,表示绕任意轴旋转
旋转矩阵的效果如图4.4所示。旋转矩阵
所有的旋转矩阵的行列式为1,并且是正交的,可以参考附录A中关于正交矩阵的定义来证明。任意多个旋转矩阵的连接也满足以上性质。旋转矩阵的逆矩阵如下:
例子:绕点旋转。[2016/07/19]假设我们绕z轴旋转
图4.2 绕点p旋转的过程
4.1.3 缩放
缩放矩阵,
图4.4展示了缩放矩阵的效果。如果
使用齐次坐标,还可以容易的实现以点(3,3)为中心的缩放矩阵。齐次坐标的w分量,也可以用来实现缩放矩阵。例如,使用缩放因子5来等比缩放,缩放矩阵的(0,0),(1,1)和(2,2)位置设置为5,或者也可以将矩阵的(3,3)设置为1/5。这两种矩阵如下所示:
不同于缩放矩阵S,使用矩阵S’必须最后进行齐次化(就是将x,y,z除以w)。使用矩阵S’可能不会高效,因为在齐次化过程中需要将各个分量除以w,如果S’位于(3,3)的值为1就不需要进行除法。如果系统不检测w是否为1,每次都进行齐次化,那么使用S’不需要额外的除法。[2016/07/24]
对角线上的元素变为负数就得到一个反射矩阵,也称之为镜面反射矩阵。如果对角线上的两个元素为-1,那么相对于旋转
例如:沿着一确定方向的缩放。缩放矩阵S只能沿着x,y或者z轴缩放。如果需要沿着其他方向缩放,那么需要一个复合变换。假设沿着一确定方向的缩放可以在一个正交的,右手坐标系完成,坐标系以
基本思想是以新的轴为坐标系,然后在此坐标系中进行标准的缩放操作,然后再从新坐标系转换到原坐标系。第一步是乘以F的转置矩阵(正交矩阵的逆矩阵就是其转置)。然后执行缩放操作,最后再执行返原操作。变换公式如4.11
4.1.4 剪切
另一类变换操作是剪切矩阵的集合。这种变换操作应用在游戏中来扭曲整个场景,产生迷幻的效果,或者创建模糊的反射效果。有六个基本的剪切矩阵,分别为
将此矩阵乘到点p产生结果
图4.3 单元正方形使用
有些计算机图形系统中使用另一种剪切矩阵:
上述公式中的两个下标用来表示对象在两个轴上分别沿着第三个轴做剪切操作。着两个操作的组合为
最后,任何剪切矩阵的行列式都为1,
4.1.5 组合变换
由于矩阵乘法的不可交换性,矩阵相乘的顺序就非常重要了。变换的组合是顺序相关的。
一个顺序相关的例子,两个矩阵S和R,S(2, 0.5, 1)表示沿着x轴方向放大两倍,沿着y轴缩小一半。[2016/08/01]
图4.4 展示了矩阵连接顺序的不同导致的结果不同。上面一行先进行旋转操作
将多个矩阵组合为一个的原因是为了效率。例如,有一个拥有几千个顶点的对象,需要缩放、旋转和位移。这就需要对每个顶点都乘以这三个矩阵,这三个矩阵可以连接为一个矩阵。然后将这个新的矩阵作用到每个顶点上。最终的组合矩阵为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的逆矩阵可以这么计算,
另一种计算X的逆矩阵的方式如下,考虑R和X如下:
上述公式中,
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(ϕ) ,那么M−1=R(−ϕ)T(−t) 。 - 如果变换矩阵是正交矩阵,那么
M−1=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分别表示旋转的次序和沿着head,pitch和roll的旋转角度。这种变换操作很直观,因此可以对外行解释清楚。例如,旋转head角可以让观察者摇头说“no”, 旋转pitch角让他点头,旋转roll角让他向两边倾斜头。我们使用head, pitch和roll来替代x,y和z轴。欧拉变换可以用在世界坐标系中或者局部坐标系中。
当你使用欧拉变换是,有时会产生万向锁结。当一个旋转自由度丢失时,这种现象就会发生。例如,旋转顺序是x/y/z。考虑如下情况,绕y轴旋转
另一种观察万向锁结的方法就是设置
因为最终的欧拉旋转矩阵只依赖于角度(r+h),我们可以推导出有一个自由度已经丢失。
模型系统中,欧拉角经常以x/y/z顺序出现,依次绕每个轴旋转,其他顺序也是可行的。例如,z/x/y顺序经常用于动画系统中,z/x/z可以用于动画和物理系统中。后一种顺序,z/x/z对某些应用来说很优秀。根据毛球理论,万向锁结不可避免,没有一种完美的顺序来避免出现万向锁结。
对于细小的角度或者朝向变化,欧拉角有些限制。很难结合两组欧拉角。例如,两组欧拉角之间的插值不能简单的通过对每个角度的插值来完成。事实上,两组不同的欧拉角可以表示同样的朝向,所以会导致插值出来的欧拉角根本不会旋转物体。有一些替代的方法来表示朝向,例如接下来要讨论的四元数。
4.2.2 从欧拉变换中抽取参数
在有些情况下,从正交欧拉变换矩阵中抽取欧拉角h,p和r很有用。抽取方法如公式4.19所示:
连接三个旋转矩阵的结果如公式4.19所示:
由上式可知,pitch角可由
那么,欧拉角的三个参数h,p,r可以由atan2(y,x)函数从矩阵F中计算出来,如公式4.22所示:
这里有一个特例需要处理。如果
如果设置h=0,那么
注意arcsin的定义,
4.2.3 矩阵分解
到此为止我们工作在这样的假设之下,我们知道我们所用的矩阵的原始值和变换过程。这种假设不总是成立的,例如一个对象的变换矩阵可能是多个矩阵的组合。从一个组合矩阵中分离出多个基本变换矩阵的操作称之为矩阵分解。
有很多原因需要分解组合矩阵,如下:
- 抽取出缩放因子
- 找到特定系统所需要的变换操作。例如VRML不能使用任意的4x4矩阵。
- 检查模型的变换操作是否是刚体变换(只包含位移和旋转)。
- 计算动画中关键帧的插值,关键帧中只包含对象的变换矩阵。
- 从旋转矩阵中移除剪切
我们已经展示了两种分解方式,由位移和旋转矩阵派生出来的刚体变换,由正交矩阵派生出的欧拉变换。
正如我们所见,分解出位移矩阵非常简单,只需要看4x4矩阵的最后一列。也可以通过矩阵的行列式值是否为负来判断矩阵是否包含镜像操作。分离出旋转、缩放和剪切需要更多努力。[2016/08/29]
幸运的是,有很多关于矩阵分解的文章,也有很多代码。Thomas和GoldMan讨论了各种类型矩阵的分解方法。Shoemake在他们的基础上改进了仿射矩阵的分解方法,他的方法也可以做为独立参考,他还尝试从变换矩阵中抽取出刚体变换操作。
4.2.4 绕任意轴旋转
有时候需一个将对象绕任意轴旋转某个角度的方法。假设旋转的轴为
为了构建这个旋转矩阵,我们需要找到任意的另外两个单位向量,这两个向量之间正交,并与
图4.7 绕任意轴
第一步就是计算出新的标准基的轴。第一个轴为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 s和r是正交(垂直)的,(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]
- Real-Time Rendering 翻译 4.变换【上】
- Real-Time Rendering 翻译 4.变换【下】
- Real-Time Rendering 翻译 1.引言
- Real-Time Rendering 翻译 2.渲染管线
- Real Time Rendering --third edition 16.8节翻译
- Real-Time Rendering 翻译 3.图形处理单元
- Real-time rendering笔记
- Real-Time Rendering 笔记
- Real-time rendering笔记
- Real-Time Rendering 笔记
- Real-time rendering笔记
- Real Time Rendering
- Real-Time Rendering-第一章 Introduction
- Real-Time Rendering (2) - 变换和矩阵(Transforms and Matrics)
- real time rendering 第三版 内容介绍
- 【转】Resources on Real-Time Rendering
- Precomputed Radiance Transfer for Real-Time Rendering
- Real-Time Rendering Chaper 2 translation
- 你的生活中碰到过哪些平时注意不到的绝美事物?
- Java基础入门-Java开发环境的下载与配置环境变量
- 【Unity编辑器】Unity基于模板生成代码的原理与应用
- Han Solo and Lazer Gun
- 发送短信验证码
- Real-Time Rendering 翻译 4.变换【上】
- 动态规划_爬楼梯
- 接口顺序
- reversed与zip的用法:顺时针方向读取二维数组
- CSS布局——960gs
- Vijos P1889 天真的因数分解
- ViewController控制器的多种创建方式
- python爬虫下载极客学院视频
- Android Xutils框架使用之DBUtils