华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx

上传人:b****2 文档编号:2536244 上传时间:2023-05-03 格式:DOCX 页数:28 大小:150.44KB
下载 相关 举报
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第1页
第1页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第2页
第2页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第3页
第3页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第4页
第4页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第5页
第5页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第6页
第6页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第7页
第7页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第8页
第8页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第9页
第9页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第10页
第10页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第11页
第11页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第12页
第12页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第13页
第13页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第14页
第14页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第15页
第15页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第16页
第16页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第17页
第17页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第18页
第18页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第19页
第19页 / 共28页
华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx_第20页
第20页 / 共28页
亲,该文档总共28页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx

《华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx》由会员分享,可在线阅读,更多相关《华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx(28页珍藏版)》请在冰点文库上搜索。

华科大图形学报告 中点Bresenham 算法 画直线 画圆 线刷子日地月模型 光照模型.docx

华科大图形学报告中点Bresenham算法画直线画圆线刷子日地月模型光照模型

 

计算机图形学上机实验报告

计算机科学与技术学院

 

班级:

0911班

学号:

U200915XXX

姓名:

XXXX

指导教师:

徐海银

完成日期:

2011/12/06

 

目录

实验一

实验目的与要求------------------------------------1

实验内容与分析------------------------------------1

实验结果显示---------------------------------------3

实验体会---------------------------------------------8

源代码------------------------------------------------8

实验二

实验目的与要求------------------------------------18

实验内容与分析------------------------------------18

实验结果显示---------------------------------------19

实验体会---------------------------------------------19

源代码-----------------------------------------------20

实验一(基本图元绘制)

实验目的与要求

(1)理解glut程序框架;

(2)理解窗口到视区的变换;

(3)理解OpenGL实现动画的原理;(4)添加代码实现中点Bresenham算法画直线;

(5)添加代码实现改进Bresenham算法画直线;

(6)添加代码实现圆的绘制(可以适当对框架坐标系进行修改);

(7)适当修改代码实现具有宽度的图形(线刷子或方刷子)。

实验内容与分析

①中点Bresenham算法画直线思想:

仅考虑0≤k≤1,由于最大位移方向为x,因此,每次x方向上加1,而y方向上或加1或加0。

判别式初值d=dx-2*dy,若d<0,则(x,y)更新为(x+1,y+1),d更新为d+2*dx-2*dy;否则(x,y)更新为(x+1,y),d更新为d-2*dy。

改进Bresenham算法画直线思想:

判别式初值e=-dx,e每次加2*dy,判断e的符号,若e>0,则(x,y)更新为(x+1,y+1),同时将e更新为e-2*dx;否则(x,y)更新为(x+1,y)。

Bresenham算法绘制圆的算法思想:

若考虑第一象限内x∈「0,R/

」的1/8圆弧,此时最大位移方向为x,因此,每次x方向上走一步,而y方向上或减1或减0。

判别式初值为d=1-R,若d<0,则先将d更新为d+2*x+3,再将(x,y)更新为(x+1,y);否则先将d更新为d+2*(x-y)+5,再将(x,y)更新为(x+1,y-1)。

但是,当圆心不在原点时,不妨设圆心为(x0,y0),则此时判别式初值为d=1-R,若d<0,则先将d更新为d+2*(x-x0)+3;否则先将d更新为d+2*((x-x0)-(y-y0))+5。

而且此时8个对称点分别为(x,y)、(x,2*y0-y)、(y-y0+x0,y0+x0-x)、(x0+y0-y,y0+x0-x)、(2*x0-x,2*y0-y)、(2*x0-x,y)、(x0+y0-y,y0+x-x0)、(x0+y-y0,y0+x-x0)。

即在画1/8圆弧上任一点时,需要同时画出另外7个点,最后即可得到整个圆。

②由于要实现动画,所以需要创建一个循环,在每次调用显示回调函数之前给当前像素点着色,使其看起来像是在直线上连续的画出一个个像素点。

为了不断的调用显示回调函数,需要利用函数glutTimerFunc(unsignedintmsecs,(*func)(intvalue),intvalue),指定一个定时器回调函数,即经过msecs毫秒后由GLUT调用指定的函数,并将value值传递给他。

被定时器调用的函数原型为voidTimerFunction(intvalue),注意,该函数与其他的回调函数不一样的地方在于该函数只会被激发一次。

所以为了实现连续的动画,必须在定时器函数中再次重新设置定时器回调函数。

③线刷子。

当用线刷子处理线宽时,若为竖直刷子,除了需要画出(x,y)像素点之外,还需要画出像素点(x,y+1)和(x,y-1);若为水平刷子,除了需要画出(x,y)像素点之外,还需要画出像素点(x-1,y)和(x+1,y)。

本实验中仅以带竖直刷子的中点Bresenham算法画直线为例。

④程序操作。

程序运行后,会生成一个25X25的网格,每一个网格即代表一个像素点。

共有5种绘制模式:

1、DDA算法画直线(起点(0,0),终点(20,15));2、中点Bresenham算法画直线(起点(0,0),终点(20,15));3、改进Bresenham算法画直线(起点(0,0),终点(20,15));4、八分法绘制圆(圆点(12,12),半径10);5、带线刷子的中点Bresenham算法画直线(起点(0,0),终点(20,15))。

分别通过按键盘上的数字键1~5来调用控制。

在画每一个像素点时,同时会显示当前各点坐标和判别式的值。

 

实验结果显示

(图1.1,DDA画线算法,各点坐标、以及最终画出的直线)

(图1.2,中点Bresenham算法画线,各点坐标、以及最终画出的直线)

(图1.3,改进的Bresenham算法画线,各点坐标、以及最终画出的直线)

(图1.4,中点Bresenham算法画圆,各点坐标、以及最终画出的图形)

 

(图1.5,带竖直线刷子的中点Bresenham算法,各点坐标、以及最终画出的直线)

实验体会

本次实验是我第一次用OpenGL编程,很不习惯它的库函数,因为库函数名太长了,而且由于本人英语不太好,所以显得更难记住函数名。

不过感觉OpenGL功能还是很强大,图形显示效果很不错。

通过本次实验,让我进一步理解了几种基本的图形生成算法,包括DDA画线,中点Bresenhama画线,改进的Bresenhama画线,Bresenhama画圆,以及如何使用线刷子处理线宽。

本来如果让我写出完整的代码,会比较困难,所以很感谢助教老师,给我们展示了实现动画的部分代码,我们只需要稍加修改并添加一些代码即可。

 

源代码(完整代码及注释见附件)

#include

#include

#include"stdio.h"

intm_PointNumber=0;//动画时绘制点的数目

/*不同的m_DrawMode值表示不同的绘制模式。

1DDA算法画直线;2中点Bresenham算法画直线;3改进Bresenham算法画直线;4八分法绘制圆;5带线刷子的中点Bresenham算法画直线。

初始时默认为1*/

intm_DrawMode=1;

voidDrawCordinateLine(void)//绘制坐标线

{

inti=0;

glColor3f(0.0f,0.0f,0.0f);//坐标线为黑色

glBegin(GL_LINES);

for(i=10;i<=250;i=i+10)

{

glVertex2f((float)(i),0.0f);

glVertex2f((float)(i),250.0f);

glVertex2f(0.0f,(float)(i));

glVertex2f(250.0f,(float)(i));

}

glEnd();

}

voidputpixel(GLsizeix,GLsizeiy)//绘制一个像素点,这里用一个正方形表示一个点

{

glRectf(10*x,10*y,10*x+10,10*y+10);

}

/*DDA画线算法。

参数说明:

起点坐标(x0,y0),终点坐标(x1,y1),num扫描转换时从起点开始输出的点的数目,用于动画*/

voidDDACreateLine(GLsizeix0,GLsizeiy0,GLsizeix1,GLsizeiy1,GLsizeinum)

{

glColor3f(1.0f,0.0f,0.0f);//设置颜色

if(num==1)//对画线动画进行控制

printf("DDA画线算法:

各点坐标\n");

elseif(num==0)

return;

//以下为画线算法的实现

GLsizeidx,dy,epsl,k;

GLfloatx,y,xIncre,yIncre;

dx=x1-x0;

dy=y1-y0;

x=x0;

y=y0;

if(abs(dx)>abs(dy))epsl=abs(dx);

elseepsl=abs(dy);

xIncre=(float)dx/epsl;

yIncre=(float)dy/epsl;

for(k=0;k<=epsl;k++)

{

putpixel((int)(x+0.5),(int)(y+0.5));

if(k>=num-1)

{

printf("x=%f,y=%f,取整后x=%d,y=%d,num=%d\n",x,y,(int)(x+0.5),(int)(y+0.5),num);

break;

}

x+=xIncre;

y+=yIncre;

i(x>=25||y>=25)break;

}

}

/*中点Bresenham算法画直线(0<=k<=1)。

参数说明:

起点坐标(x0,y0),终点坐标(x1,y1),num扫描转换时从起点开始输出的点的数目,用于动画*/

voidBresenhamLine1(GLsizeix0,GLsizeiy0,GLsizeix1,GLsizeiy1,GLsizeinum)

{

glColor3f(1.0f,0.0f,0.0f);

if(num==1)

printf("中点Bresenham算法画直线:

各点坐标及判别式的值\n");

elseif(num==0)

return;

//以下为画线算法的实现

GLsizeidx,dy,d,UpIncre,DownIncre,x,y;

if(x0>x1)

{

x=x1;x1=x0;x0=x;

y=y1;y1=y0;y0=y;

}

x=x0;y=y0;

dx=x1-x0;dy=y1-y0;

d=dx-2*dy;

UpIncre=2*dx-2*dy;DownIncre=-2*dy;

while(x<=x1)

{

putpixel(x,y);

if(x-x0>=num-1)

{

printf("x=%d,y=%d,d=%d\n",x,y,d);

break;

}

x++;

if(d<0)

{

y++;

d+=UpIncre;

}

elsed+=DownIncre;

if(x>=25||y>=25)break;

}

}

/*带线刷子的中点Bresenham算法画直线(0<=k<=1)。

参数说明:

x0,y0起点坐标,x1,y1终点坐标,num扫描转换时从起点开始输出的点的数目,用于动画*/

voidBresenhamLine2(GLsizeix0,GLsizeiy0,GLsizeix1,GLsizeiy1,GLsizeinum)

{

glColor3f(1.0f,0.0f,0.0f);

if(num==1)

printf("带线刷子的中点Bresenham算法画直线:

各点坐标及判别式的值\n");

elseif(num==0)

return;

//以下为画线算法的实现

GLsizeidx,dy,d,UpIncre,DownIncre,x,y;

if(x0>x1)

{

x=x1;x1=x0;x0=x;

y=y1;y1=y0;y0=y;

}

x=x0;y=y0;

dx=x1-x0;dy=y1-y0;

d=dx-2*dy;

UpIncre=2*dx-2*dy;DownIncre=-2*dy;

while(x<=x1)

{

putpixel(x,y+1);

putpixel(x,y);

putpixel(x,y-1);

if(x-x0>=num-1)

{

printf("x=%d,y=%d,d=%d\n",x,y,d);

break;

}

x++;

if(d<0)

{

y++;

d+=UpIncre;

}

elsed+=DownIncre;

if(x>=25||y>=25)break;

}

}

/*改进的Bresenham算法画直线(0<=k<=1),参数说明:

起点坐标(x0,y0),终点坐标(x1,y1),num扫描转换时从起点开始输出的点的数目,用于动画*/

voidBresenham2Line(GLsizeix0,GLsizeiy0,GLsizeix1,GLsizeiy1,GLsizeinum)

{

glColor3f(1.0f,0.0f,0.0f);

if(num==1)

printf("改进的Bresenham算法画直线:

各点坐标及判别式的值\n");

elseif(num==0)

return;

GLsizeix,y,dx,dy,e;

dx=x1-x0;dy=y1-y0;

e=-dx;x=x0;y=y0;

while(x<=x1)

{

putpixel(x,y);

if(x-x0>=num-1)

{

printf("x=%d,y=%d,e=%d\n",x,y,e);

break;

}

x++;

e=e+2*dy;

if(e>0)

{

y++;

e=e-2*dx;

}

}

}

//画出以(x0,y0)为圆心,包括点(x,y)在内的8个对称点

voidcirclePoint(GLsizeix0,GLsizeiy0,GLsizeix,GLsizeiy)

{

putpixel(x,y);

putpixel(x,2*y0-y);

putpixel(y-y0+x0,y0+x0-x);

putpixel(x0+y0-y,y0+x0-x);

putpixel(2*x0-x,2*y0-y);

putpixel(2*x0-x,y);

putpixel(x0+y0-y,y0+x-x0);

putpixel(x0+y-y0,y0+x-x0);

}

/*Bresenham算法画圆。

参数说明:

圆心坐标(x0,y0),圆半径r,num扫描转换时从起点开始输出的点的数目,用于动画*/

voidBresenhamCircle(GLsizeix0,GLsizeiy0,GLsizeir,GLsizeinum)

{

glColor3f(1.0f,0.0f,0.0f);

if(num==1)

printf("Bresenham算法画圆:

各点坐标及判别式的值\n");

elseif(num==0)

return;

GLsizeix,y,d;

x=x0;y=y0+r;d=1-r;

while(x-x0<=y-y0)

{

circlePoint(x0,y0,x,y);

if(x-x0>=num-1)

{

printf("x=%d,y=%d,d=%d\n",x,y,d);

break;

}

if(d<0)d+=2*(x-x0)+3;

else

{

d+=2*((x-x0)-(y-y0))+5;

y--;

}

x++;

}

}

//初始化窗口,设置窗口颜色为蓝色

voidInitial(void)

{

glClearColor(1.0f,1.0f,1.0f,1.0f);

}

//窗口大小改变时调用的登记函数

voidChangeSize(GLsizeiw,GLsizeih)

{

if(h==0)h=1;

glViewport(0,0,w,h);//设置视区尺寸

glMatrixMode(GL_PROJECTION);

glLoadIdentity();//重置坐标系统

if(w<=h)//建立修剪空间的范围

glOrtho(0.0f,250.0f,0.0f,250.0f*h/w,1.0,-1.0);

else

glOrtho(0.0f,250.0f*w/h,0.0f,250.0f,1.0,-1.0);

}

//在窗口中绘制图形

voidReDraw(void)

{

glClear(GL_COLOR_BUFFER_BIT);//用当前背景色填充窗口

DrawCordinateLine();//画出坐标线

switch(m_DrawMode)

{

case1:

DDACreateLine(0,0,20,15,m_PointNumber);

break;//DDA算法画线

case2:

BresenhamLine1(0,0,20,15,m_PointNumber);

break;//中点Bresenham算法画线

case3:

Bresenham2Line(0,0,20,15,m_PointNumber);

break;//改进的中点Bresenham算法画线

case4:

BresenhamCircle(12,12,10,m_PointNumber);

break;//Bresenham算法画圆

case5:

BresenhamLine2(0,0,20,15,m_PointNumber);

break;//带竖直线刷子的中点Bresenham算法画线

default:

break;

}

glFlush();

}

//设置时间回调函数

voidTimerFunc(intvalue)

{

if(m_PointNumber==0)value=1;

m_PointNumber=value;

glutPostRedisplay();

glutTimerFunc(500,TimerFunc,value+1);

}

//设置键盘回调函数,按键盘1~5,调用不同的画线模式

voidKeyboard(unsignedcharkey,intx,inty)

{

if(key=='1')m_DrawMode=1;

if(key=='2')m_DrawMode=2;

if(key=='3')m_DrawMode=3;

if(key=='4')m_DrawMode=4;

if(key=='5')m_DrawMode=5;

m_PointNumber=0;

glutPostRedisplay();

}

//主函数

intmain(intargc,char*argv[])

{

glutInit(&argc,argv);

//初始化GLUT库OpenGL窗口的显示模式

glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);

glutInitWindowSize(600,600);

glutInitWindowPosition(100,100);

glutCreateWindow("基本图元绘制程序--0911班刘荡");

glutDisplayFunc(ReDraw);

glutReshapeFunc(ChangeSize);

glutKeyboardFunc(Keyboard);//键盘响应回调函数

glutTimerFunc(500,TimerFunc,1);

Initial();//窗口初始化

glutMainLoop();//启动主GLUT事件处理循环

return0;

}

 

实验二(日地月模型)

实验目的与要求

(1)理解OpenGL中的变换过程;

(2)理解透视投影与平行投影的不同;

(3)添加代码实现太阳、地球和月亮的运动模型;(4)了解深度测试;

(5)通过变换调整观察的位置与方向;(6)加入光照模型。

实验内容与分析

①首先,我们认定这三个天体都是标准的球形,建立以下坐标系:

太阳的中心为原点,地球绕太阳旋转的平面与X轴与Z轴决定的平面平行,即glRotatef(increment1,0.0f,1.0f,0.0f);月亮绕地球旋转的平面与X轴与Y轴决定的平面平行,即glRotatef(increment2,0.0f,0.0f,1.0f)。

且每年第一天,地球在X轴正方向上,月亮在地球的正X轴方向。

而且根据地球绕太阳转、月亮绕地球转的关系,画图时,可以依次画太阳、地球、月亮,这样可以不必使用连续使用glPushMatrix()、glPopMatrix()来保存当前的模型视图矩阵,同样可以保证地球绕太阳转、月亮绕地球转。

②由于月亮绕地球旋转的速度是地球绕太阳旋转速度的12倍,为便于计算角度,可设地球绕太阳旋转角度为increment1,月亮绕地球旋转角度为increment2,初值均为0,为产生旋转的动画,还应增加旋转步长,increment1每次增加2度,而increment1每次增加24度。

③为了得到透视效果,我们使用gluPerspective来设置可视空间。

假定可视角为45度,最近可视距离为1.0,最远可视距离为500。

④当地球、月亮处于太阳的不同位置时,应该考虑遮挡效果。

比如,地球处在太阳背面时,地球不可见。

为增强真实感的立体感,应激活光照和深度检测。

为以示区别,可假定除太阳外,地球和月亮本身也可发光,就通过设置材质Emission成分使物体看起来有发光效果。

为产生光照的视觉效果,可使用glEnable(GL_LIGHTING)、glEnable(GL_LIGHT1)启用光照系统和点光源,且点光源就在太阳中心所在的位置。

在环境中增加漫反射,相应的,使用glMaterialfv()给太阳、地球,月亮设置对漫反射光的反射率的RGBA值,即可达到效果。

⑤程序操作。

直接运行程序即可显示运行效果。

实验结果

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2