OSG模型简单控制
来源:互联网 发布:抢魅族软件 编辑:程序博客网 时间:2024/04/30 02:34
欢迎访问我的新博客:http://www.milkcu.com/blog/
原文地址:http://www.milkcu.com/blog/archives/1392673560.html
结点基本操作
添加结点
OSG中使用osg::Node
和osg::Group
装载模型,Node是Group的父类。
可以通过下面代码再场景中显示多个模型:
#include <osgDB/ReadFile>#include <osgViewer/Viewer>#include <osg/Node>int main(void){ osgViewer::Viewer viewer; osg::Group * root = new osg::Group(); root->addChild(osgDB::readNodeFile("glider.osg")); root->addChild(osgDB::readNodeFile("osgcool.osgt")); viewer.setSceneData(root); viewer.realize(); viewer.run(); return 0;}
默认时两节点是加在场景的中间。
那为什么飞机会在左边呢?
为什么牛会把其他模型覆盖掉呢?
组结点
如果想在原结点中添加点什么,就需要把原结点作为组结点。
可以使用下面代码再飞机结点中再添加一些东西。
删除结点
可以通过removeChild和removeChildren方法删除结点,需要的参数为索引值或结点本身的指针。
可以通过下面代码实现指定结点的删除:
#include <osgDB/ReadFile>#include <osgViewer/Viewer>#include <osg/Node>int main(void){ osgViewer::Viewer viewer; osg::Group * root = new osg::Group(); root->addChild(osgDB::readNodeFile("osgcool.osgt")); osg::Node * glider = osgDB::readNodeFile("glider.osg"); root->addChild(glider); root->addChild(glider); root->removeChild(glider); root->removeChild(glider); viewer.setSceneData(root); viewer.realize(); viewer.run(); return 0;}
如果删除一个结点,那么该结点下的所有结点都会被删除。
如果一个极点被加入到一组中多次,那么这两次是分别存在的,删除一次还有一次。
隐藏结点
隐藏的模型仍在渲染,不会从内存中消失,损耗并未减少,只不过隐藏了而已。
node->setNodeMask()
可以设置隐藏与显示,node->setNodeMask(0x0)
表示隐藏,node->setNodeMask(1)
表示显示。
可以通过下面代码实现隐藏指定模型:
# include <osgDB/ReadFile># include <osgViewer/Viewer># include <osg/Node>int main(void){ osgViewer::Viewer viewer; osg::Group * root = new osg::Group(); osg::Node * osgcool = osgDB::readNodeFile("osgcool.osgt"); root->addChild(osgcool); root->addChild(osgDB::readNodeFile("glider.osg")); osgcool->setNodeMask(0x0); viewer.setSceneData(root); viewer.realize(); viewer.run(); return 0;}
在运行程序时按空格键时会回到中心点,该中心点是面向包围球的圆心,如果不存在osgcool,那么按空格会把飞机置于场景中映,而有了osgcool飞机会被放置在左边。
结点开关
可以使用结点开关osg::Switch
打开或关闭结点,在关闭时结点所占用的内存将被释放掉。
可以通过下面代码实现结点打开与关闭:
# include <osgDB/ReadFile># include <osgViewer/Viewer># include <osg/Node># include <osg/Switch>void main(){ osgViewer::Viewer viewer; osg::Group * root = new osg::Group(); osg::Switch * sw = new osg::Switch(); osg::Node * osgcool = osgDB::readNodeFile("osgcool.osgt"); sw->addChild(osgcool, false); sw->addChild(osgDB::readNodeFile("glider.osg")); root->addChild(sw); viewer.setSceneData(root); viewer.realize(); viewer.run();}
由于osgcool模型根本不存在,所以glider模型置于场景中间。
超级指针
超级指针机制,其实就是引用一个计数器。引用一次加一,释放一次减一。当减至0时,内存释放。
使用结点的三种方法:
方法一(超级指针):
osg::ref_ptr<osg::Node> node = new osg::Node();group->addChild(node.get());
这是最好的方法,十分安全,也是OSG中最常用的方法。在new osg::Node()
时申请了一个Node的资源,这时在堆内引用该Node的计数器会被置1。在group->addChild(aNode.get())
时又引用了一次,会再加1。在这两次引用都结束时,Node的资源就会被释放。
方法二:
group->addChild(new osg::Node());
这个方法也是很实用的,但是无法引出Node的指针,也许在别处可以用到,事实上会经常用到。如果已经这样做了,得到Node指针也不是不可以的,可以使用NodeVisitor来得到Node的指针,也可以使用findChild方法来做这件事。
方法三:
osg::Node * node = new osg::Node();group->addChile(node);
这个应该是最常用,但是最烂的方法了,原因在于如果在osg::Node*node = new osg::Node()
之后发生了错误,抛出了异常,Node所占用的资源没有释放。
在有大量交互以及场景变换时,建议使用超级指针。
模型矩阵变换
模型的移动、旋转、缩放其实都是对矩阵进行操作,矩阵可以当作一个特殊的结点加入到组结点中。
通过osg::MatrixTransform
定义变换矩阵,
通过setMatrix(osg::Matrix::translate(x, y, z))
实现模型移动,
通过setMatrix(osg::Matrix::scale(x, y, z))
实现模型缩放,
通过setMatrix(osg::Matrix::rotate(x, y, z))
实现模型旋转。
可以通过下面的代码实现模型的移动、旋转、缩放:
# include <osgDB/ReadFile># include <osgViewer/Viewer># include <osg/Node># include <osg/MatrixTransform>int main(void){ osgViewer::Viewer viewer; osg::ref_ptr<osg::Group> root = new osg::Group; osg::ref_ptr<osg::Node> osgcool = osgDB::readNodeFile("osgcool.osgt"); osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform; trans->setMatrix(osg::Matrix::translate(0, 0, 2)); trans->addChild(osgcool.get()); osg::ref_ptr<osg::MatrixTransform> scale = new osg::MatrixTransform; scale->setMatrix(osg::Matrix::scale(0.5, 0.5, 0.5) * osg::Matrix::translate(0, 0, -2)); scale->addChild(osgcool.get()); osg::ref_ptr<osg::MatrixTransform> rot = new osg::MatrixTransform; rot->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(45.0), 1, 0, 0) * osg::Matrix::scale(0.5, 0.5, 0.5) * osg::Matrix::translate(4, 0, -2)); rot->addChild(osgcool.get()); root->addChild(osgcool.get()); root->addChild(trans.get()); root->addChild(scale.get()); root->addChild(rot); viewer.setSceneData(root.get()); viewer.realize(); viewer.run(); return 0;}
在OSG中,坐标轴是可以设置的,默认向右的是X轴,向里的是Y轴,向上的是Z轴,与传统OPENGL坐标轴有所不同。
(全文完)
- OSG模型简单控制
- OSG-简单模型控制
- OSG模型控制
- 第3课时《osg模型控制》
- 模型简单控制
- osg模型重写
- osg模型透明代码
- osg添加骨骼模型
- osg模型发黑
- OSG视点的控制
- [osg]OSG中的图元控制
- 一个简单的库存控制模型
- unity3d模型运动转向移动简单控制
- OSG — 事件处理模型
- win32 SDk展示osg模型
- 直接控制OSG摄像机移动
- OSG 飞机路径动画控制
- OSG使用更新回调来更改模型
- 面向对象介绍
- iOS开发-比较好的文章和资源链接
- 2014.2.18读书摘记
- 六十 如何写一个简单的守护(精灵)进程原型
- IOS NSString类型十六进制转换为十进制
- OSG模型简单控制
- SDL Game Development-第2章-5.实现纹理管理器Texture Manager
- 解决/usr/bin/ld: cannot find -lxxx 问题
- Qt入门-layout布局
- 正则
- JAVA6开发WebService (二)——JAX-WS例子
- 你若安好,便是晴天
- 生活
- 用css控制表格的内容,使其在固定宽度后换行。