Added new osg::DOFTransform node from Sasa Bistrovic, designed to mirror

the OpenFlight DOF transform nodes.
This commit is contained in:
Robert Osfield
2002-08-05 15:07:18 +00:00
parent 6c998bf97d
commit 25740b5c7f
6 changed files with 676 additions and 1 deletions

View File

@@ -94,8 +94,9 @@ Phil Atkin <philatkin@philatkin.com>
Boris Bralo <boris.bralo@zg.tel.hr>
- txp TerraPage loader.
Sasa Bistrivic <sasa.bistrovic@zg.hinet.hr>
Sasa Bistrovic <sasa.bistrovic@zg.hinet.hr>
- option for detailed calculation of the near clipping plane during cull traversal.
- osg::DOFTransform
Nikolaus Hanekamp <hanekamp@stn-atlas.de>
- added support billboards to Open Flight loader.

View File

@@ -173,6 +173,10 @@ SOURCE=..\..\src\osg\DisplaySettings.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\DOFTransform.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\Drawable.cpp
# End Source File
# Begin Source File
@@ -485,6 +489,10 @@ SOURCE=..\..\include\osg\DisplaySettings
# End Source File
# Begin Source File
SOURCE=..\..\include\osg\DOFTransform
# End Source File
# Begin Source File
SOURCE=..\..\Include\Osg\Drawable
# End Source File
# Begin Source File

138
include/osg/DOFTransform Normal file
View File

@@ -0,0 +1,138 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//created by Sasa Bistrovic
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#if !defined(OSG_DOFTRANSFORM)
#define OSG_DOFTRANSFORM
//base class:
#include <osg/MatrixTransform>
namespace osg{
/** DOFTransform - encapsulates Multigen DOF behavior*/
class SG_EXPORT DOFTransform : public MatrixTransform
{
public:
/** constructor*/
DOFTransform();
/**copy constructor*/
DOFTransform(const DOFTransform& dof, const CopyOp& copyop=CopyOp::SHALLOW_COPY):
MatrixTransform(dof, copyop),
_minHPR(dof._minHPR),
_maxHPR(dof._maxHPR),
_currentHPR(dof._currentHPR),
_incrementHPR(dof._incrementHPR),
_minTranslate(dof._minTranslate),
_maxTranslate(dof._maxTranslate),
_currentTranslate(dof._currentTranslate),
_incrementTranslate(dof._incrementTranslate),
_minScale(dof._minScale),
_maxScale(dof._maxScale),
_currentScale(dof._currentScale),
_incrementScale(dof._incrementScale),
_Put(dof._Put),
_inversePut(dof._inversePut),
_limitationFlags(dof._limitationFlags),
_animationOn(dof._animationOn),
_increasingFlags(dof._increasingFlags) {}
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;}
void setCurrentHPR(const Vec3& 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 setCurrentTranslate(const Vec3& 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 setCurrentScale(const Vec3& scale);
void setPutMatrix(const Matrix& put) {_Put = put;}
void setInversePutMatrix(const Matrix& inversePut) {_inversePut = inversePut;}
void setLimitationFlags(const unsigned long flags) {_limitationFlags = flags;}
inline const Vec3& getCurrentHPR() const {return _currentHPR;}
inline const Vec3& getCurrentTranslate() const {return _currentTranslate;}
inline const Vec3& getCurrentScale() const {return _currentScale;}
inline const Matrix& getPutMatrix() const {return _Put;}
inline const Matrix& getInversePutMatrix() const {return _inversePut;}
inline const unsigned long getLimitationFlags() const {return _limitationFlags;}
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();
protected:
virtual ~DOFTransform() {}
Vec3 _minHPR;
Vec3 _maxHPR;
Vec3 _currentHPR;
Vec3 _incrementHPR;
Vec3 _minTranslate;
Vec3 _maxTranslate;
Vec3 _currentTranslate;
Vec3 _incrementTranslate;
Vec3 _minScale;
Vec3 _maxScale;
Vec3 _currentScale;
Vec3 _incrementScale;
Matrix _Put;
Matrix _inversePut;
unsigned long _limitationFlags;
/* bits from left to right
0 = x translation limited (2^31)
1 = y translation limited (2^30)
2 = z translation limited (2^29)
3 = pitch limited (2^28)
4 = roll limited (2^27)
5 = yaw limited (2^26)
6 = x scale limited (2^25)
7 = y scale limited (2^24)
8 = z scale limited (2^23)
else reserved
*/
bool _animationOn;
/** flags indicating whether value is incerasing or decreasing in animation
bits form right to left, 1 means increasing while 0 is decreasing
0 = x translation
1 = y translation
2 = z translation
3 = pitch
4 = roll
5 = yaw
6 = x scale
7 = y scale
8 = z scale
*/
unsigned short _increasingFlags;
};
}
#endif

382
src/osg/DOFTransform.cpp Normal file
View File

@@ -0,0 +1,382 @@
#include <osg/DOFTransform>
#include <osgUtil/CullVisitor>
#include <osgUtil/AppVisitor>
using namespace osg;
struct DOFCullCallback : public Transform::ComputeTransformCallback
{
/**/
virtual const bool computeLocalToWorldMatrix(Matrix& matrix, const Transform* trans, NodeVisitor* nv) const
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if(cv)
{
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
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if(cv)
{
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)
{
//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(false),
_increasingFlags(0xffffff)
{
//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);
}
void DOFTransform::setCurrentHPR(const Vec3& hpr)
{
//if there is no constrain on animation
if(!(_limitationFlags & ((unsigned long)1<<26)))
{
//if we have min == max, it is efective constrain, so don't change
if(_minHPR[2] != _maxHPR[2])
{
_currentHPR[2] = hpr[2];
unsigned short this_flag = (unsigned short)1<<4;//roll
if(_currentHPR[2] < _minHPR[2])
{
_currentHPR[2] = _minHPR[2];
//force increasing flag to 1
_increasingFlags |= this_flag;
}
else if(_currentHPR[2] > _maxHPR[2])
{
_currentHPR[2] = _maxHPR[2];
//force increasing flag to 0
_increasingFlags &= ~this_flag;
}
}
}
if(!(_limitationFlags & ((unsigned long)1<<27)))
{
if(_minHPR[1] != _maxHPR[1])
{
_currentHPR[1] = hpr[1];
unsigned short this_flag = (unsigned short)1<<3;//pitch
if(_currentHPR[1] < _minHPR[1])
{
_currentHPR[1] = _minHPR[1];
_increasingFlags |= this_flag;
}
else if(_currentHPR[1] > _maxHPR[1])
{
_currentHPR[1] = _maxHPR[1];
_increasingFlags &= ~this_flag;
}
}
}
if(!(_limitationFlags & ((unsigned long)1<<28)))
{
if(_minHPR[0] != _maxHPR[0])
{
_currentHPR[0] = hpr[0];
unsigned short this_flag = (unsigned short)1<<5;//heading
if(_currentHPR[0] < _minHPR[0])
{
_currentHPR[0] = _minHPR[0];
_increasingFlags |= this_flag;
}
else if(_currentHPR[0] > _maxHPR[0])
{
_currentHPR[0] = _maxHPR[0];
_increasingFlags &= ~this_flag;
}
}
}
}
void DOFTransform::setCurrentTranslate(const Vec3& translate)
{
if(!(_limitationFlags & (unsigned long)1<<29))
{
if(_minTranslate[2] != _maxTranslate[2])
{
_currentTranslate[2] = translate[2];
unsigned short this_flag = (unsigned short)1<<2;
if(_currentTranslate[2] < _minTranslate[2])
{
_currentTranslate[2] = _minTranslate[2];
_increasingFlags |= this_flag;
}
else if(_currentTranslate[2] > _maxTranslate[2])
{
_currentTranslate[2] = _maxTranslate[2];
_increasingFlags &= ~this_flag;
}
}
}
if(!(_limitationFlags & (unsigned long)1<<30))
{
if(_minTranslate[1] != _maxTranslate[1])
{
_currentTranslate[1] = translate[1];
unsigned short this_flag = (unsigned short)1<<1;
if(_currentTranslate[1] < _minTranslate[1])
{
_currentTranslate[1] = _minTranslate[1];
_increasingFlags |= this_flag;
}
else if(_currentTranslate[1] > _maxTranslate[1])
{
_currentTranslate[1] = _maxTranslate[1];
_increasingFlags &= ~this_flag;
}
}
}
if(!(_limitationFlags & (unsigned long)1<<31))
{
if(_minTranslate[0] != _maxTranslate[0])
{
_currentTranslate[0] = translate[0];
unsigned short this_flag = (unsigned short)1;
if(_currentTranslate[0] < _minTranslate[0])
{
_currentTranslate[0] = _minTranslate[0];
_increasingFlags |= this_flag;
}
else if(_currentTranslate[0] > _maxTranslate[0])
{
_currentTranslate[0] = _maxTranslate[0];
_increasingFlags &= ~this_flag;
}
}
}
}
void DOFTransform::setCurrentScale(const Vec3& scale)
{
if(!(_limitationFlags & ((unsigned long)1<<23)))
{
if(_minScale[2] != _maxScale[2])
{
_currentScale[2] = scale[2];
unsigned short this_flag = (unsigned short)1<<8;
if(_currentScale[2] < _minScale[2])
{
_currentScale[2] = _minScale[2];
_increasingFlags |= this_flag;
}
else if(_currentScale[2] > _maxScale[2])
{
_currentScale[2] = _maxScale[2];
_increasingFlags &= ~this_flag;
}
}
}
if(!(_limitationFlags & ((unsigned long)1<<24)))
{
if(_minScale[1] != _maxScale[1])
{
_currentScale[1] = scale[1];
unsigned short this_flag = (unsigned short)1<<7;
if(_currentScale[1] < _minScale[1])
{
_currentScale[1] = _minScale[1];
_increasingFlags |= this_flag;
}
else if(_currentScale[1] > _maxScale[1])
{
_currentScale[1] = _maxScale[1];
_increasingFlags &= ~this_flag;
}
}
}
if(!(_limitationFlags & ((unsigned long)1<<25)))
{
if(_minScale[0] != _maxScale[0])
{
_currentScale[0] = scale[0];
unsigned short this_flag = (unsigned short)1<<6;
if(_currentScale[0] < _minScale[0])
{
_currentScale[0] = _minScale[0];
_increasingFlags |= this_flag;
}
else if(_currentScale[0] > _maxScale[0])
{
_currentScale[0] = _maxScale[0];
_increasingFlags &= ~this_flag;
}
}
}
}
void DOFTransform::animate()
{
if(!_animationOn) return;
//this will increment or decrement all allowed values
Vec3 new_value = _currentTranslate;
if(_increasingFlags & 1)
new_value[0] += _incrementTranslate[0];
else
new_value[0] -= _incrementTranslate[0];
if(_increasingFlags & 1<<1)
new_value[1] += _incrementTranslate[1];
else
new_value[1] -= _incrementTranslate[1];
if(_increasingFlags & 1<<2)
new_value[2] += _incrementTranslate[2];
else
new_value[2] -= _incrementTranslate[2];
setCurrentTranslate(new_value);
new_value = _currentHPR;
if(_increasingFlags & ((unsigned short)1<<3))
new_value[1] += _incrementHPR[1];
else
new_value[1] -= _incrementHPR[1];
if(_increasingFlags & ((unsigned short)1<<4))
new_value[2] += _incrementHPR[2];
else
new_value[2] -= _incrementHPR[2];
if(_increasingFlags & ((unsigned short)1<<5))
new_value[0] += _incrementHPR[0];
else
new_value[0] -= _incrementHPR[0];
setCurrentHPR(new_value);
new_value = _currentScale;
if(_increasingFlags & 1<<6)
new_value[0] += _incrementScale[0];
else
new_value[0] -= _incrementScale[0];
if(_increasingFlags & 1<<7)
new_value[1] += _incrementScale[1];
else
new_value[1] -= _incrementScale[1];
if(_increasingFlags & 1<<8)
new_value[2] += _incrementScale[2];
else
new_value[2] -= _incrementScale[2];
setCurrentScale(new_value);
}

View File

@@ -23,6 +23,7 @@ CXXFILES =\
CullStack.cpp\
Depth.cpp\
DisplaySettings.cpp\
DOFTransform.cpp\
Drawable.cpp\
DrawPixels.cpp\
EarthSky.cpp\

View File

@@ -23,6 +23,8 @@
#include <osg/Image>
#include <osg/Notify>
#include <osg/DOFTransform>
#include <osgDB/FileNameUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
@@ -620,6 +622,146 @@ 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
osg::DOFTransform* transform = new osg::DOFTransform;
transform->setName(rec->getData()->szIdent);
transform->setDataVariance(osg::Object::DYNAMIC);
visitAncillary(osgParent, *transform, rec)->addChild( transform );
visitPrimaryNode(*transform, (PrimNodeRecord*)rec);
SDegreeOfFreedom* p_data = rec->getData();
//now fill up members:
//tranlsations:
transform->loadMinTranslate(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,
_unitScale*p_data->dfY._dfMax,
_unitScale*p_data->dfZ._dfMax));
transform->loadCurrentTranslate(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,
_unitScale*p_data->dfY._dfIncrement,
_unitScale*p_data->dfZ._dfIncrement));
//rotations:
transform->loadMinHPR(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),
osg::inDegrees(p_data->dfPitch._dfMax),
osg::inDegrees(p_data->dfRoll._dfMax)));
transform->loadCurrentHPR(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),
osg::inDegrees(p_data->dfPitch._dfIncrement),
osg::inDegrees(p_data->dfRoll._dfIncrement)));
//scales:
transform->loadMinScale(osg::Vec3(p_data->dfXscale._dfMin,
p_data->dfYscale._dfMin,
p_data->dfZscale._dfMin));
transform->loadMaxScale(osg::Vec3(p_data->dfXscale._dfMax,
p_data->dfYscale._dfMax,
p_data->dfZscale._dfMax));
transform->loadCurrentScale(osg::Vec3(p_data->dfXscale._dfCurrent,
p_data->dfYscale._dfCurrent,
p_data->dfZscale._dfCurrent));
transform->loadIncrementScale(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;
//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]
//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]
//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]
//now we have actually the second "PUT" transformation, and the first is inverse
osg::Matrix second_put = l2g_rotation * l2g_translation;
//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;
ENDIAN(flags);
//and setup limitation flags:
// transform->setLimitationFlags(flags);
*/
transform->setLimitationFlags(p_data->dwFlags);
return transform;
#else
osg::MatrixTransform* transform = new osg::MatrixTransform;
transform->setName(rec->getData()->szIdent);
@@ -690,6 +832,9 @@ osg::Group* ConvertFromFLT::visitDOF(osg::Group& osgParent, DofRecord* rec)
transform->setMatrix(dof_matrix);
return transform;
#endif
}