OpenGL综合练习:大球自转+小球公转+移动

2020-07-18  本文已影响0人  w執念

该案例的实现效果是在一个场景中绘制地板、大球、小球、公转自转和相机的移动,其中结合了OpenGL中大部分知识点,我们先看看最终的效果


效果图.gif

可以看到,这最终效果主要有以下3部分构成:
1.绿色的地板
2.自转的红色大球
3.50个随机分布的蓝色小球以及1个围绕大球公转的动态小球
下面我们主要说说这三部分是如何绘制的

地板

地板的绘制主要分为两步:
1.SetupRC函数:准备地板的顶点数据
2.RenderScene函数:利用平面着色器绘制地板

//SetupRC中
floorBatch.Begin(GL_LINES, 324);
for(GLfloat x = -20.0; x <= 20.0f; 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);
}
floorBatch.End();
//RenderScene中
 static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f};//颜色值
 shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vFloorColor);
 floorBatch.Draw();

大球

绘制大球,并实现其自转功能,主要步骤如下:
1.SetupRC函数:利用系统类创建大球
2.RenderScene函数:首先设置一个定时器,通过这个定时器得到弧度,再通过大球的绘制配合旋转方法实现大球的自转。这里为了可以直观的看到效果,我对大球设置了一个线填充

 gltMakeSphere(torusBatch, 0.3f, 40, 80);//后三个为球半径,片段数,堆叠数
static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
//设置点光源位置
M3DVector4f vLightPos = {0,10,10,1};
modelViewMatrix.Translate(0.0f, 0.2f, -3.0f);
modelViewMatrix.PushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//设置线填充
modelViewMatrix.Rotate(yRot, 0, 1, 0);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transform Pipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vTorusColor);
torusBatch.Draw();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
modelViewMatrix.PopMatrix();

小球

大球绘制完后,我们继续绘制小球,方法如下:
1.SetupRC函数:初始化小球数据
2.RenderScene函数:首先绘制50个静态小球,每绘制一个小球都需要进行push和pop操作,再矩阵通过堆栈记录旋转+平移的变换,绘制动态小球。

gltMakeSphere(sphereBatch, 0.1f, 13, 26);
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);
        //对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,vSpereColor);
        sphereBatch.Draw();
        modelViewMatrix.PopMatrix();
    }
    
// 矩阵堆栈记录旋转,平移操作
    modelViewMatrix.Rotate(yRot * -1.0f, 0, 1, 0);
    modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
    sphereBatch.Draw();

注:这里的rotate+tranalate的顺序是不能互换的,因为矩阵相乘是叉乘,不满足交换律,修改后会产生不同的效果,具体大家可以自己修改代码尝试一下。

完整的代码见OpenGL整合

上一篇 下一篇

猜你喜欢

热点阅读