Model 模型变换
缩放变换
S ( s x , s y ) = [ s x 0 0 0 s y 0 0 0 1 ] S(s_x, s_y)=\begin{bmatrix}
s_x & 0 & 0 \\
0 & s_y & 0 \\
0 & 0 & 1
\end{bmatrix}
S ( s x , s y ) = ⎣ ⎡ s x 0 0 0 s y 0 0 0 1 ⎦ ⎤
S ( s x , s y , s z ) = [ s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ] S(s_x, s_y, s_z)=\begin{bmatrix}
s_x & 0 & 0 & 0\\
0 & s_y & 0 & 0\\
0 & 0 & s_z & 0\\
0 & 0 & 0 & 1
\end{bmatrix}
S ( s x , s y , s z ) = ⎣ ⎢ ⎢ ⎡ s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ⎦ ⎥ ⎥ ⎤
反射变换
R x = [ 1 0 0 0 − 1 0 0 0 1 ] R_x=\begin{bmatrix}
1 & 0 & 0 \\
0 & -1 & 0 \\
0 & 0 & 1
\end{bmatrix}
R x = ⎣ ⎡ 1 0 0 0 − 1 0 0 0 1 ⎦ ⎤
R y = [ − 1 0 0 0 1 0 0 0 1 ] R_y=\begin{bmatrix}
-1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{bmatrix}
R y = ⎣ ⎡ − 1 0 0 0 1 0 0 0 1 ⎦ ⎤
错切变换
H ( h x , h y ) = [ 1 h x 0 h y 1 0 0 0 1 ] H(h_x, h_y)=\begin{bmatrix}
1 & h_x & 0 \\
h_y & 1 & 0 \\
0 & 0 & 1
\end{bmatrix}
H ( h x , h y ) = ⎣ ⎡ 1 h y 0 h x 1 0 0 0 1 ⎦ ⎤
旋转变换
二维空间中绕原点的旋转矩阵公式
R ( α ) = [ c o s ( α ) − s i n ( α ) 0 s i n ( α ) c o s ( α ) 0 0 0 1 ] R(\alpha)=\begin{bmatrix}
cos(\alpha) & -sin(\alpha) & 0 \\
sin(\alpha) & cos(\alpha) & 0 \\
0 & 0 & 1
\end{bmatrix}
R ( α ) = ⎣ ⎡ c o s ( α ) s i n ( α ) 0 − s i n ( α ) c o s ( α ) 0 0 0 1 ⎦ ⎤
三维空间中绕 x 轴的旋转矩阵公式
R x ( α ) = [ 1 0 0 0 0 c o s ( α ) − s i n ( α ) 0 0 s i n ( α ) c o s ( α ) 0 0 0 0 1 ] R_x(\alpha)=\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & cos(\alpha) & -sin(\alpha) & 0 \\
0 & sin(\alpha) & cos(\alpha) & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
R x ( α ) = ⎣ ⎢ ⎢ ⎡ 1 0 0 0 0 c o s ( α ) s i n ( α ) 0 0 − s i n ( α ) c o s ( α ) 0 0 0 0 1 ⎦ ⎥ ⎥ ⎤
三维空间中绕 y 轴的旋转矩阵公式
R y ( α ) = [ c o s ( α ) 0 s i n ( α ) 0 0 1 0 0 − s i n ( α ) 0 c o s ( α ) 0 0 0 0 1 ] R_y(\alpha)=\begin{bmatrix}
cos(\alpha) & 0 & sin(\alpha) & 0 \\
0 & 1 & 0 & 0 \\
-sin(\alpha) & 0 & cos(\alpha) & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
R y ( α ) = ⎣ ⎢ ⎢ ⎡ c o s ( α ) 0 − s i n ( α ) 0 0 1 0 0 s i n ( α ) 0 c o s ( α ) 0 0 0 0 1 ⎦ ⎥ ⎥ ⎤
三维空间中绕 z 轴的旋转矩阵公式
R z ( α ) = [ c o s ( α ) − s i n ( α ) 0 0 s i n ( α ) c o s ( α ) 0 0 0 0 1 0 0 0 0 1 ] R_z(\alpha)=\begin{bmatrix}
cos(\alpha) & -sin(\alpha) & 0 & 0 \\
sin(\alpha) & cos(\alpha) & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
R z ( α ) = ⎣ ⎢ ⎢ ⎡ c o s ( α ) s i n ( α ) 0 0 − s i n ( α ) c o s ( α ) 0 0 0 0 1 0 0 0 0 1 ⎦ ⎥ ⎥ ⎤
平移变换
T ( t x , t y ) = [ 1 0 t x 0 1 t y 0 0 1 ] T(t_x, t_y)=\begin{bmatrix}
1 & 0 & t_x \\
0 & 1 & t_y \\
0 & 0 & 1
\end{bmatrix}
T ( t x , t y ) = ⎣ ⎡ 1 0 0 0 1 0 t x t y 1 ⎦ ⎤
二维空间中绕任意点的旋转矩阵公式
R ( α , p ⃗ ) = T ( p ⃗ ) R ( α ) T ( − p ⃗ ) R(\alpha, \vec p)=T(\vec p) R(\alpha) T(-\vec p)
R ( α , p ) = T ( p ) R ( α ) T ( − p )
T ( p ⃗ ) T(\vec p) T ( p ) 为将点p ⃗ \vec p p 平移回去的平移矩阵
R ( α ) R(\alpha) R ( α ) 为绕原点的旋转矩阵
T ( − p ⃗ ) T(-\vec p) T ( − p ) 为将点p ⃗ \vec p p 平移到原点的平移矩阵
公式展开如下:
R ( α , p ⃗ ) = [ 1 0 p x 0 1 p y 0 0 1 ] [ c o s ( α ) − s i n ( α ) 0 s i n ( α ) c o s ( α ) 0 0 0 1 ] [ 1 0 − p x 0 1 − p y 0 0 1 ] = [ c o s ( α ) − s i n ( α ) p x ( 1 − c o s ( α ) ) + p y s i n ( α ) s i n ( α ) c o s ( α ) p y ( 1 − c o s ( α ) ) − p x s i n ( α ) 0 0 1 ] R(\alpha, \vec p)
=
\begin{bmatrix}
1 & 0 & p_x \\
0 & 1 & p_y \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
cos(\alpha) & -sin(\alpha) & 0 \\
sin(\alpha) & cos(\alpha) & 0 \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
1 & 0 & -p_x \\
0 & 1 & -p_y \\
0 & 0 & 1
\end{bmatrix}
=
\begin{bmatrix}
cos(\alpha) & -sin(\alpha) & p_x(1-cos(\alpha))+p_y sin(\alpha) \\
sin(\alpha) & cos(\alpha) & p_y(1-cos(\alpha))-p_x sin(\alpha) \\
0 & 0 & 1
\end{bmatrix}
R ( α , p ) = ⎣ ⎡ 1 0 0 0 1 0 p x p y 1 ⎦ ⎤ ⎣ ⎡ c o s ( α ) s i n ( α ) 0 − s i n ( α ) c o s ( α ) 0 0 0 1 ⎦ ⎤ ⎣ ⎡ 1 0 0 0 1 0 − p x − p y 1 ⎦ ⎤ = ⎣ ⎡ c o s ( α ) s i n ( α ) 0 − s i n ( α ) c o s ( α ) 0 p x ( 1 − c o s ( α ) ) + p y s i n ( α ) p y ( 1 − c o s ( α ) ) − p x s i n ( α ) 1 ⎦ ⎤
例如一个点( x , y ) (x,y) ( x , y ) 绕点( p x , p y ) (p_x,p_y) ( p x , p y ) 逆时针旋转α \alpha α 角度后的位置为
[ x ′ y ′ 1 ] = [ c o s ( α ) − s i n ( α ) p x ( 1 − c o s ( α ) ) + p y s i n ( α ) s i n ( α ) c o s ( α ) p y ( 1 − c o s ( α ) ) − p x s i n ( α ) 0 0 1 ] [ x y 1 ] = [ ( x − p x ) c o s ( α ) − ( y − p y ) s i n ( α ) + p x ( x − p x ) s i n ( α ) + ( y − p y ) c o s ( α ) + p y 1 ] \begin{bmatrix}
x' \\
y' \\
1
\end{bmatrix} =
\begin{bmatrix}
cos(\alpha) & -sin(\alpha) & p_x(1-cos(\alpha))+p_y sin(\alpha) \\
sin(\alpha) & cos(\alpha) & p_y(1-cos(\alpha))-p_x sin(\alpha) \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
x \\
y \\
1
\end{bmatrix}
=
\begin{bmatrix}
(x-p_x) cos(\alpha) - (y-p_y) sin(\alpha) + p_x \\
(x-p_x) sin(\alpha) + (y-p_y) cos(\alpha) + p_y \\
1
\end{bmatrix}
⎣ ⎡ x ′ y ′ 1 ⎦ ⎤ = ⎣ ⎡ c o s ( α ) s i n ( α ) 0 − s i n ( α ) c o s ( α ) 0 p x ( 1 − c o s ( α ) ) + p y s i n ( α ) p y ( 1 − c o s ( α ) ) − p x s i n ( α ) 1 ⎦ ⎤ ⎣ ⎡ x y 1 ⎦ ⎤ = ⎣ ⎡ ( x − p x ) c o s ( α ) − ( y − p y ) s i n ( α ) + p x ( x − p x ) s i n ( α ) + ( y − p y ) c o s ( α ) + p y 1 ⎦ ⎤
三维空间中绕任意向量的旋转矩阵公式
罗德里格斯旋转公式(Rodrigues’ rotation formula)
矩阵形式
R ( n , α ) = c o s ( α ) I + ( 1 − c o s ( α ) ) n ⋅ n T + s i n ( α ) [ 0 − n z n y n z 0 − n x − n y n x 0 ] R(\mathbf n, \alpha)=cos(\alpha) I + (1-cos(\alpha)) \mathbf n \cdot \mathbf n ^ T + sin(\alpha) \begin{bmatrix}
0 & -n_z & n_y \\
n_z & 0 & -n_x\\
-n_y & n_x & 0
\end{bmatrix}
R ( n , α ) = c o s ( α ) I + ( 1 − c o s ( α ) ) n ⋅ n T + s i n ( α ) ⎣ ⎡ 0 n z − n y − n z 0 n x n y − n x 0 ⎦ ⎤
其中:
n \mathbf n n 为旋转轴的单位向量
α \alpha α 为旋转角度
I I I 为单位矩阵
n ⋅ n T \mathbf n \cdot \mathbf n ^ T n ⋅ n T 为向量n \mathbf n n 的外积矩阵
反对称矩阵[ n ] × = [ 0 − n z n y n z 0 − n x − n y n x 0 ] [\mathbf n]_{\times}=\begin{bmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x\\ -n_y & n_x & 0 \end{bmatrix} [ n ] × = ⎣ ⎡ 0 n z − n y − n z 0 n x n y − n x 0 ⎦ ⎤ 为向量n \mathbf n n 的叉乘矩阵
向量形式
v ′ = R ( n , α ) v = v c o s ( α ) + ( 1 − c o s ( α ) ) ( n n T ) v + s i n ( α ) [ n ] × v = v c o s ( α ) + ( 1 − c o s ( α ) ) ( n ⋅ v ) n + s i n ( α ) ( n × v ) \mathbf{v'}=R(\mathbf n, \alpha) \mathbf v \\=
\mathbf v cos(\alpha) + (1-cos(\alpha)) (\mathbf n \mathbf n^T) \mathbf v + sin(\alpha) [\mathbf n]_{\times} \mathbf v \\=
\mathbf v cos(\alpha) + (1-cos(\alpha)) (\mathbf n \cdot \mathbf v) \mathbf n + sin(\alpha) (\mathbf n \times \mathbf v)
v ′ = R ( n , α ) v = v c o s ( α ) + ( 1 − c o s ( α ) ) ( n n T ) v + s i n ( α ) [ n ] × v = v c o s ( α ) + ( 1 − c o s ( α ) ) ( n ⋅ v ) n + s i n ( α ) ( n × v )
其中:
v \mathbf v v 为待旋转的向量
v ′ \mathbf v' v ′ 为旋转后的向量
n \mathbf n n 为旋转轴的单位向量
α \alpha α 为旋转角度
[ n ] × [\mathbf n]_{\times} [ n ] × 为向量n \mathbf n n 的叉乘矩阵,有[ n ] × v = n × v [\mathbf n]_{\times} \mathbf v = \mathbf n \times \mathbf v [ n ] × v = n × v
( n n T ) v = n ( n T ⋅ v ) = ( n ⋅ v ) n (\mathbf n \mathbf n^T) \mathbf v = \mathbf n (\mathbf {n^T} \cdot \mathbf v) = (\mathbf n \cdot \mathbf v) \mathbf n ( n n T ) v = n ( n T ⋅ v ) = ( n ⋅ v ) n
推导过程
设旋转轴为单位向量n \mathbf n n ,待旋转的向量为v \mathbf v v ,旋转后的向量为v ′ \mathbf v' v ′
将v \mathbf v v 分解为平行于n \mathbf n n 的分量v ∥ \mathbf{v_{\parallel}} v ∥ 和垂直于n \mathbf n n 的分量v ⊥ \mathbf{v_{\perp}} v ⊥
v = v ∥ + v ⊥ \mathbf v = \mathbf{v_{\parallel}} + \mathbf{v_{\perp}}
v = v ∥ + v ⊥
其中
v ∥ = ( n ⋅ v ) n \mathbf{v_{\parallel}} = (\mathbf n \cdot \mathbf v) \mathbf n
v ∥ = ( n ⋅ v ) n
v ⊥ = v − v ∥ = v − ( n ⋅ v ) n \mathbf{v_{\perp}} = \mathbf v - \mathbf{v_{\parallel}} = \mathbf v - (\mathbf n \cdot \mathbf v) \mathbf n
v ⊥ = v − v ∥ = v − ( n ⋅ v ) n
旋转后,v ∥ \mathbf{v_{\parallel}} v ∥ 不变,v ⊥ \mathbf{v_{\perp}} v ⊥ 绕n \mathbf n n 旋转α \alpha α 角度
设v ⊥ \mathbf{v_{\perp}} v ⊥ 在旋转前的垂直分量为v ⊥ 1 \mathbf{v_{\perp 1}} v ⊥ 1 ,旋转后的垂直分量为v ⊥ 2 \mathbf{v_{\perp 2}} v ⊥ 2 ,则有
v ⊥ 2 = v ⊥ c o s ( α ) + ( n × v ⊥ ) s i n ( α ) \mathbf{v_{\perp 2}} = \mathbf{v_{\perp}} cos(\alpha) + (\mathbf n \times \mathbf{v_{\perp}}) sin(\alpha)
v ⊥ 2 = v ⊥ c o s ( α ) + ( n × v ⊥ ) s i n ( α )
其中n × v ⊥ \mathbf n \times \mathbf{v_{\perp}} n × v ⊥ 为v ⊥ \mathbf{v_{\perp}} v ⊥ 绕n \mathbf n n 旋转 90 度后的向量
故
v ′ = v ∥ + v ⊥ 2 = ( n ⋅ v ) n + ( v − ( n ⋅ v ) n ) c o s ( α ) + ( n × ( v − ( n ⋅ n ) n ) ) s i n ( α ) = ( n ⋅ v ) n + v c o s ( α ) − ( n ⋅ v ) n c o s ( α ) + ( n × v ) s i n ( α ) = v c o s ( α ) + ( 1 − c o s ( α ) ) ( n ⋅ v ) n + s i n ( α ) ( n × v ) \mathbf v' = \mathbf{v_{\parallel}} + \mathbf{v_{\perp 2}} \\
= (\mathbf n \cdot \mathbf v) \mathbf n + (\mathbf v - (\mathbf n \cdot \mathbf v) \mathbf n) cos(\alpha) + (\mathbf n \times (\mathbf v - (\mathbf n \cdot \mathbf n) \mathbf n)) sin(\alpha) \\
= (\mathbf n \cdot \mathbf v) \mathbf n + \mathbf v cos(\alpha) - (\mathbf n \cdot \mathbf v) \mathbf n cos(\alpha) + (\mathbf n \times \mathbf v) sin(\alpha) \\
= \mathbf v cos(\alpha) + (1-cos(\alpha)) (\mathbf n \cdot \mathbf v) \mathbf n + sin(\alpha) (\mathbf n \times \mathbf v)
v ′ = v ∥ + v ⊥ 2 = ( n ⋅ v ) n + ( v − ( n ⋅ v ) n ) c o s ( α ) + ( n × ( v − ( n ⋅ n ) n ) ) s i n ( α ) = ( n ⋅ v ) n + v c o s ( α ) − ( n ⋅ v ) n c o s ( α ) + ( n × v ) s i n ( α ) = v c o s ( α ) + ( 1 − c o s ( α ) ) ( n ⋅ v ) n + s i n ( α ) ( n × v )
View 相机变换
相机变换矩阵的推导
一个相机由以下几部分所构成
相机位置 e ⃗ \vec e e
相机视线方向g ⃗ \vec g g
相机的正上方向t ⃗ \vec t t
在相机的参考系中,定义相机视线方向g ⃗ \vec g g 为相机坐标系的 z 轴方向
定义相机的正上方向t ⃗ \vec t t 为相机坐标系的 y 轴方向
定义g ⃗ × t ⃗ \vec g \times \vec t g × t 为相机坐标系的 x 轴方向
通常相机的视线方向为世界坐标系的− z -z − z 轴方向
首先将相机平移到原点,可得到矩阵
T v i e w = [ 1 0 0 − x e 0 1 0 − y e 0 0 1 − z e 0 0 0 1 ] T_{view}=\begin{bmatrix}
1 & 0 & 0 & -x_e\\
0 & 1 & 0 & -y_e\\
0 & 0 & 1 & -z_e\\
0 & 0 & 0 & 1
\end{bmatrix}
T v i e w = ⎣ ⎢ ⎢ ⎡ 1 0 0 0 0 1 0 0 0 0 1 0 − x e − y e − z e 1 ⎦ ⎥ ⎥ ⎤
将g ⃗ \vec g g 旋转到− z -z − z 方向,将t ⃗ \vec t t 旋转到 y 轴方向,将g ⃗ × t ⃗ \vec g \times \vec t g × t 旋转到 x 轴方向,可得到矩阵R v i e w R_{view} R v i e w ,但是这个矩阵并不好求,但我们可以反过来求。
我们可以按照变换后的基底直接求出逆变换的变换矩阵,由于是正交基底构成的矩阵,所以是正交矩阵,所以R v i e w T = R v i e w − 1 R_{view}^T=R^{-1}_{view} R v i e w T = R v i e w − 1
R v i e w − 1 = [ x g ⃗ × t ⃗ x t ⃗ x − g ⃗ 0 y g ⃗ × t ⃗ y t ⃗ y − g ⃗ 0 z g ⃗ × t ⃗ z t ⃗ z − g ⃗ 0 0 0 0 1 ] R^{-1}_{view}=\begin{bmatrix}
x_{\vec g \times \vec t} & x_{\vec t} & x_{\vec {-g}} & 0\\
y_{\vec g \times \vec t} & y_{\vec t} & y_{\vec {-g}} & 0\\
z_{\vec g \times \vec t} & z_{\vec t} & z_{\vec {-g}} & 0\\
0 & 0 & 0 & 1
\end{bmatrix}
R v i e w − 1 = ⎣ ⎢ ⎢ ⎡ x g × t y g × t z g × t 0 x t y t z t 0 x − g y − g z − g 0 0 0 0 1 ⎦ ⎥ ⎥ ⎤
故最终相机变换矩阵得到
M v i e w = R v i e w T v i e w M_{view}=R_{view}T_{view}
M v i e w = R v i e w T v i e w
Projection 投影变换
平行投影变换矩阵推导
假设平行投影摄像机的视线范围由长方体[ l , r ] × [ b , t ] × [ f , n ] [l, r] \times [b,t] \times [f,n] [ l , r ] × [ b , t ] × [ f , n ] 所确定,其中 l,r 为 x 轴方向的两平面位置,b,t 为 y 轴方向的两平面位置,f,n 为 z 轴方向的两平面位置。我们希望将其标准化到[ − 1 , 1 ] 3 [-1,1]^3 [ − 1 , 1 ] 3
首先将其平移到原点,然后再缩放它。
M o r t h o = [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ] [ 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 1 − n + f 2 0 0 0 1 ] = [ 2 r − l 0 0 − r + l r − l 0 2 t − b 0 − t + b t − b 0 0 2 n − f − n + f n − f 0 0 0 1 ] M_{ortho}=
\begin{bmatrix}
\frac{2}{r-l} & 0 & 0 & 0 \\
0 & \frac{2}{t-b} & 0 & 0 \\
0 & 0 & \frac{2}{n-f} & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
1 & 0 & 0 & -\frac{r+l}{2} \\
0 & 1 & 0 & -\frac{t+b}{2} \\
0 & 0 & 1 & -\frac{n+f}{2} \\
0 & 0 & 0 & 1
\end{bmatrix}
=
\begin{bmatrix}
\frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\
0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\
0 & 0 & \frac{2}{n-f} & -\frac{n+f}{n-f} \\
0 & 0 & 0 & 1
\end{bmatrix}
M o r t h o = ⎣ ⎢ ⎢ ⎡ r − l 2 0 0 0 0 t − b 2 0 0 0 0 n − f 2 0 0 0 0 1 ⎦ ⎥ ⎥ ⎤ ⎣ ⎢ ⎢ ⎡ 1 0 0 0 0 1 0 0 0 0 1 0 − 2 r + l − 2 t + b − 2 n + f 1 ⎦ ⎥ ⎥ ⎤ = ⎣ ⎢ ⎢ ⎡ r − l 2 0 0 0 0 t − b 2 0 0 0 0 n − f 2 0 − r − l r + l − t − b t + b − n − f n + f 1 ⎦ ⎥ ⎥ ⎤
透视投影变换矩阵推导
透视投影摄像机的视线范围由一个平头四棱台体所确定,使得内部的物体可以呈现近大远小的效果。
我们可以想象以下直接通过“挤压”将平头四棱台挤压为一个长方体,变换前后 n 平面上的点不变,n~f 平面上的点将被压缩,越接近 f 平面,点被压缩的越厉害,所以当变换到长方体后相同的三维几何体离 f 平面越近投影后的图像就越小,故能够呈现出近大远小的效果。这也是一种空间变换,但它在三维空间中属于一种非线性变换,如果我们希望使用矩阵描述,则需要借助齐次坐标将其放置在四维空间中完成这个变换。
假设这种“挤压”变换可以使用矩阵 A 描述,则最终的透视投影变换矩阵可表述如下:
M p e r s p = M o r t h o ⋅ M p e r s p → o r t h o M_{persp}=M_{ortho} \cdot M_{persp \to ortho}
M p e r s p = M o r t h o ⋅ M p e r s p → o r t h o
矩阵M p e r s p → o r t h o M_{persp \to ortho} M p e r s p → o r t h o 的推导如下:
x ′ = n z x x'=\frac{n}{z}x x ′ = z n x
y ′ = n z y y'=\frac{n}{z}y y ′ = z n y
[ x y z 1 ] ⇒ [ n z x n z y ? 1 ] = [ n x n y ? z ] \begin{bmatrix}
x \\
y \\
z \\
1 \\
\end{bmatrix}
\Rightarrow
\begin{bmatrix}
\frac{n}{z}x \\
\frac{n}{z}y \\
? \\
1 \\
\end{bmatrix}
=
\begin{bmatrix}
nx \\
ny \\
? \\
z \\
\end{bmatrix}
⎣ ⎢ ⎢ ⎡ x y z 1 ⎦ ⎥ ⎥ ⎤ ⇒ ⎣ ⎢ ⎢ ⎡ z n x z n y ? 1 ⎦ ⎥ ⎥ ⎤ = ⎣ ⎢ ⎢ ⎡ n x n y ? z ⎦ ⎥ ⎥ ⎤
由于 n 平面上的任何点在变换前后位置都仍然不变,设未知量?为 k 可得出以下关系:
[ x y n 1 ] = [ n x n y k n ] \begin{bmatrix}
x \\
y \\
n \\
1 \\
\end{bmatrix}
=
\begin{bmatrix}
nx \\
ny \\
k \\
n \\
\end{bmatrix}
⎣ ⎢ ⎢ ⎡ x y n 1 ⎦ ⎥ ⎥ ⎤ = ⎣ ⎢ ⎢ ⎡ n x n y k n ⎦ ⎥ ⎥ ⎤
解得k = n 2 k=n^2 k = n 2
故矩阵M p e r s p → o r t h o M_{persp \to ortho} M p e r s p → o r t h o 可初步写为如下形式
M p e r s p → o r t h o = [ n 0 0 0 0 n 0 0 0 0 A B 0 0 1 0 ] M_{persp \to ortho}=
\begin{bmatrix}
n & 0 & 0 & 0\\
0 & n & 0 & 0\\
0 & 0 & A & B\\
0 & 0 & 1 & 0
\end{bmatrix}
M p e r s p → o r t h o = ⎣ ⎢ ⎢ ⎡ n 0 0 0 0 n 0 0 0 0 A 1 0 0 B 0 ⎦ ⎥ ⎥ ⎤
由于 f 平面和 z 轴的交点在变换前后都不变,故得出以下关系:
[ 0 0 f 1 ] = [ 0 0 f 2 f ] \begin{bmatrix}
0 \\
0 \\
f \\
1 \\
\end{bmatrix}
=
\begin{bmatrix}
0 \\
0 \\
f^2 \\
f \\
\end{bmatrix}
⎣ ⎢ ⎢ ⎡ 0 0 f 1 ⎦ ⎥ ⎥ ⎤ = ⎣ ⎢ ⎢ ⎡ 0 0 f 2 f ⎦ ⎥ ⎥ ⎤
由这两个特殊点可列出关于 A,B 未知数的二元一次方程组
{ A n + B = n 2 A f + B = f 2 \left\{\begin{matrix}
An+B=n^2 \\
Af+B=f^2
\end{matrix}\right.
{ A n + B = n 2 A f + B = f 2
解得
{ A = n + f B = − n f \left\{\begin{matrix}
A=n+f \\
B=-nf
\end{matrix}\right.
{ A = n + f B = − n f
故得到矩阵
M p e r s p → o r t h o = [ n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ] M_{persp \to ortho}=
\begin{bmatrix}
n & 0 & 0 & 0\\
0 & n & 0 & 0\\
0 & 0 & n+f & -nf\\
0 & 0 & 1 & 0
\end{bmatrix}
M p e r s p → o r t h o = ⎣ ⎢ ⎢ ⎡ n 0 0 0 0 n 0 0 0 0 n + f 1 0 0 − n f 0 ⎦ ⎥ ⎥ ⎤
最终投影矩阵为:
M p e r s p = M o r t h o ⋅ M p e r s p → o r t h o = [ 2 n r − l 0 l + r l − r 0 0 2 n t − b b + t b − t 0 0 0 n + f n − f 2 n f f − n 0 0 1 0 ] M_{persp}= M_{ortho} \cdot M_{persp \to ortho} =
\begin{bmatrix}
\frac{2n}{r-l} & 0 & \frac{l+r}{l-r} & 0 \\
0 & \frac{2n}{t-b} & \frac{b+t}{b-t} & 0 \\
0 & 0 & \frac{n+f}{n-f} & \frac{2nf}{f-n} \\
0 & 0 & 1 & 0
\end{bmatrix}
M p e r s p = M o r t h o ⋅ M p e r s p → o r t h o = ⎣ ⎢ ⎢ ⎡ r − l 2 n 0 0 0 0 t − b 2 n 0 0 l − r l + r b − t b + t n − f n + f 1 0 0 f − n 2 n f 0 ⎦ ⎥ ⎥ ⎤
z 坐标变换深入思考
当我们从透视投影的平头四棱台空间压缩变换到平行投影的长方体后,对于内部的任意一点( x , y , z ) (x,y,z) ( x , y , z ) 坐标,变换后对应的坐标为( x ′ , y ′ , z ′ ) (x',y',z') ( x ′ , y ′ , z ′ ) ,显然是可以得到z z z 越远的点,( x ′ , y ′ ) (x',y') ( x ′ , y ′ ) 坐标被压缩的越厉害,关系式可在上述推导中体现。但是内部任意一个点的 z 坐标在变换前后就没有那么直观,我们可以进一步做一系列推导。
[ x ′ y ′ z ′ 1 ] = [ n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ] [ x y z 1 ] = [ n x n y ( n + f ) z − n f z ] = [ n x z n y z ( n + f ) − n f z 1 ] \begin{bmatrix}
x' \\
y' \\
z' \\
1
\end{bmatrix}
=
\begin{bmatrix}
n & 0 & 0 & 0\\
0 & n & 0 & 0\\
0 & 0 & n+f & -nf\\
0 & 0 & 1 & 0
\end{bmatrix}
\begin{bmatrix}
x \\
y \\
z \\
1
\end{bmatrix}
=
\begin{bmatrix}
nx \\
ny \\
(n+f)z-nf \\
z
\end{bmatrix}
=
\begin{bmatrix}
n\frac{x}{z} \\
n\frac{y}{z} \\
(n+f)-\frac{nf}{z} \\
1
\end{bmatrix}
⎣ ⎢ ⎢ ⎡ x ′ y ′ z ′ 1 ⎦ ⎥ ⎥ ⎤ = ⎣ ⎢ ⎢ ⎡ n 0 0 0 0 n 0 0 0 0 n + f 1 0 0 − n f 0 ⎦ ⎥ ⎥ ⎤ ⎣ ⎢ ⎢ ⎡ x y z 1 ⎦ ⎥ ⎥ ⎤ = ⎣ ⎢ ⎢ ⎡ n x n y ( n + f ) z − n f z ⎦ ⎥ ⎥ ⎤ = ⎣ ⎢ ⎢ ⎡ n z x n z y ( n + f ) − z n f 1 ⎦ ⎥ ⎥ ⎤
可得到函数z ′ = ( n + f ) − n f z z'=(n+f)-\frac{nf}{z} z ′ = ( n + f ) − z n f 关于自变量z z z 的函数关系,z z z 的定义域为[ n , f ] [n,f] [ n , f ]
为了得知变换前后的 z 坐标是变远了还是变近了,可以做差得到函数f ( z ) f(z) f ( z )
f ( z ) = z ′ − z = ( n + f ) − ( n f z + z ) , z ∈ [ n , f ] > 0 f(z)=z'-z=(n+f)-(\frac{nf}{z}+z), z \in [n,f] > 0
f ( z ) = z ′ − z = ( n + f ) − ( z n f + z ) , z ∈ [ n , f ] > 0
令f ( z ) = 0 f(z)=0 f ( z ) = 0 ,则得到方程z 2 − ( n + f ) + n f = 0 z^2-(n+f)+nf=0 z 2 − ( n + f ) + n f = 0 ,即( z − n ) ( z − f ) = 0 (z-n)(z-f)=0 ( z − n ) ( z − f ) = 0 ,得到方程有两个零点
x 1 = n , x 2 = f x_1=n, x_2=f
x 1 = n , x 2 = f
函数f ( z ) f(z) f ( z ) 求导得f ′ ( z ) = n f z 2 − 1 f'(z)=\frac{nf}{z^2}-1 f ′ ( z ) = z 2 n f − 1
令f ′ ( z ) > 0 f'(z)>0 f ′ ( z ) > 0 得,n < z < n f n<z<\sqrt{nf} n < z < n f ,令f ′ ( z ) < 0 f'(z)<0 f ′ ( z ) < 0 得,n f < z < f \sqrt{nf}<z<f n f < z < f
得出以下函数及导函数分布表
z
n n n
( n , n f ) (n,\sqrt{nf}) ( n , n f )
n f \sqrt{nf} n f
( n f , f ) (\sqrt{nf},f) ( n f , f )
f f f
f’(z)
-
>0
0
<0
-
f(z)
0
增函数
-
减函数
0
故f ( z ) > = 0 f(z)>=0 f ( z ) > = 0 恒成立(当z = n o r z = f z=n \space or \space z=f z = n o r z = f 时,等号成立)
故对于透视投影空间内的某一点被压缩后,z ′ > z z'>z z ′ > z ,z 坐标变远。
实际应用的透视投影矩阵
实际使用中。近平面的 l, r, b, t 是如何确定的呢?通常人们使用field of view (视场角 fovY)和aspect ratio (宽高比)来计算得到。
假设近平面到相机的距离为 n,垂直角度为 fovY,假设相机的(x, y)坐标处于近平面的中心点,则有l = − r , b = − t l=-r, b=-t l = − r , b = − t ,则根据如图的推导,可得到:
t a n ( f o v Y 2 ) = t ∣ n ∣ a s p e c t R a t i o = r − l t − b = 2 r 2 t = r t tan(\frac{fovY}{2}) = \frac{t}{|n|} \\
aspectRatio = \frac{r-l}{t-b} = \frac{2r}{2t} = \frac{r}{t}
t a n ( 2 f o v Y ) = ∣ n ∣ t a s p e c t R a t i o = t − b r − l = 2 t 2 r = t r
现在可以确定出:
{ t = ∣ n ∣ ⋅ tan ( fovY 2 ) b = − t r = t ⋅ aspectRatio l = − r \left\{
\begin{aligned}
t &= |n| \cdot \tan\left(\frac{\text{fovY}}{2}\right) \\
b &= -t \\
r &= t \cdot \text{aspectRatio} \\
l &= -r
\end{aligned}
\right.
⎩ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎧ t b r l = ∣ n ∣ ⋅ tan ( 2 fovY ) = − t = t ⋅ aspectRatio = − r