OpenGL中的变换矩阵及自定义矩阵

OpenGL中的变换矩阵的实现

OpenGL中的变换矩阵是一个4x4的数阵,使用一个包含16个元素的一维数组表示。其中,前4个元素表示矩阵的第一列,接下来的4个元素表示矩阵的第2列。即OpenGL中的矩阵运算是使用列主序矩阵的,前三列各表示xyz三个轴的方向向量,第4列表示位移变换。

自定义变换矩阵

1.为矩阵开辟存储空间

//M3DMatrix44f表示使用math3d.h中定义的一个包含16个元素的一维数组
M3DMatrix44f   transformationMatrix; 

2.创建矩阵

//这里创建一个绕y轴旋转的旋转矩阵
m3dRotationMatrix44(transformationMatrix, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);

3.指定位移向量

//指定位移向量,变换矩阵的第四列
transformationMatrix[12] = 0.0f;
transformationMatrix[13] = 0.0f;
transformationMatrix[14] = -2.5f;

4.利用创建好的矩阵变换物体的各个顶点

//m3dTransformVector3:math3d.h中定义的函数,执行顶点的变换操作
//transformedVertex:变换后的顶点坐标,包含3个元素的一维数组
//objectVertex:原始顶点坐标,包含3个元素的一维数组
//mTransform:变换矩阵
m3dTransformVector3(transformedVertex, objectVertex, mTransform);

5.示例

// Transform.cpp
#include "../../shared/gltools.h"
#include "../../shared/math3d.h"    // 3D Math Library
#include <math.h>

//定义一个圆环面
// Draw a torus (doughnut), using the current 1D texture for light shading
void DrawTorus(M3DMatrix44f mTransform)
{
    GLfloat majorRadius = 0.35f;//内环半径+环半径
    GLfloat minorRadius = 0.15f;//环半径
    GLint   numMajor = 40;
    GLint   numMinor = 20;
    M3DVector3f objectVertex;         // Vertex in object/eye space
    M3DVector3f transformedVertex;    // New Transformed vertex   
    double majorStep = 2.0f*M3D_PI / numMajor;
    double minorStep = 2.0f*M3D_PI / numMinor;
    int i, j;

    for (i=0; i<numMajor; ++i) 
    {
        double a0 = i * majorStep;
        double a1 = a0 + majorStep;
        GLfloat x0 = (GLfloat) cos(a0);
        GLfloat y0 = (GLfloat) sin(a0);
        GLfloat x1 = (GLfloat) cos(a1);
        GLfloat y1 = (GLfloat) sin(a1);

        glBegin(GL_TRIANGLE_STRIP);
        for (j=0; j<=numMinor; ++j) 
        {
            double b = j * minorStep;
            GLfloat c = (GLfloat) cos(b);
            GLfloat r = minorRadius * c + majorRadius;
            GLfloat z = minorRadius * (GLfloat) sin(b);

            // First point
            objectVertex[0] = x0*r;
            objectVertex[1] = y0*r;
            objectVertex[2] = z;
            m3dTransformVector3(transformedVertex, objectVertex, mTransform);
            glVertex3fv(transformedVertex);

            // Second point
            objectVertex[0] = x1*r;
            objectVertex[1] = y1*r;
            objectVertex[2] = z;
            m3dTransformVector3(transformedVertex, objectVertex, mTransform);
            glVertex3fv(transformedVertex);
        }
        glEnd();
    }
}


// Called to draw scene
void RenderScene(void)
{
    M3DMatrix44f   transformationMatrix;   // 为旋转矩阵开辟空间,M3DMatrix44f是在math3d.h中定义的一个包含16个元素的一维数组。
    static GLfloat yRot = 0.0f;         // Rotation angle for animation
    yRot += 0.5f;

    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 创建一个旋转矩阵,绕y轴旋转,创建之后的矩阵存储在transformationMatrix中
    m3dRotationMatrix44(transformationMatrix, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);
    //指定位移向量,变换矩阵的第四列
    transformationMatrix[12] = 0.0f;
    transformationMatrix[13] = 0.0f;
    transformationMatrix[14] = -2.5f;

    //画一个圆环面,根据创建的旋转矩阵,变换圆环面上的各个顶点
    DrawTorus(transformationMatrix);

    // Do the buffer Swap
    glutSwapBuffers();
}

// This function does any needed initialization on the rendering
// context. 
void SetupRC()
{
    // 设置蓝色背景
    glClearColor(0.0f, 0.0f, .50f, 1.0f );

    // 以线框方式画所有的物体
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

///
// Called by GLUT library when idle (window not being
// resized or moved)
void TimerFunction(int value)
{
    // Redraw the scene with new coordinates
    glutPostRedisplay();
    //没33ms调用刷新调用一次RenderScene方法,刷新屏幕
    glutTimerFunc(33,TimerFunction, 1);
}

void ChangeSize(int w, int h)
{
    GLfloat fAspect;

    // Prevent a divide by zero, when window is too short
    // (you cant make a window of zero width).
    if(h == 0)
        h = 1;

    glViewport(0, 0, w, h);

    fAspect = (GLfloat)w / (GLfloat)h;

    // Reset the coordinate system before modifying
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Set the clipping volume
    gluPerspective(35.0f, fAspect, 1.0f, 50.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800,600);
    glutCreateWindow("Manual Transformations Demo");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);

    SetupRC();
    glutTimerFunc(33, TimerFunction, 1);

    glutMainLoop();

    return 0;
}

拓展:变换的叠加

1.glut中封装的矩阵变换

2.math3d.h中定义的矩阵变换函数:m3dMatrixMultiply()

3.OpenGL中自己的矩阵乘法函数:glMultMatrix(),这个函数接受一个矩阵,并把它与当前加载的矩阵相乘,然后把结果存储在矩阵堆栈的顶部。

总结

虽然自定义变换矩阵很灵活,但是这么干是非常低效的。因为我们math3d.h中的函数完成的矩阵变换,是由CPU执行计算的,而不是让OpenGL的专用硬件为我们完成这些工作。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值