You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
314 lines
11 KiB
314 lines
11 KiB
/* -*-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. |
|
*/ |
|
|
|
#ifndef OSG_ANIMATIONPATH |
|
#define OSG_ANIMATIONPATH 1 |
|
|
|
#include <map> |
|
#include <istream> |
|
#include <float.h> |
|
|
|
#include <osg/Matrixf> |
|
#include <osg/Matrixd> |
|
#include <osg/Quat> |
|
#include <osg/NodeCallback> |
|
|
|
namespace osg { |
|
|
|
/** AnimationPath encapsulates a time varying transformation pathway. Can be |
|
* used for updating camera position and model object position. |
|
* AnimationPathCallback can be attached directly to Transform nodes to |
|
* move subgraphs around the scene. |
|
*/ |
|
class OSG_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); |
|
|
|
class ControlPoint |
|
{ |
|
public: |
|
ControlPoint(): |
|
_scale(1.0,1.0,1.0) {} |
|
|
|
ControlPoint(const osg::Vec3d& position): |
|
_position(position), |
|
_rotation(), |
|
_scale(1.0,1.0,1.0) {} |
|
|
|
ControlPoint(const osg::Vec3d& position, const osg::Quat& rotation): |
|
_position(position), |
|
_rotation(rotation), |
|
_scale(1.0,1.0,1.0) {} |
|
|
|
ControlPoint(const osg::Vec3d& position, const osg::Quat& rotation, const osg::Vec3d& scale): |
|
_position(position), |
|
_rotation(rotation), |
|
_scale(scale) {} |
|
|
|
void setPosition(const osg::Vec3d& position) { _position = position; } |
|
const osg::Vec3d& getPosition() const { return _position; } |
|
|
|
void setRotation(const osg::Quat& rotation) { _rotation = rotation; } |
|
const osg::Quat& getRotation() const { return _rotation; } |
|
|
|
void setScale(const osg::Vec3d& scale) { _scale = scale; } |
|
const osg::Vec3d& getScale() const { return _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 interpolate(double ratio,const ControlPoint& first, const ControlPoint& second) |
|
{ |
|
double 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(Matrixf& matrix) const |
|
{ |
|
matrix.makeRotate(_rotation); |
|
matrix.preMultScale(_scale); |
|
matrix.postMultTranslate(_position); |
|
} |
|
|
|
inline void getMatrix(Matrixd& matrix) const |
|
{ |
|
matrix.makeRotate(_rotation); |
|
matrix.preMultScale(_scale); |
|
matrix.postMultTranslate(_position); |
|
} |
|
|
|
inline void getInverse(Matrixf& matrix) const |
|
{ |
|
matrix.makeRotate(_rotation.inverse()); |
|
matrix.postMultScale(osg::Vec3d(1.0/_scale.x(),1.0/_scale.y(),1.0/_scale.z())); |
|
matrix.preMultTranslate(-_position); |
|
} |
|
|
|
inline void getInverse(Matrixd& matrix) const |
|
{ |
|
matrix.makeRotate(_rotation.inverse()); |
|
matrix.postMultScale(osg::Vec3d(1.0/_scale.x(),1.0/_scale.y(),1.0/_scale.z())); |
|
matrix.preMultTranslate(-_position); |
|
} |
|
|
|
protected: |
|
|
|
osg::Vec3d _position; |
|
osg::Quat _rotation; |
|
osg::Vec3d _scale; |
|
|
|
}; |
|
|
|
|
|
/** Given a specific time, return the transformation matrix for a point. */ |
|
bool getMatrix(double time,Matrixf& matrix) const |
|
{ |
|
ControlPoint cp; |
|
if (!getInterpolatedControlPoint(time,cp)) return false; |
|
cp.getMatrix(matrix); |
|
return true; |
|
} |
|
|
|
/** Given a specific time, return the transformation matrix for a point. */ |
|
bool getMatrix(double time,Matrixd& matrix) const |
|
{ |
|
ControlPoint cp; |
|
if (!getInterpolatedControlPoint(time,cp)) return false; |
|
cp.getMatrix(matrix); |
|
return true; |
|
} |
|
|
|
/** Given a specific time, return the inverse transformation matrix for a point. */ |
|
bool getInverse(double time,Matrixf& matrix) const |
|
{ |
|
ControlPoint cp; |
|
if (!getInterpolatedControlPoint(time,cp)) return false; |
|
cp.getInverse(matrix); |
|
return true; |
|
} |
|
|
|
bool getInverse(double time,Matrixd& matrix) const |
|
{ |
|
ControlPoint cp; |
|
if (!getInterpolatedControlPoint(time,cp)) return false; |
|
cp.getInverse(matrix); |
|
return true; |
|
} |
|
|
|
/** Given a specific time, return the local ControlPoint frame for a point. */ |
|
virtual bool getInterpolatedControlPoint(double time,ControlPoint& controlPoint) const; |
|
|
|
/** Insert a control point into the AnimationPath.*/ |
|
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; |
|
|
|
void setTimeControlPointMap(TimeControlPointMap& tcpm) { _timeControlPointMap=tcpm; } |
|
|
|
TimeControlPointMap& getTimeControlPointMap() { return _timeControlPointMap; } |
|
|
|
const TimeControlPointMap& getTimeControlPointMap() const { return _timeControlPointMap; } |
|
|
|
bool empty() const { return _timeControlPointMap.empty(); } |
|
|
|
void clear() { _timeControlPointMap.clear(); } |
|
|
|
/** Read the animation path from a flat ASCII file stream. */ |
|
void read(std::istream& in); |
|
|
|
/** Write the animation path to a flat ASCII file stream. */ |
|
void write(std::ostream& out) const; |
|
|
|
/** Write the control point to a flat ASCII file stream. */ |
|
void write(TimeControlPointMap::const_iterator itr, std::ostream& out) const; |
|
|
|
protected: |
|
|
|
virtual ~AnimationPath() {} |
|
|
|
TimeControlPointMap _timeControlPointMap; |
|
LoopMode _loopMode; |
|
|
|
}; |
|
|
|
|
|
class OSG_EXPORT AnimationPathCallback : public NodeCallback |
|
{ |
|
public: |
|
|
|
AnimationPathCallback(): |
|
_pivotPoint(0.0,0.0,0.0), |
|
_useInverseMatrix(false), |
|
_timeOffset(0.0), |
|
_timeMultiplier(1.0), |
|
_firstTime(DBL_MAX), |
|
_latestTime(0.0), |
|
_pause(false), |
|
_pauseTime(0.0) {} |
|
|
|
AnimationPathCallback(const AnimationPathCallback& apc,const CopyOp& copyop): |
|
NodeCallback(apc,copyop), |
|
_animationPath(apc._animationPath), |
|
_pivotPoint(apc._pivotPoint), |
|
_useInverseMatrix(apc._useInverseMatrix), |
|
_timeOffset(apc._timeOffset), |
|
_timeMultiplier(apc._timeMultiplier), |
|
_firstTime(apc._firstTime), |
|
_latestTime(apc._latestTime), |
|
_pause(apc._pause), |
|
_pauseTime(apc._pauseTime) {} |
|
|
|
|
|
META_Object(osg,AnimationPathCallback); |
|
|
|
/** Construct an AnimationPathCallback with a specified animation path.*/ |
|
AnimationPathCallback(AnimationPath* ap,double timeOffset=0.0,double timeMultiplier=1.0): |
|
_animationPath(ap), |
|
_pivotPoint(0.0,0.0,0.0), |
|
_useInverseMatrix(false), |
|
_timeOffset(timeOffset), |
|
_timeMultiplier(timeMultiplier), |
|
_firstTime(DBL_MAX), |
|
_latestTime(0.0), |
|
_pause(false), |
|
_pauseTime(0.0) {} |
|
|
|
/** Construct an AnimationPathCallback and automatically create an animation path to produce a rotation about a point.*/ |
|
AnimationPathCallback(const osg::Vec3d& pivot,const osg::Vec3d& axis,float angularVelocity); |
|
|
|
|
|
void setAnimationPath(AnimationPath* path) { _animationPath = path; } |
|
AnimationPath* getAnimationPath() { return _animationPath.get(); } |
|
const AnimationPath* getAnimationPath() const { return _animationPath.get(); } |
|
|
|
inline void setPivotPoint(const Vec3d& pivot) { _pivotPoint = pivot; } |
|
inline const Vec3d& getPivotPoint() const { return _pivotPoint; } |
|
|
|
void setUseInverseMatrix(bool useInverseMatrix) { _useInverseMatrix = useInverseMatrix; } |
|
bool getUseInverseMatrix() const { return _useInverseMatrix; } |
|
|
|
void setTimeOffset(double offset) { _timeOffset = offset; } |
|
double getTimeOffset() const { return _timeOffset; } |
|
|
|
void setTimeMultiplier(double multiplier) { _timeMultiplier = multiplier; } |
|
double getTimeMultiplier() const { return _timeMultiplier; } |
|
|
|
|
|
virtual void reset(); |
|
|
|
void setPause(bool pause); |
|
bool getPause() const { return _pause; } |
|
|
|
/** 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.*/ |
|
virtual double getAnimationTime() const; |
|
|
|
/** Implements the callback. */ |
|
virtual void operator()(Node* node, NodeVisitor* nv); |
|
|
|
void update(osg::Node& node); |
|
|
|
public: |
|
|
|
ref_ptr<AnimationPath> _animationPath; |
|
osg::Vec3d _pivotPoint; |
|
bool _useInverseMatrix; |
|
double _timeOffset; |
|
double _timeMultiplier; |
|
double _firstTime; |
|
double _latestTime; |
|
bool _pause; |
|
double _pauseTime; |
|
|
|
protected: |
|
|
|
~AnimationPathCallback(){} |
|
|
|
}; |
|
|
|
} |
|
|
|
#endif
|
|
|