Added supported for setting animation path on MatrixTransform's.
This commit is contained in:
parent
22ada7ee6b
commit
c6b6e200a4
@ -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
|
||||||
|
@ -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():
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
218
src/osgPlugins/osg/AnimationPath.cpp
Normal file
218
src/osgPlugins/osg/AnimationPath.cpp
Normal 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;
|
||||||
|
}
|
@ -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\
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user