本章內容:
羅德里格斯旋轉公式 Rodrigues' rotation formula
模型變換 modeling tranformation
視圖變換 camera/view transformation
投影變換(正交、透視)projection tranformation
視口變換 viewport tranformation
第二章 視圖、投影變換
上一章節內容:
二維空間的變換:旋轉rotation、縮放scale、剪切shear
齊次座標系Homogeneous coordinates
上一章的內容比較基礎,理解難度不大。本章相較於上一章節,難度較大。
這一章內容:
三維變換 3D transformations
羅德里格斯旋转公式 Rodrigues' rotation formula(難點)
觀測變換(視圖變換) Viewing transformation
模型變換 modeling tranformation
攝像機/視圖變換 camera/view transformation
投影變換 projection tranformation
正交變換 Orthographic projection
透視變換 Perspective projection(難點)
視口變換 viewport tranformation
2.1 3D變換 3D Transformations
在齊次座標系中, $\left(\begin{array}{}x\y\z\w\end{array}\right)$代表三維空間中的一個點$\left(\begin{array}{}x/w\y/w\z/w\1\end{array}\right),w\ne0$ .
x′y′z′1=adg0beh0cfi0txtytz1⋅xyz1(1) 2.1.1 縮放與平移 Scale&Translation
基本與二維的旋轉類似。
S(sx,sy,sz)=sx0000sy0000sz00001(2) T(tx,ty,tz)=100001000010txtytz1(3) 2.1.2 拉伸 Shear
可以僅僅進行二維的拉伸:
與2D變換一樣,任何3D變換矩陣都可以用SVD分解為旋轉、縮放和旋轉。任何對稱的3D矩陣都具有旋轉、縮放和逆旋轉的特征值分解。最後,三維旋轉可分解為三維拉伸(Shear)矩陣的乘積。
shear-x(dy,dz)=100dy10dz01(4) 2.1.3 旋轉 Rotate
比二維旋轉複雜得多,因為可能旋轉的軸更多。但是,我們如果只想繞著某一個軸旋轉,則只會改變另外兩個軸。
2.1.3.1 繞一個軸旋轉
比方說,我們繞z軸旋轉,則只需要改變x和y軸,z軸保持不動(右側是基於齊次座標下的,下面同理):
rotate-z(ϕ)=cosϕsinϕ0−sinϕcosϕ0001(5) Rx(α)=10000cosαsinα00−sinαcosα00001(6) rotate-x(ϕ)=1000cosϕsinϕ0−sinϕcosϕ(7) Rz(α)=cosαsinα00−sinαcosα0000100001(8) rotate-y(ϕ)=cosϕ0−sinϕ010sinϕ0cosϕ(9) Ry(α)=cosα0−sinα00100sinα0cosα00001(10) 但是我們發現,y軸 (9),(10) 這裡的有一些奇怪。
2.1.3.2 復合旋轉
將 $\mathbf{R}_x(\alpha),\mathbf{R}_y(\alpha),\mathbf{R}_z(\alpha)$ 復合:
Rxyz(α)=Rx(α)Ry(α)Rz(α) 2.1.3.3 羅德里格斯旋转公式 Rodrigues' rotation formula
R(n,α)=cos(α)I+(1−cos(α))nnT+sin(α)N0nz−ny−nz0nxny−nx0(11) 其中,$n$軸默認是過圓點$(0,0)$的且是單位向量;$N=n^*$,即$N$是$n$的矩陣形式(需要可以回顧上一章節 1.2.7 的內容)。
推導思路:假設是向量$a$繞著n軸旋轉至**$b$,則將$a$**分解為平行於n軸的分量(發現是不變的)加上垂直於n軸的分量。
詳細推導過程:https://www.bilibili.com/video/BV1Eu411r7GC/
2.2 觀測變換 View Transformation
前面的內容,我們學習了如何使用矩陣變換在2D或3D空間中對物體進行旋轉、平移、縮放和裁切等一系列幾何變換(geo- metric transformations)操作。幾何變換的第二個用途就是用於觀測變換,也就是一種3D到2D的映射。下圖展示了將對象從原始座標轉換到屏幕空間的空間和變換序列:
如圖所示,觀測變換分為四個步驟:
模型變換 modeling tranformation
攝像機/視圖變換 camera/view transformation
投影變換 projection transformation
視口變換 viewport transformation
提取上面三個步驟的首字母,MVP,也就很容易記住觀測變換的三大步驟了。
接下來,我們依次講解。
2.2.1 模型變換 modeling tranformation
2.2.2 攝像機/視圖變換 camera/view transformation
我們把計算機圖形想像成一個攝影的過程,攝像機就是鏡頭的中心。
攝像機/視圖變換(下文簡稱攝像機變換)的目的是,獲取所有在攝像機視線範圍的物體與攝像機之間的相對位置。非常直觀的做法就是以攝像機為中心,換一句話說,就是把攝像機調整至世界座標的原點上。怎麼讓攝像機與世界座標原點重合呢?
2.2.2.1 攝像機定義
通過上面三個定義,即可建立以$e$為原點,基底為 $u,v,w$ 的攝像機座標系(如下圖所示)。
wuv=−∥g∥g=∥t×w∥t×w=w×u(12) $u,v,w$ 分別對應笛卡爾座標系中的 $x,y,z$
$g$ 向量對應 $z$ 軸( $w$ 軸)的負方向
2.2.2.2 將相機座標系移動至原世界座標系的原點
分為兩個步驟:
第一步非常簡單,只需要將當前相機座標減去相機座標,即: $\left[\begin{array}{cccc}1 & 0 & 0 & -x_e \0 & 1 & 0 & -y_e \0 & 0 & 1 & -z_e \0 & 0 & 0 & 1\end{array}\right]$ .
第二步,由於旋轉變換矩陣是一種正則基矩陣(正交矩陣 The orthogonal matrix),矩陣 $M^T=M^{-1}$ ,所以將單位矩陣$I$旋轉至當前相機狀態的矩陣的逆矩陣則是: $\left[\begin{array}{cccc}x_u & y_u & z_u &0 \x_v & y_v & z_v & 0 \x_w & y_w & z_w & 0 \0 & 0 & 0 & 1\end{array}\right]$ .
所以,定義相機變換矩陣 $M_{cam}$ :
Mcam =[u0v0w0e1]−1=xuxvxw0yuyvyw0zuzvzw00001100001000010−xe−ye−ze1(13) 2.2.3 投影變換 projection transformation
https://stackoverflow.com/questions/36573283/from-perspective-picture-to-orthographic-picture
2.2.3.1 正交投影變換 The Orthographic Projection Transformation
攝像機在世界座標原點,看向 $-Z$ 軸, 正上方是 $Y$ 軸。
則很容易推倒出將長方體變換到中心是$(0,0,0)$ 且所在區域是 $[-1,1]^3$ 的變換矩陣$M_{orth}$:
Morth =r−l20000t−b20000n−f20−r−lr+l−t−bt+b−n−fn+f1(14) 2.2.3.2 透視投影變換 Perspective Projection
透視投影過程很簡單,我們先將Frustum“壓縮”成Cuboid,也就是先將透視投影轉換為正交投影,然後就可以利用2.2.3.1的知識做投影變換了。
壓縮如下圖所示。我們需要找出“壓縮”這一步的變換矩陣$M_{\text {persp } \rightarrow \text { ortho }}^{(4 \times 4)}$。
求解步驟如下:
將 $(x,y,z)$ 投影到屏幕上,就變成了 $(x',y',z')$
原點是視點, $z=-n$ 表示投影平面,利用相似三角形得出投影後的 $x,y$ 座標
現在我們清楚的是,xOy平面的變換過程,但是z怎麼變化尚不清楚。
回顧一個齊次座標的性質
$(x,y,z,1)=(kx,ky,kz,k\ne0)$
$(x,y,z,1)=(xz,yz,z2,z\ne0)$
例子:$(2,0,0,2)=(1,0,0,1)$,都代表三維空間中的點$(1,0,0)$。
xyz1⇒Mpersp→ortho(4×4)nx/zny/z unknown 1==mult. by znxny still unknown z(15) 我們想要求處上面方程中的變換矩陣 $M_{\text {persp } \rightarrow \text { ortho }}^{(4 \times 4)}$ ,則只需解方程(16):
Mpersp→ortho(4×4)xyz1=nxnyn⋅unknownz(16) 由於等號右邊第三行未知,我們只能寫出“壓縮”變換矩陣的一部分:
Mpersp→ ortho =n0?00n?000?100?0(17) 利用透視投影的性質:將Frustum“壓縮”成Cuboid後,n面和f面的$z$座標不變。
我們將 $z=n$ 帶入方程(16)中,得到方程(18):
Mpersp→ortho(4×4)xyn1=nxnyn2n(18) 由方程(18),將變換矩陣$M$的第三行單獨拿出來,並且方程右邊的 $n^2$ 肯定與 $x,y$ 無關,所以得到方程(19):
(00AB)xyn1=n2⇒An+B=n2(19) 且我們欲求的變換矩陣 $M_{persp \rightarrow ortho}$ 第三行的前兩個數字也確定了
又因為遠平面 $f$ 的中間點 $(0,0,f)$ 經過變換依然是 $(0,0,f)$ ,所以將 $(0,0,f)$ 帶入方程(16),得到方程(20):
n0000n0000A100B000f1=00f2f⇒Af+b=f2(20) {A=n+fB=−nf(21) 則求出“壓縮”變換矩陣 $M_{persp \rightarrow ortho}$ :
Mpersp→ortho=n0000n0000n+f100−nf0(22) 所以,透視投影 $M_{persp}=M_{ortho}M_{persp\rightarrow ortho}$
Mpersp=r−l2n0000t−b2n00l−rl+rb−tb+tn−ff+n100f−n2fn0(23) 2.2.3.3 關於透視矩陣的練習題
問:在Frustum內部,任意一點經過了“壓縮”變換矩陣 $M_{persp \rightarrow ortho}$ 的變換後,會向哪個方向移動?
答:對於Frustum中的任意一點 $\left(\begin{array}{l}x \y \z \1\end{array}\right)$ ,其中 $(n<x<f)$ ,經過“擠壓”變換都有:
$M_{persp \rightarrow ortho}\left(\begin{array}{l}x \y \z \1\end{array}\right)=\left(\begin{array}{l}nx \ny \(n+f)z-nf \z\end{array}\right)$
$\left(\begin{array}{l}nx/z \ny/z \(n+f)-nf/z \1\end{array}\right)$
現在問題轉換為判斷變化前後 $z$ 分量的大小關係。
$\text{let } z=\frac{n+f}{z}$ 經過變化得到點 $z'$
易得 $z'=\frac{n^2+f^2}{n+f}$
使 $z,z'$ 做差,得 $z'-z = \frac{(n-f)^2}{2(n+f)}$
所以 $z'-z<0$ ,所以變化後的點向遠平面靠近(距離屏幕更遠)。
2.2.4 視口變換 viewport transformation
做完模型、攝像機、投影變換之後,所有需要的物體都在$[-1,1]^3$這個立方體內了。
我們將$x=-1$放在屏幕的左側,$x=+1$仿仔屏幕的右側,$y=-1$放在屏幕的底部,$y=+1$放在屏幕的頂部。
屏幕上每一個像素都“擁有”1個以整數座標為中心的單位正方形。在渲染的時候,需要將 $[-1,1]^2$ 映射到 $[-0.5,n_x-0.5]*[-0.5,n_y-0.5]$ ,公式如下:
Mviewport=2nx00002ny0000102nx−12ny−101(24) 如果需要將 $[-1,1]^2$ 映射到 $[0,n_x]*[0,n_y]$ ,則公式如下:
Mviewport=2nx00002ny0000102nx2ny01(25) 2.2.5 觀測變換矩陣 $M$
M=MviewportMperspMcamMmodel(26) 2.2.5 變換模型代碼(c++) C++ Code(附)
模型變換 Modeling Transformation
這裡的3D變換是繞 $z$ 軸旋轉,即變換矩陣(6):
Rx(α)=10000cosαsinα00−sinαcosα00001(6) 直接通過3D變換就可以寫出get_model_matrix()
模型變換函數。
需要注意:
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
auto radian = (float)(rotation_angle/180.0*MY_PI);
Eigen::Matrix4f translate;
translate << cos(radian),-sin(radian),0,0,
sin(radian),cos(radian),0,0,
0,0,1,0,
0,0,0,1;
model = translate * model;
return model;
}
攝像機/視圖變換 camera/view transformation
默認相機的朝向一定正確,只需要調整當前攝像機的位置向量eye_pos
至世界座標的原點即可。
Eigen::Matrix4f get_view_matrix(Eigen::Vector3f eye_pos)
{
Eigen::Matrix4f view = Eigen::Matrix4f::Identity();
Eigen::Matrix4f translate;
translate << 1, 0, 0, -eye_pos[0],
0, 1, 0, -eye_pos[1],
0, 0, 1, eye_pos[2],
0, 0, 0, 1;
view = translate * view;
return view;
}
投影透視變換 Perspective Projection
本函數需要寫出兩個矩陣:
Mpersp→ortho=n0000n0000n+f100−nf0(22) Morth =r−l20000t−b20000n−f20−r−lr+l−t−bt+b−n−fn+f1(14) Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar){
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
Eigen::Matrix4f M_p2o = Eigen::Matrix4f ::Identity();
M_p2o << zNear,0,0,0,
0,zNear,0,0,
0,0,zNear+zFar,-zNear*zFar,
0,0,1,0;
Eigen::Matrix4f M_orth = Eigen::Matrix4f ::Identity();
float fov = 0.5*eye_fov*MY_PI/180;
float top = tan(fov) * zNear;
float bottom = -top;
float right = top * aspect_ratio;
float left = -right;
M_orth << 2/(right-left),0,0,-(right+left)/(right-left),
0,2/(top-bottom),0,-(top+bottom)/(top-bottom),
0,0,2/(zNear-zFar),-(zNear+zFar)/(zNear-zFar),
0,0,0,1;
projection = M_orth * M_p2o;
return projection;
}
實現以下公式即可。
R(n,α)=cos(α)I+(1−cos(α))nnT+sin(α)N0nz−ny−nz0nxny−nx0(11) Eigen::Matrix4f get_rotation(Vector3f axis, float angle){
Eigen::Matrix4f M_rodrigues = Eigen::Matrix4f::Identity();
Eigen::Matrix3f M_temp_rodrigues = Eigen::Matrix3f::Identity();
Eigen::Matrix3f M_I = Eigen::Matrix3f::Identity();
Eigen::Matrix3f M_N;
M_N << 0, -axis[2], axis[1],
axis[2], 0, -axis[0],
-axis[1], axis[0], 0;
auto radian = (float)(angle/180.0*MY_PI);
M_temp_rodrigues << cos(radian)*M_I+(1-cos(radian))*axis*axis.transpose()+sin(radian)*M_N;
M_rodrigues << M_temp_rodrigues(0,0), M_temp_rodrigues(0,1), M_temp_rodrigues(0,2), 0,
M_temp_rodrigues(1,0), M_temp_rodrigues(1,1), M_temp_rodrigues(1,2), 0,
M_temp_rodrigues(2,0), M_temp_rodrigues(2,1), M_temp_rodrigues(2,2), 0,
0, 0, 0, 1;
return M_rodrigues;
}
Reference
[1] Fundamentals of Computer Graphics 4th
[2] GAMES101 Lingqi Yan