前言(Preface)
前段時間有些朋友在論壇裡問到一些關於3D數學的知識,就想為大家寫點這方面的文章。由於之前比較忙,又遇到過春節,所以最近才著筆寫了這篇文章,希望大家喜歡。這些內容主要是一些理論知識,看上去難免有些枯燥,之後的文章我會加入一些實例進行講解的。如果內容存在錯誤和不全,就請你來更正和添加了。
三維坐標系(3D Coordinate System)
三維坐標是把二維的平面坐標推廣到三維空間中,在三維坐標中,點(x,y,z)的齊次坐標為(nx,ny,nz,n),其中n為任意不為0的數,規范化的齊次坐標為(x,y,z,1),與之相對應,三維變換的變換矩陣為4×4矩陣。
在三維空間中,我們通常使用右手坐標系(Right-Handed Coordinate System),因為它符合數學上的習慣,而在計算機圖形學中,我們會使用左手坐標系(Left-Handed Coordinate System),因為它比較符合日常習慣。其實,我們可以任意的旋轉這些坐標系,而圖形仍然保持不變。常見的坐標系如下:
屏幕坐標系:相對於顯示器的原點的2D坐標系
本地坐標系:相對於對象的原點的3D坐標系
世界坐標系:相對於3D世界的原點三維坐標系
對齊(視點)坐標系:世界坐標系的變換,觀察者的位置在世界坐標系的原點。
點(Point)
點是在某一個坐標系中使用坐標值指定的位置。因此,點到坐標原點之間的距離與坐標系的選擇有關。點P在坐標系A中的坐標為(0,0,0),而在坐標系B中的坐標則為(x,y,z)。
向量(Vector)
向量是指兩點的差值,具有大小和方向,即給定兩點,就能唯一確定一個向量,向量的大小和方向與坐標系的選擇無關。向量V=(Vx,Vy,Vz)=P1P2=(x2-x1,y2-y1,z2-z1)其中,Vx,Vy和Vz分別為向量V在x,y和z軸上的投影,稱為向量V的x分量(x component),y分量(y component)和z分量(z component)。該向量的大小為:
向量V與x,y和z軸形成的方向角(Direction Angle):α,β和γ,其中cosα,cosβ和cosγ稱為方向余弦(Direction Cosine)。
向量加法:V1+V2=(V1x+V2x,V1y+V2y,V1z+V2z)
向量標量乘:aA=(aVx,aVy,aVz)
向量標量積:V1·V2= V1x+V2x,V1y+V2y,V1z+V2z
向量積(叉積):V1×V2=(V1yV2z-V1zV1y,V1zV2x-V1xV2z,V1xV2y-V1yV2z)
=|Ux Uy Uz|
|V1x V1y V1z|
|V2x V2y V2z|
注:其中Ux,Uy,Uz分別表示沿x軸,y軸和z軸的單位向量。在以後的編程中,我們經常會用到向量積。
矩陣(Matrix)
矩陣是由若干個數值構成的矩形陣列,這些數值通常為實數,稱為矩陣的元素。如果一個矩陣的行和列數相同,我們則稱該矩陣為方陣(Square Matrix),而只有一行或者一列的矩陣用常用向量表示,例如:[x,y,z]稱為行向量(Row Vector),
|x|
|y| 則稱為列向量(Colume Vector)。
|z|
矩陣加法:|A
|A
|A
矩陣標量乘: |A
n|A
|A
矩陣的乘:
矩陣變換(Matrix Transform)
三維平移的矩陣表示為:
[x`,y`,z`,1]=[x,y,z,1] | 1 0 0 0 |
| 0 1 0 0 |
| 0 0 1 0 |
| tx ty tz 1 |
三維縮放的矩陣表示為:
[x`,y`,z`,1]=[x,y,z,1] | sz 0 0 0 |
| 0 sy 0 0 |
| 0 0 sx 0 |
| 0 0 0 1 |
繞x軸旋轉的矩陣表示為:
[x`,y`,z`,1]=[x,y,z,1] | 1 0 0 0 |
| 0 cosα sinα 0 |
| 0 -sinα cosα 0 |
| 0 0 0 1 |
繞y軸旋轉的矩陣表示為:
[x`,y`,z`,1]=[x,y,z,1] | cosα 0 -sinα 0 |
| 0 1 0 0 |
| sinα 0 cosα 0 |
| 0 0 0 1 |
繞z軸旋轉的矩陣表示為:
[x`,y`,z`,1]=[x,y,z,1] | cosα sinα 0 0 |
| -sinα cosα 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
反射(Reflection)
反射變換也稱為對稱(Symmetric)變換或鏡像(Mirror Image)變換,三維反射變換可以相對於反射軸(Reflection Axis)進行,也可以相對於反射平面進行。相對於反射軸的三維反射變換是通過將圖形繞反射軸旋轉180°來實現的。
相對於xy平面的反射變換矩陣為:
| 1 0 0 0 |
| 0 1 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
相對於yz平面的反射變換矩陣為:
|-1 0 0 0 |
| 0 1 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
相對於zx平面的反射變換矩陣為:
| 1 0 0 0 |
| 0 -1 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
錯切(Shear)
錯切變換會改變圖形的形狀。
相對於x軸的錯切變換矩陣為:
| 1 0 0 0 |
| shY 1 0 0 |
| shz 0 1 0 |
| 0 0 0 1 |
相對於y軸的錯切變換矩陣為:
| 1 shX 0 0 |
| 0 1 0 0 |
| 0 shz 1 0 |
| 0 0 0 1 |
相對於z軸的錯切變換矩陣為:
| 1 0 shX 0 |
| 0 1 shY 0 |
| 0 0 1 0 |
| 0 0 0 1 |
從簡單的平移、縮放和旋轉等可以延伸到復合平移、復合縮放、復合旋轉、固定點縮放等概念,這些就要靠讀者自己查閱資料了,在這裡我就不多講了。
三維轉換(3D Transform)
最常見的轉換有以下三種類型:
1、世界坐標系轉換:通過這種轉換方式,可以改變3D物體的位置、大小、角度等等。就是改變3D世界中的物體位置相關的特性;
2、透視轉換:透視轉換決定了三維場景如何透視到二維平面上。包括觀察三維世界攝象機鏡頭的觀察范圍等屬性;
3、觀察坐標系轉換:這種轉換方式決定了三維世界中觀察者的位置,觀察方向等屬性。
投影變換(Projection Transformation)
投影變換就是將維數為n的點變換成維數小於n的點。我們會用到的就是將三維空間中的點變換成二維平面上的點。要對三維物體進行投影變換,首先要在三維空間中選擇一個點,稱為投影中心(Center of Projection);再定義一個不經過投影中心的平面,稱為投影平面(Projection Plane);從投影中心向物體的沒一點引射線,這些射線稱為投影線(Projection Ray),投影線與投影平面的交點集合就稱為三維物體在二維投影平面上的投影。
投影可以分為兩大類,即透視投影(Perspective Projection)和平行投影(Parallel Projection);如果投影中心到投影平面的距離是有限的,那麼投影線是從投影中心發出的無數條射線,這種投影稱為透視投影;如果投影中心到投影平面的距離越來越遠,那麼投影線就越來越趨於平行,當投影中心到投影平面的距離為無窮遠的時候,投影線為一組平行線,這種投影稱為平行投影。
透視投影(Perspective Projection)
設投影中心為PC(XC,YC,ZC),投影平面為Z=ZP平面(ZP≠ZC),即投影平面平行與xy平面(垂直於z軸)並且不經過投影中心,三維空間中的點P(x,y,z)在投影平面上的透視投影為點PP(XP,YP,ZP)。
則透視投影矩陣為:
|ZP-ZC 0 XC -XCZP |
| 0 ZP-ZC YC -YCZP |
| 0 0 ZP -ZCZP |
| 0 0 1 -ZC |
如果投影中心PC在坐標原點,投影平面仍然是Z=ZP平面,即XC=YC=ZC=0,那麼透視投影矩陣變成:
| 1 0 0 0 |
| 0 1 0 0 |
| 0 0 1 0 |
| 0 0 1/zP 0 |
如果投影中心PC在z軸上,投影平面是xy平面,即XC=YC=0,那麼透視投影矩陣變成:
| 1 0 0 0 |
| 0 1 0 0 |
| 0 0 0 0 |
| 0 0 -1/zP 1 |
對於三維空間中任意一組平行線來說,如果它們平行於投影平面,那麼它們的透視投影仍然保持平行;如果他們不平行於投影平面,那麼它們的透視投影不再保持平行,並且會匯聚到一個點,該點稱為滅點(Vanishing Point);平行於坐標軸的一組平行線形成的滅點稱為主滅點(Principal Vanishing Point)或軸滅點(Axis Vanishing Point)。透視投影的主滅點的數目等於與投影平面相交的坐標軸的數目,而三維空間中的任意投影平面最少與一個坐標軸相交,最多與x,y,z三個坐標軸都相交,所以主滅點的數目最少為1個,最多為3個。根據主滅點的數目,我們可以將透視投影分為三類,即一點透視、二點透視和三點透視。
如果投影平面只與一個坐標軸相交,與另外兩個坐標軸平行,那麼透視投影只形成一個主滅點,稱為一點透視。
如果投影平面與兩個坐標軸相交,與剩下的一個坐標軸平行,那麼透視投影形成兩個主滅點,稱為二點透視。二點透視比一點透視具有更強的真實感,被廣泛地應用於建築、工程、廣告等領域。
平行投影(Parallel Projection)
根據投影方向的不同,我們可以把平行投影分為兩類:如果投影方向與投影平面垂直,既投影方向與投影平面法向量的方向相同,那麼這種投影稱為正平行投影(Orthographic Parallel Projection),簡稱為正投影;如果投影方向與投影平面斜交,那麼這種投影稱為斜平行投影(Ohlique Parallel Projection),簡稱為斜投影。
1、 正投影
正投影經常用於產生物體的三視圖。因為三視圖能准確地反映物體的長度和角度。三視圖是指投影方向分別取作x軸、y軸和z軸方向,投影平面分別垂直於x軸、y軸和z軸事的正投影,產生的視圖分別成為前視圖(Front VIEw)、側視圖(Side VIEw)和頂視圖(Top VIEw)。產生三視圖的投影矩陣分別為:
Mfront= | 0 0 0 0 |
| 0 1 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
Mside= | 1 0 0 0 |
| 0 0 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
Mtop= | 1 0 0 0 |
| 0 1 0 0 |
| 0 0 0 0 |
| 0 0 0 1 |
當投影方向不取坐標軸方向,投影平面不垂直於坐標軸時,產生的正投影稱為軸測正投影(Axonometric Orthographic Projection)。軸測正投影又分為正等測(Isimetric Projection)、正二測和正三測三種。當投影平面與三個坐標軸的交點到坐標原點的距離都相等時為正等測,也稱為等軸測;當投影平面與兩個坐標軸的交點到坐標原點的距離相等時為正二測;當投影平面與三個坐標軸的交點到坐標原點的距離都不相等時為正三測。
在這三種軸測正投影中,正等測應用最為廣泛。由於正等測的投影平面與三個坐標軸的焦點到坐標原點的距離都相等,因此投影方向(即投影平面的法向量)與三個坐標軸的夾角也相等。
2、 斜投影
投影方向與投影平面斜交的平行投影稱為斜投影。假設投影平面為Z=ZP平面,投影方向為(XD,YD,ZD)(ZD≠0),三維空間中的點P(x,y,z)在投影平面上的斜投影為點PP(xP,yP,zP)。則斜投影矩陣為:
| ZD 0 -XD XDZP |
| 0 ZD -YD YDZP |
| 0 0 0 ZDZP |
| 0 0 0 ZD |
如果投影平面為z=0平面,即ZP=0,那麼斜投影矩陣變成:
| 1 0 -XD/ZD 0 |
| 0 1 -YD/ZD 0 |
| 0 0 0 0 |
| 0 0 0 1 |
總結(Conclusion)
上面所提到的知識,都是我們平時編程時經常會用到的,可能還有些知識沒提到,只好靠自己翻翻線形代數書了。如果對上面知識有什麼不懂的和錯誤的,可以跟我討論。如果你有基礎知識,把這些理論用於實踐應該是很輕松的事,如果你沒有基礎知識,也沒什麼大不了的,可以先看看關於OpenGL的書入門。這樣上手會快一些。另外,上面的內存可能存在一些格式問題,請大家諒解。