程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> osg項目經驗1<MFC+OSG中模型點選效果>,osgmfc

osg項目經驗1<MFC+OSG中模型點選效果>,osgmfc

編輯:C++入門知識

osg項目經驗1<MFC+OSG中模型點選效果>,osgmfc


  點選主要是重載osg的GUIEventHandler,

 1 class CPickHandler : public osgGA::GUIEventHandler{   //自定義回調函數名:CPickHandler
 2     osgViewer::Viewer * mViewer;   //在這裡定義要在重載函數裡使用的變量
 3     osg::Group * mGroup;
 4     osg::Node * lastSelect;
 5     osg::Node * replacedNode;
 6     int replaceNum;
 7 public:
 8     CPickHandler(osgViewer::Viewer * viewer, osg::Group *group) :mViewer(viewer),mGroup(group),lastSelect(0),replacedNode(0){}  //聲明回調函數,括號中是回調函數需要傳入的參數,冒號後的內容是給函數內自定義的變量初始化,前面是變量名,括  號內是初始化值。
 9     virtual bool handle(const osgGA::GUIEventAdapter & ea, osgGA::GUIActionAdapter & aa){
10         switch(ea.getEventType()){
11             case(osgGA::GUIEventAdapter::PUSH):{
12                 if(lastSelect){
13                     lastSelect = 0;
14                 }
15                 Pick(ea.getX(),ea.getY());    //ea即鼠標點擊的地方,ea.getX(),ea.getY(),是獲得鼠標點擊的屏幕坐標。
16             }
17                 return true;
18         }
19         return false;
20     }
21 
22 protected:
23     void Pick(float x, float y){}//在pick()函數裡傳入了鼠標點擊的屏幕坐標,然後可以根據屏幕坐標寫你想要點擊完成的動作。
24 }

 

其中需要注意的是,OSG中有多個坐標系,我們通過鼠標點擊獲得的只是屏幕坐標,我們往往需要在場景中添加東西時,都需要得到某個點的世界坐標才能比較好操作:

但是在我們知道是哪個節點的情況下,我們可以根據:

geode->getBound().center() * osg::computeLocalToWorld(geode->getParentalNodePaths()[0])

來獲得節點geode的世界坐標。

 

我的項目的3維模型是由Obj格式導出的ive和osg文件,原始的obj模型是用sketchup做的,在制作的時候把幾個模型創建組的時候會給每個模型單獨的命名,而在osg中可以通過->getName()獲得這些名字,我可以通過用文本浏覽器notePad++打開模型的obj文件來查看這些名字,這些名字的命名都是g mash開頭的,為了方便,我把每個模型的各個部分的命名改成相同的,用python很好解決這個問題。

那麼我的pick函數是這樣的:

 1 void Pick(float x, float y){
 2         osgUtil::LineSegmentIntersector::Intersections intersections;
 3 
 4         if(mViewer->computeIntersections(x, y, intersections)){
 5             osgUtil::LineSegmentIntersector::Intersection intersection = *intersections.begin();
 6             for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr!= intersections.end(); ++hitr){
 7                 if(!hitr->nodePath.empty() && !(hitr->nodePath.back()->getName().empty())){
 8                     const osg::NodePath& np = hitr->nodePath;
 9                     
10                     for(int i = np.size() - 1; i >= 0; --i){     //遍歷選中的節點
11                         osg::Node* nd = dynamic_cast<osg::Node *> (np[i]);
12                         if(nd){
13                             if(nd->getName()=="pipelineTeam1"){    //根據模型的名字判斷是否選中了某個模型
14                                     /*
15                                     在這兒寫對該模型做的操作
16                                     */
17                             }
18                             return;
19                         }
20                     }
21                 }
22             }
23         }

但是,這只是寫好了一個回調函數,最後需要在osg控制類(我的是OSG_MFC.cpp)中的void cOSG::InitCameraConfig(void){}函數中加上一句:

mViewer->addEventHandler(new CPickHandler(mViewer, mRoot));  //要把指針轉為引用 ,因為mViewer定義的時候是 osgViewer::Viewer* mViewer;現在要使用&mViewer

那麼在我們點擊屏幕某點的時候,就會自動調用回調函數中的pick()函數,進行其中的操作。

 

我的項目在pick()回調中,做到了在選中節點的位置添加一個Geometry,在Geometry上顯示文字消息,並給選中的模型加上選中效果,可以做成高亮顯示和加上高亮的(自定義顏色)的邊框,這些會在下一篇文章中介紹。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved