编写一个程序,该程序运行时可以用鼠标的一个按键调整立方体的方向,用另一个按键平移立方体,用第三个按键缩放立方体。
这是题目,我的程序不一定完全按照这个来。初学OpenGL,对那一堆坐标系表示十分混乱,慢慢看吧,有点头绪了。
(一)
1 #include <gl/glut.h> 2 #include <math.h> 3 #define GL_PI 3.1415f 4 5 GLfloat xRot = -35.0f; 6 GLfloat yRot = 15.0f; 7 GLfloat xMov = 0.0f; 8 GLfloat winW = 0.0f; 9 GLfloat winH = 0.0f; 10 GLfloat zoom = 1.0f; 11 12 void RenderScene(void) 13 { 14 glClear(GL_COLOR_BUFFER_BIT); 15 16 glPushMatrix(); 17 glLoadIdentity(); 18 glRotatef(xRot, 1.0f, 0.0f, 0.0f); 19 glRotatef(yRot, 0.0f, 1.0f, 0.0f); 20 21 // 底面 22 glBegin(GL_LINE_LOOP); 23 glVertex3f(0.0f+xMov, 0.0f, 0.0f); 24 glVertex3f(1.0f+xMov, 0.0f, 0.0f); 25 glVertex3f(1.0f+xMov, 0.0f, 1.0f); 26 glVertex3f(0.0f+xMov, 0.0f, 1.0f); 27 glEnd(); 28 29 // 顶面 30 glBegin(GL_LINE_LOOP); 31 glVertex3f(0.0f+xMov, 1.0f, 1.0f); 32 glVertex3f(0.0f+xMov, 1.0f, 0.0f); 33 glVertex3f(1.0f+xMov, 1.0f, 0.0f); 34 glVertex3f(1.0f+xMov, 1.0f, 1.0f); 35 glEnd(); 36 37 // 背面 38 glBegin(GL_LINE_LOOP); 39 glVertex3f(0.0f+xMov, 0.0f, 0.0f); 40 glVertex3f(1.0f+xMov, 0.0f, 0.0f); 41 glVertex3f(1.0f+xMov, 1.0f, 0.0f); 42 glVertex3f(0.0f+xMov, 1.0f, 0.0f); 43 glEnd(); 44 45 // 前面 46 glBegin(GL_LINE_LOOP); 47 glVertex3f(1.0f+xMov, 0.0f, 1.0f); 48 glVertex3f(0.0f+xMov, 0.0f, 1.0f); 49 glVertex3f(0.0f+xMov, 1.0f, 1.0f); 50 glVertex3f(1.0f+xMov, 1.0f, 1.0f); 51 glEnd(); 52 53 // 右面 54 glBegin(GL_LINE_LOOP); 55 glVertex3f(1.0f+xMov, 0.0f, 0.0f); 56 glVertex3f(1.0f+xMov, 0.0f, 1.0f); 57 glVertex3f(1.0f+xMov, 1.0f, 1.0f); 58 glVertex3f(1.0f+xMov, 1.0f, 0.0f); 59 glEnd(); 60 61 // 左面 62 glBegin(GL_LINE_LOOP); 63 glVertex3f(0.0f+xMov, 0.0f, 0.0f); 64 glVertex3f(0.0f+xMov, 0.0f, 1.0f); 65 glVertex3f(0.0f+xMov, 1.0f, 1.0f); 66 glVertex3f(0.0f+xMov, 1.0f, 0.0f); 67 glEnd(); 68 69 glPopMatrix(); 70 glFlush(); 71 } 72 void OnReshape(int w, int h) 73 { 74 GLfloat aspectRatio = (GLfloat)w/(GLfloat)h; 75 winW = w; 76 winH = h; 77 78 glViewport(0,0,w,h); 79 glMatrixMode(GL_PROJECTION); 80 glLoadIdentity(); 81 if (w <= h) 82 { 83 glOrtho(-3.0f*zoom, 3.0f*zoom, -3.0f*zoom/aspectRatio, 3.0f*zoom/aspectRatio, -10.0f*zoom, 10.0f*zoom); 84 } 85 else{ 86 glOrtho(-3.0f*zoom*aspectRatio, 3.0f*zoom*aspectRatio, -3.0f*zoom, 3.0f*zoom, -10.0f*zoom, 10.0f*zoom); 87 } 88 glMatrixMode(GL_MODELVIEW); 89 glLoadIdentity(); 90 } 91 void OnMouse(int button, int state, int x, int y) 92 { 93 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 94 { 95 xRot += 1; 96 yRot += 1; 97 glutPostRedisplay(); 98 } 99 else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 100 { 101 xMov -= 0.1; 102 glutPostRedisplay(); 103 } 104 else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) 105 { 106 zoom += 0.1; 107 OnReshape(winW,winH); 108 glutPostRedisplay(); 109 } 110 } 111 void OnKeyUpDown(int key, int x, int y) 112 { 113 if (key == GLUT_KEY_UP){ 114 zoom -= 0.1; 115 } 116 else if (key == GLUT_KEY_DOWN){ 117 zoom += 0.1; 118 } 119 OnReshape(winW,winH); 120 glutPostRedisplay(); 121 } 122 123 void SetupRC() 124 { 125 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 126 glColor3f(0.0f, 1.0f, 0.0f); 127 } 128 129 void main(int argc, char **argv) 130 { 131 glutInit(&argc,argv); 132 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 133 glutCreateWindow("Cube"); 134 glutDisplayFunc(RenderScene); 135 glutReshapeFunc(OnReshape); 136 glutMouseFunc(OnMouse); 137 glutSpecialFunc(OnKeyUpDown); 138 139 SetupRC(); 140 141 glutMainLoop(); 142 }
这个程序略长,显得有点笨。手工实现了平移和放大缩小的功能,值得记录一下。
(二)
1 #include <windows.h> 2 #include<gl/glut.h> 3 #include <math.h> 4 #include<stdio.h> 5 6 GLfloat angle=0.0f; 7 GLfloat translate_x=0.0f; 8 GLfloat zoom=1.0f; 9 10 void myDisplay() 11 { 12 glClear (GL_COLOR_BUFFER_BIT); 13 glColor3f (1.0f, 1.0f, 1.0f); 14 glPushMatrix(); 15 { 16 glMatrixMode(GL_MODELVIEW); //切换到模型视图矩阵 17 glLoadIdentity(); 18 glRotatef(angle,1.0f,0.0f,0.0f); 19 glRotatef(angle, 0.0f, 1.0f, 0.0f); 20 glTranslatef(translate_x,0.0f,0.0f); 21 glScalef (zoom, zoom, zoom); 22 glutWireCube(1.5); //画立方体 23 } 24 glPopMatrix(); 25 glFlush(); 26 } 27 28 void reshape(int w,int h) 29 { 30 glViewport (0, 0, (GLsizei) w, (GLsizei) h); //调整视口位置和大小 31 glMatrixMode (GL_PROJECTION);//切换到投影矩阵 32 glLoadIdentity();//加载单位阵至投影矩阵 33 if (w <= h){ 34 glOrtho(-3.0f, 3.0f, -3.0f/(w/h), 3.0f/(w/h), -3.0f, 3.0f); 35 } 36 else{ 37 glOrtho(-3.0f*w/h, 3.0f*w/h, -3.0f, 3.0f, -3.0f, 3.0f); 38 } 39 40 glMatrixMode (GL_MODELVIEW); 41 glLoadIdentity(); 42 } 43 44 void OnMouse(int button, int state, int x, int y) 45 { 46 //鼠标左键 47 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 48 { 49 angle += 10.0f; 50 glutPostRedisplay(); 51 } 52 //鼠标右键 53 else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 54 { 55 translate_x+=0.1f; 56 glutPostRedisplay(); 57 } 58 //鼠标滚轮 59 else if (state == GLUT_UP && button == GLUT_WHEEL_DOWN) 60 { 61 if(zoom>0) 62 zoom-=0.1f; 63 glutPostRedisplay(); 64 } 65 else if(state == GLUT_UP && button == GLUT_WHEEL_UP) 66 { 67 zoom+=0.1f; 68 glutPostRedisplay(); 69 } 70 } 71 72 73 int main(int argc, char** argv) 74 { 75 glutInit(&argc, argv); 76 glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); 77 glutInitWindowPosition(100,100); 78 glutInitWindowSize(500,500); 79 glutCreateWindow("cube"); 80 81 glutDisplayFunc(myDisplay); 82 glutReshapeFunc(reshape); 83 glutMouseFunc( OnMouse ); 84 glutMainLoop(); 85 return 0; 86 }
采用了OpenGL的一些库函数实现,投影还是采用平行投影,表示对透视投影函数gluPerspective以及视点变化函数gluLookAt不是很清楚。
(三)
1 #include <windows.h> 2 #include<gl/glut.h> 3 #include <math.h> 4 #include<stdio.h> 5 6 GLfloat angle=0.0f; 7 GLfloat translate_x=0.0f; 8 GLfloat zoom=1.0f; 9 10 void myDisplay() 11 { 12 glClear (GL_COLOR_BUFFER_BIT); 13 glColor3f (1.0f, 1.0f, 1.0f); 14 glPushMatrix(); 15 16 glMatrixMode(GL_MODELVIEW); //切换到模型视图矩阵 17 glLoadIdentity(); 18 gluLookAt (0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); //设置相机参数 19 glRotatef(angle, 0.0f, 1.0f, 0.0f); 20 glTranslatef(translate_x,0.0f,0.0f); 21 glScalef (zoom, zoom, zoom); 22 glutWireCube(0.5); //画立方体 23 24 glPopMatrix(); 25 glFlush(); 26 } 27 28 void reshape(int w,int h) 29 { 30 glViewport (0, 0, (GLsizei) w, (GLsizei) h); //调整视口位置和大小 31 glMatrixMode (GL_PROJECTION);//切换到投影矩阵 32 glLoadIdentity();//加载单位阵至投影矩阵 33 gluPerspective(30,w/h,5,20); 34 glMatrixMode (GL_MODELVIEW); 35 glLoadIdentity(); 36 } 37 38 void OnMouse(int button, int state, int x, int y) 39 { 40 //鼠标左键 41 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 42 { 43 angle += 10.0f; 44 glutPostRedisplay(); 45 } 46 //鼠标右键 47 else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 48 { 49 //xMov -= 0.1; 50 translate_x+=0.1f; 51 glutPostRedisplay(); 52 } 53 //鼠标滚轮 54 else if (state == GLUT_UP && button == GLUT_WHEEL_DOWN) 55 { 56 if(zoom>0) 57 zoom-=0.1f; 58 glutPostRedisplay(); 59 } 60 else if(state == GLUT_UP && button == GLUT_WHEEL_UP) 61 { 62 zoom+=0.1f; 63 glutPostRedisplay(); 64 } 65 } 66 67 68 int main(int argc, char** argv) 69 { 70 glutInit(&argc, argv); 71 glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); 72 glutInitWindowPosition(100,100); 73 glutInitWindowSize(500,500); 74 glutCreateWindow("cube"); 75 76 glutDisplayFunc(myDisplay); 77 glutReshapeFunc(reshape); 78 glutMouseFunc( OnMouse ); 79 glutMainLoop(); 80 return 0; 81 }
用的是透视投影。我的理解是gluPerspective()和gluLookAt()要配合使用,二者中的相机位置要一致。