以日月地为例的一个模型视图变换。绕了比较多的弯路,下面是几个注意点总结。
注意点:
1.GL函数对模型的操作是基于当前局部坐标系,即模型坐标系而非世界坐标系,二者只在第一次初始化完毕之后才重合;
2.矩阵变换——缩放、平移、旋转是左乘运算,即与代码顺序相反;
3.先平移再旋转类似星体的公转,先旋转再平移类似星体的自转;
4.本例中采取模型坐标系绘制,对不同星体的操作其局部坐标不断变换,连续绘制一系列星体;另一方面若是采取单独星体绘制,即每一个星体的绘制实则是在世界坐标系中绘制,需要用glLoadIdentity()函数对之前的三维变换进行复位;
1 #pragma comment(lib,"glut32.lib") 2 #pragma comment(lib,"glut.lib") 3 #pragma comment(lib,"GlU32.lib") 4 #include<GL\glut.h> 5 #include<Windows.h> 6 //globle variable 7 GLfloat sun_rotate; 8 GLfloat moon_revolution; 9 GLfloat earth_revolution; 10 //protype func 11 void Display(void); 12 void TimerTick(int id); 13 void Init(void); 14 //main func 15 int main(int argc, char* argv[]) 16 { 17 glutInit(&argc, argv); 18 glutInitDisplayMode(GL_DOUBLE | GLUT_RGBA | GLUT_DEPTH); 19 glutInitWindowSize(800,800); 20 glutCreateWindow("model-view"); 21 Init(); 22 glutDisplayFunc(Display); 23 glutTimerFunc(20,TimerTick,0); 24 // glutTimerFunc(100,TimerTick,1); 25 glutMainLoop(); 26 } 27 void Init(void) 28 { 29 glEnable(GL_DEPTH_TEST); 30 glDepthFunc(GL_LEQUAL); 31 glClearDepth(1.0f); 32 } 33 void Display(void) 34 { 35 glClearColor(0.0f,0.0f,0.0f,0.0f); 36 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 37 } 38 void TimerTick(int id) 39 { 40 glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); 41 glMatrixMode(GL_MODELVIEW); 42 glLoadIdentity(); 43 switch(id) 44 { 45 case 0: 46 sun_rotate += 0.1; 47 glColor3f(1.0f,0.0f,0.0f); 48 glRotatef(90,1,0,0); 49 glutWireSphere(0.2, 30, 30); //sun 50 51 glColor3f(0.0f,0.0f,1.0f); 52 earth_revolution += 1; 53 glRotatef(earth_revolution,0,0,1); 54 glTranslatef (0.6,0,0); //局部坐标系 55 glutWireSphere(0.1,25,25);//earth 56 57 moon_revolution += 3; 58 glColor3f(1.0f, 1.0f, 0.0f); 59 glRotatef(moon_revolution, 0.0f, 0.0f, 1.0f); 60 glTranslatef(0.2, 0.0f, 0.0f); 61 glutWireSphere(0.04, 10, 10); 62 63 glutTimerFunc(20,TimerTick,0);//for continue timer counting 64 break; 65 // case 1: 66 // glutTimerFunc(100,TimerTick,1); 67 // break; 68 default:break; 69 } 70 glutSwapBuffers(); 71 }