利用OpenGL进行CAD三维图形消隐处理

发布时间:2011-04-09 12:27:30   来源:文档文库   
字号:

利用OpenGL进行CAD三维图形消隐处理

  三维图形消隐算法已比较成熟,但要普通编程人员对复杂三维图形进行消隐

编程,却不是容易的事。OpenGL图形库中提供了消隐处理函数,但消隐却不知因

何原因而质量不高,如消隐时直线断断续续。为此笔者进行了一定改进和精细消

处理,下面介绍两种办法。

  一、一般消隐

  这种方法为首先设置消隐使能,初始化深度缓存,设置消隐比较,直接进行

绘图即可。但此种结果是直线断断续续,时有时无,效果差。改进只需将直线线

宽加粗,若需多边形边框一同绘出,则要GL_LINES方式将边框线段重绘。具体方

法如下:

  glEnable(GL_DEPTH_TEST);//设置消隐使能

  glClearDepth(1.0);//设置初始化深度缓存值

  glClear(GL_DEPTH_BUFFER_BIT);//深度缓存消除

  gldephFunc(GL_LEQUAL);//设置消隐比较

  glLineWidth(2.0);//直线线宽应比多连形线宽多一倍

  下述设置后,即可开始绘图。消隐能正常显示,只是直线线宽均比多边形宽

一倍,图形变得粗糙,效果十理想。

  二、精细消隐处理

  精细消隐设计分三步:

  1、首先在消隐方式下对所有多边形面进行绘图,其目的是在深度缓存中写入

消隐后的多边形面的Z值,并比较后再写入深度缓存,即大大简化了多边形面的Z缓存计算。

  2、将直线及多边形边框直线由目标坐标转换成窗口坐标下的值,并将线段离

散化为窗口坐标下的象素点,再比较象素点的窗口坐标下Z值与深度缓存值,从而

将隐藏直线段消除,记录显示线段,并窗口坐标由三维换为二维。

  3、消除显示缓存,重新显示二维窗口坐标下的可视线段。

  这样处理,一方面极大地简化了Z缓存计算,使普通编程人员能胜任高级三维

CAD软件设计,消隐显示质量高;另一方面获得的可视线段,便于纯Windows图形打

印,大大地增强了OpenGL图形打印能力;此处还可便于三维图形标注。有关编程核

心部分见函数Zbuffer_Calculate()。调用顺序为先绘多边形。(Display_Polygon()),

再将直线传给Zbuffer_Calculate()进行消隐计算。下面程序为本人开发的,应用软

件中的精细消隐部分,对高质量打印十分有用。编程环境为VC++5.0,完全通过。

  #include“windows.h

  #include“math.h

  #include“GL/gl.h

  #include“GL/gl.h

  typedef struct point_2d{

   float X;

   float Y;}Point_2D;

  GLdouble modelm3D[16];

  GLdouble projm3D[16];

  GLint vp[4];

  BYTE lineABC(double*,double*,BYTE&,float&,float&,

   float&,float&,float&,float&,float&);

  voitd Display_Polyon();

  void Zbuffer_Calculate(float X1,float Y1,Float Z1),

  flat X2,float Y2,float Z2)//Z缓存计算,进行精确消隐显示。

  {

  BYTE mflage=();

  BYTE m_frmfrac=3,mHide;

  GLdouble wincor1[3],wincor2[3];

  GLfloat delta,kxy,kz,min,max,xy1,z1,i;

  GLfloat xy,z,x,y,X[2],Y[2],Zbuf;

  int N=0,M;

  Point_2Dp0,p1;

  gluProject(X1,Y1,Z1,modelm3D,projm3D,vp;

  &wincor1[0],&wincor[1],&wincor1[2];

  gluProject(X2,Y2,Z2,Modelm3D,projm3D,vp,

  &wincor2[0],&wincor2[1],&wincor2[2];

  if(lineAbc(wincor1,wincor2,mflage,delta,min,

  max,xy1,z1,kxy,kz)=3)return;

  N=0,M=FALSE;mIIide=3;

  for(i=0.0;i

  xy=xy1+kxy*i;

  z=z1+kz*i;

  if(mflage=1) {x=min i;y=xy;}

  if(mflage=2 {x=xy; y=min+i;}

  glReadPixels((int)x,(int)x,(int)y,1,1,GL_DEPTII_COMPONENT,GL_FLOAT,&Zbuf);

  if(z>=Zbuf){

  X[N]=x;Y[N]=Y,N=1;

  if(N==2){N=1;M=TRUE;}

  }

  else{

  if(M==TRUE){

  pO.X=X[0];pO.Y=Y[0];

  pl.X=X[1];P1.Y=Y[1];

  //then AddNode(pO,p1,TRUE,line_width);保存该直线段,实线线型,线宽

  }

  M=FALSE;

  N=0;

  }

  }

  if(M==TRUE&&N=1){

  p0.X=X[0];p0.Y=Y[0];

  p1.X=X[1];P1.Y=Y[1];

  //then AddNode(p0,p1,TRUE,line_width);保存该直线段,实线线型,线宽

  }

  }

  //lincAbc为计算直线窗口平面坐标下的斜率等

  BYTE lineAbc(double*wincor1,double*wincor2,BYTE&MFLAGE,

  float&delta,float&in,float&max,float&xy1,

  float&z1,float&kxy,float &kz)

  {

  if(fabs(wincor1[0]-wincor2[0])=0.0&&

  fabs(wincor1[1]-wincor2[1]==0.0)return 3;

  if(fabs(wincor1[0]-wincor2[0])>

  fabs(wincor1[1]-wincor2[1](( {

  mflage=1;delta=(float)fabs(wincor1[0]-wincor2[0]);

  if(delta>1.0)

  if(wincor1[0]

  min=wincor1[0];max=wincor2[0];

  xy1=wincor1[1];

  z1=wincor1[2];

  kxy=(wincor2[1]-wincor1[1])/(wincor2[0]-wincor1[0]);

  kz=(wincor2[2]-wincor1[2])/(wincor2[0]-wincor1[0]);

  }

  else{

  min=wincor2[0];max=wincor1[0];

  xy1=wincor2[1];

  z1=wincor2[2];

  kxy=(wincor1[1]-wincor2[1]/(wincor1[0]-wincor2[0]);

  kz=(wincor1[2]-wincor2[2]/(wincor1[0]-wincor2[0]);

  }

   }

  else{

  mflage=2;delta=fabs(wincor1[1]-wincor2[1]);

  if(delta>1.0)

  if(wincor1[1]

  min=wincor1[1];max=wincor2[1];

  xy1=wincor1[0];

  z1=wincor1[2];

  kxy=(wincor2[0]-wincor1[0])/(wincor2[1]-wincor1[1]);

  kz=(Wincor2[2]-wincor1[2])/(wincor2[1]-wincor1[1]);

  }

  else{

  min=wincor2[1];max=wincor1[1];

  xy1=wincor2[0];

  z1=wincor2[2];

  kxy=(wincor1[0]-wincor2[0])/(wincor1[1]-wincor2[1]);

  kz=(wincor1[2]-wincor2[2]/(wincor1[1]-wincor2[1]);

  }

  }

   return mflage;

  }

  void Display_Polygon()

  {//SetViewPort();设置视口大小

  //SetProjection();设置投影变换

  //SetModelView();设置视图变换

  glGetDoublev(GL_MODEL VIEW_MATRIX,modelm3D);//获取视图矩阵

  glGetDoublev(GL_PROJECTION_MATRIX,projm3D);//获取投影矩阵

  glGetIntegerv(GL_VIEWPORT,vp);//获取视口大小

  //Display();绘出所有多边形,但不显示,即若双缓存,则不交换缓存。

  }

本文来源:https://www.2haoxitong.net/k/doc/cc22a02658fb770bf78a556b.html

《利用OpenGL进行CAD三维图形消隐处理.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式