




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
计算机图形学实验报告
姓名:_________________
学号:___________________________
班级:___________________________
时间:20XX年XX月
实验一OpenGL编程与图形绘制
1.实验目的
了解OpenGL编程,并熟悉OpenGL的主要功能、绘制流程和基本语法。学会配置
OpenGL环境,并在该环境中编程绘图。
2.实验内容
OpenGL的主要功能:模型绘制、模型观察、颜色模式、光照应用、图像效果增强、位
图和图像处理、纹理映射、实时动画和交互技术。
OpenGL的绘制流程分为两个方面:一个完整的窗口系统的OpenGL图形处理系统的结
构为:最底层为图形硬件,第二层为操作系统,第三层为窗口系统,第四层为OpenGL,最
上面的层为应用软件;OpenGL命令将被放在一个命令缓冲区中,这样命令缓冲区中包含了
大量的命令、顶点数据和纹理数据。当缓冲区被清空时,缓冲区中的命令和数据都将传递给
流水线的下一个阶段。
OpenGL的基本语法中相关库有:OpenGL核心库:gl,OpenGL实用程序库:glu、OpenG
编程辅助库:aux、OpenGL实用程序工具包(OpenGLutilitytoolkit,GLUT):glut、Windows
专用库:wgl,
OpenGL的基本语法中命名规则为:OpenGL函数都遵循一个命名约定,即采用以下格
式:〈库前缀〉<根命令><可选的参数个数><可选的参数类型〉。
了解了上述基础知识后,配置好OpenGL环境,然后在该环境中编程练习图形的绘制,
本次实验主要是对点的绘制、直线的绘制和多边形面的绘制。
3.实验代码及结果
3.1点的绘制:
#include<gl/glul.h>
voidInitial(void)
{
glClearColor(1.Of,1.Of,1.Of,1.00;〃设置窗口背景颜色为白色
glMatrixMode(GL_PROJECTION);〃指定设置投影参数
gluOrtho2D(0.0,200.0,0.0,150.0);〃设置投影参数
voidDisplay(void)
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景颜色填充窗口
glColor3f(1.0f,0.0f,0.0f);〃设置当前的绘图颜色为红
//glRectf(50.0f,100.0f,150.0f,50.0f);〃绘制一个矩形
glPointSize(lO);〃三个点
glBegin(GL_POINTS);
glColor3f(1.0f,0.0f,0.0f);
glVertex2i(2,148);
glVertex2i(100,75);
glVertex2i(198,2);
glEnd();
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
)
intmain(intargc,char*argv[J)
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的显示模式
glutInitWindowSize(400,300);〃设置窗口的尺寸
glutInitWindowPosition(100,120);〃设置窗口位置
glutCreateWindow("矩形");//创建一个名为矩形的窗口
glutDisplayFunc(Display);〃设置当前窗口的显示回调函数
Initial();〃完成窗口初始化
glutMainLoopO;〃完成窗口GLUT事件处理循环
return0;
运行结果:
■矩形□0B
3.2直线的绘制:
#include<gl/glut.h>
voidInitial(void)
(
glClear€olor(1.01;1.Of,1.Of,1.00;〃设置窗口背景颜色为白色
glMatrixMode(GL_PROJECTION);〃指定设置投影参数
gluOrtho2D(0.0,200.0,0.0,150.0);〃设置投影参数
voidDisplay(void)
(
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景颜色填充窗口
glColor3f(1.0f,0.0f,0.0D;〃设置当前的绘图颜色为红色
//glRectf(50.0f,l()0.0f,150.0f,50.0f);〃绘制一个矩形
glBegin(GL_LINE_LOOP);〃五角星
glVertex2i(10,10);
glVertex2i(30,35);
glVertex2i(50,10);
glVertex2i(5,25);
glVertex2i(55,25);
glEnd();
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
intmain(mtargc,char*argv[])
(
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的显示模式
glutInitWindowSize(400,300);〃设置窗口的尺寸
glutInitWindowPosition(100,120);〃设置窗口位置
glutCreateWindow("矩形");//创建一个名为矩形的窗口
glutDisplayFunc(Display);〃设置当前窗口的显示回调函数
Initial();〃完成窗口初始化
glutMainLoopO;〃完成窗口GLUT事件处理循环
return0;
运行结果:
■矩形13回区
3.3多边形面的绘制:
#include<gl/glut.h>
voidInitial(void)
glClearColor(1.Of,1.Of,1.Of,1.00;〃设置窗口背景颜色为白色
glMatrixMode(GL_PROJECTION);//指定设置投影参数
gluOrtho2D(0.0,200.0,0.0,150.0);〃设置投影参数
)
voidDisplay(void)
(
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景颜色填充窗口
glColor3f(l.0f,0.0f,0.0f);〃设置当前的绘图颜色为红色
//glRectf(50.0f,100.0f,150.0f,50.0f);〃绘制一个矩形
glBegin(GL_TRIANGLES);〃等边三角形
glVertex2f(0.0,0.0);
glVertex2f(15,25.95);
glVertex2f(30,0);
glEnd();
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
)
intmain(intargc,char*argv[])
(
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的显示模式
glutInitWindowSize(400,300);〃设置窗口的尺寸
glutInitWindowPosition(100,120);〃设置窗口位置
glutCreateWindow("矩形”);〃创建一个名为矩形的窗口
glutDisplayFunc(Display);〃设置当前窗口的显示回调函数
Initial();〃完成窗口初始化
glutMainLoopO;〃完成窗口GLUT事件处理循环
return0;
运行结果:
实验二直线绘制实验
1.实验目的
为了进一步熟悉OpenGL编程,了解基本图形生成算法中的直线绘制,学会直线绘制算
法中最常用的三种算法:数值微分法、中点画线算法和Bresenham算法。
2.实验内容
(-)数值微分法
数值微分法直接从直线的微分方程生成直线。给定直线的两端点:P0(X0,Y0)和
P1(X1,Y1),得到直线的微分方程dy/dx=Ay/Ax=(Yl-YO)/(Xl-XO)=k。
数值微分算法的原理是,由于直线的一阶导数是连续的,而且和是成比例的,
因此通过在当前位置(Xi,Yi)分别加上两个小增量£和为无穷小的正数)来
求下一点(X(i+1),Y(i+1))的x,y坐标。
(-)中点画线算法
给定直线的两端点:PO(XO,YO)和P1(X1,Y1),可得到直线方程F(x,y)=y-kx-b=O且k=A
y/Ax=(Yl-YO)/(Xl-XO)o
绘图过程如下:
①.输入直线的两端点PO(XO,YO)和P1(X1,Y1)O
②.计算初始值Ax,Ay,d=Ax-2Ay,x=XO,y=YO.
③.绘制点(x,y)。判断d的符号,若d<0,则(x,y)更新为(x+l,y+l),d更新为d+2Z\x-2
△y;否则(x,y)更新为(x+1,y),d更新为Ay。
④.当直线没有画完时,重复步骤③,否则结束。
(三)Bresenham算法
算法步骤如下:
①.输入直线两端点PO(XO,YO)和P1(X1,Y1)»
②.计算初始值△*,Ay,e=-Ax,x=XO,y=Y0o
③.绘制点(x,y)。
@.e更新为e+2Ayo判断e的符号,若e>0,则(x,y)更新为(x+1,y+1),同样将e更新为
e-2Ax;否则(x,y)更新为(x+1,y)。
⑤.当直线没有画完时,重复步骤③和④;否则结束。
3.实验代码及结果
3.1数值微分算法编程绘制直线代码:
#include<gl/glul.h>
#include<windows.h>
voidInitial(void)
(
glClearColor(1.Of,1.Of,1.Of,1.00;〃设置窗口背景颜色为白色
glMatrixMode(GL_PROJECTION);〃指定设置投影参数
gluOrlho2D(0.0,200.0,0.0,150.0);//设置投影参数
}
voidDisplay(void)
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景颜色填充窗口
glColor3f(1.0f,0.0f,0.0f);〃设置当前的绘图颜色为红色
g]Begin(GL_LINES);
intx0=10;inty0=20;intxl=30;intyl=40;intcolor=10;
intdx,dy,epsl,k;
floatx,y,xlncre,ylncre;
dx=xl-xO;
dy=yl-yO;
x=xO;
y=yO;//
if(abs(dx)>abs(dy))
epsl=abs(dx);
elseepsl=abs(dy);
xlncre=(float)dx/(float)epsl;
ylncre=(float)dy/(float)epsl;
for(k=0;k<=epsl;k++)
(
glVertex2i(int(x+0.5),(int)(y+0.5));
x+=xlncre;
y+=ylncre;
)
glEnd();
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
)
intmain(intargc,char*argv[])
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的显示模式
glutInitWindowSize(400,300);〃设置窗口的尺寸
glutInitWindowPosition(100,120);//设置窗口位置
glutCreateWindow("矩形)〃创建一个名为矩形的窗口
glutDisplayFunc(Display);〃设置当前窗口的显示回调函数
Initial();〃完成窗口初始化
glutMainLoop();〃完成窗口GLUT事件处理循环
return0;
实验结果:
2.2中点画线算法编程绘制直线代码:
#include<gl/glut.h>
#include<windows.h>
voidInitial(void)
(
glClearColor(1.Of,1.Of,1.Of,1.Of);〃设置窗口背景颜色为白色
glMatrixMode(GL_PROJECTION);〃指定设置投影参数
gluOrtho2D(0.0,200.0,0.0,150.0);//设置投影参数
)
voidDisplay(void)
(
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景颜色填充窗口
glColor3f(1.0f,0.0f,0.0D;〃设置当前的绘图颜色为红色
glBegin(GL_POINTS);
intx0=50;inty0=20;intxl=100;intyl=120;intcolor=10;
intdx,dy,d,UpIncre,DownIncre,x,y;
if(x0>xl)
(
x=xl;xl=x0;x0=x;
y=yl;yl=yO;yO=y;
)
x=x0;y=y0;
dx=x1-xO;dy=y1-yO;
d=dx-2*dy;
Uplncre=2*dx-2*dy;Downlncre=2*dy;
while(x<=xl)
(
glVertex2i(x,y);
x++;
if(d<0)
y++;
d十二Uplncre;
)
elsed+=DownIncre;
glEndO;
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
)
intmain(intargc,char*argv[])
(
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的显示模式
glutInitWindowSize(400,300);〃设置窗口的尺寸
glutInitWindowPosition(100J20);〃设置窗口位置
glutCreateWindow(“矩形");〃创建一个名为矩形的窗口
glutDispIayFunc(Display);〃设置当前窗口的显示回调函数
Initial();〃完成窗口初始化
glutMainLoopO;〃完成窗口GLUT事件处理循环
return0;
实验结果:
■矩形目|回冈
2.3Bresenham算法编程绘制直线代码:
#include<gl/glut.h>
#include<windows.h>
voidInitial(void){
glClearColor(1.Of,1.Of,1.Of,1.Of);〃设置窗口背景颜色为白色
glMatrixMode(GL_PROJECTION);〃指定设置投影参数
gluOrtho2D(0.0,200.0,0.0,150.0);〃设置投影参数
voidDisplay(void){
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景色填充窗口
glColor3f(1.0f,0.0f,0.0D;〃设置当前的绘图颜色为红色
//Bresenham算法
glBegin(GL_POINTS);
intx0=10;intyO=20;intxl=90;intyl=90;intcolor=10;
intx,y,dx,dy,e;
dx=xl-x0;dy=yl-yO;
e=-dx;x=x0;y=y0;
while(x<=xl){
glVertex2i(x,y);
x++;
e=e+2*dy;
if(e>0){
y++;
e=e-2*dx;
)
}
glEnd();
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
)
intmain(intargc,char*argv[]){
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的现实模式
glutInitWindowSize(400,300);〃设置窗口的尺寸
glutInilWindowPosition(100,200);//设置窗口的位置
glutCreateWindow("点");〃创建一个名为矩形的窗口
glutDisplayFunc(Display);//设置当前窗口的显示函数
Initial();〃完成窗口的初始化
glutMainLoop();〃启动主GLUT事件处理循环
return0;
实验结果:
・点□0®
实验三圆绘制实验
1.实验目的
2.实验内容
(一)八分法画圆
圆心位于原点的圆有4条对称轴x=O,y=O,y=x,y=-x。若已知圆上任一点(x,y),可以得到其
在圆周上关于四条对称轴的另外7个点(y,x),(-x,y),(-x,-y),(-y,-x),(y,-x),(x,-y)。
(二)中点Bresenham画圆算法
算法步骤如下:
①输入圆的半径R
②计算初始值d=l-R,x=O,y=R。
③绘制点(x,y)及其在八分圆中的另外7个对称点。
④判断d的符号。若d<0,则先将d更新为d+2x+3,再将(x,y)更新为(x+1,y);否则先将
d更新为d+2(x-y)+5,再将(x,y)更新为(x+1,y-1)»
⑤当x〈y时,重复步骤③和④;否则结束。
(三)椭圆的中点Bresenham算法
算法步骤如下:
①输入椭圆的长半轴a和短半轴bo
0计算初始值d=b八2+a八2(-b+0.25),x=0,y=b。
③绘制点(x,y)及其在四分象限上的另外三个对称点。
④判断d的符号。若d<=0,则先将d更新为d+92(2x+3),再将(x,y)更新为(x+l,y);否则先
将d更新为d+b0(2x+3)+a八2(-2y+2),再将(x,y)更新为(x+l,y-l)。
③当bO(x+l)<a"2(y-0.5)时,重复步骤③和④;否则转到步骤⑥。
⑥用上半部分计算的最后点(x,y)来计算下半部分中d的初值
d=bA2(x+0.5)A2+aA2(y-1)A2-aA2bA2
⑦绘制点(x,y)及其在四分象限上的另外三个对称点。
⑧判断d的符号。若d<=0,则先将d更新为d+a2(2x+2)+aA2(-2y+3),再将(x,y)更新为
(x+l,y-l);否则先将d更新为d+a0(-2y+3),再将(x,y)更新为(x,y-l)。
⑨当y>=0时,重复步骤⑦和⑧;否则结束。
3.实验代码及结果
3.1八分法画圆程序代码:
#include<gl/glut.h>
#include<windows.h>
voidInitial(void)
(
glClearColor(1.Of,1.Of,1.Of,1.Of);〃设置窗口背景颜色为白色
gIMatrixMode(GL_PROJECTION);〃指定设置投影参数
gluOrtho2D(0.0,200.0,0.0,150.0);〃设置投影参数
voidCirclePoint(intx,inty,intcolor){
glVertex2i(x+50,y+50);
glVertex2i(y+50,x+50);
glVertex2i(-y+50,x+50);
glVertex2i(-x+50,y+50);
glVertex2i(-x+50,-y+50);
glVertex2i(-y+50,-x+50);
gIVertex2i(y+50,-x+50);
glVertex2i(x+50,-y+50);
)
voidDisplay(void)
(
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景颜色填充窗口
glColor3f(1.0f,0.0f,0.0f);〃设置当前的绘图颜色为红色
glPointSize(lO);
glBegin(GL_POINTS);
CirclePoint(10,20,20);
glEnd();
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
}
intmain(intargc,char*argv[])
(
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的显示模式
glutInitWindowSize(400,300);〃设置窗口的尺寸
glutInitWindowPosition(100,120);〃设置窗口位置
glutCreateWindow("矩形");〃创建一个名为矩形的窗口
glutDisplayFunc(Display);〃设置当前窗口的显示回调函数
Initial();//完成窗口初始化
glutMainLoopO;〃完成窗口GLUT事件处理循环
return0;
)
实验结果:
■矩形□0®
3.2中点Bresenham算法绘制圆代码
#include<gl/glut.h>
#include<windows.h>
voidInitial(void)
(
glClearColor(1.Of,1.Of,1.Of,1.Of);〃设置窗口背景颜色为白色
gIMatrixMode(GL_PROJECTION);〃指定设置投影参数
gluOrtho2D(0.0,200.0,0.0,150.0);〃设置投影参数
voidCirclePoint(intx,inty,intcolor){
glVertex2i(x+50,y+50);
glVertex2i(y+50,x+50);
glVertex2i(-y+50,x+50);
glVertex2i(-x+50,y+50);
g】Vertex2i(-x+50,-y+50);
glVertex2i(-y+50,-x+50);
glVertex2i(y+50,-x+50);
glVertex2i(x+50,-y+50);
)
voidMidBresenhamCircle(intr,intcolor)
(
intx,y,d;
x=0;y=r;d=l-r;
while(x<=y)
(
CirclePoint(x,y,color);
if(d<0)
d+=2*x+3;
else
(
d+=2*(x-y)+5;
y-;
)
x++;
)
)
voidDisplay(void)
(
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景颜色填充窗口
glColor3f(l.Of,O.Of,O.OD;〃设置当前的绘图颜色为红色
glPointSize(3);
glBegin(GL_POINTS);
MidBresenhamCircle(20,10);
glEnd();
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
intmain(intargc,char*argv[])
(
glutlnit(&argctargv);
glut!nitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的显示模式
glulInitWindowSize(400,300);〃设置窗口的尺寸
glut!nitWindowPosition(100,120);//设置窗口位置
glulCreateWindow("矩形");//创建一个名为矩形的窗口
glutDisplayFunc(Display);〃设置当前窗口的显示回调函数
Initial();〃完成窗口初始化
glutMainLoop();〃完成窗口GLUT事件处理循环
return0;
实验结果:
3.3中点Bresenham算法绘制椭圆代码:
#include<gl/glut.h>
#include<windows.h>
voidInitial(void)
(
glClearColor(1.Of,1.Of,1.Of,1.00;〃设置窗口背景颜色为白色
glMatrixMode(GL_PROJECTION);〃指定设置投影参数
gluOrlho2D(0.0,200.0,0.0,150.0);〃设置投影参数
)
voidMidBresenhamEllipse(inta,intb,intcolor)
(
intx,y;
floatdl,d2;
x=0;y=b;
d1=b*b+a*a*(・b+0.25);
glVertex2i(x+50,y+50);glVertex2i(-x+50,-y+50);
glVertex2i(-x+50,y+50);glVertex2i(x+50,-y+50);
while(b*b*(x+l)<a*a*(y-0.5))
if(dl<=0)
dl+=b*b*(2*x+3);
x++;
)
else
(
d1+=b*b*(2*x+3)+a*a*(-2*y+2);
x++;y・・;
)
glVertex2i(x+50,y+50);glVertex2i(-x+50,-y+50);
glVertex2i(-x+50,y+50);gIVertex2i(x+50,-y+50);
)
d2=b*b*(x+0.5)*(x+0.5)+a*a*(y-l)-a*a*b*b;
while(y>0)
(
if(d2<=0)
(
d2+=b*b*(2*x+2)+a*a*(-2*y+3);
x++;y-・;
)
else{
d2+=a*a*(・2*y+3);
y-;
)
glVertex2i(x+50,y+50);glVertex2i(-x+50,-y4-50);
glVertex2i(-x+50,y+50);glVertex2i(x+50,-y+50);
)
)
voidDisplay(void)
(
glClear(GL_COLOR_BUFFER_BIT);〃用当前背景颜色填充窗口
glColor3f(l.Of,O.Of,O.Of);〃设置当前的绘图颜色为红色
glPointSize(3);
glBegin(GL_POINTS);
MidBresenhamEllipse(40,25,10);
glEnd();
glFlush();〃清空OpenGL命令缓冲区,执行OpenGL程序
}
intmain(intargc,char*argv[])
(
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);〃初始化窗口的显示模式
glutInitWindowSize(400,300);〃设置窗口的尺寸
glutInitWindowPosition(100,120);〃设置窗口位置
glutCreateWindow(H矩形,〃创建一个名为矩形的窗口
glutDisplayFunc(Display);〃设置当前窗口的显示回调函数
Initial();〃完成窗口初始化
glutMainLoop();〃完成窗口GLUT事件处理循环
return0;
)
实验结果:
■矩形目回区)
实验四填充算法实验
1.实验目的
掌握用扫描线种子填充法,实现扫描线种子填充算法填充任一多边形区域的程序
2.实验内容
算法步骤如下:
(1)种子像素入栈。
(2)执行如下三步操作:
①栈顶像素出栈。
②填充出栈像素所在扫描线的连续像素段,从出栈的像素开始沿扫描线向左和向右填充,
直到遇到边界像素为止,即每出栈一个像素,就对包含该像素的整个扫描线区间进行填充,
并且记录下此时扫描线区间的x坐标范围[xl,x2]。
③分别检查上、下两条扫描线上位于[xl,x2]坐标区间内的未被填充的连续水平像素段,
将每个连续像素段的最左像素取作种子像素压人栈堆。
(3)检查栈是否为空,若栈非空重复执行步骤(2),若栈为非空则结束。
3.实验代码及结果
代码:
#includengl/glut.hH
#includenmath.h"
#include"stdlib.h**
#include"conio.h',
#include<stack>
typedeffloatColor[3];
structPoint
(
GLintx;
GLinty;
);
std::stack<Point>stk;
voidinit(void)
(
glClearColor(1.0,1.0,1.0,1.0);//Setdisplay-windowcolorwhite.
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,400.0,0.0,400.0);
)
voidsetPixel(GLintx,GLinty);〃种子像素坐标
voidsetPixel(Pointcur_point)
(
glBegin(GL_POINTS);
glVertex2i(cur_point.x,cur_point.y);
glEnd();
glFlush();
}
voidgetPixel(Pointcur_point,Colorc)
(
glReadPixels(cur_point.x,cur_point.y,1,1,GL_RGB,GL_FLOAT,c);
1
boolrgbColorEqual(Colorc1,Colorc2)
(
//cl颜色数据与c2颜色数据,当正负误差不超过0.0001时,返回值为1,否则为0
if((abs(cl[0]-c2[0])>0.001)||(abs(cl[l]-c2[l])>0.001)||(abs(cl[2]-c2[2])>0.001))
return0;
elsereturn1;
intFiIlLineRegion(Pointcur_point,ColoriillColor,ColorborderColorjntdirection)
!
intcount=0;
ColorinteriorColor;
glColor3f(fillColor[0],fillColor[l],fillColor[2]);
getPixel(cur_point,interiorColor);
while(!(rgbColorEqual(interiorColor,borderColor))&&!(rgbColorEqual(interiorColor,fillColor)))
〃这个判断保证读取的像素的颜色数据与边界颜色还有填充颜色数据在数值上相差
较大
〃即当正读取像素不是多边形边界,且也没有被填充,则执行以下花括号内的操作
(
setPixel(cur_poinl);//setcolotofpixeltofillColor.〃为坐标为(x,y)的像素上色
if(direction==0)
cur_point.x++;
else
cur_point.x—;
getPixel(cur_point,interiorColor);
count++;
)
returncount;
)
intIsPixelValid(Pointcur_point,ColorfillColor,Colorbordei*Color)
(
ColorinteriorColor;
getPixel(cur_point,interiorColor);
if(!(rgbColorEqual(interiorColor,borderColor))&&!(rgbColorEqual(interiorColor,fillColor)))
return1;
else
return0;
1
voidSearchLineNewSeed(intxLeft,intxRight,inty,ColorfillColor,ColorborderColor)〃在种子像
素所在扫描线上一条或下一条是扫描线寻找新种子像素
(
intxt=xLeft;
intseed_left=-1;
Pointseed_point;
Pointtemp_point;
while(xt<=xRight)
(
seed_left=-l;
temp_point.x=xt;
temp_point.y=y;
while(xt<=xRight)//findthefirstvalidpoint
(
if(IsPixelValid(temp_point,fillColor,borderColor))
(
seed_left=temp_point.x;
break;
)
else
(
xt++;
temp_point.x=xt;
}
while(xt<=xRight)//findthenextinvalidpoint
(
if(IsPixelValid(temp_point,fillColor,borderColor))
(
xt++;
temp_point.x=xt;
)
else
(
break;
)
)
if(seed_left!=-l)
(
seed_point.x=seed_left;
seed_point.y=y;
stk.push(seed_point);
)
)
)
)
voidscanLine(Pointcur_point,ColorfillColor,ColorborderColor)
(
intcount=0;
intright,left;
Pointtemp_point;
while(!stk.empty())
(
Pointseed_point=stk.top();
stk.popO;〃种子像素出栈
count=FillLineRegion(seed_point,fiHColor,borderColor,。);//填充种子像素所在的扫描
线右边
right=seed_point.x+count-1;
temp_point.x=seed_point.x-1;
temp_point.y=seed_point.y;
count=FillLineRegion(temp_point,fiHColor,borderColor,1);〃填充种子像素所在扫描线
左边
left=seed_point.x-count;
SearchLineNewSeed(left,right,seed_point.y・l,fllColor,borderColor);〃在种子•像素所在
扫描线上方一条扫描线寻找新种子像素
SearchLineNewSeed(left,right,seed_point.y+1,fillColor,borderColor);〃在种子像素所在
扫描线寻找新种子像素
)
return;
)
voidmyDraw(void)
(
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINE_LOOP);
glVertex2f(20.0f,80.0f);
glVertex2f(30.0f,95.0f);
glVertex2f(50.0f,95.0f);
glVertex2f(60.0f,80.01);
glVertex2f(70.0f,95.0f);
glVertex2f(90.0f,95.0f);
glVertex2f(100.0f,80.0f);
glVertex2f(60.0f,30.00;
glEnd();
//int乂=60,丫=60;//种子像素坐标为(60,60)
structPointseed_point={65,65);
ColorfillColonborderColor;
fillColor[0]=1.0;fillColor[1]=0.0;fillColor[2]=0.0;
borderColor[0]=0.0;borderColor[l]=0.0;borderColor[2]=0.0;//扫描的边界的颜色要与上面的
绘图颜色一致
stk.push(seed_point);〃种子像素入栈
scanLine(seed_point,fillColor,borderColor);
glFlush();
)
voidmain(intargc,char*argv[]){
glutlnit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,100);
glutCreateWindow(“边界”);
init();
giutDisplayFunc(myDraw);
glutMainLoopO;
实验五裁剪算法实验
1.实验目的
掌握用Cohen-Sutherland法裁减直线,掌握用Sutherland-Hodgman算法裁剪多边形的编
程方法,并编程实现
2.实验内容
Cohen-Sutherland直线段裁剪算法的步骤如下:
①输入直线段的两端点坐标Pl(xl,yl),P2(x2,y2),及窗口的4条边界坐标ywt.,ywb,ywi,ywr«
②对Pl,P2进行编码,点Pl的编码为codel,点P2的编码为code2。
③若codel|code2=0,对直线段P1P2”简取”之,转⑥;否则,若codel&code2!=0,对
直线段“简弃”之,转⑦;当上述两条均不满足时,进行步骤④。
④确保P1在窗户外部。若P1在窗口内,则交换P1和P2的坐标值和编码。
⑤根据P1编码从低位喀什找编码值为1的地方,从而确定P1的窗口外的哪一侧,然
后求出直线段与相应窗口边界的交点S,并用交点S的坐标值替换P1的坐标值,即在交点
S处把线段一分为二,并去掉P1S这一段。考虑到P1是窗口外的一点,因此可以去掉P1S。
转②。
⑥用直线扫描转换算法画出当前的直线段P1P2。
⑦算法结束。
Sutherland-Hodgman算法:
基本思想:将多边形的边界作为一个整体,每次用窗口的一条边界对要裁剪的多边形进
行裁剪,体现“分而治之”的思想。每次裁剪时把落在窗口外部区域的图形去掉,只保留落
在窗口内部区域的图形,并把它作为下一次裁剪的多边形。依次用窗口的4条边界对多边形
进行裁剪,则原始多边形即被裁剪完毕。
3.实验代码及结果
Cohen-Sutherland直线段裁剪算法代码:
ttinclude“stdafx.h"
#defineLEFT_EDGE1
#defineRIGHT_EDGE2
#defineBOTTOM_EDGE4
#defineTOP_EDGE8
floatymin=100;
intymax=300;
intxmin=100;
intxmax=300;
typedefstructLinea
(
intxO;
intyO;
intxl;
intyl;
}Linea;
Linea11={11.xO=450,11.yO=0,11.xl=0,11.yl=450};
Linea12={12.xO=450,12.yO=200,12.xl=0,12.yl=200};
Linea13={13.xO=200,13.yO=0,13.xl=200,13.yl=450};
voidLineGL(Linea&li)〃没有&,引用改变li的值
(
glBegin(GL_LINES);
glColor3f(1.Of,0.Of,0.Of);glVertex2f(li.xO,li.yO);
glColor3f(0.Of,1.Of,0.Of);glVertex2f(li.xl,li.yl);〃虽
然两个点的颜色设置不同,但是最终线段颜色是绿色
glEnd();〃因为
glShadeModel(GL_FLAT)设置为最后一个顶点的颜色
)〃决定整个图元的
颜色。
intCompCode(intx,inty)
(
intcode=0x00;〃此处是二进制
if(y<ymin)
code=code|4;
if(y>ymax)
code=code|8;
if(x>xmax)
code=code|2;
if(x<xmin)
code=code|1;
returncode;
)
intcohensutherlandlineclip(Linea&ii)
intaccept=0,done=0;
floatx=0,y=0;
inttotal=0,flag=0;〃total与flag是标志
intcodeO,codel,codeout;
codeO=CompCode(li.xO,li.yO);
//printf(zzcode0=%d\n,z,codeO);
codel=CompCode(li.xl,li.yl);
〃printf("codel二%d\n〃,codel);
do{
if(!(codeO|codel))〃code0&codel=0000B,线段完全在窗口内部,
全部显示
(
accept=1;
done=1;
)
elseif(codeO&codel)
(
done=1;flag=1;
)
else
(
if(codeO!=0)
codeout=codeO;
else
codeout=codel;
if(codeout&LEFT.EDGE)
{
y=li.yO+(li.yl-li.y0)*(xmin-li.xO)/(li.xl-li.xO);
x=(float)xmin;
)
elseif(codeout&RIGHT_EDGE)
(
y=li.yO+(li.yl-li.y0)*(xmax-li.xO)/(li.xl-li.xO);
x=(float)xmax;
)
elseif(codeout&BOTTOMEDGE)
(
x=li.xO+(li.xl-li.x0)*(ymin-li.yO)/(li.yl-li.yO);
y=(float)ymin;
)
elseif(codeout&TOP_EDGE)
{
x=li.xO+(li.xl-li.x0)*(ymax-li.yO)/(li.yl-li.yO);
y二(float)ymax;
)
if(codeout二二codeO)
(
li.xO=x;li.yO=y;
codeO=CompCode(li.xO,li.yO);
)
else
(
li.xl=x;li.yl=y;
codel=CompCode(li.xl,li.yl);
)
total++;
if(total>3)〃total>3,执行两次后total又加一
(
done=1;flag=1;
)
)
}while(!done);
if(accept)〃线段位于窗口内或者线段剪裁过accepts;
(
LineGL(li);
)
else
(
li.xO=0;li.yO=0;li.xl=0;li.yl=0;
LineGL(li);
)
returnaccept;
)
voidmyDisplay()
(
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f,0.Of,0.Of);
glBegin(GL_LINE_LOOP);
glVertex2f(100,100);
glVertex2f(300,100);
glVertex2f(300,300);
glVertex2f(100,300);
glEndO;
LineGL(ll);
LineGL(12);
LineGL(13);
glFlush();
)
voidInit()
glClearColor(0.0,0.0,0.0,0.0);
glShadeModel(GL_FLAT);
printf(/zPresskey'c'toClip!\nPresskey'r'toRestore!\n〃);
)
voidReshape(intw,inth)
(
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GLPROJECTION);
glLoadldentity();
glu0rtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);
〃printf(〃######Reshape\n〃);
)
voidkeyboard(unsignedcharkey,intx,inty)
(
switch(key)
(
case'c:
cohensutherlandlinec1ip(11);
cohensutherlandlineclip(12);
cohensutherlandlineclip(13);
glutPostRedisplay();
break;
case'r:
ILxO=450;11.yO=0;11.xl=0;11.yl=450;
12.xO=450;12.yO=200;12.xl=0;12.yl=200;
13.xO=200;13.yO=0;13.xl=200;13.yl=450;
Init();
glutPostRedisplay();
break;
case'x':
exit(0);
break;
default:
break;
}
}
intmain(intargc,char*argv[])
(
glutlnit(ftargc,argv);
glutInitDisplayMode(GLUTRGB|GLUT_SINGLE);
glutlnitWindowPosition(100,100);
glutlnitWindowSize(640,480);
glutCreateWindow(,/Cohen-Sutherland,/);
Init();
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutKeyboardFunc(&keyboard);〃按下键盘后会调用该函数,键和鼠标点击位置作
为变量传给keyboard函数
glutMainLoopO;
return0;
)
实验结果:
■'Cohen-Sutherland
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论