diff --git a/include/osgAnimation/Animation b/include/osgAnimation/Animation index 01e25a233..2d50372b8 100644 --- a/include/osgAnimation/Animation +++ b/include/osgAnimation/Animation @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -71,7 +71,7 @@ namespace osgAnimation void setWeight (float weight); float getWeight() const; - bool update (float time); + bool update (float time, int priority = 0); void resetTargets(); void setPlaymode (PlayMode mode) { _playmode = mode; } diff --git a/include/osgAnimation/Channel b/include/osgAnimation/Channel index d0be95dca..61c955685 100644 --- a/include/osgAnimation/Channel +++ b/include/osgAnimation/Channel @@ -37,7 +37,7 @@ namespace osgAnimation virtual ~Channel(); virtual Channel* clone() const = 0; - virtual void update(float time) = 0; + virtual void update(float time, float weight, int priority) = 0; virtual void reset() = 0; virtual Target* getTarget() = 0; virtual bool setTarget(Target*) = 0; @@ -51,9 +51,6 @@ namespace osgAnimation const std::string& getTargetName() const; void setTargetName(const std::string& name); - float getWeight() const; - void setWeight(float w); - virtual Sampler* getSampler() = 0; virtual const Sampler* getSampler() const = 0; @@ -61,7 +58,6 @@ namespace osgAnimation std::string _targetName; std::string _name; - float _weight; }; @@ -92,14 +88,14 @@ namespace osgAnimation } virtual ~TemplateChannel() {} - virtual void update(float time) + virtual void update(float time, float weight, int priority) { // skip if weight == 0 - if (_weight < 1e-4) + if (weight < 1e-4) return; typename SamplerType::UsingType value; _sampler->getValueAt(time, value); - _target->update(_weight, value); + _target->update(weight, value, priority); } virtual void reset() { _target->reset(); } virtual Target* getTarget() { return _target.get();} diff --git a/include/osgAnimation/Target b/include/osgAnimation/Target index b12e20737..832277de7 100644 --- a/include/osgAnimation/Target +++ b/include/osgAnimation/Target @@ -36,13 +36,13 @@ namespace osgAnimation Target(); virtual ~Target(); virtual void normalize() = 0; - float getWeight() const { return _weight; } - void reset() { _weight = 0;} + void reset() { _weight = 0; _priorityWeight = 0; } int getCount() const { return referenceCount(); } + float getWeight() const { return _weight; } protected: - - void addWeight(float w) { _weight += w; } float _weight; + float _priorityWeight; + int _lastPriority; }; @@ -54,72 +54,87 @@ namespace osgAnimation TemplateTarget() {} TemplateTarget(const T& v) { setValue(v); } - void update(float weight, const T& val) + inline void lerp(float t, const T& a, const T& b); + + /** + * The priority is used to detect a change of priority + * It's important to update animation target in priority + * order. eg: + * all animation with priority 1 + * all animation with priority 0 + * all animation with priority -1 + * ... + */ + void update(float weight, const T& val, int priority) { - if (!_weight) - _target = val * weight; + if (_weight || _priorityWeight) + { + if (_lastPriority != priority) + { + // change in priority + // add to weight with the same previous priority cumulated weight + _weight += _priorityWeight * (1.0 - _weight); + _priorityWeight = 0; + _lastPriority = priority; + } + + _priorityWeight += weight; + float t = (1.0 - _weight) * weight / _priorityWeight; + lerp(t, _target, val); + } else { - weight = (1.0 - _weight) * weight; - _target += val * weight; + _priorityWeight = weight; + _lastPriority = priority; + _target = val; } - addWeight(weight); } - const T& getValue() const { return _target;} + const T& getValue() const { return _target; } - void normalize() - { - float weightSummed = getWeight(); - if (fabs(weightSummed) < 1e-4 || fabs(weightSummed-1) < 1e-4) - return; - (_target) /= weightSummed; - } + inline void normalize(); - void setValue(const T& value) { _target = value;} + void setValue(const T& value) { _target = value; } protected: T _target; }; - - // Target Specialisation for Quaternions - template <> - class TemplateTarget< osg::Quat > : public Target + template + inline void TemplateTarget::normalize() { - public: - - TemplateTarget () {} - TemplateTarget (const osg::Quat& q) { setValue(q); } + _weight += _priorityWeight * (1.0f - _weight); + if (_weight < 0.9999f ) + if (_weight > 0.0001f) + _target /= _weight; // rescale by default + } - const osg::Quat& getValue() const { return _target;} - void update(float weight, const osg::Quat& val) - { - if (!_weight) - _target = val * weight; - else + template + inline void TemplateTarget::lerp(float t, const T& a, const T& b) + { + _target = a * (1.0f - t) + b * t; + } + + template <> + inline void TemplateTarget::lerp(float t, const osg::Quat& a, const osg::Quat& b) + { + _target = a * (1.0f - t) + b * t; + osg::Quat::value_type len2 = _target.length2(); + if ( len2 != 1.0 && len2 != 0.0) + _target *= 1.0/sqrt(len2); + } + template <> + inline void TemplateTarget::normalize() + { + _weight += _priorityWeight * (1.0f - _weight); + if (_weight < 0.9999f ) + if (_weight > 0.0001f) { - weight = (1.0 - _weight) * weight; - _target += val * weight; + osg::Quat::value_type len2 = _target.length2(); // normalize + if ( len2 != 1.0 && len2 != 0.0) + _target *= 1.0/sqrt(len2); } - addWeight(weight); - } - - // maybe normalize could be non virtual and put on ITarget - void normalize() - { - float weightSummed = getWeight(); - if (fabs(weightSummed) < 1e-4 || fabs(weightSummed-1.0) < 1e-4) - return; - (_target) /= weightSummed; - } - - void setValue(const osg::Quat& value) { _target = value;} - - protected: - - osg::Quat _target; - }; + } typedef TemplateTarget QuatTarget; typedef TemplateTarget Vec3Target; diff --git a/src/osgAnimation/Animation.cpp b/src/osgAnimation/Animation.cpp index 4d24d71f7..3f353aa4a 100644 --- a/src/osgAnimation/Animation.cpp +++ b/src/osgAnimation/Animation.cpp @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -95,7 +95,7 @@ void Animation::setWeight (float weight) _weight = weight; } -bool Animation::update (float time) +bool Animation::update (float time, int priority) { if (!_duration) // if not initialized then do it computeDuration(); @@ -138,8 +138,7 @@ bool Animation::update (float time) ChannelList::const_iterator chan; for( chan=_channels.begin(); chan!=_channels.end(); ++chan) { - (*chan)->setWeight(_weight); - (*chan)->update(t); + (*chan)->update(t, _weight, priority); } return true; } diff --git a/src/osgAnimation/BasicAnimationManager.cpp b/src/osgAnimation/BasicAnimationManager.cpp index 95b821354..5648531f4 100644 --- a/src/osgAnimation/BasicAnimationManager.cpp +++ b/src/osgAnimation/BasicAnimationManager.cpp @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -90,10 +90,11 @@ void BasicAnimationManager::update (double time) { // update all animation std::vector toremove; + int priority = iterAnim->first; AnimationList& list = iterAnim->second; for (unsigned int i = 0; i < list.size(); i++) { - if (! list[i]->update(time)) + if (! list[i]->update(time, priority)) { // debug // std::cout << list[i]->getName() << " finished at " << time << std::endl; diff --git a/src/osgAnimation/Channel.cpp b/src/osgAnimation/Channel.cpp index cdfb80577..ad2de93f4 100644 --- a/src/osgAnimation/Channel.cpp +++ b/src/osgAnimation/Channel.cpp @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -15,12 +15,11 @@ #include using namespace osgAnimation; -Channel::Channel() { _weight=1; } +Channel::Channel() {} Channel::~Channel() {} Channel::Channel(const Channel& channel) : osg::Referenced(channel), _targetName(channel._targetName), - _name(channel._name), - _weight(channel._weight) + _name(channel._name) { } @@ -29,7 +28,3 @@ void Channel::setName (const std::string& name) { _name = name; } const std::string& Channel::getTargetName() const { return _targetName;} void Channel::setTargetName (const std::string& name) { _targetName = name; } - -float Channel::getWeight() const { return _weight;} -void Channel::setWeight(float w) { _weight = w;} - diff --git a/src/osgAnimation/MorphGeometry.cpp b/src/osgAnimation/MorphGeometry.cpp index 4ff244008..934661abc 100644 --- a/src/osgAnimation/MorphGeometry.cpp +++ b/src/osgAnimation/MorphGeometry.cpp @@ -202,7 +202,9 @@ void MorphGeometry::transformSoftwareMethod() } } -UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) : AnimationUpdateCallback(apc, copyop) +UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) : + osg::Object(apc, copyop), + AnimationUpdateCallback(apc, copyop) { } @@ -271,7 +273,7 @@ bool UpdateMorph::link(osgAnimation::Channel* channel) } else { - std::cerr << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << std::endl; + osg::notify(osg::WARN) << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << std::endl; } return false; } diff --git a/src/osgAnimation/Target.cpp b/src/osgAnimation/Target.cpp index 7bb2da215..8afb99ff0 100644 --- a/src/osgAnimation/Target.cpp +++ b/src/osgAnimation/Target.cpp @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -18,5 +18,5 @@ using namespace osgAnimation; -Target::Target() { reset();} +Target::Target() : _weight(0), _priorityWeight(0), _lastPriority(0) {} Target::~Target() {} diff --git a/src/osgPlugins/osgAnimation/ReaderWriter.cpp b/src/osgPlugins/osgAnimation/ReaderWriter.cpp index 39dbc698f..2dffc5522 100644 --- a/src/osgPlugins/osgAnimation/ReaderWriter.cpp +++ b/src/osgPlugins/osgAnimation/ReaderWriter.cpp @@ -146,6 +146,7 @@ bool Animation_readChannel(osgAnimation::Channel* pChannel, Input& fr) } pChannel->setTargetName(target); +// we dont need this info float weight = 1.0; if (fr.matchSequence("weight %f")) { @@ -153,7 +154,7 @@ bool Animation_readChannel(osgAnimation::Channel* pChannel, Input& fr) fr += 2; iteratorAdvanced = true; } - pChannel->setWeight(weight); +// pChannel->setWeight(weight); return iteratorAdvanced; } @@ -546,7 +547,7 @@ void Animation_writeChannel(const std::string& channelString, ChannelType* pChan fw.indent() << "name \"" << pChannel->getName() << "\"" << std::endl; fw.indent() << "target \"" << pChannel->getTargetName() << "\"" << std::endl; - fw.indent() << "weight " << pChannel->getWeight() << std::endl; +// fw.indent() << "weight " << pChannel->getWeight() << std::endl; ContainerType* kfc = pChannel->getSamplerTyped()->getKeyframeContainerTyped(); if (kfc)