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.视景体 正交投影 人眼看世界,有一个可见范围。范围内可见,范围外不可见。视景体就是这么一个概念。 (上图仅学习记录用) 在OGL中,有两种投影方式,对应两种视景体。第一种,正交投影…...
【linux】服务器CPU占用50%,top/htop/ps却看不到异常进程?使用unhide可以查看!
问题描述 htop发现前32个核全被占满了,但是却找不到对应进程号 查杀 治标:杀死隐藏进程 1、unhide 安装unhide apt-get install unhideunhide使用 unhide proc果然发现了隐藏进程 kill -9 kill -9 [pid]这么多pid号,我这边杀了其中…...
JSP EL表达式获取list/Map集合与java Bean对象
上文 JSP EL表达式基本使用 中 我们对EL表达式做了一个基本的了解 也做了基础的字符串数据使用 那么 我们可以来看一下我们的集合 首先 list 这个比较简单 我们直接这样写代码 <% page import"java.util.ArrayList" %> <% page import"java.util.Lis…...
汇编程序:查找数组中最大最小值
实验内容 1. 从数据段DS中包含9个字节的数组数据VALUE中分别找出最大值(存到max中)、最小值(存到min中)。 2. 能够单步执行程序,认真观察、判断每条指令执行的结果是否正确,对错误结果,能够做出…...
ElasticSearch之禁用交换分区
操作系统将进程加载至内存中执行时,对于当前未使用到的内存页,可能会将相关内存页交换至硬盘上,即swap。 对于性能敏感、时延敏感的应用程序比如ElasticSearch,swap特性会明显影响性能和稳定性,因此最好禁用swap特性。…...
【Linux】第二十一站:文件(一)
文章目录 一、共识原理二、C系列文件接口三、从C过渡到系统:文件系统调用四、访问文件的本质 一、共识原理 文件 内容 属性 文件分为打开的文件 和 没打开的文件 打开的文件:是谁打开的?是进程!----所以研究打开的文件本质是研…...
centos7 docker开启认证的远程端口2376配置
docker开启2375会存在安全漏洞 暴露了2375端口的Docker主机。因为没有任何加密和认证过程,知道了主机IP以后,,任何人都可以管理这台主机上的容器和镜像,以前贪图方便,只开启了没有认证的docker2375端口,后…...
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在不同节点上同时提供服务,提高整体性能和可靠性。在Redis中提供集群方案总共有三种:主从复制、…...
【腾讯云 HAI域探秘】基于高性能应用服务器HAI部署的 ChatGLM2-6B模型,我开发了AI办公助手,公司行政小姐姐用了都说好!
目录 前言 一、腾讯云HAI介绍: 1、即插即用 轻松上手 2、横向对比 青出于蓝 3、多种高性能应用部署场景 二、腾讯云HAI一键部署并使用ChatGLM2-6B快速实现开发者所需的相关API服务 1、登录 高性能应用服务 HAI 控制台 2、点击 新建 选择 AI模型,…...
服务器tar压缩解压文件
文章目录 一、前言二、命令2.1、解压2.2、压缩 三、最后 一、前言 前端上传dist代码到服务器上后,是在linux上操作,所以和window有所不同。一般是打好dist,然后压缩成gz传输到服务器,此时在服务器上可能涉及到解压和压缩的操作&a…...
博物馆线上导览系统的设计与实现-计算机毕业设计源码64574
摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存…...
vue升级题
不熟悉的: 2, 3.你用过befcoreDetory 吗?清除定时器,第一个和第二个再看一下 实例加载完成是在哪个生命周期--beforecreate 7.父子组件生命周期执行顺序?为什么这么渲染?场景 8.简单描述每个周期具体适…...
Edit And Resend测试接口工具(浏览器上的Postman)
优点 可以不用设置Cookie或者Token,只设置参数进行重发接口测试API 使用Microsoft Rdge浏览器 F12——然后点击网络——在页面点击发起请求——然后选择要重发的请求右键选择Edit And Resend——在网络控制台设置自己要设置的参数去测试自己写的功能...
maven常用打包命令,值传递和引用传递,Java包 ,JDK 中常用的包有哪些,import java和javax有什么区别
文章目录 maven常用打包命令Java程序设计语言对对象采用的不是引用调用,实际上,对象引用是按值传递的。值传递和引用传递有什么区别Java包 ,JDK 中常用的包有哪些import java和javax有什么区别 谈谈java基础的内容,而且很多人都回…...
【c++随笔14】虚函数表
【c随笔14】虚函数表 一、虚函数表(Virtual Function Table)1、定义2、查看虚函数表2.1、 问题:三种类型,包含一个int类型的class、一个int类型的变量、int类型的指针:这三个大小分别是多少呢?2.2、怎么发现…...
分布式链路追踪实战篇-日志库集成opentelemetry的思路
由上文分布式链路追踪入门篇-基础原理与快速应用可以知道分布式链路追踪的作用,但是距离应用到项目中,我们还需要对项目中一些关键组件进行opentelemetry的集成,例如日志库,ORM、http框架、rpc框架等。 一、日志库如何集成opentel…...
电脑投屏到电视的软件,Mac,Linux,Win均可使用
电脑投屏到电视的软件,Mac,Linux,Win均可使用 AirDroid Cast的TV版,可以上笔记本电脑或台式电脑直接投屏到各种安卓电视上。 无线投屏可以实现本地投屏及远程投屏,AirPlay协议可以实现本地投屏,大家可以按需…...
基于vue+element-plus+echarts编写动态绘图页面
我们都知道网页的echarts可以画图,但是很多情况下都需要编码实现绘图逻辑,如果有一个前端页面可以让我输入数据然后动态生成图表的话那么该多好,其实这个需求不难实现,先看效果。 整体页面分为左右两个部分,其中左边的…...
无人机巡检如何做到实时识别,从数据到模型全流程解读
在数字化和自动化飞速发展的今天,AI识别算法正在加速进入行业生产系统。 基于巡检数据的智能开发,识别算法突破性进展的核心驱动力在于需求——从全天候巡视的平安城市,到潮汐变化的交通网络,从广阔的水域,到繁忙的街道…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...
从零手写Java版本的LSM Tree (一):LSM Tree 概述
🔥 推荐一个高质量的Java LSM Tree开源项目! https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree,专为高并发写入场景设计。 核心亮点: ⚡ 极致性能:写入速度超…...
