- 坐标变换其实一直是一个比较让人着迷的内容,嘿嘿嘿
- 从中也可以看到矩阵的魅力
- 记得一篇文章讲,矩阵就是记录一个向量到另一个向量的运动,一个点可以用一个向量来表示,乘上一个矩阵就变成了另一个向量,对应着另一个点。所以说矩阵就是记录向量空间中向量的运动,记录向量之间的转换规则。
齐次坐标
只讲三维的情况啊
- 向量空间中,只有标量和向量
- 向量 + 向量 = 向量
- 标量 * 向量 = 向量
- 三维向量空间中,可以视任意一组线性无关的向量为基
- 基 V = [ v1 , v2 , v3 ]
- 其他向量可以用一个三维的元组来表示
- 向量 a = [ A1 , A2 , A3 ]
- 于是 向量 a = A1 * v2 + A2 * v2 + A3 * v3
- 仅有向量是无法表示几何的,至少要有点吧
- 一般认为点的表示也是一个三维的元组
- 点 b = [ B1 , B2 , B3 ]
- 这样就无法区分点和向量了,咋办?
- 一般认为点的表示也是一个三维的元组
- 仿射空间
- 仿射空间中,基称为标架,由三个向量和一个点组成
- 标架 V = [ v1 , v2 , v3 , p ]
- 仿射空间的运算
- 向量+ 向量 = 向量
- 标量 * 向量 = 向量
- 点 + 向量 = 点
- PS:可以看到,点与向量的和为另一个点,其实也可以认为向量记录的是点的运动,记录着一个点转换到另一个点的信息
- 于是
- 向量 a = [ a1 , a2 , a3 , 0 ]
- 点 b = [ b1 , b2 , b3 , 1 ]
- 即
- a = a1 * v1 + a2 * v2 + a3 * v3 , 确实是向量
- b = b1 * v1 + b2 * v2 + b3 * v3 + p
- b = 向量 + p = 点
- 勉强区分开了哈
- 仿射空间中,基称为标架,由三个向量和一个点组成
- 还有问题
- 点p和向量v1v2v3怎么确定?它们的值又是在那种标架或基下的?
- 所以讨论了再多,这个标架其实还是对应我们普通的三维坐标系才显得平易近人,即
- 点p为原点
- v1 v2 v3 分别对应三个坐标轴 [1,0,0]、[0,1,0]、[0,0,1]
- 只不过我还告诉你,对于任意一个点和任意三个线性无关的向量v1 v2 v3,其都可以当作一个标架。因为三个线性无关的向量就可以表示出任意一个向量,再有一个点为基础,就可以表示任意一个点
- 所以讨论了再多,这个标架其实还是对应我们普通的三维坐标系才显得平易近人,即
- 点p和向量v1v2v3怎么确定?它们的值又是在那种标架或基下的?
- 所以想OpenGL中就默认,其世界坐标系对应的仿射空间,p为原点,v1v2v3为坐标轴
- 但是相机坐标系就不是了,因为啥?因为相机可以移动啊,可以改变朝向和正向,这些都影响着相机坐标系。单就移动来说:
- 相机的默认位置是在世界坐标系的原点,移动了之后就不是了啊
- 那么你在相机的位置看世界坐标系上的点,那些点的坐标表示就应该转换到相机坐标系上来,才对应着我们真正应该看到的点的位置
- 还是写写坐标系比较实在
坐标系
- 世界坐标系
- 世界坐标系的标架
- p为原点(0,0,0)
- v1为x轴 [ 1 , 0 , 0 ]
- v2为y轴 [ 0 , 1 , 0 ]
- v3为z轴 [ 0 , 0 , 1 ]
- 对于输入的顶点数据,如点 a = ( a1 , a2 , a3 )
- 在OpenGL内用四维来表示
- a = [ a1 , a2 , a3 , 1 ]
- 理解起来的话就是
- a = a1 * v1 + a2 * v2 + a3 * v2 + p
- a = [ a1 , 0 , 0 ] + [ 0 , a2 , 0 ] + [ 0 , 0 , a3 ] + ( 0 , 0 , 0 )
- a = ( a1 , a2 , a3 )//也就是这个点嘛
- 世界坐标系的标架
- 相机坐标系
- 相机默认的位置为世界坐标系原点,朝向是Z轴的负方向,正向是Y轴的正方向
- 考虑相机
- 位置就是相机的位置,也就是从哪里去观察这个世界
- 朝向就是相机对准的方向
- 正向就是相机该放在这个位置、对准了方向后,该怎么摆。比如一般我们拍照,竖着摆拍出来的就是竖着的照片,横着摆就是横着的照片。
- 而这些参数其实也是在世界坐标系下表示的
- 默认的相机坐标系
- 移动相机之后,相机的位置、朝向、正向就改变了
- 但顶点的数据还是对应着的世界坐标系,而我们要生成图片是依赖于相机的,所以我们要把顶点转换到相机坐标系下才行,这就是视图的转换。
- 视图转换后顶点的表示就是相对于相机坐标系,但其标架在逻辑上依然是 原点+三个坐标轴
- 裁剪坐标系
- 这还只是相机的外部参数,我们还需要确定
- 那一块的三维区域内的点,我才会拍下来,才会用来生成图像,即我需要规定一块“视景体”来确定拍照的范围
- 是否需要透视效果等等其他
- 这还只是相机的外部参数,我们还需要确定
- 还是讲坐标变换比较实在
坐标变换
OpenGL主要有两个矩阵,模型视图矩阵和投影矩阵
- 模型视图矩阵
- 对世界坐标系下顶点的变化操作,如平移、旋转、缩放(模型)都是对顶点的变化,而相机的位置、朝向、正向的改变(视图)也需要顶点从相对于世界坐标系下转换到相对于相机坐标系,这两种虽然是不同的改变但都是对顶点的操作,所以可以用一个矩阵来记录
- 对于一个点
a=∣∣∣∣∣∣x1y1z11∣∣∣∣∣∣
- 平移,就是在原坐标的基础上加上某个值
- 有平移矩阵
T=∣∣∣∣∣∣100001000100dxdydz1∣∣∣∣∣∣
- 使得
T∗a=∣∣∣∣∣∣x1+dxy1+dyz1+dz1∣∣∣∣∣∣
- 就是说只要在原先点的基础上左乘平移矩阵,就可以把点的坐标进行平移变换
- 记平移矩阵 T 为 T(dx,dy,dz),
- 有平移矩阵
- 旋转
- 先考虑绕Z轴旋转的情况,正向的旋转为右手大拇指朝向Z轴正向时,其余手指的朝向(逆时针)
- 绕Z轴旋转至改变X和Y坐标
- 有
x1=r∗cos(a)y1=r∗sin(a)x2=r∗cos(a+b)y2=r∗sin(a+b) - 所以就有
x2=x1∗cos(b)−y1∗sin(b)y2=x1∗sin(b)+y∗cos(b) - 所以绕Z轴旋转θ角度的旋转矩阵就是
Rz(θ)=∣∣∣∣∣∣cos(θ)sin(θ)00−sin(θ)cos(θ)