From c6b6e200a417b8fea7a1bc834fb9edf83014b328 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 16 Dec 2002 09:55:30 +0000 Subject: [PATCH] Added supported for setting animation path on MatrixTransform's. --- VisualStudio/osgPlugins/osg/dot_osg.dsp | 4 + include/osg/AnimationPath | 9 +- include/osg/MatrixTransform | 21 ++- src/osg/MatrixTransform.cpp | 20 ++- src/osgPlugins/osg/AnimationPath.cpp | 218 ++++++++++++++++++++++++ src/osgPlugins/osg/Makefile | 1 + src/osgPlugins/osg/MatrixTransform.cpp | 21 +++ 7 files changed, 291 insertions(+), 3 deletions(-) create mode 100644 src/osgPlugins/osg/AnimationPath.cpp diff --git a/VisualStudio/osgPlugins/osg/dot_osg.dsp b/VisualStudio/osgPlugins/osg/dot_osg.dsp index a69cafe66..fdcb5e6c1 100755 --- a/VisualStudio/osgPlugins/osg/dot_osg.dsp +++ b/VisualStudio/osgPlugins/osg/dot_osg.dsp @@ -98,6 +98,10 @@ SOURCE=..\..\..\src\osgPlugins\osg\AlphaFunc.cpp # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\osg\AnimationPath.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\osg\Billboard.cpp # End Source File # Begin Source File diff --git a/include/osg/AnimationPath b/include/osg/AnimationPath index 7a32bd30f..ff996c1be 100644 --- a/include/osg/AnimationPath +++ b/include/osg/AnimationPath @@ -16,12 +16,19 @@ namespace osg { * Subclassed from Transform::ComputeTransformCallback allows AnimationPath to * be attached directly to Transform nodes to move subgraphs around the scene. */ -class SG_EXPORT AnimationPath : public osg::Referenced +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(): diff --git a/include/osg/MatrixTransform b/include/osg/MatrixTransform index b606afb03..4797aba3d 100644 --- a/include/osg/MatrixTransform +++ b/include/osg/MatrixTransform @@ -28,6 +28,8 @@ class SG_EXPORT MatrixTransform : public Transform META_Node(osg, MatrixTransform); + virtual void traverse(NodeVisitor& nv); + /** Set the transform's matrix.*/ void setMatrix(const Matrix& mat) { (*_matrix) = mat; _inverseDirty=true; dirtyBound(); } @@ -79,8 +81,22 @@ class SG_EXPORT MatrixTransform : public Transform return true; } + + + /** Set an optional animation path. */ + void setAnimationPath(AnimationPath* ap) { _animationPath = ap; } + + /** Get a read only version of the AnimationPath object*/ + AnimationPath* getAnimationPath() { return _animationPath.get(); } + + /** Get a read only version of the AnimationPath object*/ + const AnimationPath* getAnimationPath() const { return _animationPath.get(); } + + + /** Callback which can be attached to a MatrixTransform as an app - * callback to allow it to follow the path defined by a AnimationPath.*/ + * callback to allow it to follow the path defined by a AnimationPath. + * note, now deprecated by attaching an AnimationPath directly to MatrixTransform.*/ class SG_EXPORT AnimationPathCallback : public NodeCallback { public: @@ -107,6 +123,9 @@ class SG_EXPORT MatrixTransform : public Transform ref_ptr _matrix; mutable ref_ptr _inverse; mutable bool _inverseDirty; + + osg::ref_ptr _animationPath; + }; diff --git a/src/osg/MatrixTransform.cpp b/src/osg/MatrixTransform.cpp index 735ccd1ec..871dc2bc9 100644 --- a/src/osg/MatrixTransform.cpp +++ b/src/osg/MatrixTransform.cpp @@ -13,8 +13,10 @@ MatrixTransform::MatrixTransform(const MatrixTransform& transform,const CopyOp& Transform(transform,copyop), _matrix(osgNew Matrix(*transform._matrix)), _inverse(osgNew Matrix(*transform._inverse)), - _inverseDirty(transform._inverseDirty) + _inverseDirty(transform._inverseDirty), + _animationPath(dynamic_cast(copyop(transform._animationPath.get()))) { + if (_animationPath.valid()) setNumChildrenRequiringAppTraversal(getNumChildrenRequiringAppTraversal()+1); } MatrixTransform::MatrixTransform(const Matrix& mat ) @@ -31,6 +33,22 @@ MatrixTransform::~MatrixTransform() { } + +void MatrixTransform::traverse(NodeVisitor& nv) +{ + // if app traversal update the frame count. + if (_animationPath.valid() && + nv.getVisitorType()==NodeVisitor::APP_VISITOR && + nv.getFrameStamp()) + { + double time = nv.getFrameStamp()->getReferenceTime(); + _animationPath->getMatrix(time,*_matrix); + } + + // must call any nested node callbacks and continue subgraph traversal. + MatrixTransform::traverse(nv); +} + void MatrixTransform::AnimationPathCallback::operator()(Node* node, NodeVisitor* nv) { MatrixTransform* mt = dynamic_cast(node); diff --git a/src/osgPlugins/osg/AnimationPath.cpp b/src/osgPlugins/osg/AnimationPath.cpp new file mode 100644 index 000000000..431f7a6d2 --- /dev/null +++ b/src/osgPlugins/osg/AnimationPath.cpp @@ -0,0 +1,218 @@ +#include +#include +#include + +#include +#include +#include + +using namespace osg; +using namespace osgDB; + + +// forward declare functions to use later. +bool AnimationPath_readLocalData(osg::Object &obj, osgDB::Input &fr); +bool AnimationPath_writeLocalData(const osg::Object &obj, osgDB::Output &fw); + + +// register the read and write functions with the osgDB::Registry. +osgDB::RegisterDotOsgWrapperProxy AnimationPath_Proxy +( + osgNew osg::AnimationPath, + "AnimationPath", + "Object AnimationPath", + AnimationPath_readLocalData, + AnimationPath_writeLocalData, + DotOsgWrapper::READ_AND_WRITE +); + + +bool AnimationPath_readLocalData(osg::Object &obj, osgDB::Input &fr) +{ + osg::AnimationPath *ap = dynamic_cast(&obj); + if (!ap) return false; + + + bool itAdvanced = false; + + if (fr[0].matchWord("LoopMode")) + { + if (fr[1].matchWord("SWING")) + { + ap->setLoopMode(AnimationPath::SWING); + fr += 2; + itAdvanced = true; + } + else if (fr[1].matchWord("LOOP")) + { + ap->setLoopMode(AnimationPath::LOOP); + fr += 2; + itAdvanced = true; + } + else if (fr[1].matchWord("NO_LOOPING")) + { + ap->setLoopMode(AnimationPath::NO_LOOPING); + fr += 2; + itAdvanced = true; + } + } + + + + if (fr.matchSequence("ControlPoints {")) + { + int entry = fr[1].getNoNestedBrackets(); + + fr += 2; + + float fTime = -1; + + osg::AnimationPath::ControlPoint CtrlPoint; + bool bPosParsed = false; + bool bRotParsed = false; + bool bScaleParsed = false; + + while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) + { + bool handled=false; + + if (fr[0].matchWord("Time") && + fr[1].isFloat()) + { + if (bPosParsed || bRotParsed || bScaleParsed) + { + ap->insert(fTime, CtrlPoint); + + bPosParsed = false; + bRotParsed = false; + bScaleParsed = false; + } + + fr[1].getFloat(fTime); + fr+=2; + handled = true; + } + + Vec3 vec3; + if (fr[0].matchWord("Position") && + fr[1].getFloat(vec3[0]) && + fr[2].getFloat(vec3[1]) && + fr[3].getFloat(vec3[2])) + { + CtrlPoint._position = vec3; + fr+=4; + bPosParsed = true; + handled = true; + } + + + Vec4 vec4; + if (fr[0].matchWord("Rotation") && + fr[1].getFloat(vec4[0]) && + fr[2].getFloat(vec4[1]) && + fr[3].getFloat(vec4[2]) && + fr[4].getFloat(vec4[3])) + { + CtrlPoint._rotation.makeRotate(vec4[0], vec4[1], vec4[2], vec4[3]); + fr+=5; + bRotParsed = true; + handled = true; + } + + + if (fr[0].matchWord("Scale") && + fr[1].getFloat(vec3[0]) && + fr[2].getFloat(vec3[1]) && + fr[3].getFloat(vec3[2])) + { + CtrlPoint._scale = vec3; + fr+=4; + bScaleParsed = true; + handled = true; + } + + if (!handled) fr.advanceOverCurrentFieldOrBlock(); + + } + + // If all values have been parsed in + if (bPosParsed && bRotParsed && bScaleParsed) + { + ap->insert(fTime, CtrlPoint); + } + + } + + return itAdvanced; +} + + +bool AnimationPath_writeLocalData(const osg::Object &obj, osgDB::Output &fw) +{ + const osg::AnimationPath* ap = dynamic_cast(&obj); + if (!ap) return false; + + fw.indent() << "LoopMode "; + switch(ap->getLoopMode()) + { + case AnimationPath::SWING: + fw << "SWING" <getTimeControlPointMap(); + + fw.indent() << "ControlPoints {"<< std::endl; + fw.moveIn(); + + bool bPosSet = false; + bool bRotSet = false; + bool bScaleSet = false; + AnimationPath::TimeControlPointMap::const_iterator itr; + for (itr=tcpm.begin(); + itr!=tcpm.end(); + ++itr) + { + if (itr->second._position != Vec3(0,0,0)) + bPosSet = true; + if (itr->second._rotation.asVec4() != Vec4(0,0,0,1)) + bRotSet = true; + if (itr->second._scale != Vec3(1,1,1)) + bScaleSet = true; + } + + for (itr=tcpm.begin(); + itr!=tcpm.end(); + ++itr) + { + Vec4 Rot; + + fw.indent() << "Time " << itr->first; + + if (bPosSet) + fw << " Position " << itr->second._position; + + if (bRotSet) + { + itr->second._rotation.getRotate (Rot[0], Rot[1], Rot[2], Rot[3]); + fw << " Rotation " << Rot; + } + + if (bScaleSet) + fw << " Scale " << itr->second._scale; + + fw << std::endl; + + } + + fw.moveOut(); + fw.indent() << "}"<< std::endl; + + return true; +} diff --git a/src/osgPlugins/osg/Makefile b/src/osgPlugins/osg/Makefile index fde6c1d6a..c1c96678d 100644 --- a/src/osgPlugins/osg/Makefile +++ b/src/osgPlugins/osg/Makefile @@ -3,6 +3,7 @@ include $(TOPDIR)/Make/makedefs CXXFILES =\ AlphaFunc.cpp\ + AnimationPath.cpp\ Billboard.cpp\ BlendFunc.cpp\ ClipPlane.cpp\ diff --git a/src/osgPlugins/osg/MatrixTransform.cpp b/src/osgPlugins/osg/MatrixTransform.cpp index 789b3e0cb..365c9e7d1 100644 --- a/src/osgPlugins/osg/MatrixTransform.cpp +++ b/src/osgPlugins/osg/MatrixTransform.cpp @@ -68,6 +68,22 @@ bool MatrixTransform_readLocalData(Object& obj, Input& fr) iteratorAdvanced = true; } + if (fr[0].matchWord("AnimationPath")) + { + static osg::ref_ptr prototype = new osg::AnimationPath; + osg::ref_ptr object = fr.readObjectOfType(*prototype); + osg::AnimationPath* path = dynamic_cast(object.get()); + if (path) + { + transform.setAnimationPath(path); + } + else + { + osg::Node* node = dynamic_cast(object.get()); + if (node) transform.addChild(node); + } + } + return iteratorAdvanced; } @@ -78,5 +94,10 @@ bool MatrixTransform_writeLocalData(const Object& obj, Output& fw) fw.writeObject(transform.getMatrix()); + if (transform.getAnimationPath()) + { + fw.writeObject(*transform.getAnimationPath()); + } + return true; }