osg示例解析之osganimationmorph(1)

来源:互联网 发布:java double 舍入误差 编辑:程序博客网 时间:2024/05/18 16:18

本课主要演示了osgAnimation中的变形动画,变形动画通常也称为逐顶点动画(Per-vertex Animation),是一种三维动画的表现形式。它对计算机的运算资源的消耗很大,通常以每帧计算和应用4000~9000个顶点的位置变化为宜,否则系统难以承受其他场景对象的更新和渲染工作。变形动画在osgAnimation中通过MorphGeometry以及UpdateMorph来实现,具体的实现可以参考我的另一篇文章osgAnimation之作用对象中的相关介绍。

  • 示例

该例子首先实现了一个NodeVisitor,用来寻找Geode节点中的Geometry对象:

[cpp] view plain copy
  1. struct GeometryFinder : public osg::NodeVisitor  
  2. {  
  3.     osg::ref_ptr<osg::Geometry> _geom;  
  4.     GeometryFinder() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}  
  5.     void apply(osg::Geode& geode)   
  6.     {  
  7.         if (_geom.valid())  
  8.             return;  
  9.         for (unsigned int i = 0; i < geode.getNumDrawables(); i++)   
  10.         {  
  11.             osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode.getDrawable(i));  
  12.             if (geom) {  
  13.                 _geom = geom;  
  14.                 return;  
  15.             }  
  16.         }  
  17.     }  
  18. };  
它会保存Geode中的第一个Geometry节点,之后的函数用到了这个访问器

[cpp] view plain copy
  1. osg::ref_ptr<osg::Geometry> getShape(const std::string& name)  
  2. {  
  3.     osg::ref_ptr<osg::Node> shape0 = osgDB::readNodeFile(name);  
  4.     if (shape0)  
  5.     {  
  6.         GeometryFinder finder;  
  7.         shape0->accept(finder);  
  8.         return finder._geom;  
  9.     }  
  10.     else  
  11.     {  
  12.         return NULL;  
  13.     }  
  14. }  
返回文件name中第一个的Geometry节点

下面我们看看主函数中的实现过程,应该来说还是比较清晰的:

  • 首先创建频道

[cpp] view plain copy
  1. osgAnimation::Animation* animation = new osgAnimation::Animation;  
  2. osgAnimation::FloatLinearChannel* channel0 = new osgAnimation::FloatLinearChannel;  
  3. channel0->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(0,0.0));  
  4. channel0->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(1,1.0));  
  5. channel0->setTargetName("MorphNodeCallback");  
  6. channel0->setName("0");  
这里需要注意频道的Name要设置为0、1、2这样的非负整数字符串,让它们和添加到MorphGeometry中的geometry对象对应。此外channel的targetname要和UpdateMorph的名称一样,这样在链接的时候才能成功。关于频道的设置就这两点需要注意

  • 其次创建动画和动画管理器

[cpp] view plain copy
  1. animation->addChannel(channel0);  
  2. animation->setName("Morph");  
  3. animation->computeDuration();  
  4. animation->setPlayMode(osgAnimation::Animation::PPONG);  
  5. osgAnimation::BasicAnimationManager* bam = new osgAnimation::BasicAnimationManager;  
  6. bam->registerAnimation(animation);  
动画对象将频道添加到它里面,动画管理器一样还是需要在Geode节点之上(是Geode的父节点),也就是保证进入UpdateMorph回调之前先进入动画管理器这个回调中

  • 再次 创建需要变形的几何体和目标几何体

[cpp] view plain copy
  1.  osg::ref_ptr<osg::Geometry> geom0 = getShape("morphtarget_shape0.osg");  
  2.  if (!geom0) {  
  3.      std::cerr << "can't read morphtarget_shape0.osg" << std::endl;  
  4.      return 0;  
  5.  }  
  6.   
  7.  osg::ref_ptr<osg::Geometry> geom1 = getShape("morphtarget_shape1.osg");  
  8.  if (!geom1) {  
  9.      std::cerr << "can't read morphtarget_shape1.osg" << std::endl;  
  10.      return 0;  
  11.  }  
  12.   
  13.  //原始形状  
  14.  osgAnimation::MorphGeometry* morph = new osgAnimation::MorphGeometry(*geom0);  
  15. //需要变形的形状添加到morph之中,可以是多个,结果将按权重加成  
  16.  morph->addMorphTarget(geom1.get());  

  • 最后 将UpdateMorph添加到Geode之中

[cpp] view plain copy
  1. osg::Geode* geode = new osg::Geode;  
  2. geode->addDrawable(morph);  
  3. geode->addUpdateCallback(new osgAnimation::UpdateMorph("MorphNodeCallback"));  

这样保证在进入MorphGeometry的Drawable更新回调之前先进入Geode的回调中更新几何体的权值,保证后续顶点的计算用到频道里面最新插值出的权值。

运行结果:



写在后面:在后续的osgNeHe课程中Lesson25会根据顶点进行变形,可以参考本课的实现利用osgAnimation库来实现,在实现过程中我遇到以下的问题:

当绘制的几何体为osg::PrimitiveSet::POINTS时程序会崩溃,描述和osgChina中的帖子类似。后来经过查看发现是由于没有NormalArray导致的问题,解决方法是申请一个法线向量的数组,随便设置一下添加到Geometry就可以解决这个问题了。这可能是osgAnimation代码中的一个Bug,osgAnimation要求必须有NormalArray。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买灯具哪个网站好 家用灯具什么牌子好 中式灯具效果图 中式灯具图片 中山灯具批发市场 led照明灯具批发 节能照明灯具 灯具维修电话 集成吊顶灯具批发 北京买灯具去哪里 水晶灯具批发 创意灯具设计 什么灯具比较好 工厂led照明灯具 阳光led照明灯具 哪个牌子的灯具好 网球场照明灯具 施工照明灯具 买灯具去哪里买 灯饰图片及价格 灯饰店招商 led照明灯饰 买灯 灯饰大全 书柜衣柜一体效果图大全 电脑桌带书柜效果图 图片玄关 转角书桌书柜效果图 书橱图片 家具摆放效果图 二手书架书柜 整体书柜效果图 写字台书柜组合 墙上书架造型效果图 小书柜效果图 转角书柜效果图 转角电脑桌带书柜图片 卧室书架效果图 中山灯饰 灯头 灯饰网