青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

doing5552

記錄每日點滴,不枉人生一世

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  73 Posts :: 0 Stories :: 94 Comments :: 0 Trackbacks

公告

常用鏈接

留言簿(24)

我參與的團隊

最新隨筆

搜索

  •  

積分與排名

  • 積分 - 455849
  • 排名 - 49

最新隨筆

最新評論

閱讀排行榜

評論排行榜

亂彈OpenGL中的矩陣變換(上)


在前面的日志(Shadow Volume 陰影錐技術之探Ⅲ )中,自己稍微提及了NEHE的"3D矩陣求逆"方法之高,并談了談自己的一點拙略理解。呵呵,然后,既然如此,一不做二不休,在本篇中得繼續亂彈一下下,關于OpenGL矩陣的理解。因為我實在不知道會不會在哪兒就把你忽悠+誤導了(但還是期盼你的信任),請看官自重哈哈。
這里有一句,我認為,最能夠消解頭腦中的云霧的話:OpenGL中所有的變換,都是在變換坐標系。
你還好嗎?你還能看見你眼前書桌上那個蘋果嗎?你把它向右邊移動10厘米看看?移好了嗎?想一想,假如你眼前就是OpenGL的一個渲染窗口的話,蘋果是不是往x軸正方向移動了10單位(假設單位:厘米)?恩,你現在所感受到的真實告訴你:蘋果確實不再在原位置,而是向右移了10厘米到了一個新的位置。我想說的是,當你完全邁進3D圖形學殿堂后,請不要再那么輕易相信的眼睛所感受到的真實——它是真實,但不是真實的全部。在你剛才一瞬間想象出的OpenGL渲染窗口里,蘋果沒有移動,它一直在那里,一直....而移動的是整個空間,整個世界,包括書桌,包括你,包括你的眼睛!
在OpenGL的那個世界中,最初存在著幾個重疊的空間。有模型空間,有世界空間,視圖空間,屏幕空間等。每個空間實質就是一個坐標系(統)——坐標系統當然就有坐標軸。在最初的這個時刻,也許整個OpenGL世界也就只有這一套坐標軸了:恩,一套。世界永遠只有一個,但是依附于這個世界的空間則平行地同時存在——實體(例如坐標軸,蘋果)唯一,而實體的表示(各個空間中對應的坐標軸,蘋果)則多樣。我是這么理解的,OpenGL世界。
最初的OpenGL世界只有一套看不見的坐標軸,然后,用戶說:蘋果!于是世上就有了蘋果。蘋果輕輕地出現在映射著這個世界的各個空間中——就在那個萬物之源的坐標原點上。原點與蘋果的“中心”對應(當然“中心”不一定指蘋果中間,它由上帝...不,用戶在制造這個蘋果時決定。確切地說,我們在畫物件(或者直接叫:模型)時給予這些東西的各個glVertex3頂點(坐標x,y,z),它們的存在必然以位置(0,0,0)為標尺——這個位置就是此物件的“中心”)。就在蘋果出現的此瞬間,模型空間(Model-Coordination,也稱Local-Corrdination)安靜了,此刻的整個世界的一切如同屏幕截圖般被保存起來,儲存在模型空間——永遠以當前這個“中心”為原點,以當前這些坐標(x,y,z)為蘋果各頂點的"模型坐標系坐標"。
 
//1.用戶創世第1天,說:蘋果! 世上便有了蘋果---蘋果在模型空間(local 空間)被永恒描述
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}
//1.用戶創世第1天,說:蘋果! 世上便有了蘋果---蘋果在模型空間(local 空間)被永恒描述
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}

當然,蘋果出現在模型空間坐標系統原點,必然也就出現在其他空間坐標系統的原點,此時各空間的坐標系是重合的,只不過模型空間被固定了,其他空間還沒而已。蘋果怎么移動到別處呢?恩,編程的時候可以這么問,但當你正在了解OpenGL世界的時候(如現在),這個問法很不靠譜。你看上面的代碼(glVertex3f(A); glVertex3f(B)....)這里點A,B...不是給定了嗎?就算是變量,在“畫點”的時刻變量的值也是給定的呀。是的,變的不該是蘋果,而是坐標系,準確地理解,是世界空間(World-Coordination)的那個坐標系要變,在原先與模型空間坐標系重合的基礎上變。這個變的過程,叫模型變換(Model-Translation)。具體來說就是用一個表示“轉動/移動/縮放”的矩陣左乘蘋果的各個頂點坐標,得出的結果(是一些不同的坐標)作為蘋果對應頂點在世界空間坐標系中的位置坐標。誒?蘋果變了嗎?可以這么說,蘋果的“坐標”還是原來那些A.B...但對應于世界坐標系的“位置”變化了。
這里確實是很容易迷糊,默念吧:OpenGL中所有的變換,都是在變換坐標系。不是蘋果右移了10厘米,而是世界坐標系左移了10厘米!假設蘋果中心最初恰就是出現在模型空間并與模型坐標系原點重合,然后考慮以此為初狀態的世界空間,在用戶做了模型變換(向蘋果中心點所在之坐標(0,0,0),左乘一個表示右移10厘米的模型變換矩陣)后,這個坐標由(0,0,0)變成(10,0,0),相當于坐標系原來的虛擬坐標(10,0,0)變成現在的(0,0,0)。看,坐標系(由無限的虛擬坐標構成)左移10厘米!我想說,這才是模型變換(Model-Translation)的真正所為。與之前一樣,當一切變換完成,結果被截屏存入世界空間。世界空間的動蕩結束,從此定型。
 
//2.用戶創世第2天,說:蘋果右移! 于是世界坐標系便左移了,結果存入世界空間
glMatrixMode(GL_MODEL);//表示接下來要作“模型轉換”
glTranslatef(10,0,0);//相當于一個平移矩陣
 
//1.用戶創世第1天,說:蘋果! 世上便有了蘋果---蘋果在模型空間(local 空間)被永恒描述 
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}
//2.用戶創世第2天,說:蘋果右移! 于是世界坐標系便左移了,結果存入世界空間
glMatrixMode(GL_MODEL);//表示接下來要作“模型轉換”
glTranslatef(10,0,0);//相當于一個平移矩陣

//1.用戶創世第1天,說:蘋果! 世上便有了蘋果---蘋果在模型空間(local 空間)被永恒描述
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}
接下來發生的事情跟之前一樣,只是從模型空間---(模型變換)---》世界空間的關系,改成世界空間---(視圖變換 View Translation)---》視圖空間的關系而已。請好好再模擬一次:一模一樣的過程,這次的移動所需要的左乘矩陣(左乘剛才保存的模型轉換結果嘛)由相機(眼睛,視線)的設置提供,結果存入視圖空間而已。
 
//3.用戶創世第3天,說:我是主角! 于是他擁有了第一人稱視覺,結果存視圖空間
glMatrixMode(GL_VIEW);//表示接下來要作“視圖轉換” 
gluLookat(eye,look,up)//也相當于一個平移矩陣 
 
//2.用戶創世第2天,說:蘋果右移! 于是世界坐標系便左移了,結果存入世界空間 
glMatrixMode(GL_MODEL);//表示接下來要作“模型轉換” 
glTranslatef(10,0,0);//相當于一個平移矩陣 
 
//1.用戶創世第1天,說:蘋果! 世上便有了蘋果---蘋果在模型空間(local 空間)被永恒描述  
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}
//3.用戶創世第3天,說:我是主角! 于是他擁有了第一人稱視覺,結果存視圖空間
glMatrixMode(GL_VIEW);//表示接下來要作“視圖轉換”
gluLookat(eye,look,up)//也相當于一個平移矩陣

//2.用戶創世第2天,說:蘋果右移! 于是世界坐標系便左移了,結果存入世界空間
glMatrixMode(GL_MODEL);//表示接下來要作“模型轉換”
glTranslatef(10,0,0);//相當于一個平移矩陣

//1.用戶創世第1天,說:蘋果! 世上便有了蘋果---蘋果在模型空間(local 空間)被永恒描述 
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}
噢,接下來是:視圖空間---(投影變換)---》屏幕空間。投影變換的變換手法與之前的不同,屏幕空間以視圖空間結果為基礎,先用一個平頭錐體(視景錐)把視線范圍外的空間割了(裁剪),再把投影到一個可以覆蓋渲染屏幕窗口的矩形上(具體做法是,XYZ除以隱含的齊次坐標W,然后舍棄深度Z),保存為屏幕空間——一個平面,讓用戶所能感悟到這一切不過顯示器屏幕一部分像素的把戲。當然,最后的坐標還要隱映射為渲染窗口的客戶區坐標(原點在窗口左上角,Y軸下X軸右的平面坐標),算是走出了OPENGL世界。
 
//4.用戶創世第4天,說:到顯示屏來吧! 世界便是"平"的了.最后得屏幕空間
glViewport(0,0,width,height);//設置那個"視景區矩形"大小
glMatrixMode(GL_PROJECTION));//表示接下來要作“投影轉換” 
gluPerspective(fov,aspect,near,far);//視景體應用
 
//3.用戶創世第3天,說:我是主角! 于是他擁有了第一人稱視覺,結果存視圖空間 
glMatrixMode(GL_VIEW);//表示接下來要作“視圖轉換”  
gluLookat(eye,look,up)//也相當于一個平移矩陣  
 
//2.用戶創世第2天,說:蘋果右移! 于是世界坐標系便左移了,結果存入世界空間  
glMatrixMode(GL_MODEL);//表示接下來要作“模型轉換”  
glTranslatef(10,0,0);//相當于一個平移矩陣  
 
//1.用戶創世第1天,說:蘋果! 世上便有了蘋果---蘋果在模型空間(local 空間)被永恒描述   
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}
//4.用戶創世第4天,說:到顯示屏來吧! 世界便是"平"的了.最后得屏幕空間
glViewport(0,0,width,height);//設置那個"視景區矩形"大小
glMatrixMode(GL_PROJECTION));//表示接下來要作“投影轉換”
gluPerspective(fov,aspect,near,far);//視景體應用

//3.用戶創世第3天,說:我是主角! 于是他擁有了第一人稱視覺,結果存視圖空間
glMatrixMode(GL_VIEW);//表示接下來要作“視圖轉換” 
gluLookat(eye,look,up)//也相當于一個平移矩陣 

//2.用戶創世第2天,說:蘋果右移! 于是世界坐標系便左移了,結果存入世界空間 
glMatrixMode(GL_MODEL);//表示接下來要作“模型轉換” 
glTranslatef(10,0,0);//相當于一個平移矩陣 

//1.用戶創世第1天,說:蘋果! 世上便有了蘋果---蘋果在模型空間(local 空間)被永恒描述  
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}

事實上OpenGL的glMatrixMode函數里沒有GL_MODEL和GL_VIEW這兩種設值。上面提到過,模型變換和視圖變換其實是同一種處理,而且視圖變換只由相機控制,有則有,無則默認。因此OpenGL直接就用GL_MODELVIEW一起轉換了。簡潔是簡潔,但是這樣一來用戶就不知道世界空間里的坐標系什么時候改變了,也難得到物體在世界坐標系下的位置坐標了(事實上還是有辦法的,不過搞復雜了,見以后的博文啦)。
 
glViewport(0,0,width,height);//設置那個"視景區矩形"大小 
 
glMatrixMode(GL_PROJECTION));//表示接下來要作“投影轉換”  
glLoadIdentity();
gluPerspective(fov,aspect,near,far);//視景體應用 
 
gluLookat(eye,look,up)//控制整個視景體   
 
glMatrixMode(GL_MODELVIEW);//表示接下來要作“模型視圖轉換”  
glLoadIdentity(); 
glTranslatef(10,0,0);//相當于一個平移矩陣   
 
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}
........
glViewport(0,0,width,height);//設置那個"視景區矩形"大小

glMatrixMode(GL_PROJECTION));//表示接下來要作“投影轉換” 
glLoadIdentity();
gluPerspective(fov,aspect,near,far);//視景體應用

gluLookat(eye,look,up)//控制整個視景體  

glMatrixMode(GL_MODELVIEW);//表示接下來要作“模型視圖轉換” 
glLoadIdentity();
glTranslatef(10,0,0);//相當于一個平移矩陣  
 
DrawApple() //{glBegin();glVertex3f(A);glVertex3f(B)....glEnd()}
........
此外,每次變換不是以之前保存的那個空間的位置信息為基礎嗎?這要用到glLoadIdentity()函數,初始化當前矩陣,為什么?還是看下篇吧:

本文來源于ZwqXin http://www.zwqxin.com/ , 轉載請注明
原文地址:http://www.zwqxin.com/archives/opengl/opengl-matrix-what.html


本篇文章承接上文:亂彈OpenGL中的矩陣變換(上) 。上篇中,我嘗試從一種不太成熟的OpenGL世界觀(注意,或許也是3D渲染世界的世界觀)來認識這個OpenGL世界,向自己澄清了一些概念(盡管不夠高清)。這里我想繼續從矩陣數學的角度想一想:究竟模型位置怎么在世界中各個空間的坐標系統中“轉換”?——ZwqXin
OpenGL中的坐標系是右手坐標系,矩陣按列優先存儲。這很讓人混亂,因為線代里接觸的都是行優先存儲,突然就這么column-major了.....最初還竊認為該不該從向量角度讓頭腦清晰,后來看別人文章說這跟向量沒啥關系,完全是一種規范:如同右手坐標系,只是一種規范。好吧,列就列啦:
mt0     mt4     mt8     mt12
mt1     mt5     mt9     mt13
mt2     mt6     mt10   mt14
mt3     mt7     mt11   mt15
有點怪是不?當然啦,連C語言學2維數組時都是row-major的,OpenGL卻是先一豎下來,再來下一豎(column-major)...(考慮一塊內存,第一個格子存mt0,第二存mt1.....)這就是OpenGL矩陣存儲方式。上篇提到,模型變換(Mode-Translation),視圖變換(View-Translation)乃至投影變換,這些決定了各個空間之不同的"針對坐標系的變換",實質產生出來的是一個左乘矩陣,這些矩陣就是這樣存儲的。如果你看過任何一本3D圖形學的入門書前兩章,那你應該知道模型變換(在OpenGL中反映為glTranslate,glScale,glRotate)所使用的矩陣。譬如我這里先讓蘋果繞z軸逆轉個角度Θ,再讓它變成原大小的A倍,再右移10單位:(P.S.翻譯成OpenGL世界的語言:在模型空間坐標系確定的位置基礎上,讓世界空間坐標系繞z軸順轉角度Θ,坍縮成原來一半大小,并左移10單位,注意是坍縮后1單位表示的長度跟之前的不一樣了。)
 
A*cosΘ-sinΘ0  10 
sinΘA*cosΘ00
00A*1   0
0001
   X
*     y     =   M * P(point of Apple)
      z
      1
 其中M是變換矩陣,點P(x,y,z,1)是蘋果的其中一個點的坐標(記得嗎?這個坐標是在模型空間確定的并且不變),它是一個豎向量形式的點。為什么是豎向量呢,因為OpenGL矩陣的左乘:(4X4)*(4X1)=(4X1)嘛,這是線形代數知識,(A行數XA列數)*(B行數XB列數)中,只有A列數=B行數,這兩個矩陣(向量)才可以相乘。那為什么要左乘?因為OpenGL(點)向量是列向量!哈哈,不是忽悠,這根本就是“規范問題”,譬如D3D就全采取相反的,不多說。最后,思考者應該已經把上面那個矩陣跟再上面那個“模板”對應起來了吧(OPENGL在內存中把相乘的結果——這16個數按mt0=A*cosΘ, mt1=sinΘ, mt2=0, mt3=0, mt4=-sinΘ, mt5=A*cosΘ, mt6=0......這樣的豎的順序存放)。再譬如我在之前的ShadowVolume Demo中就這樣定義了一個4X4矩陣類,并這樣定義了一個矩陣(就是上面的mt嘛)左乘某點向量的方法:
 
class CMatrix16

public:
    float mt[16];
 
   inline CVector4D operator*(CVector4D & vec4) { 
return CVector4D(mt[0] * vec4.x + mt[4] * vec4.y + mt[8] * vec4.z + mt[12] * vec4.w ,
     mt[1] * vec4.x + mt[5] * vec4.y + mt[9] * vec4.z + mt[13] * vec4.w ,
    mt[2] * vec4.x + mt[6] * vec4.y + mt[10]* vec4.z + mt[14] * vec4.w ,
     mt[3] * vec4.x + mt[7] * vec4.y + mt[11]* vec4.z + mt[15] * vec4.w );       
 
   };
 
};
class CMatrix16
{
public:
 float mt[16];

   inline CVector4D operator*(CVector4D & vec4) {
return CVector4D(mt[0] * vec4.x + mt[4] * vec4.y + mt[8] * vec4.z + mt[12] * vec4.w ,
  mt[1] * vec4.x + mt[5] * vec4.y + mt[9] * vec4.z + mt[13] * vec4.w ,
 mt[2] * vec4.x + mt[6] * vec4.y + mt[10]* vec4.z + mt[14] * vec4.w ,
  mt[3] * vec4.x + mt[7] * vec4.y + mt[11]* vec4.z + mt[15] * vec4.w );  

   };

};
然后,我們回頭看之前那條式子,得出的結果是(A*cosΘ*x - sinΘ*y + 10,sinΘ*x + A*cosΘ*y,A*z,1),這是點P的新位置,注意,再說一次,是“位置”而不是“坐標”,點P坐標依然是(x,y,z,1)。(當然,你還可以用這樣的概念來區分。)我姑且把結果記作(MP),所有點的結果構成了蘋果在世界空間的位置。好了,看看代碼:
 
glMatrixMode(GL_MODEL);
glTranslatef(10,0,0);
glScalef(A,A,A);
glRotatef(Θ, 0,0,1)
  
DrawApple() ;
glMatrixMode(GL_MODEL);
glTranslatef(10,0,0);
glScalef(A,A,A);
glRotatef(Θ, 0,0,1)
 
DrawApple() ;
請從下往上看。你問為什么順序是倒著的呢?這跟上篇遺留下來的問題很相似。現在經過模型變換來到了世界空間,接下來是視圖變換了。設當前相機得出的左乘矩陣為V,那么下一步,相似地,就是V*(MP)=(VMP)。上篇說過,OpenGL把模型變換和視圖變換合并為“模型視圖變換”,也就是說,OpenGL只生成一個左乘矩陣VM,上面的兩步乘法,在OpenGL中其實一步到位:VM*P=(VMP)。我們來到了視圖空間。真正代碼在此:
 
gluLookat(eye,look,up);
 
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();  
 
glTranslatef(10,0,0); 
glScalef(A,A,A); 
glRotatef(Θ, 0,0,1) 
   
DrawApple() ;
gluLookat(eye,look,up);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); 

glTranslatef(10,0,0);
glScalef(A,A,A);
glRotatef(Θ, 0,0,1)
  
DrawApple() ;
接下來由視景體設置,視口設置,投影處理得出的左乘矩陣是J,那么相似地,我們繼續左乘:J*(VMP)=(JVMP),來到屏幕空間——OpenGL世界的出口(之后的往窗口坐標系映射等等已經不算OpenGL的工作了)。
 
glViewport(0,0,width,height);//設置視口(視窗)大小
  
glMatrixMode(GL_PROJECTION));  
glLoadIdentity(); 
gluPerspective(fov,aspect,near,far);
 
gluLookat(eye,look,up); 
 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity();   
 
glTranslatef(10,0,0);  
glScalef(A,A,A);  
glRotatef(Θ, 0,0,1)  
    
DrawApple() ;
glViewport(0,0,width,height);//設置視口(視窗)大小
 
glMatrixMode(GL_PROJECTION)); 
glLoadIdentity();
gluPerspective(fov,aspect,near,far);

gluLookat(eye,look,up);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();  

glTranslatef(10,0,0); 
glScalef(A,A,A); 
glRotatef(Θ, 0,0,1) 
   
DrawApple() ;
是不是回到了上篇的結尾呢?恩,我從矩陣意義上再梳理了一次流程。然后,可以回答為什么代碼是倒過來寫的了吧?——這說明你很清楚,代碼是按順序從上往下執行的。沒錯,OpenGL中執行這些代碼也是從上往下執行的。所以你看看吧,這次要從上往下看:第1句:視窗設置,沒什么,它只剔除,不直接產生矩陣(而且還得在下面投影變換處發揮作用);第2句:接下來要作投影變換啦;第3句:glLoadIdentity(),哈哈!這才是重點——無論眼前的是什么,它都能把它初始化成一個單位矩陣!而這里的這個單位矩陣,是一切的開端,它確實就是一個單位矩陣(I)了,后面第4句視景體的設置產生的投影變換矩陣(J)右乘它:J= I*J;接下來第5句相機設置,第6句表示模型視圖變換的開始,第7句又一個glLoadIdentity(),繼續右乘:J= I*J*I,這有什么用啊?呵呵,因為接下來“模型視圖變換”產生的矩陣VM要繼續右乘這個結果,直接讓兩個變換矩陣相乘可以是可以,那么如果沒有投影變換呢?呵呵,這是有可能的,先不說平時我們渲染,就我們哪天突然要在模型空間搞事(譬如上次ShadowVolumeDemo那樣“回光返照”),單單應用“模型視圖變換”就關聯不到最初那個glLoadIdentity()了。所以讓一個glLoadIdentity()在作變換前出現是好的:VM = I*VM,實際上所有變換前加一個glLoadIdentity()是好習慣。
好吧,整理一下:假設把蘋果旋轉,放大,移動的相應變換矩陣是R,S,T,相機那個是L,那么這里就是 VM =L*T*S*R,也是倒過來的吧呵呵。按代碼順序的話右乘起來是這樣的:(JVM)= I*J*I*VM =I *J*I*L*S*T,等式右邊項是嚴格按照相應代碼順序來右乘的。為什么這里變右乘了?事實上我們說OpenGL的矩陣左乘規范,它跟代碼順序是兩碼事,矩陣左乘是從邏輯上來說的(也就是上篇和本篇我在開講代碼執行順序前講述的那些故事的邏輯,是屬于OpenGL世界的邏輯),代碼順序是屬于編譯器的哦。好了,這個(JVM)就是要把處于模型空間的物體轉移到屏幕上來——這時候它才和蘋果的頂點相乘:(JVMP)=(JVM)*P,看好了,也是右乘,當然的了——結果是,蘋果那么多頂點在一次渲染周期內只被“用”了一次!要知道,得出(JVM)結果的計算只有那么幾個矩陣相乘運算,但是蘋果N個頂點就有N個(JVM)*P的相乘運算哦!如果代碼執行順序相反你覺得會怎樣?“幾個N相乘”這么多次運算哦!
 
 
這里還有概念要澄清:
1.我說了,蘋果也好,其他任何畫出來的“東西”也好,它們坐標是在給出頂點坐標的時候就確定在模型空間的了,變換的是位置,也許說它們變換了還不對——因為真正被變換的是坐標系:你上面也看到了,蘋果的坐標是最后右乘上去的,之前一直變換的是最初那個單位矩陣,單位矩陣的變換也代表了最初各空間重合的OpenGL世界的坐標系——上篇說過,它的變換是反著模型的(當然也反著單位矩陣),這里也不妨說,它受變換的階段順序都是反著模型的——而且它是按照編譯器執行順序變換出來的,是真正的,真實存在的變換:OpenGL中所有的變換,都是在變換坐標系。

2.說法問題,“坐標”和“位置”,一路看下來你也知道,我不把它們當一回事(不想再羅嗦了恩)。但是更通常的叫法(雖然容易引起歧義但說得廣泛),是把“坐標”(固定于模型空間的那個,模型剛剛在世界出現時候的位置- -看,又羅嗦了)稱為“局部坐標(Local-Coordinate)”,把世界空間里面那個“位置”叫“世界坐標(World-Coordinate)”,也有直接簡稱它為坐標的(這樣的明顯不是高手),因為它最能被感知,也許你在了解什么模型空間模型變換等等等等這些概念前,唯一認識的就是世界坐標——它就標識著3D渲染窗口里那個虛擬3D世界不是么?恩,所以說世界空間是OpenGL世界中近乎“正常”的空間,類比一下,如果把我們人類所生活的空間叫“世界空間”的話,小說中描繪的到處扭曲的異次元空間就叫“模型空間”呀“屏幕空間”呀之類的了(笑)。遺憾的是OpenGL不直接給我們提供這個空間中各物體的坐標系位置呢~不怕,我們還有逆矩陣!
3.等有緣的你來發挖啦!錯誤啦認識問題啦,隨便提。這里是ZwqXin: www.zwqxin.com, 我的3D旅途記錄簿。(紀念今天2009.2.5.BLOG上軌道啦。)
最后...還有glPushMatrix()和glPopMatrix()呢?相信大家用得很多,也知道用處:在它們之外的東西不受它們里面的那些模型變換代碼影響。譬如下面這里,蘋果跟上面一樣也是做那些變換。可是橙呢?旋轉和放大對它無影響,它只是受到移動了(OpenGL世界說法是,對應坐標系移動了)。
 
glMatrixMode(GL_MODELVIEW);  
glLoadIdentity();    
  
glTranslatef(10,0,0);  
 
glPushMatrix();
  glScalef(A,A,A);   
  glRotatef(Θ, 0,0,1);       
  DrawApple() ;
glPopMatrix();
 
DrawOrange() ;
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity();   
 
glTranslatef(10,0,0); 

glPushMatrix();
  glScalef(A,A,A);  
  glRotatef(Θ, 0,0,1);      
  DrawApple() ;
glPopMatrix();

DrawOrange() ;
不知道我的講解有沒有人滿意。我自己倒是滿意了。哈哈。后面我還會有文章說說逆矩陣運算的問題和作用,并贊NEHE,有興趣的不妨CLICK一CLICK:

本文來源于ZwqXin http://www.zwqxin.com/ , 轉載請注明
原文地址:http://www.zwqxin.com/archives/opengl/opengl-matrix-what-2.html




 


 

posted on 2009-04-23 16:33 doing5552 閱讀(2122) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美电影免费观看高清完整版| 国产精品一区二区欧美| 亚洲三级观看| 亚洲国产欧美久久| 亚洲成人在线视频播放| 亚洲国产另类久久精品| 中文国产成人精品| 亚洲欧美文学| 久久久精品2019中文字幕神马| 久久都是精品| 欧美男人的天堂| 国产日韩欧美一区| 亚洲高清一区二| 亚洲午夜小视频| 久久亚洲欧美国产精品乐播| 欧美成人亚洲成人| 在线视频日韩| 蜜臀av一级做a爰片久久| 欧美精品色综合| 国产午夜精品全部视频播放| 亚洲破处大片| 久久久精品午夜少妇| 91久久夜色精品国产九色| 亚洲欧美怡红院| 欧美成人精品| 国产自产2019最新不卡| 亚洲深夜激情| 欧美 日韩 国产精品免费观看| 一本色道久久综合亚洲精品按摩 | 日韩午夜在线播放| 亚洲一区二区视频| 牛牛国产精品| 国产日韩综合| 中文亚洲免费| 欧美成人激情在线| 亚洲欧美日韩国产综合精品二区| 欧美丰满高潮xxxx喷水动漫| 国产一区二区电影在线观看| 亚洲一区黄色| 亚洲日本激情| 久久青草欧美一区二区三区| 国产精品美女一区二区在线观看| 亚洲国产成人精品久久久国产成人一区 | 亚洲国内自拍| 久久精品在线视频| 国产精品日日摸夜夜添夜夜av| 亚洲免费观看在线视频| 久久综合综合久久综合| 欧美一区二区三区免费大片| 国产精品白丝jk黑袜喷水| 9色精品在线| 亚洲国产精品久久久久| 麻豆亚洲精品| 亚洲福利久久| 免费在线看成人av| 久久久99国产精品免费| 国内久久婷婷综合| 久久一区二区三区四区| 久久九九国产精品| 在线日本成人| 亚洲国产专区校园欧美| 欧美日韩国产成人高清视频| 一本久久a久久精品亚洲| 亚洲动漫精品| 欧美大片免费看| av不卡在线观看| 亚洲精品乱码久久久久| 欧美经典一区二区三区| 亚洲天堂av图片| 亚洲一区二区免费| 国产麻豆日韩欧美久久| 久久久999国产| 久久综合色8888| 亚洲精品视频一区二区三区| 亚洲精品久久久久久久久久久久| 欧美日韩亚洲一区二区三区| 亚洲欧美在线观看| 久久久精品动漫| 亚洲靠逼com| 亚洲网址在线| 又紧又大又爽精品一区二区| 亚洲高清视频的网址| 欧美精品一区二区三区视频| 亚洲欧美日韩成人| 欧美在线视频一区二区| 亚洲国产一区二区视频| 亚洲精品一二三区| 噜噜噜在线观看免费视频日韩| 狠狠88综合久久久久综合网| 欧美激情精品久久久久久蜜臀| 欧美激情自拍| 亚洲欧美日韩另类| 久久久久一区二区三区| 日韩一区二区免费看| 亚洲性线免费观看视频成熟| 亚洲高清自拍| 亚洲免费人成在线视频观看| 亚洲二区在线视频| 中日韩视频在线观看| 亚洲福利视频免费观看| 亚洲一区二区三区高清| 亚洲国产精品久久久久婷婷884| 中文精品视频一区二区在线观看| 在线免费观看日本一区| 亚洲午夜精品国产| 亚洲欧洲在线一区| 欧美在线电影| 亚洲综合色网站| 欧美成人一区二区三区| 久久久99久久精品女同性| 欧美日韩国产经典色站一区二区三区| 久热精品视频在线观看| 国产精品欧美一区喷水| 亚洲欧洲日韩综合二区| 激情视频一区二区三区| 香蕉久久夜色| 亚洲一区二区三区午夜| 欧美暴力喷水在线| 欧美亚洲色图校园春色| 日韩香蕉视频| 在线观看欧美成人| 亚洲欧美国产高清| 一区二区三区高清不卡| 欧美v国产在线一区二区三区| 久久国产精品久久久久久电车| 欧美少妇一区二区| 91久久在线| **性色生活片久久毛片| 久久精品国产99精品国产亚洲性色 | 久久蜜桃资源一区二区老牛| 久久精品一本| 国产婷婷色一区二区三区| 亚洲一级黄色片| 亚洲欧美日韩一区在线观看| 国产精品福利片| 亚洲永久免费精品| 欧美一区二区在线| 国产在线拍揄自揄视频不卡99| 欧美在线播放| 牛牛国产精品| 1024欧美极品| 欧美成人午夜影院| 亚洲精品日韩一| 亚洲影视在线| 国产视频精品va久久久久久| 欧美一区二区在线看| 美女精品国产| 亚洲精选一区二区| 欧美日韩国产综合网| 一区二区不卡在线视频 午夜欧美不卡'| 99av国产精品欲麻豆| 久久gogo国模裸体人体| 亚洲二区在线观看| 亚洲激情电影在线| av成人天堂| 欧美丝袜一区二区三区| 性久久久久久| 欧美国产一区视频在线观看| 99热免费精品在线观看| 国产乱码精品1区2区3区| 久久精品卡一| 91久久一区二区| 欧美一区激情| 亚洲欧洲日本mm| 国产精品日韩欧美一区二区| 久久久国产精品一区二区中文| 亚洲第一福利视频| 亚洲一级片在线看| 激情欧美一区二区| 欧美日韩日韩| 久久久久久久性| 99精品视频一区二区三区| 久久精品一区二区三区四区| 亚洲三级网站| 国产一区二区三区的电影| 欧美国产日韩亚洲一区| 午夜视频在线观看一区二区| 亚洲国内高清视频| 久久综合九色综合久99| 亚洲一区二区三区精品视频| 国产一区二区三区最好精华液| 欧美 日韩 国产一区二区在线视频| 中文在线不卡| 亚洲人体一区| 久久综合色88| 午夜国产一区| 一区二区三区国产| 亚洲电影av| 国内久久精品视频| 国产精品视频九色porn| 欧美精品在线观看播放| 久久人人97超碰国产公开结果| 亚洲影院污污.| 一区二区三区视频在线看| 欧美激情a∨在线视频播放| 欧美专区第一页| 午夜视频一区二区| 午夜精品久久久久久99热| 中国成人亚色综合网站| 日韩系列在线|