这是我们将要实现的效果

通过分析,需要通过以下步骤实现
- 绘制绿色方格地板;
- 绘制中心位置的红色大球,并实现其自转;
- 绘制随机位置的50个静态小球和一个围绕红色大球公转的蓝色球;
- 实现动态蓝色球绕红色大球的公转;
- 实现移动观察者,观察红色大球自转及蓝色球公转的效果;
一、绘制地板
ChangeSize 设置视口和投影方式:设定投影投影矩阵并矩阵堆栈;
glViewport(0, 0, w, h);
// 创建投影矩阵(透视投影)
viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.f);
// 获取viewFrustum投影矩阵,并将其加载到投影矩阵堆栈上
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
/* 设置变换管道以使用两个矩阵堆栈(变换矩阵modelViewMatrix ,投影矩阵projectionMatrix)
* 初始化 GLGeometryTransform 的实例transformPipeline,通过将它的内部指针设置为模型视图矩阵堆栈和 投影矩阵堆栈实例,来完成初始化
* 这个操作也可以在SetupRC函数中完成,在窗口大小改变时或者窗口创建时设置,可以一次性完成矩阵和管线的设置。
*/
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
SetupRC() :准备绘制地板的顶点数据;
// 初始化
glClearColor(0.f, 0.f, 0.f, 1.f);
shaderManager.InitializeStockShaders();
// 开启深度测试
glEnable(GL_DEPTH_TEST);
// 设置地板顶点数据,由324个矩阵组成
floorBatch.Begin(GL_LINES, 324);
for (GLfloat x = -20.f; x <= 20.f; x += 0.5f) {
floorBatch.Vertex3f(x, -0.55f, 20.f);
floorBatch.Vertex3f(x, -0.55f, -20.f);
floorBatch.Vertex3f(20.f, -0.55f, x);
floorBatch.Vertex3f(-20.f, -0.55f, x);
}
floorBatch.End();
RenderScence():绘制绿色地板
// 清除颜色缓存区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 地板的颜色
static GLfloat vFloorColor[] = {0.f, 1.f, 0.f, 1.f};
shaderManager.UseStockShader(GLT_SHADER_FLAT,
transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor);
floorBatch.Draw();
// 执行缓存区交换
glutSwapBuffers();
二、绘制红色大球
// 清除颜色缓存区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// // 地板的颜色
// static GLfloat vFloorColor[] = {0.f, 1.f, 0.f, 1.f};
// 红色大球的颜色
static GLfloat vTorusColor[] = {1.f, 0.f, 0.f, 1.f};
// 动画定时器
static CStopWatch rotTimer;
float yPot = rotTimer.GetElapsedSeconds() * 60.f;
// 压栈
modelViewMatrix.PushMatrix();
// // 绘制地板
// shaderManager.UseStockShader(GLT_SHADER_FLAT,
// transformPipeline.GetModelViewProjectionMatrix(),
// vFloorColor);
// floorBatch.Draw();
// 获取光源位置
M3DVector4f vLightPods = {0.f, 10.f, 5.f, 1.f};
// 使得红色大球位置向屏幕里面平移(3.0)
modelViewMatrix.Translate(0.f, 0.f, -3.f);
// 压栈(复制栈顶)
modelViewMatrix.PushMatrix();
// 红色大球自转
modelViewMatrix.Rotate(yPot, 0.f, 1.f, 0.f);
// 指定着色器(点光源着色器)
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,
transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPods,
vTorusColor);
torusBatch.Draw();
// 绘制完毕出栈Pop(PushMatrix与PopMatrix一一对应)
modelViewMatrix.PopMatrix();
modelViewMatrix.PopMatrix();
// 执行缓存区交换
glutSwapBuffers();
glutPostRedisplay();
三、绘制绿色球
绘制50个随机球
// 绘制随机位置的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(),
vLightPods,
vSphereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
绘制蓝色大球并围绕红色球公转
//绘制静态小球
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();
四、移动观察者
void SpeacialKeys(int key,int x,int y){
float linear = 0.1f;
float angular = float(m3dDegToRad(5.0f));
if (key == GLUT_KEY_UP) {
cameraFrame.MoveForward(linear);
}
if (key == GLUT_KEY_DOWN) {
cameraFrame.MoveForward(-linear);
}
if (key == GLUT_KEY_LEFT) {
cameraFrame.RotateWorld(angular, 0, 1, 0);
}
if (key == GLUT_KEY_RIGHT) {
cameraFrame.RotateWorld(-angular, 0, 1, 0);
}
}