投影矩陣的推導(dǎo)_第1頁
投影矩陣的推導(dǎo)_第2頁
投影矩陣的推導(dǎo)_第3頁
投影矩陣的推導(dǎo)_第4頁
投影矩陣的推導(dǎo)_第5頁
免費預(yù)覽已結(jié)束,剩余34頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、投影矩陣的推導(dǎo)(OpenGLD3D)OpenGL-巨陣推導(dǎo)一一模型視圖變化在三維編程中,模型視圖變換是從三維世界到二維屏幕中一個很重要的變換,但是這個變換往往很多人都不太理解,要么是事而非。而這方面的文章不是太少就是講的太淺沒有真正的理解模型視圖變換,本人在這個過程中曾經(jīng)走過很多歪路,不過好在最終在自己的不懈努力下終于降伏了這只猛虎。本人就以自己的理解,通過矩陣推導(dǎo)過程一步一步來了解模型視圖變化,最后通過兩個OpenGl的程序來進一步理解模型視圖矩陣。先從一個基本的模型視圖一透視投影變換講起。透射投影是將相機空間中的點從視錐體(frustum)變換到規(guī)則觀察體(CanonicalViewVol

2、ume以下簡稱CVV)中,待裁剪完畢后進行透視除法的行為。透視投影變換是令很多剛剛進入3D圖形領(lǐng)域的開發(fā)人員感到迷惑乃至神秘的一個圖形技術(shù)。其中的理解困難在于步驟繁瑣,對一些基礎(chǔ)知識過分依賴,一旦對它們中的任何地方感到陌生,立刻導(dǎo)致理解停止不前。主流的3DAPIs都把透射投影的具體細節(jié)進行了封裝,從而只需一個函數(shù)便可生成一個透射投影矩陣比如gluPerspective(),使得我們不需要了解其算法便可實現(xiàn)三維到二維的轉(zhuǎn)化,然而實事是,一些三維圖形或游戲開發(fā)人員遇到一些視圖矩陣的問題往往會不知所措,比如視景體裁剪。以下部分內(nèi)容是從別處那轉(zhuǎn)過來的,主要感謝Twinsen和一個叫丁歐南的高中生。,使

3、得透視投影變換是在齊次坐標下進行的,而齊次坐標本身就是一個令人迷惑的概念,這里我們先把它理解清楚。齊次坐標對于一個向量v以及基oabc,可以找到一組坐標(v1,v2,v3)v=v1a+v2b+v3c(1)而對于一個點p,則可以找到一組坐標(p1,p2,p3),使得p-o=p1a+p2b+p3c從上面對向量和點的表達,我們可以看出為了在坐標系中表示一個點(如p),我們把點的位置看作是對這個基的原點o所進行的一個位移,即一個向量p-o(有的書中把這樣的向量叫做位置向量一一起始于坐標原點的特殊向量),我們在表達這個向量的同時用等價的方式表達出了點p:p=o+p1a+p2b+p3c(3)(1)(3)是

4、坐標系下表達一個向量和點的不同表達方式。這里可以看出,雖然都是用代數(shù)分量的形式表達向量和點,但表達一個點比一個向量需要額外的信息。如果我寫出一個代數(shù)分量表達(1,4,7),誰知道它是個向量還是個點!我們現(xiàn)在把(1)(3)寫成矩陣的形式:(a,Kgo)k(a.btg,oj這里(a,b,c,o)是坐標基矩陣,右邊的列向量分別是向量v和點p在基下的坐標。這樣,向量和點在同一個基下就有了不同的表達:3D向量的第4個代數(shù)分量是0,而3D點的第4個代數(shù)分量是1。像這種這種用4個代數(shù)分量表示3D幾何概念的方式是一種齊次坐標表7K。“齊次坐標表示是計算機圖形學(xué)的重要手段之一,它既能夠用來明確區(qū)分向量和點,同時

5、也更易用于進行仿射(線性)幾何變換?!盕.S.Hill,JR這樣,上面的(1,4,7)如果寫成(1,4,7,0),它就是個向量;如果是(1,4,7,1),它就是個點。下面是如何在普通坐標(OrdinaryCoordinate)和齊次坐標(HomogeneousCoordinate)之間進行轉(zhuǎn)換:從普通坐標轉(zhuǎn)換成齊次坐標時,如果(x,y,z)是個點,則變?yōu)?x,y,z,1);如果(x,y,z)是個向量,則變?yōu)?x,y,z,0)從齊次坐標轉(zhuǎn)換成普通坐標時,如果是(x,y,z,1),則知道它是個點,變成(x,y,z);如果是(x,y,z,0),則知道它是個向量,仍然變成(x,y,z)以上是通過齊次坐

6、標來區(qū)分向量和點的方式。從中可以思考得知,對于平移T、旋轉(zhuǎn)R縮放S這3個最常見的仿射變換,平移變換只對于點才有意義,因為普通向量沒有位置概念,只有大小和方向,這可以通過下面的式子清楚地看出:TTT1oO1OO1oO而旋轉(zhuǎn)和縮放對于向量和點都有意義,你可以用類似上面齊次表示來檢測。從中可以看出,齊次坐標用于仿射變換非常方便。此外,對于一個普通坐標的點P=(Px,Py,Pz),有對應(yīng)的一族齊次坐標(wPx,wPy,wPz,w),其中w不等于零。比如,P(1,4,7)的齊次坐標有(1,4,7,1)、(2,8,14,2)、(-0.1,-0.4,-0.7,-0.1)等等。因此,如果把一個點從普通坐標變成

7、齊次坐標,給x,y,z乘上同一個非零數(shù)w,然后增加第4個分量w;如果把一個齊次坐標轉(zhuǎn)換成普通坐標,把前三個坐標同時除以第4個坐標,然后去掉第4個分量。由于齊次坐標使用了4個分量來表達3D概念,使得平移變換可以使用矩陣進行,從而如F.S.Hill,JR所說,仿射(線性)變換的進行更加方便。由于圖形硬件已經(jīng)普遍地支持齊次坐標與矩陣乘法,因此更加促進了齊次坐標使用,使得它似乎成為圖形學(xué)中的一個標準。簡單的線性插值線性插值我舉的是丁歐南的溫度計的例子:已知有一破溫度計(何以謂破?刻度之間間距雖平均,但間距或大于或小于標準值,謂之破),當(dāng)其插入00c水里時顯示為50C,當(dāng)其插入1000c的沸水中時顯示為

8、900C,問:當(dāng)實際水溫為500C時此破溫度計顯示的值是多少?解:因刻度均勻,所以刻度之間的比例與好溫度計相同,由此:設(shè)顯示的數(shù)為T,(90-T)/(T-5)=(100-50)/(50-0)解出T=47.5C.結(jié)論:由一個數(shù)域(如題目中的好溫度計兩個端點0,100)映射到另一個數(shù)域(如題目中的破溫度計的兩個端點5,90)時,如果兩個數(shù)域都是線性(就如題目中暗示的刻度平均),那么它們對應(yīng)點成比例(比如50和47.5這一對端點).這道題的應(yīng)用是把一組坐標映射到另一個范圍,這將在介紹NDC(NormalizedDeviceCoordinate,歸一化的設(shè)備坐標)時用到.透視投影變換好,有了上面兩個理

9、論知識,我們開始分析這次的主角一一透視投影變換。這里我們選擇OpenGL勺透視投影變換進行分析,其他的APIs會存在一些差異,但主體思想是相似的,可以類似地推導(dǎo)。經(jīng)過相機矩陣的變換,頂點被變換到了相機空間。這個時候的多邊形也許會被視錐體裁剪,但在這個不規(guī)則的體中進行裁剪并非那么容易的事情,所以經(jīng)過圖形學(xué)前輩們的精心分析,裁剪被安排到規(guī)則觀察體(CanonicalViewVolume,CVV)中進行,CVVCVV是一個正方體,x,y,z的范圍都是-1,1,多邊形裁剪就是用這個規(guī)則體完成的。所以,事實上是透視投影變換由兩步組成:1)用透視變換矩陣把頂點從視錐體中變換到裁剪空間的2)CVV裁剪完成后

10、進行透視除法(一會進行解釋)。透視投影變換我們一步一步來,我們先從一個方向考察投影關(guān)系。上圖是右手坐標系中頂點在相機空間中的情形。設(shè)P(x,z)是經(jīng)過相機變換之后的點,視錐體由eye眼睛位置,np近裁剪平面,fp遠裁剪平面組成。N是眼睛到近裁剪平面的距離,F是眼睛到遠裁剪平面的距離。投影面可以選擇任何平行于近裁剪平面的平面,這里我們選擇近裁剪平面作為投影平面。設(shè)P(x,z)是投影之后的點,則有z=-No通過相似三角形性質(zhì),我們有關(guān)系:同理,有*yy=W-這樣,我們便得到了P投影后的點Pp*=(-N-N-K)從上面可以看出,投影的結(jié)果z始終等于-N,在投影面上。實際上,z對于投影后的P已經(jīng)沒有意

11、義了,這個信息點已經(jīng)沒用了。但對于3D圖形管線來說,為了便于進行后面的片元操作,例如z緩沖消隱算法,有必要把投影之前的z保存下來,方便后面使用。因此,我們利用這個沒用的信息點存儲z,處理成:這個形式最大化地使用了3個信息點,達到了最原始的投影變換的目的,但是它太直白了,有一點蠻干的意味,我感覺我們最終的結(jié)果不應(yīng)該是它,你說呢?我們開始結(jié)合CVV進行思考,把它寫得在數(shù)學(xué)上更優(yōu)雅一致,更易于程序處理。假入能夠把上面寫成這個形式:那么我們就可以非常方便的用矩陣以及齊次坐標理論來表達投影變換:oobOsdt一一oHoOH&oO齊快坐標變普通坐標/-lix/z-(az*b)/z其中哈,看到了齊次坐標的使

12、用,這對于你來說已經(jīng)不陌生了吧?這個新的形式不僅達到了上面原始投影變換的目的,而且使用了齊/NxNyaz+b次坐標理論,使得處理更加規(guī)范化。注意在把Vz/變成-Ny/s-(az+b)/zI-1,的一步我們是使用齊次坐標變普通坐標的規(guī)則完成的。這一步在透視投影過程中稱為透視除法(PerspectiveDivision),這是透視投影變換的第2步,經(jīng)過這一步,就丟棄了原始的z值(得到了CVV中對應(yīng)的z值,后面解釋),頂點才算完成了投影。而在這兩步之間的就是CVV裁剪過程,所以裁剪*az+bj空間使用的是齊次坐標工/,主要原因在于透視除法會損失一些必要的信息(如原始z,第4個-z保留的)從而使裁剪變

13、得更加難以處理,這里我們不討論CVV裁剪的細節(jié),只關(guān)注透視投影變換的兩步。Nooo陣矩oobOooa1-oNoo就是我們投影矩陣的第一個版本。你一定會問為什么要把z寫成口匕十匕有兩個原因:1)P的3個代數(shù)分量統(tǒng)一地除以分母-z,易于使用齊次坐標變?yōu)槠胀ㄗ鴺藖硗瓿桑沟锰幚砀右恢?、高效?)后面的CVV是一個x,y,z的范圍都為卜1,1的規(guī)則體,便于進行多邊形裁剪。而我們可以適當(dāng)?shù)倪x擇系數(shù)a和b,使得ar+bW這個式子在z=-N的時候值為-1,而在z=-F的時候值為1,從而在z方向上構(gòu)建CVV接下來我們就求出a和b:這樣我們就得到了透視投影矩陣的第一個版本:oNoOoo、QQab-10i吁N3

14、2FNF-M投塞矩陣爐臺1使用這個版本的透視投影矩陣可以從z方向上構(gòu)建CVV但是X和y方向仍然沒有限制在-1,1中,我們的透視投影矩陣的下一個版本就要解決這個問題。為了能在x和y方向把頂點從Frustum情形變成CVV情形,我們開始對x和y進行處理。先來觀察我們目前得到的最終變換結(jié)果:/Nx/z-liy/z-(az+b)/zI我們知道-Nx/z的有效范圍是投影平面的左邊界值(記為left)和右邊界值(記為right),即left,right,-Ny/z則為bottom,top。而現(xiàn)在我們想把-Nx/z屬于left,right映射到x屬于-1,1中,-Ny/z屬于bottom,top映射到y(tǒng)屬于

15、-1,1中。你想到了什么?哈,就是我們簡單的線性插值,你都已經(jīng)掌握了!我們解決掉它:f-leftxIyright-lefti-(-1)|tottomy-(-1)ttop-bottomi-r2Nx/righi+left/right-leftTight-leftA2Ny/一工top十bottom1y=Itcp-buttontp-bottom則我們得到了最終的投影點:2Nx/一工rislit十Leftright一leftright-lefttop+hottomtop-bottomtop-hottojn-(az+b)/z卜面要做的就是從這個新形式出發(fā)反推出下一個版本的透視投/NxI3經(jīng)過透視除法的形式

16、,而PIaz+b影矩陣。注意到是卜工只變化了x和y分量的形式,az+b和-z是不變的,則我們做透視除法的逆處理一一給P每個分量乘上-z,得到t(?p-再top-bottQin而這個結(jié)果又是這么來的:則我們最終得到:F7a_一F7-2FMb-zzr-上面是一般情況,我們要把它變成特殊性版本,即gluPerspective,它是一種左右對稱的投影形式,因此我們從對x和y進行插值的那一步來看:那一步來看:i-b1-(-1)It-bi-b22銷掉兩邊的1/2,得至U:則我們反推出透視投影矩陣:-2NQ就I)式一3)02+8L1其中2必、(2NZ第【2妁_0i-h儂+占002Ni-b00夕+朋尸一N2N

17、FF二西這就是gluPerspective的投影矩陣了。結(jié)論和用法:相機空間中的頂點,如果在視錐體中,則變換后就在CVV中。如果在視錐體外,變換后就在CVV外。而CVV本身的規(guī)則性對于多邊形的裁剪很有利。OpenG用構(gòu)建透視投影矩陣的時候就使用了M的形式。注意到M的最后一行不是(0001)而是(00-10),因此可以看出透視變換不是一種仿射變換,它是非線性的。另外一點你可能已經(jīng)想到,對于投影面來說,它的寬和高大多數(shù)情況下不同,即寬高比不為1,比如640/480。而CVV的寬高是相同的,即寬高比永遠是1。這就造成了多邊形的失真現(xiàn)象,比如一個投影面上的正方形在CVV的面上可能變成了一個長方形。解決

18、這個問題的方法就是在對多變形進行透視變換、裁剪、透視除法之后,在歸一化的設(shè)備坐標(NormalizedDeviceCoordinates)上進行的視口(viewport)變換中進行校正,它會把歸一化的頂點之間按照和投影面上相同的比例變換到視口中,從而解除透視投影變換帶來的失真現(xiàn)象。進行校正前提就是要使投影平面的寬高比和視口的寬高比相同。而r-l和t-b可以分別看作是投影平面的寬w和高ho如果我們不知道right、left、top以及bottom這幾個參量,也可以根據(jù)視野(FOV-FieldOfView)參量來求得。下面是兩個平面的視野關(guān)系圖:Ldill-C01-=2改*2訓(xùn)二戶一/2M+為TI

19、2cot-一些2同理=COt2其中h22M尤%.=cott-b2h=2M血”2其中,兩個fov分別是在x-z以及y-z平面上的視野。如果只給了一個視野,也可以通過投影平面的寬高比計算出來:aspect_ratioh=x=力xaspsel_尸”比5或者,w=/=-aspect_產(chǎn)痕聲用一個視野算出w或者h,然后用寬高比算出h或者w我們可以通過一個例子來證明我們矩陣的正確性:voidOpenGlCom:ReSize()(RECTrct;GetClientRect(m_Hwnd,&rct);intm_view_width=rct.right-rct.left;intm_view_height=rct

20、.bottom-rct.top;glViewport(0,0,m_view_width,m_view_height);floatnearz=5.0;floatfarz=80000;floatAspectRatio=float(m_view_height)/float(m_view_width);floatViewAngleH=90*(PI/180);/90度floatViewAngleV=atan(tan(ViewAngleH/2)*AspectRatio)*2;glMatrixMode(GL_PROJECTION);glLoadIdentity();GLfloatm16;二ZeroMemor

21、y(m,16*sizeof(float);/m8,m9=0表示對稱視椎體即gluPerspective/m0=1.0/tan(ViewAngleV/2);m5=m0*AspectRatio;m10=-(farz+nearz)/(farz-nearz);m11=-1;m14=-2*farz*nearz/(farz-nearz);glMultMatrixf(m);glMatrixMode(GL_MODELVIEW);glLoadIdentity();)voidOpenGlCom:draw()(glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glMa

22、trixMode(GL_MODELVIEW);glLoadIdentity();glPushMatrix();glDepthFunc(GL_LEQUAL);glEnable(GL_DEPTH_TEST);glBegin(GL_TRIANGLE_FAN);glTranslatef(0,0,10.0f);/往視點方向平移10單位顯示更大glColor3f(0.8f,0.8f,0.6f);glVertex3f(0,0,-20);glVertex3f(30,20,-40);glVertex3f(40,10,-30);glPopMatrix();我們看看在gluPerspective圖形有什么變化呢將R

23、eSize()改成:(RECTrct;GetClientRect(m_Hwnd,&rct);intm_view_width=rct.right-rct.left;intm_view_height=rct.bottom-rct.top;glViewport(0,0,m_view_width,m_view_height);glMatrixMode(GL_PROJECTION);glLoadIdentity();floatfAspect=float(m_view_width)/float(m_view_height);gluPerspective(90.0,fAspect,5.0,80000.0);

24、glMatrixMode(GL_MODELVIEW);glLoadIdentity();接下來,再試試看glFrustum()實現(xiàn)的效果:將ReSize()改成:RECTrct;GetClientRect(m_Hwnd,&rct);intm_view_width=rct.right-rct.left;intm_view_height=rct.bottom-rct.top;glViewport(0,0,m_view_width,m_view_height);glMatrixMode(GL_PROJECTION);glLoadIdentity();GLdoubleleft=-nearz*tan(ViewAngleV/2);GLdoubleright=nearz*tan(ViewAngleV/2);GLdoublebottom=-nearz*tan(ViewAngleH/2);GLdoubletop=nearz*tan(ViewAngleH/2);glFrustum(left,ri

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論