计算机图形学作业实验报告.docx
《计算机图形学作业实验报告.docx》由会员分享,可在线阅读,更多相关《计算机图形学作业实验报告.docx(24页珍藏版)》请在冰豆网上搜索。
计算机图形学作业实验报告
计算机图形学
实验报告
班级:
学号:
姓名:
指导教师:
完成日期:
实验一:
多边形填充
1、实验目的
了解多边形属性,熟悉相关函数的调用。
二、实验内容
步骤和实现:
首先进行初始化工作,进行显示模式(单缓冲区)和窗口等设定,主要实现根据两个函数,一个是指定场景绘制函数,glutDisplayFunc(Paint),paint函数中设置了两个三角形,一个填充,一个不填充。
用到了启用多边形点画模式glEnable(GL_POLYGON_STIPPLE)的函数,和指定多边形点画模式(填充)glPolygonStipple(fly)的函数。
另外一个就是循环执行OpenGl命令的glutMainLoop()函数。
三、实验结果
四、源程序
//POLY_STIPPLE.C
#include
voidmakeObject()//定义一个三角形
{glBegin(GL_TRIANGLES);//开始定义三角形
//按逆时针方向指定三角形的顶点坐标
glVertex2f(-0.95,-0.95);
glVertex2f(0.95,-0.95);
glVertex2f(0,0.95);
glEnd();//三角形定义结束
}
voiddisplay()
{GLsizeiw=glutGet(GLUT_WINDOW_WIDTH);//程序窗口宽度
GLsizeih=glutGet(GLUT_WINDOW_HEIGHT);//程序窗口高度
GLubytefly[]=//第二个三角形点画模式的mask值
{0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,//
0X03,0X80,0X01,0XC0,0X06,0XC0,0X03,0X60,//
0X04,0X60,0X06,0X20,0X04,0X30,0X0C,0X20,//
0X04,0X18,0X18,0X20,0X04,0X0C,0X30,0X20,//
0X04,0X06,0X60,0X20,0X44,0X03,0XC0,0X22,//
0X44,0X01,0X80,0X22,0X44,0X01,0X80,0X22,//
0X44,0X01,0X80,0X22,0X44,0X01,0X80,0X22,//
0X44,0X01,0X80,0X22,0X44,0X01,0X80,0X22,//
0X66,0X01,0X80,0X66,0X33,0X01,0X80,0XCC,//
0X19,0X81,0X81,0X98,0X0C,0XC1,0X83,0X30,//
0X07,0XE1,0X87,0XE0,0X03,0X3F,0XFC,0XC0,//
0X03,0X31,0X8C,0XC0,0X03,0X33,0XCC,0XC0,//
0X06,0X64,0X26,0X60,0X0C,0XCC,0X33,0X30,//
0X18,0XCC,0X33,0X18,0X10,0XC4,0X23,0X08,//
0X10,0X63,0XC6,0X08,0X10,0X30,0X0C,0X08,//
0X10,0X18,0X18,0X08,0X10,0X00,0X00,0X08
};
glClear(GL_COLOR_BUFFER_BIT);//清除颜色缓冲区
glViewport(0,0,w/2,h);//第一个视口,显示第一个三角形
glColor3f(1,1,1);//设置颜色,白色,默认值
makeObject();//第一个三角形
glViewport(w/2,0,w/2,h);//第二个视口,显示第二个三角形
glColor3f(1,0,0);//设置颜色,红色
glEnable(GL_POLYGON_STIPPLE);//启用多边形点画模式
glPolygonStipple(fly);//指定多边形点画模式(填充)
makeObject();//第二个三角形
glDisable(GL_POLYGON_STIPPLE);//关闭多边形点画模式
glFlush();//强制OpenGL命令序列在有限的时间内完成执行
}
intmain()
{glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA);
//设置程序窗口的显示模式(单缓冲区、RGBA颜色模型)
glutInitWindowPosition(100,100);//程序窗口的位置
glutInitWindowSize(300,150);//程序窗口的大小
glutCreateWindow("一个填充多边形的例子!
");//窗口的标题
glutDisplayFunc(display);//指定场景绘制函数
glutMainLoop();//开始循环执行OpenGL命令
}
实验二:
基本图元绘制
2、实验目的
了解OpenGL图形软件包绘制图形的基本过程及其程序框架,并在已有的程序框架中添加代码实现直线和圆的生成算法,演示直线和圆的生成过程,从而加深对直线和圆等基本图形生成算法的理解。
二、实验内容
实验操作和步骤:
本次实验主要的目的是为了掌握基本画线和画圆算法,中点画线算法的步骤是(考虑01,输入两个端点,将左端点保存在(x0,y0)中。
2,2,计算a=-(yR-yL),b=xR-xL,2a,2a+2b,p0=2a+b。
3,3,从k=0开始,对每个Xk,绘制(xk,yk),并进行下列检测:
若pk>0,则下一点为(xk+1,yk),且Pk+1=Pk+2a;
若pk<=0,则下一点为(xk+1,yk+1),且pk+1=pk+(2a+2b).
4,重复步骤3,共b次。
中点画圆的算法的步骤是:
1,输入圆半径r和圆心(xc,yc),并得到圆心在原点的圆周上的第一点:
(x0,y0)=(0,r).
2,计算决策参数的初始值:
p0=1-r.
3,从k=0开始,对每个xk,完成下列检测:
若pk<0,则下一点是(Xk+1,Yk)且P(k+1)=Pk+2X(k+1)+1
若pk>=0,则下一点是(Xk+1,Yk-1),且p(k+1)=Pk+2X(k+1)+1-2Y(k+1)
其中,2X(k+1)+1=2Xk+1+2,2Y(k+1)=2Yk-2
4,确定其他七个八分圆中的对称点
5,将计算出来的每个像素位置(x,y)变换到待画圆上:
X=x+xc,y=y+yc
6,重复3-5,直到x>=y
三、实验结果
1-1中点画线算法演示:
1-2中点画圆算法演示
四、源程序
中点画线算法程序:
//xtGL.h
#pragmaonce
#include
#include
//全局变量说明
staticvoid(*__xtViewportFunc)(int,int,int,int);
//指向用户自定义的构建视口和相关变换的函数
//函数说明
intmain(intargc,char*argv[]);
voidxtMain(intargc,char*argv[]);//xtGL的入口函数
staticvoidxtDefaultInit();//默认初始化
voidxtViewportFunc(voidFunc(int,int,int,int));
//指定用户自定义的构建视口和相关变换的函数
staticvoidxtDefaultViewport(intx,inty,intw,inth);
//构建视口和相关变换的默认函数
staticvoidxtDefaultReshape(intw,inth);//默认窗口变化回调函数
staticvoidxtDefaultPaint(void);//默认场景绘制函数
staticvoidxtView(GLuintm,GLuintn,inti,intj);//子区间函数
voidxtViewInit(intm,intn);//初始化子区间个数和大小
voidxtViewBegin(inti,intj);//第i行第j列子区间
voidxtViewEnd();//结束子区间内对象定义
//函数实现
intmain(intargc,char*argv[])
{xtDefaultInit();//默认初始化
xtMain(argc,argv);//xtGL的入口函数
glutMainLoop();//开始循环执行OpenGL命令
}
//默认初始化
staticvoidxtDefaultInit()
{intscw,sch,w,h;//屏幕宽度和高度,程序窗口的宽度和高度
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
//显示模式为:
双缓冲区,RGBA颜色模式,使用深度缓冲器
//只有一次生效,使用该框架只能使用这里规定的显示模式
scw=glutGet(GLUT_SCREEN_WIDTH);//屏幕宽度
sch=glutGet(GLUT_SCREEN_HEIGHT);//屏幕高度
h=sch/2,w=h*4/3;//程序窗口的高度和宽度
glutInitWindowPosition((scw-w)/2,(sch-h)/2);
glutInitWindowSize(w,h);
//默认窗口高度为屏幕高度的一半,宽高比为4:
3,位于屏幕中央
glutCreateWindow(__argv[0]);//窗口的默认标题
glEnable(GL_DEPTH_TEST);//打开深度测试
xtViewportFunc(xtDefaultViewport);//构建视口和相关变换的默认函数
glutReshapeFunc(xtDefaultReshape);//默认的窗口变化回调函数
glutDisplayFunc(xtDefaultPaint);//默认的场景绘制函数
}
//指定用户自定义的构建视口和相关变换的函数
voidxtViewportFunc(voidFunc(int,int,int,int))
{__xtViewportFunc=Func;
}
//构建视口和相关变换的默认函数
staticvoidxtDefaultViewport(intx,inty,intw,inth)
{floataspect;
if(h<=0)return;
aspect=1.0*w/h;//窗口横纵比
glViewport(x,y,w,h);//定义视口
//默认投影矩阵,y向观察范围为60度,近平面为1,远平面为1000
glMatrixMode(GL_PROJECTION);//当前矩阵模式为投影矩阵
glLoadIdentity();//当前矩阵为单位矩阵
gluPerspective(60,aspect,1,1000);
//定义投影矩阵,参数依次为:
y-z夹角;x/y;近平面;远平面
glTranslated(0,0,-2);//远移2单位,保证z坐标可以使用+1
glMatrixMode(GL_MODELVIEW);//当前矩阵模式为视图造型矩阵
glLoadIdentity();//当前矩阵为单位矩阵
}
//默认窗口变化回调函数(构建视口和相关变换)
staticvoidxtDefaultReshape(intw,inth)
{__xtViewportFunc(0,0,w,h);
}
//默认场景绘制函数
voidxtDefaultPaint()
{glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//清除颜色缓存和深度缓存
glutSwapBuffers();//交换颜色缓存
}
//子区间函数,内部使用
staticvoidxtView(GLuintm,GLuintn,inti,intj)
{intw,h,x,y;//子区间的宽度和高度以及子区间的左下角坐标
staticGLuintsvm=1,svn=1;//子区间个数
staticGLuintmaxRow=0;//最大行号
if(i<0||j<0)//初始化子区间个数
{svm=m;svn=n;maxRow=m-1;return;}
if(svm*svn>1)
{//只有当子区间的个数大于1时,才构建视口和相关变换
w=glutGet(GLUT_WINDOW_WIDTH)/svn;//子区间宽度
h=glutGet(GLUT_WINDOW_HEIGHT)/svm;//子区间高度
x=j*w;y=(maxRow-i)*h;//第i行j列子区间的左下位置
__xtViewportFunc(x,y,w,h);//构建视口和相关变换
}
glPushMatrix();//保存当前矩阵
glPushAttrib(GL_ALL_ATTRIB_BITS);//保存所有当前属性值
}
//初始化子区间个数和大小
voidxtViewInit(intm,intn)
{xtView(m,n,-1,-1);
}
//第i行第j列子区间(找到该子区间的位置,开始定义对象)
voidxtViewBegin(inti,intj)
{xtView(0,0,i,j);
}
//结束子区间内的对象定义(恢复当前属性值和当前矩阵)
voidxtViewEnd()
{glPopAttrib();
glPopMatrix();
}
//Demo.h
#pragmaonce
#include
#include"xtGlu.h"
voidinit()
{glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
}
voidaxis(intx1,inty1,intx2,inty2)
{intx,y;
glEnable(GL_LINE_STIPPLE);
glLineStipple(1,0XCCCC);
glLineWidth
(1);
glColor3f(0.5,0.5,0.5);
glBegin(GL_LINES);
for(x=x1;x<=x2;++x)
glVertex2i(x,y1),glVertex2i(x,y2);
for(y=y1;y<=y2;++y)
glVertex2i(x1,y),glVertex2i(x2,y);
glEnd();
glDisable(GL_LINE_STIPPLE);
for(x=x1;x<=x2;++x)
xtStrokeText(x,y1-0.5,0.003,"%d",x);
for(y=y1;y<=y2;++y)
xtStrokeText(x1-0.75,y,0.003,"%d",y);
}
#include
#include"Demo.h"
voidMid_Line1(intx1,inty1,intx2,inty2)
{inta,b,c,x,y,p,_2a,_2a_2b;
if(x2{inttemp;
temp=x1,x1=x2,x2=temp;
temp=y1,y1=y2,y2=temp;
}
a=y1-y2,b=x2-x1;
_2a=2*a,_2a_2b=_2a+2*b;
y=y1,p=2*a+b;
for(x=x1;x<=x2;++x)
{glVertex2i(x,y);
if(p>0)
p=p+_2a;
else
++y,p+=_2a_2b;
}
}
//
voidreshape(intw,inth)
{glViewport(0,0,w,h);
glLoadIdentity();
gluOrtho2D(19,31,9,21);
}
//
voiddisplay()
{
glClearColor(1,1,1,0);
glClear(GL_COLOR_BUFFER_BIT);
axis(20,10,30,18);
glLineWidth(3);
glColor3f(0,0,1);
glBegin(GL_LINES);
glVertex2i(20,10),glVertex2i(30,18);
glEnd();
glPointSize(15);
glColor3f(1,0,0);
glBegin(GL_POINTS);
Mid_Line1(20,10,30,18);
glEnd();
glFlush();
}
//
intmain()
{glutInitWindowSize(400,400);
glutCreateWindow("中点画线算法演示!
");
glutReshapeFunc(reshape);
init();
glutDisplayFunc(display);
glutMainLoop();
}
中点画圆算法程序:
(说明:
引用了Demo.h和xtGlu.h两个头文件)
#include
#include"Demo.h"
voidMid_Circle1(intr)
{intx,y,p,_2x_1,_2y;
x=0,y=r,p=1-r,_2x_1=1,_2y=2*r;
glVertex2i(x,y),glVertex2i(y,x);
while(x{++x,_2x_1+=2;
if(p<0)
p+=_2x_1;
else
--y,_2y-=2,p+=_2x_1-_2y;
glVertex2i(x,y),glVertex2i(y,x);
}
}
//
voidreshape(intw,inth)
{glViewport(0,0,w,h);
glLoadIdentity();
gluOrtho2D(-1,11,-1,11);
}
//
voidmyArc(doubler,doublerad)
{doublex=r,y=0,e=0.1/r;
glVertex2d(x,y);
while(x>0)
x-=e*y,y+=e*x,glVertex2d(x,y);
}
voiddisplay()
{glClearColor(1,1,1,0);
glClear(GL_COLOR_BUFFER_BIT);
axis(0,0,10,10);
glLineWidth
(2);
glColor3f(0,0,1);
glBegin(GL_LINE_STRIP);
myArc(10,1.57);
glEnd();
glPointSize(15);
glColor3f(1,0,0);
glBegin(GL_POINTS);
Mid_Circle1(10);
glEnd();
glFlush();
}
//
intmain()
{glutInitWindowSize(400,400);
glutCreateWindow("中点画圆算法演示!
");
glutReshapeFunc(reshape);
init();
glutDisplayFunc(display);
glutMainLoop();
}
实验三:
太阳系模型动画
一、实验目的
利用OpenGL图形软件包,建立太阳、地球和月亮的运动模型;增加光照系统,模拟太阳、地球和月亮的光照环境;并利用双缓存技术,用动画方式显示模型。
以加深学生对几何变换、投影变换以及观察变换的理解,并提高学生利用图形软件包绘制图形的能力。
二、实验内容
步骤和实现:
首先进行初始化工作,进行显示模式和窗口,设置光源等设定,主要实现根据两个函数,一个是通过重绘,这样在你移动或者改变窗口大小的时候可以保持程序还是正常是实现绘图模式,另外一个就是通过渲染,由于是一个动态的变化,所以需要时间函数来控制变化情况,分别在主窗口部分绘制太阳,地球和月亮,其中对于地球和月亮需要设置旋转角度和平移,而太阳是静态图形,很好绘制,直接调用绘图函数即可,而且由于旋转变化的原因,超过360度要处理,所以需要设定步长,最后通过主循环和时间来控制动态显示,直到用户关闭。
三、实验结果
四、源程序
#include
#include
floatday=0;//地球自转角度
floatmonth=0;//月亮自转和公转角度
floatyear=0;//地球公转角度
floatsun=0;//太阳自转角度
//设置光源
voidsetLight()
{floatpos[][4]=
{{1,0,0,1},{-1,0,0,1},{0,0,1,1},
{0,0,-1,1},{0,1,0,1},