OSG模型简单控制

转自:http://milkcu.sintune.net/blog/archives/1392673560.html

结点基本操作

添加结点

OSG中使用osg::Nodeosg::Group装载模型,Node是Group的父类。

可以通过下面代码再场景中显示多个模型:

  1. #include <osgDB/ReadFile>
  2. #include <osgViewer/Viewer>
  3. #include <osg/Node>
  4. int main(void)
  5. {
  6. osgViewer::Viewer viewer;
  7. osg::Group * root = new osg::Group();
  8. root->addChild(osgDB::readNodeFile("glider.osg"));
  9. root->addChild(osgDB::readNodeFile("osgcool.osgt"));
  10. viewer.setSceneData(root);
  11. viewer.realize();
  12. viewer.run();
  13. return ;
  14. }

默认时两节点是加在场景的中间。
那为什么飞机会在左边呢?
为什么牛会把其他模型覆盖掉呢?

组结点

如果想在原结点中添加点什么,就需要把原结点作为组结点。

可以使用下面代码再飞机结点中再添加一些东西。

删除结点

可以通过removeChild和removeChildren方法删除结点,需要的参数为索引值或结点本身的指针。

可以通过下面代码实现指定结点的删除:

  1. #include <osgDB/ReadFile>
  2. #include <osgViewer/Viewer>
  3. #include <osg/Node>
  4. int main(void)
  5. {
  6. osgViewer::Viewer viewer;
  7. osg::Group * root = new osg::Group();
  8. root->addChild(osgDB::readNodeFile("osgcool.osgt"));
  9. osg::Node * glider = osgDB::readNodeFile("glider.osg");
  10. root->addChild(glider);
  11. root->addChild(glider);
  12. root->removeChild(glider);
  13. root->removeChild(glider);
  14. viewer.setSceneData(root);
  15. viewer.realize();
  16. viewer.run();
  17. return ;
  18. }

如果删除一个结点,那么该结点下的所有结点都会被删除。

如果一个极点被加入到一组中多次,那么这两次是分别存在的,删除一次还有一次。

隐藏结点

隐藏的模型仍在渲染,不会从内存中消失,损耗并未减少,只不过隐藏了而已。

node->setNodeMask()可以设置隐藏与显示,node->setNodeMask(0x0)表示隐藏,node->setNodeMask(1)表示显示。

可以通过下面代码实现隐藏指定模型:

  1. # include <osgDB/ReadFile>
  2. # include <osgViewer/Viewer>
  3. # include <osg/Node>
  4. int main(void)
  5. {
  6. osgViewer::Viewer viewer;
  7. osg::Group * root = new osg::Group();
  8. osg::Node * osgcool = osgDB::readNodeFile("osgcool.osgt");
  9. root->addChild(osgcool);
  10. root->addChild(osgDB::readNodeFile("glider.osg"));
  11. osgcool->setNodeMask(0x0);
  12. viewer.setSceneData(root);
  13. viewer.realize();
  14. viewer.run();
  15. return ;
  16. }

在运行程序时按空格键时会回到中心点,该中心点是面向包围球的圆心,如果不存在osgcool,那么按空格会把飞机置于场景中映,而有了osgcool飞机会被放置在左边。

结点开关

可以使用结点开关osg::Switch打开或关闭结点,在关闭时结点所占用的内存将被释放掉。

可以通过下面代码实现结点打开与关闭:

  1. # include <osgDB/ReadFile>
  2. # include <osgViewer/Viewer>
  3. # include <osg/Node>
  4. # include <osg/Switch>
  5. void main()
  6. {
  7. osgViewer::Viewer viewer;
  8. osg::Group * root = new osg::Group();
  9. osg::Switch * sw = new osg::Switch();
  10. osg::Node * osgcool = osgDB::readNodeFile("osgcool.osgt");
  11. sw->addChild(osgcool, false);
  12. sw->addChild(osgDB::readNodeFile("glider.osg"));
  13. root->addChild(sw);
  14. viewer.setSceneData(root);
  15. viewer.realize();
  16. viewer.run();
  17. }

由于osgcool模型根本不存在,所以glider模型置于场景中间。

超级指针

超级指针机制,其实就是引用一个计数器。引用一次加一,释放一次减一。当减至0时,内存释放。

使用结点的三种方法:

方法一(超级指针):

  1. osg::ref_ptr<osg::Node> node = new osg::Node();
  2. group->addChild(node.get());

这是最好的方法,十分安全,也是OSG中最常用的方法。在new osg::Node()时申请了一个Node的资源,这时在堆内引用该Node的计数器会被置1。在group->addChild(aNode.get())时又引用了一次,会再加1。在这两次引用都结束时,Node的资源就会被释放。

方法二:

  1. group->addChild(new osg::Node());

这个方法也是很实用的,但是无法引出Node的指针,也许在别处可以用到,事实上会经常用到。如果已经这样做了,得到Node指针也不是不可以的,可以使用NodeVisitor来得到Node的指针,也可以使用findChild方法来做这件事。

方法三:

  1. osg::Node * node = new osg::Node();
  2. 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))实现模型旋转。

可以通过下面的代码实现模型的移动、旋转、缩放:

  1. # include <osgDB/ReadFile>
  2. # include <osgViewer/Viewer>
  3. # include <osg/Node>
  4. # include <osg/MatrixTransform>
  5.  
  6. int main(void)
  7. {
  8. osgViewer::Viewer viewer;
  9. osg::ref_ptr<osg::Group> root = new osg::Group;
  10. osg::ref_ptr<osg::Node> osgcool = osgDB::readNodeFile("osgcool.osgt");
  11.  
  12. osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform;
  13. trans->setMatrix(osg::Matrix::translate(, , ));
  14. trans->addChild(osgcool.get());
  15.  
  16. osg::ref_ptr<osg::MatrixTransform> scale = new osg::MatrixTransform;
  17. scale->setMatrix(osg::Matrix::scale(0.5, 0.5, 0.5) * osg::Matrix::translate(, , -));
  18. scale->addChild(osgcool.get());
  19.  
  20. osg::ref_ptr<osg::MatrixTransform> rot = new osg::MatrixTransform;
  21. rot->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(45.0), , , ) * osg::Matrix::scale(0.5, 0.5, 0.5) * osg::Matrix::translate(, , -));
  22. rot->addChild(osgcool.get());
  23.  
  24. root->addChild(osgcool.get());
  25. root->addChild(trans.get());
  26. root->addChild(scale.get());
  27. root->addChild(rot);
  28.  
  29. viewer.setSceneData(root.get());
  30. viewer.realize();
  31. viewer.run();
  32. return ;
  33. }

在OSG中,坐标轴是可以设置的,默认向右的是X轴,向里的是Y轴,向上的是Z轴,与传统OPENGL坐标轴有所不同。

(全文完)

OSG模型简单控制的更多相关文章

  1. 关于OGRE与OSG的简单比较【转】

    关于OGRE与OSG的简单比较 林乃养 lnychina{at}gmail.com 浙江大学CAD&CG实验室 2010年3月27日 1 前言 我曾经细致阅读过OGRE和OSG官方提供的文档, ...

  2. 关于 OGRE 与 OSG 的简单比较 (转)

    关于 OGRE 与 OSG 的简单比较 1   前言 我曾经细致阅读过 OGRE 和 OSG 官方提供的文档,有<Pro OGRE 3D Programming>.OGRE自带手册(man ...

  3. 图像切割之(五)活动轮廓模型之Snake模型简单介绍

    图像切割之(五)活动轮廓模型之Snake模型简单介绍 zouxy09@qq.com http://blog.csdn.net/zouxy09 在"图像切割之(一)概述"中咱们简单了 ...

  4. Python+selenium测试环境成功搭建,简单控制浏览器(firefox)接下来,继续学习其他浏览器上的测试环境搭建;学习Python语言,利用Python语言来写测试用例。加油!!!

    Python+selenium测试环境成功搭建,简单控制浏览器(firefox)接下来,继续学习其他浏览器上的测试环境搭建:学习Python语言,利用Python语言来写测试用例.加油!!!

  5. Neo4j属性图模型简单介绍

    本文主要是对Neo4j属性图模型简单的介绍. Neo4j是什么? Neo4j是一款是由java语言实现的图数据库,图形数据库将数据以图的数据结构进行存储和管理,并且能够以高度可问的方式优雅地表示任何种 ...

  6. 转:关于 OGRE 与 OSG 的简单比较

    1   前言 我曾经细致阅读过 OGRE 和 OSG 官方提供的文档,有<Pro OGRE 3D Programming>.OGRE自带手册(manual).王锐老师等翻译的<Ope ...

  7. Unity模拟龙之谷人物行走简单控制

    我个人挺喜欢龙之谷(DN)的人物控制的(不是广告哈....),就是人物太萌了一点,动作.打击感都挺好的. 今天用Unity简单模仿了一下DN的人物控制,当然,游戏里面动作非常多,我这里仅仅做了简单的w ...

  8. [原]osg模型动画|骨骼动画

    参考源码:osg的官方例子:osganimationviewer 首先制作一个带骨骼动画的模型  demo.FBX 这里面我们做了两个骨骼动画:1.open   2.close 下面开始在osg中使用 ...

  9. SharePoint2010 -- ECMAScript客户端模型简单示例

    ECMAScript客户端模型,是SharePoint2010推出的三种客户端模型".NET托管"."ECMAScript"."Sliverlight ...

随机推荐

  1. <转>删除文件夹下所有的.svn文件

    当使用了svn版本控制系统后每个目录下都会有一个.svn目录存在,开发完当交付产品或者上传到服务器时一般要把这些目录删除,这里总结了一下在linux和win下的办法. 一.在linux下 删除这些目录 ...

  2. phpcms-v9系统搭建wap网站及单页面

    如需要绑定域名为wap.domain.com,作下如操作: 一.把wap.domain.com域名绑定到你的这个网站主机上. 二.在网站后台——模块——手机门户域名里面填写“http://wap.do ...

  3. PMP 第十三章 项目干系人管理

    1.识别干系人是干什么?早期就识别干系人的原因是什么?识别干系人的输入和工具有哪些?干系人分析的几种模型是哪些?干系人登记册的内容有哪些?bbs.mypm.net 2.干系人参与程度的分类是怎样的?干 ...

  4. [荐]js模版引擎handlebars.js

    [官方介绍:http://handlebarsjs.com/] Handlebars provides the power necessary to let you build semantic te ...

  5. 湖南省第十二届大学生计算机程序设计竞赛 A 2016

    1803: 2016 Description  给出正整数 n 和 m,统计满足以下条件的正整数对 (a,b) 的数量:   1. 1≤a≤n,1≤b≤m; 2. a×b 是 2016 的倍数. In ...

  6. HDU 3461 Code Lock(并查集)

    很好的一个题,思想特别6 题意:给你小写字母个数n,每个字母可以向上翻动,例如:d->c,a->z.然后给你m对数(L,R)(L<=R),表示[L,R]之间可以同时向上翻动,且翻动后 ...

  7. SU Demos-06Selecting Traces

    不足之处,欢迎批评指正 共3个脚本,先看readme 第1个脚本 运行结果 第2个脚本 运行结果 第3个脚本 运行结果

  8. 门店 车销 批发送货 商超 快销专用扫描打印开单手持PDA移动销售管理系统

    门店 车销 批发送货 商超 快销专用扫描打印开单手持PDA移动销售管理系统的详细介绍 一. 以PDA等移动终端为媒介,随时随地掌握门店信息. 二. 后台集成了数据统计.多指标分析.销售.库存.会员管理 ...

  9. AngularJS 包含HTML文件

    类似于python tornado的include方法,同样是可以在一个html文件中加载另外一个html文件,这样可以不用重复的写一些几乎不改变的代码. 首先创建两个文件,然后代码如下: <! ...

  10. jquery(ajax)与js(ajax)的比较

    原始js: function update_mess(){ var account_name = $("#account").val(); var xmlhttp; if(wind ...