在OpenGL中,存在着至少存在着三種矩陣,對應着函數glMatrixMode()的三個參數:GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE。
以下主要描述GL_MODELVIEW(模型視圖矩陣)的個人理解。
在OpenGL中空間中點的三維坐標是使用行向量表示的,雖然與列向量相比存儲結構並沒有發生變化,但在坐標變換(即矩陣乘法)中會有很大不同。大家都知道一個4X4的矩陣可以表示三維坐標的平移,旋轉變換。例如一矩陣R表示一個旋轉加平移變換,空間中一點P(x, y, z),如果坐標使用列向量表示,則變換過程為
如果坐標使用行向量表示,則變換過程為上述矩陣的轉置
因此,OpenGL中變換矩陣采用的是右乘的方式,並且其需要的變換矩陣其實是真正變換矩陣的轉置(前提是矩陣在數組中采取的是以行為主的形式,即先存儲完矩陣的一行,接下來再存儲矩陣的下一行)。
函數glLoadMatrixf(const GLfloat *m)輸入的矩陣其實是變換矩陣R的轉置。
如果先后對空間中一點P(x, y, z)作多次變換,設先后的變換矩陣分別為A,B,C,則在OpenGL中應當如何輸入變換矩陣呢?當坐標使用列向量表示時,變換過程為
當坐標使用行向量表示時,變換過程為
因此,OpenGL中,最先變換的矩陣應當最后與當前矩陣相乘,並且乘的是變換矩陣的轉置。下面我以一個例子來說明上述變換。注意下面描述中的x,y,z軸實際上指的是相機坐標系中的U,V,N軸。OpenGL中,屏幕中所呈現的視平面其實是UOV平面,屏幕上方為V軸正方向,屏幕右方為U軸正方向,屏幕由里到外為N軸正方向。因此視線方向總是沿N軸負方向。
函數rotate(float angle, float x, float y, float z)是讓坐標點繞向量(x, y, z)旋轉angle角度,旋轉方向符合右手螺旋定則。函數translate(float x, float y, float z)是讓坐標點沿向量(x, y, z)平移其模長的距離。上述兩個函數生成的都是變換矩陣的轉置,並且實現的都是,其中M是當前矩陣,R是變換矩陣。
1 matrixView.identity(); //transform matrixView to an identity 2 matrixView.translate(0, 0, -r); 3 glLoadMatrixf(matrixView.get());
上述矩陣是由一個單位陣加沿負N軸的平移轉換而成,假設在世界坐標系中有一茶壺,其中心位於世界坐標系的原點,在上述變換矩陣下如下圖:
圖中,紅,綠,藍箭頭分別為世界坐標系的x,y,z軸。下面是讓該茶壺先后沿x,y,z軸旋轉90度的代碼和結果截圖
1 matrixView.identity(); //transform matrixView to an identity 2 matrixView.rotate(90, 1, 0, 0); //cameraAngleX 3 matrixView.translate(0, 0, -r); 4 glLoadMatrixf(matrixView.get());
1 matrixView.identity(); //transform matrixView to an identity 2 matrixView.rotate(90, 1, 0, 0); //cameraAngleX 3 matrixView.rotate(90, 0, 1, 0); //cameraAngleY 4 matrixView.translate(0, 0, -r); 5 glLoadMatrixf(matrixView.get());
1 matrixView.identity(); //transform matrixView to an identity 2 matrixView.rotate(90, 1, 0, 0); //cameraAngleX 3 matrixView.rotate(90, 0, 1, 0); //cameraAngleY 4 matrixView.rotate(90, 0, 0, 1); //cameraAngleZ 5 matrixView.translate(0, 0, -r); 6 glLoadMatrixf(matrixView.get());