OpenGL Transformation(openGL zh)

别裁伪体亲风雅,转益多师是汝师。这篇文章主要讲述OpenGL Transformation(openGL zh)相关的知识,希望能为你提供帮助。


参考??英文原版地址??
前言先看一下效果图:模型视图矩阵,
??茶壶工程代码下载地址?? 
??七色珠工程源码下载地址??


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光栅化处理之前:通过OpenGL流水线中的顶点运算和图元装配运算对顶点位置和法向量等几何数据进行变换。

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.

翻译:
OpenGL顶点变换
对象的坐标
它是物体的局部坐标系统,在应用任何变换之前是物体的初始位置和方向。为了转换对象,使用glRotatef(), glTranslatef(), glScalef()。
眼睛坐标(相加坐标)
它是通过GL_MODELVIEW矩阵和对象坐标相乘得到的。利用OpenGL中的GL_MODELVIEW矩阵将对象从对象空间转换为人眼空间。GL_MODELVIEW矩阵是模型矩阵和视图矩阵()的组合。模型变换是从对象空间到世界空间的转换。View transform就是从世界空间向视觉空间的转换。



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 in  ??ModelView 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??.
翻译:
注意OpenGL中没有单独的摄像机(视图)矩阵。因此,为了模拟摄像机或视图的变换,场景(3D对象和灯光)必须用视图变换的逆变换进行变换。换句话说,OpenGL定义了相机在眼空间坐标中始终位于(0,0,0)面向-Z轴,不能进行转换。在ModelView matrix中查看GL_MODELVIEW矩阵的更多细节。
法向量也从物体坐标转换为眼睛坐标进行光照计算。注意法线和顶点的转换方式不同。它是将GL_MODELVIEW矩阵逆的转置乘以一个法向量。更多细节请参阅法向量变换。

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??.
翻译:
裁剪坐标
眼睛坐标现在与GL_PROJECTION矩阵相乘,成为裁剪坐标。这个GL_PROJECTION矩阵定义了观看体积(视椎体); 如何将顶点数据投影到屏幕上(透视或正交)。它之所以被称为剪辑坐标是因为经过转换的顶点(x, y, z)是通过与±w进行比较而被剪辑的。
更多关于GL_PROJECTION矩阵的细节请参见投影矩阵。

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.
翻译:
标准化设备坐标(NDC)
它是通过将裁剪坐标除以w而产生的。它被称为透视分割。它更像是窗口(屏幕)坐标,但是还没有被转换和缩放到屏幕像素。在所有3个轴上,值的范围现在都从-1到1标准化了。

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);
翻译:
窗口坐标(屏幕坐标)
它是通过将标准化设备坐标(NDC)应用于视口转换而产生的。NDC被缩放和翻译以适应呈现屏幕。窗口坐标最终被传递给OpenGL管道的分级过程,成为一个片段。glViewport()命令用于定义最终图像映射的渲染区域的矩形。并且,glDepthRange()用于确定窗口坐标的z值。根据上述两个函数的给定参数计算窗口坐标;
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;
翻译:
通过NDC和窗口坐标之间的线性关系,简单地得到视口变换公式;


OpenGL Transformation Matrix
翻译:
OpenGL变换矩阵



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使用4 × 4矩阵进行变换。注意,矩阵中的16个元素按列主顺序存储为1D数组。你需要转置这个矩阵如果你想把它转换成标准的约定,主要的行格式。
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).
翻译:
OpenGL有4种不同类型的矩阵; GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE和GL_COLOR。你可以在代码中使用glMatrixMode()来切换当前类型。例如,为了选择GL_MODELVIEW矩阵,使用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.
翻译:
模型-视图矩阵(GL_MODELVIEW)
GL_MODELVIEW矩阵将查看矩阵和建模矩阵合并为一个矩阵。为了变换视图(摄像机),你需要用逆变换移动整个场景。gluLookAt()特别用于设置查看转换。



4 columns of GL_MODELVIEW matrix

The 3 matrix elements of the rightmost column (m12m13m14) are for the translation transformation,  glTranslatef(). The element  m15  is the  ??homogeneous coordinate??. It is specially used for projective transformation.
翻译:
4列的GL_MODELVIEW矩阵
最右边列的3个矩阵元素(m12、m13、m14)是用于转换的glTranslatef()。元素m15是齐次坐标。它专门用于射影变换。
3 elements sets, (m0m1m2), (m4m5m6) and (m8m9m10) are for Euclidean and affine transformation, such as rotation  glRotatef()  or scaling  glScalef(). Note that these 3 sets are actually representing 3 orthogonal axes;
【OpenGL Transformation(openGL zh)】翻译:
3个元素集(m0, m1, m2), (m4, m5, m6)和(m8, m9, m10)用于欧几里得和仿射变换,如旋转glRotatef()或缩放glScalef()。注意,这3个集合实际上代表了3个正交的轴;

  • (m0,m1,m2)     : +X axis,leftvector, (1, 0, 0) by default
  • (m4,m5,m6)     : +Y axis,upvector, (0, 1, 0) by default
  • (m8,m9,m10) : +Z axis,forwardvector, (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:
翻译:
我们可以直接从角度或看矢量构造GL_MODELVIEW矩阵,而不用使用OpenGL变换函数。下面是一些构建GL_MODELVIEW矩阵的有用代码:
  • ??Angles to Axes??
  • ??Lookat to Axes??
  • ??Rotation About Arbitrary Axis??
  • ??Quaternion to Rotation Matrix??
  • ??Matrix4 class??
翻译:
坐标轴角度
看向轴
任意轴旋转
四元数到旋转矩阵
Matrix4类
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.
翻译:
注意,如果对一个顶点应用多个变换,OpenGL会以相反的顺序执行矩阵乘法。例如,如果一个顶点先被MA转换,然后被MB转换,那么OpenGL在乘以顶点之前先执行MB x MA。因此,在代码中,最后一个转换首先出现,第一个转换最后出现。


// 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;   leftrightbottomtopnear  and  far  planes. 8 vertices of the viewing frustum are shown in the following image.
翻译:
投影矩阵(GL_PROJECTION)
GL_PROJECTION矩阵用于定义视椎体。这个截锥决定哪些对象或对象的一部分将被剪掉。同时,它决定了3D场景如何被投影到屏幕上。(请参阅更多的细节如何构造投影矩阵。)
OpenGL为GL_PROJECTION转换提供了两个函数。glFrustum()是产生一个透视投影,glOrtho()是产生一个正投影(平行)投影。两个函数都需要6个参数来指定6个剪切平面; 左、右、下、上、近、远平面。视图截锥的8个顶点如下图所示。



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透视视图截锥
远(后)平面的顶点可以简单地通过相似三角形的比例来计算,例如,远平面的左边为;




OpenGL Orthographic Frustum

For orthographic projection, this ratio will be 1, so the  leftrightbottom  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.
翻译:
OpenGL正字法的平截头体
对于正投影,这个比值将是1,所以远平面的左、右、底和顶值将与近平面相同。
你也可以使用带有较少参数的gluPerspective()和gluOrtho2D()函数。gluPerspective()只需要4个参数; 垂直视场(FOV),宽高宽高比和近、远剪切面距离。下面的代码描述了从gluPerspective()到glFrustum()的等价转换。
// 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 fovY
double height = front * tangent; // half height of near plane
double width = height * aspectRatio; // half width of near plane

// params: left, right, bottom, top, near, far
glFrustum(-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 (strq) 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.
翻译:
一个不对称截锥体的例子
但是,如果你需要创建一个非对称的视觉体,你必须直接使用glFrustum()。例如,如果你想将一个宽阔的场景渲染到两个相邻的屏幕,你可以将截锥拆分成两个不对称截锥(左截锥和右截锥)。然后,用每个截锥渲染场景。
纹理矩阵(GL_TEXTURE)
在任何纹理映射之前,纹理坐标(s, t, r, q)乘以GL_TEXTURE矩阵。默认情况下它是标识,所以纹理将被映射到指定纹理坐标的对象上。通过修改GL_TEXTURE,您可以滑动、旋转、拉伸和收缩纹理。
// rotate texture around X-axis
glMatrixMode(GL_TEXTURE);
glRotatef(angle, 1, 0, 0);

Color Matrix (GL_COLOR)
The color components (rgba) 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_imaging  extension.
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.
glLoadMatrixfd(m)  : 
replace the current matrix with the matrix  m.
glLoadTransposeMatrixfd(m)  : 
replace the current matrix with the row-major ordered matrix  m.
glMultMatrixfd(m)  : 
multiply the current matrix by the matrix  m, and update the result to the current matrix.
glMultTransposeMatrixfd(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.
翻译:
颜色矩阵(GL_COLOR)
颜色分量(r, g, b, a)乘以GL_COLOR矩阵。它可以用于颜色空间转换和颜色组件交换。GL_COLOR矩阵不常用,需要GL_ARB_imaging扩展。
其他矩阵的例程
glPushMatrix ():
将当前矩阵推入当前矩阵堆栈。
glPopMatrix ():
从当前矩阵堆栈中弹出当前矩阵。
glLoadIdentity ():
将当前矩阵设置为单位矩阵。
glLoadMatrix fd(m):
将当前矩阵替换为矩阵m。
glLoadTransposeMatrix fd(m):
将当前矩阵替换为主要的有序矩阵m。
glMultMatrix fd(米):
将当前矩阵乘以矩阵m,并将结果更新为当前矩阵。
glMultTransposeMatrix fd(m):
将当前矩阵乘以主要的有序矩阵m,并将结果更新为当前矩阵。
glGetFloatv (GL_MODELVIEW_MATRIX, m):
将GL_MODELVIEW矩阵的16个值返回给m。
Example: ModelView Matrix
This demo application shows how to manipulate GL_MODELVIEW matrix by translation and rotation transforms.
Download the source and binary:
翻译:
例如:ModelView矩阵
这个演示应用程序展示了如何通过平移和旋转变换来操作GL_MODELVIEW矩阵。
下载源代码和二进制文件:
(Updated: 2019-12-06)
??
matrixModelView.zip??  (include VS 2015 project)
???
matrixModelView_mac.zip??  (macOS 10.12+, include Xcode v11)
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;
翻译:
请注意,所有OpenGL函数调用都是在Mac和Windows版本上的ModelGL.h和ModelGL.cpp中实现的,并且这些文件在两个包上是相同的(与平台无关)。
这个演示应用程序使用自定义4x4矩阵类以及默认的OpenGL矩阵例程,以指定模型和相机变换。在ModelGL.cpp中定义了3个矩阵对象; matrixModel, matrixView和matrixModelView。每个矩阵存储预先计算的转换,并通过使用glLoadMatrixf()将矩阵元素传递给OpenGL。实际的绘图程序是这样的;
...
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;
翻译:
使用默认OpenGL矩阵函数的等效代码是;
...
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:
翻译:
这个演示应用程序展示了如何操作6个参数的投影转换; 左,右,下,上,近和远值。
下载源代码和二进制文件:
(Updated: 2019-11-25)
??
matrixProjection.zip??  (include VS 2015 project)
???
matrixProjection_mac.zip??  (macOS 10.12+, include Xcode v11)
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().
翻译:
同样,ModelGL.h和ModelGL.cpp是两个包上完全相同的文件(与平台无关),所有的OpenGL函数调用都放在这些文件中。
ModelGL类有一个自定义矩阵对象matrixProjection和2个成员函数setFrustum()和setOrthoFrustum(),它们等价于glFrustum()和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 fovY
float height = front * tangent; // half height of near plane
float width = height * aspectRatio; // half width of near plane

// params: left, right, bottom, top, near, far
return 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??.
翻译:
本文介绍了GL_PROJECTION矩阵16个元素的构造方法。

    推荐阅读