From 06bd9fda5bcaed26157c82e65022dd977d76abd9 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 23 Jan 2002 22:15:39 +0000 Subject: [PATCH] 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. --- VisualStudio/osg/osg.dsp | 8 ++ include/osg/PositionAttitudeTransform | 47 +++++++++++ include/osg/Transform | 81 ++++++++---------- src/osg/Makefile | 2 + src/osg/PositionAttitudeTransform.cpp | 43 ++++++++++ src/osg/Transform.cpp | 113 ++++++++++++++++++++++---- src/osgUtil/CullVisitor.cpp | 2 +- src/osgUtil/IntersectVisitor.cpp | 2 +- src/osgUtil/Optimizer.cpp | 4 +- 9 files changed, 237 insertions(+), 65 deletions(-) create mode 100644 include/osg/PositionAttitudeTransform create mode 100644 src/osg/PositionAttitudeTransform.cpp diff --git a/VisualStudio/osg/osg.dsp b/VisualStudio/osg/osg.dsp index c478a6eff..da476f182 100755 --- a/VisualStudio/osg/osg.dsp +++ b/VisualStudio/osg/osg.dsp @@ -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 diff --git a/include/osg/PositionAttitudeTransform b/include/osg/PositionAttitudeTransform new file mode 100644 index 000000000..acfca0f25 --- /dev/null +++ b/include/osg/PositionAttitudeTransform @@ -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 +#include +#include + +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 diff --git a/include/osg/Transform b/include/osg/Transform index 0b2926303..7585d3970 100644 --- a/include/osg/Transform +++ b/include/osg/Transform @@ -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; - - mutable bool _inverseDirty; - mutable ref_ptr _inverse; + mutable bool _localToWorldDirty; + mutable ref_ptr _localToWorld; + mutable bool _worldToLocalDirty; + mutable ref_ptr _worldToLocal; }; }; diff --git a/src/osg/Makefile b/src/osg/Makefile index a41558010..99eb6ea02 100644 --- a/src/osg/Makefile +++ b/src/osg/Makefile @@ -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\ diff --git a/src/osg/PositionAttitudeTransform.cpp b/src/osg/PositionAttitudeTransform.cpp new file mode 100644 index 000000000..7e11819a4 --- /dev/null +++ b/src/osg/PositionAttitudeTransform.cpp @@ -0,0 +1,43 @@ +#include + +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; + } +} diff --git a/src/osg/Transform.cpp b/src/osg/Transform.cpp index 1c3fd35fe..b21234c3c 100644 --- a/src/osg/Transform.cpp +++ b/src/osg/Transform.cpp @@ -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; + } +} diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 322a74791..f8255883a 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -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); diff --git a/src/osgUtil/IntersectVisitor.cpp b/src/osgUtil/IntersectVisitor.cpp index 6bda2c1eb..04311dda4 100644 --- a/src/osgUtil/IntersectVisitor.cpp +++ b/src/osgUtil/IntersectVisitor.cpp @@ -555,7 +555,7 @@ void IntersectVisitor::apply(Transform& node) { if (!enterNode(node)) return; - pushMatrix(node.getMatrix()); + pushMatrix(node.getLocalToWorldMatrix()); traverse(node); diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 55f1cf7dd..df3b1e677 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -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);