用途:求两个向量的夹角
c o s θ = a ⃗ ⋅ b ⃗ ∣ ∣ a ⃗ ∣ ∣ ⋅ ∣ ∣ b ⃗ ∣ ∣ = a ^ ⋅ b ^ cos\theta = \frac{\vec{a}\cdot\vec{b}}{||\vec{a}||\cdot||\vec{b}||} = \hat{a}\cdot\hat{b} cosθ=∣∣a∣∣⋅∣∣b∣∣a⋅b=a^⋅b^
a ⃗ ⋅ b ⃗ = x a x b + y a y b + z a z b \vec{a}\cdot\vec{b} = x_{a}x_{b} + y_{a}y_{b} + z_{a}z_{b} a⋅b=xaxb+yayb+zazb
用途:判断左右、内外(某个点是否在三角形内部)
∣ ∣ a ⃗ × b ⃗ ∣ ∣ = ∣ ∣ a ⃗ ∣ ∣ ⋅ ∣ ∣ b ⃗ ∣ ∣ ⋅ sin φ ||\vec{a}\times\vec{b}||=||\vec{a}||\cdot||\vec{b}||\cdot \sin\varphi ∣∣a×b∣∣=∣∣a∣∣⋅∣∣b∣∣⋅sinφ
a ⃗ × b ⃗ = A ∗ b = ( 0 − z a y a z a 0 − x a − y a x a 0 ) ( x b y b z b ) \vec{a}\times\vec{b}=A^{*}b= \left(\begin{matrix} 0 & -z_{a} & y_{a}\\ z_{a} & 0 & -x_{a} \\ -y_{a} & x_{a} & 0 \end{matrix}\right) \left(\begin{matrix} x_{b} \\ y_{b} \\ z_{b} \end{matrix}\right) a×b=A∗b=⎝⎛0za−ya−za0xaya−xa0⎠⎞⎝⎛xbybzb⎠⎞
方向遵循右手定则
∣ ∣ u ⃗ ∣ ∣ = ∣ ∣ v ⃗ ∣ ∣ = ∣ ∣ w ⃗ ∣ ∣ = 1 ||\vec{u}||=||\vec{v}||=||\vec{w}||=1 ∣∣u∣∣=∣∣v∣∣=∣∣w∣∣=1
u ⃗ ⋅ v ⃗ = v ⃗ ⋅ w ⃗ = u ⃗ ⋅ w ⃗ = 0 \vec{u}\cdot\vec{v}=\vec{v}\cdot\vec{w}=\vec{u}\cdot\vec{w}=0 u⋅v=v⋅w=u⋅w=0
w ⃗ = u ⃗ × v ⃗ \vec{w}=\vec{u}\times\vec{v} w=u×v
任意向量p都可以分解为如下形式:
p ⃗ = ( p ⃗ ⋅ u ⃗ ) u ⃗ + ( p ⃗ ⋅ v ⃗ ) v ⃗ + ( p ⃗ ⋅ w ⃗ ) w ⃗ \vec{p}=(\vec{p}\cdot\vec{u})\vec{u}+(\vec{p}\cdot\vec{v})\vec{v}+(\vec{p}\cdot\vec{w})\vec{w} p=(p⋅u)u+(p⋅v)v+(p⋅w)w
齐次坐标,使得平移变换也是线性变换
2d point: ( x , y , 1 ) T (x,y,1)^{T} (x,y,1)T
2d vector: ( x , y , 0 ) T (x,y,0)^{T} (x,y,0)T
( x , y , z , w ) T (x,y,z,w)^{T} (x,y,z,w)T is the 3d point ( x / w , y / w , z / w , 1 ) T (x/w,y/w,z/w,1)^{T} (x/w,y/w,z/w,1)T (w≠0)
变换的组合:先缩放,再旋转,最后平移
( s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ) \left(\begin{matrix} s_{x} & 0 & 0 & 0\\ 0 & s_{y} & 0 & 0\\ 0 & 0 & s_{z} & 0\\ 0 & 0 & 0 & 1 \end{matrix}\right) ⎝⎜⎜⎛sx0000sy0000sz00001⎠⎟⎟⎞
绕x轴旋转
( 1 0 0 0 0 cos α − sin α 0 0 sin α cos α 0 0 0 0 1 ) \left(\begin{matrix} 1 & 0 & 0 & 0\\ 0 & \cos\alpha & -\sin\alpha & 0\\ 0 & \sin\alpha & \cos\alpha & 0\\ 0 & 0 & 0 & 1 \end{matrix}\right) ⎝⎜⎜⎛10000cosαsinα00−sinαcosα00001⎠⎟⎟⎞
( 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ) \left(\begin{matrix} 1 & 0 & 0 & t_{x}\\ 0 & 1 & 0 & t_{y}\\ 0 & 0 & 1 & t_{z}\\ 0 & 0 & 0 & 1 \end{matrix}\right) ⎝⎜⎜⎛100001000010txtytz1⎠⎟⎟⎞
R x y z ( α , β , γ ) = R x ( α ) R y ( β ) R z ( γ ) R_{xyz}(\alpha,\beta,\gamma)=R_{x}(\alpha)R_{y}(\beta)R_{z}(\gamma) Rxyz(α,β,γ)=Rx(α)Ry(β)Rz(γ)
这样一组绕3个坐标轴的旋转角度,被称为欧拉角
在Unity中,约定的旋转顺序为先绕Z轴,再绕X轴,再绕Y轴(在不旋转坐标系的情况下),这个顺序和旋转时一起转动坐标系的Y-X-Z顺序得到的结果是一样的。第一种情况可以看做是绕世界坐标系旋转(模型旋转不会使世界坐标系旋转),第二种情况可以看做是绕模型自己的坐标系旋转(旋转时模型坐标系也会一起旋转)
欧拉角受到万向锁 (Gimbal Lock) 的影响:当依次施加三个旋转时,第一个或第二个旋转可能导致第三个轴的方向与先前两个轴之一相同。这意味着已失去“自由度”,所以旋转的顺序很重要。只有第二种情况可能会导致万向锁(动态欧拉角),静态欧拉角不会有万向锁。
R ( n ⃗ , α ) = cos α ⋅ I + ( 1 − cos α ) 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\cdot I + (1-\cos\alpha)\vec{n}\vec{n}^{T} + \sin\alpha \left(\begin{matrix} 0 & -n_{z} & n_{y} \\ n_{z} & 0 & -n_{x} \\ -n_{y} & n_{x} & 0 \end{matrix}\right) R(n,α)=cosα⋅I+(1−cosα)nnT+sinα⎝⎛0nz−ny−nz0nxny−nx0⎠⎞
旋转的插值(这部分可以之后单独写一篇了)
MVP: Model -> View -> Projection
Define a camera:
target of view transformation: transform the camera to the origin, up at Y, look at -Z and transform the objects along with the camera
M v i e w = R v i e w ⋅ T v i e w M_{view} = R_{view}\cdot T_{view} Mview=Rview⋅Tview
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} = \left(\begin{matrix} 1 & 0 & 0 & -x_{e}\\ 0 & 1 & 0 & -y_{e}\\ 0 & 0 & 1 & -z_{e}\\ 0 & 0 & 0 & 1 \end{matrix}\right) Tview=⎝⎜⎜⎛100001000010−xe−ye−ze1⎠⎟⎟⎞
Rotate g to -Z, t to Y, g×t to X
Inverse: Z to -g, Y to t, X to g×t
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} = \left(\begin{matrix} x_{\hat{g}\times\hat{t}} & x_{t} & x_{-g} & 0\\ y_{\hat{g}\times\hat{t}} & y_{t} & y_{-g} & 0\\ z_{\hat{g}\times\hat{t}} & z_{t} & z_{-g} & 0\\ 0 & 0 & 0 & 1 \end{matrix}\right) Rview−1=⎝⎜⎜⎛xg^×t^yg^×t^zg^×t^0xtytzt0x−gy−gz−g00001⎠⎟⎟⎞
R v i e w = ( R v i e w − 1 ) T R_{view}=(R^{-1}_{view})^{T} Rview=(Rview−1)T(旋转矩阵是正交矩阵)
map a cubiod [ l , r ] × [ b , t ] × [ f , n ] [l,r]×[b,t]×[f,n] [l,r]×[b,t]×[f,n] to cube [ − 1 , 1 ] 3 [-1,1]^{3} [−1,1]3
先把长方体平移到原点,再缩放为边长为2的正方体
M o r t h o = M s c a l e ⋅ M t r a n s l a t i o n = ( 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}=M_{scale}\cdot M_{translation} = \left(\begin{matrix} \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{matrix}\right) \left(\begin{matrix} 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{matrix}\right) Mortho=Mscale⋅Mtranslation=⎝⎜⎜⎛r−l20000t−b20000n−f200001⎠⎟⎟⎞⎝⎜⎜⎛100001000010−2r+l−2t+b−2n+f1⎠⎟⎟⎞
First “squish” the frustum into a cuboid, then do orghographic projection
use 3 rules to get the persp2ortho matrix:
(1) y ′ = n z y y'=\frac{n}{z}y y′=zny, x ′ = n z x x'=\frac{n}{z}x x′=znx
(2) Any point on the near plane will not change
(3) Any point’s z on the far plane will not change
M p e r s p 2 o r t h o = ( n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ) M_{persp2ortho}=\left( \begin{matrix} n & 0 & 0 & 0 \\ 0 & n & 0 &0 \\0 & 0 & n+f & -nf \\0 & 0 & 1 & 0 \end{matrix} \right) Mpersp2ortho=⎝⎜⎜⎛n0000n0000n+f100−nf0⎠⎟⎟⎞