相关主题:OpenGL 渲染管线,OpenGL 投影矩阵,OpenGL矩阵类
下载:matrixModelView.zip,matrixProjection.zip
// 注意对象首先被平移,然后被旋转
glRotatef(angle, 1, 0, 0); // 将对象绕x轴旋转angle角度
glTranslatef(x, y, z); // 移动对象到(x,y,z)处
drawObject();
// 这创建了一个对称的截头锥
// 它将给定的4个参数(fovy, aspect, near, far)转换
// 成glFrustum()所需的6个参数:(l, r, b, t, n, f)
void makeFrustum(double fovY, double aspectRatio, double front, double back)
{
const double DEG2RAD = 3.14159265 / 180;
double tangent = tan(fovY/2 * DEG2RAD); // fovY的一半的正切,fovY是视线的夹角
double height = front * tangent; // 近裁剪面的高度的一半
double width = height * aspectRatio; // 近裁剪面的宽度的一半
// params: left, right, bottom, top, near, far
glFrustum(-width, width, -height, height, front, back);
}
然而,如果你需要创建一个不对称的视景体那么必须直接使用glFrustum()函数。例如,如果你需要渲染一个宽屏场景到两个邻接的屏幕中,你可以将视景体划分成两个不对称的视景体(左边和右边),然后将场景分别渲染到两个视景体中,如下图:
// 将纹理绕x轴旋转
glMatrixMode(GL_TEXTURE);
glRotatef(angle, 1, 0, 0);
注意无论在Mac下还是在Windows下所有的OpenGL函数调用都是在ModelGL.h和ModelGL.cpp中实现的,在两个包中所有文件都是相同的。
这个例子程序使用一个自定义的4*4矩阵类和OpenGL默认的矩阵模式来指定模型变换和视图变换。ModelGL.cpp中定义了3个矩阵对象:matrxModel,matrixView和matrixModelView。每个矩阵存储了前乘的变换并使用glLoadMatrix()函数将矩阵中的元素传递到OpenGL中。实际的绘图模式如下:
...
glPushMatrix();
// 为视图变换设置视图矩阵
glLoadMatrixf(matrixView.getTranspose());
// 在模型变换之前绘制最原始的网格
drawGrid();
// 为模型变换和视图变换设置模型视图矩阵
// 从物体坐标系变换到人眼坐标系
glLoadMatrixf(matrixModelView.getTranspose());
// 模型视图变换之后绘制一个茶壶
drawTeapot();
glPopMatrix();
...
...
glPushMatrix();
// 将模型视图矩阵归一化
glLoadIdentity();
// 首先,将视图从物体坐标系变换到人眼坐标系
// 注意所有的值都是负数,因为我们是使用视图矩阵的逆来移动整个场景
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]);
// 在模型变换之前绘制最原始的网格
drawGrid();
// 模型变换
// GL_MODELVIEW矩阵的结果如下:
// ModelView_M = View_M * Model_M
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);
// 模型视图变换之后绘制一个茶壶
drawTeapot();
glPopMatrix();
...
这个例子程序显示了如何使用glFrustum()函数和glOrtho()函数来操作投影变换。
下载源代码和可执行程序:matrixProjection.zipmatrixProjection_mac.zip(OS X 10.6+)
再次说明,ModelGL.h和ModelGL.cpp在Window和Mac下是一样的,并且所有的OpenGL函数调用都在这两个文件中。
ModelGL类有一个自定义的矩阵对象,matrixProjection,和两个成员函数,setFrustum()和setOrthoFrustum(),这两个函数等价于glFrustum()和glOrtho()。
///////////////////////////////////////////////////////////////////////////////
// 使用6个参数像glFrustum()函数一样设置一个透视的视景体
// (left, right, bottom, top, near, far)
// 注意:这是以行为主的标记方式,OpenGL需要先将其转置
///////////////////////////////////////////////////////////////////////////////
void ModelGL::setFrustum(float l, float r, float b, float t, float n, float f)
{
matrixProjection.identity();
matrixProjection[0] = 2 * n / (r - l);
matrixProjection[2] = (r + l) / (r - l);
matrixProjection[5] = 2 * n / (t - b);
matrixProjection[6] = (t + b) / (t - b);
matrixProjection[10] = -(f + n) / (f - n);
matrixProjection[11] = -(2 * f * n) / (f - n);
matrixProjection[14] = -1;
matrixProjection[15] = 0;
}
///////////////////////////////////////////////////////////////////////////////
// 使用6个参数像glOrtho()函数一样设置一个正投影的视景体
// (left, right, bottom, top, near, far)
// 注意:这是以行为主的标记方式,OpenGL需要先将其转置
///////////////////////////////////////////////////////////////////////////////
void ModelGL::setOrthoFrustum(float l, float r, float b, float t, float n,
float f)
{
matrixProjection.identity();
matrixProjection[0] = 2 / (r - l);
matrixProjection[3] = -(r + l) / (r - l);
matrixProjection[5] = 2 / (t - b);
matrixProjection[7] = -(t + b) / (t - b);
matrixProjection[10] = -2 / (f - n);
matrixProjection[11] = -(f + n) / (f - n);
}
...
// 将投影矩阵传递给OpenGL
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matrixProjection.getTranspose());
...
构造一个16个元素的GL_PROJECTION矩阵可以参考这儿。