视图和模型变换
視圖變換,是指變換照相機的位置,角度。
模型變換,是指變換被照物體的位置,角度。
這兩個變換,都會影響最終圖形中,物體的位置,角度。而這兩個變換,可以達到相同的效果。比如,你想要一個倒著的水杯圖形,可以把你自己倒立,這樣看到的水杯就是倒立的了。或者把水杯倒立,自己直立,也能看到倒立的水杯。
如圖所示,這兩種變換,可以看做達到目的的不同途徑。甚至可以同時使用視圖變換和模型變換,只要最終拿到了我們想要的圖像就可以了。至于使用的是視圖變換,還是模型變換,看我們理解問題的角度。
3.2.1 對變換進行思考
變換順序,對最終的結(jié)果影響很大。
看下面的例子:
圖中有兩個操作,旋轉(zhuǎn)和移動。一個是沿原點繞z軸逆時針旋轉(zhuǎn)45度,另一個是沿x軸向下平移。左圖中,是先旋轉(zhuǎn),再移動,物體最終在x軸上。右圖中,是先移動,再旋轉(zhuǎn),物體最終在x=y軸上。變換順序不同,導(dǎo)致物體最終位置不同,這就是變換順序的影響。
變換順序,在OpenGL中的具體實現(xiàn)。
在OpenGL中,所有的變換,都是通過矩陣來實現(xiàn)的。一個矩陣,表示一個或多個變換。模型視圖變換,是通過模型視圖矩陣來實現(xiàn)的。由于這個矩陣經(jīng)常變換,需要進行管理,OpenGL中是通過矩陣堆棧來對矩陣進行管理的。
當前模型視圖矩陣如果用C來表示,在當前模型視圖基礎(chǔ)上,進行一個變換,這個變換使用的矩陣為M。那么一個頂點v的變換之后的坐標為CMv。也就是說,M變換先作用于頂點v,然后再是當前模型視圖矩陣C。
看下面的例子:
glMatrixMode(GL_MODELVIEW); glLoadIndentity(); glMultMatrixf(N); //變換N glMultMatrixf(M); //變換M glMultMatrixf(L); //變換L glBegin(GL_POINTS); glVertex3f(v); glEnd(); ?這段代碼中,模型視圖矩陣按順序分別包含了I, N, NM,最后是NML,其中I表示單位矩陣。經(jīng)過變換的頂點是NMLv。因此,頂點變換就是N(M(Lv)),也就是說,v首先與L相乘,Lv再與M相乘,MLv再與N相乘,而不是按它們指定的順序出現(xiàn)的。
全局固定坐標系
圖3-4中,左圖中的先旋轉(zhuǎn),再平移,代碼實現(xiàn)如下:
glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(T); //平移 glMultMatrixf(R); //旋轉(zhuǎn) draw_the_object();只要記住一點,物體的變換順序,和矩陣的出現(xiàn)順序,正好相反。
局部移動坐標系統(tǒng)
這個通常用于模型的關(guān)節(jié)控制。比如機器人手臂。比如畫汽車輪子上的螺釘,這個螺釘?shù)奈恢?#xff0c;相對于汽車輪子,這個輪子上建立的坐標系,叫局部移動坐標系。而輪子的位置,又是相對于汽車本身,最后,汽車本身,是在全局坐標系中指定。
3.2.2 模型變換
模型變換,主要涉及三個函數(shù),移動、旋轉(zhuǎn)、縮放。有了這三個函數(shù)的組合,我們可以進行任意變換。
void glTranslate{fd}(TYPE x, TYPE y, TYPE z); void glRotate{fd}(TYPE angle, TYPE x, TYPE y, TYPE z); void glScale{fd}(TYPE x, TYPE y, TYPE z); 這三個函數(shù),之前接觸過。glTranslate,進行平移,平移的偏移量,由(x, y, z)指定。 glRotate,旋轉(zhuǎn),以逆時針方向繞著從原點到點(x, y, z)的直線旋轉(zhuǎn)角度angle。glScale,按照一定比列進行縮放,比例在x軸,y軸,z軸方向上的量是(x, y, z)。3.2.3 視圖變換
視圖變換,相關(guān)的三個函數(shù)是glTranslate,glRotate和gluLookAt函數(shù)。
這個glTranslate和glRotate在模型變換中,我們已經(jīng)見過了。怎么模型變換和視圖變換,使用的是同樣的函數(shù)呢?因為變換是相對的。 比如,讓模型和照相機距離5個單位長度,假設(shè)模型和照相機放在一起。我們可以將物體向前移動5個單位長度,也可以將照相機向后移動5個單位長度。所以,視 圖變換,也是使用glTranslate和glRotate。只是這個參數(shù)的含義相反罷了。
比如
這個函數(shù)在場景中把物體沿z軸移動-5個單位,相當于把照相機沿z軸移動+5個單位。
使用工具函數(shù)gluLookAt()
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,GLdouble centerx, GLdouble centery, GLdouble centerz,GLdouble upx, GLdouble upy, GLdouble upz); 定義一個視圖矩陣,并把它與當前矩陣進行右乘。目標觀察點eyex, eyey, eyez。centerx, centery和centerz參數(shù)指定了視線上的任意一點。upx,upy和upz參數(shù)表示哪個方向是朝上的(也就是說,在視景體中自底向上的方向)。默認情況下,照相機位于原點,指向z軸的負方向,以y軸的正方向為朝上方向。相當于調(diào)用:
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0); 參考點的z值是-100.0, 但它也可以是任意的負值,因為它不會影響視線的方向。下面是使用gluLookAt的一個例子。
gluLookAt(4.0, 2.0, 1.0, 2.0, 4.0, -3.0, 2.0, 2.0, -1.0);
這個函數(shù),將攝像機移動到了(4.0, 2.0, 1.0)這個點,攝像機朝向(2.0, 4.0, -3.0)方向,攝像機向上的方向為(2.0, 2.0, -1.0)。
強烈推薦,理解這幾個函數(shù)(glTranslate, glRotate, gluLookAt),使用Nate Robin的教程。網(wǎng)上有下的。
創(chuàng)建自定義的工具函數(shù)
創(chuàng)建自定義的函數(shù),其實就是在自己的函數(shù)中,調(diào)用glTranslate和glRotate這兩個函數(shù)。
要創(chuàng)建自定義的工具函數(shù),主要是弄清楚兩個東西:一個是參數(shù)是相對于哪個坐標系的,第二個就是照相機的變換順序,與glTranslate,glRotate出現(xiàn)的順序相同。
比如編寫一個飛機模擬器,并且以飛機的駕駛員座位觀察點顯示飛機外面的景象。我們可以用一個圓點位于跑道上的坐標系統(tǒng)來描述整個場景,飛機相對于坐 標(x, y, z)。然后,假設(shè)飛機還有傾側(cè)角、螺旋角和航向改變角(這些都是飛機相對于它的重心的旋轉(zhuǎn)角度)。下面這個函數(shù)可以作用視圖變換函數(shù)使用。
void pilotView(GLdouble planex, GLdouble planey, GLdouble planez, GLdouble roll, GLdouble pitch, GLdouble heading) {glRotated(roll, 0.0, 0.0, 1.0); glRotated(pitch, 0.0, 1.0, 0.0); glRotated(heading, 1.0, 0.0, 0.0); glTranslated(-planex, -planey, -planez); } 這個其實很好理解,因為這個roll, pitch, heading,都是相對于飛機的。而飛機,就是我們的相機。所以,先將飛機旋轉(zhuǎn)到一定角度,然后移動到點(planex, planey, planez)上面。因為這個planex, planey, planez是相對于機場跑道的坐標系,而我們移動的飛機相當于相機,所以都要取負號。 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
- 上一篇: 梦到亲戚破产什么意思
- 下一篇: 梦到孩子生病了是什么征兆