需求:繪制一個簡單的地月太陽的旋轉模型:地球繞太陽(繞y軸)旋轉,月球繞地球(繞x軸)旋轉。 實現的步驟: //openGL 坐標系:z朝向屏幕外, y朝上,x朝右 push 向里移動300 畫了一顆太陽 繞y軸旋轉坐標系,旋轉角度為fEarthRot //(此時太陽的坐標系已經在繞太陽中心點(繞x軸)旋轉呢,不管后面有沒有下一步。理解這點很重要。) 向上移動105 畫一個顆地球 //(這時地球自然而然在繞y軸旋轉,半徑為上面移動的105。) 繞x軸旋轉坐標系,旋轉角度為fMoonRot //(此時地球的坐標系在繞地球中心點(繞x軸)旋轉。) 向上移動30 畫一顆月亮 //(這時地球自然而然在繞x軸旋轉,半徑為上面移動的30。) pop //(物體坐標系又回到世界坐標系原點) //注意它兩是靜態變量 fEarthRot++ fMoonRot++ 循環上面這動作,實現了動畫。
效果:
實現:
#include<gl/glut.h> #include <math.h> // Lighting values GLfloat whiteLight[] = { 0.2f, 0.2f, 0.2f, 1.0f }; GLfloat sourceLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f }; void createCoordinate(); //執行順序: main --> SetupRC --> TimerFunc --> ChangeSize -->RenderScene // Called to draw scene void RenderScene(void) { //openGL 坐標系:z朝向屏幕外, y朝上,x朝右 // Earth and Moon angle of revolution static float fMoonRot = 0.0f; static float fEarthRot = 0.0f; // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Save the matrix state and do the rotations glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Translate the whole scene out and into view //向里移動300 glTranslatef(0.0f, 0.0f, -300.0f); createCoordinate(); // Set material color, Red // Sun 畫了一顆太陽 glDisable(GL_LIGHTING); glColor3ub(255, 255, 0); glutSolidSphere(15.0f, 30, 17); glEnable(GL_LIGHTING); // Move the light after we draw the sun! glLightfv(GL_LIGHT0,GL_POSITION,lightPos); // 繞y軸旋轉坐標系 glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f); //向上移動105 glTranslatef(105.0f,0.0f,0.0f); //畫一個顆地球 glColor3ub(0,0,255); glutSolidSphere(15.0f, 30, 17); //繪制一個坐標系, createCoordinate(); // Rotate from Earth based coordinates and draw Moon glColor3ub(200,200,200); //繞x軸旋轉 glRotatef(fMoonRot,1.0f, 0.0f, 0.0f); //向上移動30 glTranslatef(0.0f, 30.0f, 0.0f); //畫一顆月亮 glutSolidSphere(6.0f, 30, 17); createCoordinate(); // Restore the matrix state glPopMatrix(); // Modelview matrix //月亮在轉 fMoonRot+= 5.0f; if(fMoonRot > 360.0f) fMoonRot = 0.0f; // Step earth orbit 5 degrees //地球在轉 fEarthRot += 5.0f; if(fEarthRot > 360.0f) fEarthRot = 0.0f; // Show the image glutSwapBuffers(); } void createCoordinate(){ //繪制一個坐標系, GLint factor = 2; GLushort pattern = 0x5555; //啟用點畫 glEnable(GL_LINE_STIPPLE); //點畫模式 glLineStipple(factor,pattern); glLineWidth(1.0f); glBegin(GL_LINES); //x軸 glColor3ub((GLubyte)255,(GLubyte)0,(GLubyte)0); glVertex3f(-100.0f,0.0f,0.0f); glVertex3f(100.0f,0.0f,0.0f); glColor3ub((GLubyte)0,(GLubyte)255,(GLubyte)0); //y軸 glVertex3f(0.0f,-100.0f,0.0f); glVertex3f(0.0f,100.0f,0.0f); //z軸 glColor3ub((GLubyte)0,(GLubyte)0,(GLubyte)255); glVertex3f(0.0f,0.0f,-100.0f); glVertex3f(0.0f,0.0f,100.0f); glEnd(); //關閉點畫 glDisable(GL_LINE_STIPPLE); } // This function does any needed initialization on the rendering // context. void SetupRC() { // Light values and coordinates glEnable(GL_DEPTH_TEST); // Hidden surface removal glFrontFace(GL_CCW); // Counter clock-wise polygons face out glEnable(GL_CULL_FACE); // Do not calculate inside of jet // Enable lighting glEnable(GL_LIGHTING); // Setup and enable light 0 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glEnable(GL_LIGHT0); // Enable color tracking glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); } void TimerFunc(int value) { glutPostRedisplay(); glutTimerFunc(100, TimerFunc, 1); } void ChangeSize(int w, int h) { GLfloat fAspect; if(h == 0)h = 1; glViewport(0, 0, w, h); fAspect = (GLfloat)w/(GLfloat)h; //使用並初始化投影矩陣 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, fAspect, 1.0, 425.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(800, 600); glutCreateWindow("Earth/Moon/Sun System"); glutReshapeFunc(ChangeSize); glutDisplayFunc(RenderScene); glutTimerFunc(250, TimerFunc, 1); SetupRC(); glutMainLoop(); return 0; }