1. 程式人生 > >2、OpenSceneGraph中新增節點、刪除節點、隱藏節點以及新增開關的用法

2、OpenSceneGraph中新增節點、刪除節點、隱藏節點以及新增開關的用法

1、新增節點之前要先宣告一個組也就是根節點,就像是節點樹一樣必須要有一個根,然後在這個根下新增子節點,而子節點下還可以新增子節點,可通過osg::Group來建立一個根節點,如下程式碼所示:

osg::Group *root=new osg::Group();

2、那麼在這個根上新增節點,可使用osg::Node來宣告並建立一個節點,並未該節點新增模型,如下程式碼所示:
osg::Node *avatar=osgDB::readNodeFile("avatar.osg");
osg::Node *glider=osgDB::readNodeFile("glider.osg");
3、將glider節點作為avatar的子節點,那麼需要通過節點的asGroup()來新增,如下程式碼所示:
avatar->asGroup()->addChild(glider);//在以avatar為組,新增子模型(注意:子模型的大小要小於組模型大小)
4、將avatar節點新增到根節點上去,如下程式碼所示:
root->addChild(avatar);
5、在根節點下直接新增一個節點,如下程式碼所示:
root->addChild(osgDB::readNodeFile("osgcool.osgt"));

所有程式碼如下:

#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	osg::Group *root=new osg::Group();
	osg::Switch *sw=new osg::Switch();
	osg::Node *avatar=osgDB::readNodeFile("avatar.osg");
	osg::Node *glider=osgDB::readNodeFile("glider.osg");
	avatar->asGroup()->addChild(glider);//在以avatar為組,新增子模型(注意:子模型的大小要小於組模型大小)
	root->addChild(avatar);
	root->addChild(osgDB::readNodeFile("osgcool.osgt"));
	viewer.setSceneData(root);
	viewer.realize();
	return viewer.run();
}
以下是執行效果:



6、刪除節點,比如將上圖的小飛機刪除掉可使用以下程式碼,以下程式碼提供了多種刪除方法,其中有兩種方法是無法刪除的。

//root->removeChild(avatar);//以索引刪除一個子節點
//root->removeChild(1);//刪除索引為1的節點,此函式不能刪除0的節點
//root->removeChildren(0,1);//刪除第0個節點,刪除的個數為1個
avatar->asGroup()->removeChild(glider);//在組avatar中刪除一個子節點,如果使用索引的方法是無法刪除的
//avatar->asGroup()->removeChild(1);//無法刪除
//avatar->asGroup()->removeChildren(1,1);//無法刪除
執行效果如下,可根據上圖進行比較,在腳的位置少了個小飛機。


7、隱藏節點,可通過節點物件中的setNodeMask(0)函式對該節點進行隱藏,0表示隱藏,1表示顯示,隱藏起來時該節點是還會存在於記憶體中的,程式碼如下:

avatar->setNodeMask(0);//隱藏某個模型,0表示隱藏,1表示顯示

以上是將機器人隱藏掉,如下效果所示:


以下是所有程式碼:

#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	osg::Group *root=new osg::Group();
	osg::Switch *sw=new osg::Switch();
	osg::Node *avatar=osgDB::readNodeFile("avatar.osg");
	osg::Node *glider=osgDB::readNodeFile("glider.osg");
	avatar->asGroup()->addChild(glider);//在以avatar為組,新增子模型(注意:子模型的大小要小於組模型大小)
	root->addChild(avatar);
	root->addChild(osgDB::readNodeFile("osgcool.osgt"));
	//root->removeChild(avatar);//以索引刪除一個子節點
	//root->removeChild(1);//刪除索引為1的節點,此函式不能刪除0的節點
	//root->removeChildren(0,1);//刪除第0個節點,刪除的個數為1個
	avatar->asGroup()->removeChild(glider);//在組avatar中刪除一個子節點,如果使用索引的方法是無法刪除的
	//avatar->asGroup()->removeChild(1);//無法刪除
	//avatar->asGroup()->removeChildren(1,1);//無法刪除
	avatar->setNodeMask(0);//隱藏某個模型,0表示隱藏,1表示顯示
	viewer.setSceneData(root);
	viewer.realize();
	return viewer.run();
}


8、為節點新增開關功能,就是將節點通過開關控制是否顯示節點,可通過開關來控制節點的顯示(關:節點不在記憶體中,但節點並未刪除,開:節點不需要重新新增,只需要通過開關直接顯示),那麼首先宣告 一個開關變數,如下程式碼所示:
osg::Switch *sw=new osg::Switch();
9、將其中的兩個節點新增到開關中去,然後在將此開關新增到根節點下,如下程式碼所示:
sw->addChild(avatar,false);//第二個引數為false表示將avatar關掉不顯示,如果是true就是開啟顯示
root->addChild(sw);
執行效果如下:

所有程式碼如下:

#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	osg::Group *root=new osg::Group();
	osg::Switch *sw=new osg::Switch();
	osg::Node *avatar=osgDB::readNodeFile("avatar.osg");
	osg::Node *glider=osgDB::readNodeFile("glider.osg");
	avatar->asGroup()->addChild(glider);//在以avatar為組,新增子模型(注意:子模型的大小要小於組模型大小)
	sw->addChild(avatar,false);//第二個引數為false表示將avatar關掉不顯示,如果是true就是開啟顯示
	root->addChild(sw);
	root->addChild(osgDB::readNodeFile("osgcool.osgt"));
	viewer.setSceneData(root);
	viewer.realize();
	return viewer.run();
}
10、將關掉的節點顯示出來,可通過開關的setValue()函式顯示出來或者關閉,如下程式碼所示:
sw->setValue(0,true);//第一個引數表示節點的索引,0表示新增的第一個節點,如果第二個引數是false則表示關閉節點,如果是true則是顯示
如下執行效果:

以下是所有程式碼:

#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	osg::Group *root=new osg::Group();
	osg::Switch *sw=new osg::Switch();
	osg::Node *avatar=osgDB::readNodeFile("avatar.osg");
	osg::Node *glider=osgDB::readNodeFile("glider.osg");
	avatar->asGroup()->addChild(glider);//在以avatar為組,新增子模型(注意:子模型的大小要小於組模型大小)
	sw->addChild(avatar,false);//第二個引數為false表示將avatar關掉不顯示,如果是true就是開啟顯示
	root->addChild(sw);
	root->addChild(osgDB::readNodeFile("osgcool.osgt"));
	sw->setValue(0,true);//第一個引數表示節點的索引,0表示新增的第一個節點,如果第二個引數是false則表示關閉節點,如果是true則是顯示
	viewer.setSceneData(root);
	viewer.realize();
	return viewer.run();
}

11、超級指標osg::ref_ptr的使用方法,使用此方法可以防止在刪除節點時是否釋放該節點的記憶體,比如:當有一個節點多次新增時,那麼超級指標就會自動加1,在釋放時就會自動減1,當減到0時,就會自動釋放該節點所佔的記憶體,如將以上的所有指標修改為如下程式碼所示:

#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	//osg::Group *root=new osg::Group();
	osg::ref_ptr<osg::Group> root=new osg::Group();
	//osg::Switch *sw=new osg::Switch();
	osg::ref_ptr<osg::Switch> sw=new osg::Switch();
	//osg::Node *avatar=osgDB::readNodeFile("avatar.osg");
	osg::ref_ptr<osg::Node> avatar=osgDB::readNodeFile("avatar.osg");
	//osg::Node *glider=osgDB::readNodeFile("glider.osg");
	osg::ref_ptr<osg::Node> glider=osgDB::readNodeFile("glider.osg");
	avatar->asGroup()->addChild(glider);//在以avatar為組,新增子模型(注意:子模型的大小要小於組模型大小)
	sw->addChild(avatar,false);//第二個引數為false表示將avatar關掉不顯示,如果是true就是開啟顯示
	root->addChild(avatar);
	root->addChild(osgDB::readNodeFile("osgcool.osgt"));
	sw->setValue(0,true);//第一個引數表示節點的索引,0表示新增的第一個節點,如果第二個引數是false則表示關閉節點,如果是true則是顯示
	viewer.setSceneData(root);
	viewer.realize();
	return viewer.run();
}