Added support for tracking the CoordinateSystemNode path, and passing this on to

camera manipulators.
This commit is contained in:
Robert Osfield
2007-05-18 10:33:56 +00:00
parent 79b274b3d6
commit 0d71586ee0
3 changed files with 162 additions and 2 deletions

View File

@@ -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<osgGA::MatrixManipulator> _cameraManipulator;
EventHandlers _eventHandlers;
typedef std::vector< osg::observer_ptr<osg::Node> > ObserveredNodePath;
ObserveredNodePath _coordinateSystemNodePath;
osg::ref_ptr<osg::DisplaySettings> _displaySettings;
osgUtil::SceneView::FusionDistanceMode _fusionDistanceMode;
float _fusionDistanceValue;

View File

@@ -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"<<std::endl;
osg::notify(osg::INFO)<<" CoordinateSystem = "<<node.getCoordinateSystem()<<std::endl;
_pathToCoordinateSystemNode = getNodePath();
}
else
{
osg::notify(osg::INFO)<<"Found additional CoordianteSystemNode node, but ignoring"<<std::endl;
osg::notify(osg::INFO)<<" CoordinateSystem = "<<node.getCoordinateSystem()<<std::endl;
}
traverse(node);
}
osg::NodePath _pathToCoordinateSystemNode;
};
/** callback class to use to allow matrix manipulators to querry the application for the local coordinate frame.*/
class ViewerCoordinateFrameCallback : public osgGA::MatrixManipulator::CoordinateFrameCallback
{
public:
ViewerCoordinateFrameCallback(osgViewer::View* view):
_view(view) {}
virtual osg::CoordinateFrame getCoordinateFrame(const osg::Vec3d& position) const
{
osg::notify(osg::INFO)<<"getCoordinateFrame("<<position<<")"<<std::endl;
osg::NodePath tmpPath = _view->getCoordinateSystemNodePath();
if (!tmpPath.empty())
{
osg::Matrixd coordinateFrame;
osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(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)"<<coordinateFrame<<std::endl;
}
else
{
osg::notify(osg::INFO)<<"osg::computeLocalToWorld(tmpPath)"<<std::endl;
coordinateFrame = osg::computeLocalToWorld(tmpPath);
}
return coordinateFrame;
}
else
{
osg::notify(osg::INFO)<<" no coordinate system found, using default orientation"<<std::endl;
return osg::Matrixd::translate(position);
}
}
protected:
virtual ~ViewerCoordinateFrameCallback() {}
osg::observer_ptr<osgViewer::View> _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<osgGA::GUIEventAdapter> 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<osg::Node*>(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();

View File

@@ -765,6 +765,8 @@ void Viewer::setSceneData(osg::Node* node)
_scene->setSceneData(node);
_scene->setFrameStamp(_frameStamp.get());
computeActiveCoordinateSystemNodePath();
setReferenceTime(0.0);
assignSceneDataToCameras();