公轉(zhuǎn)和自轉(zhuǎn)是OpenGL中的一個(gè)經(jīng)典案例耻矮,先來看看效果:
方法分析
1秦躯、對(duì)圖形數(shù)據(jù)初始化,需要調(diào)用setupRC()方法
2裆装、窗口大小變動(dòng)時(shí)踱承,需要調(diào)用changeSize(int,int)方法
3、每次繪制時(shí)哨免,需要調(diào)用RenderScene()方法
4茎活、按鍵盤移動(dòng),需要調(diào)用SpecialKey(int,int,int)方法
變量分析
1铁瞒、地面容器 GLBatch floorBatch
2妙色、紅色球體 GLTriangleBatch redBatch
3、藍(lán)色球體 GLTriangleBatch blueBatch
4慧耍、 觀察者 GLFrame camera
5、遠(yuǎn)處球體坐標(biāo) GLFrame spheres[NUM_SPHERES]
運(yùn)行流程:
1丐谋、main函數(shù)中先進(jìn)行初始化設(shè)置
2芍碧、在SetupRC中初始化圖形參數(shù)
3、設(shè)置視圖尺寸觸發(fā)changSize()
4号俐、每次渲染時(shí)執(zhí)行RenderScene()
5泌豆、鍵盤輸入執(zhí)行SpecialKey()后,會(huì)調(diào)用RenderSecene()
6吏饿、自轉(zhuǎn)公轉(zhuǎn)需要定時(shí)器踪危,定時(shí)器每秒鐘會(huì)觸發(fā)重新渲染調(diào)用RenderSecene()
具體個(gè)方法實(shí)現(xiàn)
1、main函數(shù)
int main(int argc,char *argv[]) {
//初始化GLUT庫
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL)
//設(shè)置GLUT窗口大小與標(biāo)題
glutInitWindowSize(1920, 1080);
glutCreateWindow("Floor");
//指定窗口改變時(shí)調(diào)用的方法
glutReshapeFunc(changeSize);
//指定渲染時(shí)調(diào)用的方法
glutDisplayFunc(RenderScene);
//指定鍵盤輸入時(shí)調(diào)用的方法
glutSpecialFunc(SpecialKey);
//判斷驅(qū)動(dòng)器有沒有問題
GLenum status = glewInit();
if (GLEW_OK != status) {
return 0;
}
//初始化渲染環(huán)境
setupRC();
//執(zhí)行l(wèi)oop循環(huán)
glutMainLoop();
return 0;
}
2猪落、changsize函數(shù)
void changeSize(int w,int h) {
//設(shè)置窗口
glViewport(0, 0, w, h);
//設(shè)置投影矩陣贞远,因?yàn)橥队熬仃囆枰翱陂L(zhǎng)寬比,所以在changsize中設(shè)置
viewFrustum.SetPerspective(35, float(w)/float(h), 1, 100);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//模型矩陣笨忌,視圖矩陣加入管道蓝仲,便于取用
transform.SetMatrixStacks(modelMatrix, projectionMatrix);
}
3、setupRC函數(shù)
void setupRC() {
//清除遺留背景色并設(shè)置背景色
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//初始化著色器
shaderManager.InitializeStockShaders();
//開啟深度測(cè)試
glEnable(GL_DEPTH_TEST);
camera.RotateWorld(float(m3dDegToRad(180.0f)), 0, 1, 0);
//地面的坐標(biāo)
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();
//紅球
gltMakeSphere(redBatch, 0.5f, 100, 100);
//藍(lán)球
gltMakeSphere(blueBatch, 0.1f, 20, 20);
//隨機(jī)位置放置藍(lán)球
for (int i = 0; i < NUM_SPHERES; i++) {
//y軸不變,X,Z產(chǎn)生隨機(jī)值
GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
//在y方向袱结,將球體設(shè)置為0.0的位置亮隙,這使得它們看起來是飄浮在眼睛的高度
//對(duì)spheres數(shù)組中的每一個(gè)頂點(diǎn),設(shè)置頂點(diǎn)數(shù)據(jù)
spheres[i].SetOrigin(x, 0.0f, -z);
}
}
4垢夹、SpecialKey函數(shù)
void SpecialKey(int keys, int x, int y) {
//每次移動(dòng)的距離
GLfloat line = 1;
//每次旋轉(zhuǎn)的弧度
float angular = float(m3dDegToRad(5.0f));
if (keys == GLUT_KEY_UP) {
camera.MoveForward(line);
}
if (keys == GLUT_KEY_DOWN) {
camera.MoveForward(-line);
}
if (keys == GLUT_KEY_LEFT) {
camera.RotateWorld(angular, 0, 1, 0);
}
if (keys == GLUT_KEY_RIGHT) {
camera.RotateWorld(-angular, 0, 1, 0);
}
}
5溢吻、RenderScene函數(shù)
void RenderScene(void) {
//清空顏色緩存區(qū)和深度緩存區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//地板顏色
static GLfloat floorC[] = {0,1,0,1};
//紅球顏色
static GLfloat redC[] = {1,0,0,1};
//籃球顏色
static GLfloat blueC[] = {0,0,1,1};
//定時(shí)器
static CStopWatch timer;
float yRot = timer.GetElapsedSeconds()*60;
//光源位置
M3DVector4f light = {0.0f,10.0f,5.0f,1.0f};
//拷貝一份棧頂?shù)臓顟B(tài)并放入棧頂
modelMatrix.PushMatrix();
//觀察者移動(dòng)
M3DMatrix44f mCamera;
camera.GetMatrix(mCamera);
modelMatrix.PushMatrix(mCamera);
//繪制地面
shaderManager.UseStockShader(GLT_SHADER_FLAT, transform.GetModelViewProjectionMatrix(),floorC);
floorBatch.Draw();
//紅球
//紅球向屏幕內(nèi)移動(dòng)
modelMatrix.Translate(0, 0, -3);
//紅球自轉(zhuǎn)需要保存自轉(zhuǎn)前的狀態(tài),先進(jìn)行拷貝入棧
modelMatrix.PushMatrix();
//紅球自轉(zhuǎn)
modelMatrix.Rotate(yRot, 0, 1, 0);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transform.GetModelViewMatrix(), transform.GetProjectionMatrix(), light, redC);
redBatch.Draw();
modelMatrix.PopMatrix();
//藍(lán)色小球
for (int i = 0; i < NUM_SPHERES; i++) {
modelMatrix.PushMatrix();
modelMatrix.MultMatrix(spheres[i]);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transform.GetModelViewMatrix(), transform.GetProjectionMatrix(), light, blueC); blueBatch.Draw();
modelMatrix.PopMatrix();
}
//公轉(zhuǎn)
modelMatrix.Rotate(yRot*-3.0, 0, 1, 0);
modelMatrix.Translate(0.8f, 0, 0);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transform.GetModelViewMatrix(), transform.GetProjectionMatrix(), light, blueC);
blueBatch.Draw();
modelMatrix.PopMatrix();
modelMatrix.PopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}