查看: 6246|回复: 6

关于osgart播放FBX骨骼动画的问题

[复制链接]

该用户从未签到

发表于 2012-10-1 20:45:44 | 显示全部楼层 |阅读模式
本帖最后由 wujita01 于 2012-10-1 20:45 编辑

先祝大家中秋国庆双喜临门~~不知道还有没有人来回答,呵呵。

接下来说说我在用osgart播放FBX骨骼动画中遇到的问题,希望能和大家一起探讨下。

OSG里面可以用osgAnimation::BasicAnimationManager来控制骨骼动画播放,停止。这在osganimationviewer里面有很好的实例。

1.首先是我使用这个例子的过程中,如果1个动画有多个Take动画,例如我播放一个动画Take 001的时候,再播放Take 002,我们得到的事实是Take 002 播放是不正常的;但是如果我在播放Take 001的时候,按了Stop,再播放Take 002,那么我们会得到正常的动画效果。播放动画的时候只能先stop正在播放的动画吗,还是需要我们设置BasicAnimationManager来打到我所预期的效果吗。请指点下。

2.第二个问题是我在解读osganimationviewer的时候遇到的。我想也是我没有钻研FBX模型结构导致的。不过还是希望知道的朋友能帮我解答下。
  1. osg::Group* node = new osg::Group();
  2. node = dynamic_cast<osg::Group*>(osgDB::readNodeFile("zero.fbx"));
复制代码
osganimationviewer里面是这样加载FBX模型的.我把他换成ProxyNode后,一点播放就报错。我搞不懂FBX动画模型为什么用Group装载,是因为他把这个骨骼模型的每个节点都加载在这个Group节点下面形成一个模型树(姑且这么称呼他,呵呵)了吗。
3.而我在使用osgart想来加载FBX模型时,因此产生了一系列问题。因为osgart的示范例子是用这样的模型节点来加载的。
  1. _root(Group)->_camera(Camera)->_mat(MatrixTransform)
  2. ->_pat((PositionAttitudeTransform)->_model(ProxyNode)
复制代码
->指向的是该节点的孩子,括号里面的是该节点的类型。我们可以发现这里的模型节点是ProxyNode的。因为ProxyNode是继承Group的。我首先想到的就是直接添加访问器NodeVisitor来进行模型动画的控制。这是自定义的NodeVisitor,依样画葫芦写的。
  1. class INodeVisitor: public osg::NodeVisitor
  2. {
  3. public:
  4.         osg::ref_ptr<osgAnimation::BasicAnimationManager> _bam;
  5.         INodeVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){}
  6.         void apply(osg::Node& node){
  7.                 if (_bam.valid())
  8.                         return;
  9.                 if (node.getUpdateCallback()){
  10.                         osgAnimation::AnimationManagerBase* b = dynamic_cast<osgAnimation::AnimationManagerBase*>(node.getUpdateCallback());
  11.                         if (b) {
  12.                                 _bam = new osgAnimation::BasicAnimationManager(*b);
  13.                                 return;
  14.                         }
  15.                 }
  16.                 traverse(node);
  17.         }
  18. };
复制代码


并通过以下代码来进行对节点的访问。
  1. proxynode->accept(finder);
  2.                                 if (finder._bam.valid()) {
  3.                                         proxynode->setUpdateCallback(finder._bam.get());
  4.                                                 _model->setUpdateCallback(finder._bam.get());
  5.                                                 IModelControl::setModel(finder._bam.get());
  6.                                         } else {
  7.                                                 osg::notify(osg::WARN) << "no osgAnimation::AnimationManagerBase found in the subgraph, no animations available" << std::endl;
  8.                                         }
复制代码


但是事与愿违,把模型加载到ProxyNode下以后,
  1. finder._bam.valid()
复制代码
返回的是false,也就是里面没有找到osgAnimation::BasicAnimationManager的相关东西。
所以我想虽然ProxyNode是继承于Group的,但是可能不适合于FBX加载骨骼动画模型。
于是我决定是把他换成Group节点来加载FBX模型,进而达到控制动画的目的。
可是天不如人意,当我改成把osgart里面的ProxyNode节点改成Group节点以后模型无法显示。
我有以下几个猜想
1.模型显示了。但是没有在摄像头前面
2.Callback里面没有写Group节点类的显示和隐藏。
这是显示隐藏的UpdateCallback

  1. void MarkerVisibilityCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
  2. {
  3.         if (osg::Switch* _switch = dynamic_cast<osg::Switch*>(node))
  4.         {
  5.                 // Handle visibilty for switch nodes
  6.         //        ::printf("%s",v_marker->valid() ? "Show" : "Hide");
  7.                 _switch->setSingleChildOn(v_marker->valid() ? 0 : 1);       
  8.         }
  9.         else
  10.         {

  11.                 // This method will work for any node.

  12.                 // Make sure the visitor will return to invisible nodes
  13.                 // If we make this node invisible (because the marker is hidden) then
  14.                 // we need to be able to return and update it later, or it will remain
  15.                 // hidden forever.
  16.                 nv->setNodeMaskOverride(0xFFFFFFFF);
  17.         //        ::printf("Marker Available: %s\n",v_marker->valid() ? "Show" : "Hide");
  18.                 node->setNodeMask(v_marker->valid() ? 0xFFFFFFFF : 0x0);
  19.         }

  20.         // must traverse the Node's subgraph            
  21.         traverse(node,nv);

  22. }
复制代码
其实这里我很乱的。因为OSG也是最近入手,只是看了锐哥,肖鹏等大神的PDF书,还没完全实战。这里的问题希望大家能帮忙解决下。在osgart用Group节点怎么加载FBX模型并显示呢。(其实这个才是这堆问题要解决的根本)

我在解决这个问题的过程中发现一个很奇怪的问题。上面提到过这个程序的节点形式是这样的
  1. _root(Group)->_camera(Camera)->_mat(MatrixTransform)
  2. ->_pat((PositionAttitudeTransform)->_model(ProxyNode)
复制代码
该程序还在_mat添加了MarkerTransformCallback。他的作用是这样的

  1. void MarkerTransformCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
  2. {
  3.         if (osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(node)) {
  4.                 mt->setMatrix(_marker->getTransform());
  5.         }

  6.         // Handler for osg::PositionAttitudeTransforms
  7.         // TODO: check correct translation/rotation order
  8.         else if (osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>(node)) {
  9.                 pat->setPosition(_marker->getTransform().getTrans());
  10.                 osg::Vec3d vd = _marker->getTransform().getTrans();
  11.                 pat->setAttitude(_marker->getTransform().getRotate());
  12.         }

  13.         // Traverse the Node's subgraph
  14.         traverse(node,nv);
  15. }
复制代码
我在测试中发现else if后面的PositionAttitudeTransform是永远执行不到的。在节点树下面有PositionAttitudeTransform 的节点traverse(node,nv);后应该是能访问到的。为什么执行不了呢。我想这会是很大可能无法显示模型的原因吧、猜想他显示到其他我们不可见的地方去了。


希望大家能帮我想想什么可能性,OSG入门刚不久,懂的还不多。希望能受到大家的指点。有颜色标记的地方希望大家能尽可能回答下。其实,写这么多,更是希望也在做同样事情的同学们能够说说遇到的问题已经怎么解决的。在此先感谢大家帮忙了。{:3_64:}

该用户从未签到

发表于 2012-10-8 10:10:53 | 显示全部楼层
1、动画的效果会融混,因此您需要停止第一个以免它和第二个动画产生混合的作用
2、您没有理解dynamic_cast的意义,不是新建而是动态类型转换,如果文件中的根节点不是指定的类型,那么不可能转换成功。您之前的new操作在这里没有意义
3、我不知道您在做什么,很显然osgART和ProxyNode没有必然联系,需要加入模型时只要简单地addChild就可以了

该用户从未签到

 楼主| 发表于 2012-10-9 23:26:31 | 显示全部楼层
array 发表于 2012-10-8 10:10
1、动画的效果会融混,因此您需要停止第一个以免它和第二个动画产生混合的作用
2、您没有理解dynamic_cast ...

感谢Array大哥的回复。您的这些意见都很有用。上面的问题基本已经解决了。

该用户从未签到

发表于 2012-10-10 10:49:04 | 显示全部楼层
您好,请问您是否实现了各个动画的连续播放,而不是每次点一个播放一个?有方法的话还望不吝赐教,先谢过

该用户从未签到

 楼主| 发表于 2012-10-10 13:44:05 | 显示全部楼层
红果儿 发表于 2012-10-10 10:49
您好,请问您是否实现了各个动画的连续播放,而不是每次点一个播放一个?有方法的话还望不吝赐教,先谢过

没有实现连续播放呢。您这样一问的话说起来好像不能设置播放模型呀。如果能设置播放模型的话让他只播放一次。在播放结束后
就可以判断isPlaying() = false了。那就可以继续播放下个动画了。不过我刚才看了下没有setMode类似的函数。我刚学OSG,对各个类的函数都不是很了解。只能说说我的想法了。希望能帮到你。

该用户从未签到

发表于 2012-10-10 18:32:23 | 显示全部楼层
wujita01 发表于 2012-10-10 13:44
没有实现连续播放呢。您这样一问的话说起来好像不能设置播放模型呀。如果能设置播放模型的话让他只播放一 ...

首先谢谢您。我也新手……。可以设置AnimationList中每一个动画的palyMode(),但是现在osganimationviewer只是场景添加事件处理后按下键盘播放键才播放,我想实现设置每个动画播放模式为ONCE后,打开场景时各动画自动按顺序播放?场景在什么地方怎么控制?这个比较郁闷……如果您有好的思路还望分享一下哈

该用户从未签到

 楼主| 发表于 2012-10-11 22:17:49 | 显示全部楼层
红果儿 发表于 2012-10-10 18:32
首先谢谢您。我也新手……。可以设置AnimationList中每一个动画的palyMode(),但是现在osganimationviewer ...

这个您只要在您需要控制的节点上Node->setUpdateCallback(new XXX());在XXX()的Callback函数里面的写您播放动画的代码就行了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表