OpenGL 矩阵变换
origin refer :http://www.songho.ca/opengl/gl_transform.html#modelview
OpenGL 矩陣變換
Related Topics:?OpenGL Pipeline,?OpenGL Projection Matrix,?OpenGL Matrix Class?
Download:?matrixModelView.zip,?matrixProjection.zip
- Overview
- OpenGL Transform Matrix
- Example: GL_MODELVIEW Matrix
- Example: GL_PROJECTION Matrix
幾何數(shù)據(jù)——如頂點(diǎn)位置,和標(biāo)準(zhǔn)向量(normal vectors),在OpenGL 管道raterization 處理過程之前可通過頂點(diǎn)操作(Vertex Operation)和基本組合操作改變這些數(shù)據(jù)。
Object Coordinates
對(duì)象的本地坐標(biāo)系——任何變換之前的最初位置.為了變換(transformation)這些對(duì)象,可以調(diào)用glRotate(),glTranslatef(),glScalef()這些方法。
增加常用坐標(biāo)系 有助于理解各種坐標(biāo)的關(guān)系《坐標(biāo)系僅表示相對(duì)關(guān)系,與具體名稱無關(guān)》
OpenGL有6種坐標(biāo)系,分別如下:
- 1,物體或模型坐標(biāo)系(Object or model coordinates);
- 2,世界坐標(biāo)系(World coordinates)
- 3,眼坐標(biāo)或相機(jī)坐標(biāo)(Eye (or Camera) coordinates)
- 4,裁剪坐標(biāo)系(Clip coordinates)
- 5,標(biāo)準(zhǔn)設(shè)備坐標(biāo)系(Normalized device coordinates)
- 6,屏幕坐標(biāo)系(Window (or screen) coordinates)?
除了上面6種外,OpenGL還存在一種假想坐標(biāo)系紋理坐標(biāo)系,這個(gè)坐標(biāo)系是不存在的,它其實(shí)是一系列變換矩陣的結(jié)果,比如它能使頂點(diǎn)從物體或模型坐標(biāo)系變換到世界坐標(biāo)系。
從object coordainates到world coordinates再到camera coordinate的變換,在OpenGL中統(tǒng)一稱為model-view轉(zhuǎn)換,初始化的時(shí)候,object coordinates和world coordinates還有camera coordinates坐標(biāo)重合在原點(diǎn),變換矩陣都為Identity,所以在OpenGL中用glLoadIdentity()初始化變換矩陣棧。model-view matix轉(zhuǎn)換points,vectorsd到camera坐標(biāo)系。
Eye Coordinates
使用GL_MODELVIEW矩陣和Object 坐標(biāo)相乘所得。在OpenGL中用GL_MODELVIEW將對(duì)象對(duì)象空間(Object Space)變換到視覺空間(eye space)。GL_MODELVIEW
矩陣是模型矩陣(Model Matrix)和視覺矩陣(View Matrix)的組合?()。其中,Model 變換指的是將Object ?Space轉(zhuǎn)換到World Space
(譯注:World Space值得是OpenGL中的三維空間),而View 變換是將World space變換到eye space。
注意:在OpenGL中沒有單獨(dú)的camera(view) matrix。因此,為了模擬camera或者view的變換,其中的場(chǎng)景(3D物體和光照)必須通過和view相反的方向變換。也就是說,OpenGL總是將camera定義在(0,0,0)點(diǎn),并且強(qiáng)制在eye space坐標(biāo)系的-Z軸方向,而且不能變換。關(guān)于GL_MODELVIEW Matrix的詳細(xì)資料可以查看此處:http://www.songho.ca/opengl/gl_transform.html#modelview
標(biāo)準(zhǔn)向量(Normal vectors)——從對(duì)象坐標(biāo)系(Object coordinates)變換到視覺坐標(biāo)系(eye coordinates),它是用來計(jì)算光照(lighting calculation)的.注意標(biāo)準(zhǔn)向量(Normal vectors)的變換和頂點(diǎn)的不同。其中視覺矩陣(view matrix)是GL_MODELVIEW逆矩陣的轉(zhuǎn)置矩陣和標(biāo)準(zhǔn)向量(Normal vector是)相乘所得,即:
更多關(guān)于標(biāo)準(zhǔn)向量變換(Normal Vector Transformation)的資料可連接到此處:http://www.songho.ca/opengl/gl_normaltransform.htm
剪切面坐標(biāo)系(Clip Coordinates)
視覺坐標(biāo)系和GL_PROJECTION矩陣相乘,得到剪切面坐標(biāo)系。GL_PROJECTION矩陣定義了可視的空間(截頭錐體)(譯注:關(guān)于什么是截頭錐體,我還查了下資料,發(fā)現(xiàn)它是這個(gè)樣子的:
,這個(gè)就是投影的效果啦)以及頂點(diǎn)數(shù)據(jù)如何投影到屏幕上(視角或者正交化(orthogonal)),它被稱為剪切面坐標(biāo)系的原因是(x,y,z)變換之后
要和±w比較。更多關(guān)于GL_PROJECTION矩陣的資料可見:http://www.songho.ca/opengl/gl_transform.html#projection
標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系(NDC)
將剪切面坐標(biāo)系除以w所得(關(guān)于w的討論可見此處:,http://www.songho.ca/math/homogeneous/homogeneous.html),它被稱為視角除法(perspective division)
.它更像是窗口坐標(biāo)系,只是還沒有轉(zhuǎn)換或者縮小到屏幕像素。其中它取值范圍在3個(gè)軸向從-1到1標(biāo)準(zhǔn)化了。
窗口坐標(biāo)系(Window Coordinates)/屏幕坐標(biāo)系(Screen Coordinates)
將標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系(NDC)應(yīng)用于視口轉(zhuǎn)換。NDC將縮小和平移以便適應(yīng)屏幕的透視。窗口坐標(biāo)系最終傳遞給OpenGL的管道處理變成了fragment。glViewPort()函數(shù)
用來定義最終圖片映射的投影區(qū)域。同樣,glDepthRange()用來決定窗口坐標(biāo)系的z坐標(biāo)。窗口坐標(biāo)系由下面兩個(gè)方法給出的參數(shù)計(jì)算出來
glViewPort(x,y,w,h);
glDepthRange(n,f);
視口轉(zhuǎn)換公式很簡(jiǎn)單,通過NDC和窗口坐標(biāo)系的線性關(guān)系得到:
OpenGL 轉(zhuǎn)換矩陣
OpenGL使用4x4矩陣變換。注意,這16個(gè)元素存儲(chǔ)在1D數(shù)組中,這些元素按列順序排列。假如你想以行為順序排列,你需要轉(zhuǎn)置該矩陣。
OpenGL有4中不用的矩陣:GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE和GL_COLOR.你可以在
代碼中使用glMatrixMode()函數(shù)改變當(dāng)前的類型。例如,為了選擇GL_MODELVIEW矩陣,可以這樣:
glMatrixMode(GL_MODELVIEW);
---------------------------------------------------------------------------------------------------------------------------------------------
Model-View 矩陣(GL_MODELVIEW)
GL_MODELVIEW矩陣在一個(gè)矩陣中包含view矩陣和model 矩陣,為了變換view(camera),你需要將整個(gè)
場(chǎng)景施以逆變換。gluLookAt()用來設(shè)置viewing變換。
最右邊的三個(gè)矩陣元素?(m12,?m13,?m14) 是用作位移變換的。m15元素是齊次坐標(biāo)。(何為齊次坐標(biāo),參見:http://www.songho.ca/math/homogeneous/homogeneous.html),該元素是用來投影變換的。
(注意這三個(gè)元素集實(shí)際上指得是3個(gè)正交坐標(biāo)系:
?
4 columns of GL_MODELVIEW matrix
我們能夠不使用OpenGL變換函數(shù),直接構(gòu)造GL_MODELVIEW矩陣。下面有一些有用的代碼構(gòu)建GL_MODELVIEW矩陣
1. Angles to Axes ?
2. Lookat to Axes
3. Matrix4 class
注意,OpenGL在多種變換同時(shí)施加到頂點(diǎn)上時(shí)以相反的順序矩陣相乘。例如,假如一個(gè)頂點(diǎn)先以MA
?x?
投影矩陣Projection Matrix(GL_PROJECTION)
GL_PROJECTION矩陣用來定義截錐體。該截錐體決定了那些對(duì)象或者對(duì)象的哪些部分將會(huì)被裁剪掉。同樣,它也決定著3D場(chǎng)景怎樣投影到屏幕中
(關(guān)于怎樣構(gòu)建投影矩陣,請(qǐng)查看
http://www.songho.ca/opengl/gl_projectionmatrix.html
OpenGL提供2個(gè)函數(shù)用來GL_PROJECTION變換。glFrustum()產(chǎn)生投影視角。glOrtho()產(chǎn)生正交(或者平行)投影。
兩個(gè)函數(shù)都需要6個(gè)參數(shù)決定6個(gè)剪切面:left, right, bottom, top, near, 和far 平面。截錐體的8個(gè)頂點(diǎn)如下所示:
?
OpenGL Perspective Viewing Frustum
遠(yuǎn)端平面(后面)的頂點(diǎn)能夠簡(jiǎn)單地通過相似三角形的比率計(jì)算出來。例如,遠(yuǎn)端平面的左側(cè)可以如下計(jì)算:
對(duì)于正交投影,ratio為1,所以遠(yuǎn)端平面的left,right,bottom和top值都與近端平面的值相同。
、//OpenGL ES中常用到的幾種坐標(biāo)系:世界坐標(biāo)系、物體坐標(biāo)系、設(shè)備坐標(biāo)系、眼坐標(biāo)系當(dāng)然還有假想的紋理坐標(biāo)系
同樣,你也可以使用gluPerspective()和gluOrtho2D()函數(shù),但是傳遞更少的參數(shù)。gluPerspective()只需要4個(gè)參數(shù):視圖的垂直區(qū)域(vertical field of view(FOV)),
width/height的ratio,還有近端平面和遠(yuǎn)端平面的距離。下面代碼使用gluPerspective()和glFrustum()實(shí)現(xiàn)同樣的功能:
OpenGL正交的截錐體
?
OpenGL Orthographic Frustum
然而,假如你想要一個(gè)非對(duì)稱的視覺空間,你可以直接使用glFrustum()。例如,
假如你想要呈現(xiàn)一個(gè)大的場(chǎng)景到2個(gè)相鄰的屏幕,你可以截?cái)嘟劐F體變成2個(gè)不對(duì)稱的截錐體(左和右)。然后,
呈現(xiàn)每個(gè)截錐體場(chǎng)景。
(這句話太不好翻譯了,原位如下:
For example, if you want to render a wide scene into 2 adjoining screens, you can break down the frustum into 2 asymmetric frustums (left and right). Then, render the scene with each frustum.
?
An example of an asymmetric frustum
紋理矩陣(GL_TEXTURE)
紋理坐標(biāo)(s,t,r,q)在任何紋理映射之前乘以GL_TEXTURE矩陣所得,默認(rèn)是恒等的。所以紋理映射到物體的位置將正好是你賦值給紋理坐標(biāo)的位置。
通過改變GL_TEXTURE,你可以滑動(dòng),旋轉(zhuǎn),拉伸或者伸縮紋理。
顏色矩陣(GL_COLOR)
顏色部分是通過乘以GL_COLOR矩陣所得。該矩陣用于顏色空間和顏色組件的變換。(原位如下:It can be used for color space conversion and color component swaping)
顏色矩陣并不是通用的,需要GL_ARB_imaging擴(kuò)展(什么是GL_ARB_imaging擴(kuò)展?求解)
其他矩陣?yán)?/p>
glPushMatrix()——將當(dāng)前的矩陣壓入矩陣棧
glPopMatrix()——從當(dāng)前的矩陣棧中彈出當(dāng)前的矩陣
glLoadIdentity()——設(shè)置當(dāng)前矩陣為等同矩陣
glLoadMatrix{fd}(m)——將當(dāng)前矩陣替換成矩陣m
glLoadTransposeMatrix{fd}(m)——將當(dāng)前矩陣換成其轉(zhuǎn)置矩陣
glMultMatrix{fd}(m)——將當(dāng)前矩陣乘以矩陣m,并且更新當(dāng)前矩陣
glMultTransposeMatrix{fd}(m)——將當(dāng)前矩陣乘以其轉(zhuǎn)置矩陣,并且更新當(dāng)前矩陣
glGetFloatv(GL_MODELVIEW_MATRIX,?m)?——將GL_MODELVIEW矩陣的16個(gè)值加載到m中
例子1:ModelView Matrix
這個(gè)demo應(yīng)用顯示怎樣使用glTranslatef()和glRotatef()操作GL_MODELVIEW
下載鏈接:
matrixModelView.zip: ??
http://www.songho.ca/opengl/files/matrixModelView.zip
(OS X 10.6+) matrixModelView_mac.zip: ??http://www.songho.ca/opengl/files/matrixModelView_mac.zip
注意所有的OpenGL函數(shù)在Mac和Windows下都在ModelGL.h和ModelGL.cpp中實(shí)現(xiàn),在這些包中的這些文件是完全一樣的。
該demo應(yīng)用使用一個(gè)定制的4X4類(鏈接為:http://www.songho.ca/opengl/gl_matrix.html)作為默認(rèn)的OpenGL矩陣?yán)?#xff0c;為了指定model和camera變換.
在ModelGL.cpp中有3中矩陣對(duì)象:matrixModel,matrixView和matrixModelView.每一種矩陣保存著預(yù)先計(jì)算好的變換。然后將這些矩陣元素傳遞給OpenGL的函數(shù)——glLoadMatrix().實(shí)際的畫圖程序應(yīng)該向下面這個(gè)樣子:
使用OpenGL默認(rèn)的矩陣函數(shù),相同的代碼如下:
投影矩陣?yán)?#xff1a;
該 demo應(yīng)用顯示了如何使用glFrustum()和glOrtho()函數(shù)操作投影變換。
源碼和二進(jìn)制文件下載的鏈接:
matrixProjection.zip: ??
http://www.songho.ca/opengl/files/matrixProjection.zip
matrixProjection_mac.zip(OS X 10.6+): ??
http://www.songho.ca/opengl/files/matrixProjection_mac.zip
同樣,ModelGL.h和ModelGL.cpp在兩者的包中有同樣的文件,且所有的OpenGL函數(shù)都置于這些文件中。
ModelGL類有一個(gè)定制的matrix對(duì)象:matrixProjection,兩個(gè)成員函數(shù):setFrustum()和setOrthoFrustum().
其功能與glFrustum()和glOrtho()函數(shù)相同
GL_PROJECTION矩陣構(gòu)建的16個(gè)參數(shù)在這可以看到:
http://www.songho.ca/opengl/gl_projectionmatrix.html
OpenGL Transformation
Related Topics:?OpenGL Pipeline,?OpenGL Projection Matrix,?OpenGL Matrix Class?
Download:?matrixModelView.zip,?matrixProjection.zip
- Overview
- OpenGL Transform Matrix
- Example: GL_MODELVIEW Matrix
- Example: GL_PROJECTION Matrix
Overview
Geometric data such as vertex positions and normal vectors are transformed via?Vertex Operation?and?Primitive Assembly?operation in?OpenGL pipeline?before raterization process.
?OpenGL vertex transformation
Object Coordinates
It is the local coordinate system of objects and is initial position and orientation of objects before any transform is applied. In order to transform objects, use glRotatef(), glTranslatef(), glScalef().
Eye Coordinates
It is yielded by multiplying GL_MODELVIEW matrix and object coordinates. Objects are transformed from object space to eye space using GL_MODELVIEW matrix in OpenGL.?GL_MODELVIEW?matrix is a combination of Model and View matrices (). Model transform is to convert from object space to world space. And, View transform is to convert from world space to eye space.
Note that there is no separate camera (view) matrix in OpenGL. Therefore, in order to simulate transforming the camera or view, the scene (3D objects and lights) must be transformed with the inverse of the view transformation. In other words, OpenGL defines that the camera is always located at (0, 0, 0) and facing to -Z axis in the eye space coordinates, and cannot be transformed.?See more details of GL_MODELVIEW matrix inModelView Matrix.
Normal vectors are also transformed from object coordinates to eye coordinates for lighting calculation. Note that normals are transformed in different way as vertices do. It is mutiplying the tranpose of the inverse of GL_MODELVIEW matrix by a normal vector.?See more details in?Normal Vector Transformation.?
Clip Coordinates
The eye coordinates are now multiplied with?GL_PROJECTION?matrix, and become the clip coordinates. This GL_PROJECTION matrix defines the viewing volume (frustum); how the vertex data are projected onto the screen (perspective or orthogonal). The reason it is called?clip coordinates?is that the transformed vertex (x, y, z) is clipped by comparing with ±w.?
See more details of GL_PROJECTION matrix in?Projection Matrix.
Normalized Device Coordinates (NDC)
It is yielded by dividing the clip coordinates by?w. It is called?perspective division. It is more like window (screen) coordinates, but has not been translated and scaled to screen pixels yet. The range of values is now normalized from -1 to 1 in all 3 axes.
Window Coordinates (Screen Coordinates)
It is yielded by applying normalized device coordinates (NDC) to viewport transformation. The NDC are scaled and translated in order to fit into the rendering screen. The window coordinates finally are passed to the raterization process of?OpenGL pipeline?to become a fragment.?glViewport()?command is used to define the rectangle of the rendering area where the final image is mapped. And,?glDepthRange()?is used to determine the?z?value of the window coordinates. The window coordinates are computed with the given parameters of the above 2 functions;?
glViewport(x, y, w, h);?
glDepthRange(n, f);
The viewport transform formula is simply acquired by the linear relationship between NDC and the window coordinates;?
OpenGL Transformation Matrix
?OpenGL Transform Matrix
OpenGL uses?4 x 4 matrix?for transformations. Notice that 16 elements in the matrix are stored as 1D array in column-major order. You need to transpose this matrix if you want to convert it to the standard convention, row-major format.
OpenGL has 4 different types of matrices;?GL_MODELVIEW,?GL_PROJECTION,?GL_TEXTURE, and?GL_COLOR. You can switch the current type by using?glMatrixMode()?in your code. For example, in order to select GL_MODELVIEW matrix, use?glMatrixMode(GL_MODELVIEW).
Model-View Matrix (GL_MODELVIEW)
GL_MODELVIEW matrix combines viewing matrix and modeling matrix into one matrix. In order to transform the view (camera), you need to move whole scene with the inverse transformation.?gluLookAt()?is particularly used to set viewing transform.
?4 columns of GL_MODELVIEW matrix
The 3 matrix elements of the rightmost column (m12,?m13,?m14) are for the translation transformation,?glTranslatef(). The element?m15?is the?homogeneous coordinate. It is specially used for projective transformation.
3 elements sets, (m0,?m1,?m2), (m4,?m5,?m6) and (m8,?m9,?m10) are for Euclidean and affine transformation, such as rotation?glRotatef()?or scaling?glScalef(). Note that these 3 sets are actually representing 3 orthogonal axes;
- (m0,?m1,?m2) ??: +X axis,?left?vector, (1, 0, 0) by default
- (m4,?m5,?m6) ??: +Y axis,?up?vector, (0, 1, 0) by default
- (m8,?m9,?m10) : +Z axis,?forward?vector, (0, 0, 1) by default
We can directly construct GL_MODELVIEW matrix from angles or lookat vector without using OpenGL transform functions. Here are some useful codes to build GL_MODELVIEW matrix:
- Angles to Axes
- Lookat to Axes
- Matrix4 class
Note that OpenGL performs matrices multiplications in reverse order if multiple transforms are applied to a vertex. For example, If a vertex is transformed by?MA?first, and transformed by?MB?second, then OpenGL performs?MB?x?MA?first before multiplying the vertex. So, the last transform comes first and the first transform occurs last in your code.?
// Note that the object will be translated first then rotated
glRotatef(angle, 1, 0, 0); // rotate object angle degree around X-axis
glTranslatef(x, y, z); // move object to (x, y, z)
drawObject();
Projection Matrix (GL_PROJECTION)
GL_PROJECTION matrix is used to define the frustum. This frustum determines which objects or portions of objects will be clipped out. Also, it determines how the 3D scene is projected onto the screen.?(Please see more details?how to construct the projection matrix.)
OpenGL provides 2 functions for GL_PROJECTION transformation.?glFrustum()?is to produce a perspective projection, and?glOrtho()?is to produce a orthographic (parallel) projection. Both functions require 6 parameters to specify 6 clipping planes;?left,?right,?bottom,?top,?near?and?far?planes. 8 vertices of the viewing frustum are shown in the following image.
?OpenGL Perspective Viewing Frustum
The vertices of the far (back) plane can be simply calculated by the ratio of similar triangles, for example, the left of the far plane is;?
OpenGL Orthographic Frustum
For orthographic projection, this ratio will be 1, so the?left,?right,?bottom?and?top?values of the far plane will be same as on the near plane.
You may also use gluPerspective() and gluOrtho2D() functions with less number of parameters.?gluPerspective()?requires only 4 parameters; vertical field of view (FOV), the aspect ratio of width to height and the distances to near and far clipping planes. The equivalent conversion from gluPerspective() to glFrustum() is described in the following code.
// This creates a symmetric frustum.
// It converts to 6 params (l, r, b, t, n, f) for glFrustum()
// from given 4 params (fovy, aspect, near, far)
void makeFrustum(double fovY, double aspectRatio, double front, double back)
{const double DEG2RAD = 3.14159265 / 180;double tangent = tan(fovY/2 * DEG2RAD); // tangent of half fovYdouble height = front * tangent; // half height of near planedouble width = height * aspectRatio; // half width of near plane// params: left, right, bottom, top, near, farglFrustum(-width, width, -height, height, front, back);
}
?An example of an asymmetric frustum
However, you have to use glFrustum() directly if you need to create a non-symmetrical viewing volume. For example, if you want to render a wide scene into 2 adjoining screens, you can break down the frustum into 2 asymmetric frustums (left and right). Then, render the scene with each frustum.
Texture Matrix (GL_TEXTURE)
Texture coordinates (s,?t,?r,?q) are multiplied by GL_TEXTURE matrix before any texture mapping. By default it is the identity, so texture will be mapped to objects exactly where you assigned the texture coordinates. By modifying GL_TEXTURE, you can slide, rotate, stretch, and shrink the texture.
// rotate texture around X-axis
glMatrixMode(GL_TEXTURE);
glRotatef(angle, 1, 0, 0);
Color Matrix (GL_COLOR)
The color components (r,?g,?b,?a) are multiplied by GL_COLOR matrix. It can be used for color space conversion and color component swaping. GL_COLOR matrix is not commonly used and is required?GL_ARB_imagingextension.
Other Matrix Routines
glPushMatrix()?:?push the current matrix into the current matrix stack.glPopMatrix()?:?pop the current matrix from the current matrix stack.glLoadIdentity()?:?set the current matrix to the identity matrix.glLoadMatrix{fd}(m)?:?replace the current matrix with the matrix?m.glLoadTransposeMatrix{fd}(m)?:?replace the current matrix with the row-major ordered matrix?m.glMultMatrix{fd}(m)?:?multiply the current matrix by the matrix?m, and update the result to the current matrix.glMultTransposeMatrix{fd}(m)?:?multiply the current matrix by the row-major ordered matrix?m, and update the result to the current matrix.glGetFloatv(GL_MODELVIEW_MATRIX,?m)?:?return 16 values of GL_MODELVIEW matrix to?m.?
Example: ModelView Matrix
This demo application shows how to manipulate GL_MODELVIEW matrix by translation and rotation transforms.
Download the source and binary:?
(Updated: 2018-04-16)
matrixModelView.zip?(include VS 2015 project)?
matrixModelView_mac.zip?(macOS 10.10+, include Xcode v9)
Note that all OpenGL function calls are implemented in?ModelGL.h?and?ModelGL.cpp?on both Mac and Windows versions, and these files are?identical?on both packages (platform independent).
This demo application uses?a custom 4x4 matrix class?as well as default OpenGL matrix routines in order to specify model and camera transforms. There are 3 of matrix objects defined in ModelGL.cpp; matrixModel, matrixView and matrixModelView. Each matrix stores the pre-computed transformation and passes the matrix elements to OpenGL by using?glLoadMatrixf(). The actual drawing routine looks like;
...
glPushMatrix();// set view matrix for camera transform
glLoadMatrixf(matrixView.get());// draw the grid at origin before model transform
drawGrid();// set modelview matrix for both model and view transform
// It transforms from object space to eye space.
glLoadMatrixf(matrixModelView.get());// draw a teapot after both view and model transforms
drawTeapot();glPopMatrix();
...
The equivalent code using default OpenGL matrix functions is;
...
glPushMatrix();// initialze ModelView matrix
glLoadIdentity();// First, transform the camera (viewing matrix) from world space to eye space
// Notice translation and heading values are negated,
// because we move the whole scene with the inverse of camera transform
// ORDER: translation -> roll -> heading -> pitch
glRotatef(cameraAngle[2], 0, 0, 1); // roll
glRotatef(-cameraAngle[1], 0, 1, 0); // heading
glRotatef(cameraAngle[0], 1, 0, 0); // pitch
glTranslatef(-cameraPosition[0], -cameraPosition[1], -cameraPosition[2]);// draw the grid at origin before model transform
drawGrid();// transform the object (model matrix)
// The result of GL_MODELVIEW matrix will be:
// ModelView_M = View_M * Model_M
// ORDER: rotZ -> rotY -> rotX -> translation
glTranslatef(modelPosition[0], modelPosition[1], modelPosition[2]);
glRotatef(modelAngle[0], 1, 0, 0);
glRotatef(modelAngle[1], 0, 1, 0);
glRotatef(modelAngle[2], 0, 0, 1);// draw a teapot with model and view transform together
drawTeapot();glPopMatrix();
...
Example: Projection Matrix
This demo application is to show how to manipulate the projection transformation with 6 parameters; left, right, bottom, top, near and far values.
Download the source and binary:?
(Updated: 2017-03-15)
matrixProjection.zip?(include VS 2015 project)?
matrixProjection_mac.zip?(macOS 10.10+, include Xcode v9)
Again,?ModelGL.h?and?ModelGL.cpp?are exactly same files on both packages (platform independent), and all OpenGL function calls are placed in these files.
ModelGL class has?a custom matrix object,?matrixProjection, and 2 member functions,?setFrustum()?and?setOrthoFrustum(), which are equivalent to?glFrustum()?and?glOrtho().
///
// return a perspective frustum with 6 params similar to glFrustum()
// (left, right, bottom, top, near, far)
///
Matrix4 ModelGL::setFrustum(float l, float r, float b, float t, float n, float f)
{Matrix4 matrix;matrix[0] = 2 * n / (r - l);matrix[5] = 2 * n / (t - b);matrix[8] = (r + l) / (r - l);matrix[9] = (t + b) / (t - b);matrix[10] = -(f + n) / (f - n);matrix[11] = -1;matrix[14] = -(2 * f * n) / (f - n);matrix[15] = 0;return matrix;
}///
// return a symmetric perspective frustum with 4 params similar to
// gluPerspective() (vertical field of view, aspect ratio, near, far)
///
Matrix4 ModelGL::setFrustum(float fovY, float aspectRatio, float front, float back)
{float tangent = tanf(fovY/2 * DEG2RAD); // tangent of half fovYfloat height = front * tangent; // half height of near planefloat width = height * aspectRatio; // half width of near plane// params: left, right, bottom, top, near, farreturn setFrustum(-width, width, -height, height, front, back);
}///
// set a orthographic frustum with 6 params similar to glOrtho()
// (left, right, bottom, top, near, far)
///
Matrix4 ModelGL::setOrthoFrustum(float l, float r, float b, float t, float n, float f)
{Matrix4 matrix;matrix[0] = 2 / (r - l);matrix[5] = 2 / (t - b);matrix[10] = -2 / (f - n);matrix[12] = -(r + l) / (r - l);matrix[13] = -(t + b) / (t - b);matrix[14] = -(f + n) / (f - n);return matrix;
}
...// how to pass projection matrx to OpenGL
Matrix4 projectionMatrix = setFrustum(l, r, b, t, n, f);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matrixProjection.get());
...
Constructing 16 elements of GL_PROJECTION matrix is explained?here.
總結(jié)
以上是生活随笔為你收集整理的OpenGL 矩阵变换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android:JNI 与 NDK到底是
- 下一篇: Android 应用进行性能分析/APP