From 0d71586ee00c871293a8e812d3777c681b9ffaa7 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 18 May 2007 10:33:56 +0000 Subject: [PATCH] Added support for tracking the CoordinateSystemNode path, and passing this on to camera manipulators. --- include/osgViewer/View | 13 ++++ src/osgViewer/View.cpp | 149 ++++++++++++++++++++++++++++++++++++++- src/osgViewer/Viewer.cpp | 2 + 3 files changed, 162 insertions(+), 2 deletions(-) diff --git a/include/osgViewer/View b/include/osgViewer/View index e8a1387ff..1a71b245c 100644 --- a/include/osgViewer/View +++ b/include/osgViewer/View @@ -84,6 +84,16 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter EventHandlers& getEventHandlers() { return _eventHandlers; } const EventHandlers& getEventHandlers() const { return _eventHandlers; } + + /** Set the NodePath to any active CoordinateSystemNode present in the Scene.*/ + void setCoordinateSystemNodePath(const osg::NodePath& nodePath); + + /** Get the NodePath to any active CoordinateSystemNode present in the Scene.*/ + osg::NodePath getCoordinateSystemNodePath() const; + + /** Compute the NodePath to any active CoordinateSystemNode present in the Scene.*/ + void computeActiveCoordinateSystemNodePath(); + /** Set the DsplaySettings object associated with this view.*/ void setDisplaySettings(osg::DisplaySettings* ds) { _displaySettings = ds; } @@ -154,6 +164,9 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter osg::ref_ptr _cameraManipulator; EventHandlers _eventHandlers; + typedef std::vector< osg::observer_ptr > ObserveredNodePath; + ObserveredNodePath _coordinateSystemNodePath; + osg::ref_ptr _displaySettings; osgUtil::SceneView::FusionDistanceMode _fusionDistanceMode; float _fusionDistanceValue; diff --git a/src/osgViewer/View.cpp b/src/osgViewer/View.cpp index 3510ad976..73c29609e 100644 --- a/src/osgViewer/View.cpp +++ b/src/osgViewer/View.cpp @@ -20,6 +20,104 @@ using namespace osgViewer; +class CollectedCoordinateSystemNodesVisitor : public osg::NodeVisitor +{ +public: + + CollectedCoordinateSystemNodesVisitor(): + NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {} + + + virtual void apply(osg::Node& node) + { + traverse(node); + } + + virtual void apply(osg::CoordinateSystemNode& node) + { + if (_pathToCoordinateSystemNode.empty()) + { + osg::notify(osg::INFO)<<"Found CoordianteSystemNode node"<getCoordinateSystemNodePath(); + + if (!tmpPath.empty()) + { + osg::Matrixd coordinateFrame; + + osg::CoordinateSystemNode* csn = dynamic_cast(tmpPath.back()); + if (csn) + { + osg::Vec3 local_position = position*osg::computeWorldToLocal(tmpPath); + + // get the coordinate frame in world coords. + coordinateFrame = csn->computeLocalCoordinateFrame(local_position)* osg::computeLocalToWorld(tmpPath); + + // keep the position of the coordinate frame to reapply after rescale. + osg::Vec3d pos = coordinateFrame.getTrans(); + + // compensate for any scaling, so that the coordinate frame is a unit size + osg::Vec3d x(1.0,0.0,0.0); + osg::Vec3d y(0.0,1.0,0.0); + osg::Vec3d z(0.0,0.0,1.0); + x = osg::Matrixd::transform3x3(x,coordinateFrame); + y = osg::Matrixd::transform3x3(y,coordinateFrame); + z = osg::Matrixd::transform3x3(z,coordinateFrame); + coordinateFrame.preMult(osg::Matrixd::scale(1.0/x.length(),1.0/y.length(),1.0/z.length())); + + // reapply the position. + coordinateFrame.setTrans(pos); + + osg::notify(osg::INFO)<<"csn->computeLocalCoordinateFrame(position)* osg::computeLocalToWorld(tmpPath)"< _view; +}; + View::View(): _fusionDistanceMode(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE), _fusionDistanceValue(1.0f) @@ -64,15 +162,20 @@ void View::setSceneData(osg::Node* node) _scene = new osgViewer::Scene; _scene->setSceneData(node); + computeActiveCoordinateSystemNodePath(); + assignSceneDataToCameras(); } void View::setCameraManipulator(osgGA::MatrixManipulator* manipulator) { _cameraManipulator = manipulator; - if (_cameraManipulator.valid() && getSceneData()) + + if (_cameraManipulator.valid()) { - _cameraManipulator->setNode(getSceneData()); + _cameraManipulator->setCoordinateFrameCallback(new ViewerCoordinateFrameCallback(this)); + + if (getSceneData()) _cameraManipulator->setNode(getSceneData()); osg::ref_ptr dummyEvent = _eventQueue->createEvent(); @@ -85,6 +188,48 @@ void View::addEventHandler(osgGA::GUIEventHandler* eventHandler) _eventHandlers.push_back(eventHandler); } +void View::setCoordinateSystemNodePath(const osg::NodePath& nodePath) +{ + _coordinateSystemNodePath.clear(); + std::copy(nodePath.begin(), + nodePath.end(), + std::back_inserter(_coordinateSystemNodePath)); +} + +osg::NodePath View::getCoordinateSystemNodePath() const +{ + osg::NodePath nodePath; + for(ObserveredNodePath::const_iterator itr = _coordinateSystemNodePath.begin(); + itr != _coordinateSystemNodePath.end(); + ++itr) + { + nodePath.push_back(const_cast(itr->get())); + } + return nodePath; +} + +void View::computeActiveCoordinateSystemNodePath() +{ + // now search for CoordinateSystemNode's for which we want to track. + osg::Node* subgraph = getSceneData(); + + if (subgraph) + { + + CollectedCoordinateSystemNodesVisitor ccsnv; + subgraph->accept(ccsnv); + + if (!ccsnv._pathToCoordinateSystemNode.empty()) + { + setCoordinateSystemNodePath(ccsnv._pathToCoordinateSystemNode); + return; + } + } + + // otherwise no node path found so reset to empty. + setCoordinateSystemNodePath(osg::NodePath()); +} + void View::setUpViewAcrossAllScreens() { osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index f6085bfb5..0933430e4 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -765,6 +765,8 @@ void Viewer::setSceneData(osg::Node* node) _scene->setSceneData(node); _scene->setFrameStamp(_frameStamp.get()); + computeActiveCoordinateSystemNodePath(); + setReferenceTime(0.0); assignSceneDataToCameras();