OpenGL学习脚印: 坐标和变换的数学基础(math-coordinates and transformations)
来源:互联网 发布:lol代升级软件 编辑:程序博客网 时间:2024/06/05 10:36
写在前面
上一节介绍了向量和矩阵,本节将熟悉坐标、线性变换、仿射变换以及坐标转换等概念和计算方法,这些内容对后续的学习将会有很大帮助。部分内容不是OpenGL编程初学者所必须掌握的,可以在以后需要时再回头来看。
这里是对这些知识点的一个总结,旨在对他们有个整体把握,后面具体应用时会使用这些概念。内容尽量以例子形式说明,仅在必要时会给出数学证明。一个主题往往涉及过多内容,对于文中省略的部分,请参考相应的教材。
通过本节可以了解到
- 坐标的概念
- 线性变换的概念和计算方法
- 仿射变换
- 坐标转换的概念和计算方法
坐标系及坐标
坐标是在特定坐标系下表示物体位置的方法,一谈到坐标,必定是在某个坐标系下给定的。例如经纬度坐标是相对于地球的球面坐标系统给出的。
坐标系则给出了一个参考框架,在这个框架里面,定义其他位置相对于一个起始点(这个起始点称作原点
常见的坐标系包括:笛卡尔坐标系,极坐标系,球面坐标系等。
如下图所示的我们熟悉的,2D笛卡尔坐标系(来自wiki):
如下图所示的熟悉的3D笛卡尔坐标系(来自wiki):
定义坐标系
定义一个坐标系需要指定(参考自Objects in Motion):
- 坐标系的维度 2D, 3D, 4D等等
- 定义坐标空间轴的向量 这些向量成为基向量,他们有名字,例如x,y,z;这些向量一般而言都是正交的,但不一定非得互相正交(只要线性无关即可,后面介绍),但是每一个维度必须只有一个轴。
- 坐标系的原点O 原点是导出其他点的参考点。
- 一个表明空间中点是否合法的区域 在此区域之外的点就不再合法。这个区域根据空间不同,可以是无穷的。
这里,维度已由基向量维数确定,合法区域一般是无穷的,但是在图形处理中某些坐标空间是有限的,例如规范化设备空间(后面其他文章会介绍)。作为一个了解,基向量不一定非得正交,如下图所示:
对于一般情况,我们只需要记住:
坐标系=(基向量,原点
左手坐标系和右手坐标系
对于任意2个2D坐标系,我们通过旋转、移动翻转可以将两个坐标系xy轴的指向相同。
但是对于3D坐标系,任意两个坐标系却不能等价。实际上,存在两种完全不同的3D坐标系:左手坐标系和右手坐标系。如果同属于左手坐标系或者右手坐标系,则可以通过旋转来重合,否则不可以。
判断一个坐标系是否属于右手系,可以拿出右手,然后右手的大拇指代表+x轴指向,食指代表+y轴指向,中指代表+z轴指向,你可以转动你的右手来匹配这个坐标系,如果能匹配则是右手坐标系,否则是左手坐标系。判断左手坐标系的方法类似。如下图所示为判断右手坐标系的方法(来自OpenGL coordinate system):
关于左右手坐标系理解还可以可参考下图(来自《3D数学基础》):
如上右图右手坐标系,这里拇指、食指、其余手指分别代表x,y,z轴的正方向。高等数学教材上使用的是右手坐标系。
旋转正方向的判断
同样还存在一个左手规则和右手规则,可以用于判断当物体绕轴旋转时正方向的判定问题。
对于左手规则,确定一个旋转轴后,左手握成拳头,拇指指向旋转轴的正方向,则其余手指弯曲方向即为旋转的正方向。从旋转轴正向末端来看,正向旋转是顺时针的。对于右手规则,有同样的方法。可参见下图:
左手右手规则在不同场合有着不同作用。上一节,我们使用右手规则判断了叉积的结果向量的方向。
注意OpenGL中坐标系 OpenGL中的物体、世界、照相机坐标系都属于右手坐标系,而规范化设备坐标系使用左手坐标系。笼统地说OpenGL使用右手坐标系是不合适的。这些坐标系后面会介绍。关于这个问题可以参考SO.
坐标
坐标是在指定坐标系中,相对于原点
这样在坐标系中一点
这时称
一般地使用的3D笛卡尔坐标系使用标准基向量和坐标原点:
从上面可以看到,在一个坐标系中,求取坐标的过程,是一个向量分解的过程。求取一个位置在另一个不同的坐标系中的坐标,则需要进行坐标转换。后面会介绍。
使用坐标系的优势
使用坐标系统便能以解析几何的形式来研究空间几何。通过建立一个坐标系使得空间中点用有序实数组表示,空间图形用方程表示,这样能方便地研究几何图形的性质。
必要基础概念
了解线性变换、仿射变换以及坐标转换,对于后面学习图形编程中的模型变换方法有很大帮助,因此这里予以介绍。要了解这些概念,需要一些其他概念的支撑,这里逐一介绍。每一个概念以定义结合示例的形式给出,如果暂时没有理解清楚,可以暂时跳过,以后回过头来再看或者参考这个主题的其他资料。本部分最后会给出完整的线性变换示例。
向量组的线性组合
向量组是一组向量的集合,例如
则称向量
向量组线性无关
对于向量组
α1,α2,⋯,αm ,如果存在不全为零的数λ1,λ2,⋯,λm ,使下面的等式成立:
λ1α1+λ2α2+⋯+λmαm=0(2)
则称向量组α1,α2,⋯,αm 线性相关(linearly dependent), 否则称为线性无关( linearly independent)。也就是要使向量组α1,α2,⋯,αm 线性无关,那么所有的系数λi 都必须为0。
线性相关的一种几何解释 来自math.stackexchange:
假定你有一组向量
当然存在其他方法,判断向量组线性相关性,感兴趣的可以参考线性代数教材。
线性空间的基
向量空间(也叫做线性空间)是对我们经常使用的2D和3D空间一般规律的拓展,它的定义主要反映的是满足一系列的运算规律,例如交换律和结合律等。由于这个定义包含较多规则,不在此列出,感兴趣的可以参考vector space。
如果在线性空间V中存在n个线性无关的向量
α1,α2,⋯,αn 使得V中任意元素α 都能由他们线性表示,则称α1,α2,⋯,αn 为V的一个基。基所含向量个数n称为线性空间V的维数,并称V为n维线性空间。
例如2D空间中,二维向量组
向量在基下的坐标
设
α1,α2,⋯,αn 是n维线性空间V的一个基,若任取α∈V ,总有且仅有一组有序实数x1,x2,⋯,xn ,使得:
α=x1α1+x2α2+⋯+xnαn=(α1,α2,⋯,αn)⎡⎣⎢⎢⎢⎢x1x2⋮xn⎤⎦⎥⎥⎥⎥(3)
成立,则称这组有序数x1,x2,⋯,xn 为元素α 在基α1,α2,⋯,αn 下的坐标,记作(x1,x2,⋯,xn)T 。
这里元素
线性变换(Linear Transformations)
变换这个词类似于函数,即将一个定义域里的输入量转化为值域里的另一个值,变换就是一个映射关系,一种规则。线性变换的一些性质对于后续学习3D模型变换时,理解起来将会更容易。
线性变换
T:U→V 是一个函数,将定义域U中元素,映射到值域V中,并满足下列两个条件(参考Definition LT):
1)可加性 对任意u1,u2∈U ,都满足:T(u1+u2)=T(u1)+T(u2)
2)齐次性 对任意u∈U 和任意标量k ,都满足:T(ku)=kT(u)
可以利用上面的两个条件,即可加性和齐次性条件验证一个变换是否是线性变换。
线性变换示例(来自Example ALT)
首先验证其是否满足可加性:
然后验证是否满足齐次性:
由上述*和**式可知,变换T满足可加性和齐次性,因而是线性变换。
实际上判断线性变换还有一个简单方法,即看变换后每个组成部分是不是原来分量的倍数(不能为常量)。
例如变换
都不是线性变换。其中g中
对于线性变换一个重要的性质是(令齐次性表达式中u=0可得到):
线性变换与矩阵一一对应
对一个线性变换
T ,存在一个矩阵A 与之对应,变换表示为T(x)=Ax ,其中x 为列向量。
证明: 1.首先证明充分性。
当
其中:
2.证明必要性
当变换
由矩阵乘法性质,容易得到:
则说明
由1,2得到,线性变换
例如矩阵
对应的线性变换为:
由给定的线性变换:
要找到对应的矩阵A,由上面定理证明时可知,标准矩阵A的内容为:
其中
所以最终计算得到矩阵
后面会详细介绍矩阵A的计算方法。在此之前,先来看下线性变换的应用。
线性变换的应用
线性变换在3D图形中模型变换部分应用很多,例如旋转、错切(shear)、缩放等操作都是线性变换。在OpenGL中使用矩阵操作来表示这些线性变换。例如2D平面上绕原点的旋转
通过利用极坐标系表示
那么矩阵:
使用矩阵表达变换的优势 通过使用矩阵形式,能够级联对物体顶点的变换,例如先执行旋转,后执行缩放,则表示为:
线性变换对应矩阵的计算方法(重要结论)
线性变换由基及变换后基的值唯一确定,通过计算线性变换后基的值可以得到线性变换对应的矩阵A。 这是本节讲述线性变换最重要的结论。
定理: 设
u1,u2,⋯,un 是线性空间U的一个基,线性空间V包含向量v1,v2,⋯,vn (可以相同)。那么存在唯一的线性变换T:U→V 使得:T(ui)=vi(1≤i≤n) 。
上面的定理证明,感兴趣的可以参考 Theorem LTDB,不在此处给出详细过程。
这个定理告诉我们: 只要知道了线性空间U的给定基
这个定理的作用就好比,两点确定一条直线。因此我们可以通过计算:
也就是说,矩阵
例如对于上面的旋转矩阵,从基和转换后基的角度,也就是从x,y轴来看,
利用三角函数公式可以计算转换后
。
因此可以顺利的写出旋转矩阵为:
矩阵第一列即为
在后面使用OpenGL模型变换矩阵时,经常要使用到这个方法,理解了这一点后面理解模型变换矩阵就会变得简单。
基变换与坐标变换(重要结论)
一个位置,在不同的坐标系里有不同的坐标。设
则上面的式子可以简写为:
矩阵
设有一个向量
其中:
由上式得到:
将式子a代入式子b得到:
式子c和d给出了向量
上面的矩阵
这个矩阵的三个列向量,就是基
对应的
那么上面的式子c和d可以分别改写为:
从式子e和f来看,我们可以得出,要在两个基之间转换坐标,只需要求出一个基在另一个基里的坐标表示即可,这个坐标表示构成矩阵
示例
已知基
基
容易求出:
即:
也可得:
即:
给定向量
也就是:
那么:
容易验证:
(1)
(2)
仿射变换
线性变换无法表达一类重要的变换——平移变换。平移变换表达的是对于点
我们尝试寻找变换
当
仿射变换与线性变换不同之处在于,线性变换保持原点位置不变,而仿射变换可以改变原点的位置。仿射变换包括线性变换,例如旋转,缩放等变换,特殊地是仿射变换包括平移变换。例如
使用3x3矩阵无法表达平移变换(当
齐次坐标(homogeneous coordinate)
齐次坐标是在原来坐标的基础上添加了一个
定义标量0和1与点的乘法为:
可以把向量
因此,使用齐次坐标系表示点形式为:
表示向量为:
这里齐次坐标的
使用4x4矩阵表示仿射变换
对于上面的平移变换:
当
可以计算得到
上面的矩阵A对应平移变换,对于线性变换,矩阵A中:
也就是说矩阵A的结构为:
使用4x4矩阵表示坐标转换
前面介绍的基变换与坐标变换,没有考虑到原点,两个坐标系的原点位置可能不同,因此需要使用4x4矩阵调整下上面的结果。对于参考点
还需要添加一个
写成矩阵形式为:
其中M是一个4x4矩阵:
坐标转换的其余部分,与上面讲述的3x3矩阵类似。
坐标转换示例1
下图所示的旋转坐标系后,求取原坐标系下点p在[s,t]坐标系下坐标,如下图所示:
直接利用极坐标推导的过程,请参考 坐标旋转变换公式的推导。我们使用上面介绍的寻找基向量之间关系的方法来计算这个变换矩阵。
已知
那么:
即:
坐标转换示例2
这个例子来自参考资料[1]。
如下图所示,存在两个坐标系,世界坐标系和照相机坐标系:
其中照相机坐标系的原点位于世界坐标系的
那么点O和xyz轴构成的世界坐标系和以点P及uvn构成的照相机坐标系之间存在转换关系。其中uvnP在世界坐标系的表示为:
xyzO在照相机坐标系下的表示为:
则世界坐标系的原点O在uvnP坐标系下的坐标为:
这个即求出世界坐标系的原点在照相机坐标系下的
同时照相机坐标系下的原点P在世界坐标系
这个即求出了照相机坐标系的原点在世界坐标系的
这个例子说明了不同坐标系下坐标之间的转换,后面还会详细介绍OpenGL中使用的坐标转换。
参考资料
[1]《交互式计算机图形学-基于OpenGL着色器的自动向下方法》电子工业出版社 Edward Angle等著
[2]《3D数学基础:图形与游戏开发》 清华大学出版社
[3]《线性代数》武汉大学数学与统计学院 高等教育出版社 齐民友主编
[4] Linear Transformations
[5] matrices_linear_transformations
[6] Linear transformations
[7] Objects in Motion
[8] 很棒的 LINEAR TRANSFORMATIONS 课件
- OpenGL学习脚印: 坐标和变换的数学基础(math-coordinates and transformations)
- OpenGL学习脚印: 坐标和变换的数学基础(math-coordinates and transformations)
- OpenGL学习脚印: 投影矩阵和视口变换矩阵(math-projection and viewport matrix)
- OpenGL学习脚印: 坐标变换过程(vertex transformation)
- OpenGL学习脚印: 向量和矩阵要点(math-vector and matrices)
- OpenGL学习脚印: 向量和矩阵要点(math-vector and matrices)
- OpenGL学习脚印: 模型变换(model transformation)
- OpenGL学习脚印: 视变换(view transformation)
- OpenGL学习脚印: 模型变换(model transformation)
- OpenGL学习脚印: 视变换(view transformation)
- OpenGL的坐标变换
- OpenGL Basic Transformations - OpenGL 基础变换原理(1)
- OpenGL Basic Transformations - OpenGL 基础变换原理(2)
- Transformations between ECEF and ENU coordinates
- OpenGL矩阵和坐标变换
- OPENGL 点击与选取的基础---坐标变换
- OpenGL学习脚印: 光照基础(basic lighting)
- OpenGL ES几何变换和坐标变换
- Android Fragment release 有时黑屏解决办法
- 通过传址来传递和返回对象
- 基础知识:二、 Service
- service和serviceImpl抽取
- leetcode_292_Nim Game
- OpenGL学习脚印: 坐标和变换的数学基础(math-coordinates and transformations)
- centos 启动后,自动执行自己的脚本。
- 微信登陆,用到的。
- 路在远方,努力不止!!!
- POJ3320
- 使用Dom4j解析XML
- 2014年第五届蓝桥杯C/C++程序设计本科B组决赛 出栈次序(结果填空)
- C#委托和事件
- ssh 相关设置