From Michael Platings,
- Animations with equal priority are now weighted correctly relative to each other - (minor) Channels no longer store their weight as the only time it's used is in update() when Animation can pass in the weight directly From Cedric Pinson, - I adjusted the quaternion blending to keep the commutativy property
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
* 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; }
|
||||
|
||||
@@ -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();}
|
||||
|
||||
@@ -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 <class T>
|
||||
inline void TemplateTarget<T>::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 <class T>
|
||||
inline void TemplateTarget<T>::lerp(float t, const T& a, const T& b)
|
||||
{
|
||||
_target = a * (1.0f - t) + b * t;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void TemplateTarget<osg::Quat>::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<osg::Quat>::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<osg::Quat> QuatTarget;
|
||||
typedef TemplateTarget<osg::Vec3> Vec3Target;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
* 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<int> 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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
* 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 <osgAnimation/Channel>
|
||||
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;}
|
||||
|
||||
|
||||
@@ -202,7 +202,9 @@ void MorphGeometry::transformSoftwareMethod()
|
||||
}
|
||||
}
|
||||
|
||||
UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) : AnimationUpdateCallback<osg::NodeCallback>(apc, copyop)
|
||||
UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) :
|
||||
osg::Object(apc, copyop),
|
||||
AnimationUpdateCallback<osg::NodeCallback>(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;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
* 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() {}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user