本节课程视频地址:https://www.bilibili.com/video/BV1X7411F744/?p=4
补充上一节课的一个内容,旋转矩阵的逆矩阵是它的转置,也就是说有 R − θ = R θ − 1 = R θ T R_{-\theta} = R_\theta^{-1}=R_\theta^T R−θ=Rθ−1=RθT
上节课讲了,二维变换中的绕原点的旋转、缩放、切变,以及齐次坐标,还有通过简单变换组合成复杂变换。
这节课先讲三维变换,然后讲困难且重要的观测变换(Viewing Transformation)
文章目录
- 三维变换(3D Transformation)
- 缩放
- 平移
- 旋转
- Rodrigues 旋转公式
- 观测变换 (Viewing transformation)
- 视图变换 (View transformation)
- 投影变换(Perspective Projection)
- 正交投影
- 透视投影
三维变换(3D Transformation)
三维的齐次坐标:
- 点: ( x , y , z , 1 ) T (x,y,z,1)^T (x,y,z,1)T
- 向量: ( x , y , z , 0 ) T (x,y,z,0)^T (x,y,z,0)T
注:(x,y,z,w)其中w!=0 表示的是点(x/w,y/w,z/w)
齐次坐标使用4维矩阵来表示仿射变换:
[
x
′
y
′
z
′
1
]
=
[
a
b
c
t
x
d
e
f
t
y
g
h
i
t
z
0
0
0
1
]
⋅
[
x
y
z
1
]
\begin{bmatrix} x'\\ y' \\ z' \\ 1 \end{bmatrix}= \begin{bmatrix} a&b&c&t_x\\ d&e&f&t_y\\ g&h&i&t_z \\ 0&0&0&1 \end{bmatrix} \cdot \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix}
x′y′z′1
=
adg0beh0cfi0txtytz1
⋅
xyz1
注:仿射变换中是先线性变换(也就是绕原点所作的变换)再平移变换。
缩放
[ x ′ y ′ z ′ 1 ] = [ s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ] ⋅ [ x y z 1 ] \begin{bmatrix} x'\\ y' \\ z' \\ 1 \end{bmatrix}= \begin{bmatrix} s_x&0&0&0\\ 0&s_y&0&0\\ 0&0&s_z&0\\ 0&0&0&1 \end{bmatrix} \cdot \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} x′y′z′1 = sx0000sy0000sz00001 ⋅ xyz1
平移
[ x ′ y ′ z ′ 1 ] = [ 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ] ⋅ [ x y z 1 ] \begin{bmatrix} x'\\ y' \\ z' \\ 1 \end{bmatrix}= \begin{bmatrix} 1&0&0&t_x\\ 0&1&0&t_y\\ 0&0&1&t_z\\ 0&0&0&1 \end{bmatrix} \cdot \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} x′y′z′1 = 100001000010txtytz1 ⋅ xyz1
旋转
三维的旋转分为绕x轴旋转、绕y轴旋转和绕z轴旋转。
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}\\
Rx(α)=
10000cosαsinα00−sinαcosα00001
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}
Ry(α)=
cosα0−sinα00100sinα0cosα00001
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}
Rz(α)=
cosα−sinα00−sinαcosα0000100001
注意旋转矩阵 R y ( α ) R_y(\alpha) Ry(α)的 s i n α sin\alpha sinα的正负号是和另外两个相反的。其实没有反,因为这是一个右手系的坐标轴,绕x轴逆时针旋转的方向是在y0z平面中y轴旋转到z轴的方向,绕z轴旋转的方向是在x0y平面中x轴旋转到y轴的方向,而绕y轴旋转的方向在z0x平面中是从z轴旋转到x轴的方向。以x0y平面的旋转为例: x ′ = x c o s α − y s i n α x' = xcos\alpha - ysin\alpha x′=xcosα−ysinα,即要得到 x ′ x' x′需要乘上y轴原始坐标的 − s i n α -sin\alpha −sinα。所以在z0x平面内,要得到z轴所在坐标: z ′ = z c o s α − x s i n α z' = zcos\alpha - xsin\alpha z′=zcosα−xsinα。清晰的记忆方法,以绕x轴旋转为例,绕x轴旋转在y0z平面内是从y轴到z轴的方向, y ′ = y cos α − z sin α y' = y\cos\alpha - z\sin\alpha y′=ycosα−zsinα即转离y轴的方向就减,$z’ = z\cos\alpha + y\sin\alpha $ 即朝z轴转的方向就加。
Rodrigues 旋转公式
绕旋转轴 n ⃗ \vec{n} n 旋转角度 α \alpha α:
形式一:
R
(
n
⃗
,
α
)
=
c
o
s
(
α
)
I
+
(
1
−
c
o
s
(
α
)
)
n
⃗
⋅
n
⃗
T
+
sin
α
⋅
[
0
−
n
z
n
y
n
z
0
−
n
x
−
n
y
n
x
0
]
R(\vec{n},\alpha)=cos(\alpha) I + (1-cos(\alpha)) \vec{n}\cdot \vec{n}^T + \sin\alpha\cdot \begin{bmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \\ \end{bmatrix}
R(n,α)=cos(α)I+(1−cos(α))n⋅nT+sinα⋅
0nz−ny−nz0nxny−nx0
形式二:
R
(
n
⃗
,
α
)
=
I
+
sin
α
⋅
[
0
−
n
z
n
y
n
z
0
−
n
x
−
n
y
n
x
0
]
+
(
1
−
c
o
s
(
α
)
)
⋅
[
0
−
n
z
n
y
n
z
0
−
n
x
−
n
y
n
x
0
]
2
R(\vec{n},\alpha)= I + \sin\alpha\cdot \begin{bmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \\ \end{bmatrix} + (1-cos(\alpha))\cdot{\begin{bmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \\ \end{bmatrix}}^2
R(n,α)=I+sinα⋅
0nz−ny−nz0nxny−nx0
+(1−cos(α))⋅
0nz−ny−nz0nxny−nx0
2
证明:
https://www.cnblogs.com/wtyuan/p/12324495.html
观测变换 (Viewing transformation)
视图变换 (View transformation)
什么是视图变换
想象一下拍照:
- 首先要找一个好的背景,把人的位置和人与背景的相对位置安排好(模型变换);
- 然后要找一个好的角度(视图变换);
- 最后按快门(投影变换)。
定义相机:
- 位置向量 Postion: e ⃗ \vec{e} e
- 朝向 Look-at direction: g ⃗ \vec{g} g
- 相机向上的方向 Up direction (垂直于朝向) : t ⃗ \vec{t} t
约定:相机永远放在原点,相机永远以+y为向上方向,相机永远朝-z方向看。 也就是进行视图变换时要将所有对象和相机一起做变换,直到相机在原点,朝向-z,以+y为正方向。
如何将相机从它原来的位置移到约定位置
- 平移 e ⃗ \vec{e} e到原点;
- 旋转 g ⃗ \vec{g} g 到 -z 方向;
- 旋转 t ⃗ \vec{t} t 到 +y 方向
- 旋转 g ⃗ × t ⃗ \vec{g} \times \vec{t} g×t 到 +x 方向
如何求出将相机旋转到约定位置的旋转矩阵?
先平移到原点:
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}
Tview=
100001000010−xe−ye−ze1
再考虑它的逆旋转,找到三个特殊向量的旋转,即 x ^ \hat{x} x^ 到 g ^ × t ^ \hat{g} \times \hat{t} g^×t^, y ^ \hat{y} y^ 到 t ^ \hat {t} t^, z ^ \hat{z} z^ 到 − g ^ -\hat{g} −g^,就能找到这个逆旋转的旋转矩阵:
R
r
e
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_{review}^{-1} = \begin{bmatrix} x_{\hat{g}\times\hat{t}} & x_{\hat{t}} & x_{-\hat{g}} & 0\\ y_{\hat{g}\times\hat{t}} & y_{\hat{t}} & y_{-\hat{g}} & 0\\ z_{\hat{g}\times\hat{t}} & z_{\hat{t}} & z_{-\hat{g}} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}
Rreview−1=
xg^×t^yg^×t^zg^×t^0xt^yt^zt^0x−g^y−g^z−g^00001
旋转矩阵是正交矩阵,上面这个矩阵显然符合,旋转矩阵的逆矩阵就是它的转置:
R
r
e
v
i
e
w
=
[
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
]
R_{review} = \begin{bmatrix} x_{\hat{g}\times\hat{t}} & y_{\hat{g}\times\hat{t}} & z_{\hat{g}\times\hat{t}} & 0 \\ x_{\hat{t}} & y_{\hat{t}} & z_{\hat{t}} & 0 \\ x_{-\hat{g}} & y_{-\hat{g}} & z_{-\hat{g}} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
Rreview=
xg^×t^xt^x−g^0yg^×t^yt^y−g^0zg^×t^zt^z−g^00001
总结:将所有对象和相机一起做变换,直到相机在原点,朝向-z,以+y为正方向。
这就是视图变换。
投影变换(Perspective Projection)
正交投影(Orthographic projection)
透视投影(Perspective projection)
区别:正交投影没有近大远小而透视投影有。
正交投影
做法一:
假设已经进行了视图变换(即相机在原点,朝向-z,以+y为向上方向)
第一步,把所有点的z坐标变为0;
第二步,将得到的二维平面坐标做平移和缩放,让它们装在 [ − 1 , − 1 ] 2 [-1,-1]^2 [−1,−1]2 这个正方形里。(至于为什么要进行这一步操作,这是一个约定俗成的办法,可以方便之后的操作)
做法二:(正规做法)
实际的计算机图形学操作中,还有一个比简单地把z扔掉更方便的做法:
同样,假设已经进行了视图变换(即相机在原点,朝向-z,以+y为向上方向)
假设此时所有物体装在一个 [ l , r ] × [ b , t ] × [ f , n ] [l, r]\times[b,t] \times [f, n] [l,r]×[b,t]×[f,n] 的长方体内,将这个长方体映射到 [ − 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
]
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}
Mortho=
r−l20000t−b20000n−f200001
100001000010−2r+l−2t+b−2n+f1
透视投影
回顾齐次坐标的一个重要性质:
( x , y , z , 1 ) (x,y,z,1) (x,y,z,1)表示一个点,
( k x , k y , k z , k ! = 0 ) (kx,ky,kz,k!=0) (kx,ky,kz,k!=0)也表示该点,
( x z , y z , z 2 , z ! = 0 ) (xz,yz,z^2,z!=0) (xz,yz,z2,z!=0)也表示该点。
做法:
将一个截头锥体,“挤压”到一个长方体:
如何“挤压”呢?
提前告诉你,这个“挤压”可以用一个矩阵表示,一般叫投影变换矩阵,那么这个矩阵怎么求呢?
观察,该“挤压”的特点:
x坐标和 y坐标很明显有相似关系
y
′
=
n
z
y
,
x
′
=
n
z
x
y' = \frac{n}{z}y,\ \ \ x' = \frac{n}{z}x
y′=zny, x′=znx
z坐标怎么变目前还不知道,用齐次坐标表示:
[
x
y
z
1
]
→
[
n
x
/
z
n
y
/
z
u
n
k
n
o
w
n
1
]
=
=
[
n
x
n
y
u
n
k
n
o
w
n
z
]
\begin{bmatrix} x\\y\\z\\1 \end{bmatrix}\rightarrow \begin{bmatrix} nx/z\\ny/z\\unknown\\1 \end{bmatrix} == \begin{bmatrix} nx\\ny\\unknown\\z \end{bmatrix}
xyz1
→
nx/zny/zunknown1
==
nxnyunknownz
这样已经可以得到这个变换矩阵的一大部分了:
M
p
e
r
s
p
→
o
r
t
h
o
=
[
n
0
0
0
0
n
0
0
?
?
?
?
0
0
n
0
]
M_{persp\rightarrow ortho} = \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ ? & ? & ? & ?\\ 0 & 0 & n & 0 \end{bmatrix}
Mpersp→ortho=
n0?00n?000?n00?0
那么该矩阵的第三行怎么求?
利用两点:
-
近平面上的点不会发生改变
[ x y n 1 ] → [ x y n 1 ] = = [ n x n y n 2 n ] \begin{bmatrix} x\\y\\n\\1 \end{bmatrix} \rightarrow \begin{bmatrix} x\\y\\n\\1 \end{bmatrix} == \begin{bmatrix} nx\\ ny\\ n^2\\ n \end{bmatrix} xyn1 → xyn1 == nxnyn2n
因为 n 2 n^2 n2与 x x x无关,所以第三行的第一个和第二个元素是0,也就是说对于透视投影矩阵的第三行有:
[ 0 0 A B ] [ x y n 1 ] = n 2 \begin{bmatrix} 0&0&A&B \end{bmatrix} \begin{bmatrix} x\\y\\n\\1 \end{bmatrix}=n^2 [00AB] xyn1 =n2 -
远平面上与z轴相交的点不会改变
[ 0 0 f 1 ] → [ 0 0 f 1 ] = = [ 0 0 f 2 f ] \begin{bmatrix} 0\\0\\f\\1 \end{bmatrix}\rightarrow \begin{bmatrix} 0\\0\\f\\1 \end{bmatrix}== \begin{bmatrix} 0\\0\\f^2\\f \end{bmatrix} 00f1 → 00f1 == 00f2f
也就是:
[ 0 0 A B ] [ 0 0 f 2 f ] = f 2 \begin{bmatrix} 0 & 0 & A & B \end{bmatrix} \begin{bmatrix} 0\\0\\f^2\\f \end{bmatrix} = f^2 [00AB] 00f2f =f2
可以建立方程组求解A和B了:
A
n
+
B
=
n
2
A
f
+
B
=
f
2
An+B=n^2\\ Af+B=f^2
An+B=n2Af+B=f2
解得
A
=
n
+
f
,
B
=
−
n
f
A = n+f,\ \ \ B= -nf
A=n+f, B=−nf
得到该矩阵为:
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
n
0
]
M_{persp\rightarrow ortho} = \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & n & 0 \end{bmatrix}
Mpersp→ortho=
n0000n0000n+fn00−nf0
最后
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}M_{persp\rightarrow ortho}
Mpersp=MorthoMpersp→ortho
问题:对于截头锥体中间的点,它的z坐标怎么变?
[ n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 n 0 ] [ x y z 1 ] = [ n x n y n z + f z − n f z ] \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & n & 0 \end{bmatrix} \begin{bmatrix} x\\y\\z\\1 \end{bmatrix}= \begin{bmatrix} nx\\ny\\nz+fz-nf\\z \end{bmatrix} n0000n0000n+fn00−nf0 xyz1 = nxnynz+fz−nfz
记
f
(
z
)
=
n
z
+
f
z
−
n
f
z
−
z
=
1
z
[
−
z
2
+
(
n
+
f
)
z
−
n
f
]
f(z) = \frac{nz+fz-nf}{z}-z = \frac{1}{z}[-z^2+(n+f)z -nf]
f(z)=znz+fz−nf−z=z1[−z2+(n+f)z−nf]
对于中括号中的二次函数,开口向下,且两个零点为z=f和z=n,所以中括号中的二次函数在f<n<z这个区间里大于0,又z<0,所以f(z)小于0,即z的坐标会变小(朝远平面方向变)。