最近在重温计算机图形学的基础知识,期望能做到温故知新,加深对其的理解,以便能从容应对工作中各种情况。
小弟水平有限,若有不正确之处,欢迎大家批评指正。
相关文章链接:
【计算机图形学基础】线性代数基础1
【计算机图形学基础】线性代数基础2
【计算机图形学基础】相机矩阵
【计算机图形学基础】投影矩阵
【计算机图形学基础】光照模型和着色频率
【计算机图形学基础】阴影映射
1 向量
1.1 向量点乘
1.1.1 基本属性
向量点乘会得到一个标量;
a
⃗
\vec{a}
a
⋅
\cdot
⋅
b
⃗
\vec{b}
b = |a| |b|
c
o
s
θ
cos\theta
cosθ
a
⃗
\vec{a}
a
⋅
\cdot
⋅
b
⃗
\vec{b}
b =
(
a
x
a
y
a
z
)
\begin{pmatrix}a_{x}&a_{y}&a_{z}\end{pmatrix}
(axayaz)
(
b
x
b
y
b
z
)
\begin{pmatrix}b_{x}\\b_{y}\\b_{z}\end{pmatrix}
⎝
⎛bxbybz⎠
⎞ =
a
x
b
x
a_{x}b_{x}
axbx +
a
y
b
y
a_{y}b_{y}
ayby +
a
z
b
z
a_{z}b_{z}
azbz
若
a
⃗
\vec{a}
a和
b
⃗
\vec{b}
b是单位向量,有:
a
⃗
\vec{a}
a
⋅
\cdot
⋅
b
⃗
\vec{b}
b =
c
o
s
(
θ
)
cos(\theta)
cos(θ)
1.1.2 几何意义
(1) 求取两个向量的夹角
c
o
s
θ
cos\theta
cosθ = (
a
⃗
\vec{a}
a
⋅
\cdot
⋅
b
⃗
\vec{b}
b)
/
/
/ (
∣
a
∣
∗
∣
b
∣
|a| * |b|
∣a∣∗∣b∣)
(2) 求向量的投影
求取
b
⃗
\vec{b}
b 在
a
⃗
\vec{a}
a 上的投影(或反过来):
b
⃗
⊥
\vec{b}_{\bot}
b⊥ =
b
⃗
\vec{b}
b *
c
o
s
θ
cos\theta
cosθ
(3) 求两个单位向量的接近程度
a
⃗
\vec{a}
a
⋅
\cdot
⋅
b
⃗
\vec{b}
b =
c
o
s
(
θ
)
cos(\theta)
cos(θ)。
若两个向量接近,则点乘结果接近1;
若两个向量较远,则点乘结果接近0;
若两个向量异向,则点乘结果小于0;
若两个向量异向且正好相反,则点乘结果为-1。
(4) 求两个向量的前后关系
求
a
⃗
\vec{a}
a在
b
⃗
\vec{b}
b的前后关系:向量点积的符号由
c
o
s
θ
cos\theta
cosθ决定;
若
c
o
s
θ
>
0
cos\theta > 0
cosθ>0,说明两个向量指向前方;若
c
o
s
θ
<
0
cos\theta < 0
cosθ<0,说明两个向量一前一后。
1.2 向量叉乘
1.2.1 基本属性
向量叉乘会得到一个矢量,其定义为:
a
⃗
\vec{a}
a
⨂
\bigotimes
⨂
b
⃗
\vec{b}
b =
c
⃗
\vec{c}
c;
向量叉乘按照右手法则,会得到第三个向量
c
⃗
\vec{c}
c,
c
⃗
\vec{c}
c 垂直于
a
⃗
\vec{a}
a 和
b
⃗
\vec{b}
b 所在的平面;
其中,
c
⃗
\vec{c}
c 的大小等于
∣
a
∣
|a|
∣a∣
∣
b
∣
|b|
∣b∣
s
i
n
θ
sin\theta
sinθ。
注意,因为右手法则向量叉乘是不具备交换律。所以有:
a
⃗
\vec{a}
a
⨂
\bigotimes
⨂
b
⃗
\vec{b}
b =
−
b
⃗
-\vec{b}
−b
⨂
\bigotimes
⨂
a
⃗
\vec{a}
a。
向量的叉乘,也可以用矩阵的形式表示,其中
a
⃗
\vec{a}
a要转换为dual matrix的形式:
1.2.2 几何意义
(1) 单位向量建立三维空间中的直角坐标系
x
⃗
\vec{x}
x
⨂
\bigotimes
⨂
y
⃗
\vec{y}
y = +
z
⃗
\vec{z}
z
y
⃗
\vec{y}
y
⨂
\bigotimes
⨂
x
⃗
\vec{x}
x = -
z
⃗
\vec{z}
z
y
⃗
\vec{y}
y
⨂
\bigotimes
⨂
z
⃗
\vec{z}
z = +
x
⃗
\vec{x}
x
z
⃗
\vec{z}
z
⨂
\bigotimes
⨂
y
⃗
\vec{y}
y = -
x
⃗
\vec{x}
x
z
⃗
\vec{z}
z
⨂
\bigotimes
⨂
x
⃗
\vec{x}
x = +
y
⃗
\vec{y}
y
x
⃗
\vec{x}
x
⨂
\bigotimes
⨂
z
⃗
\vec{z}
z = -
y
⃗
\vec{y}
y
(2) 判断两个向量的左右关系
如下所示,
a
⃗
\vec{a}
a 和
b
⃗
\vec{b}
b 在三维空间x-y平面中:
可以看到,此时
b
⃗
\vec{b}
b在
a
⃗
\vec{a}
a的左侧(
a
⃗
\vec{a}
a逆时针旋转)。
如何判定上述左右关系?
当
a
⃗
\vec{a}
a
⨂
\bigotimes
⨂
b
⃗
\vec{b}
b 得到的
c
⃗
\vec{c}
c 的z方向大于0,就说
b
⃗
\vec{b}
b在
a
⃗
\vec{a}
a的左侧,
a
⃗
\vec{a}
a在
b
⃗
\vec{b}
b的右侧。判断左右关系的本质是右手法则。
(3) 判断点是否在三角形的内部
如下图所示,点A、B、C仍然在x-y平面内:
从A开始,逆时针逐向量与P进行比较:
A
B
→
\overrightarrow{AB}
AB
⨂
\bigotimes
⨂
A
P
→
\overrightarrow{AP}
AP的结果向量Z方向大于0;
B
C
→
\overrightarrow{BC}
BC
⨂
\bigotimes
⨂
B
P
→
\overrightarrow{BP}
BP的结果向量Z方向大于0;
C
A
→
\overrightarrow{CA}
CA
⨂
\bigotimes
⨂
C
P
→
\overrightarrow{CP}
CP的结果向量Z方向大于0;
上述三次比较生成了三个向量,由于三个结果向量的Z方向都大于0,因此可以判断P在
△
\triangle
△ABC的内部。
综上,判断点P是否在三角形内部的方法是:点P都在三角形三边的左边(若给定三角形三点的顺序是顺时针,则P需要在三角形三边的右边)。
1.3 标准正交基
标准正交基是三个相互垂直的单位向量,标记为
x
⃗
\vec{x}
x,
y
⃗
\vec{y}
y,
z
⃗
\vec{z}
z,其中
x
⃗
\vec{x}
x 和
y
⃗
\vec{y}
y 垂直,且满足
x
⃗
\vec{x}
x
⨂
\bigotimes
⨂
y
⃗
\vec{y}
y =
z
⃗
\vec{z}
z。
因此任意向量
p
⃗
\vec{p}
p 在xyz组成的坐标系可用其点积表示:
p
⃗
\vec{p}
p = (
p
⃗
\vec{p}
p
⋅
\cdot
⋅
x
⃗
\vec{x}
x)
x
⃗
\vec{x}
x + (
p
⃗
\vec{p}
p
⋅
\cdot
⋅
y
⃗
\vec{y}
y)
y
⃗
\vec{y}
y + (
p
⃗
\vec{p}
p
⋅
\cdot
⋅
z
⃗
\vec{z}
z)
z
⃗
\vec{z}
z
2 矩阵
2.1 矩阵乘法
矩阵乘法需要两个矩阵的行和列满足一定关系:
M
a
n
M_{an}
Man x
N
n
b
N_{nb}
Nnb,M的列数必须等于N的行数。
矩阵乘法不具备交换律:
M
M
M
N
N
N
!
=
!=
!=
N
N
N
M
M
M;
矩阵乘法具有结合律:(
A
A
A
B
B
B)
C
C
C
=
=
=
A
A
A(
B
B
B
C
C
C);
矩阵的转置: ( a x a y a z b x b y b z ) T \begin{pmatrix}a_{x}&a_{y}&a_{z}\\b_{x}&b_{y}&b_{z}\end{pmatrix}^{T} (axbxaybyazbz)T = ( a x b x a y b y a z b z ) \begin{pmatrix}a_{x}&b_{x}\\a_{y}&b_{y}\\a_{z}&b_{z}\end{pmatrix} ⎝ ⎛axayazbxbybz⎠ ⎞, ( A B ) T (AB)^{T} (AB)T = B T B^{T} BT A T A^{T} AT
矩阵的逆: A A A A − 1 A^{-1} A−1 = A − 1 A^{-1} A−1 A A A = I I I,其中 I I I是单位阵, ( A B ) − 1 (AB)^{-1} (AB)−1 = B − 1 B^{-1} B−1 A − 1 A^{-1} A−1 。
点乘的矩阵形式如下:
叉乘的矩阵形式如下:
2.2 矩阵变换
2.2.1 线性变换
线性变换形式如下:
x
′
=
a
x
+
b
y
x' = ax + by
x′=ax+by
y
′
=
c
x
+
d
y
y' = cx + dy
y′=cx+dy
( x ′ y ′ ) \begin{pmatrix}x'\\y'\end{pmatrix} (x′y′) = ( a b c d ) \begin{pmatrix}a&b\\c&d\end{pmatrix} (acbd) ( x y ) \begin{pmatrix}x\\y\end{pmatrix} (xy)
X ′ = M X X' = MX X′=MX
线性变换具备如下性质:
① 可加性: L(
v
⃗
\vec v
v +
w
⃗
\vec w
w) = L(
v
⃗
\vec v
v) + L(
w
⃗
\vec w
w);
② 成比例: L(c
v
⃗
\vec v
v) = cL(
v
⃗
\vec v
v);
上述性质可理解为:线性变换后1) 任意直线还是直线; 2) 原点位置不变。
2.2.2 模型变换
模型变换均属于线性变换。
(1) 缩放变换
二维空间中,缩放变换如下所示:
(2) 对称变换
二维空间中,绕Y轴的对称变换如下所示:
(3) 旋转
旋转都是绕原点进行旋转,旋转角度逆时针为正。二维空间中,矩阵如下:
对于旋转矩阵,若将
θ
\theta
θ 转变为
−
θ
-\theta
−θ,其矩阵如下所示:
R ( − θ ) R(-\theta) R(−θ) = ( c o s θ s i n θ − s i n θ c o s θ ) \begin{pmatrix} cos\theta & sin\theta \\ -sin\theta & cos\theta \end{pmatrix} (cosθ−sinθsinθcosθ) = R ( θ ) T R(\theta)^{T} R(θ)T
又由旋转的定义可知, R ( − θ ) R(-\theta) R(−θ) = R ( θ ) − 1 R(\theta)^{-1} R(θ)−1;
综上,对于旋转矩阵,有属性 R ( θ ) − 1 R(\theta)^{-1} R(θ)−1 = R ( θ ) T R(\theta)^{T} R(θ)T,这个属性后续会用到,也说明旋转矩阵是正交阵。
3 齐次坐标
3.1 为什么会有齐次坐标
对于平移变换,在二维的情况下,只能满足如下变换形式:
根据2.2.1所述,上述矩阵不是线性变换。
为了不让平移变换成为一种特殊情况,就在当前维度上新增一个维度,使平移变换在表示形式上是线性变换。这也体现了一种trade off的思想。
3.2 齐次坐标下的点和向量
在三维空间中,齐次坐标下的点表示为:
(
x
y
z
1
)
T
\begin{pmatrix} x & y & z & 1 \end{pmatrix}^{T}
(xyz1)T
在三维空间中,齐次坐标下的向量表示为:
(
x
y
z
0
)
T
\begin{pmatrix} x & y & z & 0 \end{pmatrix}^{T}
(xyz0)T
综上,可以看到,点被平移后,是新的点;向量被平移后,仍然是原向量。
根据齐次坐标是1或0,有如下操作:
v
e
c
t
o
r
+
v
e
c
t
o
r
=
v
e
c
t
o
r
vector + vector = vector
vector+vector=vector
v
e
c
t
o
r
+
p
o
i
n
t
=
p
o
i
n
t
vector + point = point
vector+point=point
p
o
i
n
t
−
p
o
i
n
t
=
v
e
c
t
o
r
point - point = vector
point−point=vector
上述操作根据结果的齐次坐标是0或1,都能很好的理解。那么如果情况是:点+点,结果是什么呢?
p
o
i
n
t
+
p
o
i
n
t
=
?
?
?
point + point = ???
point+point=???
在齐次坐标下,
(
x
y
z
w
)
T
\begin{pmatrix} x & y & z & w \end{pmatrix}^{T}
(xyzw)T表示的三维空间点,实际是:
(
x
/
w
y
/
w
z
/
w
1
)
T
\begin{pmatrix} x/w & y/w & z/w & 1 \end{pmatrix}^{T}
(x/wy/wz/w1)T,当然w不能等于0。
所以,结果如下:
p
o
i
n
t
+
p
o
i
n
t
=
p
o
i
n
t
point + point = point
point+point=point
4 模型矩阵
4.1 缩放
4.2 平移
引入齐次坐标后,平移矩阵的形式也遵从了线性变换。
4.3 旋转
绕X轴旋转如下,其中
α
\alpha
α 是从X轴正向往负向观察,逆时针为正:
绕X轴旋转同二维中相似,其中X轴不变,所以第一行是
(
1
0
0
0
)
T
\begin{pmatrix} 1 & 0 & 0 & 0 \end{pmatrix}^{T}
(1000)T;
绕Z轴旋转如下:
其中Z轴不变,所以第三行是
(
1
0
0
0
)
T
\begin{pmatrix} 1 & 0 & 0 & 0 \end{pmatrix}^{T}
(1000)T;
绕Y轴旋转如下:
绕Y轴旋转和绕X、Z轴旋转不一样,它的旋转参数实际进行了转置,为什么?
假设以XYZ的顺序定义三轴:
X
⃗
\vec{X}
X =
Y
⃗
\vec{Y}
Y
⨂
\bigotimes
⨂
Z
⃗
\vec{Z}
Z
Z
⃗
\vec{Z}
Z =
X
⃗
\vec{X}
X
⨂
\bigotimes
⨂
Y
⃗
\vec{Y}
Y
按XYZ的顺序,Y的定义:
−
Y
⃗
-\vec{Y}
−Y =
X
⃗
\vec{X}
X
⨂
\bigotimes
⨂
Z
⃗
\vec{Z}
Z
因此需要对旋转矩阵求反。而旋转矩阵是正交阵,取反就等于求转置。因此Y和X、Z的旋转矩阵不同。
4.4 仿射变换
应用了齐次坐标后,仿射变换也可以写成线性变化的形式:左边3X3的矩阵是线性变换参数,第四列是平移变换的参数。
如上所示,仿射变换中,先应用的是线性变换,再执行的平移。这个顺序非常重要。
我们在执行旋转前,若旋转中心不在(0, 0, 0),需要先平移(-x, -y, -z),然后执行相应旋转,再执行平移(x, y, z)还原。