实验四 自由曲线的绘制(OpenGL版)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
南昌大学实验报告四
学生姓名:张鑫维学号:6100407234 专业班级:计算机072 实验类型:□验证□综合■设计□创新实验日期:2010-12-3 实验成绩:
自由曲线的绘制(OpenGL版)
1. 实验目的
1、掌握Bezier曲线的定义生成算法、离散生成算法;
2、掌握B样条曲线的定义生成算法。
2. 实验内容
假设窗口的宽高分别是600 , 600 个像素单位,定义的裁剪窗口由函数
gluOrtho2D(-50.0,50.0,-50.0,50.0)决定。
曲线控制点数据:
1、已知空间四点P0(-40.0,-40.0,0.0)、P1(-10.0,200.0,0.0)、P2(10.0,-200.0,0.0)、P3(40.0,40.0,0.0),根据Bezier曲线的定义编程绘制曲线。
2、已知空间四点P0(-40.0,-40.0,0.0)、P1(-10.0,200.0,0.0)、P2(10.0,-200.0,0.0)、P3(40.0,40.0,0.0),根据Bezier曲线的离散生成算法绘制曲线。
3、已知空间四点P0(-40.0,-40.0,0.0)、P1(-10.0,200.0,0.0)、P2(10.0,-200.0,0.0)、P3(40.0,40.0,0.0),根据B样条曲线的定义绘制曲线。
3.实验指导
由于几何外形设计的要求越来越高,传统的曲线曲面表示方法,已不能满足用户的需求。1962 年,法国雷诺汽车公司的P.E.Bezier 构造了一种以逼近为基础的参数曲线和曲面的设计方法,并用这种方法完成了一种称为UNISURF 的曲线和曲面设计系统,1972年,该系统被投入了应用。Bezier方法将函数逼近同几何表示结合起来,使得设计师在计算机上就象使用作图工具一样得心应手。
4. 实验结果
按照定义画出的Bezier曲线(101个点) 按照de Casteljau算法画出的Bezier曲线(1001个点)
三次Bezier曲线的自由生成确定三次B样条曲线的控制点
所有控制点确定后画出B样条曲线拖拽第四个控制点,调整曲线
5. 实验心得
这个实验考查的是自由曲线的绘制,要求熟练掌握好Bezier曲线和B样条曲线的原理和编程。我首先按照实验要求,完成了对已知四个控制点的Bezier曲线生成,采用了定义和de Casteljau两种算法编程。在掌握好Bezier曲线的两种算法后,我尝试着扩展实验,利用鼠标响应函数mouse(),选取用户左击鼠标确定的控制点,在取得了四个控制点后,打印出四个控制点、控制多边形线段以及生成的Bezier曲线。这样可以通过鼠标点击,自由绘制三次Bezier曲线了。
B样条曲线的关键是deBoor算法。我之前按照书上的编写了程序,结果四个控制点只打出一个点,而不见曲线。后来老师说书上的有问题,我又参考了他给的资料后才正确完成了程序。后来,我又进一步完善了程序。先是让程序能从鼠标接收任意多个控制点,按照控制点的个数动态算出对应的开放节点矢量,接着调用deBoor算法,算出每段曲线上的点的坐标。随后,我又将橡皮筋技术应用到了该程序,让程序在绘制了曲线后能通过鼠标左键的拖拽控制点实现B样条曲线的调整,进一步提高了程序的可用性。
通过这个实验,我不仅深入了解了自由曲线绘制的算法,还熟练了OpenGL编程。特别是
鼠标响应函数的处理,让我收获颇大,对交互式的OpenGL编程能力有了很大的提高。
6. 程序源码
float deboor(int degree,float coeff[],float knot[],float u,int i) { //deboor算法
int k,j;
float t1,t2,coeffa[30];
for(j=i-degree; j<=i; j++)
coeffa[j]=coeff[j];
for(k=1; k<=degree; k++){
for(j=i; j>=i-degree+k; j--){ t1=(float)(knot[j+degree-k+1]-u)/ (knot[j+degree-k+1]-knot[j]);
t2=1.0-t1;
coeffa[j]=t1*coeffa[j-1]+t2*coeff a[j];}}
return coeffa[i];}
void bspToPoints(int degree,int L,float coeff[],float knot[],int dense,float points[],int &pointNum)
{ //控制点生成曲线点坐标
int i,j;
float u;
pointNum=0;
for(i=degree; i<=L+degree;i++){
if(knot[i+1]>knot[i]){
for(j=0; j points[pointNum++]=deboor(degree, coeff,knot,u,i);}}}} void calKnot(float knot[]) { //计算节点矢量 int i,j,l; for(i=0; i<3; i++) knot[i]=0.0; for(j=0; j<=controlNum-3; j++,i++) knot[i]=j; for(l=0; l<3; l++,i++) knot[i]=j-1; } bool isDot(int x,int y) { //判断是否为控制点 int i; y=600.0-y; for(i=0; i if((x-Vertex_X[i])*(x-Vertex_X[i] )+(y-Vertex_Y[i])*(y-Vertex_Y[i])<=25 ){controlIndex=i; return true;} return false;} void displayImage(void) { //画出包含控制点的B样条曲线 int i; glClear(GL_COLOR_BUFFER_BIT); glPointSize(1.0); glColor3f(1.0, 0.0, 0.0); glEnable (GL_LINE_STIPPLE); glLineStipple (1, 0xF0F0); glBegin(GL_LINE_STRIP); for(i=0; i glEnd(); glDisable(GL_LINE_STIPPLE); glColor3f(1.0, 1.0, 1.0); glBegin(GL_POINTS); for(i=0; i glPointSize(5.0); glColor3f (1.0, 1.0, 0.0); glBegin(GL_POINTS); for(i=0; i glVertex2f(Vertex_X[i],Vertex_Y[i ]); glEnd();} void displayInit(void) { //初始状态下的绘制函数 glClear(GL_COLOR_BUFFER_BIT); glFlush();} void displayOnDraw(void) { //生成曲线过程中的绘制函数 int i; glClear(GL_COLOR_BUFFER_BIT); glPointSize(1.0);