资源描述
实验报告
课程名称:三维图形程序设计
学 院:计算机科学与工程学院
专 业:计算机科学与技术
指导教师:曹跃
学生姓名:郭小明
学 号:2011060100010
实验成绩:
日 期:2013 年 5 月 3 日
电 子 科 技 大 学
实 验 报 告
实验一:三维图形程序上机操作训练与图元编程
一. 实验室名称:主楼A2412 实验时间:2013年5月 3日
二.实验目的:
1. 掌握VC中OpenGL三维编程环境的建立过程;
2. 掌握GLUT编写OpenGL应用程序的基本步骤,熟悉GLUT基于事件驱动的编程模型;
3. 掌握不同类型图元的顶点装配方式,并能够利用图元建立简单的几何对象。
三.实验原理:
OpenGL编程语言
面向对象编程技术
四. 实验内容:
(一)安装、配置和测试OpenGL三维编程环境
1. 首先检查Windows操作系统中是否正确安装了Visual Studio集成开发环境:实验要求在Windows XP、Visual C++ 2005平台以上;
2. 解压OpenGL.zip到任意目录下;
3. 检查OpenGL核心库和实用库及其头文件是否安装正确和完整:检查%VSINSTALLDIR%\VC\PlatformSDK\Include\GL目录下是否存在gl.h、glu.h两个头文件,并从解压得到的GL子目录下拷贝缺少的头文件到该目录下;检查%VSINSTALLDIR%\VC\PlatformSDK\Lib目录下是否存在OpenGL32.lib、GLU32.lib两个库文件,并从解压得到的Lib子目录下拷贝缺少的Lib文件到该目录下;
4. 安装GLUT库及其头文件。从解压得到的GL子目录下拷贝glut.h到%VSINSTALLDIR%\VC\PlatformSDK\Include\GL目录中,从解压得到的Lib子目录下拷贝 glut32.lib到%VSINSTALLDIR%\VC\PlatformSDK\Lib下,拷贝glut32.dll到%windir%\system32目录下。
5. 检测OpenGL环境是否配置正确。
a. 打开Visual Studio集成开发环境,新建一个类型为“Win32控制台应用程序”的空项目Test;
b. 在项目中新建一个C源文件Test.c;
c. 拷贝如下代码到Test.c中;
d. 生成Test项目,观察“输出”窗口中的编译和链接输出信息,若显示类似“生成: 1 已成功, 0 已失败, 0 最新, 0 已跳过”表明项目生成成功,否则根据输出信息检查程序或者OpenGL编程环境是否设置正确,并在改正后重新生成Test项目;
e. 运行Test.exe查看程序是否能够正常启动。
/** Test.C **/
#include <GL/glut.h>
void display();
void init();
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutCreateWindow(“Simple”);
glutDisplayFunc(display);
init();
glutMainLoop();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
}
void init()
{
glClearColor(0.0,0.0,0.0,0.0);
}
(二)编程任务1:
1. 分别利用点、线图元生成锥形螺旋曲线和环形螺旋曲线,要求可以设置点的大小、线可以设置线形和宽度。
锥形螺旋曲线的参数方程为:
环形螺旋曲线的参数方程为:
其中,t为参数且。a,b和c是常数,比如可取a=2.0,b=3.0,c=18.0。
(三)编程任务2:
1. 在窗口中绘制三角形和四边形两个简单填充图形,要求它们能够被鼠标选中并随鼠标一起拖动,此外能够使用右键菜单分别设置两个简单图形的颜色。
2. 利用三角形图元生成黑白相间的圆锥台,要求通过键盘或鼠标能够改变圆锥台地大端和小端直径。
五.实验要求
1. 实验前要做好充分准备。
2. 实验中独立完成源程序编辑、编译、链接过程,运行并记录程序运行结果;
3. 对程序结果进行分析。
六、实验器材(设备、元器件):
编译器 Microsoft Visual Studio 2010 OpenGLAPI 函数库
七、实验步骤:
1: 首先需要配置OpenGL编程环境,在 Microsoft Visual Studio 2010 中添加相应的头文件以及lib文件,头文件添加地址为 C:\Program Files\Microsoft Visual Studio 10.0\VC\include\GL
lib文件添加地址 C:\Program Files\Microsoft Visual Studio 10.0\VC\lib
并且将glut.dll 添加到System.32 的文件夹里
配置过程如图:
下面是需要的头文件:(有)
将头文件放入:C:\Program Files\Microsoft Visual Studio 10.0\VC\include\GL
下面是需要的lib文件
C:\Program Files\Microsoft Visual Studio 10.0\VC\lib
把他们放入 C:\Program Files\Microsoft Visual Studio 10.0\VC\lib就行了
下面是建立OpenGL工程的过程
选择空项目:
然后输入名称
选择添加C++文件
键入代码就可以了。
2 然后根据相应的编程要求进行编程试验 具体实现过程
八、 实验数据及结果分析:
编程任务1:
分别利用点、线图元生成锥形螺旋曲线和环形螺旋曲线,要求可以设置点的大小、线可以设置线形和宽度。
锥形螺旋曲线的参数方程为:
环形螺旋曲线的参数方程为:
其中,t为参数且。a,b和c是常数,比如可取a=2.0,b=3.0,c=18.0。
#include<GL/glut.h>
#include <math.h>
#define PI 3.14
void drawMyLines()
{
float t;
float x,y,z;
float a=2,b=3,c=18;
glColor3f(1.0,0.5,0.5);
glBegin(GL_LINE_STRIP);
for(t=0.0;t<=2*PI;t+=0.0002)
{
x=a*t*cos(c*t)+b;
y=a*t*sin(c*t)+b;
z=c*t;
glVertex3f(x,y,z);
}
glEnd();
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES); //建立坐标轴
glVertex3f(0,0,0);
glVertex3f(12,0,0);
glEnd();
glBegin(GL_LINES); //建立坐标轴
glVertex3f(0,0,0);
glVertex3f(0,0,12);
glEnd();
glBegin(GL_LINES); //建立坐标轴
glVertex3f(0,0,0);
glVertex3f(0,12,0);
glEnd();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
drawMyLines(); //调用drawMyLines函数
glFlush();
}
void init()
{
glClearColor(0.0,0.0,0.0,0.0);
glColor3f(1.0,1.0,1.0);
gluLookAt(1,1,1, //更改视角
3,3,3,
-1,-1,1
);
glMatrixMode(GL_PROJECTION); //设置投影模式
glLoadIdentity(); //设置单位矩形
glOrtho(-12.0,12.0,-12.0,12.0,-12,12);
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Simple");
glutDisplayFunc(display);
init();
glutMainLoop(); //使程序一直处在监听状态中
return 0;
}
#include<GL/glut.h>
#include <math.h>
#define PI 3.14
void drawMyLines()
{
float t;
float x,y,z;
float a=2,b=3,c=18;
glColor3f(1.0,0.5,0.5);
glBegin(GL_LINE_STRIP); // 绘制函数模块
for(t=0.0;t<=2*PI;t+=0.0002)
{
x=(a*sin(c*t)+b)*cos(t);
y=(a*sin(c*t)+b)*sin(t);
z=a*cos(c*t);
glVertex3f(x,y,z);
}
glEnd();
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES); //绘制坐标轴
glVertex3f(0,0,0);
glVertex3f(12,0,0);
glEnd();
glBegin(GL_LINES); //绘制坐标轴
glVertex3f(0,0,0);
glVertex3f(0,0,12);
glEnd();
glBegin(GL_LINES); //绘制坐标轴
glVertex3f(0,0,0);
glVertex3f(0,12,0);
glEnd();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
drawMyLines();
glFlush();
}
void init()
{
glClearColor(0.0,0.0,0.0,0.0);
glColor3f(1.0,1.0,1.0);
gluLookAt(1,1,1,
3,3,3,
-1,-1,1
);
glMatrixMode(GL_PROJECTION); //设置投影模式
glLoadIdentity(); //使用单位矩阵
glOrtho(-12.0,12.0,-12.0,12.0,-12,12);
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Simple");
glutDisplayFunc(display);
init();
glutMainLoop();
return 0;
}
编程任务2:
1. 在窗口中绘制三角形和四边形两个简单填充图形,要求它们能够被鼠标选中并随鼠标一起拖动,此外能够使用右键菜单分别设置两个简单图形的颜色。
#include <stdio.h>
#include <GL/glut.h>
#define SIZE 512
int wide=600,height=600;
GLint HITS;
void init()
{
glClearColor (1.0, 1.0, 1.0, 0.0);
}
int Rect1_x1=-250,Rect1_y1=-250,Rect1_x2=450,Rect1_y2=450;
int Rect2_x1=-500,Rect2_y1=-500,Rect2_x2=250,Rect2_y2=250;
int movex1=0,movey1=0;
int movex2=0,movey2=0;
int mousex=0,mousey=0;
int RGB1[3]={1.0,1.0,0.0};
int RGB2[3]={0.0,1.0,1.0};
void drawObjects(GLenum mode,int flag)
{
if(mode == GL_SELECT) glLoadName(1);
glColor3f(RGB1[0],RGB1[1],RGB1[2]);
glTranslated(4*movex1,4*movey1,0);
glRectf(Rect1_x1,Rect1_y1 ,Rect1_x2 ,Rect1_y2 );
glTranslated(-4*movex1,-4*movey1,0);
if(mode == GL_SELECT) glLoadName(2);
glColor3f(RGB2[0],RGB2[1],RGB2[2]);
glTranslated(4*movex2,4*movey2,0);
glBegin(GL_TRIANGLES);
glVertex2i(0,0);
glVertex2i(145,245);
glVertex2i(-45,280);
glEnd();
glTranslated(-4*movex2,-4*movey2,0);
}
void display(int flag)
{
glClear(GL_COLOR_BUFFER_BIT);
drawObjects(GL_RENDER,flag);
glFlush();
}
void processHits (GLint hits, GLuint buffer[])
{
unsigned int i, j;
GLint ii, jj, names, *ptr;
printf ("hits = %d\n", hits);
ptr = (GLint *) buffer;
for (i = 0; i < hits; i++) {
names = *ptr;
ptr+=3;
for (j = 0; j < names; j++) {
if(*ptr==1)
printf ("red rectangle\n");
else
printf ("blue rectangle\n");
ptr++;
}
printf ("\n");
}
}
GLuint selectBuf[SIZE];
void mouse(int button, int state, int x, int y) //鼠标函数
{
GLint hits;
GLint viewport[4];
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
mousex = x;
mousey = y;
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SIZE, selectBuf);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y),5.0, 5.0, viewport);
gluOrtho2D (-2.0*wide, 2.0*wide, -2.0*height, 2.0*height);
drawObjects(GL_SELECT,0);
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glFlush ();
hits = glRenderMode (GL_RENDER);
HITS = hits;
processHits (hits, selectBuf);
glutPostRedisplay();
}
}
void reshape(int w, int h)
{
wide = w;
height = h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-2.0*wide, 2.0*wide, -2.0*height, 2.0*height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}
void motion(int x,int y) //建立移动函数
{
if(HITS == 1 && selectBuf[3] == 1 )
{
movex1 = x-mousex+movex1;
movey1 = mousey-y+movey1;
display(1);
}
else if (HITS == 1 && selectBuf[3] == 2 )
{
movex2 = x-mousex+movex2;
movey2 = mousey-y+movey2;
display(2);
}
else if (HITS == 2 )
{
movex1 = x-mousex+movex1;
movey1 = mousey-y+movey1;
movex2 = x-mousex+movex2;
movey2 = mousey-y+movey2;
display(3);
}
mousex = x;
mousey = y;
}
void subMenu1Func(int data) //设置控制键盘键
{
switch(data)
{
case 1:
RGB1[0]=1.0;
RGB1[1]=0.0;
RGB1[2]=0.0;
break;
case 2:
RGB1[0]=0.0;
RGB1[1]=1.0;
RGB1[2]=0.0;
break;
case 3:
RGB1[0]=0.0;
RGB1[1]=0.0;
RGB1[2]=1.0;
break;
}
display(0);
}
void subMenu2Func(int data) //设置控制键盘键
{
switch(data)
{
case 1:
RGB2[0]=1.0;
RGB2[1]=0.0;
RGB2[2]=0.0;
break;
case 2:
RGB2[0]=0.0;
RGB2[1]=1.0;
RGB2[2]=0.0;
break;
case 3:
RGB2[0]=0.0;
RGB2[1]=0.0;
RGB2[2]=1.0;
break;
}
display(0);
}
void MenuFunc(int data)
{
}
int subMenu1,subMenu2,Menu;
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (wide, height);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
//创建菜单改变颜色
subMenu1 = glutCreateMenu(subMenu1Func);
glutAddMenuEntry("红ì色?",1);
glutAddMenuEntry("绿ì色?",2);
glutAddMenuEntry("蓝?色?",3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
//创建菜单改变颜色
subMenu2 = glutCreateMenu(subMenu2Func);
glutAddMenuEntry("红ì色?",1);
glutAddMenuEntry("绿ì色?",2);
glutAddMenuEntry("蓝?色?",3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
Menu = glutCreateMenu(MenuFunc);
//为两个菜单设置名字
glutAddSubMenu("设置方块1的颜色",subMenu1);
glutAddSubMenu("设置三角形1的?颜色",subMenu2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutReshapeFunc (reshape);
glutDisplayFunc(display);
glutMouseFunc (mouse);
glutKeyboardFunc (keyboard);
glutMotionFunc(motion);
glutMainLoop();//是程序的监听一直运行,保证捕捉到操作,直到
return 0;
}
这是生成的图像:一个绿色的三角形和一个黄色的矩形 系统可以根据操作
他们可以随着鼠标的拖动而移动 下面是移动的图像的截图:分别把三角形移动到上方 把矩形移动到下方
下面分别通过右击更改图形的颜色,把三角形的颜色通过菜单选项改成了红色,
下面将矩形的颜色改成绿色:
编程任务3:利用三角形图元生成黑白相间的圆锥台,要求通过键盘或鼠标能够改变圆锥台地大端和小端直径。
#include <GL\glut.h>
#include <math.h>
#include <stdio.h>
void init()
{
glClearColor(0.0,0.0,0.0,0.0); //清除颜色并进行设置
glOrtho(-100,100,-100,100,-100,100); //设置视口
}
int D_top=10,D_bottom=20,H=20;
float PI = 3.14159;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
int i=0;float angle=0.0f;
glBegin(GL_TRIANGLES);
for(;i<32;angle += PI/32.0f,i++)
{
glColor3f(0.9,0.9,0.9);
glVertex3f(D_bottom*cos(angle),D_bottom*sin(angle),0);
glVertex3f(D_bottom*cos(angle+PI/16.0),D_bottom*sin(angle+PI/16.0),0);
glVertex3f(D_top*cos(angle),D_top*sin(angle),H);
glColor3f(0.1,0.1,0.2);
glVertex3f(D_top*cos(angle),D_top*sin(angle),H);
glVertex3f(D_top*cos(angle+PI/16.0),D_top*sin(angle+PI/16.0),H);
glVertex3f(D_bottom*cos(angle+PI/16.0),D_bottom*sin(angle+PI/16.0),0);
}
glEnd();
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0,0,0);
for(i=0;i<33;angle += PI/16.0f,i++)
{
glColor3f(1.0,1.0,1.0);
glVertex3f(D_bottom*cos(angle),D_bottom*sin(angle),0);
glColor3f(0.1,0.1,0.2);
glVertex3f(D_bottom*cos(angle+PI/32.0),D_bottom*sin(angle+PI/32.0),0);
}
glEnd();
glBegin(GL_TRIANGLE_FAN); //绘制图形
glVertex3f(0,0,H);
for(i=0;i<32;angle += PI/32.0f,i++)
{
glColor3f(1.0,1.0,1.0);
glVertex3f(D_top*cos(angle),D_top*sin(angle),H);
glColor3f(0.1,0.1,0.1);
glVertex3f(D_top*cos(angle+PI/32.0),D_top*sin(angle+PI/32.0),H);
}
glEnd();
glFlush();
}
void keyboard(unsigned char key, int x, int y) //设置移动键盘键
{
switch(key)
{
case 'x':
printf("x");
glRotatef(10,1.0,0.0,0.0);
break;
case 'y':
printf("y");
glRotatef(10,0.0,1.0,0.0);
break;
case 'z':
printf("z");
glRotatef(10,0.0,0.0,1.0);
break;
case 'D':
D_top += 2;
break;
case 'd':
D_top -= 2;
break;
case 'R':
D_bottom += 2;
break;
case 'r':
D_bottom -= 2;
break;
case 'H':
H += 2;
break;
case 'h':
H -= 2;
break;
}
display();
}
int main(int argc,char ** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(100,100); // 设置窗口位置
glutInitWindowSize(500,500); //设置窗口大小
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard); //调用键盘函数
glutMainLoop();
return 0;
}
这是试验程序运行之后的结果:
通过键盘键X可以对圆锥台进行旋转:
通过shift +d可以将圆锥台的底面积扩大:
通过shift+h 可以讲圆锥台的高度增高:
九、总结、改进建议及心得体会:
1:通过本实验的操作,掌握VC中OpenGL三维编程环境的建立过程,对操作实践有了更进一步的认识,认识了实践的重要性。
2: 通过本实验掌握GLUT编写OpenGL应用程序的基本步骤,熟悉GLUT基于事件驱动的编程模型;
3: 学习了openGL的事件监听机制的使用方法,颜色绘制的方法,图形组合的方法,动态移动图形的方法。 知道了API函数库对于编程的重要性,体会到了编程过程的乐趣。在不断地调试过程中,逐步掌握了面向对象编程的深刻思想。
4:知道了仔细阅读经典程序是学习的重要方式。
十:编制的应用程序上机调试的情况、上机调试步骤、调试所遇到的问题
1:在调试过程中出现了较多的代码编辑错误,足以可见自己的编写代码的能力还是有待加强的。
2:上机调试过程中出现了与文件名后缀有关的问题,在某些编程模式下需要使用.c
作为后缀,而有些情况下需要.cpp作为后缀名。
3.第二个程序在如何分别控制两个图形移动的分别控制出现了较大问题,最后仍存在小bug,比如在移动的时候选择的不精确,主要是因为坐标计算不精确导致的。
展开阅读全文