# 3D 变换
# 平移
T(tx,ty,tz)=100001000010txtytz1
# 缩放
S(sx,sy,sz)=sx0000sy0000sz00001
# 旋转
Rx(α)=10000cosαsinα00−sinαcosα00001Ry(α)=cosα0−sinα00100sinα0cosα00001Rz(α)=cosαsinα00−sinαcosα0000100001
3D 旋转变换矩阵遵循循环对称:X×Y=Z,Y×Z=X,Z×X=Y
# 合成的旋转变换
Rxyz(α,β,γ)=Rx(α)Ry(β)Rz(γ)
- 称为 “欧拉角”
- 常用于飞行模拟器:roll、pitch、yaw
# 罗德里格斯旋转公式
绕旋转轴 n 旋转 α 角度
R(n,α)=cos(α)I+(1−cos(α))nnT+sin(α)NN=0nz−ny−nz0nxny−nx0
四元数:旋转与旋转之间的差值
# 推导过程
-
对 v 做正交分解,得:v=v∥+v⊥
-
由向量的矢量投影公式,得:v∥=(v⋅k)⋅k
-
由 ① 和 ② ,得:v⊥=v−v∥=v−(v⋅k)⋅k
-
∵ k,v⊥ 与 w 两两垂直,且 ∣w∣=∣v⊥∣
∴ 由向量积得
w=k×v⊥=k×[v−(v⋅k)k]=k×v−k×(v⋅k)k=k×v−k×v∥
∵ k 与 v∥ 共线
∴ w=k×v
-
v⊥ 旋转 θ 角后得到 vrot⊥
将 vrot⊥ 正交分解,得:vrot⊥=a+b
a=vrot⊥×cos(θ−90∘)=vrot⊥×cos,a=wsinθ
b=vrot⊥×cos(180∘−θ)=vrot⊥×cos,b=v⊥cosθ
∴vrot⊥=a+b=wsinθ+vrot⊥cosθ=sinθk×v+cosθ[v−(v⋅k)k]
-
vrot=v∥+vrot⊥=(v⋅k)+sinθk×v+cosθ[v−(v⋅k)k]=(v⋅k)k+sinθk×v+cosθv−cosθ(v⋅k)k=cosθv+(1−cosθ)(v⋅k)k+sinθk×v
-
将得到的结果变为矩阵的形式:
-
推导,得:vrot=cosθv+(1−cosθ)(v⋅k)k+sinθk×v
把 k 和 v 分别写作列向量:
k=kxkykzv=vxvyvz
令 vrot=Rv,下面对 R 进行计算
-
(v⋅k)k=k(v⋅k)=k(kT⋅v)
-
k×v=kyvz−kzvykzvx−kxvzkxvy−kyvx=0kz−ky−kz0kxky−kx0vxvyvz
-
∴ R=Icosθ+(1−cosθ)kxkykz(kxkykz)+sinθ0kz−ky−kz0kxky−kx0
其中 I 为 3×3 的单位矩阵
# 如何将三维变成二维并在屏幕上显示出来
- 模型变换 (M)
- 相机变换 (V)
- 投影变换 (P)
# 相机的定义
- 位置 e
- 视线方向 $\hat {g} $
- 垂直方向 t^
如果把摄像机和世界一起变换,那么照片是一样的,所以把摄像机变换到新坐标系的原点,其他所有物体也做同样的变换
# TEG 坐标系怎么转变为 XYZ 坐标系
Mview=RviewTview
-
先做平移,Tview=100001000010−xe−ye−ze1
-
再做旋转,顺着思路要把 g^ 旋转到 −Z 坐标轴,把 t^ 旋转到 Y 坐标轴,把 (g×t) 旋转到 X 坐标轴,但这样的旋转矩阵非常难写
-
所以采用逆向思路,把坐标轴移到相机坐标轴,通过逆操作写(该旋转矩阵为正交矩阵,其逆矩阵就是它的转置矩阵)(基变换)
Rview−1=xg^×t^yg^×t^zg^×t^0xtytzt0x−gy−gz−g00001Rview=xg^×t^xtx−g0yg^×t^yty−g0zg^×t^ztz−g00001
# 投影变换
# 计算机图形学中的投影
# 透视投影与正交投影
# 正交投影
- 相机位于原点,面向 −Z,上方是 Y
- 忽略 Z 坐标
- 将生成的矩形平移并缩放为 [−1,1]2
Mortho=r−l20000t−b20000n−f200001100001000010−2r+l=2t+b−2n+f1
- 沿着 −Z 使远近不直观(n>f)
- 仅供参考:这就是 OpenGL 使用左手坐标的原因。
# 透视投影
- 最常见于计算机图形学、艺术、视觉系统
- 近大远小
- 平行线不平行; 收敛到单点
# 推导过程
正交投影矩阵的视锥体是一个四棱锥的一部分,其中近平面为 z=n,远平面为z=f,我们要把这个视锥体转换到一个正方体[−1,1][−1,1][−1,1] 中,可以先把远平面压缩,把视锥体压缩成一个长方体,然后再通过第二步中的正交投影矩阵就可以变换到正方体中,如图。
在把视锥体压缩成长方体的过程中,我们规定三个原则
-
近平面的所有点坐标不变
-
远平面的所有点坐标 z 值不变 都是 f
-
远平面的中心点坐标值不变 为 (0,0,f)
然后我们假设视锥体内的任意一点 (x,y,z),压缩以后的 xy 坐标应该与近平面上对应的点相同,如图解相似三角形可以得到 y→ny/z,x→nx/z
故对于(x,y,z,1) 一点,它在视锥体压缩以后坐标应该为(nx/z,ny/z,unknow,1)。
z 值我们还不知道,这里先不讨论。
xyz1⇒nx/zny/zunknown1
也就是我们现在需要找到一个矩阵 Mpersp→ortho,使得上面的转换成立。
假设矩阵的第一行为 A,B,C,D。可以得到等式 Ax+By+Cz+D=nx/z。
然后我们发现这个等式好像很难求,如果让 A=n/z,其他等于0,的确可以得到结果。
但是矩阵的值应该是常数,n/z 是个变量。
而其他的结果也很难写出来,同时矩阵的第二行也会有同样的问题 Ex+Fy+Gz+H=ny/z,也很难求。
所以我们换一种方法,前面根据已学知识可以知道(x,y,z,1) 与(kx,ky,kz,k=0) 这两个点是完全等价的点,
所以我们让k 取z 可以把坐标(nx/z,ny/z,unknow,1) 变为(nx,ny,still unknow,z)。
Mpresp→ortho(4×4)xyz1=nxnyunknownz
也就是我们需要找到矩阵 Mpersp→ortho,使得上面的转换成立。
现在就变简单了,Ax+By+Cz+D=nx,求出 A=n,B=C=D=0
Ex+Fy+Gz+H=ny,求出 F=n,E=G=H=0
Mx+Ny+Oz+P=z,求出 O=1,M=N=P=0。
Mpresp→orthon0?00n?000?100?0
于是,我们求出了矩阵的其中三行,只剩下第三行是未知的。
然后我们想下之前的三个原则,其中一个,近平面的所有点坐标不变。
也就是点 (x,y,n,1) 通过矩阵 Mpersp→ortho 变换后,应该还是等于 (x,y,n,1)。
n0?00n?000?100?0∗xyn1=xyn1
对于第一二四行,我们写出等式
nx+0y+0n+0∗1=x0x+ny+0n+0∗1=y0x+0y+1n+0∗1=1
很明显这是有问题的,因为 n 应该是任意常数,但是现在只有在 n 等于 1 时,一二四行的运算才成立
所以我们根据前面的方法,再把 (x,y,n,1) 都乘以一个 n 等价变为 (nx,ny,n∗n,n)。
这样转换就变成了
n0?00n?000?100?0∗xyn1=nxnyn∗nn
对于第一二四行,我们写出等式
nx+0y+0n+0∗1=nx0x+ny+0n+0∗1=ny0x+0y+1n+0∗1=n
完美成立。现在我们可以安心的求第三行了。
设第三行的四个数分别为 ABCD
可以获得等式 Ax+By+Cn+D=n∗n。
明显 A=0,B=0,Cn+D=n∗n ①
我们接下来考虑第三个原则,远平面的中心点坐标值不变 为(0,0,f)
同样为了保证之前求的矩阵一二四行成立,我们需要把 (0,0,f,1) 写成 (0,0,f∗f,f)
n0?00n?000?100?0∗00f1=00f∗ff
Cf+D=f∗f ②
联立 ① ②,解得:C=n+f,D=−nf
终于,我们求得了 Mpersp→ortho 矩阵为
n0000n0000n+f100−nf0
也就是通过这个矩阵,我们可以把原来的透视投影的视锥体压缩为正交投影的视锥体(长方体)
最后我们再乘上一开始求出来正交投影矩阵 Morth 就得到了透视投影矩阵:Mpersp=Mortho∗Mpersp→ortho
2/(r−l)00002/(t−b)00002/(n−f)10001∗100001000010−(l+r)/2−(b+t)/2−(f+n)/21=n0000n0000n+f10000