计算机图形学设计.docx
《计算机图形学设计.docx》由会员分享,可在线阅读,更多相关《计算机图形学设计.docx(20页珍藏版)》请在冰豆网上搜索。
计算机图形学设计
《计算机图形学》课程设计报告
题目名称:
机器人手臂
专业计算机科学与技术
班级
学号
姓名
指导教师王玉昆
2014年6月12日
机器人手臂
一、设计内容与要求
1.1设计题目
机器人手臂
1.2设计内容
内容:
(1)掌握动画基本原理;
(2)实现三维几何变换及其组合;
功能要求:
(1)利用glutWireCube创建机器手臂:
上臂,前臂,带有手指的手
(2)编写三维旋转变换矩阵实现“上臂带动前臂转,前臂带动手转”的效果;
(3)使用键盘的上下左右控制键各部分的旋转;
1.3设计目标
通过课程设计,使学生具备通过具体的平台实现图形算法的设计、编程与调试的能力,完成对实验结果分析、总结及撰写技术报告的能力,达到:
巩固和实践计算机图形学课程中的理论和算法;
学习表现计算机图形学算法的技巧;
培养认真学习、积极探索的精神。
二、方案设计
2.1总体方案设计
1.图形学基本原理
(1)几何变换相关原理
视点变换和模型变换在计算机图形学中统一称为几何变换。
视点变换和模型变换只是考虑问题的出发点不同,最后变换的结果都是一样的。
几何变换是指三维场景中的物体运动姿态的变化,包括物体的平移,旋转和缩放。
在OpenGL中提供了3个命令函数来实现平移,旋转和缩放。
它们是glTranslate(),glRotate(),glScale(),从而可以确定一个物体在场景中的位置,旋转角度和缩放比例。
直接使用OpenGL中的矩阵操作函数可以实现几何变换,但是使用OpenGL中的变换函数,变换的速度要快得多。
(2)几何图形像素化相关原理
是指单元格中颜色值相近的像素结成块来清晰的定义一个选区。
(3)光照模型相关原理
当光线照射到物体表面上时,将出现3种情况:
光从物体表面反射,形成反射光。
光穿透物体,形成透射光。
光被物体吸收,转化称为物体的内能。
在上述3种情形的光线中,通常只有前两种情况的光线会对人眼产生视觉效果,使人察觉到物体的色彩变化。
OpenGL用一种近似的光照模型模拟现实世界的光照效果。
在该模型中,仅当物体表面吸引和反射光线时,光源才会起作用。
每一个物体表面都假定是由具有某种特性的材料构成的。
一种材料可能发出自己的光线,也可能在各个方向上发散一些射入的光线,还有可能象镜子一样在某个方向强烈地反射入射光。
2.2.系统界面与操作说明
(1)系统界面与图形显示示例
(2)操作说明(配合图示进行说明)
肩膀:
'a'顺时针旋转,'A'逆时针旋转手臂:
's'顺时针旋转,'S'逆时针旋转
手掌:
'd'顺时针旋转,'D'逆时针旋转
大拇指:
'g'向外翻转,'G'向内翻转
大拇指指尖:
't'向外翻转,'T'向内翻转
食指:
'h'向内,'H'向外
食指指尖:
'y'向外翻转,'Y'向内翻转
中指:
'j'向内,'J'向外
中指指尖:
'u'向外翻转,'U'向内翻转
无名指:
'k'向内,'K'向外
无名指指尖:
'i'向外翻转,'I'向内翻转
小指:
'l'向内,'L'向外
小指指尖:
'o'向外翻转,'O'向内翻转
2.3过程流程图
五步初始化窗口的模式
调用
glutDisplayFunc调用显示模型voiddisplay
glutReshapeFunc可以重新构造窗口voidreshape
glutKeyboardFunc调用键盘函数voidkeyboard
glutMainLoop
三、详细设计
3.1、源程序与注释
#include
#include"gl/glut.h"//添加公用库,不然无窗口也无法使用键盘
//一些函数要求OpenGL的类型作为参数,GLfloat,32-bit浮点
GLfloatrotShoulder=0.0;//肩-45~90
GLfloatrotElbow=0.0;//肘0~160
GLfloatrotWrist=0.0;//腕-80~80
//以下取值范围为0~90
GLfloatrotFinger10=0.0;//拇指和手掌相联的关节
GLfloatrotFinger11=0.0;//手指上的关节
GLfloatrotFinger20=0.0;//食指
GLfloatrotFinger21=0.0;
GLfloatrotFinger30=0.0;//中指
GLfloatrotFinger31=0.0;
GLfloatrotFinger40=0.0;//无名指
GLfloatrotFinger41=0.0;
GLfloatrotFinger50=0.0;//小指
GLfloatrotFinger51=0.0;
voidinit()
{
staticGLfloatlight0_position[]={1.0,1.0,1.0,0.0};
staticGLfloatlight0_diffuse[]={0.0,1.0,1.0,1.0};
glClearColor(1.0,1.0,0.0,0.0);//建立窗口被创建成为什么背景色黄色
glShadeModel(GL_SMOOTH);//一个多边形可以初始化为一个颜色(flatshading)或者多个不同的颜色(smoothshading),此函数默认指定为GL_SMOOTH
glEnable(GL_DEPTH_TEST);//状态可以改变,和它相反的是glDisable()
glEnable(GL_LIGHTING);//OpenGL必须明确定义光照,不然关照模型,光源,材质都无法显示
glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);//可以定以至少8种光,这里是白光。
可以定义为聚光灯还是泛光灯
glEnable(GL_LIGHT0);//定义了你要的灯的特征,你要把它们用此函数转化,你也需要调用glEnable()准备运行灯光函数的计算参数
}
voidreshape(GLsizeiw,GLsizeih)//32位整形,相当于long
{
if(0==h)
h=1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,(GLfloat)w/(GLfloat)h,0.1,500.0);
glMatrixMode(GL_MODELVIEW);
}
voiddisplay()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清空色深缓冲和位深缓冲
glLoadIdentity();//当视角转换被指定,先要定义当前矩阵,如果不定义会和上次的矩阵一起
gluLookAt(0.0,0.0,60.0,0.0,0.0,0.0,0.0,1.0,0.0);//指定相机的放置,目标指向哪,什么方式(0,1,0)向上指示
glRotatef(30.0,0.0,1.0,0.0);//关于y轴偏30°
glPushMatrix();//肩
glTranslatef(6.0,0.0,0.0);//把对象正移6个单位/把视点负移6个单位
glRotatef(rotShoulder,0.0,0.0,1.0);//沿z轴旋转rotShoulder角度
glScalef(12.0,2.0,4.0);//这个函数用来指定沿三个轴缩放多少,x轴12,y轴2,z轴4
glutSolidCube(1.0);
glScalef(1.0/12.0,1.0/2.0,1.0/4.0);//消除对之后坐标的影响
glPushMatrix();//肘
glTranslatef(6.0,0.0,0.0);
glRotatef(rotElbow,0.0,0.0,1.0);
glTranslatef(6.0,0.0,0.0);//分两次平移,第一次使得旋转轴在立方体尾部
glScalef(12.0,2.0,4.0);
glutSolidCube(1.0);
glScalef(1.0/12.0,1.0/2.0,1.0/4.0);
glPushMatrix();//手掌
glTranslatef(6.0,0.0,0.0);
glRotatef(rotWrist,0.0,0.0,1.0);
glTranslatef(3.0,0.0,0.0);
glScalef(6.0,1.0,4.0);
glutSolidCube(1.0);
glScalef(1.0/6.0,1.0,1.0/4.0);
glPushMatrix();//拇指与手腕相联的关节
glTranslatef(-1.0,0.0,-1.0);
glRotatef(-rotFinger10,0.0,0.0,1.0);
glRotatef(rotFinger10,1.0,0.0,0.0);
glTranslatef(-1.0,0.0,-2.0);
glScalef(1.0,1.0,2.0);
glutSolidCube(1.0);
glScalef(1.0,1.0,1.0/2.0);
glPushMatrix();//拇指上的关节
glTranslatef(0.0,0.0,-1.0);
glRotatef(rotFinger11,1.0,0.0,0.0);
glTranslatef(0.0,0.0,0.0);
glScalef(1.0,1.0,2.0);
glutSolidCube(1.0);
glPopMatrix();
glPopMatrix();
glPushMatrix();//食指与手腕相联的关节
glTranslatef(3.0,0.0,-1.5);
glRotatef(rotFinger20,0.0,0.0,1.0);
glTranslatef(1.0,0.0,0.0);
glScalef(2.0,1.0,1.0);
glutSolidCube(1.0);
glScalef(1.0/2.0,1.0,1.0);
glPushMatrix();//食指上的关节
glTranslatef(1.0,0.0,0.0);
glRotatef(rotFinger21,0.0,0.0,1.0);
glTranslatef(1.25,0.0,0.0);
glScalef(2.5,1.0,1.0);
glutSolidCube(1.0);
glPopMatrix();//食指关节出栈
glPopMatrix();//食指出栈
/**********************************************************/
glPushMatrix();//中指
glTranslatef(3.0,0.0,-1.5);
glRotatef(rotFinger30,0.0,0.0,1.0);
glTranslatef(1.0,0.0,1.0);
glScalef(2.5,1.0,1.0);
glutSolidCube(1.0);
glScalef(1.0/2.0,1.0,1.0);
glPushMatrix();
glTranslatef(1.0,0.0,0.0);
glRotatef(rotFinger31,0.0,0.0,1.0);
glTranslatef(1.25,0.0,0.0);
glScalef(2.5,1.0,1.0);
glutSolidCube(1.0);
glPopMatrix();
glPopMatrix();
/*************************************************************/
glPushMatrix();//无名指
glTranslatef(3.0,0.0,-1.5);
glRotatef(rotFinger40,0.0,0.0,1.0);
glTranslatef(1.0,0.0,2.0);
glScalef(2.0,1.0,1.0);
glutSolidCube(1.0);
glScalef(1.0/2.0,1.0,1.0);
glPushMatrix();
glTranslatef(1.0,0.0,0.0);
glRotatef(rotFinger41,0.0,0.0,1.0);
glTranslatef(1.25,0.0,0.0);
glScalef(2.5,1.0,1.0);
glutSolidCube(1.0);
glPopMatrix();
glPopMatrix();
/***************************************************************/
glPushMatrix();//小指
glTranslatef(3.0,0.0,-1.5);
glRotatef(rotFinger50,0.0,0.0,1.0);
glTranslatef(1.0,0.0,3.0);
glScalef(1.5,1.0,1.0);
glutSolidCube(1.0);
glScalef(1.0/1.5,1.0,1.0);
glPushMatrix();
glTranslatef(1.0,0.0,0.0);
glRotatef(rotFinger51,0.0,0.0,1.0);
glTranslatef(1.25,0.0,0.0);
glScalef(2.5,1.0,1.0);
glutSolidCube(1.0);
glPopMatrix();
glPopMatrix();
/************************************************************/
glPopMatrix();//手掌出栈
glPopMatrix();//上臂出栈
glPopMatrix();//整个手臂出栈
glutSwapBuffers();//交换缓冲区
}
voidkeyboard(GLubytekey,GLintx,GLinty)
{
//小写字母减少旋转度数,大写字母增加
switch(key){
//肩
case'a':
If(rotShoulder>-45.0)
rotShoulder-=5.0;
glutPostRedisplay();//程序改变窗口的内容
break;
case'A':
if(rotShoulder<90.0)
rotShoulder+=5.0;
glutPostRedisplay();
break;
//肘
case's':
if(rotElbow>0.0)
rotElbow-=5.0;
glutPostRedisplay();
break;
case'S':
if(rotElbow<160.0)
rotElbow+=5.0;
glutPostRedisplay();
break;
//腕
case'd':
if(rotWrist>-80.0)
rotWrist-=5.0;
glutPostRedisplay();
break;
case'D':
if(rotWrist<80.0)
rotWrist+=5.0;
glutPostRedisplay();
break;
//拇指
case'g':
if(rotFinger10>0.0)
rotFinger10-=5.0;
glutPostRedisplay();
break;
case'G':
if(rotFinger10<90.0)
rotFinger10+=5.0;
glutPostRedisplay();
break;
case't':
if(rotFinger11>0.0)
rotFinger11-=5.0;
glutPostRedisplay();
break;
case'T':
if(rotFinger11<90.0)
rotFinger11+=5.0;
glutPostRedisplay();
break;
//食指
case'h':
if(rotFinger20>0.0)
rotFinger20-=5.0;
glutPostRedisplay();
break;
case'H':
if(rotFinger20<90.0)
rotFinger20+=5.0;
glutPostRedisplay();
break;
case'y':
if(rotFinger21>0.0)
rotFinger21-=5.0;
glutPostRedisplay();
break;
case'Y':
if(rotFinger21<90.0)
rotFinger21+=5.0;
glutPostRedisplay();
break;
case'j':
if(rotFinger30>0.0)
rotFinger30-=5.0;
glutPostRedisplay();
break;
case'J':
if(rotFinger30<90.0)
rotFinger30+=5.0;
glutPostRedisplay();
break;
case'u':
if(rotFinger31>0.0)
rotFinger31-=5.0;
glutPostRedisplay();
break;
case'U':
if(rotFinger31<90.0)
rotFinger31+=5.0;
glutPostRedisplay();
break;
case'k':
if(rotFinger40>0.0)
rotFinger40-=5.0;
glutPostRedisplay();
break;
case'K':
if(rotFinger40<90.0)
rotFinger40+=5.0;
glutPostRedisplay();
break;
case'i':
if(rotFinger41>0.0)
rotFinger41-=5.0;
glutPostRedisplay();
break;
case'I':
if(rotFinger41<90.0)
rotFinger41+=5.0;
glutPostRedisplay();
break;
case'l':
if(rotFinger50>0.0)
rotFinger50-=5.0;
glutPostRedisplay();
break;
case'L':
if(rotFinger50<90.0)
rotFinger50+=5.0;
glutPostRedisplay();
break;
case'o':
if(rotFinger51>0.0)
rotFinger51-=5.0;
glutPostRedisplay();
break;
case'O':
if(rotFinger51<90.0)
rotFinger51+=5.0;
glutPostRedisplay();
break;
default:
break;
}
}
intmain(intargc,char**argv)
{//五步初始化窗口的模式调用
glutInit(&argc,argv);//初始化glut和任何命令线的参数
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);//用双缓存,rgba颜色模式,深度缓存
glutInitWindowPosition(200,100);//指定屏幕左上点位置
glutInitWindowSize(400,300);//用像素指定大小
glutCreateWindow("机器人手臂");//直到glutMainLoop()被调用,此窗口开始被调用了
init();
glutDisplayFunc(display);
//glutDisplayFunc(void(*func)(void))是第一个也是最重要的回调函数,不断要重复的函数就放在这里
glutReshapeFunc(reshape);
//回调函数,当你初始打开一个窗口或者之后移动或者重新定义大小,窗口会发送一个外部事件来通知你
//重新建立有新画布的矩形区
//定义物体将被画的坐标系统
glutKeyboardFunc(keyboard);//调用键盘的函数
glutMainLoop();
return0;
四、总结
4.1、经验总结
总结在原理理解、程序设计中所遇到的困难是如何解决的,可以举出1至2个例子。
问题分为3类,一类是大方向问题,比如一开始编程序时连OpenGL用VC编都不知道,这时去问下老师是比较快的方法。
听了老师的建议后,对自己做的东西拿捏就比较准,不至于盲目的前进。
问了老师以后,老师只是大方向给了提示,具体还是要自己做,就快速的看一些相关的书,这里的快速不是细细钻研,而是快速的学习。
书上给的程序和自己项目有关的就快速的用。
差不多如此就可以大概的完成程序,毕竟我们的目的是完成程序,而不是搞研究,这样基本就可以完成了。
大程序完成后就一般会有第二类问题,是自己创新的问题。
因为是自己的东西,所以一定要有创新,要加一些自己的东西。
这时就要对程序有个比较深入的了解了。
细细研究一下程序的算法等等,问问老师,多和同学交流,上网看高手的博客,或者在群里讨论,有时候别人的一句话就可能让你恍然大悟。
不然很