From 1dcf4fe81fb00a06729a13b5ec841866707a715b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 27 Feb 2006 19:48:34 +0000 Subject: [PATCH] Added support in osg::computeWorldToLocal and compteLocalToWorld functions for automatically stripping any absolute or root CameraNode's from the NodePaths. Added osg::Node::getWorldMatrices() convinience method. --- include/osg/Node | 7 ++++++ include/osg/Transform | 8 +++--- src/osg/Node.cpp | 26 ++++++++++++++++++++ src/osg/Transform.cpp | 57 +++++++++++++++++++++++++++++++------------ 4 files changed, 79 insertions(+), 19 deletions(-) diff --git a/include/osg/Node b/include/osg/Node index a36cb315c..36b05ec57 100644 --- a/include/osg/Node +++ b/include/osg/Node @@ -36,6 +36,8 @@ typedef std::vector< Node* > NodePath; /** A vector of NodePath, typically used to describe all the paths from a node to the potential root nodes it has.*/ typedef std::vector< NodePath > NodePathList; +/** A vector of NodePath, typically used to describe all the paths from a node to the potential root nodes it has.*/ +typedef std::vector< Matrix > MatrixList; /** META_Node macro define the standard clone, isSameKindAs, className * and accept methods. Use when subclassing from Node to make it @@ -89,6 +91,7 @@ class OSG_EXPORT Node : public Object /** Convert 'this' into a Transform pointer if Node is a Transform, otherwise return 0. * Equivalent to dynamic_cast(this).*/ virtual Transform* asTransform() { return 0; } + /** convert 'const this' into a const Transform pointer if Node is a Transform, otherwise return 0. * Equivalent to dynamic_cast(this).*/ virtual const Transform* asTransform() const { return 0; } @@ -129,6 +132,10 @@ class OSG_EXPORT Node : public Object * The optional Node* haltTraversalAtNode allows the user to prevent traversal beyond a specifed node. */ NodePathList getParentalNodePaths(osg::Node* haltTraversalAtNode=0) const; + /** Get the list of matrices that transform this node from local coordinates to world coordinates. + * The optional Node* haltTraversalAtNode allows the user to prevent traversal beyond a specifed node. */ + MatrixList getWorldMatrices(osg::Node* haltTraversalAtNode=0) const; + /** Set update node callback, called during update traversal. */ void setUpdateCallback(NodeCallback* nc); diff --git a/include/osg/Transform b/include/osg/Transform index a991de748..bc723033b 100644 --- a/include/osg/Transform +++ b/include/osg/Transform @@ -28,24 +28,24 @@ namespace osg { /** Compute the matrix which transforms objects in local coords to world coords, * by accumulating the Transform local to world matrices along the specified node path. */ -extern OSG_EXPORT Matrix computeLocalToWorld(const NodePath& nodePath); +extern OSG_EXPORT Matrix computeLocalToWorld(const NodePath& nodePath, bool ignoreCameraNodes = true); /** Compute the matrix which transforms objects in world coords to local coords, * by accumulating the Transform world to local matrices along the specified node path. */ -extern OSG_EXPORT Matrix computeWorldToLocal(const NodePath& nodePath); +extern OSG_EXPORT Matrix computeWorldToLocal(const NodePath& nodePath, bool ignoreCameraNodes = true); /** Compute the matrix which transforms objects in local coords to eye coords, * by accumulating the Transform local to world matrices along the specified node path * and multipling by the supplied initial camera modelview. */ -extern OSG_EXPORT Matrix computeLocalToEye(const Matrix& modelview, const NodePath& nodePath); +extern OSG_EXPORT Matrix computeLocalToEye(const Matrix& modelview, const NodePath& nodePath, bool ignoreCameraNodes = true); /** Compute the matrix which transforms objects in eye coords to local coords, * by accumulating the Transform world to local matrices along the specified node path * and multipling by the inverse of the supplied initialial camera modelview. */ -extern OSG_EXPORT Matrix computeEyeToLocal(const Matrix& modelview, const NodePath& nodePath); +extern OSG_EXPORT Matrix computeEyeToLocal(const Matrix& modelview, const NodePath& nodePath, bool ignoreCameraNodes = true); /** A Transform is a group node for which all children are transformed by diff --git a/src/osg/Node.cpp b/src/osg/Node.cpp index 81520364e..3050c7762 100644 --- a/src/osg/Node.cpp +++ b/src/osg/Node.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -170,6 +171,31 @@ NodePathList Node::getParentalNodePaths(osg::Node* haltTraversalAtNode) const return cpp._nodePaths; } +MatrixList Node::getWorldMatrices(osg::Node* haltTraversalAtNode) const +{ + CollectParentPaths cpp(haltTraversalAtNode); + const_cast(this)->accept(cpp); + + MatrixList matrices; + + for(NodePathList::iterator itr = cpp._nodePaths.begin(); + itr != cpp._nodePaths.end(); + ++itr) + { + NodePath& nodePath = *itr; + if (nodePath.empty()) + { + matrices.push_back(osg::Matrix::identity()); + } + else + { + matrices.push_back(osg::computeLocalToWorld(nodePath)); + } + } + + return matrices; +} + void Node::setUpdateCallback(NodeCallback* nc) { // if no changes just return. diff --git a/src/osg/Transform.cpp b/src/osg/Transform.cpp index 4e7f9b1ac..a54f5c3f4 100644 --- a/src/osg/Transform.cpp +++ b/src/osg/Transform.cpp @@ -11,6 +11,9 @@ * OpenSceneGraph Public License for more details. */ #include +#include + +#include using namespace osg; @@ -27,11 +30,13 @@ class TransformVisitor : public NodeVisitor CoordMode _coordMode; Matrix& _matrix; + bool _ignoreCameraNodes; - TransformVisitor(Matrix& matrix,CoordMode coordMode): + TransformVisitor(Matrix& matrix,CoordMode coordMode, bool ignoreCameraNodes): NodeVisitor(), _coordMode(coordMode), - _matrix(matrix) + _matrix(matrix), + _ignoreCameraNodes(ignoreCameraNodes) {} virtual void apply(Transform& transform) @@ -48,46 +53,68 @@ class TransformVisitor : public NodeVisitor void accumulate(const NodePath& nodePath) { - NodePath& non_const_nodePath = const_cast(nodePath); - for(NodePath::iterator itr=non_const_nodePath.begin(); - itr!=non_const_nodePath.end(); - ++itr) + if (nodePath.empty()) return; + + unsigned int i = 0; + if (_ignoreCameraNodes) { - (*itr)->accept(*this); + // we need to found out the last absolute CameraNode in NodePath and + // set the i index to after it so the final accumulation set ignores it. + i = nodePath.size(); + NodePath::const_reverse_iterator ritr; + for(ritr = nodePath.rbegin(); + ritr != nodePath.rend(); + ++ritr, --i) + { + const osg::CameraNode* camera = dynamic_cast(*ritr); + if (camera && + (camera->getReferenceFrame()==osg::Transform::ABSOLUTE_RF || camera->getParents().empty())) + { + break; + } + } + } + + // do the accumulation of the active part of nodepath. + for(; + i(nodePath[i])->accept(*this); } } }; -Matrix osg::computeLocalToWorld(const NodePath& nodePath) +Matrix osg::computeLocalToWorld(const NodePath& nodePath, bool ignoreCameraNodes) { Matrix matrix; - TransformVisitor tv(matrix,TransformVisitor::LOCAL_TO_WORLD); + TransformVisitor tv(matrix,TransformVisitor::LOCAL_TO_WORLD,ignoreCameraNodes); tv.accumulate(nodePath); return matrix; } -Matrix osg::computeWorldToLocal(const NodePath& nodePath) +Matrix osg::computeWorldToLocal(const NodePath& nodePath, bool ignoreCameraNodes) { osg::Matrix matrix; - TransformVisitor tv(matrix,TransformVisitor::WORLD_TO_LOCAL); + TransformVisitor tv(matrix,TransformVisitor::WORLD_TO_LOCAL,ignoreCameraNodes); tv.accumulate(nodePath); return matrix; } -Matrix osg::computeLocalToEye(const Matrix& modelview,const NodePath& nodePath) +Matrix osg::computeLocalToEye(const Matrix& modelview,const NodePath& nodePath, bool ignoreCameraNodes) { Matrix matrix(modelview); - TransformVisitor tv(matrix,TransformVisitor::LOCAL_TO_WORLD); + TransformVisitor tv(matrix,TransformVisitor::LOCAL_TO_WORLD,ignoreCameraNodes); tv.accumulate(nodePath); return matrix; } -Matrix osg::computeEyeToLocal(const Matrix& modelview,const NodePath& nodePath) +Matrix osg::computeEyeToLocal(const Matrix& modelview,const NodePath& nodePath, bool ignoreCameraNodes) { Matrix matrix; matrix.invert(modelview); - TransformVisitor tv(matrix,TransformVisitor::WORLD_TO_LOCAL); + TransformVisitor tv(matrix,TransformVisitor::WORLD_TO_LOCAL,ignoreCameraNodes); tv.accumulate(nodePath); return matrix; }