Added supported for setting animation path on MatrixTransform's.

This commit is contained in:
Robert Osfield 2002-12-16 09:55:30 +00:00
parent 22ada7ee6b
commit c6b6e200a4
7 changed files with 291 additions and 3 deletions

View File

@ -98,6 +98,10 @@ SOURCE=..\..\..\src\osgPlugins\osg\AlphaFunc.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\src\osgPlugins\osg\AnimationPath.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\osg\Billboard.cpp SOURCE=..\..\..\src\osgPlugins\osg\Billboard.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@ -16,12 +16,19 @@ namespace osg {
* Subclassed from Transform::ComputeTransformCallback allows AnimationPath to * Subclassed from Transform::ComputeTransformCallback allows AnimationPath to
* be attached directly to Transform nodes to move subgraphs around the scene. * 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: public:
AnimationPath():_loopMode(LOOP) {} 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 struct ControlPoint
{ {
ControlPoint(): ControlPoint():

View File

@ -28,6 +28,8 @@ class SG_EXPORT MatrixTransform : public Transform
META_Node(osg, MatrixTransform); META_Node(osg, MatrixTransform);
virtual void traverse(NodeVisitor& nv);
/** Set the transform's matrix.*/ /** Set the transform's matrix.*/
void setMatrix(const Matrix& mat) { (*_matrix) = mat; _inverseDirty=true; dirtyBound(); } void setMatrix(const Matrix& mat) { (*_matrix) = mat; _inverseDirty=true; dirtyBound(); }
@ -79,8 +81,22 @@ class SG_EXPORT MatrixTransform : public Transform
return true; 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 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 class SG_EXPORT AnimationPathCallback : public NodeCallback
{ {
public: public:
@ -107,6 +123,9 @@ class SG_EXPORT MatrixTransform : public Transform
ref_ptr<Matrix> _matrix; ref_ptr<Matrix> _matrix;
mutable ref_ptr<Matrix> _inverse; mutable ref_ptr<Matrix> _inverse;
mutable bool _inverseDirty; mutable bool _inverseDirty;
osg::ref_ptr<AnimationPath> _animationPath;
}; };

View File

@ -13,8 +13,10 @@ MatrixTransform::MatrixTransform(const MatrixTransform& transform,const CopyOp&
Transform(transform,copyop), Transform(transform,copyop),
_matrix(osgNew Matrix(*transform._matrix)), _matrix(osgNew Matrix(*transform._matrix)),
_inverse(osgNew Matrix(*transform._inverse)), _inverse(osgNew Matrix(*transform._inverse)),
_inverseDirty(transform._inverseDirty) _inverseDirty(transform._inverseDirty),
_animationPath(dynamic_cast<AnimationPath*>(copyop(transform._animationPath.get())))
{ {
if (_animationPath.valid()) setNumChildrenRequiringAppTraversal(getNumChildrenRequiringAppTraversal()+1);
} }
MatrixTransform::MatrixTransform(const Matrix& mat ) 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) void MatrixTransform::AnimationPathCallback::operator()(Node* node, NodeVisitor* nv)
{ {
MatrixTransform* mt = dynamic_cast<MatrixTransform*>(node); MatrixTransform* mt = dynamic_cast<MatrixTransform*>(node);

View File

@ -0,0 +1,218 @@
#include <osg/Notify>
#include <osg/Geometry>
#include <osg/AnimationPath>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
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<osg::AnimationPath*>(&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<const osg::AnimationPath*>(&obj);
if (!ap) return false;
fw.indent() << "LoopMode ";
switch(ap->getLoopMode())
{
case AnimationPath::SWING:
fw << "SWING" <<std::endl;
break;
case AnimationPath::LOOP:
fw << "LOOP"<<std::endl;
break;
case AnimationPath::NO_LOOPING:
fw << "NO_LOOPING"<<std::endl;
break;
}
const AnimationPath::TimeControlPointMap& tcpm = ap->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;
}

View File

@ -3,6 +3,7 @@ include $(TOPDIR)/Make/makedefs
CXXFILES =\ CXXFILES =\
AlphaFunc.cpp\ AlphaFunc.cpp\
AnimationPath.cpp\
Billboard.cpp\ Billboard.cpp\
BlendFunc.cpp\ BlendFunc.cpp\
ClipPlane.cpp\ ClipPlane.cpp\

View File

@ -68,6 +68,22 @@ bool MatrixTransform_readLocalData(Object& obj, Input& fr)
iteratorAdvanced = true; iteratorAdvanced = true;
} }
if (fr[0].matchWord("AnimationPath"))
{
static osg::ref_ptr<osg::AnimationPath> prototype = new osg::AnimationPath;
osg::ref_ptr<osg::Object> object = fr.readObjectOfType(*prototype);
osg::AnimationPath* path = dynamic_cast<osg::AnimationPath*>(object.get());
if (path)
{
transform.setAnimationPath(path);
}
else
{
osg::Node* node = dynamic_cast<osg::Node*>(object.get());
if (node) transform.addChild(node);
}
}
return iteratorAdvanced; return iteratorAdvanced;
} }
@ -78,5 +94,10 @@ bool MatrixTransform_writeLocalData(const Object& obj, Output& fw)
fw.writeObject(transform.getMatrix()); fw.writeObject(transform.getMatrix());
if (transform.getAnimationPath())
{
fw.writeObject(*transform.getAnimationPath());
}
return true; return true;
} }