您好,欢迎来到测品娱乐。
搜索
您的当前位置:首页贵州大学 计算机图形学

贵州大学 计算机图形学

来源:测品娱乐
《 软件工程 》专业

试卷答题

课程名称:计算机图形学

姓名 年级:2011级 成绩

1、编写一程序实现,将中点画线算法推广以便能画出任意斜率的直线段。(10分)

答:

程序流程图:

开始输入坐标点|斜率|>1斜率为正yes斜率为正画线处理画线处理画线处理画线处理结束

核心函数:

void Midpoint(int x0,int y0,int x1,int y1)//画直线 {

int a,b,d1,d2,d,x,y; float dx=x1-x0; float dy=y1-y0; a=y0-y1,b=x1-x0;

if(fabsf(dx)>(fabsf(dy)))//判断斜率是否大于一 {

//斜率小于一 d=2*a+b;

d1=2*a,d2=2*a+2*b; x=x0,y=y0;

glBegin(GL_POINTS); glVertex3f(x,y,0);

glEnd();

if(y0<=yy1)//斜率为正 {

while(xif(d<0)//d<0时取右上方的 {

x++,y++,d+=d2; }

else{x++,d+=d1;}//否则取右方的点 glBegin(GL_POINTS); glVertex3f(x,y,0); glEnd(); } } else

{//斜率小于0时 d=2*a-b; d2=2*a-2*b; while(xif(d>=0){x++,y--,d+=d2;}//取右下方的点 else{x++,d+=d1;}//去右方的点 glBegin(GL_POINTS); glVertex3f(x,y,0); glEnd(); } } } else

{//斜率大于一 d=2*b+a;

d1=2*b,d2=2*a+2*b; x=x0,y=y0;

glBegin(GL_POINTS); glVertex3f(x,y,0); glEnd(); if(y0<=yy1) {

while(yif(d>=0){x++,y++,d+=d2;}//取右上方点 else{y++,d+=d1;}//取右方点 glBegin(GL_POINTS);

glVertex3f(x,y,0); glEnd(); } } else {

//斜率为负 d=a-2*b;

d1=-2*b,d2=2*a-2*b; while(y>y1) {

if(d<0){x++,y--,d+=d2;}//取右下方的点 else{y--,d+=d1;}//取右方的点 glBegin(GL_POINTS); glVertex3f(x,y,0); glEnd(); } } } }

流程图:

运行结果:

3、假设圆的圆心不在原点,试编写一个算法对整个圆进行扫描转换,需做出控制界面。(15分)

答:程序流程图

开始输入圆的圆心和半径初始化dx>yd>0d=d+4*(x-y)+10y--p=p+4*x+6x++输出xy结束 核心代码:

void drawcircle(float xc,float yc,float radius) {

xc=xc; yc=yc;

xc=int(xc+0.5); yc=int(yc+0.5);

cout<int x,y,p;//(x,y)为要绘制的点 p为 x=0;

radius=y=int(radius+0.5); p=3-2*radius;

while(xplot_circle_points(xc,yc,x,y);//调用绘制点的函数

if(p<0)//如果p<0,说明正右方的点离圆上的点近,选取正右方的点

}

p=p+4*x+6;//选取正右方的点,p的增量为4*x+6

else //如果p>=0,说明右下方的点离圆上的点近,选取右下方的点 {

p=p+4*(x-y)+10;////选取右下方的点,p的增量为4*(x-y)+10 y-=1;//选取右下方的点时,要将y-- }

x+=1;//无论选取哪一个点,x都要自增1

}

if(x==y)//x>=y跳出循环

plot_circle_points(xc,yc,x,y);

运行结果:

4、编写一程序实现线段裁剪的中点分割算法,程序需演示逼近的步骤,并做出控制界面。(15分)

答:

流程图:

开始输入坐标坐标编码关键代码:

void CS_LineClip(float x1,float y1,float x2,float y2) { float xm=0,ym=0; int code1,code2,code; //对两个顶点进行编码 code1=encode(x1,y1); code2=encode(x2,y2); float x,y,xx,yy;//临时存储两点坐标

否结束code1!=0||code2!=0是int(code1&code2)!=0否是确定要裁剪端点code直线在窗体外处理code在窗体左侧是窗体左侧处理否code在窗体有侧是窗体右侧处理code在窗体下侧窗体上侧处理否是窗体下侧处理否 环

while(code1!=0||code2!=0) { if(int(code1&code2)!=0)//如果code1&code2)!=0则直线在裁剪窗体外面 { Draw_windows(); return; } if(code1!=0) //判断是哪个端点在窗体外 { code=code1;//对code1端点赋值给code准备裁剪 x=x1; y=y1; xx=x2; yy=y2; } else { code=code2;//对code2端点赋值给code准备裁剪 x=x2; y=y2; xx=x1; yy=y1; } if(int(LEFT&code)!=0)//要裁剪的端点才窗体左侧 { do { xm=(x+xx)/2,ym=(y+yy)/2;//取中点 if(xm>window.XL)//判断中点是否在窗体可见侧 { //中点赋值给p2点 xx=xm; yy=ym; } else { //中点赋值给p1点 x=xm; y=ym; } draw_point(xm,ym); }while(fabsf(x-xx)>0.5||fabsf(y-yy)>0.5);//两点间距离小于某个常数退出循

}

else if(int(RIGHT&code)!=0)//要裁剪的端点才窗体右侧 { do { xm=(x+xx)/2,ym=(y+yy)/2;//取中点

if(xm0.5||fabsf(y-yy)>0.5);//两点间距离小于某个常数退出循 }

else if(int(BOTTOM&code)!=0) { do { xm=(x+xx)/2,ym=(y+yy)/2;//取中点 if(ym>window.YB)//判断中点是否在窗体可见侧 {//中点赋值给p2点 xx=xm; yy=ym; } else {//中点赋值给p1点 x=xm; y=ym; } draw_point(xm,ym); }while(fabs(x-xx)>1.0||fabs(y-yy)>1.0);//两点间距离小于某个常数退出循 }

else if(int(TOP&code)!=0) {

do { xm=(x+xx)/2,ym=(y+yy)/2;//取中点 if(ym1.0||fabs(y-yy)>1.0);//两点间距离小于某个常数退出循环

} if(code==code1) { x1=xm;y1=ym;code1=encode(int(xm+0.5),int(ym+0.5)); } else { x2=xm;y2=ym;code2=encode(int(xm+0.5),int(ym+0.5)); } Draw_windows(); Draw_Line(x1,y1,x2,y2); } }

运行结果:

5、编写一程序实现多边形扫描转换算法中的扫描线填充算法,需做出控制界面。(15分) 流程图:

输入顶点建立新边表建立活性链表i=y值最小顶点i关键代码: void PolyScan() {

int max_y=0,MinY=1024; int i; for(i=0;imax_y) max_y=point[i].y; if(point[i].ynext=NULL; NET *pNET[800]; setNET(pNET,max_y); for(i=MinY;i<=max_y;i++)//从miny到maxy到y进行扫描 { NET *p0=pAET->next; while(p0)//每次将活性边表中所有节点的x值增加dx { p0->x=p0->x + p0->dx; p0=p0->next; } AET *sq=pAET; p0=pAET->next; sq->next=NULL; while(p0)//对活性边表按x值从小到大排序 { while(sq->next && p0->x >= sq->next->x)//p0中的第一个节点比sp中的当前节点大,sp指针后移 sq=sq->next; //将p指向的节点添加到sp中 NET *s=p0->next; p0->next=sq->next; sq->next=p0; p0=s; sq=pAET; } AET *q=pAET; p0=q->next; while(p0)//遍历活性边表

}

{ if(p0->ymax==i)//如果谋边扫描结束,就把他从活性边表中删除 { q->next=p0->next; delete p0; p0=q->next; } else//否则指针后移判断下一条边 { q=q->next; p0=q->next; } }

p0=pNET[i]->next; q=pAET;

while(p0)//将新边按大小顺序添加到活性边表中 { while(q->next && p0->x >= q->next->x) q=q->next; NET *s=p0->next; p0->next=q->next; q->next=p0; p0=s; q=pAET; }

p0=pAET->next; //配对输出结果 while(p0 && p0->next) { for(float j=p0->x;j<=p0->next->x;j++) { glBegin(GL_POINTS); glVertex3f(j,i,0); glEnd(); glFlush(); } p0=p0->next->next; } }

glEnd(); glFlush();

运行结果:

6、编写程序实现,设有三角形ABC,其中三个顶点为A(1,3), B(5,10), C(10,12)求对于直线y=x+1的对称变换后的A’B’C’,并显示。(10分)

答:程序流程图

平移直线截距的距离旋转直线斜率的角度对称反旋转反平移

关键代码:

void getXY(float x,float y)//计算操作后顶点 {

X1=a[0][0]*x+a[0][1]*y+a[0][2]; Y1=a[1][0]*x+a[1][1]*y+a[1][2]; }

void setABC()//得到操作后的三角形 {

getXY(xa,ya); xa=X1;ya=Y1; getXY(xb,yb); xb=X1;yb=Y1; getXY(xc,yc); xc=X1;yc=Y1; }

void mouse(int button, int state, int x, int y) {

if(button == GLUT_RIGHT_BUTTON) { if(state == GLUT_DOWN) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); xa=10,ya=30,xb=50,yb=100,xc=100,yc=120; display(); left_click_count=0; right_click_count=0; }

}

else if(button == GLUT_LEFT_BUTTON) { if(state == GLUT_DOWN) { switch(left_click_count) { case 0:///平移 a[0][2]=0; a[1][2]=-10; setABC();// glColor3f( 1.0, 0.0, 1.0); seta(); draw_Triangle(); left_click_count++; break; case 1://旋转 a[0][0]=0.707; a[0][1]=0.707; a[1][0]=-0.707; a[1][1]=0.707; setABC(); glColor3f( 0.0, 0.0, 1.0); seta(); draw_Triangle(); left_click_count++; break; case 2: //对称 a[0][0]=1; a[1][1]=-1; setABC(); xc=X1;yc=Y1; glColor3f( 0.0, 1.0, 1.0); seta(); draw_Triangle(); left_click_count++; break; case 3: //旋转 a[0][0]=0.707; a[0][1]=-0.707; a[1][0]=0.707; a[1][1]=0.707;

setABC(); glColor3f( 0.0, 0.0, 1.0); seta(); draw_Triangle(); left_click_count++; break; case 4: //平移 a[0][2]=0; a[1][2]=10; setABC(); glColor3f( 1.0, 0.0, 1.0); seta(); draw_Triangle(); left_click_count++; default: break; } } } }

运行结果:

7、在OPENGL下,编写一程序,采用顶点数组数据结构绘制立方体线框,用不同颜色绘制边线, 并让立方体绕对角线旋转45度. (20分) 答:流程图:

平移到原点旋转使得旋转轴与坐标轴重合旋转45反旋转反平移

关键代码:

void myDisplay6(void) {

glEnable(GL_DEPTH_TEST);//开启更新深度缓冲区的功能

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清空

glMatrixMode(GL_PROJECTION);//glMatrixMode设置当前矩阵模式为投影矩阵

glLoadIdentity();//将当前点移到了屏幕中心

gluPerspective(75,1,1,400);//指定了观察的视景体

glMatrixMode(GL_MODELVIEW);//设置当前矩阵模式为模型视景矩阵 glLoadIdentity();

gluLookAt(3,3,3,1,1,1,0,0,1);//视点矩阵 draw_Coordinate();//画坐标系

glTranslatef(a[0][0],a[0][1],a[0][2]);//平移 glRotatef(45,0.0f,0.0f,1.0f);//旋转 glRotatef(54.74,0.0f,1.0f,0.0f);//旋转 glRotatef(45,0.0f,0.0f,1.0f);//旋转

glRotatef(54.74,0.0f,-1.0f,0.0f);//旋转 glRotatef(45,0.0f,0.0f,-1.0f);//旋转

glTranslatef(-a[0][0],-a[0][1],-a[0][2]);//平移 draw_cube();//画立方体 glutSwapBuffers(); }

运行结果:

8、在OPENGL下,已知单位正立方体,试编写一程序实现输出该形体的正平行投影和一点透视投影图。(15分) 答: 核心代码

void display0() {

glEnable(GL_DEPTH_TEST);

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity();

glFrustum(-2.5,2.5,-2.5,2.5,1.5,40); glMatrixMode(GL_MODELVIEW); glLoadIdentity();

gluLookAt(1.5,1.5,3.0,1.2,1.2,-4.5,0,0,1); draw_Coordinate(); draw_cube();

glutSwapBuffers(); }

void display() {

glEnable(GL_DEPTH_TEST);

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity();

glOrtho(-4.0,4.0,-4.0,4.0,1,1200); glMatrixMode(GL_MODELVIEW); glLoadIdentity();

gluLookAt(8,8,8,0,0,0,1,0,0);

draw_Coordinate();

draw_cube();

glutSwapBuffers(); }

运行结果:

9在OPENGL下,使用Grouraud明暗处理方法生成在一个球面的真实图形。(15分)

核心代码:

void init(void) {

GLfloat mat_specular[] = {0.0, 1.0, 0.0, 1.0}; GLfloat mat_shininess[] = {100.0};

GLfloat light_position[] = {1.0, 1.0f, 1.0, 0.0}; GLfloat white_light[] = {0.0, 1.0, 0.0, 1.0};

GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};// 定义光模型参数 glClearColor(0.0, 0.0, 0.0, 0.0);

glShadeModel(GL_SMOOTH);//光滑明暗模式

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);//光线照射到该材质上,经过镜面反射后形成的光线强度(颜色)

glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);//镜面反射指数 //用定义好的光源属性给指定光源GL_LIGHT0进行设置

glLightfv(GL_LIGHT0, GL_POSITION, light_position);

glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);//设置漫射光成分 glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);//设置镜面光成分 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);// 定义光模型

glEnable(GL_LIGHTING);//启用灯源 glEnable(GL_LIGHT0);//启用0号光源

glEnable(GL_DEPTH_TEST);//启用深度测试,根据坐标的远近自动隐藏被遮住的图形(材料) }

运行结果:

11、在OPENGL下,使用下列函数生成的棋盘纹理映射到一个球面上。(15分)

0,g(u,v)1,u*8v*8为奇数

u*8v*8为偶数关键代码:

void makeCheckImages(void)//生成纹理 {

int i, j, c;

for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i&0x8)==0)^((j&0x8)==0)))*255; checkImage[i][j][0] = (GLubyte) c; checkImage[i][j][1] = (GLubyte) c; checkImage[i][j][2] = (GLubyte) c; checkImage[i][j][3] = (GLubyte) 255; } } }

int InitGL(GLvoid) {

makeCheckImages();

glGenTextures(1, &texName); //根据纹理参数返回n个纹理索引

glBindTexture(GL_TEXTURE_2D, texName);//将纹理与纹理处理目标绑定 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);//S方向上的贴图模式,将纹理坐标在0.0,1.0的范围之内.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);//T方向上的贴图模式,将纹理坐标在0.0,1.0的范围之内. glTexParameteri(GL_TEXTURE_2D,

GL_TEXTURE_MAG_FILTER,GL_NEAREST);// 放大过滤,使用距离当前渲染像素中心最近的4个纹素加权平均值

glTexParameteri(GL_TEXTURE_2D,

GL_TEXTURE_MIN_FILTER,GL_NEAREST);//缩小过滤,使用距离当前渲染像素中心最近的4个纹素加权平均值

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage);//根据指定的参数,生成一个2D纹理 glEnable(GL_TEXTURE_2D);//// 启用二维纹理

GLUquadricObj *quadratic=gluNewQuadric(); //创建二次曲面对象 gluQuadricTexture(quadratic, GL_TRUE);//启用该二次曲面的纹理 gluSphere(quadratic,1.0, 50, 50);//创建一个球面对象

return true;

}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- cepb.cn 版权所有 湘ICP备2022005869号-7

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务