美文网首页
OpenGL-- 小球绕大球公转案例解析

OpenGL-- 小球绕大球公转案例解析

作者: HardCabbage | 来源:发表于2020-07-19 20:49 被阅读0次

一、 效果图 大球自传,并且小球绕着公转效果图

代码思路:

  • 先绘制地板
  • 地板 + 大球的效果
  • 地板+ 大球+小球的效果
  • 地板+大球+小球+公转自传的效果
  • 地板+大球+小球+公转自传 + 移动效果
    我们按照上线的思路进行处理,最终得到我们想要的效果。

二、绘制地板效果

2.1基本流程设置代码
#include "GLTools.h"
#include "GLShaderManager.h"
#include "GLFrustum.h"
#include "GLBatch.h"
#include "GLMatrixStack.h"
#include "GLGeometryTransform.h"
#include "StopWatch.h"

#include <math.h>
#include <stdio.h>

#ifdef ____
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
void SetupRC()
{
    
}
void RenderScene(void){
    
}
void ChangeSize(int nWidth, int nHeight){
    
}
int main(int argc, char* argv[]){
    gltSetWorkingDirectory(argv[0]);
    //初始化一个GLUT库
    glutInit(&argc, (char**)argv);
    //创建一个窗口并且定制窗口名称
    glutCreateWindow("OpenGL SphereWorld");
    glutReshapeFunc(ChangeSize);

    //注册一个绘图函数,操作系统在必要时刻会对窗体进行重绘制操作
    //它设置了一个显示回调(diplay callback),即GLUT在每次更新窗口内容的时候回自动调用该例程
    glutDisplayFunc(RenderScene);
    //这是一个无限执行的循环,它会负责一直处理窗口和操作系统的用户输入等操作。(注意:不会执行在glutMainLoop()之后的所有命令。)
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }
    
    
    SetupRC();
    glutMainLoop();
return 0;
    
}
2.2地板绘制

设置地板的顶点数据

   for (GLfloat x=-20.0; x<=20.f; x+=0.5) {
        floorBatch.Vertex3f(x, -0.55f, 20.0f);
        floorBatch.Vertex3f(x, -0.55f, -20.0f);
        
        floorBatch.Vertex3f(20.0f, -0.55f, x);
        floorBatch.Vertex3f(-20.0f, -0.55f, x);
    }
地板效果图
2.3绘制大球
  • 使用void gltMakeSphere(GLTriangleBatch& sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks);设置大球模型gltMakeSphere(torusBatch, 0.4f, 40, 80);
  • 此处我们设置光源位置
M3DVector4f vLightPos = {0.0f,10.0f,5.0f,1.0f};
    
     //5.使得大球位置平移(3.0)向屏幕里面
     modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
     //6.压栈(复制栈顶)
     modelViewMatrix.PushMatrix();
     //7.大球自转
     modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
     //8.指定合适的着色器(点光源着色器)
     shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
                                  transformPipeline.GetProjectionMatrix(), vLightPos, vTorusColor);
     torusBatch.Draw();

注意:针对我们上线绘制地板的时候已经压栈过一次,所以下面需要两次出栈的操作。由于新绘制了大球所以需要调用glutPostRedisplay();操作,重新渲染一遍才能正常显示。

地板+大球的效果图
绘制地板+大球+小球
  • 设置小球的个数并且用数组将每个小球的顶点数据存起来
#define NUM_SPHERES 50
GLFrame spheres[NUM_SPHERES];
  • 随机设置小球的位置
   for (int i = 0; i < NUM_SPHERES; i++) {
        
        //y轴不变,X,Z产生随机值
        GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
        GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
        
        //在y方向,将球体设置为0.0的位置,这使得它们看起来是飘浮在眼睛的高度
        //对spheres数组中的每一个顶点,设置顶点数据
        spheres[i].SetOrigin(x, 0.0f, z);
    }
  • 绘制50个小球
 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();
        
    }
地板+大球+小球效果图
设置一个蓝球绕红球公转
  • 绘制一个蓝球 ,设置旋转平移
modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
    modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSphereColor);
    sphereBatch.Draw();
一个蓝球绕红球公转
移动上下左右键改变观察者位置
  • 加入观察者
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.PushMatrix(mCamera);
  • 判断特殊键的方法实现
void SpeacialKeys(int key,int x,int y){
    //移动步长
    float linear = 0.1f;
    //旋转度数
    float angular = float(m3dDegToRad(5.0f));
    
    if (key == GLUT_KEY_UP) {
        //MoveForward 平移
        cameraFrame.MoveForward(linear);
    }
    if (key == GLUT_KEY_DOWN) {
        cameraFrame.MoveForward(-linear);
    }
    
    if (key == GLUT_KEY_LEFT) {
        //RotateWorld 旋转
        cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
    }
    
    if (key == GLUT_KEY_RIGHT) {
        cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
    }
    
    
}
移动效果图

相关文章

  • OpenGL-- 小球绕大球公转案例解析

    一、 效果图大球自传,并且小球绕着公转效果图 代码思路: 先绘制地板 地板 + 大球的效果 地板+ 大球+小球的效...

  • 案例09:球体世界

    OpenGL + OpenGL ES +Metal 系列文章汇总 本案例是基于案例06:大球自转+小球公转+移动的...

  • OpenGL案例08:球体世界

    本案例是基于案例06:大球自转+小球公转+移动[https://www.jianshu.com/p/4896498...

  • OpenGL纹理综合案例

    之前用OpenGL做了一个关于大球公转,小球自转的案例,现在我们通过纹理去绘制大球小球和地板,呈现出一个有倒影的画...

  • 03源码--007--纹理应用:球体世界

    案例 03源码--004--综合案例:太阳系:讲述了如何绘制一个球体世界,大球自转,小球公转;案例 03源码--0...

  • 案例06:大球自转+小球公转+移动

    OpenGL + OpenGL ES +Metal 系列文章汇总 这个案例是OpenGL中的一个比较经典的综合案例...

  • OpenGL综合案例(大球自转,小球公转)

    在之前我写过几篇博客,关于OpenGL的一些专业名词的介绍,绘制一些简单的图形(三角形,正方形,球,金字塔等图案)...

  • OpenGL综合练习

    大球自传小球公转案例是OpenGL比较综合的一个经典案例,案例效果如下所示,接下来我们将一步一步得来完成这个经典案...

  • 案例分析5:OpenGL下的球体世界

    本案例是基于案例分析2:大球自转+小球公转+移动的基础上增加了纹理和镜像显示,最终的效果如图所示 对应代码地址纹理...

  • 案例分析2:大球自转+小球公转+移动

    最终效果 这次利用前面学过的知识来完成一个综合项目,在一个场景中绘制地板、大球、小球、公转自转和相机的移动。 对应...

网友评论

      本文标题:OpenGL-- 小球绕大球公转案例解析

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