(个人笔记,由于刚开始学习再加上英语不太好,所以有的地理解的可能不太对,望指正)
Chapter 4 Transforms
基础变换
仿射变换的特点是保证了平行关系,但是长度跟角度可能发生变化。
各种变换操作的描述:

其中正交投影是正交的。。。
Basic Transforms
Translation
T(t)=T(tx,ty,tz)=(100tx010ty001tz0001)T−1(t)=T(−t) T(t) = T(t_x, t_y, t_z) = \begin{pmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \\ \qquad \\ \qquad T^{-1}(t) = T(-t) T(t)=T(tx,ty,tz)=⎝⎜⎜⎛100001000010txtytz1⎠⎟⎟⎞T−1(t)=T(−t)
Rotation
旋转会保持点之间的距离以及handness
二维旋转
u=(rcos(θ+ϕ)rsin(θ+ϕ))=(r(cosθcosϕ−sinθcosϕ)r(sinθcosϕ+sinϕcosθ))=(cosϕ−sinϕsinϕcosϕ)(rcosθrsinθ)=R(ϕ)v u = \begin{pmatrix} rcos(\theta + \phi) \\ rsin(\theta + \phi) \end{pmatrix} = \begin{pmatrix} r(cos\theta cos\phi - sin\theta cos\phi) \\ r(sin\theta cos\phi + sin\phi cos\theta) \end{pmatrix} = \begin{pmatrix} cos \phi & -sin\phi \\ sin \phi & cos \phi \end{pmatrix} \begin{pmatrix} rcos\theta \\ rsin\theta \end{pmatrix} = R(\phi)v u=(rcos(θ+ϕ)rsin(θ+ϕ))=(r(cosθcosϕ−sinθcosϕ)r(sinθcosϕ+sinϕcosθ))=(cosϕsinϕ−sinϕcosϕ)(rcosθrsinθ)=R(ϕ)v
三维旋转
Rx(ϕ)=(10000cosϕ−sinϕ00sinϕcosϕ00001),Ry(ϕ)=(cosϕ0sinϕ00100−sinϕ0cosϕ00001),Rz(ϕ)=(cosϕ−sinϕ00sinϕcosϕ0000100001) R_x(\phi) = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & cos\phi & -sin\phi & 0 \\ 0 & sin\phi & cos\phi & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}, \\ R_y(\phi) = \begin{pmatrix} cos\phi & 0 & sin\phi & 0 \\ 0 & 1 & 0 & 0 \\ -sin\phi & 0 & cos\phi & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}, \\ R_z(\phi) = \begin{pmatrix} cos\phi & -sin\phi & 0 & 0 \\ sin\phi & cos\phi & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} Rx(ϕ)=⎝⎜⎜⎛10000cosϕsinϕ00−sinϕcosϕ00001⎠⎟⎟⎞,Ry(ϕ)=⎝⎜⎜⎛cosϕ0−sinϕ00100sinϕ0cosϕ00001⎠⎟⎟⎞,Rz(ϕ)=⎝⎜⎜⎛cosϕsinϕ00−sinϕcosϕ0000100001⎠⎟⎟⎞
三维旋转矩阵的迹(trace)都为:
tr(R)=1+2cosϕ tr(R) = 1 + 2cos\phi tr(R)=1+2cosϕ
所有旋转矩阵的行列式值都为1并且都是正交的。
Ri−1(ϕ)=Ri(−ϕ) R_i^{-1}(\phi) = R_i(-\phi) Ri−1(ϕ)=Ri(−ϕ)
例子:绕一点旋转

旋转公式:
X=T(p)Rz(ϕ)T(−p) X = T(p)R_z(\phi)T(-p) X=T(p)Rz(ϕ)T(−p)
Scaling
S(s)=(sx0000sy0000sz00001)S−1(s)=S(1/sx,1/sy,1/sz) S(s) = \begin{pmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 &1 \end{pmatrix} \\ \qquad \\ S^{-1}(s) = S(1/s_x, 1/s_y, 1/s_z) S(s)=⎝⎜⎜⎛sx0000sy0000sz00001⎠⎟⎟⎞S−1(s)=S(1/sx,1/sy,1/sz)
反射变换可以通过-1作为参数进行缩放,反射变换可能导致顶点顺序发生变化。要判断某个变换是否是反射,则计算左上3x3矩阵的行列式,如果为负则是反射变换。
Shearing
三维空间下Shearing变换共有六种:Hxy(s),Hxz(s),Hyx(s),Hyz(s),Hzx(s),Hzy(s)H_{xy}(s), H_{xz}(s), H_{yx}(s), H_{yz}(s), H_{zx}(s), H_{zy}(s)Hxy(s),Hxz(s),Hyx(s),Hyz(s),Hzx(s),Hzy(s)其中第一个脚注表示是哪个维度值发生变化,第二个值是哪个维度进行shearing操作,也就是乘以哪个维度的值,以Hxz(s)H_{xz}(s)Hxz(s)为例:

变换矩阵为:
改变换产生了一个点(px+spz,py,pz)(p_x + sp_z, p_y, p_z)(px+spz,py,pz)
shearing变换的逆变换:Hij−1(s)=Hij(−s)H_{ij}^{-1}(s)=H_{ij}(-s)Hij−1(s)=Hij(−s)
The Rigid-Body Transform
只包含平移跟旋转的变换矩阵称为刚体变换。
$$
X=T(t)R=\begin{pmatrix}
R & T \
0 & 1 \
\end{pmatrix}
x^{-1}=(T(t)R)^{-1}=R^{-1}T(t)^{-1}=R^TT(-t)
$$
Normal Transform
Mn=(A−1)TA−1=1∣A∣A∗ M_n = (A^{-1})^T \\ A^{-1}=\frac{1}{|A|}A^* Mn=(A−1)TA−1=∣A∣1A∗
法线变化只需要计算左上3x3的部分
Special Matrix Transforms and Operations
x-pitch, y-head, z-roll
Extracting Parameters from the Euler Transform
$$
E(h, p, r) = \begin{pmatrix}
e_{00} & e_{01} & e_{02} \
e_{10} & e_{11} & e_{12} \
e_{20} & e_{21} & e_{22}
\end{pmatrix} = R_z®R_x§R_y(h)
\ \qquad
\ \qquad
\ = \begin{pmatrix}
cosrcosh-sinrsinpsinh & -sinrcosp & cosrsinh+sinrsinpcosh \
sinrcosh+cosrsinpsinh & cosrcosp & sinrsinh-cosrsinpcosh \
-cospsinh & sinp & cospcosh
\end{pmatrix}
\\ \qquad
\\ \qquad
\\ sinp = e_{21} \\
\frac{e_{01}}{e_{11}} = \frac{-sinr}{cosr}=-tanr\\
\frac{e_{20}}{e_{22}} = \frac{-sinh}{cosh}=-tanh\\
可以得出:\\
h=atan(-e_{20}, e_{22})\\
p=arcsin(e_{21})\\
r=atan(-e_{01},e_{11})
$$
万向锁:https://blog.youkuaiyun.com/hanjuefu5827/article/details/80659343
Rotation about an Arbitrary Axis
绕任意轴r旋转:

其中M矩阵:
M=(rTsTtT) M = \begin{pmatrix} r^T \\ s^T \\ t^T \end{pmatrix} M=⎝⎛rTsTtT⎠⎞
绕任意轴旋转矩阵:
X=MTRx(α)M X=M^TR_x(\alpha)M X=MTRx(α)M
Quaternions
定义:
q^=(qv→,qw)=iqx+jqy+kqz+qw=qv→+qwqv→=iqx+jqy+kqz=(qz,qy,qz),i2=j2=k2=−1,jk=−ky=i,ki=−ik=j,ij=−ji=k \hat{q}=(\overrightarrow{q_v}, q_w)=iq_x+jq_y+kq_z+q_w=\overrightarrow{q_v}+q_w \\ \overrightarrow{q_v}=iq_x+jq_y+kq_z=(q_z,q_y,q_z),\\ i^2=j^2=k^2=-1,\\ jk=-ky=i,ki=-ik=j,ij=-ji=k q^=(qv,qw)=iqx+jqy+kqz+qw=qv+qwqv=iqx+jqy+kqz=(qz,qy,qz),i2=j2=k2=−1,jk=−ky=i,ki=−ik=j,ij=−ji=k
乘法:
q^r^=(iqx+jqy+kqz+qw)(irx+jry+krz+rw)=i(qyrz−qzry+rwqx+qwrx)+j(qzrx−qxrz+rwqy+qwry)+k(qxry−qyrx+rwqz+qwrz)+qwrw−qxrx−qyry−qzrz‘=(qv→∗rv→+rwqv→+qwrv→, qwrw−qv→∙rv→) \hat{q}\hat{r}=(iq_x+jq_y+kq_z+q_w)(ir_x+jr_y+kr_z+r_w)\\ =i(q_yr_z-q_zr_y+r_wq_x+q_wr_x)+j(q_zr_x-q_xr_z+r_wq_y+q_wr_y)+k(q_xr_y-q_yr_x+r_wq_z+q_wr_z)+q_wr_w-q_xr_x-q_yr_y-q_zr_z\\` =(\overrightarrow{q_v}*\overrightarrow{r_v} + r_w\overrightarrow{q_v}+q_w\overrightarrow{r_v},\ q_wr_w-\overrightarrow{q_v}\bullet \overrightarrow{r_v}) q^r^=(iqx+jqy+kqz+qw)(irx+jry+krz+rw)=i(qyrz−qzry+rwqx+qwrx)+j(qzrx−qxrz+rwqy+qwry)+k(qxry−qyrx+rwqz+qwrz)+qwrw−qxrx−qyry−qzrz‘=(qv∗rv+rwqv+qwrv, qwrw−qv∙rv)
共轭(conjugate):
$$
\hat{q}*=(\overrightarrow{q_v},q_w)=(-\overrightarrow{q_v},q_w)\
(\hat{q}*)=\hat{q}\
(\hat{q}+\hat{r})*=\hat{q}+\hat{r}^\
(\hat{q}\hat{r})*=\hat{r}\hat{q}^
$$
模(norm):
n(q^)=q^∗q^=qv→∙qv→+qw2=qx2+qy2+qz2+qw2n(q^∗)=n(q^)n(q^r^)=n(q^)n(r^) n(\hat{q})=\sqrt{\hat{q}^*\hat{q}}=\sqrt{\overrightarrow{q_v} \bullet \overrightarrow{q_v}+q_w^2}\\ =\sqrt{q_x^2+q_y^2+q_z^2+q_w^2}\\ \\n(\hat{q}^*)=n(\hat{q}) \\n(\hat{q}\hat{r})=n(\hat{q})n(\hat{r}) n(q^)=q^∗q^=qv∙qv+qw2=qx2+qy2+qz2+qw2n(q^∗)=n(q^)n(q^r^)=n(q^)n(r^)
Identity:
i^=(0→,1) \hat{i}=(\overrightarrow{0}, 1) i^=(0,1)
逆:
q^−1=1n(q^)2q^∗ \hat{q}^{-1}=\frac{1}{n(\hat{q})^2}\hat{q}^* q^−1=n(q^)21q^∗
对于单位四元素它的模为1,所以他可以被写成:
q^=(sinϕuq,cosϕ)∣∣uq∣∣=1 \hat{q}=(sin\phi u_q, cos\phi)\\ ||u_q||=1 q^=(sinϕuq,cosϕ)∣∣uq∣∣=1
根据欧拉公式,也可以写成:
q^=sinϕuq+cosϕ=eϕuqlog(q^)=log(eϕuq)=ϕuqq^t=(sinϕuq+cosϕ)t=eϕtuq=sin(ϕt)uq+cos(ϕt) \hat{q}=sin\phi u_q+cos\phi=e^{\phi u_q}\\ log(\hat{q})=log(e^{\phi u_q})=\phi _uq \hat{q}^t=(sin\phi u_q+cos\phi)^t=e^{\phi tu_q}=sin(\phi t)u_q+cos(\phi t) q^=sinϕuq+cosϕ=eϕuqlog(q^)=log(eϕuq)=ϕuqq^t=(sinϕuq+cosϕ)t=eϕtuq=sin(ϕt)uq+cos(ϕt)
Quaternion Transforms
假定一个点或者是向量p=(px py pz pw)Tp=(p_x \ p_y \ p_z \ p_w)^Tp=(px py pz pw)T,一个单位四元数q^=(sinϕuq,cosϕ)\hat{q}=(sin\phi u_q,cos\phi)q^=(sinϕuq,cosϕ),可以证明q^p^q^−1\hat{q}\hat{p}\hat{q}^{-1}q^p^q^−1可以表示为p^\hat{p}p^绕轴uqu_quq旋转2ϕ2\phi2ϕ,由于是单位四元数所以q^−1=q^∗\hat{q}^{-1}=\hat{q}^*q^−1=q^∗
对于任何非零实数诚意q^\hat{q}q^任然表示相同的变换,这意味着q^\hat{q}q^与−q^-\hat{q}−q^表示相同的旋转。
对于多个旋转,可以通过结合律:
r^(q^p^q^∗)r^∗=(r^q^)p^(q^∗r^∗) \hat{r}(\hat{q}\hat{p}\hat{q}^*)\hat{r}^*=(\hat{r}\hat{q})\hat{p}(\hat{q}^*\hat{r}^*) r^(q^p^q^∗)r^∗=(r^q^)p^(q^∗r^∗)
Matrix Conversion
Mq=(1−s(qy2+qz2)s(qxqy−qwqz)s(qxqz+qwqy)0s(qxqy+qwqz)1−s(qx2+qz2)s(qyqz−qwqx)0s(qxqz−qwqy)s(qyqz+qwqx)1−s(qx2+qy2)00000) M^q = \begin{pmatrix} 1-s(q_y^2+q_z^2) & s(q_xq_y-q_wq_z) & s(q_xq_z+q_wq_y) & 0 \\ s(q_xq_y+q_wq_z) & 1-s(q_x^2+q_z^2) & s(q_yq_z-q_wq_x) & 0 \\ s(q_xq_z-q_wq_y) & s(q_yq_z+q_wq_x) & 1-s(q_x^2+q_y^2) & 0 \\ 0 & 0 & 0 & 0 \end{pmatrix}\\ Mq=⎝⎜⎜⎛1−s(qy2+qz2)s(qxqy+qwqz)s(qxqz−qwqy)0s(qxqy−qwqz)1−s(qx2+qz2)s(qyqz+qwqx)0s(qxqz+qwqy)s(qyqz−qwqx)1−s(qx2+qy2)00000⎠⎟⎟⎞
其中s=2/(n(q^))2s=2/(n(\hat{q}))^2s=2/(n(q^))2
对于单位四元数,可以简化为
Mq=(1−2(qy2+qz2)2(qxqy−qwqz)2(qxqz+qwqy)02(qxqy+qwqz)1−2(qx2+qz2)2(qyqz−qwqx)02(qxqz−qwqy)2(qyqz+qwqx)1−2(qx2+qy2)00000) M^q = \begin{pmatrix} 1-2(q_y^2+q_z^2) & 2(q_xq_y-q_wq_z) & 2(q_xq_z+q_wq_y) & 0 \\ 2(q_xq_y+q_wq_z) & 1-2(q_x^2+q_z^2) & 2(q_yq_z-q_wq_x) & 0 \\ 2(q_xq_z-q_wq_y) & 2(q_yq_z+q_wq_x) & 1-2(q_x^2+q_y^2) & 0 \\ 0 & 0 & 0 & 0 \end{pmatrix}\\ Mq=⎝⎜⎜⎛1−2(qy2+qz2)2(qxqy+qwqz)2(qxqz−qwqy)02(qxqy−qwqz)1−2(qx2+qz2)2(qyqz+qwqx)02(qxqz+qwqy)2(qyqz−qwqx)1−2(qx2+qy2)00000⎠⎟⎟⎞
球面线性插值
根据q^\hat{q}q^、r^\hat{r}r^以及参数t∈[0,1]t\in[0,1]t∈[0,1]求一个差值四元数
s^(q^,r^,t)=(r^q^−1)tq^ \hat{s}(\hat{q}, \hat{r}, t)=(\hat{r}\hat{q}^{-1})^t\hat{q} s^(q^,r^,t)=(r^q^−1)tq^
实际计算中使用
s^(q^,r^,t)=slerp(q^,r^,t)=sin(ϕ(1−t))sinϕq^+sin(ϕt)sinϕr^ \hat{s}(\hat{q}, \hat{r}, t)=slerp(\hat{q}, \hat{r}, t)\\ =\frac{sin(\phi(1-t))}{sin\phi}\hat{q}+\frac{sin(\phi t)}{sin\phi}\hat{r} s^(q^,r^,t)=slerp(q^,r^,t)=sinϕsin(ϕ(1−t))q^+sinϕsin(ϕt)r^
其中cosϕ=qxrx+qyry+qzrz+qwrwcos\phi=q_xr_x+q_yr_y+q_zr_z+q_wr_wcosϕ=qxrx+qyry+qzrz+qwrw
将一个向量旋转到另一个向量
将限量sss旋转到向量ttt:首先归一化sss与ttt,然后计算旋转轴u=(s∗t)/∣∣s∗t∣∣u=(s*t)/||s*t||u=(s∗t)/∣∣s∗t∣∣,第三设e=s∙t=cos(2ϕ) ∣∣s∗t∣∣=sin(2ϕ)e=s\bullet t=cos(2\phi) \ \ \ ||s*t||=sin(2\phi)e=s∙t=cos(2ϕ) ∣∣s∗t∣∣=sin(2ϕ),其中2ϕ2\phi2ϕ是sss与ttt的夹角。那么这个四元数可以表示为q^=(sinϕu,cosϕ)\hat{q}=(sin\phi u,cos\phi)q^=(sinϕu,cosϕ),化简可得:
q^=(sinϕsin2ϕ(s∗t),cosϕ)=(qv,qw)=(12(1+e)(s∗t),2(1+e)2) \hat{q}=(\frac{sin\phi}{sin2\phi}(s*t), cos\phi)\\ =(q_v,q_w)=(\frac{1}{\sqrt{2(1+e)}}(s*t),\frac{\sqrt{2(1+e)}}{2}) q^=(sin2ϕsinϕ(s∗t),cosϕ)=(qv,qw)=(2(1+e)1(s∗t),22(1+e))
顶点混合(Vertex Blending)
皮肤表面顶点收到多个骨骼影响,经过动画变换最终位置的基本公式是:
u(t)=∑i=0n−1ωiBi(t)Mi−1p, where∑i=0n−1=1, ωi≥0 u(t)=\sum_{i=0}^{n-1}\omega_iB_i(t)M_i^{-1}p,\ \ where \sum_{i=0}^{n-1}=1,\ \ \omega_i\ge 0 u(t)=i=0∑n−1ωiBi(t)Mi−1p, wherei=0∑n−1=1, ωi≥0
其中ωi\omega_iωi表示第iii块骨骼对于顶点ppp的影响权重。MiM_iMi表示从骨骼的本地坐标转换到世界坐标的变换矩阵。Bi(t)B_i(t)Bi(t)表示第iii个骨骼随着物体动画的进行所需要的世界变换矩阵,通常来讲是一系列矩阵的结合,比如说是之前各级骨骼的变换以及本地动画矩阵(什么鬼。。。)
每一个骨骼将一个顶点根据每一帧中的索引变换到一个位置,最终的位置是根据一系列计算出的顶点差值得到的。在一些说明中MiM_iMi会作为Bi(t)B_i(t)Bi(t)的一部分,在实际中也是。发现的计算也可以使用上述公式,需要将Bi(t)MiB_i(t)M_iBi(t)Mi替换成逆的转置。
在GPU计算中,mesh顶点会作为静态的缓存一次性发送给GPU,这部分数据可以被GPU反复使用,每次要变化的只有骨骼的矩阵。骨骼变换也可以储存到纹理当中,每一次变换如果使用四元数则只需要两个纹理元素来表示旋转的话。
顶点混合的缺点是会出现一些折叠(folding)、扭曲(twisting)和自相交(self intersection)。解决的方法之一是使用对偶四元数(dual quaternions),它可以很好地避免肢体的糖纸扭曲(candy wrapper twist)
变形(Morphing)
变形效果主要有两个主要问题:顶点对应(vertex correspondence)问题和插值问题。对于两个顶点数量不同,拓扑结构不同,网格连接关系不同的模型进行变形首先要做的就是顶点对应。
如果对于一个顶点能够一一对应的模型,那么就可以进行逐顶点的插值了。对于一个时间点t∈[t0,t1]t\in[t_0,t_1]t∈[t0,t1],首先计算s=(t−t0)/(t1−t0)s=(t-t_0)/(t_1-t_0)s=(t−t0)/(t1−t0),然后就可以先行插值了:
m=(1−s)p0+sp1 m=(1-s)p_0+sp_1 m=(1−s)p0+sp1
Geometry Cache Playback
Projections
正交投影(Orthographic Projection)
Po=S(s)T(t)=(2r−l00002t−b00002f−n00001)(100−l+r2010−t+b2001−f+n20001)=(2r−l00−r+lr−l02t−b0−t+bt−b002f−n−f+nf−n0001) P_o = S(s)T(t) = \begin{pmatrix} \frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{f-n} & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & -\frac{l+r}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{f+n}{2} \\ 0 & 0 & 0 & 1 \end{pmatrix} \\ = \begin{pmatrix} \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}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{pmatrix} Po=S(s)T(t)=⎝⎜⎜⎛r−l20000t−b20000f−n200001⎠⎟⎟⎞⎝⎜⎜⎛100001000010−2l+r−2t+b−2f+n1⎠⎟⎟⎞=⎝⎜⎜⎛r−l20000t−b20000f−n20−r−lr+l−t−bt+b−f−nf+n1⎠⎟⎟⎞
示意图如下:

透视投影(Perspective Projection)
示意图如下:

p在投影平面上的投影q的坐标为q=(qx,qy,−d)q=(q_x,q_y,-d)q=(qx,qy,−d),qxq_xqx和qyq_yqy的计算公式如下:
qxpx=−dpz ⇒ qx=−dpxpz \frac{q_x}{p_x}=\frac{-d}{p_z} \ \Rightarrow \ q_x=-d\frac{p_x}{p_z} pxqx=pz−d ⇒ qx=−dpzpx
透视矩阵:
Pp=(10000100001000−1/d0)
P_p = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & -1/d & 0
\end{pmatrix}
Pp=⎝⎜⎜⎛10000100001−1/d0000⎠⎟⎟⎞
变换效果如下:

点p的透视变换
q=Ppp=(10000100001000−1/d0)(pxpypz1)=(pxpypz−pz/d)⇒(−dpx/pz−dpy/pz−d1) q = P_pp = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & -1/d & 0 \end{pmatrix} \begin{pmatrix} p_x \\ p_y \\ p_z \\ 1 \end{pmatrix} =\begin{pmatrix} p_x \\ p_y \\ p_z \\ -p_z/d \end{pmatrix} \Rightarrow \begin{pmatrix} -dp_x/p_z \\ -dp_y/p_z \\ -d \\ 1 \end{pmatrix} q=Ppp=⎝⎜⎜⎛10000100001−1/d0000⎠⎟⎟⎞⎝⎜⎜⎛pxpypz1⎠⎟⎟⎞=⎝⎜⎜⎛pxpypz−pz/d⎠⎟⎟⎞⇒⎝⎜⎜⎛−dpx/pz−dpy/pz−d1⎠⎟⎟⎞
Field of view
ϕ=2arctan(w/(2d)) \phi = 2arctan(w/(2d)) ϕ=2arctan(w/(2d))
其中ϕ\phiϕ表示field of view,www表示垂直于视线的物体的宽度,ddd表示距离物体的距离
透视变换
Pp=(2nr−l0−r+lr−l002nt−b−t+bt−b000f+nf−n−2fnf−n0010) P_p = \begin{pmatrix} \frac{2n}{r-l} & 0 & -\frac{r+l}{r-l} & 0 \\ 0 & \frac{2n}{t-b} & -\frac{t+b}{t-b} & 0 \\ 0 & 0 & \frac{f+n}{f-n} & -\frac{2fn}{f-n} \\ 0 & 0 & 1 & 0 \end{pmatrix} Pp=⎝⎜⎜⎛r−l2n0000t−b2n00−r−lr+l−t−bt+bf−nf+n100−f−n2fn0⎠⎟⎟⎞
对于fff趋近于无穷,也可以写成
Pp=(2nr−l0−r+lr−l002nt−b−t+bt−b0001−2n0010) P_p = \begin{pmatrix} \frac{2n}{r-l} & 0 & -\frac{r+l}{r-l} & 0 \\ 0 & \frac{2n}{t-b} & -\frac{t+b}{t-b} & 0 \\ 0 & 0 & 1 & -2n \\ 0 & 0 & 1 & 0 \end{pmatrix} Pp=⎝⎜⎜⎛r−l2n0000t−b2n00−r−lr+l−t−bt+b1100−2n0⎠⎟⎟⎞
在OpenGL当中会首先乘以S(1, 1, -1, 1),那么0<n′<f′0<n'<f'0<n′<f′得到:
Pp=(2n′r−l0−r+lr−l002n′t−b−t+bt−b000−f′+n′f′−n′−2f′n′f′−n′00−10) P_p = \begin{pmatrix} \frac{2n'}{r-l} & 0 & -\frac{r+l}{r-l} & 0 \\ 0 & \frac{2n'}{t-b} & -\frac{t+b}{t-b} & 0 \\ 0 & 0 & -\frac{f'+n'}{f'-n'} & -\frac{2f'n'}{f'-n'} \\ 0 & 0 & -1 & 0 \end{pmatrix} Pp=⎝⎜⎜⎜⎛r−l2n′0000t−b2n′00−r−lr+l−t−bt+b−f′−n′f′+n′−100−f′−n′2f′n′0⎠⎟⎟⎟⎞
根据fov可以化简为:
Pp=(c/a0000c0000−f′+n′f′−n′−2f′n′f′−n′00−10)其中a=w/h,c=1.0/tan(ϕ/2) P_p = \begin{pmatrix} c/a & 0 & 0 & 0 \\ 0 & c & 0 & 0 \\ 0 & 0 & -\frac{f'+n'}{f'-n'} & -\frac{2f'n'}{f'-n'} \\ 0 & 0 & -1 & 0 \end{pmatrix} \\ 其中 a = w / h,c=1.0/tan(\phi/2) Pp=⎝⎜⎜⎛c/a0000c0000−f′−n′f′+n′−100−f′−n′2f′n′0⎠⎟⎟⎞其中a=w/h,c=1.0/tan(ϕ/2)
z-buffer的精确度
点p经过透视变换之后可得:
v=Pp=(⋯⋯dpz+e±pz) v=Pp=\begin{pmatrix} \cdots \\ \cdots \\ dp_z+e \\ \pm p_z \end{pmatrix} v=Pp=⎝⎜⎜⎛⋯⋯dpz+e±pz⎠⎟⎟⎞
其中d=−f′+n′f′−n′d=-\frac{f'+n'}{f'-n'}d=−f′−n′f′+n′,e=−2f′n′f′−n′e=-\frac{2f'n'}{f'-n'}e=−f′−n′2f′n′,可以得到:
zNDC=dpz+e−pz=d−epz z_{NDC}=\frac{dp_z+e}{-p_z}=d-\frac{e}{p_z} zNDC=−pzdpz+e=d−pze
变换曲线:

为了提高深度的精确度,一个常用的方法是翻转z(reversed z),也就是使用1.0−zNDC1.0-z_{NDC}1.0−zNDC。几种不同处理的对比如下:

对于屏幕空间的深度计算,可以使用以下公式进行remapping:
z=w(log2(max(10−6,1+w))fc−1),[OpenGL]z=wlog2(max(10−6,1+w))fc/2,[DX] z=w(log_2(max(10^{-6}, 1+w))f_c-1), \qquad [OpenGL] \\ z=wlog_2(max(10^{-6}, 1+w))f_c/2, \qquad [DX] \\ z=w(log2(max(10−6,1+w))fc−1),[OpenGL]z=wlog2(max(10−6,1+w))fc/2,[DX]
其中www是顶点经过透视变换之后的www值,zzz是顶点着色器中得到的zzz值,fc=2/log2(f+1)f_c=2/log_2(f+1)fc=2/log2(f+1)
本文深入探讨了计算机图形学中的基本变换,包括平移、旋转、缩放等,并详细解析了四元数的概念、运算及其在旋转中的应用。通过实例展示了如何使用四元数避免万向锁问题,实现高效稳定的旋转变换。
511

被折叠的 条评论
为什么被折叠?



