隐藏面消除
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
隐藏面消除
✧实验目的
通过实现隐藏面算法,深入理解消隐算法的原理。
进一步熟悉OpenGL编程。
✧算法所采用的数据结构
本程序采用活化边表的扫描线Z缓冲器算法,并实现了交互界面的测试。
采用C/C++ 、OpenGL编写程序
✧主要的函数功能说明
void insertEdge(Edge *list,Edge *edge)
//在已经建立的边表中按照x坐标递增的顺序插入一条新边
void getEdgeList(int count,point *pts,Edge *edges[],int a)
//根据已给出的顶点得到边表
void sort(Edge *list,Edge *edge)
//对活化边表中的边进行排序
void getActiveList(int scan,Edge *active,Edge *edges[])
//构造活化边表
void scanfill()
//扫描填充算法的实现
✧测试用例
本程序实现一个交互输入的界面,下面是用于算法检验的数据:
2
9
90 300 110
330 380 -210
390 200 -90
180 120 200
90 300 110
120 280 100
350 220 -70
200 130 170
120 280 100
1.0 1.0 1.0 -500
4
230 250 -80
480 480 -560
430 150 -180
300 80 20
1.0 1.0 1.0 -400
得到的运行界面如下图所示:
代码附录
#include
#include
#include
#include
#include
#define SCAN_NUM 500
typedef struct Edge //边Y桶中的边结构
{
int yUpper; //边的最大y值
float xInt,dx; //边的最低点的x值,之所以是最低点,是因为本程序是从下往上扫描的
int E_mark;
float z,dzx,dzy;
struct Edge *next; //指向下一条边节点的指针
}Edge;
typedef struct point //定义一个点的结构体
{
int x;
int y;
float z;
}point;
extern point **points=NULL; //存放多个多边形的顶点信息
extern float **as=NULL; //存放多边形所在平面的方程的四个系数
extern int *counts=NULL; //存放各个多边形的顶点个数
extern int num=0; //记录多边形个数
void DrawPoint(int x, int y)//画点函数
{
::glBegin(GL_POINTS);
::glVertex2d(x, y);
::glEnd();
}
int nexty(int k,int count,point *pts)//当前测试点的下一个点的纵坐标,其方向为顺时针
{
int j;
if((k+1)>(count-1))
j=0;
else j=k+1;
while(pts[k].y==pts[j].y)
{
if((j+1)>(count-1))
j=0;
else
j++;
}
return pts[j].y;
}
void insertEdge(Edge *list,Edge *edge)//往已知边表中插入一条边,当然得按顺序插入
{
Edge *p,*q=list;
p=q->next;//p指向y=lower.y的第一条边
while(p!=NULL)
{
if(edge->xInt
else
{
q=p; //p、q后移
p=p->next;
}
}
edge->next=q->next;//插入edge边
q->next=edge;
}
void makeEdges(point lower,point upper,int yComp,Edge *edges[],int &a)
{
Edge *edge=new Edge;
edge->dx=(float)(upper.x-lower.x)/(upper.y-lower.y);//存储当前边(lower、upper)信息
edge->xInt=(float)lower.x;//边的x坐标
if(upper.y edge->yUpper=upper.y-1;//如果upper点非极值点 else //如果为极值点 edge->yUpper=upper.y; edge->E_mark=a; edge->z=lower.z; edge->dzx=-as[a][0]/as[a][2]; edge->dzy=-as[a][1]/as[a][2]; insertEdge(edges[lower.y],edge);//将此边添加至有序边表 } void getEdgeList(int count,point *pts,Edge *edges[],int a) { point v1,v2; //定义两个中间变量 int i,yPrev=pts[count-2].y;//定义yPrev为当前点的前一点纵坐标坐标 v1.x=pts[count-1].x; v1.y=pts[count-1].y; v1.z=pts[count-1].z; for(i=0;i { v2=pts[i];//v2记录当前测试点 if(v1.y!=v2.y)//如果直线非水平的 { if(v1.y