Have made osg::Transform more extensible via additions of new getLocalToWorldMatrix()
and getWorldToLocalMatrix(), computeLocalToWorld() and computeWorldToLocal() methods. Have updated the CullVisitor, IntersectVisitor and Optimizer to use the new osg::Transform::getLocalToWorldMatrix() which has the same functionality as the old getMatrix() but is now supports subclasses of osg::Transform transparently. Have added osg::PositionAttitudeTransform as subclass of osg::Transform which manages the transform as position and attitude via a Vec3 and Quat respectively.
This commit is contained in:
parent
9c8c73c77f
commit
06bd9fda5b
@ -245,6 +245,10 @@ SOURCE=..\..\src\osg\PolygonOffset.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\PositionAttitudeTransform.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\Quat.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -497,6 +501,10 @@ SOURCE=..\..\Include\Osg\PolygonOffset
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Include\Osg\PositionAttitudeTransform
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Include\Osg\Quat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
47
include/osg/PositionAttitudeTransform
Normal file
47
include/osg/PositionAttitudeTransform
Normal file
@ -0,0 +1,47 @@
|
||||
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
|
||||
//Distributed under the terms of the GNU Library General Public License (LGPL)
|
||||
//as published by the Free Software Foundation.
|
||||
|
||||
#ifndef OSG_POSITIONATTITIDETRANSFORM
|
||||
#define OSG_POSITIONATTITIDETRANSFORM 1
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Transform>
|
||||
#include <osg/Quat>
|
||||
|
||||
namespace osg {
|
||||
|
||||
/** PositionAttitideTransform - is Transfrom the set the coordinates transform
|
||||
up via a Vec3 position and Quat attitude.
|
||||
*/
|
||||
class SG_EXPORT PositionAttitudeTransform : public Transform
|
||||
{
|
||||
public :
|
||||
PositionAttitudeTransform();
|
||||
|
||||
META_Node(PositionAttitudeTransform);
|
||||
|
||||
|
||||
void setPosition(const Vec3& pos) { _position = pos; _localToWorldDirty = _worldToLocalDirty = true; }
|
||||
|
||||
const Vec3& getPosition() const { return _position; }
|
||||
|
||||
void setAttitude(const Quat& quat) { _attitude = quat; _localToWorldDirty = _worldToLocalDirty = true; }
|
||||
|
||||
const Quat& getAttitude() const { return _attitude; }
|
||||
|
||||
|
||||
protected :
|
||||
|
||||
virtual void computeLocalToWorld() const;
|
||||
|
||||
virtual void computeWorldToLocal() const;
|
||||
|
||||
Vec3 _position;
|
||||
Quat _attitude;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -50,50 +50,40 @@ class SG_EXPORT Transform : public Group
|
||||
/** Get the Transform Type.*/
|
||||
inline const Type getType() const { return _type; }
|
||||
|
||||
|
||||
|
||||
enum Mode
|
||||
{
|
||||
VIEW,
|
||||
MODEL
|
||||
};
|
||||
|
||||
inline void setMode(Mode mode) { _mode = mode; }
|
||||
|
||||
inline const Mode getMode() const { return _mode; }
|
||||
|
||||
/** Get the transform's matrix. */
|
||||
inline const Matrix& getMatrix() const { if (_matrixDirty) computeMatrix(); return *_matrix; }
|
||||
|
||||
/** Get the transformation matrix which moves from local coords to world coords.*/
|
||||
inline const Matrix& getLocalToWorldMatrix() const { if (_localToWorldDirty) computeLocalToWorld(); return *_localToWorld; }
|
||||
|
||||
/** Get the inverse of the transform's matrix.
|
||||
* Automatically compute the inverse if it is not up to date. */
|
||||
inline const Matrix& getInverse() const { if (_inverseDirty) computeInverse(); return *_inverse; }
|
||||
/** Get the transformation matrix which moves from world coords to local coords.*/
|
||||
inline const Matrix& getWorldToLocalMatrix() const { if (_worldToLocalDirty) computeWorldToLocal(); return *_worldToLocal; }
|
||||
|
||||
|
||||
|
||||
/** Set the transform's matrix.*/
|
||||
inline void setMatrix(const Matrix& mat )
|
||||
{
|
||||
(*_matrix) = mat;
|
||||
void setMatrix(const Matrix& mat);
|
||||
|
||||
/** Get the transform's matrix. */
|
||||
inline const Matrix& getMatrix() const { if (_mode==MODEL) return *_localToWorld; else return *_worldToLocal; }
|
||||
|
||||
_matrixDirty = false; // matrix is valid, so no need to compute
|
||||
_inverseDirty = true; // inverse is now invalid, so will need to recompute.
|
||||
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
/** preMult trasforms relative to the childrens coordinate system.*/
|
||||
inline void preMult( const Matrix& mat )
|
||||
{
|
||||
(*_matrix) = mat * (*_matrix);
|
||||
|
||||
_matrixDirty = false; // matrix is valid, so no need to compute
|
||||
_inverseDirty = true; // inverse is now invalid, so will need to recompute.
|
||||
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
/** postMult trasforms relative to the parents coordinate system.*/
|
||||
inline void postMult( const Matrix& mat )
|
||||
{
|
||||
(*_matrix) = (*_matrix) * mat;
|
||||
|
||||
_matrixDirty = false; // matrix is valid, so no need to compute
|
||||
_inverseDirty = true; // inverse is now invalid, so will need to recompute.
|
||||
|
||||
dirtyBound();
|
||||
}
|
||||
/** preMult transform.*/
|
||||
void preMult(const Matrix& mat);
|
||||
|
||||
/** postMult transform.*/
|
||||
void postMult(const Matrix& mat);
|
||||
|
||||
|
||||
protected :
|
||||
|
||||
virtual ~Transform();
|
||||
@ -103,24 +93,23 @@ class SG_EXPORT Transform : public Group
|
||||
* the underlying matrix (calling computeMatrix if required.) */
|
||||
virtual const bool computeBound() const;
|
||||
|
||||
/** If you subclass from osg::Transform you must override computeMatrix() to provide your own mechanism for
|
||||
/** If you subclass from osg::Transform you must override computeLocalToWorld() to provide your own mechanism for
|
||||
* setting up the 4x4 matrix. An example of a subclass might a PositionAttitudeTransfrom which is its own
|
||||
* Vec3 and Quat to calculate the matrix.*/
|
||||
virtual void computeMatrix() const { _matrixDirty = false; }
|
||||
virtual void computeLocalToWorld() const;
|
||||
|
||||
/** If you subclass from osg::Transform it is safe to rely on this default implementation which uses osg::Matrix::invert(getMatrix())
|
||||
* to compute the inverse. However, you may wish to override this method too since there may well be a more optimal way to
|
||||
* compute the inverse rather than rely on the brute force method of osg::Matrix::invert(..).*/
|
||||
virtual void computeInverse() const { if (_inverseDirty) _inverse->invert(getMatrix()); _inverseDirty = false; }
|
||||
/** If you subclass from osg::Transform it must also override computeWorldToLocal() to provide your own mechanism for
|
||||
* setting up the 4x4 matrix.*/
|
||||
virtual void computeWorldToLocal() const;
|
||||
|
||||
Type _type;
|
||||
Mode _mode;
|
||||
|
||||
mutable bool _matrixDirty;
|
||||
mutable ref_ptr<Matrix> _matrix;
|
||||
|
||||
mutable bool _inverseDirty;
|
||||
mutable ref_ptr<Matrix> _inverse;
|
||||
mutable bool _localToWorldDirty;
|
||||
mutable ref_ptr<Matrix> _localToWorld;
|
||||
|
||||
mutable bool _worldToLocalDirty;
|
||||
mutable ref_ptr<Matrix> _worldToLocal;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -41,6 +41,7 @@ C++FILES = \
|
||||
Point.cpp\
|
||||
PolygonMode.cpp\
|
||||
PolygonOffset.cpp\
|
||||
PositionAttitudeTransform.cpp\
|
||||
Quat.cpp\
|
||||
ShadeModel.cpp\
|
||||
State.cpp\
|
||||
@ -108,6 +109,7 @@ TARGET_INCLUDE_FILES = \
|
||||
osg/Point\
|
||||
osg/PolygonMode\
|
||||
osg/PolygonOffset\
|
||||
osg/PositionAttitudeTransform\
|
||||
osg/Plane\
|
||||
osg/Quat\
|
||||
osg/Referenced\
|
||||
|
43
src/osg/PositionAttitudeTransform.cpp
Normal file
43
src/osg/PositionAttitudeTransform.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
PositionAttitudeTransform::PositionAttitudeTransform()
|
||||
{
|
||||
}
|
||||
|
||||
void PositionAttitudeTransform::computeLocalToWorld() const
|
||||
{
|
||||
if (_localToWorldDirty)
|
||||
{
|
||||
if (_mode==MODEL)
|
||||
{
|
||||
_localToWorld->makeRotate(_attitude);
|
||||
_localToWorld->setTrans(_position);
|
||||
}
|
||||
else
|
||||
{
|
||||
_localToWorld->makeTranslate(-_position);
|
||||
_localToWorld->postMult(osg::Matrix::rotate(_attitude.inverse()));
|
||||
}
|
||||
_localToWorldDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void PositionAttitudeTransform::computeWorldToLocal() const
|
||||
{
|
||||
if (_worldToLocalDirty)
|
||||
{
|
||||
if (_mode==MODEL)
|
||||
{
|
||||
_worldToLocal->makeTranslate(-_position);
|
||||
_worldToLocal->postMult(osg::Matrix::rotate(_attitude.inverse()));
|
||||
}
|
||||
else
|
||||
{
|
||||
_worldToLocal->makeRotate(_attitude);
|
||||
_worldToLocal->setTrans(_position);
|
||||
}
|
||||
_worldToLocalDirty = false;
|
||||
}
|
||||
}
|
@ -5,25 +5,28 @@ using namespace osg;
|
||||
Transform::Transform()
|
||||
{
|
||||
_type = DYNAMIC;
|
||||
_mode = MODEL;
|
||||
|
||||
_matrix = new Matrix;
|
||||
_matrix->makeIdentity();
|
||||
_matrixDirty = false;
|
||||
|
||||
_inverse = new Matrix;
|
||||
_inverse->makeIdentity();
|
||||
_inverseDirty = false;
|
||||
_localToWorld = new Matrix;
|
||||
_localToWorld->makeIdentity();
|
||||
_localToWorldDirty = false;
|
||||
|
||||
_worldToLocal = new Matrix;
|
||||
_worldToLocal->makeIdentity();
|
||||
_worldToLocalDirty = false;
|
||||
}
|
||||
|
||||
|
||||
Transform::Transform(const Matrix& mat )
|
||||
{
|
||||
_type = DYNAMIC;
|
||||
_mode = MODEL;
|
||||
|
||||
_matrix = new Matrix(mat);
|
||||
_matrixDirty = false;
|
||||
_localToWorld = new Matrix(mat);
|
||||
_localToWorldDirty = false;
|
||||
|
||||
_inverseDirty = true; // will neeed to recompute.
|
||||
_worldToLocal = new Matrix;
|
||||
_worldToLocalDirty = true;
|
||||
}
|
||||
|
||||
|
||||
@ -31,25 +34,81 @@ Transform::~Transform()
|
||||
{
|
||||
}
|
||||
|
||||
void Transform::setMatrix(const Matrix& mat )
|
||||
{
|
||||
if (_mode==MODEL)
|
||||
{
|
||||
(*_localToWorld) = mat;
|
||||
_localToWorldDirty = false;
|
||||
_worldToLocalDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_worldToLocal) = mat;
|
||||
_worldToLocalDirty = false;
|
||||
_localToWorldDirty = true;
|
||||
}
|
||||
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
/** preMult transform.*/
|
||||
void Transform::preMult( const Matrix& mat )
|
||||
{
|
||||
if (_mode==MODEL)
|
||||
{
|
||||
_localToWorld->preMult(mat);
|
||||
_localToWorldDirty = false;
|
||||
_worldToLocalDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_worldToLocal->preMult(mat);
|
||||
_worldToLocalDirty = false;
|
||||
_localToWorldDirty = true;
|
||||
}
|
||||
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
/** postMult transform.*/
|
||||
void Transform::postMult( const Matrix& mat )
|
||||
{
|
||||
if (_mode==MODEL)
|
||||
{
|
||||
_localToWorld->postMult(mat);
|
||||
_localToWorldDirty = false;
|
||||
_worldToLocalDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_worldToLocal->postMult(mat);
|
||||
_worldToLocalDirty = false;
|
||||
_localToWorldDirty = true;
|
||||
}
|
||||
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
const bool Transform::computeBound() const
|
||||
{
|
||||
if (!Group::computeBound()) return false;
|
||||
|
||||
if (_matrixDirty) computeMatrix();
|
||||
if (_localToWorldDirty) computeLocalToWorld();
|
||||
|
||||
Vec3 xdash = _bsphere._center;
|
||||
xdash.x() += _bsphere._radius;
|
||||
xdash = xdash*(*_matrix);
|
||||
xdash = xdash*(*_localToWorld);
|
||||
|
||||
Vec3 ydash = _bsphere._center;
|
||||
ydash.y() += _bsphere._radius;
|
||||
ydash = ydash*(*_matrix);
|
||||
ydash = ydash*(*_localToWorld);
|
||||
|
||||
Vec3 zdash = _bsphere._center;
|
||||
zdash.y() += _bsphere._radius;
|
||||
zdash = zdash*(*_matrix);
|
||||
zdash = zdash*(*_localToWorld);
|
||||
|
||||
_bsphere._center = _bsphere._center*(*_matrix);
|
||||
_bsphere._center = _bsphere._center*(*_localToWorld);
|
||||
|
||||
xdash -= _bsphere._center;
|
||||
float len_xdash = xdash.length();
|
||||
@ -66,3 +125,27 @@ const bool Transform::computeBound() const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Transform::computeLocalToWorld() const
|
||||
{
|
||||
if (_localToWorldDirty)
|
||||
{
|
||||
if (_mode==VIEW)
|
||||
{
|
||||
_localToWorld->invert(*_worldToLocal);
|
||||
}
|
||||
_localToWorldDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Transform::computeWorldToLocal() const
|
||||
{
|
||||
if (_worldToLocalDirty)
|
||||
{
|
||||
if (_mode==MODEL)
|
||||
{
|
||||
_worldToLocal->invert(*_localToWorld);
|
||||
}
|
||||
_worldToLocalDirty = false;
|
||||
}
|
||||
}
|
||||
|
@ -1054,7 +1054,7 @@ void CullVisitor::apply(Transform& node)
|
||||
StateSet* node_state = node.getStateSet();
|
||||
if (node_state) pushStateSet(node_state);
|
||||
|
||||
pushCullViewState(&node.getMatrix());
|
||||
pushCullViewState(&node.getLocalToWorldMatrix());
|
||||
|
||||
traverse(node);
|
||||
|
||||
|
@ -555,7 +555,7 @@ void IntersectVisitor::apply(Transform& node)
|
||||
{
|
||||
if (!enterNode(node)) return;
|
||||
|
||||
pushMatrix(node.getMatrix());
|
||||
pushMatrix(node.getLocalToWorldMatrix());
|
||||
|
||||
traverse(node);
|
||||
|
||||
|
@ -330,11 +330,11 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Transform& transform)
|
||||
{
|
||||
if (_matrixStack.empty())
|
||||
{
|
||||
_matrixStack.push_back(transform.getMatrix());
|
||||
_matrixStack.push_back(transform.getLocalToWorldMatrix());
|
||||
}
|
||||
else
|
||||
{
|
||||
_matrixStack.push_back(transform.getMatrix()*_matrixStack.back());
|
||||
_matrixStack.push_back(transform.getLocalToWorldMatrix()*_matrixStack.back());
|
||||
}
|
||||
|
||||
_transformStack.push_back(&transform);
|
||||
|
Loading…
Reference in New Issue
Block a user