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/hif (w <= h)glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange*2.0f, nRange*2.0f);elseglOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange*2.0f, nRange*2.0f);glMatrixMode(GL_MODELVIEW);  //再把堆栈由 投影栈 转换为 变换栈glLoadIdentity();
}//先不看这个(灯光什么的,初始化)
void SetupRC() {// Light values and coordinatesGLfloat  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 outglEnable(GL_CULL_FACE);		// Do not calculate inside of jet// Enable lightingglEnable(GL_LIGHTING);// Setup and enable light 0glLightModelfv(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 trackingglEnable(GL_COLOR_MATERIAL);// Set Material properties to follow glColor valuesglColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);// Black blue backgroundglClearColor(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 WindowglutPostRedisplay();
}void RenderScene(void) {float fZ,bZ;// Clear the window with current clearing colorglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);fZ = 100.0f;bZ = -100.0f;// Save the matrix state and do the rotationsglPushMatrix();glRotatef(xRot, 1.0f, 0.0f, 0.0f);glRotatef(yRot, 0.0f, 1.0f, 0.0f);// Set material color, RedglColor3f(1.0f, 0.0f, 0.0f);// Front FaceglBegin(GL_QUADS);// Pointing straight out ZglNormal3f(0.0f, 0.0f, 1.0f);// Left PanelglVertex3f(-50.0f, 50.0f, fZ);glVertex3f(-50.0f, -50.0f, fZ);glVertex3f(-35.0f, -50.0f, fZ);glVertex3f(-35.0f,50.0f,fZ);// Right PanelglVertex3f(50.0f, 50.0f, fZ);glVertex3f(35.0f, 50.0f, fZ);glVertex3f(35.0f, -50.0f, fZ);glVertex3f(50.0f,-50.0f,fZ);// Top PanelglVertex3f(-35.0f, 50.0f, fZ);glVertex3f(-35.0f, 35.0f, fZ);glVertex3f(35.0f, 35.0f, fZ);glVertex3f(35.0f, 50.0f,fZ);// Bottom PanelglVertex3f(-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 axisglNormal3f(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 sectionglNormal3f(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 sectionglNormal3f(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 SectionglNormal3f(-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 outglBegin(GL_QUADS);// Back section// Pointing straight out ZglNormal3f(0.0f, 0.0f, -1.0f);// Left PanelglVertex3f(-50.0f, 50.0f, bZ);glVertex3f(-50.0f, -50.0f, bZ);glVertex3f(-35.0f, -50.0f, bZ);glVertex3f(-35.0f,50.0f,bZ);// Right PanelglVertex3f(50.0f, 50.0f, bZ);glVertex3f(35.0f, 50.0f, bZ);glVertex3f(35.0f, -50.0f, bZ);glVertex3f(50.0f,-50.0f,bZ);// Top PanelglVertex3f(-35.0f, 50.0f, bZ);glVertex3f(-35.0f, 35.0f, bZ);glVertex3f(35.0f, 35.0f, bZ);glVertex3f(35.0f, 50.0f,bZ);// Bottom PanelglVertex3f(-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 axisglNormal3f(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 sectionglNormal3f(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 sectionglNormal3f(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 SectionglNormal3f(-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 stateglPopMatrix();// Buffer swapglutSwapBuffers();
}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 nucleusstatic float fElect1 = 0.0f;// Clear the window with current clearing colorglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Reset the modelview matrixglMatrixMode(GL_MODELVIEW);glLoadIdentity();glTranslatef(0.0f, 0.0f, -100.0f); //AglColor3ub(255, 0, 0);glutSolidSphere(10.0f, 15, 15);  // 红色实心球(A)glColor3ub(255,255,0);glPushMatrix();glRotatef(fElect1, 0.0f, 1.0f, 0.0f);  //BglTranslatef(90.0f, 0.0f, 0.0f);       //CglutSolidSphere(6.0f, 15, 15);         //黄色实心球1(ABC)glPopMatrix();//xRot由特殊键控制glPushMatrix();glRotatef(45.0f, 0.0f, 0.0f, 1.0f);  //DglRotatef(xRot, 0.0f, 1.0f, 0.0f);   //EglTranslatef(-70.0f, 0.0f, 0.0f);    //FglutSolidSphere(6.0f, 15, 15);       //黄色实心球2(ADEF)glPopMatrix();glPushMatrix();glRotatef(300.0f,0.0f, 0.0f, 1.0f);    //GglRotatef(fElect1, 0.0f, 1.0f, 0.0f);  //HglTranslatef(0.0f, 0.0f, 60.0f);       //IglutSolidSphere(6.0f, 15, 15);         //黄色实心球3(AGHI)glPopMatrix();// Increment the angle of revolutionfElect1 += 1.0f;if (fElect1 > 360.0f)fElect1 = 0.0f;// Show the imageglutSwapBuffers();
}void SetupRC() //初始化函数
{glEnable(GL_DEPTH_TEST);	// Hidden surface removalglFrontFace(GL_CCW);		// Counter clock-wise polygons face outglEnable(GL_CULL_FACE);		// Do not calculate inside of jetglClearColor(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);elseglOrtho (-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);                //BglRotatef((GLfloat) day, 0.0, 1.0, 0.0);    //CglutWireSphere(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);  //AglRotatef(15, 1.0f, 0.0f, 0.0f);    //BglDisable(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);   //CglColor3ub(0,0,255);glTranslatef(para[i][1],0.0f,0.0f);                  //DglutSolidSphere(para[i][0], 30, 17);                 //画行星(ABCD)glPushMatrix();      //ABCD再复制一份放到栈顶glLoadIdentity();    //转化为单位阵(I)glTranslatef(0.0f, 0.0f, -300.0f);   //EglRotatef(15, 1.0f, 0.0f, 0.0f);     //FglDisable(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 弹出,弹出后,栈顶元素变为ABglEnable(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 rotationsglMatrixMode(GL_MODELVIEW);glPushMatrix();glLoadIdentity();glTranslatef(0.0f, 0.0f, -300.0f);  //AglDisable(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); //BglColor3ub(0,0,255);glTranslatef(105.0f,0.0f,0.0f);   //CglutSolidSphere(6.0f, 30, 17);    ///地球(ABC)glColor3ub(200,200,200);glRotatef(fMoonRot,0.0f, 0.0f, 1.0f); //DglTranslatef(15.0f, 0.0f, 0.0f);      //EglutSolidSphere(3.0f, 30, 17);        ///月亮(ABCDE)// Restore the matrix stateglPopMatrix();	// Modelview matrixfMoonRot += 10.0f;if (fMoonRot > 360.0f)fMoonRot = 0.0f;fEarthRot += 2.0f;if (fEarthRot > 360.0f)fEarthRot = 0.0f;// Show the imageglutSwapBuffers();
}///
// This function does any needed initialization on the rendering context.
void SetupRC() {glEnable(GL_DEPTH_TEST);	// Hidden surface removalglFrontFace(GL_CCW);	   	// Counter clock-wise polygons face outglEnable(GL_CULL_FACE);		// Do not calculate inside of jetglEnable(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 resetglMatrixMode(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);   //BglRotatef ((GLfloat) shoulder, 0.0, 0.0, 1.0f);   //CglTranslatef (1.0, 0.0, 0.0);     //DglPushMatrix();         //将当前栈顶矩阵ABCD复制一份,放在栈顶glScalef (2.0f, 0.4f, 1.0f);       //EglutWireCube (1.0);     ///机器人 上手臂(ABCDE)glPopMatrix();          //将当前栈顶矩阵ABCDE弹出glTranslatef (1.0f, 0.0, 0.0);     //FglRotatef ((GLfloat) elbow, 0.0, 0.0, 1.0f);   //GglTranslatef (1.0f, 0.0, 0.0);     //HglScalef (2.0f, 0.4f, 1.0f);  //IglutWireCube (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),先向右平移一个单位,之后再进行旋转,这样物体的最左侧位于原点位置,相当于物体以其最右侧为旋转固定中心进行旋转。完成这一效果之后,再进行平移也不影响这一效果(物体以其最右侧为旋转固定中心进行旋转)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/173809.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux进程状态(僵尸进程,孤儿进程)+进程优先级+进程调度与切换

Linux进程状态[僵尸进程,孤儿进程]进程优先级 一.进程状态1.进程排队2.教材上对于进程状态的描述:1.阻塞挂起 3.Linux下具体的进程状态:1.Linux下的进程状态数组2.R3.S:可终止睡眠---浅度睡眠1.补充:前台进程和后台进程2.一种"奇怪"的现象 4.D:不可终止睡眠---深度睡…

探索人类命运与宇宙奥秘的震撼之旅 豆瓣高分巨作《三体》湖北卫视开播

当思考触及宇宙的边缘&#xff0c;当人类命运与外星文明相碰撞&#xff0c;电视剧《三体》以其深邃的内涵和引人深思的故事&#xff0c;重新审视人类的过去、现在和未来&#xff0c;带我们逐步揭开地外未知文明“三体”世界的神秘面纱。根据著名科幻作家刘慈欣同名小说改编&…

Ubuntu新手使用教程

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Django之ORM

ORM全称对象关系映射 作用&#xff1a;通过python面向对象的代码简单快捷的操作数据库&#xff0c;但是封装程度太高&#xff0c;有时候sql语句的效率偏低&#xff0c;需要自己写sql语句 类----->表 对象--->记录 对象属性--->记录某个字段对应的值 写在models.p…

如何通过内网穿透实现远程访问Linux SVN服务

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

骑行三家村赏红杉之旅:挑战与汗水共存,美景和惊喜同行的路线

2023年11月25日&#xff0c;一个冬日里阳光明媚的周末&#xff0c;校长骑行队的骑友们相约&#xff0c;共同踏上了骑行三家村赏红杉林的旅程。这次骑行路线从大观公园门口开始&#xff0c;途径大观湿地公园、干勾尾、碧鸡关加油站、太平、水沟盖板路、明朗、绝望坡、山顶、三家…

kali安装内网穿透工具并实现ssh远程连接

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过[cpolar 内网穿透](cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站)软件实现ssh远程连接kali 1…

成都优优聚美团代运营——让您脱颖而出!

随着互联网的快速发展&#xff0c;越来越多的企业开始注重线上业务的拓展&#xff0c;而美团作为国内领先的生活服务平台之一&#xff0c;自然成为了许多品牌宣传和推广的重要渠道。在成都地区&#xff0c;优优聚美团代运营公司凭借多年的经验和专业团队的优势&#xff0c;成为…

单调栈:LeetCode 907. 子数组的最小值之和

907. 子数组的最小值之和 给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;连续&#xff09;子数组。 由于答案可能很大&#xff0c;因此 返回答案模 10^9 7 。 思路同乘法原理 LeetCode 828. 统计子串中的唯一字符-…

护眼灯有效果吗?对孩子眼睛好的护眼台灯推荐

2022年12月29日&#xff0c;内蒙古消费者协会发布的比较试验结果显示&#xff0c;被检测的35款读写作业台灯样品中有12款标记项目不符合国家强制性标准要求&#xff0c;占被检测样品的34%&#xff0c;其中博士有成、大力智能、霍尼韦尔位列质量黑榜。该从哪些方面注意权衡做好选…

如何用CHAT配置linux的远程连接?

问CHAT&#xff1a;配置linux的远程连接 1.下载ssh 2.启动ssh服务 3.查看ssh服务状态 4.设置ssh服务开机自启动 5.设置windows的cmd下ssh 6.通过cmd的ssh命令远程到linux linux的ip:10.8.9.23 用户名:Li CHAT回复&#xff1a;以下是为配置Linux的远程连接的步骤说明&#xff1a…

AMD ROCm软件栈组件介绍

AMD ROCm™ Platform 1.1 ROCm简介 参考&#xff1a;https://github.com/RadeonOpenCompute/ROCm ROCm&#xff08;Radeon Open Compute&#xff09;开源软件栈。 在NVIDIA GPU上&#xff0c;术语“CUDA”通常是指GPU编程编译器、API和运行时库&#xff0c;但ROCm不那么单一…

【虹科干货】什么是软件成分分析(SCA)?

大家或许都发现了&#xff0c;开发人员愈发依赖开源代码来快速为其专有软件添加功能。据估计&#xff0c;开源代码占专有应用程序代码库的 60-80%。相伴而来的&#xff0c;除了更高的效率&#xff0c;还有更高的风险。因此&#xff0c;管理开源代码对于降低组织的安全风险至关重…

原神「神铸赋形」活动祈愿现已开启

亲爱的旅行者&#xff0c;「神铸赋形」活动祈愿现已开启&#xff0c;「单手剑静水流涌之辉」「法器碧落之珑」概率UP&#xff01; 活动期间&#xff0c;旅行者可以在「神铸赋形」活动祈愿中获得更多武器与角色&#xff0c;提升队伍的战斗力&#xff01; 〓祈愿时间〓 4.2版本更…

Spinnaker 基于 docker registry 触发部署

docker registry 触发部署 Spinnaker可以通过Docker镜像的变化来触发部署&#xff0c;这种方法允许你在Docker镜像发生变化时自动启动新的部署流程。 示例原理如下图所示&#xff1a; 以下是如何在Spinnaker中实现基于Docker Registry触发部署的配置流程。最终实现的效果如下…

数据库应用:MongoDB 数据备份与恢复

目录 一、实验 1.MongoDB 数据库备份与恢复 2.MongoDB 数据表备份与恢复 二、问题 1.MongoDB有哪些命令行工具实现数据备份与恢复 一、实验 1.MongoDB 数据库备份与恢复 &#xff08;1&#xff09;查看版本 rootnode1:~# mongo --version&#xff08;2&#xff09;准备…

html学习

1.框架标签 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body ><p align"center"><a href "http://www.baidu.com" target"aa">百度&l…

BUUCTF [MRCTF2020]你能看懂音符吗 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 感谢Galaxy师傅供题。 密文&#xff1a; 下载附件&#xff0c;得到一个rar压缩包。 解题思路&#xff1a; 1、尝试解压rar压缩包&#xff0c;出现错误无法解压。 使用010 Editor…

YOLOv7独家原创改进: AKConv(可改变核卷积),即插即用的卷积,效果秒杀DSConv | 2023年11月最新发表

💡💡💡本文全网首发独家改进:可改变核卷积(AKConv),赋予卷积核任意数量的参数和任意采样形状,为网络开销和性能之间的权衡提供更丰富的选择,解决具有固定样本形状和正方形的卷积核不能很好地适应不断变化的目标的问题点,效果秒殺DSConv 1)AKConv替代标准卷积进行…

大电流和大电压谁对人体伤害大

突然想起以前看的这个&#xff0c; 网上有很多解答了这个问题&#xff0c;答案是大电流比大电压对人体伤害大。 我之所以重新来写些&#xff0c; 是想起一种有趣的比喻&#xff0c; 这个答案不绝对。 先看一个场景&#xff0c; 一群牛和一头老虎对你冲来&#xff0c; 谁对你的…