这是慕课上的计算机图形学的作业,作业要求是:
具体要求:
(1)构建一个三维场景:
可利用glut提供的各种简单形体来搭建;或者读入别的模型来构成场景。
加入光照效果。
(2)用键盘操纵一个物体(如一艘飞船,或一个机器人)在三维场景中漫游。
视点可以放在物体上,或跟随物体;可利用gluLookAt( )函数来实现对视点的控制。
撰写的作业文档中包括:
(1)程序功能的描述,效果请附图;
(2)论述实现漫游的程序思路;
(3)漫游操作顺畅,效果良好。
因为刚开始学,真的体会到了绘图的奥妙,光照纹理这些神奇的计算,也体会到了数学对于计算机的重要性,这里画的机器人其实在做许多重复的事情,其中的重点就是坐标的计算和glPushMatrix、glPopMatrix的使用。下面是效果:
下面是实现的代码:
注释都在代码中
#include
#include
#include
using namespace std;
const GLfloat Pi = 3.1415926536f;
//摄像机离物体的距离
float G_fDistance = 3.6f;
//机器人的旋转角度
float G_fAngle_horizon = 0.0;
float G_fAngle_vertical = 0.0f;
float G_left_upper_arm1 = 0.0;//左上臂运动角度(左右运动)
float G_left_upper_arm2 = 0.0;//左上臂运动角度(前后运动)
float G_left_lower_arm1 = 0.0f;//左下臂运动角度(左右运动)
float G_left_lower_arm2 = 0.0f;//左下臂运动角度(前后运动)
float G_right_upper_arm1 = 0.0;//右上臂运动角度(左右运动)
float G_right_upper_arm2 = 0.0;//右上臂运动角度(前后运动)
float G_right_lower_arm1 = 0.0f;//右下臂运动角度(左右运动)
float G_right_lower_arm2 = 0.0f;//右下臂运动角度(前后运动)
float G_left_upper_leg = 0.0;//左大腿运动角度(前后运动)
float G_left_lower_leg = 0.0f;//左小腿运动角度(前后运动)
float G_right_upper_leg = 0.0;//右大腿运动角度(前后运动)
float G_right_lower_leg = 0.0f;//右小腿运动角度(前后运动)
void myinit(void);
void myReshape(GLsizei w, GLsizei h);
void display(void);
void processSpecialKeys(int key, int x, int y);
void processNormalKeys(unsigned char key,int x,int y);
void timer(int value);
//主函数
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
//初始化OPENGL显示方式
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
//设定OPENGL窗口位置和大小
glutInitWindowSize (500, 800);
glutInitWindowPosition (100, 100);
//打开窗口
glutCreateWindow ("简单机器人");
cout<<"w,s,a,d控制机器人右上臂前后左右"<<"\n";
cout<<"5、2、1、3控制机器人左臂上臂前后左右"<<"\n";
cout<<"t、g、f、h控制机器人右下臂前后左右"<<"\n";
cout<<"i、k、j、l控制机器人左臂下臂前后左右"<<"\n";
cout<<"6、7控制机器人右大腿前后"<<"\n";
cout<<"8、9控制机器人左大腿前后"<<"\n";
cout<<"z、x控制机器人右小腿前后"<<"\n";
cout<<"c、v控制机器人左小腿前后"<<"\n";
cout<<"‘[’、‘]’用来控制机器人离屏幕远近"<<"\n";
cout<<"键盘上的上下左右键可以旋转机器人"<<"\n";
//调用初始化函数
myinit();
//设定窗口大小变化的回调函数
glutReshapeFunc(myReshape);
//设定键盘控制的回调函数
glutSpecialFunc(processSpecialKeys);
glutKeyboardFunc(processNormalKeys);
//开始OPENGL的循环
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
void myinit(void)//初始化
{
glEnable(GL_DEPTH);
}
void myReshape(GLsizei w, GLsizei h)//设定窗口大小变化的回调函数
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)w/(GLfloat)h,1,30);
}
void drawstar(GLfloat a,GLfloat x,GLfloat y)//画星星的函数
{//a为星星的半径,x,y为平移的量
GLfloat bx = a * cos(18 * Pi/180);
GLfloat by = a * sin(18 * Pi/180);
GLfloat cy = -a * cos(36 * Pi/180);
GLfloat cx = a * sin(36 * Pi/180);
GLfloat
PointA[2] = { 0, a },
PointB[2] = { bx, by },
PointC[2] = { cx, cy },
PointD[2] = { -cx, cy },
PointE[2] = { -bx, by };
// 按照A->C->E->B->D->A的顺序,可以一笔将五角星画出
glTranslatef(x,y,0.0);
glColor3f(1.0,1.0,0.0);
glBegin(GL_LINE_LOOP);
glVertex2fv(PointA);
glVertex2fv(PointC);
glVertex2fv(PointE);
glVertex2fv(PointB);
glVertex2fv(PointD);
glEnd();
}
void drawfinger(GLfloat x,GLfloat y,GLfloat z)//画手指
{
glPushMatrix();
glColor3f(0.0,0.0,1.0);
glTranslatef(x,y,z);
glPushMatrix();
glScalef(0.025,0.05,0.025);
glutSolidCube(1.0);
glPopMatrix();
glPopMatrix();
}
void drawfoot(GLfloat x,GLfloat y,GLfloat z)//画脚
{
glPushMatrix();
glColor3f(0.0,0.0,1.0);
glTranslatef(x,y,z);
glPushMatrix();
glScalef(0.25,0.05,0.25);
glutSolidCube(1.0);
glPopMatrix();
glPopMatrix();
}
void display(void)
{
//清除颜色和深度缓存
glClearColor(0.0,0.0,0.0,0.0);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//视角的变化
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-G_fDistance);
glRotatef(G_fAngle_horizon, 0.0f, 1.0f, 0.0f);
glRotatef(G_fAngle_vertical, 1.0f, 0.0f, 0.0f);
//身体
glColor3f(1.0,0.0,0.0);
glPushMatrix();
glScalef(1.0,0.75,0.5);
glutSolidCube(1.0);
glPopMatrix();
//画五星红旗
glPushMatrix();
GLfloat distance=0.15;//大的五角星到小的五角星的距离
GLfloat x1=distance*cos(54*Pi/180);
GLfloat y1=distance*sin(54*Pi/180);
GLfloat x2=distance*cos(18*Pi/180);
GLfloat y2=distance*sin(18*Pi/180);
drawstar(0.1,-0.4,0.225);
glPushMatrix();
drawstar(0.05,x1,y1);
glPopMatrix();
glPushMatrix();
drawstar(0.05,x2,y2);
glPopMatrix();
glPushMatrix();
drawstar(0.05,x1,-y1);
glPopMatrix();
glPushMatrix();
drawstar(0.05,x2,-y2);
glPopMatrix();
glPopMatrix();
//头和眼
glPushMatrix();
//头
glTranslatef(0.0,0.625,0.0);
glColor3f(0.8,0.5,0.2);
glutSolidSphere(0.25,20,20);
//绿帽子
glPushMatrix();
glColor3f(0.0,1.0,0.0);
glTranslatef(0.0,0.25,0.0);
glRotatef(90,1.0,0.0,0.0);
glutSolidTorus(0.1,0.15,20,20);
glPopMatrix();
//左眼
glPushMatrix();
glColor3f(1.0,0.0,0.0);
glTranslatef(-0.12,0.0,0.0);
glScalef(1.0,0.75,0.5);
glutSolidSphere(0.1,20,20);
glPopMatrix();
//右眼
glPushMatrix();
glColor3f(1.0,0.0,0.0);
glTranslatef(0.12,0.0,0.0);
glScalef(1.0,0.75,0.5);
glutSolidSphere(0.1,20,20);
glPopMatrix();
glPopMatrix();
//左臂
glPushMatrix();
//左上臂
glColor3f(1.0,0.0,1.0);
glTranslatef(-0.575,0.375,0.0);
glRotatef(G_left_upper_arm1,0.0,0.0,1.0);
glRotatef(G_left_upper_arm2,1.0,0.0,0.0);
glTranslatef(0.0,-0.225,0.0);
glPushMatrix();
glScalef(0.125,0.45,0.3);
glutSolidCube(1.0);
glPopMatrix();
//左肘
glColor3f(0.0,1.0,1.0);
glTranslatef(0.0,-0.25625,0.0);
glutSolidSphere(0.0625,20,20);
//左下臂
glColor3f(1.0,0.0,1.0);
glTranslatef(0.0,-0.03125,0.0);
glRotatef(G_left_lower_arm1,0.0,0.0,1.0);
glRotatef(G_left_lower_arm2,1.0,0.0,0.0);
glTranslatef(0.0,-0.225,0.0);
glPushMatrix();
glScalef(0.125,0.45,0.15);
glutSolidCube(1.0);
glPopMatrix();
//画手指
drawfinger(-0.0675,-0.25,0.075);
drawfinger(0.0675,-0.25,0.075);
drawfinger(0,-0.25,-0.075);
glPopMatrix();
//右臂
glPushMatrix();
//右上臂
glColor3f(1.0,0.0,1.0);
glTranslatef(0.575,0.375,0.0);
glRotatef(G_right_upper_arm1,0.0,0.0,1.0);
glRotatef(G_right_upper_arm2,1.0,0.0,0.0);
glTranslatef(0.0,-0.225,0.0);
glPushMatrix();
glScalef(0.125,0.45,0.3);
glutSolidCube(1.0);
glPopMatrix();
//右肘
glColor3f(0.0,1.0,1.0);
glTranslatef(0.0,-0.25625,0.0);
glutSolidSphere(0.0625,20,20);
//右下臂
glColor3f(1.0,0.0,1.0);
glTranslatef(0.0,-0.03125,0.0);
glRotatef(G_right_lower_arm1,0.0,0.0,1.0);
glRotatef(G_right_lower_arm2,1.0,0.0,0.0);
glTranslatef(0.0,-0.225,0.0);
glPushMatrix();
glScalef(0.125,0.45,0.15);
glutSolidCube(1.0);
glPopMatrix();
//画手指
drawfinger(-0.0675,-0.25,0.075);
drawfinger(0.0675,-0.25,0.075);
drawfinger(0,-0.25,-0.075);
glPopMatrix();
//左腿
glPushMatrix();
//左大腿
glColor3f(1.0,0.0,1.0);
glTranslatef(0.15,-0.375,0.0);
glRotatef(G_left_upper_leg,1.0,0.0,0.0);
glTranslatef(0.0,-0.225,0.0);
glPushMatrix();
glScalef(0.25,0.45,0.3);
glutSolidCube(1.0);
glPopMatrix();
//左膝盖
glColor3f(0.0,1.0,1.0);
glTranslatef(0.0,-0.25625,0.0);
glutSolidSphere(0.0625,20,20);
//左小腿
glColor3f(1.0,0.0,1.0);
glTranslatef(0.0,-0.0625,0.0);
glRotatef(G_left_lower_leg,1.0,0.0,0.0);
glTranslatef(0.0,-0.225,0.0);
glPushMatrix();
glScalef(0.125,0.45,0.3);
glutSolidCube(1.0);
glPopMatrix();
drawfoot(0.0,-0.25,0.0);
glPopMatrix();
//右腿
glPushMatrix();
//右大腿
glColor3f(1.0,0.0,1.0);
glTranslatef(-0.15,-0.375,0.0);
glRotatef(G_right_upper_leg,1.0,0.0,0.0);
glTranslatef(0.0,-0.225,0.0);
glPushMatrix();
glScalef(0.25,0.45,0.3);
glutSolidCube(1.0);
glPopMatrix();
//右膝盖
glColor3f(0.0,1.0,1.0);
glTranslatef(0.0,-0.25625,0.0);
glutSolidSphere(0.0625,20,20);
//右小腿
glColor3f(1.0,0.0,1.0);
glTranslatef(0.0,-0.0625,0.0);
glRotatef(G_right_lower_leg,1.0,0.0,0.0);
glTranslatef(0.0,-0.225,0.0);
glPushMatrix();
glScalef(0.125,0.45,0.3);
glutSolidCube(1.0);
glPopMatrix();
drawfoot(0.0,-0.25,0.0);
glPopMatrix();
//交换前后缓冲区
glutSwapBuffers();
}
//响应键盘输入, 从而设定物体移近移远以及旋转的回调函数
void processSpecialKeys(int key, int x, int y)
{
switch(key) {
case GLUT_KEY_LEFT:
G_fAngle_horizon -= 5.0f;
break;
case GLUT_KEY_RIGHT:
G_fAngle_horizon += 5.0f;
break;
case GLUT_KEY_UP:
G_fAngle_vertical -= 5.0f;
break;
case GLUT_KEY_DOWN:
G_fAngle_vertical += 5.0f;
break;
}
glutPostRedisplay();
}
void processNormalKeys(unsigned char key,int x,int y)
{
switch(key) {
case 91: //"["
G_fDistance -= 0.3f;
break;
case 93: //"]"
G_fDistance += 0.3f;
break;
case 49: //1
G_left_upper_arm1-=15.0;
break;
case 51: //3
G_left_upper_arm1+=15.0;
break;
case 50: //2
G_left_upper_arm2-=15.0;
break;
case 53: //5
G_left_upper_arm2+=15.0;
break;
//i、k、j、l控制机器人左臂下臂前后左右
case 106: //j
G_left_lower_arm1-=15.0;
break;
case 108: //l
G_left_lower_arm1+=15.0;
break;
case 105: //i
G_left_lower_arm2-=15.0;
break;
case 107: //k
G_left_lower_arm2+=15.0;
break;
case 97: //a
G_right_upper_arm1-=15.0;
break;
case 100: //d
G_right_upper_arm1+=15.0;
break;
case 119: //w
G_right_upper_arm2-=15.0;
break;
case 115: //s
G_right_upper_arm2+=15.0;
break;
case 102: //f
G_right_lower_arm1-=15.0;
break;
case 104: //h
G_right_lower_arm1+=15.0;
break;
case 116: //t
G_right_lower_arm2-=15.0;
break;
case 103: //g
G_right_lower_arm2+=15.0;
break;
case 56://8
G_left_upper_leg-=15.0;
break;
case 57://9
G_left_upper_leg+=15.0;
break;
case 99://c
G_left_lower_leg-=15.0;
break;
case 118://v
G_left_lower_leg+=15.0;
break;
case 54://6
G_right_upper_leg-=15.0;
break;
case 55://7
G_right_upper_leg+=15.0;
break;
case 122://z
G_right_lower_leg-=15.0;
break;
case 120://x
G_right_lower_leg+=15.0;
break;
case 27: //"esc"
exit(0);
}
glutPostRedisplay();
}