主页 > 互联网  > 

OpenGL的学习之路-5

OpenGL的学习之路-5

1.视景体 正交投影 

人眼看世界,有一个可见范围。范围内可见,范围外不可见。视景体就是这么一个概念。

(上图仅学习记录用)

在OGL中,有两种投影方式,对应两种视景体。第一种,正交投影;第二种,透视投影(更符合人眼)。

正交投影 

 

透视投影(可见,从视觉效果上,透视投影更符合人眼)

正交投影(代码)

#include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> // Rotation amounts static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; void ChangeSize(GLsizei w, GLsizei h) { GLfloat nRange = 100.0f; if (h == 0) h = 1; glViewport(0, 0, w, h); //视口是一个矩形区域,它定义了OpenGL窗口中可以显示图形的区域 glMatrixMode(GL_PROJECTION); //下面对堆栈的操作是对 投影堆栈 glLoadIdentity(); //保持视景体的 纵横比 为w/h if (w <= h) glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange*2.0f, nRange*2.0f); else glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange*2.0f, nRange*2.0f); glMatrixMode(GL_MODELVIEW); //再把堆栈由 投影栈 转换为 变换栈 glLoadIdentity(); } //先不看这个(灯光什么的,初始化) void SetupRC() { // Light values and coordinates GLfloat whiteLight[] = { 0.45f, 0.45f, 0.45f, 1.0f }; GLfloat sourceLight[] = { 0.25f, 0.25f, 0.25f, 1.0f }; GLfloat lightPos[] = { -50.f, 25.0f, 250.0f, 0.0f }; 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_AMBIENT,sourceLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glEnable(GL_LIGHT0); // Enable color tracking glEnable(GL_COLOR_MATERIAL); // Set Material properties to follow glColor values glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // Black blue background glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); } void SpecialKeys(int key, int x, int y) { if (key == GLUT_KEY_UP) xRot -= 5.0f; if (key == GLUT_KEY_DOWN) xRot += 5.0f; if (key == GLUT_KEY_LEFT) yRot -= 5.0f; if (key == GLUT_KEY_RIGHT) yRot += 5.0f; xRot = (GLfloat)((const int)xRot % 360); yRot = (GLfloat)((const int)yRot % 360); // Refresh the Window glutPostRedisplay(); } void RenderScene(void) { float fZ,bZ; // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); fZ = 100.0f; bZ = -100.0f; // Save the matrix state and do the rotations glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); // Set material color, Red glColor3f(1.0f, 0.0f, 0.0f); // Front Face glBegin(GL_QUADS); // Pointing straight out Z glNormal3f(0.0f, 0.0f, 1.0f); // Left Panel glVertex3f(-50.0f, 50.0f, fZ); glVertex3f(-50.0f, -50.0f, fZ); glVertex3f(-35.0f, -50.0f, fZ); glVertex3f(-35.0f,50.0f,fZ); // Right Panel glVertex3f(50.0f, 50.0f, fZ); glVertex3f(35.0f, 50.0f, fZ); glVertex3f(35.0f, -50.0f, fZ); glVertex3f(50.0f,-50.0f,fZ); // Top Panel glVertex3f(-35.0f, 50.0f, fZ); glVertex3f(-35.0f, 35.0f, fZ); glVertex3f(35.0f, 35.0f, fZ); glVertex3f(35.0f, 50.0f,fZ); // Bottom Panel glVertex3f(-35.0f, -35.0f, fZ); glVertex3f(-35.0f, -50.0f, fZ); glVertex3f(35.0f, -50.0f, fZ); glVertex3f(35.0f, -35.0f,fZ); // Top length section // Normal points up Y axis glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-50.0f, 50.0f, fZ); glVertex3f(50.0f, 50.0f, fZ); glVertex3f(50.0f, 50.0f, bZ); glVertex3f(-50.0f,50.0f,bZ); // Bottom section glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-50.0f, -50.0f, fZ); glVertex3f(-50.0f, -50.0f, bZ); glVertex3f(50.0f, -50.0f, bZ); glVertex3f(50.0f, -50.0f, fZ); // Left section glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f(50.0f, 50.0f, fZ); glVertex3f(50.0f, -50.0f, fZ); glVertex3f(50.0f, -50.0f, bZ); glVertex3f(50.0f, 50.0f, bZ); // Right Section glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-50.0f, 50.0f, fZ); glVertex3f(-50.0f, 50.0f, bZ); glVertex3f(-50.0f, -50.0f, bZ); glVertex3f(-50.0f, -50.0f, fZ); glEnd(); glFrontFace(GL_CW); // clock-wise polygons face out glBegin(GL_QUADS); // Back section // Pointing straight out Z glNormal3f(0.0f, 0.0f, -1.0f); // Left Panel glVertex3f(-50.0f, 50.0f, bZ); glVertex3f(-50.0f, -50.0f, bZ); glVertex3f(-35.0f, -50.0f, bZ); glVertex3f(-35.0f,50.0f,bZ); // Right Panel glVertex3f(50.0f, 50.0f, bZ); glVertex3f(35.0f, 50.0f, bZ); glVertex3f(35.0f, -50.0f, bZ); glVertex3f(50.0f,-50.0f,bZ); // Top Panel glVertex3f(-35.0f, 50.0f, bZ); glVertex3f(-35.0f, 35.0f, bZ); glVertex3f(35.0f, 35.0f, bZ); glVertex3f(35.0f, 50.0f,bZ); // Bottom Panel glVertex3f(-35.0f, -35.0f, bZ); glVertex3f(-35.0f, -50.0f, bZ); glVertex3f(35.0f, -50.0f, bZ); glVertex3f(35.0f, -35.0f,bZ); // Insides / glColor3f(0.75f, 0.75f, 0.75f); // Normal points up Y axis glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-35.0f, 35.0f, fZ); glVertex3f(35.0f, 35.0f, fZ); glVertex3f(35.0f, 35.0f, bZ); glVertex3f(-35.0f,35.0f,bZ); // Bottom section glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-35.0f, -35.0f, fZ); glVertex3f(-35.0f, -35.0f, bZ); glVertex3f(35.0f, -35.0f, bZ); glVertex3f(35.0f, -35.0f, fZ); // Left section glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f(-35.0f, 35.0f, fZ); glVertex3f(-35.0f, 35.0f, bZ); glVertex3f(-35.0f, -35.0f, bZ); glVertex3f(-35.0f, -35.0f, fZ); // Right Section glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(35.0f, 35.0f, fZ); glVertex3f(35.0f, -35.0f, fZ); glVertex3f(35.0f, -35.0f, bZ); glVertex3f(35.0f, 35.0f, bZ); glEnd(); glFrontFace(GL_CCW); // Counter clock-wise polygons face out // Restore the matrix state glPopMatrix(); // Buffer swap glutSwapBuffers(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); //需要动画,使用的是双缓冲 glutInitWindowSize(800, 600); glutCreateWindow("Orthographic Projection"); //回调函数 glutReshapeFunc(ChangeSize); //改变窗口大小 glutSpecialFunc(SpecialKeys); //敲击特殊键 glutDisplayFunc(RenderScene); //显示 //初始化函数 SetupRC(); glutMainLoop(); return 0; }

透视投影(替换代码)

2.几个代码示例(主要目的:弄明白 变换栈)

(1)三个球绕红球转

效果:

#include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> // Rotation amounts static float xRot = 0.0f; void RenderScene(void) { // Angle of revolution around the nucleus static float fElect1 = 0.0f; // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset the modelview matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -100.0f); //A glColor3ub(255, 0, 0); glutSolidSphere(10.0f, 15, 15); // 红色实心球(A) glColor3ub(255,255,0); glPushMatrix(); glRotatef(fElect1, 0.0f, 1.0f, 0.0f); //B glTranslatef(90.0f, 0.0f, 0.0f); //C glutSolidSphere(6.0f, 15, 15); //黄色实心球1(ABC) glPopMatrix(); //xRot由特殊键控制 glPushMatrix(); glRotatef(45.0f, 0.0f, 0.0f, 1.0f); //D glRotatef(xRot, 0.0f, 1.0f, 0.0f); //E glTranslatef(-70.0f, 0.0f, 0.0f); //F glutSolidSphere(6.0f, 15, 15); //黄色实心球2(ADEF) glPopMatrix(); glPushMatrix(); glRotatef(300.0f,0.0f, 0.0f, 1.0f); //G glRotatef(fElect1, 0.0f, 1.0f, 0.0f); //H glTranslatef(0.0f, 0.0f, 60.0f); //I glutSolidSphere(6.0f, 15, 15); //黄色实心球3(AGHI) glPopMatrix(); // Increment the angle of revolution fElect1 += 1.0f; if (fElect1 > 360.0f) fElect1 = 0.0f; // Show the image glutSwapBuffers(); } void SetupRC() //初始化函数 { 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 glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); } void SpecialKeys(int key, int x, int y) { if (key == GLUT_KEY_UP) xRot -= 5.0f; if (key == GLUT_KEY_DOWN) xRot += 5.0f; //if (key == GLUT_KEY_LEFT) yRot -= 5.0f; //if (key == GLUT_KEY_RIGHT) yRot += 5.0f; if (key > 356.0f) xRot = 0.0f; if (key < -1.0f) xRot = 355.0f; //if (key > 356.0f) yRot = 0.0f; //if (key < -1.0f) yRot = 355.0f; glutPostRedisplay(); // Refresh the Window } void TimerFunc(int value) { glutPostRedisplay(); // Refresh the Window /* millis:指定的时间间隔,以毫秒为单位。 callback:指向回调函数的指针,该回调函数在指定时间间隔过后被调用。 data:传递给回调函数的整型数值参数 */ glutTimerFunc(10, TimerFunc, 1); //seconds, func, para(注册了一个定时器) } void ChangeSize(int w, int h) { float nRange = 100.0f; if (h == 0) h = 1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //正交投影(left, right, bottom, top, near, far) if (w <= h) glOrtho (-nRange, nRange, nRange*h/w, -nRange*h/w, -nRange*2.0f, nRange*2.0f); else glOrtho (-nRange*w/h, nRange*w/h, nRange, -nRange, -nRange*2.0f, nRange*2.0f); } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(800, 600); glutCreateWindow("OpenGL Atom"); glutReshapeFunc(ChangeSize); //改变窗口大小时的回调函数 glutSpecialFunc(SpecialKeys); //敲击特殊键的回调函数 glutDisplayFunc(RenderScene); //显示的回调函数 glutTimerFunc(500, TimerFunc, 1); ///new!!(保持连续变化) SetupRC(); glutMainLoop(); return 0; }

(2)键盘控制的自转和公转

效果:

/// #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <stdlib.h> #include <iostream> /// static int year = 0, day = 0; /// void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); } /// void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glPushMatrix(); glRotatef((GLfloat)year, 0.0, 1.0, 0.0); //A(实现自传效果) glutWireSphere(1.0, 20, 16); //画线框太阳(A) ///思考:加上这两句的效果会怎样? //glPopMatrix(); //glPushMatrix(); glTranslatef(2.0, 0.0, 0.0); //B glRotatef((GLfloat) day, 0.0, 1.0, 0.0); //C glutWireSphere(0.2, 10, 8); //画线框地球(ABC) glPopMatrix(); glutSwapBuffers(); } /// void reshape(int w, int h) { glViewport(0, 0,(GLsizei) w,(GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,(float) w/(float) h, 1.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); } /// void keyboard(unsigned char key, int x, int y) { switch(key) { case 'd': day =(day + 10) % 360; break; case 'D': day =(day - 10) % 360; break; case 'y': year =(year + 5) % 360; break; case 'Y': year =(year - 5) % 360; break; case 27: exit(0); default: break; } glutPostRedisplay(); } /// int main(int argc, char** argv) { std::cout<<"D/d: 行星转动\nY/y: 太阳转动\n"; glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(500, 100); glutCreateWindow("earthmoon"); init(); //初始化函数 glutDisplayFunc(display); //显示的回调函数 glutReshapeFunc(reshape); //改变窗口大小的回调函数 glutKeyboardFunc(keyboard); //点击键盘的回调函数 glutMainLoop(); return 0; }

如果点击‘D’或者‘d’,矩阵C变化,地球实现自转的效果;如果点击‘Y’或者‘y’,矩阵A变化,太阳自转,地球跟着太阳转;如果同时按下‘D’或者‘d’以及‘Y’或者‘y’,地球自转的同时绕着太阳公转,同时,太阳也在自转。

(3)星系

效果:

#include <math.h> #include <gl/gl.h> #include <gl/glu.h> #include <gl/glut.h> #define N 6 /// // Lighting values float whiteLight[] = { 0.2f, 0.2f, 0.2f, 1.0f }; float sourceLight[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f }; float para[N][3] = { {2.0f, 30.0f, 99.f}, {3.0f, 50.0f, 44.f}, {6.0f, 70.0f, 20.f}, {5.0f, 90.0f, 80.f}, {9.0f, 110.0f, 10.f}, {2.0f, 120.0f, 15.f} }; float fEarthRot = 0; /// void RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -300.0f); //A glRotatef(15, 1.0f, 0.0f, 0.0f); //B glDisable(GL_LIGHTING); glColor3ub(255, 255, 0); glutSolidSphere(10.0f, 18, 17); // 太阳(AB) glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_POSITION, lightPos); // Move the light after we draw the sun! for (int i=0; i<N; ++i) //画几大行星 { glPushMatrix(); //AB再复制一份放到栈顶 glRotatef(fEarthRot*para[i][2], 0.0f, 1.0f, 0.0f); //C glColor3ub(0,0,255); glTranslatef(para[i][1],0.0f,0.0f); //D glutSolidSphere(para[i][0], 30, 17); //画行星(ABCD) glPushMatrix(); //ABCD再复制一份放到栈顶 glLoadIdentity(); //转化为单位阵(I) glTranslatef(0.0f, 0.0f, -300.0f); //E glRotatef(15, 1.0f, 0.0f, 0.0f); //F glDisable(GL_LIGHTING); glColor3f(1,0,0); glBegin(GL_LINE_LOOP); //画轨迹 for (float j=0; j<2*3.14149265; j+=0.1f) { glVertex3f(para[i][1]*sin(j), 0.0f, para[i][1]*cos(j)); //轨迹(EF) } glEnd(); glPopMatrix(); //将当前栈顶矩阵 EF 弹出 glPopMatrix(); //将当前栈顶矩阵 ABCD 弹出,弹出后,栈顶元素变为AB glEnable(GL_LIGHTING); } glPopMatrix(); //将当前栈顶矩阵 AB 弹出 fEarthRot += 0.1f; if (fEarthRot > 360.0f) fEarthRot = 0.0f; //转起来 glutSwapBuffers(); } //初始化函数,关于灯光的一些操作 /// void SetupRC() { glEnable(GL_DEPTH_TEST); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glClearColor(0.3f, 0.3f, 0.3f, 1.0f ); } /// void TimerFunc(int value) { glutPostRedisplay(); //重新绘制 glutTimerFunc(100, TimerFunc, 1); //设置定时器 } /// void ChangeSize(int w, int h) { float fAspect; if (h == 0) h = 1; glViewport(0, 0, w, h); fAspect = (float)w/(float)h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0f, fAspect, 1.0, 600.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); ///new!! SetupRC(); //初始化 glutMainLoop(); return 0; }

程序分析:

(4)月亮绕着地球转、地球绕着太阳转

效果:

#include <math.h> #include <gl/gl.h> #include <gl/glu.h> #include <gl/glut.h> /// // Lighting values float whiteLight[] = { 0.2f, 0.2f, 0.2f, 1.0f }; float sourceLight[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f }; /// void RenderScene(void) { static float fMoonRot = 0.0f; static float fEarthRot = 0.0f; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Save the matrix state and do the rotations glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -300.0f); //A glDisable(GL_LIGHTING); glColor3ub(255, 255, 0); glutSolidSphere(18.0f, 18, 17); /// 太阳(A) glEnable(GL_LIGHTING); // Move the light after we draw the sun! glLightfv(GL_LIGHT0, GL_POSITION, lightPos); glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f); //B glColor3ub(0,0,255); glTranslatef(105.0f,0.0f,0.0f); //C glutSolidSphere(6.0f, 30, 17); ///地球(ABC) glColor3ub(200,200,200); glRotatef(fMoonRot,0.0f, 0.0f, 1.0f); //D glTranslatef(15.0f, 0.0f, 0.0f); //E glutSolidSphere(3.0f, 30, 17); ///月亮(ABCDE) // Restore the matrix state glPopMatrix(); // Modelview matrix fMoonRot += 10.0f; if (fMoonRot > 360.0f) fMoonRot = 0.0f; fEarthRot += 2.0f; if (fEarthRot > 360.0f) fEarthRot = 0.0f; // Show the image glutSwapBuffers(); } /// // This function does any needed initialization on the rendering context. void SetupRC() { 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 glEnable(GL_LIGHTING); glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glClearColor(0.3f, 0.3f, 0.3f, 1.0f ); } /// void TimerFunc(int value) { glutPostRedisplay(); glutTimerFunc(100, TimerFunc, 1); } /// void ChangeSize(int w, int h) { float fAspect; if (h == 0) h = 1; glViewport(0, 0, w, h); fAspect = (float)w/(float)h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, fAspect, 1.0, 425.0); //透视投影 // Modelview matrix reset 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); ///new!! SetupRC(); //初始化函数 glutMainLoop(); return 0; }

 推广:

(5)机器人的手臂

效果:

/// #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <stdlib.h> #include <stdio.h> /// static int shoulder = 0, elbow = 0; /// void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_FLAT); } /// void display(void) { glClear (GL_COLOR_BUFFER_BIT); glPushMatrix(); //将当前栈顶矩阵A复制一份,放在栈顶 glTranslatef (-1.0f, 0.0, 0.0); //B glRotatef ((GLfloat) shoulder, 0.0, 0.0, 1.0f); //C glTranslatef (1.0, 0.0, 0.0); //D glPushMatrix(); //将当前栈顶矩阵ABCD复制一份,放在栈顶 glScalef (2.0f, 0.4f, 1.0f); //E glutWireCube (1.0); ///机器人 上手臂(ABCDE) glPopMatrix(); //将当前栈顶矩阵ABCDE弹出 glTranslatef (1.0f, 0.0, 0.0); //F glRotatef ((GLfloat) elbow, 0.0, 0.0, 1.0f); //G glTranslatef (1.0f, 0.0, 0.0); //H glScalef (2.0f, 0.4f, 1.0f); //I glutWireCube (1.0f); ///机器人 下手臂(ABCDFGHI) glPopMatrix(); //将当前栈顶矩阵ABCDFGHI弹出 glPopMatrix(); //将当前栈顶矩阵ABCD弹出 glPopMatrix(); //将当前栈顶矩阵A弹出 glutSwapBuffers(); } /// void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective(65.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0); //透视投影 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef (0.0, 0.0, -5.0); // A } /// void keyboard (unsigned char key, int x, int y) { switch (key) { case 's': shoulder = (shoulder + 5) % 360; break; case 'S': shoulder = (shoulder - 5) % 360; break; case 'e': elbow = (elbow + 5) % 360; break; case 'E': elbow = (elbow - 5) % 360; break; case 27: exit(0); default: break; } glutPostRedisplay(); } /// int main(int argc, char** argv) { printf("S, Or E\n"); glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow ("robot"); init (); //初始化函数 glutDisplayFunc(display); //显示的回调函数 glutReshapeFunc(reshape); //改变窗口大小时的回调函数 glutKeyboardFunc(keyboard); //敲击键盘的回调函数 glutMainLoop(); return 0; }

简单分析:

显示函数中,旋转之前都有一个平移。也就是物体进行缩放后(长度变为2),先向右平移一个单位,之后再进行旋转,这样物体的最左侧位于原点位置,相当于物体以其最右侧为旋转固定中心进行旋转。完成这一效果之后,再进行平移也不影响这一效果(物体以其最右侧为旋转固定中心进行旋转)。

标签:

OpenGL的学习之路-5由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“OpenGL的学习之路-5