OpenSceneGraph/include/osg/AnimationPath

137 lines
4.6 KiB
Plaintext

//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSG_ANIMATIONPATH
#define OSG_ANIMATIONPATH 1
#include <osg/Matrix>
#include <osg/Quat>
#include <map>
namespace osg {
/** AnimationPath for specify the time varying transformation pathway to use when update camera and model objects.
* Subclassed from Transform::ComputeTransformCallback allows AnimationPath to
* be attached directly to Transform nodes to move subgraphs around the scene.
*/
class SG_EXPORT AnimationPath : public virtual osg::Object
{
public:
AnimationPath():_loopMode(LOOP) {}
AnimationPath(const AnimationPath& ap, const CopyOp& copyop=CopyOp::SHALLOW_COPY):
Object(ap,copyop),
_timeControlPointMap(ap._timeControlPointMap),
_loopMode(ap._loopMode) {}
META_Object(osg,AnimationPath)
struct ControlPoint
{
ControlPoint():
_scale(1.0f,1.0f,1.0f) {}
ControlPoint(const osg::Vec3& position):
_position(position),
_rotation(),
_scale(1.0f,1.0f,1.0f) {}
ControlPoint(const osg::Vec3& position, const osg::Quat& rotation):
_position(position),
_rotation(rotation),
_scale(1.0f,1.0f,1.0f) {}
ControlPoint(const osg::Vec3& position, const osg::Quat& rotation, const osg::Vec3& scale):
_position(position),
_rotation(rotation),
_scale(scale) {}
osg::Vec3 _position;
osg::Quat _rotation;
osg::Vec3 _scale;
inline void interpolate(float ratio,const ControlPoint& first, const ControlPoint& second)
{
float one_minus_ratio = 1.0f-ratio;
_position = first._position*one_minus_ratio + second._position*ratio;
_rotation.slerp(ratio,first._rotation,second._rotation);
_scale = first._scale*one_minus_ratio + second._scale*ratio;
}
inline void getMatrix(Matrix& matrix) const
{
matrix.makeScale(_scale);
matrix.postMult(_rotation.getMatrix());
matrix.postMult(osg::Matrix::translate(_position));
}
inline void getInverse(Matrix& matrix) const
{
matrix.makeScale(1.0f/_scale.x(),1.0f/_scale.y(),1.0f/_scale.y());
matrix.postMult(_rotation.inverse().getMatrix());
matrix.postMult(osg::Matrix::translate(-_position));
}
};
/** get the transformation matrix for a point in time.*/
bool getMatrix(double time,Matrix& matrix) const
{
ControlPoint cp;
if (!getInterpolatedControlPoint(time,cp)) return false;
cp.getMatrix(matrix);
return true;
}
/** get the inverse transformation matrix for a point in time.*/
bool getInverse(double time,Matrix& matrix) const
{
ControlPoint cp;
if (!getInterpolatedControlPoint(time,cp)) return false;
cp.getInverse(matrix);
return true;
}
/** get the local ControlPoint frame for a point in time.*/
virtual bool getInterpolatedControlPoint(double time,ControlPoint& controlPoint) const;
void insert(double time,const ControlPoint& controlPoint);
double getFirstTime() const { if (!_timeControlPointMap.empty()) return _timeControlPointMap.begin()->first; else return 0.0;}
double getLastTime() const { if (!_timeControlPointMap.empty()) return _timeControlPointMap.rbegin()->first; else return 0.0;}
double getPeriod() const { return getLastTime()-getFirstTime();}
enum LoopMode
{
SWING,
LOOP,
NO_LOOPING
};
void setLoopMode(LoopMode lm) { _loopMode = lm; }
LoopMode getLoopMode() const { return _loopMode; }
typedef std::map<double,ControlPoint> TimeControlPointMap;
TimeControlPointMap& getTimeControlPointMap() { return _timeControlPointMap; }
const TimeControlPointMap& getTimeControlPointMap() const { return _timeControlPointMap; }
protected:
virtual ~AnimationPath() {}
TimeControlPointMap _timeControlPointMap;
LoopMode _loopMode;
};
}
#endif