OSG項目經驗2<在場景中添加文字面版>


添加文字版需要用到osg的三個名字空間:
                        osgText::Text,這個類用來添加文字和設置文字的一些屬性;
                        osg::Geometry,這個類用來畫常見的圖形;
                        osg/ShapeDrawable,通過這個類也可以畫一些常見的圖形,並且可以吧Geometry加進osg::Geode節點中;
下面先簡要介紹一下這三個命名空間;
 
1、osgText::Text:見http://www.cnblogs.com/xiaocainiao2hao/p/4544273.html
 
2、OSG::Gemotery
      用戶使用Gemotery類,可以通過制定頂點、顏色和法線的方式,繪制簡單的多邊形,然后通過Geode->addDrawable()方法,把繪制的多邊形添加到節點中。
    我在項目中僅僅畫了矩形,然后通過設置geo的各個屬性來達到想要的效果,這在后面的代碼中會加以介紹。如果想了解更多的關於osg::Geometry的相關知識,請查看www.baidu.com。
 
3、osg::ShapeDrawable類
    這個沒啥好介紹的,也是畫一些節本的圖形,不果geode要調用它的一個方法比較有用
                                geode->addDrawable(osg::Geometry geo)
    這個可以把我們自己畫的Gemotery圖形加到節點中。
 
下面通過部分代碼來對這三個類的應用加以介紹:
    在項目經驗1中,我們已經能夠通過自定義的CPickHandler()回調來達到我們在場景中用鼠標點擊某個點,就能得到點擊處的屏幕坐標,進而轉換為世界坐標,而且我們能夠通過模型的相關信息(我用的是模型的名字)來確定我們選擇的是哪個模型,進而對我們的選擇事件作出相應。
    那么,我們首先在我們選擇的模型上加上一個信息展示面板,展示模型的相關信息。
    
    第一步,我們需要獲得我們選擇的模型的世界坐標:
                      
1   osg::Vec3 center;                      // osg中的坐標是三維的,所以我們需要定義一個三維向量center用來存儲獲得的坐標
2   int NodeNum;
3   center = mRoot->getChild(NodeNum)->computeBound()._center;  //獲得鼠標點擊模型的包圍盒的中心處坐標,NodeNum是我加載模型的時候模型在節點中的序號

 

    我們可以通過center這個坐標獲得我們選擇節點的世界坐標,通過下面一句:                  
osg::Vec3 wordMark = mRoot->getChild(NodeNum)->getBound().center()*osg::computeLocalToWorld(mGroup->getChild(NodeNum)->getParentalNodePaths()[0]);//獲得節點的世界坐標
    然后我們就可以通過這個世界坐標在該位置添加文字面板了。
 
    下寫一個添加文字的方法:
    
 1   void CreatText(osgText::Text& textObject,osgText::Font* font,float size,const osg::Vec3& pos )
 2     {
 3              textObject.setFont(font);// 讀入字體
 4              textObject.setCharacterSize(size);//字體大小
 5              textObject.setPosition(pos);
 6              textObject.setColor(osg::Vec4(0.0,1.0,0.0,1.0));
 7              textObject.setAlignment(osgText::Text::LEFT_BOTTOM);//文字對齊方向
 8              textObject.setAutoRotateToScreen(true);//跟隨視角不斷變化,但離物體越遠,文字越小
 9              textObject.setAxisAlignment(osgText::Text::XZ_PLANE);//獲取文字對稱成方式
10  
11     }//在這個函數中也可以根據自己的需要使用text的其他方法,如文字描邊:textObject.setBackdropType(),給文字加上邊框:textObject.setDrawMode()等
12  
13     void createContent(osgText::Text& textObject,const char* string)
14     {
15             int requiredSize=mbstowcs(NULL,string,0);        //如果mbstowcs第一參數為NULL那么返回字符串的數目
16             wchar_t* wText=new wchar_t[requiredSize+1];
17             mbstowcs(wText,string,requiredSize+1)           ;//由char轉換成wchar類型
18             textObject.setText(wText);
19             delete wText;
20     }
    然后我們可以通過調用這兩個函數添加文字:
   
 1      const char* textString={
 2            "我選中的節點是這個;\n"
 3            "先畫一個文字面板;\n"
 4            "再添加文字;\n"
 5            "然后把文字和面板都添加到geode中;\n"
 6            "最后把geode加載到mRoot中"
 7           };
 8       const char* titleString={
 9            "文字面板"
10           };
11         osgText::Font* fontHei = osgText::readFontFile("simhei.ttf");   //讀入字體
12         osg::ref_ptr<osgText::Text> text = new osgText::Text;              //新建一個text對象
13         CreatText(*text,fontHei,350.0,wordMark);                                //調用CreatText()方法,創建一個文字對象,wordMark就是我們上步計算的選擇節點的世界坐標
14         createContent(*text,textString);    
15  
16         osg::ref_ptr<osgText::Text> title = new osgText::Text;
17         setupProperties(*title,fontHei,350.0,osg::Vec3(wordMark.x()+1100,wordMark.y()-2508,wordMark.z()+1600));
18         createContent(*title,titleString);
19         title->setColor(osg::Vec4(1.0,0.0,0.0,1.0)); 
20                        
21         osg::ref_ptr<osg::Geode> geode3 = new osg::Geode;          //創建一個geode對象,用來加載text和Gemotery對象
22         //給文字添加底板
23         osg::ref_ptr<osg::Geometry> geo = new osg::Geometry;    //創建一個Gemotery對象
24         osg::Vec4Array* colorArray = new osg::Vec4Array;              //創建一個Vec4Array對象,存放顏色信息
25         geo = osg::createTexturedQuadGeometry(osg::Vec3(wordMark.x(),wordMark.y()+6,wordMark.z()+1400),osg::Vec3(4500,0.0,0.0),osg::Vec3(0.0,0.0,200),1.0,1.0);    //畫一個小矩形,用來擺放title,后面會對createTexturedQuadGeometry里面的參數做介紹
26         colorArray->push_back(osg::Vec4(0.0,1.0,0.0,1.0));            //給colorArray賦值,0101是綠色
27         geo->setColorArray(colorArray);                                        //給畫的矩形設置顏色
28         geode3->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(wordMark.x(),wordMark.y()+8,wordMark.z()-130.0),osg::Vec3(4500,0.0,0.0),osg::Vec3(0.0,0.0,1600),1.0,1.0));    //再畫一個大矩形,用來放其它文字信息,並且把矩形加進geode對象中
29         geode3->addDrawable(geo.get());      //把小矩形也加載進geode
30         geode3->addDrawable(text.get());
31         geode3->addDrawable(title.get()); 
32         mRoot->addChild(geode3);                //把文字面板加進mRoot中

 

在上面的代碼中的wordMark.x()和y、z坐標加減值都是我根據顯示效果自己調整的位置。在具體情況下需要自己確定值。
 
關於
         createTexturedQuadGeometry(const Vec3 & corner,const Vec3 & widthVec,const Vec3 & heightVec,float l,float b,float r,float t ); 
其中corner是起點(矩形的左下角),然后從這個起點按照widthVec和heightVec來畫出一個矩形,我一般設置
                        
              widthVec=osg::Vec3(num1,0,0);    //這個num1就是矩形的長
                        heightVec=osg::Vec3(0,0,num2);  //這個num2就是矩形的高
l,b一般都取0.0,r,t如果不相等,那么二維的貼圖會變成長方形。也就是說,我的黑白棋盤格,會變成黑白長方格。相等的話,就會變成黑白正方格。
 
 
另外colorArray 對象的顏色值             
          colarray->push_back(osg::Vec4(1.0, 0.0, 0.0, 1.0));    //Red

                colarray->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0));    //Green

                colarray->push_back(osg::Vec4(0.0, 0.0, 1.0, 1.0));    //Blue

                colarray->push_back(osg::Vec4(1.0, 1.0, 1.0, 1.0));    //White

 

 

 

 


免責聲明!

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



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