OpenGl 球体的公转,自传,移动
绘制的流程:
根据特殊键(SpeacialKeys)移动位置观看效果
ChangeSize函数:自定义函数,当屏幕大小发生变化/第一次创建时,调用函数。
RenderScene函数:屏幕发生变化/主动渲染界面会调用函数。
SpeacialKeys函数:上下左右键控制观看位置
SetupRC函数:需要渲染的图形相关顶点数据/颜色数据的准备工作。
首先在main函数中添加需要使用的函数方法,并且在ChangeSize函数中设置视口,创建透视投影矩阵,并压入栈堆中,通过设置变换管道获取两个堆栈矩阵变换矩阵(变换矩阵modelViewMatrix ,投影矩阵projectionMatrix)。
void ChangeSize(int nWidth, int nHeight){
//1.设置视口
glViewport(0, 0, nWidth, nHeight);
//2.创建投影矩阵,
viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
//viewFrustum.GetProjectionMatrix() 获取viewFrustum投影矩阵
//并将其加载到投影矩阵堆栈上projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//3.设置变换管道以使用两个矩阵堆栈(变换矩阵modelViewMatrix ,投影矩阵projectionMatrix) transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix); //屏幕更改大小或已初始化}
地板的绘制
SetupRC函数:准备顶点数据
RenderScene:利用平面着色器绘制地板
地板绘制流程.png
大球绘制
在绘制地板的基础上开始绘制大球,实现大球的自传效果,由于大球与观察者所处同一位置,因此大球的z轴需要Translate -3.0f,方便观察。
SetupRC函数中开启深度测试
glEnable(GL_DEPTH_TEST);
SetupRC函数:通过系统模型类创建顶点数据
RenderScene函数分为三部:
- 开启定时器
- 设置光源位置,利用点光源着色器绘制大球
- 利用Rotate()实现自传
-
PushMatrix()压栈对应PopMatrix()还原;
大球绘制.png
50个小球的绘制
全局声明:#define NUM_SPHERES 50,通过数组记录50小球的位置
SetupRC函数:通过系统模型类创建顶点数据,通过for循环的方式随机绘制小球顶点数据,处于同一水平y轴不发生改变,x,z发生变化。
//5. 绘制小球;
gltMakeSphere(sphereBatch, 0.1f, 13, 26);
//6. 随机位置放置小球球
for (int i = 0; i < NUM_SPHERES; i++) {
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);
}
RenderScene:利用点光源着色器并通过循环绘制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,vSpereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
绘制50小球.png
绘制小球围绕大球公转
无需SetupRC函数再次绘制小球,直接使用绘制50小球时绘制的小球来使用,方法和绘制大球时一直,不过为了实现围绕大球旋转的效果,小球需要Rotate+Translate实现公转效果。
但是如果Translate+Rotate,那么小气就会出现自传的效果,大家可以尝试看看。
SpeacialKeys(特殊键)
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);
}
到这里,主要功能就实现了,我们可以通过特殊键为观看界面效果。