Introduced new scheme for handling mouse events with osgViewer. The new scheme enables robust event handling even when using distortion correction render to texture Cameras.

This commit is contained in:
Robert Osfield
2013-05-03 19:26:27 +00:00
parent 63088ab63e
commit 668d351765
36 changed files with 1116 additions and 698 deletions

View File

@@ -12,6 +12,9 @@
*/
#include <osg/GLExtensions>
#include <osg/TextureRectangle>
#include <osg/TextureCubeMap>
#include <osgGA/TrackballManipulator>
#include <osgViewer/CompositeViewer>
#include <osgViewer/Renderer>
@@ -640,27 +643,6 @@ void CompositeViewer::advance(double simulationTime)
_frameStamp->setSimulationTime(simulationTime);
}
for(RefViews::iterator vitr = _views.begin();
vitr != _views.end();
++vitr)
{
View* view = vitr->get();
osgGA::GUIEventAdapter* eventState = view->getEventQueue()->getCurrentEventState();
if (view->getCamera()->getViewport())
{
osg::Viewport* viewport = view->getCamera()->getViewport();
eventState->setInputRange( viewport->x(), viewport->y(), viewport->x() + viewport->width(), viewport->y() + viewport->height());
}
else
{
eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
}
view->getEventQueue()->frame( getFrameStamp()->getReferenceTime() );
}
if (getViewerStats() && getViewerStats()->collectStats("frame_rate"))
{
@@ -697,6 +679,195 @@ void CompositeViewer::setCameraWithFocus(osg::Camera* camera)
_viewWithFocus = 0;
}
void CompositeViewer::generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event)
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
if (!gw) return;
// What type of Camera is it?
// 1) Master Camera : do nothin extra
// 2) Slave Camera, Relative RF, Same scene graph as master : transform coords into Master Camera and add to PointerData list
// 3) Slave Camera, Relative RF, Different scene graph from master : do nothing extra?
// 4) Slave Camera, Absolute RF, Same scene graph as master : do nothing extra?
// 5) Slave Camera, Absolute RF, Different scene graph : do nothing extra?
// 6) Slave Camera, Absolute RF, Different scene graph but a distortion correction subgraph depending upon RTT Camera (slave or master)
// : project ray into RTT Camera's clip space, and RTT Camera's is Relative RF and sharing same scene graph as master then transform coords.
// if camera isn't the master it must be a slave and could need reprojecting.
osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
if (!view) return;
osg::Camera* view_masterCamera = view->getCamera();
if (camera!=view_masterCamera)
{
float x = event.getX();
float y = event.getY();
bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
osg::Matrix masterCameraVPW = view_masterCamera->getViewMatrix() * view_masterCamera->getProjectionMatrix();
if (view_masterCamera->getViewport())
{
osg::Viewport* viewport = view_masterCamera->getViewport();
masterCameraVPW *= viewport->computeWindowMatrix();
}
// slave Camera tahnks to sharing the same View
osg::View::Slave* slave = view ? view->findSlaveForCamera(camera) : 0;
if (slave)
{
if (camera->getReferenceFrame()==osg::Camera::RELATIVE_RF && slave->_useMastersSceneData)
{
osg::Viewport* viewport = camera->getViewport();
osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
//OSG_NOTICE<<" pointer event new_coord.x()="<<new_coord.x()<<" new_coord.y()="<<new_coord.y()<<std::endl;
event.addPointerData(new osgGA::PointerData(view_masterCamera, new_coord.x(), -1.0, 1.0,
new_coord.y(), -1.0, 1.0));
}
else if (!slave->_useMastersSceneData)
{
// Are their any RTT Camera's that this Camera depends upon for textures?
osg::ref_ptr<osgUtil::LineSegmentIntersector> ray = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x,y);
osgUtil::IntersectionVisitor iv(ray.get());
camera->accept(iv);
if (ray->containsIntersections())
{
osg::Vec3 tc;
osg::Texture* texture = ray->getFirstIntersection().getTextureLookUp(tc);
if (texture)
{
// look up Texture in RTT Camera's.
for(unsigned int i=0; i<view->getNumSlaves();++i)
{
osg::Camera* slave_camera = view->getSlave(i)._camera;
if (slave_camera)
{
osg::Camera::BufferAttachmentMap::const_iterator ba_itr = slave_camera->getBufferAttachmentMap().find(osg::Camera::COLOR_BUFFER);
if (ba_itr != slave_camera->getBufferAttachmentMap().end())
{
if (ba_itr->second._texture == texture)
{
osg::TextureRectangle* tr = dynamic_cast<osg::TextureRectangle*>(ba_itr->second._texture.get());
osg::TextureCubeMap* tcm = dynamic_cast<osg::TextureCubeMap*>(ba_itr->second._texture.get());
if (tr)
{
event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, static_cast<float>(tr->getTextureWidth()),
tc.y(), 0.0f, static_cast<float>(tr->getTextureHeight())));
}
else if (tcm)
{
OSG_NOTICE<<" Slave has matched texture cubemap"<<ba_itr->second._texture.get()<<", "<<ba_itr->second._face<<std::endl;
}
else
{
event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, 1.0f,
tc.y(), 0.0f, 1.0f));
}
}
}
}
}
}
}
}
}
}
}
void CompositeViewer::generatePointerData(osgGA::GUIEventAdapter& event)
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
if (!gw) return;
float x = event.getX();
float y = event.getY();
bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
y, 0, gw->getTraits()->height));
osg::GraphicsContext::Cameras& cameras = gw->getCameras();
for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
citr != cameras.end();
++citr)
{
osg::Camera* camera = *citr;
if (camera->getAllowEventFocus() &&
camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
{
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
if (viewport &&
x >= viewport->x() && y >= viewport->y() &&
x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
{
event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
(y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
osg::Camera* view_masterCamera = view ? view->getCamera() : 0;
// if camera isn't the master it must be a slave and could need reprojecting.
if (view && camera!=view_masterCamera)
{
generateSlavePointerData(camera, event);
}
}
}
}
}
void CompositeViewer::reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event)
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(dest_event.getGraphicsContext());
if (!gw) return;
float x = dest_event.getX();
float y = dest_event.getY();
bool invert_y = dest_event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
dest_event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
y, 0, gw->getTraits()->height));
osg::Camera* camera = (source_event.getNumPointerData()>=2) ? dynamic_cast<osg::Camera*>(source_event.getPointerData(1)->object.get()) : 0;
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
if (!viewport) return;
dest_event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
(y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
osg::Camera* view_masterCamera = view ? view->getCamera() : 0;
// if camera isn't the master it must be a slave and could need reprojecting.
if (view && camera!=view_masterCamera)
{
generateSlavePointerData(camera, dest_event);
}
}
struct SortEvents
{
bool operator() (const osg::ref_ptr<osgGA::GUIEventAdapter>& lhs,const osg::ref_ptr<osgGA::GUIEventAdapter>& rhs) const
{
return lhs->getTime() < rhs->getTime();
}
};
void CompositeViewer::eventTraversal()
{
if (_done) return;
@@ -707,10 +878,7 @@ void CompositeViewer::eventTraversal()
double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
// OSG_NOTICE<<"CompositeViewer::frameEventTraversal()."<<std::endl;
// need to copy events from the GraphicsWindow's into local EventQueue;
// need to copy events from the GraphicsWindow's into local EventQueue for each view;
typedef std::map<osgViewer::View*, osgGA::EventQueue::Events> ViewEventsMap;
ViewEventsMap viewEventsMap;
@@ -720,22 +888,9 @@ void CompositeViewer::eventTraversal()
// set done if there are no windows
checkWindowStatus(contexts);
if (_done) return;
Scenes scenes;
getScenes(scenes);
osgViewer::View* masterView = getViewWithFocus() ? getViewWithFocus() : _views[0].get();
osg::Camera* masterCamera = masterView->getCamera();
osgGA::GUIEventAdapter* eventState = masterView->getEventQueue()->getCurrentEventState();
osg::Matrix masterCameraVPW = masterCamera->getViewMatrix() * masterCamera->getProjectionMatrix();
if (masterCamera->getViewport())
{
osg::Viewport* viewport = masterCamera->getViewport();
masterCameraVPW *= viewport->computeWindowMatrix();
}
// get events from all windows attached to Viewer.
osgGA::EventQueue::Events all_events;
for(Contexts::iterator citr = contexts.begin();
citr != contexts.end();
++citr)
@@ -748,178 +903,130 @@ void CompositeViewer::eventTraversal()
osgGA::EventQueue::Events gw_events;
gw->getEventQueue()->takeEvents(gw_events, cutOffTime);
osgGA::EventQueue::Events::iterator itr;
for(itr = gw_events.begin();
for(osgGA::EventQueue::Events::iterator itr = gw_events.begin();
itr != gw_events.end();
++itr)
{
osgGA::GUIEventAdapter* event = itr->get();
//OSG_NOTICE<<"event->getGraphicsContext()="<<event->getGraphicsContext()<<std::endl;
bool pointerEvent = false;
float x = event->getX();
float y = event->getY();
bool invert_y = event->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::RESIZE):
setCameraWithFocus(0);
break;
case(osgGA::GUIEventAdapter::PUSH):
case(osgGA::GUIEventAdapter::RELEASE):
case(osgGA::GUIEventAdapter::DOUBLECLICK):
case(osgGA::GUIEventAdapter::DRAG):
case(osgGA::GUIEventAdapter::MOVE):
{
pointerEvent = true;
if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG || !getCameraWithFocus())
{
osg::GraphicsContext::Cameras& cameras = gw->getCameras();
for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
citr != cameras.end();
++citr)
{
osg::Camera* camera = *citr;
if ((camera->getNodeMask()!=0) &&
camera->getView() &&
camera->getAllowEventFocus() &&
camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
{
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
if (viewport &&
x >= viewport->x() && y >= viewport->y() &&
x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
{
setCameraWithFocus(camera);
// If this camera is not a slave camera
if (camera->getView()->getCamera() == camera)
{
eventState->setGraphicsContext(gw);
eventState->setInputRange( viewport->x(), viewport->y(),
viewport->x()+viewport->width(),
viewport->y()+viewport->height());
}
else
{
eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
}
if (getViewWithFocus()!=masterView)
{
// need to reset the masterView
masterView = getViewWithFocus();
masterCamera = masterView->getCamera();
eventState = masterView->getEventQueue()->getCurrentEventState();
masterCameraVPW = masterCamera->getViewMatrix() * masterCamera->getProjectionMatrix();
if (masterCamera->getViewport())
{
osg::Viewport* viewport = masterCamera->getViewport();
masterCameraVPW *= viewport->computeWindowMatrix();
}
}
// If this camera is not a slave camera
if (camera->getView()->getCamera() == camera)
{
eventState->setGraphicsContext(gw);
eventState->setInputRange( viewport->x(), viewport->y(),
viewport->x()+viewport->width(),
viewport->y()+viewport->height());
}
else
{
eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
}
}
}
}
}
break;
}
default:
break;
}
if (pointerEvent)
{
if (getCameraWithFocus())
{
osg::Viewport* viewport = getCameraWithFocus()->getViewport();
osg::Matrix localCameraVPW = getCameraWithFocus()->getViewMatrix() * getCameraWithFocus()->getProjectionMatrix();
if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
x = new_coord.x();
y = new_coord.y();
event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
event->setX(x);
event->setY(y);
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
}
// pass along the new pointer events details to the eventState of the viewer
eventState->setX(x);
eventState->setY(y);
eventState->setButtonMask(event->getButtonMask());
eventState->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
}
else
{
event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
event->setX(eventState->getX());
event->setY(eventState->getY());
event->setButtonMask(eventState->getButtonMask());
event->setMouseYOrientation(eventState->getMouseYOrientation());
}
(*itr)->setGraphicsContext(gw);
}
for(itr = gw_events.begin();
itr != gw_events.end();
++itr)
{
osgGA::GUIEventAdapter* event = itr->get();
switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
{
bool wasThreading = areThreadsRunning();
if (wasThreading) stopThreading();
gw->close();
if (wasThreading) startThreading();
break;
}
default:
break;
}
}
viewEventsMap[masterView].insert( viewEventsMap[masterView].end(), gw_events.begin(), gw_events.end() );
all_events.insert(all_events.end(), gw_events.begin(), gw_events.end());
}
}
// sort all the events in time order so we can make sure we pass them all on in the correct order.
all_events.sort(SortEvents());
// pass on pointer data onto non mouse events to keep the position data usable by all recipients of all events.
for(osgGA::EventQueue::Events::iterator itr = all_events.begin();
itr != all_events.end();
++itr)
{
osgGA::GUIEventAdapter* event = itr->get();
// OSG_NOTICE<<"mouseEventState Xmin = "<<eventState->getXmin()<<" Ymin="<<eventState->getYmin()<<" xMax="<<eventState->getXmax()<<" Ymax="<<eventState->getYmax()<<std::endl;
switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::PUSH):
case(osgGA::GUIEventAdapter::RELEASE):
case(osgGA::GUIEventAdapter::DOUBLECLICK):
case(osgGA::GUIEventAdapter::MOVE):
case(osgGA::GUIEventAdapter::DRAG):
{
if ((event->getEventType()!=osgGA::GUIEventAdapter::DRAG && event->getEventType()!=osgGA::GUIEventAdapter::RELEASE) ||
!_previousEvent ||
_previousEvent->getGraphicsContext()!=event->getGraphicsContext() ||
_previousEvent->getNumPointerData()<2)
{
generatePointerData(*event);
}
else
{
reprojectPointerData(*_previousEvent, *event);
}
#if 0
// assign topmost PointeData settings as the events X,Y and InputRange
osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1);
event->setX(pd->x);
event->setY(pd->y);
event->setInputRange(pd->xMin, pd->yMin, pd->xMax, pd->yMax);
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
#else
if (event->getMouseYOrientation()!=osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
{
event->setY((event->getYmax()-event->getY())+event->getYmin());
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
}
#endif
_previousEvent = event;
break;
}
default:
if (_previousEvent.valid()) event->copyPointerDataFrom(*_previousEvent);
break;
}
osgGA::PointerData* pd = event->getNumPointerData()>0 ? event->getPointerData(event->getNumPointerData()-1) : 0;
osg::Camera* camera = pd ? dynamic_cast<osg::Camera*>(pd->object.get()) : 0;
osgViewer::View* view = camera ? dynamic_cast<osgViewer::View*>(camera->getView()) : 0;
if (!view)
{
if (_viewWithFocus.valid())
{
// OSG_NOTICE<<"Falling back to using _viewWithFocus"<<std::endl;
view = _viewWithFocus.get();
}
else if (!_views.empty())
{
// OSG_NOTICE<<"Falling back to using first view as one with focus"<<std::endl;
view = _views[0].get();
}
}
// reassign view with focus
if (_viewWithFocus != view) _viewWithFocus = view;
if (view)
{
viewEventsMap[view].push_back( event );
osgGA::GUIEventAdapter* eventState = view->getEventQueue()->getCurrentEventState();
eventState->copyPointerDataFrom(*event);
}
_previousEvent = event;
}
// handle any close windows
for(osgGA::EventQueue::Events::iterator itr = all_events.begin();
itr != all_events.end();
++itr)
{
osgGA::GUIEventAdapter* event = itr->get();
switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
{
bool wasThreading = areThreadsRunning();
if (wasThreading) stopThreading();
if (event->getGraphicsContext())
{
event->getGraphicsContext()->close();
}
if (wasThreading) startThreading();
break;
}
default:
break;
}
}
for(RefViews::iterator vitr = _views.begin();
vitr != _views.end();
@@ -941,12 +1048,12 @@ void CompositeViewer::eventTraversal()
es->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime);
}
// generate frame event
view->getEventQueue()->frame( getFrameStamp()->getReferenceTime() );
view->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime);
}
// OSG_NOTICE<<"Events "<<events.size()<<std::endl;
if ((_keyEventSetsDone!=0) || _quitEventSetsDone)
{
for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
@@ -987,10 +1094,11 @@ void CompositeViewer::eventTraversal()
++veitr)
{
View* view = veitr->first;
_eventVisitor->setActionAdapter(view);
if (view->getSceneData())
if (view && view->getSceneData())
{
_eventVisitor->setActionAdapter(view);
for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
itr != veitr->second.end();
++itr)
@@ -1078,8 +1186,6 @@ void CompositeViewer::eventTraversal()
}
}
if (getViewerStats() && getViewerStats()->collectStats("event"))
{
double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
@@ -1091,7 +1197,6 @@ void CompositeViewer::eventTraversal()
}
}
void CompositeViewer::updateTraversal()
{
if (_done) return;

View File

@@ -251,6 +251,9 @@ void GraphicsWindowCarbon::init()
}
_valid = (_pixelFormat != NULL);
_initialized = true;
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphcisContext();
}
bool GraphicsWindowCarbon::setWindowDecorationImplementation(bool flag)
@@ -452,6 +455,10 @@ bool GraphicsWindowCarbon::realizeImplementation()
_currentVSync = _traits->vsync;
_realized = true;
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphcisContext();
return _realized;
}

View File

@@ -1074,6 +1074,9 @@ void GraphicsWindowCocoa::init()
_updateContext = false;
_valid = _initialized = true;
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphcisContext();
}
@@ -1241,6 +1244,9 @@ bool GraphicsWindowCocoa::realizeImplementation()
// Cocoa's origin is bottom/left:
getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphcisContext();
_valid = _initialized = _realized = true;
return _valid;
}

View File

@@ -727,6 +727,9 @@ void GraphicsWindowIOS::init()
//if -1.0 we use the screens scale factor
_viewContentScaleFactor = -1.0f;
_valid = _initialized = true;
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphcisContext();
}
@@ -889,6 +892,9 @@ bool GraphicsWindowIOS::realizeImplementation()
// IOSs origin is top/left:
getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS);
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphcisContext();
_valid = _initialized = _realized = true;
return _valid;

View File

@@ -1184,6 +1184,9 @@ void GraphicsWindowWin32::init()
_initialized = _ownsWindow ? createWindow() : setWindow(windowHandle);
_valid = _initialized;
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphcisContext();
// 2008/10/03
// Few days ago NVidia released WHQL certified drivers ver 178.13.
@@ -1986,6 +1989,9 @@ bool GraphicsWindowWin32::realizeImplementation()
_realized = true;
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphcisContext();
return true;
}

View File

@@ -841,8 +841,7 @@ void GraphicsWindowX11::init()
}
}
getEventQueue()->syncWindowRectangleWithGraphcisContext();
}
bool GraphicsWindowX11::createWindow()
@@ -995,7 +994,7 @@ bool GraphicsWindowX11::createWindow()
XFlush( _eventDisplay );
XSync( _eventDisplay, 0 );
rescanModifierMapping();
return true;
}
@@ -1056,7 +1055,9 @@ bool GraphicsWindowX11::realizeImplementation()
XMapWindow( _display, _window );
// Window temp = _window;
getEventQueue()->syncWindowRectangleWithGraphcisContext();
// Window temp = _window;
// XSetWMColormapWindows( _display, _window, &temp, 1);
_realized = true;

View File

@@ -1062,7 +1062,7 @@ void View::setUpViewFor3DSphericalDisplay(double radius, double collar, unsigned
camera->setDrawBuffer(buffer);
camera->setReadBuffer(buffer);
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setAllowEventFocus(false);
camera->setAllowEventFocus(true);
camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
//camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
@@ -1956,7 +1956,7 @@ void View::requestContinuousUpdate(bool flag)
void View::requestWarpPointer(float x,float y)
{
OSG_INFO<<"View::requestWarpPointer("<<x<<","<<y<<")"<<std::endl;
float local_x, local_y;
const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
if (camera)
@@ -1991,45 +1991,55 @@ bool View::containsCamera(const osg::Camera* camera) const
return false;
}
const osg::Camera* View::getCameraContainingPosition(float x, float y, float& local_x, float& local_y) const
{
const osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
const osgViewer::GraphicsWindow* gw = dynamic_cast<const osgViewer::GraphicsWindow*>(eventState->getGraphicsContext());
bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
// OSG_NOTICE<<"getCameraContainingPosition("<<x<<", "<<y<<") view_invert_y = "<<view_invert_y<<", Xmin() = "<<eventState->getXmin()<<", Xmax() = "<<eventState->getXmax()<<", Ymin() = "<<eventState->getYmin()<<", Ymax() = "<<eventState->getYmax()<<std::endl;
double epsilon = 0.5;
if (_camera->getGraphicsContext() &&
(!gw || _camera->getGraphicsContext()==gw) &&
_camera->getViewport())
// if master camera has graphics context and eventState context matches then assume coordinates refer
// to master camera
bool masterActive = (_camera->getGraphicsContext()!=0 && _camera->getViewport());
bool eventStateMatchesMaster = (gw!=0) ? _camera->getGraphicsContext()==gw : false;
if (masterActive && eventStateMatchesMaster)
{
// OSG_NOTICE<<"Event state matches master"<<std::endl;
const osg::Viewport* viewport = _camera->getViewport();
double new_x = x;
double new_y = y;
if (!gw)
{
new_x = static_cast<double>(_camera->getGraphicsContext()->getTraits()->width) * (x - eventState->getXmin())/(eventState->getXmax()-eventState->getXmin());
new_y = view_invert_y ?
static_cast<double>(_camera->getGraphicsContext()->getTraits()->height) * (1.0 - (y- eventState->getYmin())/(eventState->getYmax()-eventState->getYmin())) :
static_cast<double>(_camera->getGraphicsContext()->getTraits()->height) * (y - eventState->getYmin())/(eventState->getYmax()-eventState->getYmin());
}
if (viewport &&
new_x >= (viewport->x()-epsilon) && new_y >= (viewport->y()-epsilon) &&
// rescale mouse x,y first to 0 to 1 range
double new_x = (x-eventState->getXmin())/(eventState->getXmax()-eventState->getXmin());
double new_y = (y-eventState->getYmin())/(eventState->getYmax()-eventState->getYmin());
// flip y if required
if (view_invert_y) new_y = 1.0f-new_y;
// rescale mouse x, y to window dimensions so we can check against master Camera's viewport
new_x *= static_cast<double>(_camera->getGraphicsContext()->getTraits()->width);
new_y *= static_cast<double>(_camera->getGraphicsContext()->getTraits()->height);
if (new_x >= (viewport->x()-epsilon) && new_y >= (viewport->y()-epsilon) &&
new_x < (viewport->x()+viewport->width()-1.0+epsilon) && new_y <= (viewport->y()+viewport->height()-1.0+epsilon) )
{
local_x = new_x;
local_y = new_y;
OSG_INFO<<"Returning master camera"<<std::endl;
//OSG_NOTICE<<"Returning master camera"<<std::endl;
return _camera.get();
}
else
{
// OSG_NOTICE<<"master camera viewport not matched."<<std::endl;
}
}
osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
// convert to non dimensional
@@ -2088,77 +2098,67 @@ const osg::Camera* View::getCameraContainingPosition(float x, float y, float& lo
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;
float local_x, local_y;
const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
if (!camera) camera = _camera.get();
OSG_NOTICE<<"computeIntersections("<<x<<", "<<y<<") local_x="<<local_x<<", local_y="<<local_y<<std::endl;
if (camera) return computeIntersections(camera, (camera->getViewport()==0)?osgUtil::Intersector::PROJECTION : osgUtil::Intersector::WINDOW, local_x, local_y, intersections, traversalMask);
else return false;
}
bool View::computeIntersections(float x,float y, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections, osg::Node::NodeMask traversalMask)
{
float local_x, local_y;
const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
OSG_NOTICE<<"computeIntersections("<<x<<", "<<y<<") local_x="<<local_x<<", local_y="<<local_y<<std::endl;
osgUtil::LineSegmentIntersector::CoordinateFrame cf = camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(cf, local_x, local_y);
if (camera) return computeIntersections(camera, (camera->getViewport()==0)?osgUtil::Intersector::PROJECTION : osgUtil::Intersector::WINDOW, local_x, local_y, nodePath, intersections, traversalMask);
else return false;
}
#if 0
OSG_NOTICE<<"View::computeIntersections(x="<<x<<", y="<<y<<", local_x="<<local_x<<", local_y="<<local_y<<") "<<cf<<std::endl;
OSG_NOTICE<<" viewport ("<<camera->getViewport()->x()<<","<<camera->getViewport()->y()<<","<<camera->getViewport()->width()<<","<<camera->getViewport()->height()<<")"<<std::endl;
const osg::GraphicsContext::Traits* traits = camera->getGraphicsContext() ? camera->getGraphicsContext()->getTraits() : 0;
if (traits)
bool View::computeIntersections(const osgGA::GUIEventAdapter& ea, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask)
{
#if 1
if (ea.getNumPointerData()>=1)
{
OSG_NOTICE<<" window ("<<traits->x<<","<<traits->y<<","<<traits->width<<","<<traits->height<<")"<<std::endl;
const osgGA::PointerData* pd = ea.getPointerData(ea.getNumPointerData()-1);
const osg::Camera* camera = dynamic_cast<const osg::Camera*>(pd->object.get());
if (camera)
{
return computeIntersections(camera, osgUtil::Intersector::PROJECTION, pd->getXnormalized(), pd->getYnormalized(), intersections, traversalMask);
}
}
#endif
return computeIntersections(ea.getX(), ea.getY(), intersections, traversalMask);
}
bool View::computeIntersections(const osgGA::GUIEventAdapter& ea, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask)
{
#if 1
if (ea.getNumPointerData()>=1)
{
const osgGA::PointerData* pd = ea.getPointerData(ea.getNumPointerData()-1);
const osg::Camera* camera = dynamic_cast<const osg::Camera*>(pd->object.get());
if (camera)
{
return computeIntersections(camera, osgUtil::Intersector::PROJECTION, pd->getXnormalized(), pd->getYnormalized(), nodePath, intersections, traversalMask);
}
}
#endif
return computeIntersections(ea.getX(), ea.getY(), nodePath, intersections, traversalMask);
}
bool View::computeIntersections(const osg::Camera* camera, osgUtil::Intersector::CoordinateFrame cf, float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections, osg::Node::NodeMask traversalMask)
{
if (!camera) return false;
osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(cf, x, y);
osgUtil::IntersectionVisitor iv(picker.get());
iv.setTraversalMask(traversalMask);
#if 1
const_cast<osg::Camera*>(camera)->accept(iv);
#else
// timing test code paths for comparing KdTree based intersections vs conventional intersections
iv.setUseKdTreeWhenAvailable(true);
iv.setDoDummyTraversal(true);
const_cast<osg::Camera*>(camera)->accept(iv);
osg::Timer_t before = osg::Timer::instance()->tick();
const_cast<osg::Camera*>(camera)->accept(iv);
osg::Timer_t after_dummy = osg::Timer::instance()->tick();
int intersectsBeforeKdTree = picker->getIntersections().size();
iv.setDoDummyTraversal(false);
const_cast<osg::Camera*>(camera)->accept(iv);
osg::Timer_t after_kdTree_2 = osg::Timer::instance()->tick();
int intersectsBeforeConventional = picker->getIntersections().size();
iv.setUseKdTreeWhenAvailable(false);
const_cast<osg::Camera*>(camera)->accept(iv);
osg::Timer_t after = osg::Timer::instance()->tick();
int intersectsAfterConventional = picker->getIntersections().size();
double timeDummy = osg::Timer::instance()->delta_m(before, after_dummy);
double timeKdTree = osg::Timer::instance()->delta_m(after_dummy, after_kdTree_2);
double timeConventional = osg::Timer::instance()->delta_m(after_kdTree_2, after);
OSG_NOTICE<<"Using Dummy "<<timeDummy<<std::endl;
OSG_NOTICE<<" KdTrees "<<timeKdTree
<<"\tNum intersects = "<<intersectsBeforeConventional-intersectsBeforeKdTree<<std::endl;
OSG_NOTICE<<" KdTrees - Traversal "<<timeKdTree-timeDummy<<std::endl;
OSG_NOTICE<<" Conventional "<<timeConventional
<<"\tNum intersects = "<<intersectsAfterConventional-intersectsBeforeConventional<<std::endl;
OSG_NOTICE<<" Conventional - Traversal "<<timeConventional-timeDummy<<std::endl;
OSG_NOTICE<<" Delta "<<timeConventional/timeKdTree<<std::endl;
OSG_NOTICE<<" Delta sans Traversal "<<(timeConventional-timeDummy)/(timeKdTree-timeDummy)<<std::endl;
OSG_NOTICE<<std::endl;
#endif
if (picker->containsIntersections())
{
@@ -2172,13 +2172,9 @@ bool View::computeIntersections(float x,float y, osgUtil::LineSegmentIntersector
}
}
bool View::computeIntersections(float x,float y, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask)
bool View::computeIntersections(const osg::Camera* camera, osgUtil::Intersector::CoordinateFrame cf, float x,float y, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask)
{
if (!_camera.valid() || nodePath.empty()) 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();
if (!camera || nodePath.empty()) return false;
osg::Matrixd matrix;
if (nodePath.size()>1)
@@ -2192,7 +2188,7 @@ bool View::computeIntersections(float x,float y, const osg::NodePath& nodePath,
double zNear = -1.0;
double zFar = 1.0;
if (camera->getViewport())
if (cf==osgUtil::Intersector::WINDOW && camera->getViewport())
{
matrix.postMult(camera->getViewport()->computeWindowMatrix());
zNear = 0.0;
@@ -2202,8 +2198,8 @@ bool View::computeIntersections(float x,float y, const osg::NodePath& nodePath,
osg::Matrixd inverse;
inverse.invert(matrix);
osg::Vec3d startVertex = osg::Vec3d(local_x,local_y,zNear) * inverse;
osg::Vec3d endVertex = osg::Vec3d(local_x,local_y,zFar) * inverse;
osg::Vec3d startVertex = osg::Vec3d(x,y,zNear) * inverse;
osg::Vec3d endVertex = osg::Vec3d(x,y,zFar) * inverse;
osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::MODEL, startVertex, endVertex);
@@ -2223,7 +2219,6 @@ bool View::computeIntersections(float x,float y, const osg::NodePath& nodePath,
}
}
void View::addDevice(osgGA::Device* eventSource)
{
Devices::iterator itr = std::find( _eventSources.begin(), _eventSources.end(), eventSource );

View File

@@ -16,6 +16,8 @@
#include <osg/DeleteHandler>
#include <osg/io_utils>
#include <osg/TextureRectangle>
#include <osg/TextureCubeMap>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
@@ -266,7 +268,6 @@ void Viewer::take(osg::View& rhs)
_startRenderingBarrier = rhs_viewer->_startRenderingBarrier;
_endRenderingDispatchBarrier = rhs_viewer->_endRenderingDispatchBarrier;
_endDynamicDrawBlock = rhs_viewer->_endDynamicDrawBlock;
_cameraWithFocus = rhs_viewer->_cameraWithFocus;
_eventVisitor = rhs_viewer->_eventVisitor;
_updateOperations = rhs_viewer->_updateOperations;
_updateVisitor = rhs_viewer->_updateVisitor;
@@ -279,7 +280,6 @@ void Viewer::take(osg::View& rhs)
rhs_viewer->_startRenderingBarrier = 0;
rhs_viewer->_endRenderingDispatchBarrier = 0;
rhs_viewer->_endDynamicDrawBlock = 0;
rhs_viewer->_cameraWithFocus = 0;
rhs_viewer->_eventVisitor = 0;
rhs_viewer->_updateOperations = 0;
rhs_viewer->_updateVisitor = 0;
@@ -429,8 +429,6 @@ void Viewer::realize()
{
//OSG_INFO<<"Viewer::realize()"<<std::endl;
setCameraWithFocus(0);
Contexts contexts;
getContexts(contexts);
@@ -561,7 +559,7 @@ void Viewer::realize()
}
}
}
#if 0
osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
if (getCamera()->getViewport())
{
@@ -572,6 +570,7 @@ void Viewer::realize()
{
eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
}
#endif
}
@@ -616,6 +615,177 @@ void Viewer::advance(double simulationTime)
}
void Viewer::generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event)
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
if (!gw) return;
// What type of Camera is it?
// 1) Master Camera : do nothin extra
// 2) Slave Camera, Relative RF, Same scene graph as master : transform coords into Master Camera and add to PointerData list
// 3) Slave Camera, Relative RF, Different scene graph from master : do nothing extra?
// 4) Slave Camera, Absolute RF, Same scene graph as master : do nothing extra?
// 5) Slave Camera, Absolute RF, Different scene graph : do nothing extra?
// 6) Slave Camera, Absolute RF, Different scene graph but a distortion correction subgraph depending upon RTT Camera (slave or master)
// : project ray into RTT Camera's clip space, and RTT Camera's is Relative RF and sharing same scene graph as master then transform coords.
// if camera isn't the master it must be a slave and could need reprojecting.
if (camera!=getCamera())
{
float x = event.getX();
float y = event.getY();
bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
if (getCamera()->getViewport())
{
osg::Viewport* viewport = getCamera()->getViewport();
masterCameraVPW *= viewport->computeWindowMatrix();
}
// slave Camera tahnks to sharing the same View
osg::View::Slave* slave = findSlaveForCamera(camera);
if (slave)
{
if (camera->getReferenceFrame()==osg::Camera::RELATIVE_RF && slave->_useMastersSceneData)
{
osg::Viewport* viewport = camera->getViewport();
osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
//OSG_NOTICE<<" pointer event new_coord.x()="<<new_coord.x()<<" new_coord.y()="<<new_coord.y()<<std::endl;
event.addPointerData(new osgGA::PointerData(getCamera(), new_coord.x(), -1.0, 1.0,
new_coord.y(), -1.0, 1.0));
}
else if (!slave->_useMastersSceneData)
{
// Are their any RTT Camera's that this Camera depends upon for textures?
osg::ref_ptr<osgUtil::LineSegmentIntersector> ray = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x,y);
osgUtil::IntersectionVisitor iv(ray.get());
camera->accept(iv);
if (ray->containsIntersections())
{
osg::Vec3 tc;
osg::Texture* texture = ray->getFirstIntersection().getTextureLookUp(tc);
if (texture)
{
// look up Texture in RTT Camera's.
for(unsigned int i=0; i<getNumSlaves();++i)
{
osg::Camera* slave_camera = getSlave(i)._camera;
if (slave_camera)
{
osg::Camera::BufferAttachmentMap::const_iterator ba_itr = slave_camera->getBufferAttachmentMap().find(osg::Camera::COLOR_BUFFER);
if (ba_itr != slave_camera->getBufferAttachmentMap().end())
{
if (ba_itr->second._texture == texture)
{
osg::TextureRectangle* tr = dynamic_cast<osg::TextureRectangle*>(ba_itr->second._texture.get());
osg::TextureCubeMap* tcm = dynamic_cast<osg::TextureCubeMap*>(ba_itr->second._texture.get());
if (tr)
{
event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, static_cast<float>(tr->getTextureWidth()),
tc.y(), 0.0f, static_cast<float>(tr->getTextureHeight())));
}
else if (tcm)
{
OSG_NOTICE<<" Slave has matched texture cubemap"<<ba_itr->second._texture.get()<<", "<<ba_itr->second._face<<std::endl;
}
else
{
event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, 1.0f,
tc.y(), 0.0f, 1.0f));
}
}
}
}
}
}
}
}
}
}
}
void Viewer::generatePointerData(osgGA::GUIEventAdapter& event)
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
if (!gw) return;
float x = event.getX();
float y = event.getY();
bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
y, 0, gw->getTraits()->height));
// new code for populating the PointerData
osgViewer::View* this_view = dynamic_cast<osgViewer::View*>(this);
osg::GraphicsContext::Cameras& cameras = gw->getCameras();
for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
citr != cameras.end();
++citr)
{
osg::Camera* camera = *citr;
if (camera->getView()==this_view &&
camera->getAllowEventFocus() &&
camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
{
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
if (viewport &&
x >= viewport->x() && y >= viewport->y() &&
x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
{
event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
(y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
// if camera isn't the master it must be a slave and could need reprojecting.
if (camera!=getCamera())
{
generateSlavePointerData(camera, event);
}
}
}
}
}
void Viewer::reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event)
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(dest_event.getGraphicsContext());
if (!gw) return;
float x = dest_event.getX();
float y = dest_event.getY();
bool invert_y = dest_event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
dest_event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
y, 0, gw->getTraits()->height));
osg::Camera* camera = (source_event.getNumPointerData()>=2) ? dynamic_cast<osg::Camera*>(source_event.getPointerData(1)->object.get()) : 0;
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
if (!viewport) return;
dest_event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
(y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
// if camera isn't the master it must be a slave and could need reprojecting.
if (camera!=getCamera())
{
generateSlavePointerData(camera, dest_event);
}
}
void Viewer::eventTraversal()
{
if (_done) return;
@@ -637,13 +807,6 @@ void Viewer::eventTraversal()
if (_done) return;
osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
if (getCamera()->getViewport())
{
osg::Viewport* viewport = getCamera()->getViewport();
masterCameraVPW *= viewport->computeWindowMatrix();
}
// get events from user Devices attached to Viewer.
for(Devices::iterator eitr = _eventSources.begin();
@@ -679,111 +842,54 @@ void Viewer::eventTraversal()
{
osgGA::GUIEventAdapter* event = itr->get();
bool pointerEvent = false;
float x = event->getX();
float y = event->getY();
bool invert_y = event->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
event->setGraphicsContext(gw);
switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::PUSH):
case(osgGA::GUIEventAdapter::RELEASE):
case(osgGA::GUIEventAdapter::DOUBLECLICK):
case(osgGA::GUIEventAdapter::DRAG):
case(osgGA::GUIEventAdapter::MOVE):
case(osgGA::GUIEventAdapter::DRAG):
{
pointerEvent = true;
if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG || !getCameraWithFocus())
if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG ||
eventState->getGraphicsContext()!=event->getGraphicsContext() ||
eventState->getNumPointerData()<2)
{
osg::GraphicsContext::Cameras& cameras = gw->getCameras();
for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
citr != cameras.end();
++citr)
{
osg::Camera* camera = *citr;
if (camera->getView()==this &&
camera->getAllowEventFocus() &&
camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
{
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
if (viewport &&
x >= viewport->x() && y >= viewport->y() &&
x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
{
// OSG_NOTICE<<"setCamera with focus "<<camera->getName()<<" x="<<x<<" y="<<y<<std::endl;
setCameraWithFocus(camera);
}
}
}
generatePointerData(*event);
}
else
{
reprojectPointerData(*eventState, *event);
}
#if 0
// assign topmost PointeData settings as the events X,Y and InputRange
osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1);
event->setX(pd->x);
event->setY(pd->y);
event->setInputRange(pd->xMin, pd->yMin, pd->xMax, pd->yMax);
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
#else
if (event->getMouseYOrientation()!=osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
{
event->setY((event->getYmax()-event->getY())+event->getYmin());
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
}
#endif
eventState->copyPointerDataFrom(*event);
break;
}
default:
event->copyPointerDataFrom(*eventState);
break;
}
if (pointerEvent)
{
if (getCameraWithFocus())
{
if (getCameraWithFocus()!=getCamera())
{
osg::Viewport* viewport = getCameraWithFocus()->getViewport();
osg::Matrix localCameraVPW = getCameraWithFocus()->getViewMatrix() * getCameraWithFocus()->getProjectionMatrix();
if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
x = new_coord.x();
y = new_coord.y();
}
// OSG_NOTICE<<"pointer event new_coord.x()="<<new_coord.x()<<" new_coord.y()="<<new_coord.y()<<std::endl;
event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
event->setX(x);
event->setY(y);
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
}
else
{
x = eventState->getXmin() + (x/double(gw->getTraits()->width))*(eventState->getXmax() - eventState->getXmin());
y = eventState->getYmin() + (y/double(gw->getTraits()->height))*(eventState->getYmax() - eventState->getYmin());
// OSG_NOTICE<<"new x = "<<x<<" new y = "<<y<<std::endl;
event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
event->setX(x);
event->setY(y);
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
}
// pass along the new pointer events details to the eventState of the viewer
eventState->setX(x);
eventState->setY(y);
eventState->setButtonMask(event->getButtonMask());
eventState->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
}
else
{
event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
event->setX(eventState->getX());
event->setY(eventState->getY());
event->setButtonMask(eventState->getButtonMask());
event->setMouseYOrientation(eventState->getMouseYOrientation());
}
//OSG_NOTICE<<" mouse x = "<<event->getX()<<" y="<<event->getY()<<std::endl;
// OSG_NOTICE<<" mouse Xmin = "<<event->getXmin()<<" Ymin="<<event->getYmin()<<" xMax="<<event->getXmax()<<" Ymax="<<event->getYmax()<<std::endl;
events.push_back(event);
}
for(itr = gw_events.begin();
itr != gw_events.end();
++itr)
@@ -808,22 +914,9 @@ void Viewer::eventTraversal()
}
}
events.insert(events.end(), gw_events.begin(), gw_events.end());
}
}
// pass on the coorindates of the main camera to make sure the frame event is scaled appropriately.
if (getCamera()->getViewport())
{
osg::Viewport* viewport = getCamera()->getViewport();
eventState->setInputRange( viewport->x(), viewport->y(), viewport->x() + viewport->width(), viewport->y() + viewport->height());
}
else
{
eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
}
// create a frame event for the new frame.
_eventQueue->frame( getFrameStamp()->getReferenceTime() );
@@ -831,53 +924,6 @@ void Viewer::eventTraversal()
_eventQueue->takeEvents(events, cutOffTime);
#if 0
// OSG_NOTICE<<"Events "<<events.size()<<std::endl;
for(osgGA::EventQueue::Events::iterator itr = events.begin();
itr != events.end();
++itr)
{
osgGA::GUIEventAdapter* event = itr->get();
switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::PUSH):
OSG_NOTICE<<" PUSH "<<event->getButton()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
break;
case(osgGA::GUIEventAdapter::RELEASE):
OSG_NOTICE<<" RELEASE "<<event->getButton()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
break;
case(osgGA::GUIEventAdapter::DRAG):
OSG_NOTICE<<" DRAG "<<event->getButtonMask()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
break;
case(osgGA::GUIEventAdapter::MOVE):
OSG_NOTICE<<" MOVE "<<event->getButtonMask()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
break;
case(osgGA::GUIEventAdapter::SCROLL):
OSG_NOTICE<<" SCROLL "<<event->getScrollingMotion()<<std::endl;
break;
case(osgGA::GUIEventAdapter::KEYDOWN):
OSG_NOTICE<<" KEYDOWN '"<<(char)event->getKey()<<"'"<<std::endl;
break;
case(osgGA::GUIEventAdapter::KEYUP):
OSG_NOTICE<<" KEYUP '"<<(char)event->getKey()<<"'"<<std::endl;
break;
case(osgGA::GUIEventAdapter::RESIZE):
OSG_NOTICE<<" RESIZE "<<event->getWindowX()<<"/"<<event->getWindowY()<<" x "<<event->getWindowWidth()<<"/"<<event->getWindowHeight() << std::endl;
break;
case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
OSG_NOTICE<<" QUIT_APPLICATION " << std::endl;
break;
case(osgGA::GUIEventAdapter::FRAME):
// OSG_NOTICE<<" FRAME "<<std::endl;
break;
default:
// OSG_NOTICE<<" Event not handled"<<std::endl;
break;
}
}
#endif
// OSG_NOTICE<<"Events "<<events.size()<<std::endl;
if ((_keyEventSetsDone!=0) || _quitEventSetsDone)

View File

@@ -716,90 +716,13 @@ InteractiveImageHandler::InteractiveImageHandler(osg::Image* image, osg::Texture
}
}
bool InteractiveImageHandler::computeIntersections(osgViewer::View* view, float x,float y, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask) const
{
float local_x, local_y = 0.0;
const osg::Camera* camera;
if (_fullscreen)
{
if (!_camera) return false;
camera = _camera.get();
local_x = x;
local_y = y;
}
else
{
if (!view->getCamera() || nodePath.empty()) return false;
camera = view->getCameraContainingPosition(x, y, local_x, local_y);
if (!camera) camera = view->getCamera();
}
osg::ref_ptr< osgUtil::LineSegmentIntersector > picker;
if (_fullscreen)
{
picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, local_x, local_y);
}
else
{
osg::Matrixd matrix;
if (nodePath.size()>1)
{
osg::NodePath prunedNodePath(nodePath.begin(),nodePath.end()-1);
matrix = osg::computeLocalToWorld(prunedNodePath);
}
matrix.postMult(camera->getViewMatrix());
matrix.postMult(camera->getProjectionMatrix());
double zNear = -1.0;
double zFar = 1.0;
if (camera->getViewport())
{
matrix.postMult(camera->getViewport()->computeWindowMatrix());
zNear = 0.0;
zFar = 1.0;
}
osg::Matrixd inverse;
inverse.invert(matrix);
osg::Vec3d startVertex = osg::Vec3d(local_x,local_y,zNear) * inverse;
osg::Vec3d endVertex = osg::Vec3d(local_x,local_y,zFar) * inverse;
picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::MODEL, startVertex, endVertex);
}
osgUtil::IntersectionVisitor iv(picker.get());
iv.setTraversalMask(traversalMask);
if (_fullscreen)
{
const_cast<osg::Camera*>(camera)->accept(iv);
}
else
{
nodePath.back()->accept(iv);
}
if (picker->containsIntersections())
{
intersections = picker->getIntersections();
return true;
}
else
{
intersections.clear();
return false;
}
}
bool InteractiveImageHandler::mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const
{
if (!view) return false;
osgUtil::LineSegmentIntersector::Intersections intersections;
bool foundIntersection = view==0 ? false :
(nv==0 ? view->computeIntersections(ea.getX(), ea.getY(), intersections) :
//view->computeIntersections(ea.getX(), ea.getY(), nv->getNodePath(), intersections));
computeIntersections(view, ea.getX(), ea.getY(), nv->getNodePath(), intersections));
bool foundIntersection = (nv==0) ? view->computeIntersections(ea, intersections) :
view->computeIntersections(ea, nv->getNodePath(), intersections);
if (foundIntersection)
{