osg 示例程序解析之osgdelaunay


osg 示例程序解析之osgdelaunay

轉自:http://lzchenheng.blog.163.com/blog/static/838335362010821103038928/

本示例程序主要說明如何用osgUtil::DelaunayTriangulator類建立約束的delaunay(德洛內)三角網,delaunay(德洛內)三角網主要用於基於離散點數據構建三維表面。如經常用於構建地形表面,本示例程序就是用該類構建一個地形,然后添加一些約束條件,在地形上繪制道路、區域等要素,示例程序的主要函數為:makedelaunay(),該函數輸入的參數是約束的數目,輸出的是一個組節點,下面對這個函數的實現進行說明。

1、生成離散點數據

該函數首先隨機生成一些離散點數據,代碼如下:

//隨機生成地形坐標點,存儲到Points中
 int eod=0;
 while(eod>=0) {
     osg::Vec3d pos=getpt(eod);
     if (pos.z()>-10000){
           points->push_back(pos);
           eod++;
      }

      else {
         eod=-9999;
       }
 }

2、生成一些約束類,這些類派生與osgUtil::DelaunayConstraint,如
 osg::ref_ptr<ArealConstraint> dc2; 約束區域
 osg::ref_ptr<ArealConstraint> forest; 約束區域,作為一片樹林
 osg::ref_ptr<LinearConstraint> dc3;  約束區域,一條線
 等等,然后確定約束的邊或點,如當輸入的參數大於0時,確定金字塔的底邊作為約束邊,如下代碼所示:

//令5個金字塔的底邊作為約束邊
  for(unsigned int ipy=0; ipy<5; ipy++){
       osg::ref_ptr<pyramid>pyr=new pyramid;
       float x=2210+ipy*120, y=1120+ipy*220;
       //設置金字塔繪制的位置及大小尺寸
       pyr->setpos(osg::Vec3(x,y,getheight(x,y)),125.0+10*ipy);
       //確定金字塔底面4邊形4個頂點坐標
       pyr->calcVertices(); //make vertices
       //底面4條邊構成約束

        pyr->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,4) );
       //添加約束邊,金字塔底面4邊形4條邊作為約束
       trig->addInputConstraint(pyr.get());
       //存儲約束邊
       pyrlist.push_back(pyr.get());
  }

  addInputConstraint()方法用於向三角網中添加約束條件。

其余的約束條件的生成與添加與其類似。

3、三角化處理

添加完約束條件后,進行三角化處理,如下代碼所示:

trig->setInputPointArray(points);
 osg::Vec3Array *norms=new osg::Vec3Array;
 trig->setOutputNormalArray(norms);
 //三角化處理
 trig->triangulate();

4、將三角化的圖元添加到葉節點中

//添加構建的三角形作為圖元
gm->addPrimitiveSet(trig->getTriangles());
gm->setNormalArray(trig->getOutputNormalArray());
gm->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
geode->addDrawable(gm.get());

5、繪制約束的幾何體

為了方便看出約束的效果,我們用線框的方式顯示圖形,把葉節點的狀態改為線框顯示方式。

osg::PolygonMode *pLolyMode=new osg::PolygonMode();
 pLolyMode->setMode(osg::PolygonMode::FRONT_AND_BACK ,osg::PolygonMode::LINE);
 stateset->setAttribute(pLolyMode);
 geode->setStateSet( stateset );

在繪制約束體之前,先要使用removeInternalTriangles()方法,移開約束條件構建的三角形,對於繪制金字塔的代碼:

for ( std::vector < pyramid* >::iterator itr=pyrlist.begin(); itr!=pyrlist.end(); itr++) {
       //移開金字塔約束邊形成的三角形,形成4個4邊形空洞
       //trig->removeInternalTriangles(*itr);
      //繪制金字塔 

       //geode->addDrawable((*itr)->makeGeometry()); // this fills the holes of each pyramid with geometry
  }

 如果我們注釋以下兩句:

 //trig->removeInternalTriangles(*itr);
//geode->addDrawable((*itr)->makeGeometry()); // this fills the holes of each pyramid with geometry

會看到如下的效果:

osg 示例程序解析之osgdelaunay - 陳恆 - 陳恆的博客

 我們看到受約束的地方仍然形成了三角形,沒有生成生4邊形的空洞,如果我們把第一句的注釋去掉,會看到如下結果:

osg 示例程序解析之osgdelaunay - 陳恆 - 陳恆的博客

 說明建立約束條件后,只有使用trig->removeInternalTriangles()方法,才能使約束生效,通過本示例程序,我們可以知道如何基於離散點及約束條件,構建受約束的三角網的方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM