当前位置: 首页 > news >正文

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),先向右平移一个单位,之后再进行旋转,这样物体的最左侧位于原点位置,相当于物体以其最右侧为旋转固定中心进行旋转。完成这一效果之后,再进行平移也不影响这一效果(物体以其最右侧为旋转固定中心进行旋转)。

相关文章:

OpenGL的学习之路 -5

1.视景体 正交投影 人眼看世界&#xff0c;有一个可见范围。范围内可见&#xff0c;范围外不可见。视景体就是这么一个概念。 &#xff08;上图仅学习记录用&#xff09; 在OGL中&#xff0c;有两种投影方式&#xff0c;对应两种视景体。第一种&#xff0c;正交投影&#xf…...

【linux】服务器CPU占用50%,top/htop/ps却看不到异常进程?使用unhide可以查看!

问题描述 htop发现前32个核全被占满了&#xff0c;但是却找不到对应进程号 查杀 治标&#xff1a;杀死隐藏进程 1、unhide 安装unhide apt-get install unhideunhide使用 unhide proc果然发现了隐藏进程 kill -9 kill -9 [pid]这么多pid号&#xff0c;我这边杀了其中…...

JSP EL表达式获取list/Map集合与java Bean对象

上文 JSP EL表达式基本使用 中 我们对EL表达式做了一个基本的了解 也做了基础的字符串数据使用 那么 我们可以来看一下我们的集合 首先 list 这个比较简单 我们直接这样写代码 <% page import"java.util.ArrayList" %> <% page import"java.util.Lis…...

汇编程序:查找数组中最大最小值

实验内容 1. 从数据段DS中包含9个字节的数组数据VALUE中分别找出最大值&#xff08;存到max中&#xff09;、最小值&#xff08;存到min中&#xff09;。 2. 能够单步执行程序&#xff0c;认真观察、判断每条指令执行的结果是否正确&#xff0c;对错误结果&#xff0c;能够做出…...

ElasticSearch之禁用交换分区

操作系统将进程加载至内存中执行时&#xff0c;对于当前未使用到的内存页&#xff0c;可能会将相关内存页交换至硬盘上&#xff0c;即swap。 对于性能敏感、时延敏感的应用程序比如ElasticSearch&#xff0c;swap特性会明显影响性能和稳定性&#xff0c;因此最好禁用swap特性。…...

【Linux】第二十一站:文件(一)

文章目录 一、共识原理二、C系列文件接口三、从C过渡到系统&#xff1a;文件系统调用四、访问文件的本质 一、共识原理 文件 内容 属性 文件分为打开的文件 和 没打开的文件 打开的文件&#xff1a;是谁打开的&#xff1f;是进程&#xff01;----所以研究打开的文件本质是研…...

centos7 docker开启认证的远程端口2376配置

docker开启2375会存在安全漏洞 暴露了2375端口的Docker主机。因为没有任何加密和认证过程&#xff0c;知道了主机IP以后&#xff0c;&#xff0c;任何人都可以管理这台主机上的容器和镜像&#xff0c;以前贪图方便&#xff0c;只开启了没有认证的docker2375端口&#xff0c;后…...

Java王者荣耀小游戏

Background类 package LX;import java.awt.*; //背景类 public class Background extends GameObject{public Background(GameFrame gameFrame) {super(gameFrame);}Image bg Toolkit.getDefaultToolkit().getImage("C:\\Users\\ASUS\\Desktop\\王者荣耀图片\\Map.jpg&…...

谈谈Redis的几种经典集群模式

目录 前言 主从复制 哨兵模式 分片集群 前言 Redis集群是一种通过将多个Redis节点连接在一起以实现高可用性、数据分片和负载均衡的技术。它允许Redis在不同节点上同时提供服务&#xff0c;提高整体性能和可靠性。在Redis中提供集群方案总共有三种&#xff1a;主从复制、…...

【腾讯云 HAI域探秘】基于高性能应用服务器HAI部署的 ChatGLM2-6B模型,我开发了AI办公助手,公司行政小姐姐用了都说好!

目录 前言 一、腾讯云HAI介绍&#xff1a; 1、即插即用 轻松上手 2、横向对比 青出于蓝 3、多种高性能应用部署场景 二、腾讯云HAI一键部署并使用ChatGLM2-6B快速实现开发者所需的相关API服务 1、登录 高性能应用服务 HAI 控制台 2、点击 新建 选择 AI模型&#xff0c;…...

服务器tar压缩解压文件

文章目录 一、前言二、命令2.1、解压2.2、压缩 三、最后 一、前言 前端上传dist代码到服务器上后&#xff0c;是在linux上操作&#xff0c;所以和window有所不同。一般是打好dist&#xff0c;然后压缩成gz传输到服务器&#xff0c;此时在服务器上可能涉及到解压和压缩的操作&a…...

博物馆线上导览系统的设计与实现-计算机毕业设计源码64574

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…...

vue升级题

不熟悉的&#xff1a; 2&#xff0c; 3.你用过befcoreDetory 吗&#xff1f;清除定时器&#xff0c;第一个和第二个再看一下 实例加载完成是在哪个生命周期--beforecreate 7.父子组件生命周期执行顺序&#xff1f;为什么这么渲染&#xff1f;场景 8.简单描述每个周期具体适…...

Edit And Resend测试接口工具(浏览器上的Postman)

优点 可以不用设置Cookie或者Token&#xff0c;只设置参数进行重发接口测试API 使用Microsoft Rdge浏览器 F12——然后点击网络——在页面点击发起请求——然后选择要重发的请求右键选择Edit And Resend——在网络控制台设置自己要设置的参数去测试自己写的功能...

maven常用打包命令,值传递和引用传递,Java包 ,JDK 中常用的包有哪些,import java和javax有什么区别

文章目录 maven常用打包命令Java程序设计语言对对象采用的不是引用调用&#xff0c;实际上&#xff0c;对象引用是按值传递的。值传递和引用传递有什么区别Java包 &#xff0c;JDK 中常用的包有哪些import java和javax有什么区别 谈谈java基础的内容&#xff0c;而且很多人都回…...

【c++随笔14】虚函数表

【c随笔14】虚函数表 一、虚函数表&#xff08;Virtual Function Table&#xff09;1、定义2、查看虚函数表2.1、 问题&#xff1a;三种类型&#xff0c;包含一个int类型的class、一个int类型的变量、int类型的指针&#xff1a;这三个大小分别是多少呢&#xff1f;2.2、怎么发现…...

分布式链路追踪实战篇-日志库集成opentelemetry的思路

由上文分布式链路追踪入门篇-基础原理与快速应用可以知道分布式链路追踪的作用&#xff0c;但是距离应用到项目中&#xff0c;我们还需要对项目中一些关键组件进行opentelemetry的集成&#xff0c;例如日志库&#xff0c;ORM、http框架、rpc框架等。 一、日志库如何集成opentel…...

电脑投屏到电视的软件,Mac,Linux,Win均可使用

电脑投屏到电视的软件&#xff0c;Mac&#xff0c;Linux&#xff0c;Win均可使用 AirDroid Cast的TV版&#xff0c;可以上笔记本电脑或台式电脑直接投屏到各种安卓电视上。 无线投屏可以实现本地投屏及远程投屏&#xff0c;AirPlay协议可以实现本地投屏&#xff0c;大家可以按需…...

基于vue+element-plus+echarts编写动态绘图页面

我们都知道网页的echarts可以画图&#xff0c;但是很多情况下都需要编码实现绘图逻辑&#xff0c;如果有一个前端页面可以让我输入数据然后动态生成图表的话那么该多好&#xff0c;其实这个需求不难实现&#xff0c;先看效果。 整体页面分为左右两个部分&#xff0c;其中左边的…...

无人机巡检如何做到实时识别,从数据到模型全流程解读

在数字化和自动化飞速发展的今天&#xff0c;AI识别算法正在加速进入行业生产系统。 基于巡检数据的智能开发&#xff0c;识别算法突破性进展的核心驱动力在于需求——从全天候巡视的平安城市&#xff0c;到潮汐变化的交通网络&#xff0c;从广阔的水域&#xff0c;到繁忙的街道…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念&#xff1a; 1&#xff09;ZYNQ全称&#xff1a;ZYNQ7000 All Pgrammable SoC 2&#xff09;SoC:system on chips(片上系统)&#xff0c;对比集成电路的SoB&#xff08;system on board&#xff09; 3&#xff09;ARM&#xff1a;处理器…...