本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html
作者写的比较好,再次收藏,希望更多的人可以看到这个文章
互联网是是一个相互分形并学习的平台,我希望我每个人可以将我们认为有价值的东西,在不损害他人利益的情况下分享给更多的人。
添加模型
在OSG当中模型是使用osg::Group和osg::Node来装载在一起的,比如同时需要加入两个模型,模型A了模型B,AB各自是一个NODE,那么可以使用以下语句来做到,首先使用一个Group,然后Group->addChild(A),同样,之后要Group->addChild(B)。然后再把Group添加到viewer当中就可以了。如图3.1所示AB之间的关系。在这里要申明的是NODE是Group的父类,在类中都有相应的方法可以转到对方,故Node与Group
是通用的,Node也可以被当作Group来用。
简单实例代码
#include<osgDB/ReadFile> #include<osgViewer/Viewer> #include<osg/Node> void main() { osgViewer::Viewer viewer; osg::Group * root=new osg::Group(); root->addChild(osgDB::readNodeFile("glider.osg")); root->addChild(osgDB::readNodeFile("osgcool.osg")); viewer.setSceneData(root); viewer.realize(); viewer.run(); }
运行结果
删除结点
如果我们不需要某个结点了,比如上图我们看那个小飞机很不爽,我们想把它从场景中删除掉。不知道于某种目的,反正现在要删除掉,可能是开始想看见它现在不想看见它了。可以通过removeChild方法,除多个孩子也可以通过removeChildren方法,里面的参数有些需要索引值,有些需要结点本身的指针,读者可以自己尝试。这里要注意的是,如果要删除一个结点,那么该结点下的所有结点都会被删除。如果一个结点被加入到一个组中两次,那么这两次是分别存在的,删除一次还有另一次。删除操作不能说不是个危险的操作,有些时候,尤其在有移动结点等等混在一起时,删除操作有时候会发生一些比较奇怪的现象。在内存映象当中,如果一个模型被读取一次,而用了多次,那么所占用的空间是不会改变的。
隐藏模型与结点开关
Ø 隐藏模型
隐藏模型其实模型仍在渲染当中,因此损耗并未减少,只不过隐藏了而已,隐藏的确不是个什么好操作,但是有时候对小模型确实也很实用。node->setNodeMask可以设置隐藏与显示。
Ø 节点开关
在OSG当中,专门有一个类来负责打开与关闭结点,该类名为osg::Switch,里面有相应的方法来控制它所管理的结点的打开与关闭。
两个方法都能控制模型的显示和隐藏,区别在于隐藏模型方法不会让模型在内存中消失,这样对于小的物体频繁的调用会节省一些时间,而对于有些大的模块在用一次以后可能很久再用第二次,这个时候用节点开关可以将模型销毁,再次使用再调入内存,以防止占用更多的资源。
超级指针
超级指针的机制,其实就是引用一个计数器,这个计数器会计算这个箱子被引用的次数,被别人引用一次这个计数器增加一,别人不用一次,即:释放一次,则计数器减一。当减至0时,内存放掉不用。
们来看使用一个Node的三种方法,对比一下:
Ø //方法一,最好的方法,十分安全,也是OSG中最常用的方法,多少版本它都没变
osg::ref_ptr<osg::Node>aNode(new osg::Node());
group->addChild(aNode.get());
Ø //方法二,也是非常好的方法,有时候不适用,但也十分安全
group->addChild(new osg::Node());
Ø //方法三,非常危险,但是令许多人无故铤而走险的方法
osg::Node*anotherNode=new osg::Node();
group->addChild(anotherNode);
方法一:在new::Node()时申请了一个Node的资源,这时在堆内引用该Node的计算器会被置1。在group->addChild(aNode.get())时又引用了一次,会再加1。在这两次引用都结束时,Node的资源就会被释放。
方法二:这个方法也是很实用的,但是无法引出Node的指针,也许在别处可以用到,事实上会经常用到。如果已经这样做了,得到Node指针也不是不可以的,可以使用NodeVisitor来得到Node的指针,也可以使用findChild方法来做这件事。
方法三:这个应该是最常用,但是最烂的方法了,原因在于如果在osg::Node*antherode=new osg::Node()之后发生了错误,抛出了异常,谁来释放Node所占用的资源呢。而这个异常在后面被捕获,程序正常的走下去,而内存却没有被正常的放掉。
移动/旋转/缩放模型
移动/旋转/缩放其实都是对矩阵进行操作,在OSG当中,矩阵可以当作一个特殊的结点加入到root当中,而矩阵下也可以另入结点,而加入的结点就会被这个矩阵处理过,比如移动过/旋转过/缩放过。在OSG中控制矩阵的类为osg::MatrixTransform。
Ø 移动
osg::Matrix::translate
Ø 旋转
osg::Matrix::rotate
Ø 缩放
osg::Matrix::scale