diff --git a/include/osg/Node b/include/osg/Node index b02aa7323..a36cb315c 100644 --- a/include/osg/Node +++ b/include/osg/Node @@ -28,6 +28,14 @@ namespace osg { class NodeVisitor; class Group; class Transform; +class Node; + +/** A vector of Nodes pointers which is used to describe the path from a root node to a descendant.*/ +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; + /** META_Node macro define the standard clone, isSameKindAs, className * and accept methods. Use when subclassing from Node to make it @@ -103,6 +111,7 @@ class OSG_EXPORT Node : public Object inline ParentList getParents() { return _parents; } inline Group* getParent(unsigned int i) { return _parents[i]; } + /** * Get a single const parent of node. * @param i index of the parent to get. @@ -116,6 +125,10 @@ class OSG_EXPORT Node : public Object */ inline unsigned int getNumParents() const { return _parents.size(); } + /** Get the list of node paths parent paths. + * The optional Node* haltTraversalAtNode allows the user to prevent traversal beyond a specifed node. */ + NodePathList getParentalNodePaths(osg::Node* haltTraversalAtNode=0) const; + /** Set update node callback, called during update traversal. */ void setUpdateCallback(NodeCallback* nc); @@ -337,9 +350,6 @@ class OSG_EXPORT Node : public Object }; -/** A vector of Nodes pointers which is used to describe the path from a root node to a descendant.*/ -typedef std::vector NodePath; - } #endif diff --git a/src/osg/Node.cpp b/src/osg/Node.cpp index 6cddd0318..81520364e 100644 --- a/src/osg/Node.cpp +++ b/src/osg/Node.cpp @@ -21,6 +21,36 @@ using namespace osg; +namespace osg +{ + /// Helper class for generating NodePathList. + class CollectParentPaths : public NodeVisitor + { + public: + CollectParentPaths(osg::Node* haltTraversalAtNode=0) : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS), + _haltTraversalAtNode(haltTraversalAtNode) + { + } + + virtual void apply(osg::Node& node) + { + if (node.getNumParents()==0 || &node==_haltTraversalAtNode) + { + _nodePaths.push_back(getNodePath()); + } + else + { + traverse(node); + } + } + + Node* _haltTraversalAtNode; + NodePath _nodePath; + NodePathList _nodePaths; + }; +} + Node::Node() { _boundingSphereComputed = false; @@ -133,6 +163,12 @@ osg::StateSet* Node::getOrCreateStateSet() return _stateset.get(); } +NodePathList Node::getParentalNodePaths(osg::Node* haltTraversalAtNode) const +{ + CollectParentPaths cpp(haltTraversalAtNode); + const_cast(this)->accept(cpp); + return cpp._nodePaths; +} void Node::setUpdateCallback(NodeCallback* nc) { diff --git a/src/osg/NodeTrackerCallback.cpp b/src/osg/NodeTrackerCallback.cpp index 3850c8138..9b7c3053c 100644 --- a/src/osg/NodeTrackerCallback.cpp +++ b/src/osg/NodeTrackerCallback.cpp @@ -21,26 +21,6 @@ using namespace osg; -class CollectParentPaths : public osg::NodeVisitor -{ -public: - CollectParentPaths() : - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {} - - virtual void apply(osg::Node& node) - { - if (node.getNumParents()==0) - { - _nodePaths.push_back(getNodePath()); - } - traverse(node); - } - - osg::NodePath _nodePath; - typedef std::vector< osg::NodePath > NodePathList; - NodePathList _nodePaths; -}; - class ApplyMatrixVisitor : public NodeVisitor { public: @@ -88,13 +68,12 @@ void NodeTrackerCallback::setTrackNode(osg::Node* node) return; } - CollectParentPaths cpp; - node->accept(cpp); + NodePathList parentNodePaths = node->getParentalNodePaths(); - if (!cpp._nodePaths.empty()) + if (!parentNodePaths.empty()) { osg::notify(osg::INFO)<<"NodeTrackerCallback::setTrackNode(Node*): Path set"<getViewport(); proj = sv->getProjectionMatrix(); view = sv->getViewMatrix(); + rootNode = sv->getSceneData(); } else { @@ -764,19 +766,37 @@ bool Viewer::computeIntersections(float x,float y,unsigned int cameraNum,osg::No view = osg::Matrixd(camera->getViewMatrix()); } - osgUtil::PickVisitor pick(viewport, proj, view, pixel_x, pixel_y); - pick.setTraversalMask(traversalMask); - node->accept(pick); - - // copy all the hits across to the external hits list - for(osgUtil::PickVisitor::LineSegmentHitListMap::iterator itr = pick.getSegHitList().begin(); - itr != pick.getSegHitList().end(); - ++itr) + unsigned int numHitsBefore = hits.size(); + + osg::NodePathList parentNodePaths = node->getParentalNodePaths(rootNode); + for(unsigned int i=0;isecond.begin(), itr->second.end()); + osg::NodePath& nodePath = parentNodePaths[i]; + + // remove the intersection node from the nodePath as it'll be accounted for + // in the PickVisitor traversal, so we don't double account for its transform. + if (!nodePath.empty()) nodePath.pop_back(); + + osg::Matrixd modelview(view); + // modify the view matrix so that it accounts for this nodePath's accumulated transform + if (!nodePath.empty()) modelview.preMult(computeLocalToWorld(nodePath)); + + osgUtil::PickVisitor pick(viewport, proj, modelview, pixel_x, pixel_y); + pick.setTraversalMask(traversalMask); + node->accept(pick); + + // copy all the hits across to the external hits list + for(osgUtil::PickVisitor::LineSegmentHitListMap::iterator itr = pick.getSegHitList().begin(); + itr != pick.getSegHitList().end(); + ++itr) + { + hits.insert(hits.end(),itr->second.begin(), itr->second.end()); + } + } - return true; + // return true if we now have more hits than before + return hits.size()>numHitsBefore; } return false; } diff --git a/src/osgWrappers/osg/Node.cpp b/src/osgWrappers/osg/Node.cpp index e4cdac4bc..3603278cd 100644 --- a/src/osgWrappers/osg/Node.cpp +++ b/src/osgWrappers/osg/Node.cpp @@ -55,6 +55,7 @@ BEGIN_OBJECT_REFLECTOR(osg::Node) I_Method1(osg::Group *, getParent, IN, unsigned int, i); I_Method1(const osg::Group *, getParent, IN, unsigned int, i); I_Method0(unsigned int, getNumParents); + I_MethodWithDefaults1(osg::NodePathList, getParentalNodePaths, IN, osg::Node *, haltTraversalAtNode, 0); I_Method1(void, setUpdateCallback, IN, osg::NodeCallback *, nc); I_Method0(osg::NodeCallback *, getUpdateCallback); I_Method0(const osg::NodeCallback *, getUpdateCallback); @@ -123,7 +124,11 @@ END_REFLECTOR TYPE_NAME_ALIAS(std::vector< osg::Node * >, osg::NodePath); +TYPE_NAME_ALIAS(std::vector< osg::NodePath >, osg::NodePathList); + STD_VECTOR_REFLECTOR(std::vector< osg::Group * >); +STD_VECTOR_REFLECTOR(std::vector< osg::NodePath >); + STD_VECTOR_REFLECTOR(std::vector< std::string >); diff --git a/src/osgWrappers/osgTerrain/DataSet.cpp b/src/osgWrappers/osgTerrain/DataSet.cpp index b4af99eab..81edf7aae 100644 --- a/src/osgWrappers/osgTerrain/DataSet.cpp +++ b/src/osgWrappers/osgTerrain/DataSet.cpp @@ -337,6 +337,8 @@ BEGIN_OBJECT_REFLECTOR(osgTerrain::DataSet::Source) I_Method0(const std::string &, getFileName); I_Method1(void, setTemporaryFile, IN, bool, temporaryFile); I_Method0(bool, getTemporaryFile); + I_Method1(void, setGdalDataSet, IN, GDALDataset *, gdalDataSet); + I_Method0(GDALDataset *, getGdalDataSet); I_Method1(void, setCoordinateSystemPolicy, IN, osgTerrain::DataSet::Source::ParameterPolicy, policy); I_Method0(osgTerrain::DataSet::Source::ParameterPolicy, getCoordinateSystemPolicy); I_Method1(void, setCoordinateSystem, IN, const std::string &, wellKnownText); @@ -371,6 +373,7 @@ BEGIN_OBJECT_REFLECTOR(osgTerrain::DataSet::Source) I_Property(osg::CoordinateSystemNode *, CoordinateSystem); I_Property(osgTerrain::DataSet::Source::ParameterPolicy, CoordinateSystemPolicy); I_Property(const std::string &, FileName); + I_Property(GDALDataset *, GdalDataSet); I_Property(osg::Matrixd &, GeoTransform); I_Property(osgTerrain::DataSet::Source::ParameterPolicy, GeoTransformPolicy); I_Property(unsigned int, Layer);