diff --git a/include/osg/RefNodePath b/include/osg/RefNodePath index bdef818cc..ee4d61a63 100644 --- a/include/osg/RefNodePath +++ b/include/osg/RefNodePath @@ -37,6 +37,27 @@ class RefNodePath : public NodeList } } + RefNodePath& operator = (const RefNodePath& rhs) + { + if (&rhs == this) return *this; + + NodeList::operator = (rhs); + + return *this; + } + + RefNodePath& operator = (const NodePath& rhs) + { + for(osg::NodePath::const_iterator itr=rhs.begin(); + itr != rhs.end(); + ++itr) + { + push_back(*itr); + } + + return *this; + } + inline operator NodePath () const { NodePath nodePath; diff --git a/include/osg/Transform b/include/osg/Transform index c20921053..aa9ef6979 100644 --- a/include/osg/Transform +++ b/include/osg/Transform @@ -27,21 +27,21 @@ 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 SG_EXPORT Matrix computeLocalToWorld(NodePath& nodePath); +extern SG_EXPORT Matrix computeLocalToWorld(const NodePath& nodePath); /** 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 SG_EXPORT Matrix computeWorldToLocal(NodePath& nodePath); +extern SG_EXPORT Matrix computeWorldToLocal(const NodePath& nodePath); /** 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 * the supplied initialial camera modelview .*/ -extern SG_EXPORT Matrix computeLocalToEye(const Matrix& modelview, NodePath& nodePath); +extern SG_EXPORT Matrix computeLocalToEye(const Matrix& modelview, const NodePath& nodePath); /** 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 * the inverse of the supplied initialial camera modelview.*/ -extern SG_EXPORT Matrix computeEyeToLocal(const Matrix& modelview, NodePath& nodePath); +extern SG_EXPORT Matrix computeEyeToLocal(const Matrix& modelview, const NodePath& nodePath); /** A Transform is a group node for which all children are transformed by diff --git a/include/osgGA/NodeTrackerManipulator b/include/osgGA/NodeTrackerManipulator index 1a0199e8a..9ac1f4f99 100644 --- a/include/osgGA/NodeTrackerManipulator +++ b/include/osgGA/NodeTrackerManipulator @@ -15,7 +15,9 @@ #define OSGGA_NODETRACKERMANIPULATOR 1 #include + #include +#include namespace osgGA{ @@ -27,10 +29,15 @@ class OSGGA_EXPORT NodeTrackerManipulator : public MatrixManipulator virtual const char* className() const { return "NodeTrackerManipulator"; } - void setTrackNode(osg::Node* node) { _trackNode = node; } - osg::Node* getTrackNode() { return _trackNode.get(); } - const osg::Node* getTrackNode() const { return _trackNode.get(); } + void setTrackNodePath(const osg::RefNodePath& nodePath) { _trackNodePath = nodePath; } + void setTrackNodePath(const osg::NodePath& nodePath) { _trackNodePath = nodePath; } + osg::RefNodePath& getTrackNodePath() { return _trackNodePath; } + const osg::RefNodePath& getTrackNodePath() const { return _trackNodePath; } + + void setTrackNode(osg::Node* node); + osg::Node* getTrackNode() { return _trackNodePath.empty() ? 0 : _trackNodePath.back().get(); } + const osg::Node* getTrackNode() const { return _trackNodePath.empty() ? 0 : _trackNodePath.back().get(); } enum TrackerMode { @@ -99,6 +106,21 @@ class OSGGA_EXPORT NodeTrackerManipulator : public MatrixManipulator protected: virtual ~NodeTrackerManipulator(); + + inline bool validateNodePath() const + { + if (!_trackNodePath.valid()) + { + if (_trackNodePath.empty()) + { + osg::notify(osg::NOTICE)<<"Warning: tracked node path has been invalidated by changes in the scene graph."<(this); + non_const_this->_trackNodePath.clear(); + } + return false; + } + return true; + } /** Reset the internal GUIEvent stack.*/ void flushMouseEventStack(); @@ -133,7 +155,8 @@ class OSGGA_EXPORT NodeTrackerManipulator : public MatrixManipulator osg::ref_ptr _ga_t0; osg::ref_ptr _node; - osg::ref_ptr _trackNode; + + osg::RefNodePath _trackNodePath; TrackerMode _trackerMode; RotationMode _rotationMode; diff --git a/src/osg/Transform.cpp b/src/osg/Transform.cpp index 7caeea81f..269da8838 100644 --- a/src/osg/Transform.cpp +++ b/src/osg/Transform.cpp @@ -46,10 +46,11 @@ class TransformVisitor : public NodeVisitor } } - void accumulate(NodePath& nodePath) + void accumulate(const NodePath& nodePath) { - for(NodePath::iterator itr=nodePath.begin(); - itr!=nodePath.end(); + NodePath& non_const_nodePath = const_cast(nodePath); + for(NodePath::iterator itr=non_const_nodePath.begin(); + itr!=non_const_nodePath.end(); ++itr) { (*itr)->accept(*this); @@ -58,7 +59,7 @@ class TransformVisitor : public NodeVisitor }; -Matrix osg::computeLocalToWorld(NodePath& nodePath) +Matrix osg::computeLocalToWorld(const NodePath& nodePath) { Matrix matrix; TransformVisitor tv(matrix,TransformVisitor::LOCAL_TO_WORLD); @@ -66,7 +67,7 @@ Matrix osg::computeLocalToWorld(NodePath& nodePath) return matrix; } -Matrix osg::computeWorldToLocal(NodePath& nodePath) +Matrix osg::computeWorldToLocal(const NodePath& nodePath) { osg::Matrix matrix; TransformVisitor tv(matrix,TransformVisitor::WORLD_TO_LOCAL); @@ -74,7 +75,7 @@ Matrix osg::computeWorldToLocal(NodePath& nodePath) return matrix; } -Matrix osg::computeLocalToEye(const Matrix& modelview,NodePath& nodePath) +Matrix osg::computeLocalToEye(const Matrix& modelview,const NodePath& nodePath) { Matrix matrix(modelview); TransformVisitor tv(matrix,TransformVisitor::LOCAL_TO_WORLD); @@ -82,7 +83,7 @@ Matrix osg::computeLocalToEye(const Matrix& modelview,NodePath& nodePath) return matrix; } -Matrix osg::computeEyeToLocal(const Matrix& modelview,NodePath& nodePath) +Matrix osg::computeEyeToLocal(const Matrix& modelview,const NodePath& nodePath) { Matrix matrix; matrix.invert(modelview); diff --git a/src/osgGA/NodeTrackerManipulator.cpp b/src/osgGA/NodeTrackerManipulator.cpp index f3ecb9c58..470127b24 100644 --- a/src/osgGA/NodeTrackerManipulator.cpp +++ b/src/osgGA/NodeTrackerManipulator.cpp @@ -72,6 +72,16 @@ void NodeTrackerManipulator::setNode(osg::Node* node) if (getAutoComputeHomePosition()) computeHomePosition(); } +void NodeTrackerManipulator::setTrackNode(osg::Node* node) +{ + CollectParentPaths cpp; + node->accept(cpp); + + if (!cpp._nodePaths.empty()) + { + _trackNodePath = cpp._nodePaths[0]; + } +} const osg::Node* NodeTrackerManipulator::getNode() const { @@ -321,32 +331,19 @@ void NodeTrackerManipulator::setByMatrix(const osg::Matrixd& matrix) void NodeTrackerManipulator::computeNodeWorldToLocal(osg::Matrixd& worldToLocal) const { - if (_trackNode.valid()) + if (validateNodePath()) { - CollectParentPaths cpp; - NodeTrackerManipulator* non_const_this = const_cast(this); - non_const_this->_trackNode->accept(cpp); - - if (!cpp._nodePaths.empty()) - { - worldToLocal = osg::computeWorldToLocal(cpp._nodePaths[0]); - } + worldToLocal = osg::computeWorldToLocal(_trackNodePath); } } void NodeTrackerManipulator::computeNodeLocalToWorld(osg::Matrixd& localToWorld) const { - if (_trackNode.valid()) + if (validateNodePath()) { - CollectParentPaths cpp; - NodeTrackerManipulator* non_const_this = const_cast(this); - non_const_this->_trackNode->accept(cpp); - - if (!cpp._nodePaths.empty()) - { - localToWorld = osg::computeLocalToWorld(cpp._nodePaths[0]); - } + localToWorld = osg::computeLocalToWorld(_trackNodePath); } + } void NodeTrackerManipulator::computeNodeCenterAndRotation(osg::Vec3d& nodeCenter, osg::Quat& nodeRotation) const @@ -354,8 +351,8 @@ void NodeTrackerManipulator::computeNodeCenterAndRotation(osg::Vec3d& nodeCenter osg::Matrixd localToWorld; computeNodeLocalToWorld(localToWorld); - if (_trackNode.valid()) - nodeCenter = _trackNode->getBound().center()*localToWorld; + if (validateNodePath()) + nodeCenter = _trackNodePath.back()->getBound().center()*localToWorld; else nodeCenter = osg::Vec3d(0.0f,0.0f,0.0f)*localToWorld; @@ -482,25 +479,13 @@ bool NodeTrackerManipulator::calcMovement() if (dx==0 && dy==0) return false; - if (_trackNode.valid()) + if (validateNodePath()) { - // osg::notify(osg::NOTICE)<<"_trackNode="<<_trackNode->getName()<accept(cpp); - - // osg::notify(osg::NOTICE)<<"number of nodepaths = "<getBound().center() * localToWorld; - - - } - } + _center = _trackNodePath.back()->getBound().center() * localToWorld; + } unsigned int buttonMask = _ga_t1->getButtonMask(); if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)