From Cedric Pinson, Pulled in osgAnimation from OpenSceneGraph-osgWidget-dev into svn/trunk.
This commit is contained in:
103
include/osgAnimation/Animation
Normal file
103
include/osgAnimation/Animation
Normal file
@@ -0,0 +1,103 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ANIMATION_H
|
||||
#define OSGANIMATION_ANIMATION_H
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Channel>
|
||||
#include <osg/ref_ptr>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT Animation : public virtual osg::Object
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, Animation)
|
||||
|
||||
Animation() : _duration(0), _weight(0), _startTime(0), _playmode(LOOP) {}
|
||||
Animation(const osgAnimation::Animation& anim, const osg::CopyOp&);
|
||||
|
||||
enum PlayMode
|
||||
{
|
||||
ONCE,
|
||||
STAY,
|
||||
LOOP,
|
||||
PPONG
|
||||
};
|
||||
|
||||
// addChannel insert the channel and call the computeDuration function
|
||||
void addChannel (Channel* pChannel);
|
||||
|
||||
/** Those accessors let you add and remove channels
|
||||
* if you modify something that can change the duration
|
||||
* you are supposed to call computeDuration or setDuration
|
||||
*/
|
||||
ChannelList& getChannels();
|
||||
const ChannelList& getChannels() const;
|
||||
|
||||
/** Change the duration of animation
|
||||
* then evaluate the animation in the range 0-duration
|
||||
* it stretch the animation in time.
|
||||
* see computeDuration too
|
||||
*/
|
||||
void setDuration(double duration);
|
||||
|
||||
|
||||
/** Compute duration from channel and keyframes
|
||||
* if the duration is not specified you should
|
||||
* call this method before using it
|
||||
*/
|
||||
void computeDuration();
|
||||
|
||||
float getDuration() const;
|
||||
|
||||
|
||||
void setWeight (float weight);
|
||||
float getWeight() const;
|
||||
|
||||
bool update (float time);
|
||||
void resetTargets();
|
||||
|
||||
void setPlaymode (PlayMode mode) { _playmode = mode; }
|
||||
void setStartTime(float time) { _startTime = time;}
|
||||
float getStartTime() const { return _startTime;}
|
||||
|
||||
protected:
|
||||
|
||||
double computeDurationFromChannels() const;
|
||||
|
||||
~Animation() {}
|
||||
|
||||
std::string _name;
|
||||
double _duration;
|
||||
double _originalDuration;
|
||||
float _weight;
|
||||
float _startTime;
|
||||
PlayMode _playmode;
|
||||
ChannelList _channels;
|
||||
|
||||
};
|
||||
|
||||
typedef std::vector<osg::ref_ptr<osgAnimation::Animation> > AnimationList;
|
||||
typedef std::map<std::string, osg::ref_ptr<osgAnimation::Animation> > AnimationMap;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
58
include/osgAnimation/AnimationManager
Normal file
58
include/osgAnimation/AnimationManager
Normal file
@@ -0,0 +1,58 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ANIMATION_MANAGER_H
|
||||
#define OSGANIMATION_ANIMATION_MANAGER_H
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/FrameStamp>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT AnimationManager : public AnimationManagerBase
|
||||
{
|
||||
public:
|
||||
|
||||
META_Node(osgAnimation, AnimationManager);
|
||||
|
||||
AnimationManager();
|
||||
AnimationManager(const AnimationManager& b, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) :
|
||||
AnimationManagerBase(b,copyop) {}
|
||||
virtual ~AnimationManager();
|
||||
|
||||
void update (double time);
|
||||
|
||||
void playAnimation (Animation* pAnimation, int priority = 0, float weight = 1.0);
|
||||
bool stopAnimation (Animation* pAnimation);
|
||||
|
||||
bool findAnimation (Animation* pAnimation);
|
||||
bool isPlaying (Animation* pAnimation);
|
||||
bool isPlaying (const std::string& animationName);
|
||||
|
||||
void stopAll();
|
||||
|
||||
protected:
|
||||
typedef std::map<int, AnimationList > AnimationLayers;
|
||||
|
||||
AnimationLayers _animationsPlaying;
|
||||
|
||||
// clock
|
||||
double _lastUpdate;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
98
include/osgAnimation/AnimationManagerBase
Normal file
98
include/osgAnimation/AnimationManagerBase
Normal file
@@ -0,0 +1,98 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ANIMATIONMANAGERBASE_H
|
||||
#define OSGANIMATION_ANIMATIONMANAGERBASE_H
|
||||
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/FrameStamp>
|
||||
#include <osg/Group>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT AnimationManagerBase : public osg::Group
|
||||
{
|
||||
public:
|
||||
typedef std::set<osg::ref_ptr<Target> > TargetSet;
|
||||
struct UpdateCallback : public osg::NodeCallback
|
||||
{
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
AnimationManagerBase* b = dynamic_cast<AnimationManagerBase*>(node);
|
||||
if (b)
|
||||
{
|
||||
if (b->needToLink())
|
||||
{
|
||||
/** manager need to link, it means that an animation has been added
|
||||
so we need to relink all item animated with all animations.
|
||||
We apply the linker visitor on the manager node to affect
|
||||
all its children.
|
||||
But it should not be done here, it should be done in the
|
||||
update of AnimationManager
|
||||
*/
|
||||
b->link();
|
||||
}
|
||||
const osg::FrameStamp* fs = nv->getFrameStamp();
|
||||
b->update(fs->getSimulationTime());
|
||||
}
|
||||
}
|
||||
traverse(node,nv);
|
||||
}
|
||||
};
|
||||
|
||||
AnimationManagerBase();
|
||||
AnimationManagerBase(const AnimationManagerBase& b, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) :
|
||||
osg::Group(b,copyop)
|
||||
{
|
||||
_animations = b._animations;
|
||||
_targets = b._targets;
|
||||
_needToLink = b._needToLink;
|
||||
}
|
||||
virtual ~AnimationManagerBase();
|
||||
|
||||
virtual void update (double time) = 0;
|
||||
virtual void buildTargetReference();
|
||||
virtual void registerAnimation (Animation* animation);
|
||||
virtual void link();
|
||||
virtual bool needToLink() const;
|
||||
const AnimationList& getAnimationList() const { return _animations;}
|
||||
AnimationMap getAnimationMap() const;
|
||||
|
||||
void clearTargets()
|
||||
{
|
||||
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); it++)
|
||||
(*it).get()->reset();
|
||||
}
|
||||
void normalizeTargets()
|
||||
{
|
||||
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); it++)
|
||||
(*it).get()->normalize();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
AnimationList _animations;
|
||||
TargetSet _targets;
|
||||
bool _needToLink;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
49
include/osgAnimation/Assert
Normal file
49
include/osgAnimation/Assert
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ASSERT_H
|
||||
#define OSGANIMATION_ASSERT_H
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <exception>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
struct ThrowAssert : public std::exception
|
||||
{
|
||||
virtual const char* what() const throw () { return mMsg.c_str();}
|
||||
|
||||
std::string mMsg;
|
||||
ThrowAssert(const std::string& msg, const char* file, int line )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Assert (" << msg << ") in file " << file << " at line " << line;
|
||||
mMsg = ss.str();
|
||||
}
|
||||
|
||||
ThrowAssert() {}
|
||||
virtual ~ThrowAssert() throw () {}
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef OSGANIMATION_ASSERT_THROW
|
||||
#define OSGANIMATION_ASSERT(a) if (!(a)) throw osgAnimation::ThrowAssert(std::string(#a),__FILE__,__LINE__);
|
||||
|
||||
#else
|
||||
#define OSGANIMATION_ASSERT(a) {if (!(a)) *((int*)0) = 0;}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
300
include/osgAnimation/Bone
Normal file
300
include/osgAnimation/Bone
Normal file
@@ -0,0 +1,300 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_BONE_H
|
||||
#define OSGANIMATION_BONE_H
|
||||
|
||||
#include <osg/Transform>
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Node>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Notify>
|
||||
#include <osg/io_utils>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Target>
|
||||
#include <osgAnimation/Sampler>
|
||||
#include <osgAnimation/Channel>
|
||||
#include <osgAnimation/Keyframe>
|
||||
#include <osgAnimation/UpdateCallback>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/AnimationManager>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
inline osg::Matrix operator* (const osg::Matrix matrix, double v)
|
||||
{
|
||||
osg::Matrix result;
|
||||
for (int i = 0; i < 16; i++)
|
||||
result.ptr()[i] = matrix.ptr()[i] * v;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline osg::Matrix operator+ (const osg::Matrix a, const osg::Matrix b)
|
||||
{
|
||||
osg::Matrix result;
|
||||
for (int i = 0; i < 16; i++)
|
||||
result.ptr()[i] = a.ptr()[i] + b.ptr()[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
// A bone can't have more than one parent Bone, so sharing a part of Bone's hierarchy
|
||||
// has not sense. You can share the entire hierarchie but not only a part of
|
||||
class OSGANIMATION_EXPORT Bone : public osg::Transform
|
||||
{
|
||||
public:
|
||||
typedef osg::ref_ptr<Bone> PointerType;
|
||||
typedef std::map<std::string, PointerType > BoneMap;
|
||||
typedef osg::Matrix MatrixType;
|
||||
|
||||
META_Node(osgAnimation, Bone);
|
||||
Bone(const Bone& b, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) :
|
||||
osg::Transform(b,copyop),
|
||||
_position(b._position),
|
||||
_rotation(b._rotation),
|
||||
_scale(b._scale) {}
|
||||
|
||||
Bone(const std::string& name = "")
|
||||
{
|
||||
setName(name);
|
||||
_needToRecomputeBindMatrix = false;
|
||||
setUpdateCallback(new UpdateBone);
|
||||
}
|
||||
|
||||
|
||||
struct BoneMapVisitor : public osg::NodeVisitor
|
||||
{
|
||||
BoneMap _map;
|
||||
BoneMapVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
|
||||
void apply(osg::Node& node) { return; }
|
||||
void apply(osg::Transform& node)
|
||||
{
|
||||
Bone* bone = dynamic_cast<Bone*>(&node);
|
||||
if (bone)
|
||||
{
|
||||
_map[bone->getName()] = bone;
|
||||
traverse(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FindNearestParentAnimationManager : public osg::NodeVisitor
|
||||
{
|
||||
osg::ref_ptr<osgAnimation::AnimationManagerBase> _manager;
|
||||
FindNearestParentAnimationManager() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {}
|
||||
void apply(osg::Group& node)
|
||||
{
|
||||
if (_manager.valid())
|
||||
return;
|
||||
_manager = dynamic_cast<osgAnimation::AnimationManagerBase*>(&node);
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateBone : public AnimationUpdateCallback
|
||||
{
|
||||
public:
|
||||
osg::ref_ptr<osgAnimation::Vec3Target> _position;
|
||||
osg::ref_ptr<osgAnimation::QuatTarget> _quaternion;
|
||||
osg::ref_ptr<osgAnimation::Vec3Target> _scale;
|
||||
|
||||
public:
|
||||
META_Object(osgAnimation, UpdateBone);
|
||||
UpdateBone(const UpdateBone& apc,const osg::CopyOp& copyop);
|
||||
|
||||
UpdateBone(const std::string& name = "")
|
||||
{
|
||||
setName(name);
|
||||
_quaternion = new osgAnimation::QuatTarget;
|
||||
_position = new osgAnimation::Vec3Target;
|
||||
_scale = new osgAnimation::Vec3Target;
|
||||
}
|
||||
|
||||
void update(osgAnimation::Bone& bone)
|
||||
{
|
||||
bone.setTranslation(_position->getValue());
|
||||
bone.setRotation(_quaternion->getValue());
|
||||
bone.setScale(_scale->getValue());
|
||||
bone.dirtyBound();
|
||||
}
|
||||
|
||||
bool needLink() const
|
||||
{
|
||||
// the idea is to return true if nothing is linked
|
||||
return !((_position->getCount() + _quaternion->getCount() + _scale->getCount()) > 3);
|
||||
}
|
||||
|
||||
bool link(osgAnimation::Channel* channel)
|
||||
{
|
||||
if (channel->getName().find("quaternion") != std::string::npos)
|
||||
{
|
||||
osgAnimation::QuatSphericalLinearChannel* qc = dynamic_cast<osgAnimation::QuatSphericalLinearChannel*>(channel);
|
||||
if (qc)
|
||||
{
|
||||
qc->setTarget(_quaternion.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (channel->getName().find("position") != std::string::npos)
|
||||
{
|
||||
osgAnimation::Vec3LinearChannel* vc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
|
||||
if (vc)
|
||||
{
|
||||
vc->setTarget(_position.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (channel->getName().find("scale") != std::string::npos)
|
||||
{
|
||||
osgAnimation::Vec3LinearChannel* vc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
|
||||
if (vc)
|
||||
{
|
||||
vc->setTarget(_scale.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
Bone* b = dynamic_cast<Bone*>(node);
|
||||
if (b && !_manager.valid())
|
||||
{
|
||||
FindNearestParentAnimationManager finder;
|
||||
|
||||
if (b->getParents().size() > 1)
|
||||
{
|
||||
osg::notify(osg::WARN) << "A Bone should not have multi parent ( " << b->getName() << " ) has parents ";
|
||||
osg::notify(osg::WARN) << "( " << b->getParents()[0]->getName();
|
||||
for (int i = 1; i < (int)b->getParents().size(); i++)
|
||||
osg::notify(osg::WARN) << ", " << b->getParents()[i]->getName();
|
||||
osg::notify(osg::WARN) << ")" << std::endl;
|
||||
return;
|
||||
}
|
||||
b->getParents()[0]->accept(finder);
|
||||
|
||||
if (!finder._manager.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "Warning can't update Bone, path to parent AnimationManagerBase not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
_manager = finder._manager.get();
|
||||
}
|
||||
|
||||
updateLink();
|
||||
update(*b);
|
||||
}
|
||||
traverse(node,nv);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
osg::Vec3 _position;
|
||||
osg::Quat _rotation;
|
||||
osg::Vec3 _scale;
|
||||
|
||||
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
|
||||
virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
|
||||
|
||||
// flag to recompute bind pose
|
||||
bool _needToRecomputeBindMatrix;
|
||||
|
||||
// bind data
|
||||
osg::Matrix _bindInBoneSpace;
|
||||
osg::Matrix _invBindInSkeletonSpace;
|
||||
|
||||
// bone updated
|
||||
osg::Matrix _boneInSkeletonSpace;
|
||||
|
||||
Bone* getBoneParent();
|
||||
const Bone* getBoneParent() const;
|
||||
|
||||
void setTranslation(const osg::Vec3& trans) { _position = trans;}
|
||||
void setRotation(const osg::Quat& quat) { _rotation = quat;}
|
||||
void setScale(const osg::Vec3& scale) { _scale = scale;}
|
||||
|
||||
const osg::Vec3& getTranslation() const { return _position;}
|
||||
const osg::Quat& getRotation() const { return _rotation;}
|
||||
osg::Matrix getMatrixInBoneSpace() const { return (osg::Matrix(getRotation())) * osg::Matrix::translate(getTranslation()) * _bindInBoneSpace;}
|
||||
const osg::Matrix& getBindMatrixInBoneSpace() const { return _bindInBoneSpace; }
|
||||
const osg::Matrix& getMatrixInSkeletonSpace() const { return _boneInSkeletonSpace; }
|
||||
const osg::Matrix& getInvBindMatrixInSkeletonSpace() const { return _invBindInSkeletonSpace;}
|
||||
|
||||
void setBindMatrixInBoneSpace(const osg::Matrix& matrix)
|
||||
{
|
||||
_bindInBoneSpace = matrix;
|
||||
_needToRecomputeBindMatrix = true;
|
||||
}
|
||||
|
||||
inline bool needToComputeBindMatrix() { return _needToRecomputeBindMatrix;}
|
||||
virtual void computeBindMatrix();
|
||||
|
||||
bool needLink() const;
|
||||
|
||||
void setNeedToComputeBindMatrix(bool state) { _needToRecomputeBindMatrix = state; }
|
||||
|
||||
/** Add Node to Group.
|
||||
* If node is not NULL and is not contained in Group then increment its
|
||||
* reference count, add it to the child list and dirty the bounding
|
||||
* sphere to force it to recompute on next getBound() and return true for success.
|
||||
* Otherwise return false. Scene nodes can't be added as child nodes.
|
||||
*/
|
||||
virtual bool addChild( Node *child );
|
||||
BoneMap getBoneMap();
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline bool Bone::computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const
|
||||
{
|
||||
if (_referenceFrame==RELATIVE_RF)
|
||||
matrix.preMult(getMatrixInBoneSpace());
|
||||
else
|
||||
matrix = getMatrixInBoneSpace();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool Bone::computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const
|
||||
{
|
||||
if (_referenceFrame==RELATIVE_RF)
|
||||
matrix.postMult(osg::Matrix::inverse(getMatrixInBoneSpace()));
|
||||
else
|
||||
matrix = osg::Matrix::inverse(getMatrixInBoneSpace());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
136
include/osgAnimation/Channel
Normal file
136
include/osgAnimation/Channel
Normal file
@@ -0,0 +1,136 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_CHANNEL_H
|
||||
#define OSGANIMATION_CHANNEL_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Sampler>
|
||||
#include <osgAnimation/Target>
|
||||
#include <osgAnimation/Assert>
|
||||
#include <osg/Referenced>
|
||||
#include <string>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT Channel : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
Channel();
|
||||
virtual ~Channel();
|
||||
|
||||
virtual void update(float time) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual Target* getTarget() = 0;
|
||||
|
||||
const std::string& getName() const;
|
||||
void setName(const std::string& name);
|
||||
|
||||
virtual float getStartTime() const = 0;
|
||||
virtual float getEndTime() const = 0;
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
|
||||
std::string _targetName;
|
||||
std::string _name;
|
||||
float _weight;
|
||||
};
|
||||
|
||||
|
||||
template <typename SamplerType>
|
||||
class TemplateChannel : public Channel
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename SamplerType::UsingType UsingType;
|
||||
typedef TemplateTarget<UsingType> TargetType;
|
||||
typedef TemplateKeyframeContainer<typename SamplerType::KeyframeType> KeyframeContainerType;
|
||||
|
||||
TemplateChannel (SamplerType* s = 0,TargetType* target = 0)
|
||||
{
|
||||
if (target)
|
||||
_target = target;
|
||||
else
|
||||
_target = new TargetType;
|
||||
_sampler = s;
|
||||
}
|
||||
|
||||
virtual ~TemplateChannel() {}
|
||||
virtual void update(float time)
|
||||
{
|
||||
// skip if weight == 0
|
||||
if (_weight < 1e-4)
|
||||
return;
|
||||
typename SamplerType::UsingType value;
|
||||
_sampler->getValueAt(time, value);
|
||||
_target->update(_weight, value);
|
||||
}
|
||||
virtual void reset() { _target->reset(); }
|
||||
virtual Target* getTarget() { return _target.get();}
|
||||
|
||||
SamplerType* getOrCreateSampler()
|
||||
{
|
||||
if (!_sampler.valid())
|
||||
_sampler = new SamplerType;
|
||||
return _sampler.get();
|
||||
}
|
||||
|
||||
Sampler* getSampler() { return _sampler.get(); }
|
||||
const Sampler* getSampler() const { return _sampler.get(); }
|
||||
|
||||
SamplerType* getSamplerTyped() { return _sampler.get();}
|
||||
const SamplerType* getSamplerTyped() const { return _sampler.get();}
|
||||
void setSampler(SamplerType* sampler) { _sampler = sampler; }
|
||||
|
||||
TargetType* getTargetTyped() { return _target.get(); }
|
||||
void setTarget(TargetType* target) { _target = target; }
|
||||
|
||||
virtual float getStartTime() const { OSGANIMATION_ASSERT(_sampler.valid() && "no sampler attached to channel"); return _sampler->getStartTime(); }
|
||||
virtual float getEndTime() const { OSGANIMATION_ASSERT(_sampler.valid() && "no sampler attached to channel"); return _sampler->getEndTime(); }
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<TargetType> _target;
|
||||
osg::ref_ptr<SamplerType> _sampler;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<osg::ref_ptr<osgAnimation::Channel> > ChannelList;
|
||||
typedef TemplateChannel<DoubleLinearSampler> DoubleLinearChannel;
|
||||
typedef TemplateChannel<FloatLinearSampler> FloatLinearChannel;
|
||||
|
||||
typedef TemplateChannel<Vec2LinearSampler> Vec2LinearChannel;
|
||||
typedef TemplateChannel<Vec3LinearSampler> Vec3LinearChannel;
|
||||
typedef TemplateChannel<Vec4LinearSampler> Vec4LinearChannel;
|
||||
typedef TemplateChannel<QuatSphericalLinearSampler> QuatSphericalLinearChannel;
|
||||
|
||||
typedef TemplateChannel<FloatCubicBezierSampler> FloatCubicBezierChannel;
|
||||
typedef TemplateChannel<DoubleCubicBezierSampler> DoubleCubicBezierChannel;
|
||||
typedef TemplateChannel<Vec2CubicBezierSampler> Vec2CubicBezierChannel;
|
||||
typedef TemplateChannel<Vec3CubicBezierSampler> Vec3CubicBezierChannel;
|
||||
typedef TemplateChannel<Vec4CubicBezierSampler> Vec4CubicBezierChannel;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
56
include/osgAnimation/CubicBezier
Normal file
56
include/osgAnimation/CubicBezier
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_CUBIC_BEZIER_H
|
||||
#define OSGANIMATION_CUBIC_BEZIER_H
|
||||
|
||||
#include <osg/Vec2>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Quat>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
template <class T>
|
||||
struct TemplateCubicBezier
|
||||
{
|
||||
T mPoint[3];
|
||||
const T& getP0() const { return mPoint[0];}
|
||||
const T& getP1() const { return mPoint[1];}
|
||||
const T& getP2() const { return mPoint[2];}
|
||||
TemplateCubicBezier(const T& v0, const T& v1, const T& v2)
|
||||
{
|
||||
mPoint[0] = v0;
|
||||
mPoint[1] = v1;
|
||||
mPoint[2] = v2;
|
||||
}
|
||||
|
||||
TemplateCubicBezier() {}
|
||||
|
||||
const T& getPosition() const { return mPoint[0];}
|
||||
const T& getTangentPoint1() const { return mPoint[1];}
|
||||
const T& getTangentPoint2() const { return mPoint[2];}
|
||||
};
|
||||
|
||||
|
||||
typedef TemplateCubicBezier<float> FloatCubicBezier;
|
||||
typedef TemplateCubicBezier<double> DoubleCubicBezier;
|
||||
typedef TemplateCubicBezier<osg::Vec2> Vec2CubicBezier;
|
||||
typedef TemplateCubicBezier<osg::Vec3> Vec3CubicBezier;
|
||||
typedef TemplateCubicBezier<osg::Vec4> Vec4CubicBezier;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
238
include/osgAnimation/EaseMotion
Normal file
238
include/osgAnimation/EaseMotion
Normal file
@@ -0,0 +1,238 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_EASE_MOTION_H
|
||||
#define OSGANIMATION_EASE_MOTION_H
|
||||
|
||||
namespace osgAnimation {
|
||||
|
||||
struct LinearFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { result = t;}
|
||||
};
|
||||
|
||||
|
||||
struct OutBounceFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
if ((t) < (1/2.75))
|
||||
{
|
||||
result = 7.5625 * t * t;
|
||||
}
|
||||
else if (t < (2/2.75))
|
||||
{
|
||||
t = t - (1.5/2.75);
|
||||
result = 7.5625* t * t + .75;
|
||||
}
|
||||
else if (t < (2.5/2.75))
|
||||
{
|
||||
t = t - (2.25/2.75);
|
||||
result = 7.5625 * t * t + .9375;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = t - (2.625/2.75);
|
||||
result = 7.5625* t * t + .984375;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct InBounceFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
OutBounceFunction::getValueAt(1-t, result);
|
||||
result = 1 - result;
|
||||
}
|
||||
};
|
||||
|
||||
struct InOutBounceFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
if (t < 0.5)
|
||||
{
|
||||
InBounceFunction::getValueAt(t * 2, result);
|
||||
result *= 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
OutBounceFunction::getValueAt(t * 2 - 1 , result);
|
||||
result = result * 0.5 + 0.5;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct OutQuadFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { result = - (t * (t -2.0));}
|
||||
};
|
||||
|
||||
struct InQuadFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { result = t*t;}
|
||||
};
|
||||
struct InOutQuadFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
t = t * 2.0;
|
||||
if (t < 1.0)
|
||||
result = 0.5 * t * t;
|
||||
else
|
||||
{
|
||||
t = t - 1.0;
|
||||
result = - 0.5 * t * ( t - 2) - 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct OutCubicFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { t = t-1.0; result = t*t*t + 1;}
|
||||
};
|
||||
struct InCubicFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { result = t*t*t;}
|
||||
};
|
||||
struct InOutCubicFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
t = t * 2;
|
||||
if (t < 1.0)
|
||||
result = 0.5 * t * t * t;
|
||||
else {
|
||||
t = t - 2;
|
||||
result = 0.5 * t * t * t + 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Motion
|
||||
{
|
||||
public:
|
||||
typedef float value_type;
|
||||
enum TimeBehaviour
|
||||
{
|
||||
CLAMP,
|
||||
LOOP,
|
||||
};
|
||||
Motion(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : _time(0), _b(startValue), _c(changeValue), _d(duration), _behaviour(tb) {}
|
||||
virtual ~Motion() {}
|
||||
void reset() { setTime(0);}
|
||||
float getTime() const { return _time; }
|
||||
void update(float dt)
|
||||
{
|
||||
_time += dt;
|
||||
switch (_behaviour)
|
||||
{
|
||||
case CLAMP:
|
||||
if (_time > _d)
|
||||
_time = _d;
|
||||
else if (_time < 0.0)
|
||||
_time = 0.0;
|
||||
break;
|
||||
case LOOP:
|
||||
_time = fmodf(_time, _d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setTime(float time) { _time = time; update(0);}
|
||||
void getValue(value_type& result) const { getValueAt(_time, result); }
|
||||
value_type getValue() const
|
||||
{
|
||||
value_type result;
|
||||
getValueAt(_time, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void getValueAt(float time, value_type& result) const
|
||||
{
|
||||
getValueInNormalizedRange(time/_d, result);
|
||||
result = result * _c + _b;
|
||||
}
|
||||
value_type getValueAt(float time) const
|
||||
{
|
||||
value_type result;
|
||||
getValueAt(time, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void getValueInNormalizedRange(float t, value_type& result) const = 0;
|
||||
|
||||
protected:
|
||||
float _time;
|
||||
float _b;
|
||||
float _c;
|
||||
float _d;
|
||||
TimeBehaviour _behaviour;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct MathMotionTemplate : public Motion
|
||||
{
|
||||
MathMotionTemplate(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : Motion(startValue, duration, changeValue, tb) {}
|
||||
virtual void getValueInNormalizedRange(float t, value_type& result) const { T::getValueAt(t, result); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct SamplerMotionTemplate : public Motion
|
||||
{
|
||||
T _sampler;
|
||||
SamplerMotionTemplate(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : Motion(startValue, duration, changeValue, tb) {}
|
||||
T& getSampler() { return _sampler;}
|
||||
const T& getSampler() const { return _sampler;}
|
||||
virtual void getValueInNormalizedRange(float t, value_type& result) const
|
||||
{
|
||||
if (!_sampler.getKeyframeContainer())
|
||||
{
|
||||
result = 0;
|
||||
return;
|
||||
}
|
||||
float size = _sampler.getEndTime() - _sampler.getStartTime();
|
||||
t = t * size + _sampler.getStartTime();
|
||||
_sampler.getValueAt(t, result);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// linear
|
||||
typedef MathMotionTemplate<LinearFunction > LinearMotion;
|
||||
|
||||
// cubic
|
||||
typedef MathMotionTemplate<OutCubicFunction > OutCubicMotion;
|
||||
typedef MathMotionTemplate<InCubicFunction> InCubicMotion;
|
||||
typedef MathMotionTemplate<InOutCubicFunction> InOutCubicMotion;
|
||||
|
||||
// quad
|
||||
typedef MathMotionTemplate<OutQuadFunction > OutQuadMotion;
|
||||
typedef MathMotionTemplate<InQuadFunction> InQuadMotion;
|
||||
typedef MathMotionTemplate<InOutQuadFunction> InOutQuadMotion;
|
||||
|
||||
// bounce
|
||||
typedef MathMotionTemplate<OutBounceFunction > OutBounceMotion;
|
||||
typedef MathMotionTemplate<InBounceFunction> InBounceMotion;
|
||||
typedef MathMotionTemplate<InOutBounceFunction> InOutBounceMotion;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
65
include/osgAnimation/Export
Normal file
65
include/osgAnimation/Export
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* 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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
// The following symbol has a underscore suffix for compatibility.
|
||||
#ifndef OSGANIMATION_EXPORT_
|
||||
#define OSGANIMATION_EXPORT_ 1
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( disable : 4244 )
|
||||
#pragma warning( disable : 4251 )
|
||||
#pragma warning( disable : 4267 )
|
||||
#pragma warning( disable : 4275 )
|
||||
#pragma warning( disable : 4290 )
|
||||
#pragma warning( disable : 4786 )
|
||||
#pragma warning( disable : 4305 )
|
||||
#pragma warning( disable : 4996 )
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
|
||||
# if defined( OSG_LIBRARY_STATIC )
|
||||
# define OSGANIMATION_EXPORT
|
||||
# elif defined( OSGANIMATION_LIBRARY )
|
||||
# define OSGANIMATION_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define OSGANIMATION_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define OSGANIMATION_EXPORT
|
||||
#endif
|
||||
|
||||
// set up define for whether member templates are supported by VisualStudio compilers.
|
||||
#ifdef _MSC_VER
|
||||
# if (_MSC_VER >= 1300)
|
||||
# define __STL_MEMBER_TEMPLATES
|
||||
# endif
|
||||
#endif
|
||||
/* Define NULL pointer value */
|
||||
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
\namespace osgAnimation
|
||||
|
||||
The osgAnimation library provides general purpose utility classes for animation.
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
||||
206
include/osgAnimation/Interpolator
Normal file
206
include/osgAnimation/Interpolator
Normal file
@@ -0,0 +1,206 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_INTERPOLATOR_H
|
||||
#define OSGANIMATION_INTERPOLATOR_H
|
||||
|
||||
#include <osgAnimation/Assert>
|
||||
#include <osgAnimation/Interpolator>
|
||||
#include <osgAnimation/Keyframe>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
template <class TYPE, class KEY>
|
||||
class TemplateInterpolatorBase
|
||||
{
|
||||
public:
|
||||
typedef KEY KeyframeType;
|
||||
typedef TYPE UsingType;
|
||||
|
||||
public:
|
||||
mutable int _lastKeyAccess;
|
||||
|
||||
TemplateInterpolatorBase() : _lastKeyAccess(-1) {}
|
||||
|
||||
void reset() { _lastKeyAccess = -1; }
|
||||
int getKeyIndexFromTime(const TemplateKeyframeContainer<KEY>& keys, float time) const
|
||||
{
|
||||
OSGANIMATION_ASSERT(!keys.empty() && "no keys");
|
||||
OSGANIMATION_ASSERT(time >= keys.front().getTime() && time <= keys.back().getTime() && "bad range");
|
||||
|
||||
// todo use a cache
|
||||
int key_size = keys.size();
|
||||
const TemplateKeyframe<KeyframeType>* keysVector = &keys.front();
|
||||
for (int i = 0; i < key_size-1; i++)
|
||||
{
|
||||
float time0 = keysVector[i].getTime();
|
||||
float time1 = keysVector[i+1].getTime();
|
||||
#ifndef OSGANIMATION_NO_EXTRA_CHECK
|
||||
if ( time0>time1 )
|
||||
OSGANIMATION_ASSERT(0 && "invalid input data");
|
||||
#endif
|
||||
if ( time >= time0 && time < time1 )
|
||||
{
|
||||
_lastKeyAccess = i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
std::cout << time << " first key " << keysVector[0].getTime() << " last key " << keysVector[key_size-1].getTime() << std::endl;
|
||||
*((int *)0) = 0;
|
||||
OSGANIMATION_ASSERT(0 && "impossible has happened");
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class TYPE, class KEY=TYPE>
|
||||
class TemplateLinearInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
|
||||
{
|
||||
public:
|
||||
|
||||
TemplateLinearInterpolator() {}
|
||||
void getValue(const TemplateKeyframeContainer<KEY>& keyframes, float time, TYPE& result) const
|
||||
{
|
||||
|
||||
if (time >= keyframes.back().getTime())
|
||||
{
|
||||
result = keyframes.back().getValue();
|
||||
return;
|
||||
}
|
||||
else if (time <= keyframes.front().getTime())
|
||||
{
|
||||
result = keyframes.front().getValue();
|
||||
return;
|
||||
}
|
||||
|
||||
int i = getKeyIndexFromTime(keyframes,time);
|
||||
float blend = (time - keyframes[i].getTime()) / ( keyframes[i+1].getTime() - keyframes[i].getTime());
|
||||
const TYPE& v1 = keyframes[i].getValue();
|
||||
const TYPE& v2 = keyframes[i+1].getValue();
|
||||
result = v1*(1-blend) + v2*blend;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class TYPE, class KEY=TYPE>
|
||||
class TemplateSphericalLinearInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
|
||||
{
|
||||
public:
|
||||
TemplateSphericalLinearInterpolator() {}
|
||||
void getValue(const TemplateKeyframeContainer<KEY>& keyframes, float time, TYPE& result) const
|
||||
{
|
||||
if (time >= keyframes.back().getTime())
|
||||
{
|
||||
result = keyframes.back().getValue();
|
||||
return;
|
||||
}
|
||||
else if (time <= keyframes.front().getTime())
|
||||
{
|
||||
result = keyframes.front().getValue();
|
||||
return;
|
||||
}
|
||||
|
||||
int i = getKeyIndexFromTime(keyframes,time);
|
||||
float blend = (time - keyframes[i].getTime()) / ( keyframes[i+1].getTime() - keyframes[i].getTime());
|
||||
const TYPE& q1 = keyframes[i].getValue();
|
||||
const TYPE& q2 = keyframes[i+1].getValue();
|
||||
result.slerp(blend,q1,q2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class TYPE, class KEY>
|
||||
class TemplateLinearPackedInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
|
||||
{
|
||||
public:
|
||||
|
||||
TemplateLinearPackedInterpolator() {}
|
||||
void getValue(const TemplateKeyframeContainer<KEY>& keyframes, float time, TYPE& result) const
|
||||
{
|
||||
if (time >= keyframes.back().getTime())
|
||||
{
|
||||
keyframes.back().getValue().uncompress(keyframes.mScale, keyframes.mMin, result);
|
||||
return;
|
||||
}
|
||||
else if (time <= keyframes.front().getTime())
|
||||
{
|
||||
keyframes.front().getValue().uncompress(keyframes.mScale, keyframes.mMin, result);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = getKeyIndexFromTime(keyframes,time);
|
||||
float blend = (time - keyframes[i].getTime()) / ( keyframes[i+1].getTime() - keyframes[i].getTime());
|
||||
TYPE v1,v2;
|
||||
keyframes[i].getValue().uncompress(keyframes.mScale, keyframes.mMin, v1);
|
||||
keyframes[i+1].getValue().uncompress(keyframes.mScale, keyframes.mMin, v2);
|
||||
result = v1*(1-blend) + v2*blend;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// http://en.wikipedia.org/wiki/B%C3%A9zier_curve
|
||||
template <class TYPE, class KEY=TYPE>
|
||||
class TemplateCubicBezierInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
|
||||
{
|
||||
public:
|
||||
|
||||
TemplateCubicBezierInterpolator() {}
|
||||
void getValue(const TemplateKeyframeContainer<KEY>& keyframes, float time, TYPE& result) const
|
||||
{
|
||||
|
||||
if (time >= keyframes.back().getTime())
|
||||
{
|
||||
result = keyframes.back().getValue().getPosition();
|
||||
return;
|
||||
}
|
||||
else if (time <= keyframes.front().getTime())
|
||||
{
|
||||
result = keyframes.front().getValue().getPosition();
|
||||
return;
|
||||
}
|
||||
|
||||
int i = getKeyIndexFromTime(keyframes,time);
|
||||
|
||||
float t = (time - keyframes[i].getTime()) / ( keyframes[i+1].getTime() - keyframes[i].getTime());
|
||||
float one_minus_t = 1.0-t;
|
||||
float one_minus_t2 = one_minus_t * one_minus_t;
|
||||
float one_minus_t3 = one_minus_t2 * one_minus_t;
|
||||
float t2 = t * t;
|
||||
|
||||
TYPE v0 = keyframes[i].getValue().getPosition() * one_minus_t3;
|
||||
TYPE v1 = keyframes[i].getValue().getTangentPoint1() * (3.0 * t * one_minus_t2);
|
||||
TYPE v2 = keyframes[i].getValue().getTangentPoint2() * (3.0 * t2 * one_minus_t);
|
||||
TYPE v3 = keyframes[i+1].getValue().getPosition() * (t2 * t);
|
||||
|
||||
result = v0 + v1 + v2 + v3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef TemplateLinearInterpolator<double, double> DoubleLinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<float, float> FloatLinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<osg::Vec2, osg::Vec2> Vec2LinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<osg::Vec3, osg::Vec3> Vec3LinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<osg::Vec3, Vec3Packed> Vec3PackedLinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<osg::Vec4, osg::Vec4> Vec4LinearInterpolator;
|
||||
typedef TemplateSphericalLinearInterpolator<osg::Quat, osg::Quat> QuatSphericalLinearInterpolator;
|
||||
|
||||
typedef TemplateCubicBezierInterpolator<float, FloatCubicBezier > FloatCubicBezierInterpolator;
|
||||
typedef TemplateCubicBezierInterpolator<double, DoubleCubicBezier> DoubleCubicBezierInterpolator;
|
||||
typedef TemplateCubicBezierInterpolator<osg::Vec2, Vec2CubicBezier> Vec2CubicBezierInterpolator;
|
||||
typedef TemplateCubicBezierInterpolator<osg::Vec3, Vec3CubicBezier> Vec3CubicBezierInterpolator;
|
||||
typedef TemplateCubicBezierInterpolator<osg::Vec4, Vec4CubicBezier> Vec4CubicBezierInterpolator;
|
||||
|
||||
}
|
||||
#endif
|
||||
130
include/osgAnimation/Keyframe
Normal file
130
include/osgAnimation/Keyframe
Normal file
@@ -0,0 +1,130 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_KEYFRAME_H
|
||||
#define OSGANIMATION_KEYFRAME_H
|
||||
|
||||
#include <string>
|
||||
#include <osg/Referenced>
|
||||
#include <osgAnimation/Vec3Packed>
|
||||
#include <osgAnimation/CubicBezier>
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec2>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class Keyframe
|
||||
{
|
||||
public:
|
||||
float getTime() const { return _time; }
|
||||
void setTime(float time) { _time = time; }
|
||||
|
||||
protected:
|
||||
float _time;
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class TemplateKeyframe : public Keyframe
|
||||
{
|
||||
protected:
|
||||
T _value;
|
||||
public:
|
||||
TemplateKeyframe () {}
|
||||
~TemplateKeyframe () {}
|
||||
|
||||
TemplateKeyframe (float time, const T& value)
|
||||
{
|
||||
_time = time;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
void setValue(const T& value) { _value = value;}
|
||||
const T& getValue() const { return _value;}
|
||||
};
|
||||
|
||||
|
||||
class KeyframeContainer : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
KeyframeContainer() {}
|
||||
virtual unsigned int size() const = 0;
|
||||
protected:
|
||||
~KeyframeContainer() {}
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
class TemplateKeyframeContainer : public std::vector<TemplateKeyframe<T> >, public KeyframeContainer
|
||||
{
|
||||
public:
|
||||
// const char* getKeyframeType() { return #T ;}
|
||||
TemplateKeyframeContainer() {}
|
||||
typedef TemplateKeyframe<T> KeyType;
|
||||
|
||||
virtual unsigned int size() const { return (unsigned int)std::vector<TemplateKeyframe<T> >::size(); }
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
class TemplateKeyframeContainer<Vec3Packed> : public std::vector<TemplateKeyframe<Vec3Packed> >, public KeyframeContainer
|
||||
{
|
||||
public:
|
||||
typedef TemplateKeyframe<Vec3Packed> KeyType;
|
||||
|
||||
TemplateKeyframeContainer() {}
|
||||
const char* getKeyframeType() { return "Vec3Packed" ;}
|
||||
void init(const osg::Vec3f& min, const osg::Vec3f& scale) { _min = min; _scale = scale; }
|
||||
|
||||
osg::Vec3f _min;
|
||||
osg::Vec3f _scale;
|
||||
};
|
||||
|
||||
|
||||
typedef TemplateKeyframe<float> FloatKeyframe;
|
||||
typedef TemplateKeyframeContainer<float> FloatKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<osg::Vec2> Vec2Keyframe;
|
||||
typedef TemplateKeyframeContainer<osg::Vec2> Vec2KeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<osg::Vec3> Vec3Keyframe;
|
||||
typedef TemplateKeyframeContainer<osg::Vec3> Vec3KeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<osg::Vec4> Vec4Keyframe;
|
||||
typedef TemplateKeyframeContainer<osg::Vec4> Vec4KeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<osg::Quat> QuatKeyframe;
|
||||
typedef TemplateKeyframeContainer<osg::Quat> QuatKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<Vec3Packed> Vec3PackedKeyframe;
|
||||
typedef TemplateKeyframeContainer<Vec3Packed> Vec3PackedKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<FloatCubicBezier> FloatCubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<FloatCubicBezier> FloatCubicBezierKeyframeContainer;
|
||||
typedef TemplateKeyframe<DoubleCubicBezier> DoubleCubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<DoubleCubicBezier> DoubleCubicBezierKeyframeContainer;
|
||||
typedef TemplateKeyframe<Vec2CubicBezier> Vec2CubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<Vec2CubicBezier> Vec2CubicBezierKeyframeContainer;
|
||||
typedef TemplateKeyframe<Vec3CubicBezier> Vec3CubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<Vec3CubicBezier> Vec3CubicBezierKeyframeContainer;
|
||||
typedef TemplateKeyframe<Vec4CubicBezier> Vec4CubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<Vec4CubicBezier> Vec4CubicBezierKeyframeContainer;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
50
include/osgAnimation/LinkVisitor
Normal file
50
include/osgAnimation/LinkVisitor
Normal file
@@ -0,0 +1,50 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_NODE_VISITOR_H
|
||||
#define OSGANIMATION_NODE_VISITOR_H
|
||||
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/UpdateCallback>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
struct LinkVisitor : public osg::NodeVisitor
|
||||
{
|
||||
AnimationList _animations;
|
||||
unsigned int _nbLinkedTarget;
|
||||
LinkVisitor(Animation* animation) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _animations.push_back(animation); _nbLinkedTarget = 0;}
|
||||
LinkVisitor(const AnimationList& animations) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _animations = animations; _nbLinkedTarget = 0;}
|
||||
void apply(osg::Node& node)
|
||||
{
|
||||
osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(node.getUpdateCallback());
|
||||
if (cb)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; i < (int)_animations.size(); i++)
|
||||
{
|
||||
result += cb->link(_animations[i].get());
|
||||
_nbLinkedTarget += result;
|
||||
}
|
||||
std::cout << "LinkVisitor links " << result << " for \"" << cb->getName() << '"' << std::endl;
|
||||
}
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
159
include/osgAnimation/RigGeometry
Normal file
159
include/osgAnimation/RigGeometry
Normal file
@@ -0,0 +1,159 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_RIGGEOMETRY_H
|
||||
#define OSGANIMATION_RIGGEOMETRY_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Skinning>
|
||||
#include <osgAnimation/Skeleton>
|
||||
#include <osg/Geometry>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT RigGeometry : public osg::Geometry
|
||||
{
|
||||
public:
|
||||
|
||||
struct FindNearestParentSkeleton : public osg::NodeVisitor
|
||||
{
|
||||
osg::ref_ptr<osgAnimation::Skeleton> _root;
|
||||
FindNearestParentSkeleton() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {}
|
||||
void apply(osg::Transform& node)
|
||||
{
|
||||
if (_root.valid())
|
||||
return;
|
||||
_root = dynamic_cast<osgAnimation::Skeleton*>(&node);
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct UpdateVertex : public osg::Drawable::UpdateCallback
|
||||
{
|
||||
virtual void update(osg::NodeVisitor*, osg::Drawable* drw)
|
||||
{
|
||||
RigGeometry* geom = dynamic_cast<RigGeometry*>(drw);
|
||||
if (!geom)
|
||||
return;
|
||||
if (!geom->getSkeleton() && !geom->getParents().empty())
|
||||
{
|
||||
FindNearestParentSkeleton finder;
|
||||
if (geom->getParents().size() > 1)
|
||||
osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << geom->getName() << " )" << std::endl;
|
||||
geom->getParents()[0]->accept(finder);
|
||||
|
||||
if (!finder._root.valid())
|
||||
return;
|
||||
geom->buildVertexSet();
|
||||
geom->buildTransformer(finder._root.get());
|
||||
}
|
||||
|
||||
if (!geom->getSkeleton())
|
||||
return;
|
||||
|
||||
if (geom->getNeedToComputeMatrix())
|
||||
geom->computeMatrixFromRootSkeleton();
|
||||
geom->transformSoftwareMethod();
|
||||
}
|
||||
};
|
||||
|
||||
/** BuildVertexTransformerVisitor is used to setup RigGeometry drawable
|
||||
* throw a subgraph.
|
||||
*/
|
||||
struct BuildVertexTransformerVisitor : public osg::NodeVisitor
|
||||
{
|
||||
osg::ref_ptr<Skeleton> _root;
|
||||
BuildVertexTransformerVisitor(Skeleton* root): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _root = root;}
|
||||
void apply(osg::Geode& node)
|
||||
{
|
||||
int num = node.getNumDrawables();
|
||||
for (int i = 0; i < num; i++) {
|
||||
RigGeometry* geom = dynamic_cast<RigGeometry*>(node.getDrawable(i));
|
||||
if (geom)
|
||||
{
|
||||
geom->buildVertexSet();
|
||||
geom->buildTransformer(_root.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
RigGeometry()
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
setUpdateCallback(new UpdateVertex);
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
_needToComputeMatrix = true;
|
||||
_matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity();
|
||||
}
|
||||
RigGeometry(const osg::Geometry& b) : osg::Geometry(b, osg::CopyOp::SHALLOW_COPY)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
setUpdateCallback(new UpdateVertex);
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
_needToComputeMatrix = true;
|
||||
_matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity();
|
||||
}
|
||||
|
||||
RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) :
|
||||
osg::Geometry(b,copyop),
|
||||
_positionSource(b._positionSource),
|
||||
_normalSource(b._normalSource),
|
||||
_vertexInfluenceSet(b._vertexInfluenceSet),
|
||||
_vertexInfluenceMap(b._vertexInfluenceMap),
|
||||
_transformVertexes(b._transformVertexes),
|
||||
_needToComputeMatrix(b._needToComputeMatrix) {}
|
||||
|
||||
virtual osg::Object* cloneType() const { return new RigGeometry(); }
|
||||
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new RigGeometry(*this,copyop); }
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const RigGeometry*>(obj)!=NULL; }
|
||||
virtual const char* libraryName() const { return "osgAnimation"; }
|
||||
virtual const char* className() const { return "RigGeometry"; }
|
||||
|
||||
|
||||
void setInfluenceMap(osgAnimation::VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; }
|
||||
const osgAnimation::VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();}
|
||||
osgAnimation::VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();}
|
||||
void buildVertexSet();
|
||||
void buildTransformer(Skeleton* root);
|
||||
void computeMatrixFromRootSkeleton();
|
||||
|
||||
void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;}
|
||||
bool getNeedToComputeMatrix() const { return _needToComputeMatrix;}
|
||||
|
||||
const Skeleton* getSkeleton() const;
|
||||
Skeleton* getSkeleton();
|
||||
virtual void transformSoftwareMethod();
|
||||
const osgAnimation::VertexInfluenceSet& getVertexInfluenceSet() const { return _vertexInfluenceSet;}
|
||||
|
||||
std::vector<osg::Vec3> _positionSource;
|
||||
std::vector<osg::Vec3> _normalSource;
|
||||
|
||||
osgAnimation::VertexInfluenceSet _vertexInfluenceSet;
|
||||
osg::ref_ptr<osgAnimation::VertexInfluenceMap> _vertexInfluenceMap;
|
||||
osgAnimation::TransformVertexFunctor _transformVertexes;
|
||||
|
||||
osg::Matrix _matrixFromSkeletonToGeometry;
|
||||
osg::Matrix _invMatrixFromSkeletonToGeometry;
|
||||
osg::observer_ptr<Skeleton> _root;
|
||||
bool _needToComputeMatrix;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
124
include/osgAnimation/Sampler
Normal file
124
include/osgAnimation/Sampler
Normal file
@@ -0,0 +1,124 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_SAMPLER_H
|
||||
#define OSGANIMATION_SAMPLER_H
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <osg/Referenced>
|
||||
#include <osg/ref_ptr>
|
||||
#include <osgAnimation/Keyframe>
|
||||
#include <osgAnimation/Interpolator>
|
||||
#include <osgAnimation/Assert>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class Sampler : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
virtual KeyframeContainer* getKeyframeContainer() = 0;
|
||||
virtual const KeyframeContainer* getKeyframeContainer() const = 0;
|
||||
protected:
|
||||
};
|
||||
|
||||
// Sampler generic
|
||||
template <class F>
|
||||
class TemplateSampler : public Sampler
|
||||
{
|
||||
public:
|
||||
typedef typename F::KeyframeType KeyframeType;
|
||||
typedef TemplateKeyframeContainer<KeyframeType> KeyframeContainerType;
|
||||
typedef typename F::UsingType UsingType;
|
||||
typedef F FunctorType;
|
||||
|
||||
TemplateSampler() {}
|
||||
~TemplateSampler() {}
|
||||
|
||||
void getValueAt(float time, UsingType& result) const { _functor.getValue(*_keyframes, time, result);}
|
||||
void setKeyframeContainer(KeyframeContainerType* kf) { _keyframes = kf;}
|
||||
|
||||
virtual KeyframeContainer* getKeyframeContainer() { return _keyframes.get(); }
|
||||
virtual const KeyframeContainer* getKeyframeContainer() const { return _keyframes.get();}
|
||||
|
||||
KeyframeContainerType* getKeyframeContainerTyped() { return _keyframes.get();}
|
||||
const KeyframeContainerType* getKeyframeContainerTyped() const { return _keyframes.get();}
|
||||
KeyframeContainerType* getOrCreateKeyframeContainer()
|
||||
{
|
||||
if (_keyframes != 0)
|
||||
return _keyframes.get();
|
||||
_keyframes = new KeyframeContainerType;
|
||||
return _keyframes.get();
|
||||
}
|
||||
|
||||
float getStartTime() const
|
||||
{
|
||||
OSGANIMATION_ASSERT(_keyframes.valid() && !_keyframes->empty() && "no keyframes");
|
||||
return _keyframes->front().getTime();
|
||||
}
|
||||
|
||||
float getEndTime() const
|
||||
{
|
||||
OSGANIMATION_ASSERT(_keyframes.valid() && !_keyframes->empty() && "no keyframes");
|
||||
return _keyframes->back().getTime();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
FunctorType _functor;
|
||||
osg::ref_ptr<KeyframeContainerType> _keyframes;
|
||||
};
|
||||
|
||||
|
||||
template<typename VALUESAMPLERTYPE, typename TIMESAMPLERTYPE>
|
||||
class TemplateCompositeSampler : public osg::Referenced
|
||||
{
|
||||
VALUESAMPLERTYPE& _value;
|
||||
TIMESAMPLERTYPE& _time;
|
||||
|
||||
public:
|
||||
typedef typename VALUESAMPLERTYPE::FunctorType::UsingType UsingType;
|
||||
typedef typename VALUESAMPLERTYPE::FunctorType::KeyframeType KeyframeType;
|
||||
|
||||
TemplateCompositeSampler(VALUESAMPLERTYPE& value, TIMESAMPLERTYPE& time) : _value(value), _time(time)
|
||||
{
|
||||
}
|
||||
|
||||
void getValueAt(float time, typename VALUESAMPLERTYPE::FunctorType::UsingType& result)
|
||||
{
|
||||
float newtime;
|
||||
_time.getValueAt(time, newtime);
|
||||
_value.getValueAt(newtime, result);
|
||||
}
|
||||
float getStartTime() const {return _time.getStartTime(); }
|
||||
float getEndTime() const {return _time.getEndTime();}
|
||||
};
|
||||
|
||||
|
||||
typedef TemplateSampler<DoubleLinearInterpolator> DoubleLinearSampler;
|
||||
typedef TemplateSampler<FloatLinearInterpolator> FloatLinearSampler;
|
||||
typedef TemplateSampler<Vec2LinearInterpolator> Vec2LinearSampler;
|
||||
typedef TemplateSampler<Vec3LinearInterpolator> Vec3LinearSampler;
|
||||
typedef TemplateSampler<Vec4LinearInterpolator> Vec4LinearSampler;
|
||||
typedef TemplateSampler<QuatSphericalLinearInterpolator> QuatSphericalLinearSampler;
|
||||
typedef TemplateSampler<FloatCubicBezierInterpolator> FloatCubicBezierSampler;
|
||||
typedef TemplateSampler<DoubleCubicBezierInterpolator> DoubleCubicBezierSampler;
|
||||
typedef TemplateSampler<Vec2CubicBezierInterpolator> Vec2CubicBezierSampler;
|
||||
typedef TemplateSampler<Vec3CubicBezierInterpolator> Vec3CubicBezierSampler;
|
||||
typedef TemplateSampler<Vec4CubicBezierInterpolator> Vec4CubicBezierSampler;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
44
include/osgAnimation/Skeleton
Normal file
44
include/osgAnimation/Skeleton
Normal file
@@ -0,0 +1,44 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_SKELETON_H
|
||||
#define OSGANIMATION_SKELETON_H
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/Export>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT Skeleton : public Bone
|
||||
{
|
||||
public:
|
||||
META_Node(osgAnimation, Skeleton);
|
||||
|
||||
struct UpdateCallback : public osg::NodeCallback
|
||||
{
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
|
||||
Skeleton(const Skeleton& b, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) : Bone(b,copyop) {}
|
||||
Skeleton();
|
||||
|
||||
void computeBindMatrix() { _invBindInSkeletonSpace = osg::Matrix::inverse(_bindInBoneSpace); }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
167
include/osgAnimation/Skinning
Normal file
167
include/osgAnimation/Skinning
Normal file
@@ -0,0 +1,167 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_SKINNING_H
|
||||
#define OSGANIMATION_SKINNING_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <osgAnimation/Assert>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Quat>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
|
||||
class TransformVertexFunctor
|
||||
{
|
||||
public:
|
||||
typedef osg::Matrix MatrixType;
|
||||
typedef osgAnimation::Bone BoneType;
|
||||
typedef Bone::BoneMap BoneMap;
|
||||
|
||||
class BoneWeight
|
||||
{
|
||||
public:
|
||||
BoneWeight(BoneType* bone, float weight) : _bone(bone), _weight(weight) {}
|
||||
const BoneType* getBone() const { return &(*_bone); }
|
||||
float getWeight() const { return _weight; }
|
||||
protected:
|
||||
osg::ref_ptr<BoneType> _bone;
|
||||
float _weight;
|
||||
};
|
||||
|
||||
typedef std::vector<BoneWeight> BoneWeightList;
|
||||
typedef std::vector<int> VertexList;
|
||||
|
||||
class UniqBoneSetVertexSet
|
||||
{
|
||||
public:
|
||||
BoneWeightList& getBones() { return _bones; }
|
||||
VertexList& getVertexes() { return _vertexes; }
|
||||
void computeMatrixForVertexSet()
|
||||
{
|
||||
if (_bones.empty())
|
||||
{
|
||||
osg::notify(osg::WARN) << "TransformVertexFunctor::UniqBoneSetVertexSet no bones found" << std::endl;
|
||||
_result = MatrixType::identity();
|
||||
return;
|
||||
}
|
||||
_result = MatrixType(0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0);
|
||||
int size = _bones.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const BoneType* bone = _bones[i].getBone();
|
||||
const MatrixType& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
|
||||
const MatrixType& matrix = bone->getMatrixInSkeletonSpace();
|
||||
double w = _bones[i].getWeight();
|
||||
_result = _result + ( (invBindMatrix * matrix ) * w);
|
||||
}
|
||||
}
|
||||
const MatrixType& getMatrix() const { return _result;}
|
||||
protected:
|
||||
BoneWeightList _bones;
|
||||
VertexList _vertexes;
|
||||
MatrixType _result;
|
||||
};
|
||||
|
||||
|
||||
void init(const BoneMap& map, const osgAnimation::VertexInfluenceSet::UniqVertexSetToBoneSetList& influence)
|
||||
{
|
||||
_boneSetVertexSet.clear();
|
||||
|
||||
int size = influence.size();
|
||||
_boneSetVertexSet.resize(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const osgAnimation::VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i];
|
||||
int nbBones = inf.getBones().size();
|
||||
|
||||
for (int b = 0; b < nbBones; b++)
|
||||
{
|
||||
const std::string& bname = inf.getBones()[b].getBoneName();
|
||||
float weight = inf.getBones()[b].getWeight();
|
||||
if (map.find(bname) == map.end())
|
||||
{
|
||||
std::cerr << "Warning TransformVertexFunctor Bone " << bname << " not found, skip the influence group " <<bname << std::endl;
|
||||
continue;
|
||||
}
|
||||
BoneMap::const_iterator it = map.find(bname);
|
||||
if (it == map.end())
|
||||
std::cerr << "Warning TransformVertexFunctor does not find bone " << bname << " in the map" << std::endl;
|
||||
BoneType* bone = it->second.get();
|
||||
_boneSetVertexSet[i].getBones().push_back(BoneWeight(bone, weight));
|
||||
}
|
||||
_boneSetVertexSet[i].getVertexes() = inf.getVertexes();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class V> void compute(const V* src, V* dst)
|
||||
{
|
||||
OSGANIMATION_ASSERT(src != dst);
|
||||
int size = _boneSetVertexSet.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
||||
uniq.computeMatrixForVertexSet();
|
||||
const MatrixType& matrix = uniq.getMatrix();
|
||||
|
||||
const VertexList& vertexes = uniq.getVertexes();
|
||||
int vertexSize = vertexes.size();
|
||||
for (int j = 0; j < vertexSize; j++)
|
||||
{
|
||||
int idx = vertexes[j];
|
||||
dst[idx] = src[idx] * matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class V> void compute(const MatrixType& transform, const MatrixType& invTransform, const V* src, V* dst)
|
||||
{
|
||||
OSGANIMATION_ASSERT(src != dst);
|
||||
int size = _boneSetVertexSet.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
||||
uniq.computeMatrixForVertexSet();
|
||||
MatrixType matrix = transform * uniq.getMatrix() * invTransform;
|
||||
|
||||
const VertexList& vertexes = uniq.getVertexes();
|
||||
int vertexSize = vertexes.size();
|
||||
for (int j = 0; j < vertexSize; j++)
|
||||
{
|
||||
int idx = vertexes[j];
|
||||
dst[idx] = src[idx] * matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<UniqBoneSetVertexSet> _boneSetVertexSet;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
132
include/osgAnimation/Target
Normal file
132
include/osgAnimation/Target
Normal file
@@ -0,0 +1,132 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OSGANIMATION_TARGET_H
|
||||
#define OSGANIMATION_TARGET_H
|
||||
|
||||
#include <vector>
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec2>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Referenced>
|
||||
#include <osgAnimation/Export>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class Channel;
|
||||
|
||||
class OSGANIMATION_EXPORT Target : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
Target();
|
||||
virtual ~Target();
|
||||
virtual void normalize() = 0;
|
||||
float getWeight() const { return _weight; }
|
||||
void reset() { _weight = 0;}
|
||||
int getCount() const { return referenceCount(); }
|
||||
protected:
|
||||
|
||||
void addWeight(float w) { _weight += w; }
|
||||
float _weight;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
class TemplateTarget : public Target
|
||||
{
|
||||
public:
|
||||
|
||||
TemplateTarget() {}
|
||||
TemplateTarget(const T& v) { setValue(v); }
|
||||
|
||||
void update(float weight, const T& val)
|
||||
{
|
||||
if (!_weight)
|
||||
_target = val * weight;
|
||||
else
|
||||
{
|
||||
weight = (1.0 - _weight) * weight;
|
||||
_target += val * weight;
|
||||
}
|
||||
addWeight(weight);
|
||||
}
|
||||
const T& getValue() const { return _target;}
|
||||
|
||||
void normalize()
|
||||
{
|
||||
float weightSummed = getWeight();
|
||||
if (fabs(weightSummed) < 1e-4 || fabs(weightSummed-1) < 1e-4)
|
||||
return;
|
||||
(_target) /= weightSummed;
|
||||
}
|
||||
|
||||
void setValue(const T& value) { _target = value;}
|
||||
|
||||
protected:
|
||||
|
||||
T _target;
|
||||
};
|
||||
|
||||
|
||||
// Target Specialisation for Quaternions
|
||||
template <>
|
||||
class TemplateTarget< osg::Quat > : public Target
|
||||
{
|
||||
public:
|
||||
|
||||
TemplateTarget () {}
|
||||
|
||||
const osg::Quat& getValue() const { return _target;}
|
||||
void update(float weight, const osg::Quat& val)
|
||||
{
|
||||
if (!_weight)
|
||||
_target = val * weight;
|
||||
else
|
||||
{
|
||||
weight = (1.0 - _weight) * weight;
|
||||
_target += val * weight;
|
||||
}
|
||||
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;
|
||||
typedef TemplateTarget<osg::Vec4> Vec4Target;
|
||||
typedef TemplateTarget<osg::Vec2> Vec2Target;
|
||||
typedef TemplateTarget<float> FloatTarget;
|
||||
typedef TemplateTarget<double> DoubleTarget;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
563
include/osgAnimation/Timeline
Normal file
563
include/osgAnimation/Timeline
Normal file
@@ -0,0 +1,563 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_TIMELINE_H
|
||||
#define OSGANIMATION_TIMELINE_H
|
||||
|
||||
#include <osg/Object>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Group>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class Action : public virtual osg::Object
|
||||
{
|
||||
public:
|
||||
|
||||
class Callback : public virtual osg::Object
|
||||
{
|
||||
public:
|
||||
Callback(){}
|
||||
Callback(const Callback& nc,const osg::CopyOp&) {}
|
||||
|
||||
META_Object(osgAnimation,Callback);
|
||||
|
||||
virtual void operator()(Action* action) {}
|
||||
void addNestedCallback(Callback* callback)
|
||||
{
|
||||
if (_nested.valid())
|
||||
_nested->addNestedCallback(callback);
|
||||
else
|
||||
_nested = callback;
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<Callback> _nested;
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<unsigned int, osg::ref_ptr<Callback> > FrameCallback;
|
||||
|
||||
META_Object(osgAnimation, Action);
|
||||
Action()
|
||||
{
|
||||
_numberFrame = 25;
|
||||
_fps = 25;
|
||||
_speed = 1.0;
|
||||
_loop = 1;
|
||||
}
|
||||
Action(const Action& nc,const osg::CopyOp&) {}
|
||||
|
||||
void setCallback(double when, Callback* callback)
|
||||
{
|
||||
setCallback(static_cast<unsigned int>(floor(when*_fps)), callback);
|
||||
}
|
||||
|
||||
void setCallback(unsigned int frame, Callback* callback)
|
||||
{
|
||||
if (_framesCallback[frame].valid())
|
||||
_framesCallback[frame]->addNestedCallback(callback);
|
||||
else
|
||||
_framesCallback[frame] = callback;
|
||||
}
|
||||
Callback* getCallback(unsigned int frame)
|
||||
{
|
||||
if (_framesCallback.find(frame) == _framesCallback.end())
|
||||
return 0;
|
||||
return _framesCallback[frame].get();
|
||||
}
|
||||
|
||||
void setNumFrames(unsigned int numFrames) { _numberFrame = numFrames;}
|
||||
void setDuration(double duration) { _numberFrame = static_cast<unsigned int>(floor(duration * _fps)); }
|
||||
|
||||
unsigned int getNumFrames() const { return _numberFrame;}
|
||||
double getDuration() const { return _numberFrame * 1.0 / _fps; }
|
||||
|
||||
// 0 means infini else it's the number of loop
|
||||
virtual void setLoop(int nb) { _loop = nb; }
|
||||
virtual unsigned int getLoop() const { return _loop;}
|
||||
|
||||
// get the number of loop, the frame relative to loop.
|
||||
// return true if in range, and false if out of range.
|
||||
bool evaluateFrame(unsigned int frame, unsigned int& resultframe, unsigned int& nbloop )
|
||||
{
|
||||
nbloop = frame / getNumFrames();
|
||||
resultframe = frame;
|
||||
|
||||
if (frame > getNumFrames()-1)
|
||||
{
|
||||
if (!getLoop())
|
||||
resultframe = frame % getNumFrames();
|
||||
else
|
||||
{
|
||||
if (nbloop >= getLoop())
|
||||
return false;
|
||||
else
|
||||
resultframe = frame % getNumFrames();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
unsigned int frameInAction;
|
||||
unsigned int loopDone;
|
||||
if (!evaluateFrame(frame, frameInAction, loopDone))
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " Action frame " << frameInAction << " finished" << std::endl;
|
||||
else
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " Action frame " << frame << " relative to loop " << frameInAction << " no loop " << loopDone<< std::endl;
|
||||
}
|
||||
|
||||
virtual void evaluateCallback(unsigned int frame)
|
||||
{
|
||||
unsigned int frameInAction;
|
||||
unsigned int loopDone;
|
||||
if (!evaluateFrame(frame, frameInAction, loopDone))
|
||||
return;
|
||||
|
||||
frame = frameInAction;
|
||||
if (_framesCallback.find(frame) != _framesCallback.end())
|
||||
{
|
||||
std::cout << getName() << " evaluate callback " << _framesCallback[frame]->getName() << " at " << frame << std::endl;
|
||||
(*_framesCallback[frame])(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
FrameCallback _framesCallback;
|
||||
|
||||
double _speed;
|
||||
unsigned int _fps;
|
||||
unsigned int _numberFrame;
|
||||
unsigned int _loop;
|
||||
|
||||
enum State
|
||||
{
|
||||
Play,
|
||||
Stop,
|
||||
};
|
||||
|
||||
State _state;
|
||||
};
|
||||
|
||||
|
||||
class Timeline : public virtual osg::Object
|
||||
{
|
||||
protected:
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction;
|
||||
typedef std::vector<FrameAction> ActionList;
|
||||
typedef std::map<int, ActionList> ActionLayers;
|
||||
|
||||
ActionLayers _actions;
|
||||
|
||||
double _lastUpdate;
|
||||
double _speed;
|
||||
unsigned int _currentFrame;
|
||||
unsigned int _fps;
|
||||
unsigned int _numberFrame;
|
||||
unsigned int _previousFrameEvaluated;
|
||||
bool _loop;
|
||||
bool _initFirstFrame;
|
||||
|
||||
enum State
|
||||
{
|
||||
Play,
|
||||
Stop,
|
||||
};
|
||||
|
||||
State _state;
|
||||
|
||||
// to manage pending operation
|
||||
bool _evaluating;
|
||||
|
||||
struct Command
|
||||
{
|
||||
Command():_priority(0) {}
|
||||
Command(int priority, const FrameAction& action) : _priority(priority), _action(action) {}
|
||||
int _priority;
|
||||
FrameAction _action;
|
||||
};
|
||||
|
||||
typedef std::vector<Command> CommandList;
|
||||
CommandList _addActionOperations;
|
||||
ActionList _removeActionOperations;
|
||||
|
||||
void setEvaluating(bool state) { _evaluating = state;}
|
||||
void processPendingOperation()
|
||||
{
|
||||
// process all pending add action operation
|
||||
while( !_addActionOperations.empty())
|
||||
{
|
||||
internalAddAction(_addActionOperations.back()._priority, _addActionOperations.back()._action);
|
||||
_addActionOperations.pop_back();
|
||||
}
|
||||
|
||||
// process all pending remove action operation
|
||||
while( !_removeActionOperations.empty())
|
||||
{
|
||||
internalRemoveAction(_removeActionOperations.back().second);
|
||||
_removeActionOperations.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void internalRemoveAction(Action* action)
|
||||
{
|
||||
for (ActionLayers::iterator it = _actions.begin(); it != _actions.end(); it++)
|
||||
{
|
||||
ActionList& fa = it->second;
|
||||
for (unsigned int i = 0; i < fa.size(); i++)
|
||||
if (fa[i].second.get() == action)
|
||||
{
|
||||
fa.erase(fa.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void internalAddAction(int priority, const FrameAction& ftl)
|
||||
{
|
||||
_actions[priority].push_back(ftl);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
META_Object(osgAnimation, Timeline);
|
||||
|
||||
Timeline()
|
||||
{
|
||||
_lastUpdate = 0;
|
||||
_currentFrame = 0;
|
||||
_fps = 25;
|
||||
_speed = 1.0;
|
||||
_state = Stop;
|
||||
_initFirstFrame = false;
|
||||
_previousFrameEvaluated = 0;
|
||||
_evaluating = 0;
|
||||
_numberFrame = -1; // something like infinity
|
||||
setName("Timeline");
|
||||
}
|
||||
Timeline(const Timeline& nc,const osg::CopyOp&) {}
|
||||
State getStatus() const { return _state; }
|
||||
const ActionList& getActionLayer(int i)
|
||||
{
|
||||
return _actions[i];
|
||||
}
|
||||
unsigned int getCurrentFrame() const { return _currentFrame;}
|
||||
double getCurrentTime() const { return _currentFrame * 1.0 / _fps;}
|
||||
|
||||
void play() { _state = Play; }
|
||||
void gotoFrame(unsigned int frame) { _currentFrame = frame; }
|
||||
void stop() { _state = Stop; }
|
||||
bool getEvaluating() const { return _evaluating;}
|
||||
|
||||
bool isActive(Action* activeAction)
|
||||
{
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::iterator iterAnim = _actions.begin(); iterAnim != _actions.end(); ++iterAnim )
|
||||
{
|
||||
// update all animation
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
Action* action = list[i].second.get();
|
||||
if (action == activeAction)
|
||||
{
|
||||
unsigned int firstFrame = list[i].first;
|
||||
// check if current frame of timeline hit an action interval
|
||||
if (_currentFrame >= firstFrame &&
|
||||
_currentFrame < (firstFrame + action->getNumFrames()) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void removeAction(Action* action)
|
||||
{
|
||||
if (getEvaluating())
|
||||
_removeActionOperations.push_back(FrameAction(0, action));
|
||||
else
|
||||
internalRemoveAction(action);
|
||||
}
|
||||
|
||||
virtual void addActionAt(unsigned int frame, Action* action, int priority = 0)
|
||||
{
|
||||
if (getEvaluating())
|
||||
_addActionOperations.push_back(Command(priority,FrameAction(frame, action)));
|
||||
else
|
||||
internalAddAction(priority, FrameAction(frame, action));
|
||||
}
|
||||
virtual void addActionAt(double t, Action* action, int priority = 0)
|
||||
{
|
||||
unsigned int frame = static_cast<unsigned int>(floor(t * _fps));
|
||||
addActionAt(frame, action, priority);
|
||||
}
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
setEvaluating(true);
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " evaluate frame " << _currentFrame << std::endl;
|
||||
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); iterAnim != _actions.rend(); ++iterAnim )
|
||||
{
|
||||
// update all animation
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
unsigned int firstFrame = list[i].first;
|
||||
Action* action = list[i].second.get();
|
||||
// check if current frame of timeline hit an action interval
|
||||
if (frame >= firstFrame &&
|
||||
frame < (firstFrame + action->getNumFrames()) )
|
||||
action->evaluate(frame - firstFrame);
|
||||
}
|
||||
}
|
||||
setEvaluating(false);
|
||||
|
||||
// evaluate callback after updating all animation
|
||||
evaluateCallback(frame);
|
||||
_previousFrameEvaluated = frame;
|
||||
}
|
||||
|
||||
virtual void evaluateCallback(unsigned int frame)
|
||||
{
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); iterAnim != _actions.rend(); ++iterAnim )
|
||||
{
|
||||
// update all animation
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
unsigned int firstFrame = list[i].first;
|
||||
Action* action = list[i].second.get();
|
||||
// check if current frame of timeline hit an action interval
|
||||
if (frame >= firstFrame &&
|
||||
frame < (firstFrame + action->getNumFrames()) )
|
||||
action->evaluateCallback(frame - firstFrame);
|
||||
}
|
||||
}
|
||||
processPendingOperation();
|
||||
}
|
||||
|
||||
virtual void update(double simulationTime)
|
||||
{
|
||||
// first time we call update we generate one frame
|
||||
if (!_initFirstFrame)
|
||||
{
|
||||
_lastUpdate = simulationTime;
|
||||
_initFirstFrame = true;
|
||||
evaluate(_currentFrame);
|
||||
}
|
||||
|
||||
// find the number of frame pass since the last update
|
||||
double delta = (simulationTime - _lastUpdate);
|
||||
double nbframes = delta * _fps * _speed;
|
||||
unsigned int nb = static_cast<unsigned int>(floor(nbframes));
|
||||
|
||||
for (unsigned int i = 0; i < nb; i++)
|
||||
{
|
||||
if (_state == Play)
|
||||
_currentFrame++;
|
||||
evaluate(_currentFrame);
|
||||
}
|
||||
if (nb)
|
||||
{
|
||||
_lastUpdate += ((double)nb) / _fps;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// blend in from 0 to weight in duration
|
||||
class BlendIn : public Action
|
||||
{
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
|
||||
public:
|
||||
BlendIn(Animation* animation, double duration, double weight)
|
||||
{
|
||||
_animation = animation;
|
||||
_weight = weight;
|
||||
float d = duration * _fps;
|
||||
setNumFrames(static_cast<unsigned int>(floor(d)) + 1);
|
||||
setName("BlendIn");
|
||||
}
|
||||
double getWeight() const { return _weight;}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
// frame + 1 because the start is 0 and we want to start the blend in at the first
|
||||
// frame.
|
||||
double ratio = ( (frame+1) * 1.0 / (getNumFrames()) );
|
||||
double w = _weight;
|
||||
if (frame < getNumFrames() -1 ) // the last frame we set the target weight the user asked
|
||||
w = _weight * ratio;
|
||||
_animation->setWeight(w);
|
||||
}
|
||||
};
|
||||
|
||||
// blend in from 0 to weight in duration
|
||||
class BlendOut : public Action
|
||||
{
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
public:
|
||||
BlendOut(Animation* animation, double duration)
|
||||
{
|
||||
_animation = animation;
|
||||
float d = duration * _fps;
|
||||
setNumFrames(static_cast<unsigned int>(floor(d) + 1));
|
||||
_weight = 1.0;
|
||||
setName("BlendOut");
|
||||
}
|
||||
double getWeight() const { return _weight;}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
// frame + 1 because the start is 0 and we want to start the blend in at the first
|
||||
// frame.
|
||||
double ratio = ( (frame+1) * 1.0 / (getNumFrames()) );
|
||||
double w = 0.0;
|
||||
if (frame < getNumFrames() -1 ) // the last frame we set the target weight the user asked
|
||||
w = _weight * (1.0-ratio);
|
||||
_animation->setWeight(w);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ActionAnimation : public Action
|
||||
{
|
||||
public:
|
||||
ActionAnimation(Animation* animation) : _animation(animation)
|
||||
{
|
||||
setDuration(animation->getDuration());
|
||||
setName(animation->getName());
|
||||
}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
_animation->update(frame * 1.0/_fps);
|
||||
}
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
protected:
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
};
|
||||
|
||||
|
||||
// encapsulate animation with blend in blend out for classic usage
|
||||
class StripAnimation : public Action
|
||||
{
|
||||
protected:
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction;
|
||||
|
||||
public:
|
||||
StripAnimation(Animation* animation, double blendInDuration, double blendOutDuration, double blendInWeightTarget = 1.0 )
|
||||
{
|
||||
_blendIn = new BlendIn(animation, blendInDuration, blendInWeightTarget);
|
||||
_animation = new ActionAnimation(animation);
|
||||
unsigned int start = static_cast<unsigned int>(floor((_animation->getDuration() - blendOutDuration) * _fps));
|
||||
_blendOut = FrameAction(start, new BlendOut(animation, blendOutDuration));
|
||||
setName(animation->getName() + "_Strip");
|
||||
_blendIn->setName(_animation->getName() + "_" + _blendIn->getName());
|
||||
_blendOut.second->setName(_animation->getName() + "_" + _blendOut.second->getName());
|
||||
setDuration(animation->getDuration());
|
||||
}
|
||||
|
||||
ActionAnimation* getActionAnimation() { return _animation.get(); }
|
||||
BlendIn* getBlendIn() { return _blendIn.get(); }
|
||||
BlendOut* getBlendOut() { return dynamic_cast<BlendOut*>(_blendOut.second.get()); }
|
||||
const ActionAnimation* getActionAnimation() const { return _animation.get(); }
|
||||
const BlendIn* getBlendIn() const { return _blendIn.get(); }
|
||||
const BlendOut* getBlendOut() const { return dynamic_cast<BlendOut*>(_blendOut.second.get()); }
|
||||
|
||||
unsigned int getLoop() const { return _animation->getLoop(); }
|
||||
void setLoop(unsigned int loop)
|
||||
{
|
||||
_animation->setLoop(loop);
|
||||
if (!loop)
|
||||
setDuration(-1);
|
||||
else
|
||||
setDuration(loop * _animation->getDuration());
|
||||
|
||||
// duration changed re evaluate the blendout duration
|
||||
unsigned int start = static_cast<unsigned int>(floor((getDuration() - _blendOut.second->getDuration()) * _fps));
|
||||
_blendOut = FrameAction(start, _blendOut.second);
|
||||
}
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
if (frame > getNumFrames() - 1)
|
||||
return;
|
||||
|
||||
Action::evaluate(frame);
|
||||
if (frame < _blendIn->getNumFrames())
|
||||
_blendIn->evaluate(frame);
|
||||
if (frame >= _blendOut.first)
|
||||
_blendOut.second->evaluate(frame - _blendOut.first);
|
||||
_animation->evaluate(frame);
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<BlendIn> _blendIn;
|
||||
FrameAction _blendOut;
|
||||
osg::ref_ptr<ActionAnimation> _animation;
|
||||
};
|
||||
|
||||
|
||||
class RunAction : public Action::Callback
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<Timeline> _tm;
|
||||
osg::ref_ptr<Action> _action;
|
||||
|
||||
public:
|
||||
RunAction(Timeline* tm, Action* a) : _tm(tm), _action(a) {}
|
||||
virtual void operator()(Action* action)
|
||||
{
|
||||
_tm->addActionAt(_tm->getCurrentFrame(), _action.get()); // warning we are trsversing the vector
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class AnimationManagerTimeline : public AnimationManagerBase
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<Timeline> _timeline;
|
||||
|
||||
public:
|
||||
META_Node(osgAnimation, AnimationManagerTimeline);
|
||||
AnimationManagerTimeline();
|
||||
AnimationManagerTimeline(const AnimationManagerBase& manager);
|
||||
AnimationManagerTimeline(const AnimationManagerTimeline& nc,const osg::CopyOp&) {}
|
||||
|
||||
Timeline* getTimeline() { return _timeline.get(); }
|
||||
void update(double time);
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
68
include/osgAnimation/UpdateCallback
Normal file
68
include/osgAnimation/UpdateCallback
Normal file
@@ -0,0 +1,68 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_UPDATE_CALLBACK_H
|
||||
#define OSGANIMATION_UPDATE_CALLBACK_H
|
||||
|
||||
#include <osg/Vec3>
|
||||
#include <osg/NodeCallback>
|
||||
#include <osg/observer_ptr>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/Export>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT AnimationUpdateCallback : public osg::NodeCallback
|
||||
{
|
||||
protected:
|
||||
osg::observer_ptr<osgAnimation::AnimationManagerBase> _manager;
|
||||
|
||||
public:
|
||||
AnimationUpdateCallback(const std::string& name = "") { setName(name); }
|
||||
AnimationUpdateCallback(const AnimationUpdateCallback& apc,const osg::CopyOp& copyop);
|
||||
osgAnimation::AnimationManagerBase* getAnimationManager();
|
||||
virtual bool needLink() const = 0;
|
||||
virtual bool link(osgAnimation::Channel* channel) = 0;
|
||||
virtual int link(osgAnimation::Animation* animation);
|
||||
virtual void updateLink();
|
||||
};
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateTransform : public AnimationUpdateCallback
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<osgAnimation::Vec3Target> _euler;
|
||||
osg::ref_ptr<osgAnimation::Vec3Target> _position;
|
||||
osg::ref_ptr<osgAnimation::Vec3Target> _scale;
|
||||
|
||||
public:
|
||||
|
||||
META_Object(osgAnimation, UpdateTransform);
|
||||
|
||||
UpdateTransform(const std::string& name = "");
|
||||
UpdateTransform(const UpdateTransform& apc,const osg::CopyOp& copyop);
|
||||
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
void update(osg::MatrixTransform& mat);
|
||||
void update(osg::PositionAttitudeTransform& pat);
|
||||
bool needLink() const;
|
||||
bool link(osgAnimation::Channel* channel);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
118
include/osgAnimation/Vec3Packed
Normal file
118
include/osgAnimation/Vec3Packed
Normal file
@@ -0,0 +1,118 @@
|
||||
/* -*-c++-*-
|
||||
*/
|
||||
//****************************************************************************//
|
||||
// loader.cpp //
|
||||
// Copyright (C) 2001, 2002 Bruno 'Beosil' Heidelberger //
|
||||
//****************************************************************************//
|
||||
// This library is free software; you can redistribute it and/or modify it //
|
||||
// under the terms of the GNU Lesser General Public License as published by //
|
||||
// the Free Software Foundation; either version 2.1 of the License, or (at //
|
||||
// your option) any later version. //
|
||||
//****************************************************************************//
|
||||
/*****************************************************************************/
|
||||
/** Loads a core compressed keyframe instance.
|
||||
*
|
||||
* This function loads a core compressed keyframe instance from a data source.
|
||||
*
|
||||
* @param dataSrc The data source to load the core compressed keyframe instance from.
|
||||
*
|
||||
* @return One of the following values:
|
||||
* \li a pointer to the core keyframe
|
||||
* \li \b 0 if an error happened
|
||||
* Authors
|
||||
* Igor Kravchenko
|
||||
* Cedric Pinson <mornifle@plopbyte.net>
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef OSGANIMATION_PACKED_H
|
||||
#define OSGANIMATION_PACKED_H
|
||||
|
||||
#include <float.h>
|
||||
#include <vector>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Math>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
|
||||
struct Vec3Packed
|
||||
{
|
||||
typedef unsigned int uint32_t;
|
||||
uint32_t m32bits;
|
||||
Vec3Packed(uint32_t val): m32bits(val) {}
|
||||
Vec3Packed(): m32bits(0) {}
|
||||
|
||||
void uncompress(const osg::Vec3& scale, const osg::Vec3& min, osg::Vec3& result) const
|
||||
{
|
||||
uint32_t pt[3];
|
||||
pt[0] = m32bits & 0x7ff;
|
||||
pt[1] = (m32bits >> 11) & 0x7ff;
|
||||
pt[2] = m32bits >> 22;
|
||||
result[0] = scale[0] * pt[0] + min[0];
|
||||
result[1] = scale[1] * pt[1] + min[1];
|
||||
result[2] = scale[2] * pt[2] + min[2];
|
||||
}
|
||||
|
||||
void compress(const osg::Vec3f& src, const osg::Vec3f& min, const osg::Vec3f& scaleInv)
|
||||
{
|
||||
uint32_t srci[3];
|
||||
srci[0] = osg::minimum(static_cast<uint32_t>(((src[0] - min[0] )*scaleInv[0])), uint32_t(2047));
|
||||
srci[1] = osg::minimum(static_cast<uint32_t>(((src[1] - min[1] )*scaleInv[1])), uint32_t(2047));
|
||||
srci[2] = osg::minimum(static_cast<uint32_t>(((src[2] - min[2] )*scaleInv[2])), uint32_t(1023));
|
||||
m32bits = srci[0] + (srci[1] << 11) + (srci[2] << 22);
|
||||
}
|
||||
};
|
||||
|
||||
struct Vec3ArrayPacked
|
||||
{
|
||||
std::vector<Vec3Packed> mVecCompressed;
|
||||
osg::Vec3 mMin;
|
||||
osg::Vec3 mScale;
|
||||
osg::Vec3 mScaleInv;
|
||||
|
||||
void analyze(const std::vector<osg::Vec3>& src)
|
||||
{
|
||||
//analyze the keys
|
||||
mMin.set(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
osg::Vec3 maxp(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
int nb = (int)src.size();
|
||||
for(int i = 0; i < nb; i++)
|
||||
{
|
||||
const osg::Vec3 &pos = src[i];
|
||||
for(int j = 0; j < 3; j++)
|
||||
{
|
||||
maxp[j] = osg::maximum(pos[j],maxp[j]);
|
||||
mMin[j] = osg::minimum(pos[j],mMin[j]);
|
||||
}
|
||||
}
|
||||
|
||||
osg::Vec3 diff = maxp - mMin;
|
||||
mScaleInv.set(0,0,0);
|
||||
if (diff[0] != 0)
|
||||
mScaleInv[0] = 2047.0/diff[0];
|
||||
|
||||
if (diff[1] != 0)
|
||||
mScaleInv[1] = 2047.0/diff[1];
|
||||
|
||||
if (diff[2] != 0)
|
||||
mScaleInv[2] = 1023.0/diff[2];
|
||||
|
||||
mScale[0] = diff[0] / 2047;
|
||||
mScale[1] = diff[1] / 2047;
|
||||
mScale[2] = diff[2] / 1023;
|
||||
}
|
||||
|
||||
void compress(const std::vector<osg::Vec3>& src)
|
||||
{
|
||||
mVecCompressed.resize(src.size());
|
||||
// save all core keyframes
|
||||
for(int i = 0; i < (int)src.size(); i++)
|
||||
mVecCompressed[i].compress(src[i], mMin, mScaleInv);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
108
include/osgAnimation/VertexInfluence
Normal file
108
include/osgAnimation/VertexInfluence
Normal file
@@ -0,0 +1,108 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@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
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_VERTEX_INFLUENCES_H
|
||||
#define OSGANIMATION_VERTEX_INFLUENCES_H
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osgAnimation/Export>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
// first is vertex index, and second the weight, the
|
||||
typedef std::pair<int, float> VertexIndexWeight;
|
||||
typedef std::vector<VertexIndexWeight> VertexList;
|
||||
class OSGANIMATION_EXPORT VertexInfluence : public VertexList
|
||||
{
|
||||
public:
|
||||
const std::string& getName() const { return _name;}
|
||||
void setName(const std::string& name) { _name = name;}
|
||||
|
||||
protected:
|
||||
// the name is the bone to link to
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
// typedef std::map<std::string, VertexInfluence> VertexInfluenceMap;
|
||||
|
||||
class VertexInfluenceMap : public std::map<std::string, VertexInfluence> , public osg::Object
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, VertexInfluenceMap);
|
||||
|
||||
VertexInfluenceMap() {}
|
||||
VertexInfluenceMap(const osgAnimation::VertexInfluenceMap& infl, const osg::CopyOp&) {;}
|
||||
};
|
||||
|
||||
|
||||
// this class manage VertexInfluence database by mesh
|
||||
// reference bones per vertex ...
|
||||
class VertexInfluenceSet
|
||||
{
|
||||
public:
|
||||
typedef std::vector<VertexInfluence> BoneToVertexList;
|
||||
|
||||
class BoneWeight
|
||||
{
|
||||
public:
|
||||
BoneWeight(const std::string& name, float weight) : _boneName(name), _weight(weight) {}
|
||||
const std::string& getBoneName() const { return _boneName; }
|
||||
float getWeight() const { return _weight; }
|
||||
void setWeight(float weight) { _weight = weight; }
|
||||
bool operator==(const BoneWeight& b) const { return (_boneName == b.getBoneName() && _weight == b.getWeight()); }
|
||||
protected:
|
||||
std::string _boneName;
|
||||
float _weight;
|
||||
};
|
||||
|
||||
typedef std::vector<BoneWeight> BoneWeightList;
|
||||
typedef std::map<int,BoneWeightList> VertexIndexToBoneWeightMap;
|
||||
|
||||
class UniqVertexSetToBoneSet
|
||||
{
|
||||
public:
|
||||
void setBones(BoneWeightList& bones) { _bones = bones;}
|
||||
const BoneWeightList& getBones() const { return _bones;}
|
||||
std::vector<int>& getVertexes() { return _vertexes;}
|
||||
const std::vector<int>& getVertexes() const { return _vertexes;}
|
||||
protected:
|
||||
std::vector<int> _vertexes;
|
||||
BoneWeightList _bones; // here we could limit matrix operation by caching (weight * matrix)
|
||||
};
|
||||
|
||||
typedef std::vector<UniqVertexSetToBoneSet> UniqVertexSetToBoneSetList;
|
||||
|
||||
const UniqVertexSetToBoneSetList& getUniqVertexSetToBoneSetList() const { return _uniqVertexSetToBoneSet;}
|
||||
void addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); }
|
||||
void buildVertex2BoneList();
|
||||
void buildUniqVertexSetToBoneSetList();
|
||||
void clear()
|
||||
{
|
||||
_bone2Vertexes.clear();
|
||||
_bone2Vertexes.clear();
|
||||
_uniqVertexSetToBoneSet.clear();
|
||||
}
|
||||
protected:
|
||||
BoneToVertexList _bone2Vertexes;
|
||||
VertexIndexToBoneWeightMap _vertex2Bones;
|
||||
UniqVertexSetToBoneSetList _uniqVertexSetToBoneSet;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user