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:
Cedric Pinson
2009-08-26 09:24:02 +00:00
parent c56dd6faa5
commit 3c45fb1e6c
9 changed files with 92 additions and 83 deletions

View File

@@ -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; }

View File

@@ -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();}

View File

@@ -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;