osgExample - osgAnimationMorph

来源:互联网 发布:php表达式去除a标签 编辑:程序博客网 时间:2024/06/05 17:44

例子代码

这个例子只分析一下流程,共三个步骤:

数据绑定

就是将要改变的数据与更新对象绑定起来,由更新对象负责“如何去改变数据”。
这个操作是在AnimationManagerBase第一次被回调的时候发生的。

  1. BasicAnimationManager调用operator()
  2. 调用link(),将UpdateMorph与所有的Animation连接起来
  3. link函数中用LinkVisitor遍历所有AnimationUpdateCallback,在咱们这个例子里那就是UpdateMorph
  4. link(Channel*)中,会把TargetName对上的Channel挑出来,调用它的setTarget,从而将UpdateMorph里需要动态改变的值交给Channel

看着很深,其实代码却很简单,没几行,就不详细解释了。

跟这个步骤相关的有一个小地方值得提一下,就是例子代码里的这句:

channel0->setName("0");

它到底是干什么的呢?答案就在UpdateMorph::update里面:

bool UpdateMorph::link(osgAnimation::Channel* channel){    // Typically morph geometries only have the weights for morph targets animated    std::istringstream iss(channel->getName());    int weightIndex;    iss >> weightIndex;    if (iss.fail())    {        return false;    }    if (weightIndex >= 0)    {        osgAnimation::FloatTarget* ft = _weightTargets[weightIndex].get();        if (!ft)        {            ft = new osgAnimation::FloatTarget;            _weightTargets[weightIndex] = ft;        }        return channel->setTarget(ft);    }    else    {        OSG_WARN << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << std::endl;    }    return false;}

看到了么,那个“0”是作为索引用的。其实我觉得这里直接用string作为索引也不是不可以啊^_^ 也许字符串作为键的搜索效率不如int吧,哈哈。

数据更新

  1. AnimationManagerBase::operator()里调用update()
  2. 遍历所有的Animation,调用它们的update(),如果已经更新完事了,那就把它从Animation列表中去掉(保证不再重新更新)
  3. Animation中会根据自己的播放类型(单次,循环,来回……)算出一个时间,遍历所有的Channel::update(),把时间值传给Channel
  4. 在Channel的update会根据时间算出一个插值结果,并将它设到Target中

注意这里提到了Target,没错!它就是数据绑定中绑在UpdateMorph里的那个值。

到这儿就完成了UpdateMorph的数据更新。

模型更新

UpdateMorph::operator()虽然代码一大坨,但只干了一件事:setWeight。也就是将之前得到的插值值作为权值设到MorphGeometry里。
跳到MorphGeometry里,会发现一个函数特别长:transformSoftwareMethod,没错,它才是这个例子的重点。

先解释一下程序是怎么调用到这个函数的,其实也很简单,osg又利用了UpdateCallback机制完成了这个调用。

  1. 定义一个回调类:MorphGeometry::UpdateVertex
  2. 构造函数中将这个类设为回调类:setUpdateCallback(new UpdateVertex)
  3. 回调类的update函数再调用transformSoftwareMethod

函数看着很长很长(100多行呢。。),但其实只实现了一个公式:

    result = src * (1-weight) + dst * weight;

然后……好像就没啥然后了……整个流程到这儿就完结了。

0 0
原创粉丝点击