房产公司五证:利用OpenGL进行CAD三维图形消隐处理

来源:百度文库 编辑:偶看新闻 时间:2024/05/06 18:14:00
利用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();绘出所有多边形,但不显示,即若双缓存,则不交换缓存。
  }