PBRT-E2.7-變換(Transformations)

PBRT-E2.7-變換(Transformations)

來自專欄 Way On PBRT1 人贊了文章

一般來說,一個變換(Transformation) mathbf{T} 是指一個從點到點或者向量到向量間的映射:

mathbf{p} =mathbf{p}_{0}+ s_{1}mathbf{v}_{1} + dots + s_{n}mathbf{v}_{n} mathbf{p}=mathbf{T}(mathbf{p}) qquad mathbf{v}=mathbf{T}(mathbf{v})

一般來說變換可以分為以下三種:

  1. 線性(Linear):如果 mathbf{T} 是一個線性映射,那麼對於任意的標量 s 都有 mathbf{T}(smathbf{v}) = smathbf{T}(mathbf{v})mathbf{T}(mathbf{v}_{1}+mathbf{v}_{2}) = mathbf{T}(mathbf{v}_{1})+mathbf{T}(mathbf{v}_{2}) 。線性變換的這兩條性質能夠極大地簡化變換推導的過程。
  2. 連續(Continuous):簡單來說就是 mathbf{T}mathbf{p}mathbf{v} 的周圍區域相應的也映射到了mathbf{p}mathbf{v}周圍的區域。
  3. 一對一(One-to-one)且可逆(Invertible):對每一個頂點 mathbf{p} mathbf{T} 都只會將其映射到唯一的點 mathbf{p} 上,且存在一個從 mathbf{p}mathbf{p} 的逆變換 mathbf{T}^{-1}

藉由這些基本性質,一般我們可以使用一個 4	imes4 的矩陣來表示點和向量在同一個固定標架下的線性變換以及它們在標架之間的線性變換。

其次坐標(Homogeneous coordinates)

給定一個標架 (mathbf{p},mathbf{v}_{1},mathbf{v}_{2},mathbf{v}_{3}) ,該標架下 xyz 分量相同的點 (mathbf{p}_{x},mathbf{p}_{y},mathbf{p}_{z}) 和向量 (mathbf{v}_{x},mathbf{v}_{y},mathbf{v}_{z}) 之間存在明顯的二義性(Ambiguity)。在 E2.1-坐標系統 中我們知道點和向量分別被定義為:

mathbf{p} =mathbf{p}_{0}+ s_{1}mathbf{v}_{1} + dots + s_{n}mathbf{v}_{n}

mathbf{v} = s_{1}mathbf{v}_{1} + dots + s_{n}mathbf{v}_{n}

將其分別寫成矩陣相乘的形式可以得到:

mathbf{p}= left[egin{matrix} s_{1}&s_{2}&s_{3}&1\ end{matrix}
ight] left[egin{matrix} mathbf{v}_{1}\ mathbf{v}_{2}\ mathbf{v}_{3}\ mathbf{p}_{0}\ end{matrix}
ight]

mathbf{v}= left[egin{matrix} s_{1}&s_{2}&s_{3}&0\ end{matrix}
ight] left[egin{matrix} mathbf{v}_{1}\ mathbf{v}_{2}\ mathbf{v}_{3}\ mathbf{p}_{0}\ end{matrix}
ight]

這樣由 s_{1}s_{2}s_{3} 以及 0 或者 1 組成的四維坐標被稱作是點和向量的其次(Homogeneous)表示,又稱其次坐標(Homogeneous coordinate)。其次坐標的第四個分量又被稱作權重(Weight),對於點它可以是任意的非零值:其次坐標 (1,3,-2,1)(-2,-6,4,-2) 所描述都是同一個點 (1,3,-2) 。將其次坐標轉換為普通坐標的方法就是將其次坐標的前三個分量除以它的權重(第四個分量):

(x,y,z,w)=(frac{x}{w},frac{y}{w},frac{z}{w})

點和向量在標架間的變換

給定一個矩陣 mathbf{M} 表示從一個標架到另一個標架的變換:

mathbf{M}= left[egin{matrix} m_{0,0}&m_{0,1}&m_{0,2}&m_{0,3}\ m_{1,0}&m_{1,1}&m_{1,2}&m_{1,3}\ m_{2,0}&m_{2,1}&m_{2,2}&m_{2,3}\ m_{3,0}&m_{3,1}&m_{3,2}&m_{3,3}\ end{matrix}
ight]

我們將變換 mathbf{M} 作用到 標準標架下的x(1,0,0) 上:

mathbf{Mx}=mathbf{M} left[egin{matrix} 1\ 0\ 0\ 0\ end{matrix}
ight] = left[egin{matrix} m_{0,0}\ m_{1,0}\ m_{2,0}\ m_{3,0}\ end{matrix}
ight]

同理可以得到

mathbf{My}= left[egin{matrix} m_{0,1}\ m_{1,1}\ m_{2,1}\ m_{3,1}\ end{matrix}
ight] , mathbf{Mz}= left[egin{matrix} m_{0,2}\ m_{1,2}\ m_{2,2}\ m_{3,2}\ end{matrix}
ight] , mathbf{Mp}= left[egin{matrix} m_{0,3}\ m_{1,3}\ m_{2,3}\ m_{3,3}\ end{matrix}
ight]

這樣我們通過矩陣 mathbf{M} 的每一列就能得到標準標架經過變換後得到標架的基向量和原點的坐標了。

通過下面的式子可以看到,直接將變換作用於點和向量等價於先將變換作用於其所處標架下的基向量和原點,然後再尋找其在變換後標架下的坐標,剛好這個坐標在變換的前後相等的。

mathbf{M}mathbf{p} =mathbf{M}mathbf{p}_{0}+ s_{1}mathbf{M}mathbf{v}_{1} + dots + s_{n}mathbf{M}mathbf{v}_{n}

mathbf{M}mathbf{v} = s_{1}mathbf{M}mathbf{v}_{1} + dots + s_{n}mathbf{M}mathbf{v}_{n}

PBRT中使用的是列向量,如果你使用行向量記得對轉置一下下面給出的變換矩陣。

平移變換(Translations)

  • 定義:mathbf{T}(Delta x,Delta y,Delta z)(x,y,z)=(x+Delta x,y+Delta y,z+Delta z)
  • 性質:

mathbf{T}(0,0,0)=mathbf{I}

mathbf{T}(x_1,y_1,z_1)mathbf{T}(x_2,y_2,z_2)=mathbf{T}(x_1+x_2,y_1+y_2,z_1+z_2)

mathbf{T}(x_1,y_1,z_1)mathbf{T}(x_2,y_2,z_2)=mathbf{T}(x_2,y_2,z_2)mathbf{T}(x_1,y_1,z_1)

mathbf{T}^{-1}(x,y,z)=mathbf{T}(-x,-y,-z)

  • 變換矩陣:

mathbf{T}(Delta x,Delta y,Delta z)= left[egin{matrix} 1&0&0&Delta x\ 0&1&0&Delta y\ 0&0&1&Delta z\ 0&0&0&1\ end{matrix}
ight]

縮放變換(Scaling)

  • 定義: mathbf{S}(Delta x,Delta y,Delta z)(x,y,z)=(xDelta x,yDelta y,zDelta z)
  • 性質:

mathbf{S}(1,1,1)=mathbf{I}

mathbf{S}(x_1,y_1,z_1)mathbf{S}(x_2,y_2,z_2)=mathbf{S}(x_1x_2,y_1y_2,z_1z_2)

mathbf{S}^{-1}(x,y,z)=mathbf{S}(frac{1}{x},frac{1}{y},frac{1}{z})

  • 變換矩陣:

mathbf{S}(Delta x,Delta y,Delta z)= left[egin{matrix} Delta x&0&0&0\ 0&Delta y&0&0\ 0&0&Delta z&0\ 0&0&0&1\ end{matrix}
ight]

繞坐標軸旋轉變換(Rotation)

定義: mathbf{R}_{x}(	heta)mathbf{R}_{y}(	heta)mathbf{R}_{z}(	heta) 表示繞 xyz 軸旋轉 	heta 角度。

性質:

mathbf{R}_{a}(0)=mathbf{I}

mathbf{R}_{a}(	heta_{1})mathbf{R}_{a}(	heta_{2})=mathbf{R}_{a}(	heta_{1}+	heta_{2})

mathbf{R}_{a}(	heta_{1})mathbf{R}_{a}(	heta_{2})=mathbf{R}_{a}(	heta_{2})mathbf{R}_{a}(	heta_{1})

mathbf{R}^{-1}_{a}(	heta)=mathbf{R}_{a}(-	heta)=mathbf{R}^{T}_{a}(	heta)

變換矩陣:

mathbf{R}_{x}(	heta)= left[egin{matrix} 1&0&0&0\ 0&cos	heta&-sin	heta&0\ 0&sin	heta&cos	heta&0\ 0&0&0&1\ end{matrix}
ight] , mathbf{R}_{y}(	heta)= left[egin{matrix} cos	heta&0&sin	heta&0\ 0&1&0&0\ -sin	heta&0&cos	heta&0\ 0&0&0&1\ end{matrix}
ight] , mathbf{R}_{z}(	heta)= left[egin{matrix} cos	heta&-sin	heta&0&0\ sin	heta&cos	heta&0&0\ 0&0&1&0\ 0&0&0&1\ end{matrix}
ight]

繞任意軸旋轉變換(Rotation)

設旋轉軸的方向為 mathbf{a} ,待旋轉向量為 mathbf{v} ,旋轉轉的角度為 	heta

首先求解向量 mathbf{v} 在旋轉軸 mathbf{a} 上的分量 mathbf{v}_c ,設向量 mathbf{v} 與旋轉軸 mathbf{a} 的夾角為 alpha ,則有:

mathbf{v}_c=mathbf{a}||mathbf{v}||cosalpha=mathbf{a}(mathbf{v} cdot mathbf{a})

接下來計算向量 mathbf{v} 的末端繞軸 mathbf{a}旋轉所得到圓盤所處的平面上的一組基向量 mathbf{v}_1mathbf{v}_2

mathbf{v}_1 = mathbf{v} - mathbf{v}_c

mathbf{v}_2=mathbf{v}_1	imes mathbf{a}

注意這裡的 mathbf{a} 為單位向量,因此基向量 mathbf{v}_1mathbf{v}_2的模長是相等的,都等於 mathbf{v} - mathbf{v}_c ,根據前面的推導我們知道對點和向量的變換等價於對其所處標架的原點和進行變換再用同樣的係數進行線性表示:

mathbf{M}mathbf{p} =mathbf{M}mathbf{p}_{0}+ s_{1}mathbf{M}mathbf{v}_{1} + dots + s_{n}mathbf{M}mathbf{v}_{n}

mathbf{M}mathbf{v} = s_{1}mathbf{M}mathbf{v}_{1} + dots + s_{n}mathbf{M}mathbf{v}_{n}

因此我們可以得到 mathbf{v}_1 旋轉後的向量 mathbf{v}_1 ,這樣就能算出 mathbf{v} 旋轉後的向量 mathbf{v}mathbf{v}=mathbf{v}_c+mathbf{v}_1cos	heta+mathbf{v}_2sin	heta

然後我們將標準標架的基向量 (1,0,0)(0,1,0)(0,0,1) 作為 mathbf{v} 分別帶入上面的式子進行計算得到旋轉後的向量,並依次作為旋轉矩陣的列,這樣就能夠得到繞任意軸旋轉的變換矩陣了。

mathbf{v}=(0,1,0) 為例:

mathbf{v}_c=(a_x,a_y,a_z)((0,1,0)cdot(a_x,a_y,a_z))=(a_xa_y,a_y^2,a_ya_z)

mathbf{v}_1=(0,1,0)-(a_xa_y,a_y^2,a_ya_z)=(-a_xa_y,1-a_y^2,-a_ya_z)

mathbf{v}_2=(-a_xa_y,1-a_y^2,-a_ya_z)	imes(a_x,a_y,a_z)= left[egin{matrix} mathbf{i}&mathbf{j}&mathbf{k}\ -a_xa_y&1-a_y^2&-a_ya_z\ a_x&a_y&a_z\ end{matrix}
ight] = a_zmathbf{i}+0mathbf{j}+(-a_x)mathbf{k}=(a_z,0,-a_x)

egin{align} mathbf{v}&=(a_xa_y,a_y^2,a_ya_z)+(-a_xa_y,1-a_y^2,-a_ya_z)cos	heta+(a_z,0,-a_x)sin	heta\ &=(a_xa_y(1-cos	heta)+a_zsin	heta,a_y^2+(1-a_y^2)cos	heta,a_ya_z(1-cos	heta)-a_xsin	heta) end{align}

同理可以計算得到另外兩個基向量變換後的坐標。

最終得到繞任意旋轉的旋轉矩陣為:

mathbf{R}_a(	heta)= left[egin{matrix} a_x^2+(1-a_x^2)cos	heta&a_xa_y(1-cos	heta)+a_zsin	heta&a_xa_z(1-cos	heta)-a_ysin	heta&0\ a_xa_y(1-cos	heta)-a_zsin	heta&a_y^2+(1-a_y^2)cos	heta&a_ya_z(1-cos	heta)+a_xsin	heta&0\ a_xa_z(1-cos	heta)+a_ysin	heta&a_ya_z(1-cos	heta)-a_xsin	heta&a_z^2+(1-a_z^2)cos	heta&0\ 0&0&0&1 end{matrix}
ight]

不過PBRT中給出的這個示意圖的旋轉方向好像和前面繞軸旋轉給出的示意圖的旋轉方向是相反的:

所以為了統一,上面的旋轉矩陣應該寫成之前算出來矩陣的逆矩陣(事實上PBRT的實現里用的就是下面的矩陣):

mathbf{R}_a(	heta)= left[egin{matrix} a_x^2+(1-a_x^2)cos	heta&a_xa_y(1-cos	heta)-a_zsin	heta&a_xa_z(1-cos	heta)+a_ysin	heta&0\ a_xa_y(1-cos	heta)+a_zsin	heta&a_y^2+(1-a_y^2)cos	heta&a_ya_z(1-cos	heta)-a_xsin	heta&0\ a_xa_z(1-cos	heta)-a_ysin	heta&a_ya_z(1-cos	heta)+a_xsin	heta&a_z^2+(1-a_z^2)cos	heta&0\ 0&0&0&1 end{matrix}
ight]

推薦閱讀:

製作簡易碰撞體線框
[gdc18]farcry5的地形渲染技術
一篇光線追蹤的入門
多邊形的布爾運算-或 與 異或 減法
【GPU精粹與Shader編程】(三) 《GPU Gems 1》全書核心內容提煉總結 · 下篇

TAG:計算機圖形學 |