美文网首页
OpenGL-公转自转demo

OpenGL-公转自转demo

作者: 过气的程序员DZ | 来源:发表于2020-07-15 17:37 被阅读0次

开场白

本文主要介绍用OpenGL实现的效果:大球自转,小球围绕大球公转的效果。如图:


效果图

示例代码地址
本例中使用的是以调整观察者位置的方式进行移动的,也可以修改成调整物体的方式,代码中有相关代码,只是注释了。

主要代码

渲染方法:

void RenderScene(void) {
    // 1
    //地板颜色
    static GLfloat vFloorColor[] = {0.0, 1.0, 0.0, 1.0};
    //打球颜色
    static GLfloat vTorusColor[] = {1, 0, 0, 1};
    //小球颜色
    static GLfloat vSphereColor[] = {0, 0, 1, 1};
    
    //2
    //此处需要使用静态变量 原因CStopWatch中有一个成员变量m_LastCount,需要记录,当调用GetElapsedSeconds时,内部实现是当前的秒数与m_LastCount中的秒数进行插值
    static CStopWatch rotTimer;
    //旋转度数
    float yRot = rotTimer.GetElapsedSeconds() * 60;
    
    //3
    //清除一个或一组特定的缓冲区
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    
    //4.观察者
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    
    //入栈-保存观察者位置
    modelViewMatrix.PushMatrix(mCamera);
    
//    modelViewMatrix.PushMatrix(objectFrame);
    
    //5渲染地板
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor);
    floorBatch.Draw();
    
    //光源
    M3DVector4f vLightPos = {0.0f, 10.0f, 5.0f, 1.0f};
    
    //6渲染大球
    modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
    modelViewMatrix.PushMatrix();
    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vLightPos, vTorusColor);
    torusBatch.Draw();
    modelViewMatrix.PopMatrix();
    
    //7渲染50个(NUM_SPHERES)随机小球
    for (int i = 0; i < NUM_SPHERES; i++) {
        modelViewMatrix.PushMatrix();
        modelViewMatrix.MultMatrix(spheres[I]);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vLightPos, vSphereColor);
        sphereBatch.Draw();
        modelViewMatrix.PopMatrix();
    }
    
    //8渲染一个小球绕着打球旋转
    modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
    modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
//    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vSphereColor);

    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vLightPos, vSphereColor);
    sphereBatch.Draw();
    
    //出栈-与上面观察者的入栈 保持出入栈一致
    modelViewMatrix.PopMatrix();
    
    //将在后台缓冲区进行渲染,然后在结束时交换到前台
    glutSwapBuffers();
    //9触发重新绘制
    glutPostRedisplay();
}
}

代码简要逻辑:

  1. 定义了地板、大球和小球的颜色
  2. 定义一个定时器变量rotTimer。这个地方一定要使用static静态方式,因为RenderScene在不停的调用,需要拿到上次的值。
  3. 清空缓冲区
  4. 定义观察者矩阵,并加入到modelView矩阵堆栈中
  5. 绘制地板
  6. 绘制大球,并自转
  7. 绘制50个随机小球
  8. 绘制绕大球公转的小球
  9. 触发重新绘制方法

modelViewMatrix栈变换流程

modeViewMatrix变换流程

这张图表达了整个代码中modeViewMatrix矩阵变化的过程:

  1. modelViewMatrix在初始化的时候会默认加入一个单元矩阵
  2. 加入观察者矩阵
  3. 准备渲染大球的时候,调用modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);,此时会把栈顶元素取出进行矩阵乘法,然后替换栈顶元素。然后将栈顶元素再入栈一次,目的是保存之前的状态。因为栈顶元素会被后面的旋转操作修改。
  4. 旋转处理,与第三不类似,但是不用保存状态。
  5. 大球绘制后,出栈。此时栈顶是camero矩阵移动后的结果。
  6. 开始绘制随机50个小球,入栈出栈,与之前操作没什么区别
  7. 开始绘制公转小球

相关文章

  • OpenGL-公转自转demo

    开场白 本文主要介绍用OpenGL实现的效果:大球自转,小球围绕大球公转的效果。如图: 示例代码地址本例中使用的是...

  • OpenGL纹理案例-球体世界

    开场白 本文在我之前的文章OpenGL-公转自转demo中的demo为基础,添加纹理。效果图: 简述逻辑 Setu...

  • 自转公转

    如同光和热 以及引力 我的世界明暗和重心 都在有你的这边 如同潮汐和磁场 我的世界出现风暴或极光 都由你决定

  • 公转自转

    转转转 公转自转, 年年环 月不偷懒。 转转转 从不晕转, 日日忙 夜不停暂。 异参照 异向公转, 时时绕 刻不容...

  • 自转&公转

    18世纪美国最伟大的科学家,著名的政治家和文学家,杰出的外交家及发明家本杰明.富兰克林说过一句话 “世上有...

  • 自转和公转

    文/独上西楼 风扇 自转成一个星球时 每个人 也都是一个星球 星球们 围绕着另一个星球 自转与公转 从一档加速到五...

  • 自转、公转脚本

    自转 public class StarRotation : MonoBehaviour { public flo...

  • 自转和公转

    任何成熟的物质体系都拥有自转和公转两大运动体系。 比如我们生存的地球就是一个成熟的物质体系,已经存在四十多亿年。并...

  • 地球为什么是倾斜的?

    地球在公转的同时还在自转,自转轴与公转平面并不是垂直关系,二者之间的夹角是66.5度,即自转轨道面与公转轨道面并不...

  • 为什么月球永远都只有一面朝向地球?

    今天要分享的是:月球自转与公转之谜 月球在自转的同时也在公转,巧合的是它的自转速度和它围着地球公转的速度一模一样,...

网友评论

      本文标题:OpenGL-公转自转demo

      本文链接:https://www.haomeiwen.com/subject/mvljhktx.html