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