2003-01-22 00:45:36 +08:00
|
|
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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.
|
|
|
|
*/
|
2002-02-27 08:58:54 +08:00
|
|
|
|
|
|
|
#ifndef OSG_ANIMATIONPATH
|
|
|
|
#define OSG_ANIMATIONPATH 1
|
|
|
|
|
2003-09-06 06:35:34 +08:00
|
|
|
#include <osg/Matrixf>
|
|
|
|
#include <osg/Matrixd>
|
2002-02-27 08:58:54 +08:00
|
|
|
#include <osg/Quat>
|
2003-01-04 05:42:02 +08:00
|
|
|
#include <osg/NodeCallback>
|
2002-02-27 08:58:54 +08:00
|
|
|
|
|
|
|
#include <map>
|
2004-01-13 17:47:31 +08:00
|
|
|
#include <float.h>
|
2002-02-27 08:58:54 +08:00
|
|
|
|
|
|
|
namespace osg {
|
|
|
|
|
2002-04-22 06:05:26 +08:00
|
|
|
/** 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.
|
2002-02-27 08:58:54 +08:00
|
|
|
*/
|
2002-12-16 17:55:30 +08:00
|
|
|
class SG_EXPORT AnimationPath : public virtual osg::Object
|
2002-02-27 08:58:54 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
AnimationPath():_loopMode(LOOP) {}
|
2002-04-22 06:05:26 +08:00
|
|
|
|
2002-12-16 17:55:30 +08:00
|
|
|
AnimationPath(const AnimationPath& ap, const CopyOp& copyop=CopyOp::SHALLOW_COPY):
|
|
|
|
Object(ap,copyop),
|
|
|
|
_timeControlPointMap(ap._timeControlPointMap),
|
|
|
|
_loopMode(ap._loopMode) {}
|
|
|
|
|
2003-04-27 18:58:39 +08:00
|
|
|
META_Object(osg,AnimationPath);
|
2002-12-16 17:55:30 +08:00
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
struct ControlPoint
|
|
|
|
{
|
2002-10-08 04:01:28 +08:00
|
|
|
ControlPoint():
|
|
|
|
_scale(1.0f,1.0f,1.0f) {}
|
2002-04-22 06:05:26 +08:00
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
ControlPoint(const osg::Vec3& position):
|
|
|
|
_position(position),
|
|
|
|
_rotation(),
|
2002-10-08 04:01:28 +08:00
|
|
|
_scale(1.0f,1.0f,1.0f) {}
|
2002-04-22 06:05:26 +08:00
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
ControlPoint(const osg::Vec3& position, const osg::Quat& rotation):
|
|
|
|
_position(position),
|
|
|
|
_rotation(rotation),
|
2002-10-08 04:01:28 +08:00
|
|
|
_scale(1.0f,1.0f,1.0f) {}
|
2002-02-27 08:58:54 +08:00
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
ControlPoint(const osg::Vec3& position, const osg::Quat& rotation, const osg::Vec3& scale):
|
2002-02-27 08:58:54 +08:00
|
|
|
_position(position),
|
|
|
|
_rotation(rotation),
|
|
|
|
_scale(scale) {}
|
|
|
|
|
|
|
|
osg::Vec3 _position;
|
|
|
|
osg::Quat _rotation;
|
|
|
|
osg::Vec3 _scale;
|
2003-11-04 07:13:31 +08:00
|
|
|
|
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
inline void interpolate(float ratio,const ControlPoint& first, const ControlPoint& second)
|
2002-02-27 08:58:54 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-09-06 06:35:34 +08:00
|
|
|
inline void getMatrix(Matrixf& matrix) const
|
2002-02-27 08:58:54 +08:00
|
|
|
{
|
|
|
|
matrix.makeScale(_scale);
|
2003-09-06 06:35:34 +08:00
|
|
|
matrix.postMult(osg::Matrixf::rotate(_rotation));
|
|
|
|
matrix.postMult(osg::Matrixf::translate(_position));
|
2002-02-27 08:58:54 +08:00
|
|
|
}
|
|
|
|
|
2003-09-06 06:35:34 +08:00
|
|
|
inline void getMatrix(Matrixd& matrix) const
|
|
|
|
{
|
|
|
|
matrix.makeScale(_scale);
|
|
|
|
matrix.postMult(osg::Matrixd::rotate(_rotation));
|
|
|
|
matrix.postMult(osg::Matrixd::translate(_position));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void getInverse(Matrixf& matrix) const
|
|
|
|
{
|
|
|
|
matrix.makeScale(1.0f/_scale.x(),1.0f/_scale.y(),1.0f/_scale.y());
|
2003-11-04 07:13:31 +08:00
|
|
|
matrix.preMult(osg::Matrixf::rotate(_rotation.inverse()));
|
|
|
|
matrix.preMult(osg::Matrixf::translate(-_position));
|
2003-09-06 06:35:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void getInverse(Matrixd& matrix) const
|
2002-02-27 08:58:54 +08:00
|
|
|
{
|
|
|
|
matrix.makeScale(1.0f/_scale.x(),1.0f/_scale.y(),1.0f/_scale.y());
|
2003-11-04 07:13:31 +08:00
|
|
|
matrix.preMult(osg::Matrixd::rotate(_rotation.inverse()));
|
|
|
|
matrix.preMult(osg::Matrixd::translate(-_position));
|
2002-02-27 08:58:54 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
|
|
|
|
/** get the transformation matrix for a point in time.*/
|
2003-09-06 06:35:34 +08:00
|
|
|
bool getMatrix(double time,Matrixf& matrix) const
|
|
|
|
{
|
|
|
|
ControlPoint cp;
|
|
|
|
if (!getInterpolatedControlPoint(time,cp)) return false;
|
|
|
|
cp.getMatrix(matrix);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** get the transformation matrix for a point in time.*/
|
|
|
|
bool getMatrix(double time,Matrixd& matrix) const
|
2002-08-13 23:31:10 +08:00
|
|
|
{
|
|
|
|
ControlPoint cp;
|
|
|
|
if (!getInterpolatedControlPoint(time,cp)) return false;
|
|
|
|
cp.getMatrix(matrix);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** get the inverse transformation matrix for a point in time.*/
|
2003-09-06 06:35:34 +08:00
|
|
|
bool getInverse(double time,Matrixf& matrix) const
|
2002-08-13 23:31:10 +08:00
|
|
|
{
|
|
|
|
ControlPoint cp;
|
|
|
|
if (!getInterpolatedControlPoint(time,cp)) return false;
|
|
|
|
cp.getInverse(matrix);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2003-09-06 06:35:34 +08:00
|
|
|
bool getInverse(double time,Matrixd& matrix) const
|
|
|
|
{
|
|
|
|
ControlPoint cp;
|
|
|
|
if (!getInterpolatedControlPoint(time,cp)) return false;
|
|
|
|
cp.getInverse(matrix);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
/** get the local ControlPoint frame for a point in time.*/
|
2002-10-10 22:58:44 +08:00
|
|
|
virtual bool getInterpolatedControlPoint(double time,ControlPoint& controlPoint) const;
|
2002-08-13 23:31:10 +08:00
|
|
|
|
2002-10-10 22:58:44 +08:00
|
|
|
void insert(double time,const ControlPoint& controlPoint);
|
2002-08-13 23:31:10 +08:00
|
|
|
|
|
|
|
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; }
|
2002-02-27 08:58:54 +08:00
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
LoopMode getLoopMode() const { return _loopMode; }
|
2002-02-27 08:58:54 +08:00
|
|
|
|
2002-11-06 18:24:33 +08:00
|
|
|
|
|
|
|
typedef std::map<double,ControlPoint> TimeControlPointMap;
|
|
|
|
|
|
|
|
TimeControlPointMap& getTimeControlPointMap() { return _timeControlPointMap; }
|
|
|
|
|
|
|
|
const TimeControlPointMap& getTimeControlPointMap() const { return _timeControlPointMap; }
|
2003-11-04 07:13:31 +08:00
|
|
|
|
|
|
|
/** read the anumation path from a flat ascii file stream.*/
|
|
|
|
void read(std::istream& in);
|
|
|
|
|
|
|
|
/** write the anumation path to a flat ascii file stream.*/
|
2004-02-21 04:10:51 +08:00
|
|
|
void write(std::ostream& out) const;
|
2002-11-06 18:24:33 +08:00
|
|
|
|
2002-02-27 08:58:54 +08:00
|
|
|
protected:
|
|
|
|
|
|
|
|
virtual ~AnimationPath() {}
|
|
|
|
|
2002-08-13 23:31:10 +08:00
|
|
|
TimeControlPointMap _timeControlPointMap;
|
|
|
|
LoopMode _loopMode;
|
2002-02-27 08:58:54 +08:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2003-01-03 04:10:04 +08:00
|
|
|
|
2003-01-04 05:42:02 +08:00
|
|
|
class SG_EXPORT AnimationPathCallback : public NodeCallback
|
2003-01-03 04:10:04 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
AnimationPathCallback():
|
2004-02-21 04:10:51 +08:00
|
|
|
_useInverseMatrix(false),
|
2003-01-03 04:10:04 +08:00
|
|
|
_timeOffset(0.0),
|
|
|
|
_timeMultiplier(1.0),
|
2004-01-12 21:53:04 +08:00
|
|
|
_firstTime(DBL_MAX),
|
2003-11-04 07:13:31 +08:00
|
|
|
_latestTime(0.0),
|
2004-02-21 04:47:35 +08:00
|
|
|
_pause(false),
|
2003-11-04 07:13:31 +08:00
|
|
|
_pauseTime(0.0) {}
|
2003-01-03 04:10:04 +08:00
|
|
|
|
|
|
|
AnimationPathCallback(const AnimationPathCallback& apc,const CopyOp& copyop):
|
|
|
|
NodeCallback(apc,copyop),
|
|
|
|
_animationPath(apc._animationPath),
|
2003-11-04 07:13:31 +08:00
|
|
|
_useInverseMatrix(apc._useInverseMatrix),
|
2003-01-03 04:10:04 +08:00
|
|
|
_timeOffset(apc._timeOffset),
|
|
|
|
_timeMultiplier(apc._timeMultiplier),
|
|
|
|
_firstTime(apc._firstTime),
|
2003-11-04 07:13:31 +08:00
|
|
|
_latestTime(apc._latestTime),
|
|
|
|
_pause(apc._pause),
|
|
|
|
_pauseTime(apc._pauseTime) {}
|
2003-01-03 04:10:04 +08:00
|
|
|
|
|
|
|
|
2003-04-27 18:58:39 +08:00
|
|
|
META_Object(osg,AnimationPathCallback);
|
2003-01-03 04:10:04 +08:00
|
|
|
|
|
|
|
AnimationPathCallback(AnimationPath* ap,double timeOffset=0.0f,double timeMultiplier=1.0f):
|
|
|
|
_animationPath(ap),
|
2003-11-04 07:13:31 +08:00
|
|
|
_useInverseMatrix(false),
|
2003-01-03 04:10:04 +08:00
|
|
|
_timeOffset(timeOffset),
|
|
|
|
_timeMultiplier(timeMultiplier),
|
2004-01-12 21:53:04 +08:00
|
|
|
_firstTime(DBL_MAX),
|
2003-11-04 07:13:31 +08:00
|
|
|
_latestTime(0.0),
|
|
|
|
_pause(false),
|
|
|
|
_pauseTime(0.0) {}
|
2004-02-22 00:56:23 +08:00
|
|
|
|
2003-01-03 04:10:04 +08:00
|
|
|
|
|
|
|
void setAnimationPath(AnimationPath* path) { _animationPath = path; }
|
|
|
|
|
|
|
|
AnimationPath* getAnimationPath() { return _animationPath.get(); }
|
|
|
|
|
|
|
|
const AnimationPath* getAnimationPath() const { return _animationPath.get(); }
|
2003-11-04 07:13:31 +08:00
|
|
|
|
|
|
|
void setUseInverseMatrix(bool useInverseMatrix) { _useInverseMatrix = useInverseMatrix; }
|
|
|
|
bool getUseInverseMatrix() const { return _useInverseMatrix; }
|
|
|
|
|
2004-02-22 00:56:23 +08:00
|
|
|
void setTimeOffset(double offset) { _timeOffset = offset; }
|
|
|
|
double getTimeOffset() const { return _timeOffset; }
|
|
|
|
|
|
|
|
void setTimeMultiplier(double multiplier) { _timeMultiplier = multiplier; }
|
|
|
|
double getTimeMultiplier() const { return _timeMultiplier; }
|
|
|
|
|
|
|
|
|
2003-11-04 07:13:31 +08:00
|
|
|
void reset();
|
2003-01-03 04:10:04 +08:00
|
|
|
|
2003-11-04 07:13:31 +08:00
|
|
|
void setPause(bool pause);
|
2003-01-03 04:10:04 +08:00
|
|
|
|
2004-01-31 19:34:28 +08:00
|
|
|
/** get the animation time that is used to specify the position along the AnimationPath.
|
|
|
|
* Animation time is computed from the formula ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier.*/
|
|
|
|
double getAnimationTime() const;
|
|
|
|
|
2003-01-03 04:10:04 +08:00
|
|
|
/** implements the callback*/
|
|
|
|
virtual void operator()(Node* node, NodeVisitor* nv);
|
|
|
|
|
2003-11-04 07:13:31 +08:00
|
|
|
void update(osg::Node& node);
|
2003-01-03 04:10:04 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
ref_ptr<AnimationPath> _animationPath;
|
2003-11-04 07:13:31 +08:00
|
|
|
bool _useInverseMatrix;
|
2003-01-03 04:10:04 +08:00
|
|
|
double _timeOffset;
|
|
|
|
double _timeMultiplier;
|
|
|
|
double _firstTime;
|
2003-11-04 07:13:31 +08:00
|
|
|
double _latestTime;
|
|
|
|
bool _pause;
|
|
|
|
double _pauseTime;
|
2003-01-10 17:25:42 +08:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
~AnimationPathCallback(){}
|
|
|
|
|
2003-01-03 04:10:04 +08:00
|
|
|
};
|
|
|
|
|
2002-02-27 08:58:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|