Improved handling of intersection computations on datasets with multiple cameras

This commit is contained in:
Robert Osfield
2007-01-15 16:09:32 +00:00
parent b06dbda224
commit 91968a9bec
3 changed files with 198 additions and 51 deletions

View File

@@ -6,6 +6,114 @@
#include <osgGA/AnimationPathManipulator>
#include <iostream>
class ThreadingHandler : public osgGA::GUIEventHandler
{
public:
ThreadingHandler() {}
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
if (!viewer) return false;
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYUP):
{
if (ea.getKey()=='m')
{
switch(viewer->getThreadingModel())
{
case(osgViewer::Viewer::SingleThreaded):
viewer->setThreadingModel(osgViewer::Viewer::ThreadPerContext);
osg::notify(osg::NOTICE)<<"Threading model 'ThreadPerContext' selected."<<std::endl;
break;
case(osgViewer::Viewer::ThreadPerContext):
viewer->setThreadingModel(osgViewer::Viewer::ThreadPerCamera);
osg::notify(osg::NOTICE)<<"Threading model 'ThreadPerCamera' selected."<<std::endl;
break;
case(osgViewer::Viewer::ThreadPerCamera):
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
osg::notify(osg::NOTICE)<<"Threading model 'SingleTheaded' selected."<<std::endl;
break;
}
return true;
}
if (ea.getKey()=='e')
{
switch(viewer->getEndBarrierPosition())
{
case(osgViewer::Viewer::BeforeSwapBuffers):
viewer->setEndBarrierPosition(osgViewer::Viewer::AfterSwapBuffers);
osg::notify(osg::NOTICE)<<"Threading model 'AfterSwapBuffers' selected."<<std::endl;
break;
case(osgViewer::Viewer::AfterSwapBuffers):
viewer->setEndBarrierPosition(osgViewer::Viewer::BeforeSwapBuffers);
osg::notify(osg::NOTICE)<<"Threading model 'BeforeSwapBuffers' selected."<<std::endl;
break;
}
return true;
}
}
default: break;
}
return false;
}
bool _done;
};
class ModelHandler : public osgGA::GUIEventHandler
{
public:
ModelHandler():
_position(0) {}
typedef std::vector<std::string> Filenames;
Filenames _filenames;
unsigned int _position;
void add(const std::string& filename) { _filenames.push_back(filename); }
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
if (!viewer) return false;
if (_filenames.empty()) return false;
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYUP):
{
if (ea.getKey()=='l')
{
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile( _filenames[_position] );
++_position;
if (_position>=_filenames.size()) _position = 0;
if (model.valid())
{
viewer->setSceneData(model.get());
}
return true;
}
}
default: break;
}
return false;
}
bool _done;
};
void singleWindowMultipleCameras(osgViewer::Viewer& viewer)
{
osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
@@ -147,6 +255,18 @@ int main( int argc, char **argv )
if (apm.valid()) viewer.setCameraManipulator(apm.get());
else viewer.setCameraManipulator( new osgGA::TrackballManipulator() );
#if 0
ModelHandler* modelHandler = new ModelHandler;
for(int i=1; i<arguments.argc();++i)
{
modelHandler->add(arguments[i]);
}
viewer.addEventHandler(modelHandler);
#else
// load the scene.
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
if (!loadedModel)
@@ -156,8 +276,7 @@ int main( int argc, char **argv )
}
viewer.setSceneData(loadedModel.get());
// viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
#endif
viewer.realize();

View File

@@ -68,6 +68,10 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter
void setUpViewOnSingleScreen(unsigned int screenNum=0);
/** Get the camera which contains the pointer position x,y specified master cameras window/eye coords.
* Also passes back the local window coords for the graphics context associated with the camera passed back. */
const osg::Camera* getCameraContainingPosition(float x, float y, float& local_x, float& local_y) const;
/** Compute intersections between a ray through the specified master cameras window/eye coords and a specified node.
* Note, when a master cameras has slaves and no viewport itself its coordinate frame will be in clip space i.e. -1,-1 to 1,1,
* while if its has a viewport the coordintates will be relative to its viewport dimensions.
@@ -82,6 +86,8 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter
virtual void requestRedraw();
virtual void requestContinuousUpdate(bool needed=true);
virtual void requestWarpPointer(float x,float y);
public:

View File

@@ -311,26 +311,49 @@ void View::requestContinuousUpdate(bool)
void View::requestWarpPointer(float x,float y)
{
// osg::notify(osg::NOTICE)<<"View::requestWarpPointer("<<x<<","<<y<<")"<<std::endl;
osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
getEventQueue()->mouseWarped(x,y);
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
if (gw)
float local_x, local_y;
const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
if (camera)
{
bool gw_invert_y = gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
const osgViewer::GraphicsWindow* gw = dynamic_cast<const osgViewer::GraphicsWindow*>(camera->getGraphicsContext());
if (gw)
{
if (gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS)
{
local_y = gw->getTraits()->height - local_y;
}
const_cast<osgViewer::GraphicsWindow*>(gw)->requestWarpPointer(local_x, local_y);
}
}
}
x = x * float(gw->getTraits()->width) / (eventState->getXmax()-eventState->getXmin());
y = y * float(gw->getTraits()->height) / (eventState->getYmax()-eventState->getYmin());
const osg::Camera* View::getCameraContainingPosition(float x, float y, float& local_x, float& local_y) const
{
const osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
double epsilon = 0.5;
if (view_invert_y != gw_invert_y) y = gw->getTraits()->height - y;
if (_camera->getGraphicsContext() && _camera->getViewport())
{
const osg::Viewport* viewport = _camera->getViewport();
gw->requestWarpPointer(x, y);
osg::Vec2d new_coord(x, y);
return;
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
if (gw && gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS)
{
new_coord.y() = gw->getTraits()->height - new_coord.y();
}
if (viewport &&
new_coord.x() >= (viewport->x()-epsilon) && new_coord.y() >= (viewport->y()-epsilon) &&
new_coord.x() < (viewport->x()+viewport->width()-1.0+epsilon) && new_coord.y() <= (viewport->y()+viewport->height()-1.0+epsilon) )
{
local_x = new_coord.x();
local_y = new_coord.y();
return _camera.get();
}
}
osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
@@ -343,15 +366,14 @@ void View::requestWarpPointer(float x,float y)
// osg::notify(osg::NOTICE)<<" remapped ("<<x<<","<<y<<")"<<std::endl;;
// osg::notify(osg::NOTICE)<<" number of slaves = "<<getNumSlaves()<<std::endl;;
double epsilon = 0.5;
for(unsigned i=0; i<getNumSlaves(); ++i)
{
Slave& slave = getSlave(i);
const Slave& slave = getSlave(i);
if (slave._camera.valid())
{
osg::Camera* camera = slave._camera.get();
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
const osg::Camera* camera = slave._camera.get();
const osg::Viewport* viewport = camera ? camera->getViewport() : 0;
osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
@@ -367,46 +389,40 @@ void View::requestWarpPointer(float x,float y)
new_coord.x() < (viewport->x()+viewport->width()-1.0+epsilon) && new_coord.y() <= (viewport->y()+viewport->height()-1.0+epsilon) )
{
// osg::notify(osg::NOTICE)<<" in viewport "<<std::endl;;
local_x = new_coord.x();
local_y = new_coord.y();
gw = dynamic_cast<osgViewer::GraphicsWindow*>(camera->getGraphicsContext());
if (gw)
{
x = new_coord.x();
y = new_coord.y();
bool gw_invert_y = gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (gw_invert_y) y = gw->getTraits()->height - y;
gw->requestWarpPointer(x, y);
return;
}
return camera;
}
else
{
// osg::notify(osg::NOTICE)<<" not in viewport "<<viewport->x()<<" "<<(viewport->x()+viewport->width())<<std::endl;;
}
}
}
// osg::notify(osg::NOTICE)<<" ** no warping applied. **"<<std::endl;
}
local_x = x;
local_y = y;
return 0;
}
bool View::computeIntersections(float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask)
{
if (!_camera.valid()) return false;
float local_x, local_y = 0.0;
const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
if (!camera) camera = _camera.get();
osgUtil::LineSegmentIntersector::CoordinateFrame cf = _camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector(cf, x, y);
osgUtil::LineSegmentIntersector::CoordinateFrame cf = camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector(cf, local_x, local_y);
osgUtil::IntersectionVisitor iv(picker);
iv.setTraversalMask(traversalMask);
_camera->accept(iv);
const_cast<osg::Camera*>(camera)->accept(iv);
if (picker->containsIntersections())
{
@@ -418,28 +434,34 @@ bool View::computeIntersections(float x,float y, osgUtil::LineSegmentIntersector
intersections.clear();
return false;
}
return false;
}
bool View::computeIntersections(float x,float y, osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask)
{
if (!_camera.valid()) return false;
osg::Matrix matrix = osg::computeWorldToLocal(nodePath) * _camera->getViewMatrix() * _camera->getProjectionMatrix();
float local_x, local_y = 0.0;
const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
if (!camera) camera = _camera.get();
osg::Matrix matrix = osg::computeWorldToLocal(nodePath) * camera->getViewMatrix() * camera->getProjectionMatrix();
double zNear = -1.0;
double zFar = 1.0;
if (_camera->getViewport())
if (camera->getViewport())
{
matrix.postMult(_camera->getViewport()->computeWindowMatrix());
matrix.postMult(camera->getViewport()->computeWindowMatrix());
zNear = 0.0;
zFar = 1.0;
}
osg::Matrix inverse;
inverse.invert(matrix);
osg::Vec3d startVertex = osg::Vec3d(x,y,zNear) * inverse;
osg::Vec3d endVertex = osg::Vec3d(x,y,zFar) * inverse;
osg::Vec3d startVertex = osg::Vec3d(local_x,local_y,zNear) * inverse;
osg::Vec3d endVertex = osg::Vec3d(local_x,local_y,zFar) * inverse;
osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::MODEL, startVertex, endVertex);