OpenGL的学习之路 -5

news2024/11/29 21:41:53

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;
}

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

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

相关文章

声音响度、声压级计权(A B C)实现

声压 sound pressure 声压就是大气压受到声波扰动后产生的变化&#xff0c;即为大气压强的余压&#xff0c;它相当于在大气压强上的叠加一个声波扰动引起的压强变化。由于声压的测量比较容易实现&#xff0c;通过声压的测量也可以间接求得质点速度等其它物理量&#xff0c;所以…

人工智能入门教学——AI代理(AI Agent)

目录 一、简介 二、特征 三、结构 四、工作流程 五、类型 六、应用 一、简介 AI代理 (Artificial Intelligence Agent)是指使用人工智能技术和算法来执行特定任务、解决问题或实现目标的程序或系统。这些代理可以是简单的程序&#xff0c;也可以是复杂的系统&#xff0c…

学生党福音!一个能自定义词库的单词软件--单词魔方

大家好 我是Yhen 这一期给大家介绍一款自制的单词软件–单词魔方 文章目录 一.创作缘由二.功能介绍&升级内容三.使用方法四.程序获取 一.创作缘由 为什么会有想法开发这个单词软件呢&#xff1f; 因为平时自己在做阅读&#xff0c;看电影时积累下来了一些单词 当我想要系…

Spring Cache(缓存框架)

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

C++ libcxxabi中dynamic_cast 实现

摘要&#xff1a;最近在看一个崩溃的过程中详细看了一遍cxxabi的定义&#xff0c;就想着看一些llvm中cxxabi的一些实现。本文描述了cxxabi中dynamic_cast的实现以及原理。   关键字&#xff1a;cxxabi,dynamic_cast 1 简介 C中&#xff0c;dynamic_cast用于有虚函数的继承链…

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…

vite-性能优化-构建优化-cnd加速优化

CDN 加速优化 - 感觉用不大到 主要作用 &#xff1a; 将引入的依赖&#xff0c;打包部署后&#xff0c;在用户访问的时候&#xff0c; 通过网络CDN的方式进行加载&#xff0c;而非直接从你自己的服务器上加载。优点 &#xff1a; 1、直接降低了你自己的打包的体积&#xff0c…

基于helm的方式在k8s集群中部署gitlab - 部署(一)

文章目录 1. 背景说明2. 你可以学到什么&#xff1f;3. 前置条件4. 安装docker服务&#xff08;所有节点&#xff09;5. 部署k8s集群5.1 系统配置&#xff08;所有节点&#xff09;5.2 安装kubelet组件(所有节点)5.2.1 编写kubelet源5.2.2 安装kubelet5.2.3 启动kubelet 5.3 集…

2023nacos源码解读第4集——整体了解nacos源码模块

文章目录 1、类Linux tree的windows treee工具2、源码目录结构3、模块依赖关系 1、类Linux tree的windows treee工具 windows 自带的tree 不够用&#xff0c;使用node npm安装一个类Linux 的treee npm install -g cnpm --registryhttps://registry.npm.taobao.org npm config…

MySQL 8 手动安装后无法启动的问题解决

开头还是介绍一下群&#xff0c;如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;&#xff08;…

springframe工程导入

配置gradle工程 init.d 目录下新建init.gradle allprojects {repositories {mavenLocal()maven {allowInsecureProtocol trueurl https://maven.aliyun.com/nexus/content/repositories/central/}} } 报错Plugin [id: org.jetbrains.dokka, version: 0.10.1, apply: false] w…

Python集合类型

目录 目标 版本 官方文档 集合分类 实战 创建 循环 常用方法 目标 掌握set和frozenset两种集合的使用方法&#xff0c;包括&#xff1a;创建、交集、并集、差集等操作。 版本 Python 3.12.0 官方文档 Set Types — set, frozensethttps://docs.python.org/3/library/s…

常见指令的数据通路和执行过程

作此篇的原因是17年19题&#xff1a; 本题选A&#xff0c;做的时候总感觉不够通透&#xff0c;因此把这题涉及到的内容全部看了一遍&#xff0c;顿时没有那种朦胧感了 零、五段式流水线&#xff1a; 以下均为MIPS设定&#xff1a;指令长度为32位&#xff0c;主存按字节编址&a…

RC-MVSNet:无监督的多视角立体视觉与神经渲染--论文笔记(2022年)

RC-MVSNet&#xff1a;无监督的多视角立体视觉与神经渲染--论文笔记&#xff08;2022年&#xff09; 摘要1 引言2 相关工作2.1 基于监督的MVS2.2 无监督和自监督MVS2.3 多视图神经渲染 3 实现方法3.1 无监督的MVS网络 Chang, D. et al. (2022). RC-MVSNet: Unsupervised Multi-…

领域驱动设计总结——如何构造领域模型

领域驱动设计总结——如何构造领域模型 本文为领域驱动设计系列总结的第三篇&#xff0c;主要对领域驱动设计概念做个介绍&#xff0c;本系列领域驱动设计总结主要是在Eric Evans 所编写的《领域驱动设计》 一书的基础上进行归纳和总结。本文主要介绍在领域驱动设计中如何构造…

【数据中台】开源项目(2)-Dbus系统架构

大体来说&#xff0c;Dbus支持两类数据源&#xff1a; RDBMS数据源 日志类数据源 1 RMDBMS类数据源的实现 以mysql为例子. 分为三个部分&#xff1a; 日志抽取模块(最新版DBus已经废弃该模块&#xff0c;使用canal直接输出到kafka) 增量转换模块 全量拉取模块 1.1 日志抽…

紫光展锐 展讯芯片 展讯处理器解锁BL 各分区结构 ROM 分区列表代表什么 bin img 表示什么意思

是展锐 Android 10.0、Android 9.0 平台 ROM 空间划分情况以及分区格式、分区大小和分区功能的 初步描述。 prodnv 开机后系统中的 productinfo 分区&#xff0c;保 存 adc 校准参数、eng.db 数据库。 Miscdata 保存 ota、recovery 时的一些数据 recovery 存放 recovery.i…

【深度学习实验】图像处理(二):PIL 和 PyTorch(transforms)中的图像处理与随机图片增强

文章目录 一、实验介绍二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 导入需要的工具包1. PIL图像处理a. 生成绿色和蓝色图像b. 缩放和合成图像c 在合成图像上添加文字d. 展示并保存图像 2. PIL随机图像增强a. 定义随机图像增强函数b. 实验结果展示 3. PyTorch&…

【Amazon】通过代理连接的方式导入 AWS EKS集群至KubeSphere主容器平台

文章目录 一、设置主集群方式一&#xff1a;使用 Web 控制台方式二&#xff1a;使用 Kubectl命令 二、在主集群中设置代理服务地址方式一&#xff1a;使用 Web 控制台方式二&#xff1a;使用 Kubectl命令 三、登录控制台验证四、准备成员集群方式一&#xff1a;使用 Web 控制台…

P17C++析构函数

目录 前言 01 什么是析构函数 1.1 举个栗子 02 为什么要写析构函数 前言 今天我们要讨论一下它的“孪生兄弟”&#xff0c;析构函数&#xff0c;它们在某些方面非常相似。 与构造函数相反&#xff0c;当对象结束其生命周期&#xff0c;如对象所在的函数已调用完毕时&…