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)机器人的手臂

效果:

///
// robot.c
// This program shows how to composite modeling transformations to draw
// translated and rotated hierarchical models.
//
// Interaction:  pressing the s and e keys (shoulder and elbow) alters
// the rotation of the robot arm.
///
#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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flask学习二:项目拆分、请求与响应、cookie

教程 教程地址&#xff1a; 千锋教育Flask2框架从入门到精通&#xff0c;Python全栈开发必备教程 老师讲的很好&#xff0c;可以看一下。 项目拆分 项目结构 在项目根目录下&#xff0c;创建一个App目录&#xff0c;这是项目下的一个应用&#xff0c;应该类似于后端的微服…

案例029:基于微信小程序的阅读网站设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

为什么PCB板大多数都是绿色的?

什么时候开始接触到PCB板的呢&#xff1f;也许是是把家里的电视遥控器拆开的时候&#xff0c;也许是你的小霸王学习机游戏手柄给按坏拆开的时候&#xff0c;也许那时候你还不知道这叫PCB电路板。然后就是大学里使用嘉立创免费打板的时候&#xff0c;有一个选项绿色板还是黑色板…

自建CA实战之 《0x01 Nginx 配置 https单向认证》

自建私有化证书颁发机构&#xff08;Certificate Authority&#xff0c;CA&#xff09;实战之 《0x01 Nginx 配置 https单向认证》 上一篇文章我们介绍了如何自建私有化证书颁发机构&#xff08;Certificate Authority&#xff0c;CA&#xff09;&#xff0c;本篇文章我们将介…

单细胞seurat入门—— 从原始数据到表达矩阵

根据所使用的建库方法&#xff0c;单细胞的RNA序列&#xff08;也称为读取&#xff08;reads&#xff09;或标签&#xff08;tags&#xff09;&#xff09;将从转录本的3端&#xff08;或5端&#xff09;&#xff08;10X Genomics&#xff0c;CEL-seq2&#xff0c;Drop-seq&…

Java 文件常用操作与流转换

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

SATA信息传输FIS结构总结通过实例代码(快速)掌握(二)

目录 一、简介二、总体介绍2.1 详细FIS传输过程2.2 FIS内容详解 三、FIS实例3.1 构造一个write FIS3.1.1 WRITE FIS内容3.1.2 协议分析仪trace分析3.1.3 write过程总trace 3.2 构造一个read FIS3.2.1 READ FIS内容3.2.2 协议分析仪 read trace3.2.3 read过程总trace 3.3 FIS和C…

Linux系统管理:WinSCP 安装与使用

目录 一、实验 1.下载WinSCP 2.安装WinSCP 3.使用WinSCP 一、实验 1.下载WinSCP &#xff08;1&#xff09;地址 Downloading WinSCP-6.1.2-Setup.exe :: WinSCP 2.安装WinSCP &#xff08;1&#xff09;选择安装程序模式 &#xff08;2&#xff09;点击 &#xff08;3…

C++初识类和对象

前言 上一期我们介绍了一些C入门的基础知识&#xff0c;本期我们来介绍面向对象。初步认识一下面向对象和面向过程、类、以及封装&#xff01; 本期内容介绍 面向过程和面向对象 类的引入 类的定义 类的访问限定符和封装 类的作用域 类的实例化 类对象模型 this指针 一、面向…

name 属性:提高 Vue 应用可维护性的关键

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Linux加强篇006-存储结构与管理硬盘

目录 前言 1. 从“/”开始 2. 物理设备命名规则 3. 文件系统与数据资料 4. 挂载硬件设备 5. 添加硬盘设备 6. 添加交换分区 7. 磁盘容量配额 8. VDO虚拟数据优化 9. 软硬方式链接 前言 悟已往之不谏&#xff0c;知来者之可追。实迷途其未远&#xff0c;觉今是而昨非…

5.7 Windows驱动开发:取进程模块函数地址

在笔者上一篇文章《内核取应用层模块基地址》中简单为大家介绍了如何通过遍历PLIST_ENTRY32链表的方式获取到32位应用程序中特定模块的基地址&#xff0c;由于是入门系列所以并没有封装实现太过于通用的获取函数&#xff0c;本章将继续延申这个话题&#xff0c;并依次实现通用版…

linux内核态内存泄漏检测-kmemleak

参考文章&#xff1a;Linux内核态内存泄漏检测工具--kmemleak工具原理及应用_linux 内存泄漏检测工具-CSDN博客 细说&#xff5c;Linux 内存泄漏检测实现原理与实现_内核_指针_信息 kmemleak原理&#xff1a;看网上说大概原理是在通过kmalloc&#xff0c;vmalloc&#xff0c…

分布式锁,分布式锁应该具备哪些条件,分布式锁的实现方式有:基于Zookeeper实现、Redis实现、数据库实现

文章目录 分布式锁0-1分布式锁--包含CAP理论模型概述分布式锁&#xff1a;分布式锁应该具备哪些条件&#xff1a;分布式锁的业务场景&#xff1a; 分布式锁的实现方式有&#xff1a;基于Zookeeper - 分布式锁实现思想优缺点基于Redis - 分布式锁实现思想实现思想的具体步骤&…

[AutoSAR存储] 车载存储层次 和 常用存储芯片概述

公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《AutoSAR存储》 <<<< 返回总目录 <<<< 1 存储系统层次 先抛个问题&#xff0c; 为什么要划分存储器的层次&#xff1f; 速度越快&#xff0c;但成本越高&#xff0c;从经济的角度规…

【Web】[GKCTF 2021]easycms

直接点击登录按钮没有反应 扫目录扫出来/admin.php 访问 弱口令admin 12345直接登录成功 点开设计--主题--自定义 编辑页头&#xff0c;类型选择php源代码 点保存显示权限不够 设计--组件--素材库 先随便上传一个文件&#xff0c;之后改文件名称为../../../../../system/tmp…

OSS+CDN的资费和安全

文章目录 花费OSSCDNOSS CDN 安全OSS防盗链跨域设置CORS数据加密 CDN防盗链URL鉴权Cookie鉴权远程鉴权IP黑白名单UA黑白名单 回源服务自定义私有参数IP黑白名单数据加密 花费 OSS 存储费用 &#xff1a;0.12元/GB/月下行流量费用 &#xff1a;0.5元/GB请求费用 &#xff1a;…

2023金盾杯线上赛-AGRT战队-WP

目录 WEB ApeCoin get_source ezupload easyphp MISC 来都来了 芙宁娜 Honor Crypto 我看看谁还不会RSA hakiehs babyrsa PWN sign-format RE Re1 WEB ApeCoin 扫描发现有源码泄露&#xff0c;访问www.tar.gz得到源码。 在源码中发现了冰蝎马。 Md5解码&am…

持续集成部署-k8s-配置与存储-存储类:动态创建NFS-PV案例

动态创建NFS-PV案例 1. 前置条件2. StorageClass 存储类的概念和使用3. RBAC 配置4. storageClass 配置5. 创建应用&#xff0c;测试 PVC 的自动配置6. 解决 PVC 为 Pending 状态问题7. 单独测试自动创建 PVC 1. 前置条件 这里使用 NFS 存储的方式&#xff0c;来演示动态创建 …

springboot打印启动信息

打印启动信息 转载自:www.javaman.cn 1 spring Bean实例化流程 基本流程&#xff1a; 1、Spring容器在进行初始化时&#xff0c;会将xml或者annotation配置的bean的信息封装成一个BeanDefinition对象&#xff08;每一个bean标签或者bean注解都封装成一个BeanDefinition对象&a…