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

2020-07-19  本文已影响0人  HardCabbage

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

代码思路:

二、绘制地板效果

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绘制大球
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);
    }
 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);
    }
    
    
}
移动效果图
上一篇 下一篇

猜你喜欢

热点阅读