Updates to DOFTransform so that its overrides the traverse() and compute*() methods

rather than depending upon callbacks for animating and compute matrices.  Merged the
put/inverseput code between Sasa's and Ferndinand's DOF code.

From Bora Utka, Added support to osg::Sequence/OpenFlight AnimNode to the flt plugin.
This commit is contained in:
Robert Osfield 2002-08-12 13:42:43 +00:00
parent d43b00ac4e
commit 29490a8c1c
4 changed files with 212 additions and 213 deletions

View File

@ -40,26 +40,28 @@ class SG_EXPORT DOFTransform : public Transform
META_Node(osg, DOFTransform);
void loadMinHPR(const Vec3& hpr) {_minHPR = hpr;}
void loadMaxHPR(const Vec3& hpr) {_maxHPR = hpr;}
void loadCurrentHPR(const Vec3& hpr) {_currentHPR = hpr;}
void loadIncrementHPR(const Vec3& hpr) {_incrementHPR = hpr;}
virtual void traverse(NodeVisitor& nv);
void setCurrentHPR(const Vec3& hpr);
void setMinHPR(const Vec3& hpr) {_minHPR = hpr;}
void setMaxHPR(const Vec3& hpr) {_maxHPR = hpr;}
void setCurrentHPR(const Vec3& hpr) {_currentHPR = hpr;}
void setIncrementHPR(const Vec3& hpr) {_incrementHPR = hpr;}
void loadMinTranslate(const Vec3& translate) {_minTranslate = translate;}
void loadMaxTranslate(const Vec3& translate) {_maxTranslate = translate;}
void loadCurrentTranslate(const Vec3& translate){_currentTranslate = translate;}
void loadIncrementTranslate(const Vec3& translate) {_incrementTranslate = translate;}
void updateCurrentHPR(const Vec3& hpr);
void setCurrentTranslate(const Vec3& translate);
void setMinTranslate(const Vec3& translate) {_minTranslate = translate;}
void setMaxTranslate(const Vec3& translate) {_maxTranslate = translate;}
void setCurrentTranslate(const Vec3& translate){_currentTranslate = translate;}
void setIncrementTranslate(const Vec3& translate) {_incrementTranslate = translate;}
void loadMinScale(const Vec3& scale) {_minScale = scale;}
void loadMaxScale(const Vec3& scale) {_maxScale = scale;}
void loadCurrentScale(const Vec3& scale) {_currentScale = scale;}
void loadIncrementScale(const Vec3& scale) {_incrementScale = scale;}
void updateCurrentTranslate(const Vec3& translate);
void setCurrentScale(const Vec3& scale);
void setMinScale(const Vec3& scale) {_minScale = scale;}
void setMaxScale(const Vec3& scale) {_maxScale = scale;}
void setCurrentScale(const Vec3& scale) {_currentScale = scale;}
void setIncrementScale(const Vec3& scale) {_incrementScale = scale;}
void updateCurrentScale(const Vec3& scale);
void setPutMatrix(const Matrix& put) {_Put = put;}
void setInversePutMatrix(const Matrix& inversePut) {_inversePut = inversePut;}
@ -78,10 +80,12 @@ class SG_EXPORT DOFTransform : public Transform
inline void setAnimationOn(bool do_animate) {_animationOn = do_animate;}
inline const bool animationOn() const {return _animationOn;}
// inline const bool increasing() const {return _increasing;}
void animate();
virtual const bool computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor* nv) const;
virtual const bool computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor* nv) const;
protected:
virtual ~DOFTransform() {}

View File

@ -2,120 +2,96 @@
using namespace osg;
struct DOFCullCallback : public Transform::ComputeTransformCallback
{
/**/
virtual const bool computeLocalToWorldMatrix(Matrix& matrix, const Transform* trans, NodeVisitor* nv) const
{
const DOFTransform* dof = dynamic_cast<const DOFTransform*>(trans);
if(dof)
{
//here we are:
//put the PUT matrix first:
Matrix l2w(dof->getPutMatrix());
//now the current matrix:
Matrix current;
current.makeTranslate(dof->getCurrentTranslate());
//now create the local rotation:
current.preMult(Matrix::rotate(dof->getCurrentHPR()[1], 1.0, 0.0, 0.0));//pitch
current.preMult(Matrix::rotate(dof->getCurrentHPR()[2], 0.0, 1.0, 0.0));//roll
current.preMult(Matrix::rotate(dof->getCurrentHPR()[0], 0.0, 0.0, 1.0));//heading
//and scale:
current.preMult(Matrix::scale(dof->getCurrentScale()));
l2w.postMult(current);
//and impose inverse put:
l2w.postMult(dof->getInversePutMatrix());
//finally:
matrix.preMult(l2w);
}
return true;
}
/**/
virtual const bool computeWorldToLocalMatrix(Matrix& matrix, const Transform* trans, NodeVisitor* nv) const
{
const DOFTransform* dof = dynamic_cast<const DOFTransform*>(trans);
if(dof)
{
//here we are:
//put the PUT matrix first:
Matrix w2l(dof->getInversePutMatrix());
//now the current matrix:
Matrix current;
current.makeTranslate(-dof->getCurrentTranslate());
//now create the local rotation:
current.postMult(Matrix::rotate(-dof->getCurrentHPR()[0], 0.0, 0.0, 1.0));//heading
current.postMult(Matrix::rotate(-dof->getCurrentHPR()[2], 0.0, 1.0, 0.0));//roll
current.postMult(Matrix::rotate(-dof->getCurrentHPR()[1], 1.0, 0.0, 0.0));//pitch
//and scale:
current.postMult(Matrix::scale(1./dof->getCurrentScale()[0], 1./dof->getCurrentScale()[1], 1./dof->getCurrentScale()[2]));
w2l.postMult(current);
//and impose inverse put:
w2l.postMult(dof->getPutMatrix());
//finally:
matrix.postMult(w2l);
}
return true;
}
};
class DOFAnimationAppCallback : public osg::NodeCallback
{
/** Callback method call by the NodeVisitor when visiting a node.*/
virtual void operator()(Node* node, NodeVisitor* nv)
{
if (nv && nv->getVisitorType()==NodeVisitor::APP_VISITOR)
{
//this is aspp visitor, see if we have DOFTransform:
DOFTransform* dof = dynamic_cast<DOFTransform*>(node);
if(dof)
{
//see if it is ina animation mode:
dof->animate();
}
}
// note, callback is repsonsible for scenegraph traversal so
// should always include call the traverse(node,nv) to ensure
// that the rest of cullbacks and the scene graph are traversed.
traverse(node,nv);
}
};
DOFTransform::DOFTransform():
_limitationFlags(0),
_animationOn(true),
_increasingFlags(0xffff)
{
//default zero-ed Vec3-s are fine for all
//default idenetiy inverse matrix is fine:
_computeTransformCallback = new DOFCullCallback;
DOFAnimationAppCallback* dof_animation = new DOFAnimationAppCallback;
setAppCallback(dof_animation);
setNumChildrenRequiringAppTraversal(1);
}
void DOFTransform::setCurrentHPR(const Vec3& hpr)
void DOFTransform::traverse(NodeVisitor& nv)
{
if (nv.getVisitorType()==NodeVisitor::APP_VISITOR)
{
animate();
}
Transform::traverse(nv);
}
const bool DOFTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
//put the PUT matrix first:
Matrix l2w(getPutMatrix());
//now the current matrix:
Matrix current;
current.makeTranslate(getCurrentTranslate());
//now create the local rotation:
current.preMult(Matrix::rotate(getCurrentHPR()[1], 1.0, 0.0, 0.0));//pitch
current.preMult(Matrix::rotate(getCurrentHPR()[2], 0.0, 1.0, 0.0));//roll
current.preMult(Matrix::rotate(getCurrentHPR()[0], 0.0, 0.0, 1.0));//heading
//and scale:
current.preMult(Matrix::scale(getCurrentScale()));
l2w.postMult(current);
//and impose inverse put:
l2w.postMult(getInversePutMatrix());
// finally.
if (_referenceFrame==RELATIVE_TO_PARENTS)
{
matrix.preMult(l2w);
}
else
{
matrix = l2w;
}
return true;
}
const bool DOFTransform::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*) const
{
//put the PUT matrix first:
Matrix w2l(getInversePutMatrix());
//now the current matrix:
Matrix current;
current.makeTranslate(-getCurrentTranslate());
//now create the local rotation:
current.postMult(Matrix::rotate(-getCurrentHPR()[0], 0.0, 0.0, 1.0));//heading
current.postMult(Matrix::rotate(-getCurrentHPR()[2], 0.0, 1.0, 0.0));//roll
current.postMult(Matrix::rotate(-getCurrentHPR()[1], 1.0, 0.0, 0.0));//pitch
//and scale:
current.postMult(Matrix::scale(1./getCurrentScale()[0], 1./getCurrentScale()[1], 1./getCurrentScale()[2]));
w2l.postMult(current);
//and impose inverse put:
w2l.postMult(getPutMatrix());
if (_referenceFrame==RELATIVE_TO_PARENTS)
{
//finally:
matrix.postMult(w2l);
}
else // absolute
{
matrix = w2l;
}
return true;
}
void DOFTransform::updateCurrentHPR(const Vec3& hpr)
{
//if there is no constrain on animation
if(!(_limitationFlags & ((unsigned long)1<<26)))
@ -183,9 +159,10 @@ void DOFTransform::setCurrentHPR(const Vec3& hpr)
}
}
}
dirtyBound();
}
void DOFTransform::setCurrentTranslate(const Vec3& translate)
void DOFTransform::updateCurrentTranslate(const Vec3& translate)
{
if(!(_limitationFlags & (unsigned long)1<<29))
{
@ -246,9 +223,10 @@ void DOFTransform::setCurrentTranslate(const Vec3& translate)
}
}
}
dirtyBound();
}
void DOFTransform::setCurrentScale(const Vec3& scale)
void DOFTransform::updateCurrentScale(const Vec3& scale)
{
if(!(_limitationFlags & ((unsigned long)1<<23)))
@ -310,6 +288,7 @@ void DOFTransform::setCurrentScale(const Vec3& scale)
}
}
}
dirtyBound();
}
void DOFTransform::animate()
@ -334,7 +313,7 @@ void DOFTransform::animate()
else
new_value[2] -= _incrementTranslate[2];
setCurrentTranslate(new_value);
updateCurrentTranslate(new_value);
new_value = _currentHPR;
@ -353,7 +332,7 @@ void DOFTransform::animate()
else
new_value[0] -= _incrementHPR[0];
setCurrentHPR(new_value);
updateCurrentHPR(new_value);
new_value = _currentScale;
@ -372,7 +351,6 @@ void DOFTransform::animate()
else
new_value[2] -= _incrementScale[2];
setCurrentScale(new_value);
updateCurrentScale(new_value);
dirtyBound();
}

View File

@ -36,6 +36,15 @@ struct SGroup
class GroupRecord : public PrimNodeRecord
{
public:
enum FlagBit {
FORWARD_ANIM = 0x40000000,
SWING_ANIM = 0x20000000,
BOUND_BOX_FOLLOW = 0x10000000,
FREEZE_BOUND_BOX = 0x08000000,
DEFAULT_PARENT = 0x04000000
};
GroupRecord();
virtual Record* clone() const { return new GroupRecord(); }

View File

@ -24,6 +24,7 @@
#include <osg/Notify>
#include <osg/DOFTransform>
#include <osg/Sequence>
#include <osgDB/FileNameUtils>
#include <osgDB/FileNameUtils>
@ -557,12 +558,38 @@ void ConvertFromFLT::visitNormalTextureVertex(osg::Group& , NormalTextureVertexR
osg::Group* ConvertFromFLT::visitGroup(osg::Group& osgParent, GroupRecord* rec)
{
osg::Group* group = new osg::Group;
group->setName(rec->getData()->szIdent);
visitAncillary(osgParent, *group, rec)->addChild( group );
visitPrimaryNode(*group, rec);
return group;
SGroup* currentGroup = (SGroup*) rec->getData();
bool forwardAnim , swingAnim;
// OpenFlight 15.7 has two animation flags, forward and swing
if ( (currentGroup->dwFlags & GroupRecord::FORWARD_ANIM)== GroupRecord::FORWARD_ANIM) forwardAnim = true; else forwardAnim = false;
if ( (currentGroup->dwFlags & GroupRecord::SWING_ANIM) == GroupRecord::SWING_ANIM) swingAnim = true; else swingAnim = false;
if( forwardAnim || swingAnim )
{
osg::Sequence* animSeq = new osg::Sequence;
if ( forwardAnim )
animSeq->setInterval(osg::Sequence::LOOP, 0, -1);
else
animSeq->setInterval(osg::Sequence::SWING, 0, -1);
animSeq->setName(rec->getData()->szIdent);
visitAncillary(osgParent, *animSeq, rec)->addChild( animSeq );
visitPrimaryNode(*animSeq, rec);
return animSeq;
}
else
{
osg::Group* group = new osg::Group;
group->setName(rec->getData()->szIdent);
visitAncillary(osgParent, *group, rec)->addChild( group );
visitPrimaryNode(*group, rec);
return group;
}
}
osg::Group* ConvertFromFLT::visitRoadConstruction(osg::Group& osgParent, GroupRecord* rec)
@ -622,7 +649,9 @@ osg::Group* ConvertFromFLT::visitOldLOD(osg::Group& osgParent, OldLodRecord* rec
// Converted DOF to use transform - jtracy@ist.ucf.edu
osg::Group* ConvertFromFLT::visitDOF(osg::Group& osgParent, DofRecord* rec)
{
#if 1
#define USE_DOFTransform
#if defined(USE_DOFTransform)
osg::DOFTransform* transform = new osg::DOFTransform;
transform->setName(rec->getData()->szIdent);
@ -635,119 +664,96 @@ osg::Group* ConvertFromFLT::visitDOF(osg::Group& osgParent, DofRecord* rec)
//now fill up members:
//tranlsations:
transform->loadMinTranslate(osg::Vec3(_unitScale*p_data->dfX._dfMin,
transform->setMinTranslate(osg::Vec3(_unitScale*p_data->dfX._dfMin,
_unitScale*p_data->dfY._dfMin,
_unitScale*p_data->dfZ._dfMin));
transform->loadMaxTranslate(osg::Vec3(_unitScale*p_data->dfX._dfMax,
transform->setMaxTranslate(osg::Vec3(_unitScale*p_data->dfX._dfMax,
_unitScale*p_data->dfY._dfMax,
_unitScale*p_data->dfZ._dfMax));
transform->loadCurrentTranslate(osg::Vec3(_unitScale*p_data->dfX._dfCurrent,
transform->setCurrentTranslate(osg::Vec3(_unitScale*p_data->dfX._dfCurrent,
_unitScale*p_data->dfY._dfCurrent,
_unitScale*p_data->dfZ._dfCurrent));
transform->loadIncrementTranslate(osg::Vec3(_unitScale*p_data->dfX._dfIncrement,
transform->setIncrementTranslate(osg::Vec3(_unitScale*p_data->dfX._dfIncrement,
_unitScale*p_data->dfY._dfIncrement,
_unitScale*p_data->dfZ._dfIncrement));
//rotations:
transform->loadMinHPR(osg::Vec3(osg::inDegrees(p_data->dfYaw._dfMin),
transform->setMinHPR(osg::Vec3(osg::inDegrees(p_data->dfYaw._dfMin),
osg::inDegrees(p_data->dfPitch._dfMin),
osg::inDegrees(p_data->dfRoll._dfMin)));
transform->loadMaxHPR(osg::Vec3(osg::inDegrees(p_data->dfYaw._dfMax),
transform->setMaxHPR(osg::Vec3(osg::inDegrees(p_data->dfYaw._dfMax),
osg::inDegrees(p_data->dfPitch._dfMax),
osg::inDegrees(p_data->dfRoll._dfMax)));
transform->loadCurrentHPR(osg::Vec3(osg::inDegrees(p_data->dfYaw._dfCurrent),
transform->setCurrentHPR(osg::Vec3(osg::inDegrees(p_data->dfYaw._dfCurrent),
osg::inDegrees(p_data->dfPitch._dfCurrent),
osg::inDegrees(p_data->dfRoll._dfCurrent)));
transform->loadIncrementHPR(osg::Vec3(osg::inDegrees(p_data->dfYaw._dfIncrement),
transform->setIncrementHPR(osg::Vec3(osg::inDegrees(p_data->dfYaw._dfIncrement),
osg::inDegrees(p_data->dfPitch._dfIncrement),
osg::inDegrees(p_data->dfRoll._dfIncrement)));
//scales:
transform->loadMinScale(osg::Vec3(p_data->dfXscale._dfMin,
transform->setMinScale(osg::Vec3(p_data->dfXscale._dfMin,
p_data->dfYscale._dfMin,
p_data->dfZscale._dfMin));
transform->loadMaxScale(osg::Vec3(p_data->dfXscale._dfMax,
transform->setMaxScale(osg::Vec3(p_data->dfXscale._dfMax,
p_data->dfYscale._dfMax,
p_data->dfZscale._dfMax));
transform->loadCurrentScale(osg::Vec3(p_data->dfXscale._dfCurrent,
transform->setCurrentScale(osg::Vec3(p_data->dfXscale._dfCurrent,
p_data->dfYscale._dfCurrent,
p_data->dfZscale._dfCurrent));
transform->loadIncrementScale(osg::Vec3(p_data->dfXscale._dfIncrement,
transform->setIncrementScale(osg::Vec3(p_data->dfXscale._dfIncrement,
p_data->dfYscale._dfIncrement,
p_data->dfZscale._dfIncrement));
//now calculate put and inverse put matrix:
//the translation matrix:
osg::Matrix l2g_translation;
// compute the put matrix.
osg::Vec3 O ( p_data->OriginLocalDOF.x(),
p_data->OriginLocalDOF.y(),
p_data->OriginLocalDOF.z());
//translation vector
osg::Vec3 origin_translation(p_data->OriginLocalDOF.x(), p_data->OriginLocalDOF.y(), p_data->OriginLocalDOF.z());
origin_translation *= _unitScale;//of course, has to be scaled to units used
//so we make translation matrix
l2g_translation.makeTranslate(origin_translation);
//now we need to construct rotation matrix that describes how is local coordinate system
//rotatoed in global:
osg::Matrix l2g_rotation;
//we make two normalized osg::Vec3s so we can cross-multiply them ....
//first we have "point on x axis", i.e. what the DOF local looks like in global
osg::Vec3 point_on_x_axis(p_data->PointOnXaxis.x(), p_data->PointOnXaxis.y(), p_data->PointOnXaxis.z());
point_on_x_axis *= _unitScale;
point_on_x_axis -= origin_translation;//we need to offset it for the origin
//second, we have "point in xy plane", so x ^ y gives us local z vector
osg::Vec3 point_in_xy_plane(p_data->PointInXYplane.x(), p_data->PointInXYplane.y(), p_data->PointInXYplane.z());
point_in_xy_plane *= _unitScale;
point_in_xy_plane -= origin_translation;//also offset it
//just in case, normalize them:
point_on_x_axis.normalize();
//now, local x in global is [1 0 0 1] * rotation_matrix, so we can directly write down first row
l2g_rotation.ptr()[0] = point_on_x_axis.x(); //that is mat[0][0]
l2g_rotation.ptr()[1] = point_on_x_axis.y(); //that is mat[0][1]
l2g_rotation.ptr()[2] = point_on_x_axis.z(); //that is mat[0][2]
osg::Vec3 xAxis ( p_data->PointOnXaxis.x(),
p_data->PointOnXaxis.y(),
p_data->PointOnXaxis.z());
xAxis = xAxis - O;
xAxis.normalize();
osg::Vec3 xyPlane ( p_data->PointInXYplane.x(),
p_data->PointInXYplane.y(),
p_data->PointInXYplane.z());
xyPlane = xyPlane - O;
xyPlane.normalize();
//the cross product of x ^point_in_local_xy_plane gives local z
osg::Vec3 z_transformed = point_on_x_axis ^ point_in_xy_plane;
z_transformed.normalize();//we have to normalize it, and than we can directly writ it down to rotation matrix
//we can write it down to matrix directly:
l2g_rotation.ptr()[8] = z_transformed.x(); //that is mat[2][0]
l2g_rotation.ptr()[9] = z_transformed.y(); //that is mat[2][1]
l2g_rotation.ptr()[10] = z_transformed.z(); //that is mat[2][2]
osg::Vec3 normalz = xAxis ^ xyPlane;
normalz.normalize();
//now that we have x and z, we can get y = z ^ x
osg::Vec3 y_transformed = z_transformed ^ point_on_x_axis;
//and just in case, we can normalize it:
// y_transformed.normalize();
//this goes to rotation matrix:
l2g_rotation.ptr()[4] = y_transformed.x(); //that is mat[1][0]
l2g_rotation.ptr()[5] = y_transformed.y(); //that is mat[1][0]
l2g_rotation.ptr()[6] = y_transformed.z(); //that is mat[1][0]
// get X, Y, Z axis of the DOF in terms of global coordinates
osg::Vec3 Rz = normalz;
if (Rz == osg::Vec3(0,0,0)) Rz[2] = 1;
osg::Vec3 Rx = xAxis;
if (Rx == osg::Vec3(0,0,0)) Rx[0] = 1;
osg::Vec3 Ry = Rz ^ Rx;
//now we have actually the second "PUT" transformation, and the first is inverse
osg::Matrix second_put = l2g_rotation * l2g_translation;
O *= _unitScale;
// create the putmatrix
osg::Matrix inv_putmat( Rx.x(), Rx.y(), Rx.z(), 0,
Ry.x(), Ry.y(), Ry.z(), 0,
Rz.x(), Rz.y(), Rz.z(), 0,
O.x(), O.y(), O.z(), 1);
transform->setInversePutMatrix(inv_putmat);
transform->setPutMatrix(osg::Matrix::inverse(inv_putmat));
//and we take invers of it since it has to be done at the end, see FLT spec
osg::Matrix the_first = osg::Matrix::inverse(second_put);
transform->setPutMatrix(the_first);
transform->setInversePutMatrix(second_put);
/*
//and now do a little ENDIAN to put flags in ordewr as described in OpenFlight spec
unsigned long flags = p_data->dwFlags;
@ -780,16 +786,16 @@ osg::Group* ConvertFromFLT::visitDOF(osg::Group& osgParent, DofRecord* rec)
p_data->PointOnXaxis.y(),
p_data->PointOnXaxis.z());
xAxis = xAxis - O;
xAxis.normalize();
xAxis.normalize();
osg::Vec3 xyPlane ( p_data->PointInXYplane.x(),
p_data->PointInXYplane.y(),
p_data->PointInXYplane.z());
xyPlane = xyPlane - O;
xyPlane.normalize();
xyPlane.normalize();
osg::Vec3 normalz = xAxis ^ xyPlane;
normalz.normalize();
normalz.normalize();
// get X, Y, Z axis of the DOF in terms of global coordinates
osg::Vec3 Rz = normalz;
@ -817,20 +823,22 @@ osg::Group* ConvertFromFLT::visitDOF(osg::Group& osgParent, DofRecord* rec)
float sy = rec->getData()->dfYscale.current();
float sz = rec->getData()->dfZscale.current();
// this is the local DOF transformation
osg::Matrix dof_matrix = osg::Matrix::scale(sx, sy, sz)*
// this is the local DOF transformation
osg::Matrix dof_matrix = osg::Matrix::scale(sx, sy, sz)*
osg::Matrix::rotate(yaw_rad, 0.0f,0.0f,1.0f)*
osg::Matrix::rotate(roll_rad, 0.0f,1.0f,0.0f)*
osg::Matrix::rotate(pitch_rad, 1.0f,0.0f,0.0f)*
osg::Matrix::translate(trans);
// transforming local into global
dof_matrix.preMult(osg::Matrix::inverse(putmat));
// transforming local into global
dof_matrix.preMult(osg::Matrix::inverse(putmat));
// transforming global into local
dof_matrix.postMult(putmat);
cout << "putmat "<< putmat<<endl;
transform->setMatrix(dof_matrix);
// transforming global into local
dof_matrix.postMult(putmat);
transform->setMatrix(dof_matrix);
return transform;
#endif