Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Introduced new scheme for handling mouse events with osgViewer. The n…

…ew scheme enables robust event handling even when using distortion correction render to texture Cameras.
  • Loading branch information...
commit 6e69fe0bce7220747dbec813190622282cc57d12 1 parent bd81d96
Robert OSFIELD authored
Showing with 1,100 additions and 682 deletions.
  1. +4 −5 examples/osgcompositeviewer/osgcompositeviewer.cpp
  2. +160 −41 examples/osgkeystone/osgkeystone.cpp
  3. +7 −7 examples/osglauncher/osglauncher.cpp
  4. +2 −2 examples/osgmovie/osgmovie.cpp
  5. +1 −1  examples/osgmultiplemovies/osgmultiplemovies.cpp
  6. +1 −1  examples/osgoccluder/osgoccluder.cpp
  7. +1 −10 examples/osgoscdevice/osgoscdevice.cpp
  8. +2 −2 examples/osgparticleeffects/osgparticleeffects.cpp
  9. +2 −12 examples/osgpick/osgpick.cpp
  10. +1 −1  examples/osgwidgetbox/osgwidgetbox.cpp
  11. +7 −0 include/osgGA/EventQueue
  12. +88 −1 include/osgGA/GUIEventAdapter
  13. +5 −0 include/osgUtil/LineSegmentIntersector
  14. +6 −0 include/osgViewer/CompositeViewer
  15. +17 −8 include/osgViewer/View
  16. +3 −6 include/osgViewer/Viewer
  17. +0 −1  include/osgViewer/ViewerEventHandlers
  18. +7 −0 src/osgGA/EventQueue.cpp
  19. +11 −0 src/osgGA/GUIEventAdapter.cpp
  20. +1 −1  src/osgManipulator/Dragger.cpp
  21. +2 −2 src/osgPlugins/p3d/ReaderWriterP3D.cpp
  22. +1 −1  src/osgPresentation/PickEventHandler.cpp
  23. +6 −0 src/osgQt/GraphicsWindowQt.cpp
  24. +109 −0 src/osgUtil/LineSegmentIntersector.cpp
  25. +303 −198 src/osgViewer/CompositeViewer.cpp
  26. +7 −0 src/osgViewer/GraphicsWindowCarbon.cpp
  27. +6 −0 src/osgViewer/GraphicsWindowCocoa.mm
  28. +6 −0 src/osgViewer/GraphicsWindowIOS.mm
  29. +6 −0 src/osgViewer/GraphicsWindowWin32.cpp
  30. +5 −4 src/osgViewer/GraphicsWindowX11.cpp
  31. +86 −91 src/osgViewer/View.cpp
  32. +205 −159 src/osgViewer/Viewer.cpp
  33. +4 −81 src/osgViewer/ViewerEventHandlers.cpp
  34. +8 −1 src/osgWidget/ViewerEventHandlers.cpp
  35. +7 −1 src/osgWidget/Widget.cpp
  36. +13 −45 src/osgWidget/WindowManager.cpp
View
9 examples/osgcompositeviewer/osgcompositeviewer.cpp
@@ -54,7 +54,7 @@ class PickHandler : public osgGA::GUIEventHandler {
~PickHandler() {}
- bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
+ bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
if (!view) return false;
@@ -71,7 +71,7 @@ class PickHandler : public osgGA::GUIEventHandler {
{
if (_mx==ea.getX() && _my==ea.getY())
{
- pick(view, ea.getX(), ea.getY());
+ pick(view, ea);
}
break;
}
@@ -81,13 +81,13 @@ class PickHandler : public osgGA::GUIEventHandler {
return false;
}
- void pick(osgViewer::View* view, float x, float y)
+ void pick(osgViewer::View* view, const osgGA::GUIEventAdapter& event)
{
osg::Node* node = 0;
osg::Group* parent = 0;
osgUtil::LineSegmentIntersector::Intersections intersections;
- if (view->computeIntersections(x, y, intersections))
+ if (view->computeIntersections(event, intersections))
{
osgUtil::LineSegmentIntersector::Intersection intersection = *intersections.begin();
osg::NodePath& nodePath = intersection.nodePath;
@@ -98,7 +98,6 @@ class PickHandler : public osgGA::GUIEventHandler {
// now we try to decorate the hit node by the osgFX::Scribe to show that its been "picked"
if (parent && node)
{
-
osgFX::Scribe* parentAsScribe = dynamic_cast<osgFX::Scribe*>(parent);
if (!parentAsScribe)
{
View
201 examples/osgkeystone/osgkeystone.cpp
@@ -35,6 +35,7 @@ class Keystone : public osg::Referenced
public:
Keystone():
keystoneEditingEnabled(false),
+ gridColour(1.0f,1.0f,1.0f,1.0f),
bottom_left(-1.0,-1.0),
bottom_right(1.0,-1.0),
top_left(-1.0,1.0),
@@ -52,6 +53,7 @@ class Keystone : public osg::Referenced
{
if (&rhs==this) return *this;
keystoneEditingEnabled = rhs.keystoneEditingEnabled;
+ gridColour = rhs.gridColour;
bottom_left = rhs.bottom_left;
bottom_right = rhs.bottom_right;
top_left = rhs.top_left;
@@ -61,6 +63,8 @@ class Keystone : public osg::Referenced
bool keystoneEditingEnabled;
+ osg::Vec4 gridColour;
+
osg::Vec2d bottom_left;
osg::Vec2d bottom_right;
osg::Vec2d top_left;
@@ -97,7 +101,7 @@ class KeystoneHandler : public osgGA::GUIEventHandler
~KeystoneHandler() {}
- bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);
+ bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor* nv);
void setKeystoneEditingEnabled(bool enabled) { if (_currentControlPoints.valid()) _currentControlPoints->keystoneEditingEnabled = enabled; }
bool getKeystoneEditingEnabled() const { return _currentControlPoints.valid() ? _currentControlPoints->keystoneEditingEnabled : false; }
@@ -228,8 +232,31 @@ osg::Vec2d KeystoneHandler::incrementScale(const osgGA::GUIEventAdapter& ea) con
return _defaultIncrement;
}
-bool KeystoneHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
+bool KeystoneHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor* nv)
{
+ osg::Camera* camera = dynamic_cast<osg::Camera*>(obj);
+ osg::Viewport* viewport = camera ? camera->getViewport() : 0;
+
+ if (!viewport) return false;
+
+ bool haveCameraMatch = false;
+ float x = ea.getXnormalized();
+ float y = ea.getYnormalized();
+ for(unsigned int i=0; i<ea.getNumPointerData(); ++i)
+ {
+ const osgGA::PointerData* pd = ea.getPointerData(i);
+ if (pd->object==obj)
+ {
+ haveCameraMatch = true;
+ x = pd->getXnormalized();
+ y = pd->getYnormalized();
+ break;
+ }
+ }
+
+
+ if (!haveCameraMatch) return false;
+
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::PUSH):
@@ -241,7 +268,7 @@ bool KeystoneHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionA
{
_selectedRegion = computeRegion(ea);
(*_startControlPoints) = (*_currentControlPoints);
- _startPosition.set(ea.getXnormalized(),ea.getYnormalized());
+ _startPosition.set(x,y);
}
else
{
@@ -257,7 +284,7 @@ bool KeystoneHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionA
if (_selectedRegion!=NONE_SELECTED)
{
(*_currentControlPoints) = (*_startControlPoints);
- osg::Vec2d currentPosition(ea.getXnormalized(), ea.getYnormalized());
+ osg::Vec2d currentPosition(x, y);
osg::Vec2d delta(currentPosition-_startPosition);
osg::Vec2d scale = incrementScale(ea);
move(_selectedRegion, osg::Vec2d(delta.x()*scale.x(), delta.y()*scale.y()) );
@@ -306,19 +333,19 @@ bool KeystoneHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionA
}
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_7 || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Home)
{
- _currentControlPoints->top_left.set(ea.getXnormalized(), ea.getYnormalized());
+ _currentControlPoints->top_left.set(x, y);
}
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_9 || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Up)
{
- _currentControlPoints->top_right.set(ea.getXnormalized(), ea.getYnormalized());
+ _currentControlPoints->top_right.set(x, y);
}
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_3 || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Page_Down)
{
- _currentControlPoints->bottom_right.set(ea.getXnormalized(), ea.getYnormalized());
+ _currentControlPoints->bottom_right.set(x, y);
}
else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_1 || ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_End)
{
- _currentControlPoints->bottom_left.set(ea.getXnormalized(), ea.getYnormalized());
+ _currentControlPoints->bottom_left.set(x, y);
}
}
else if (ea.getUnmodifiedKey()=='g' && (ea.getModKeyMask()==osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL || ea.getModKeyMask()==osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL))
@@ -471,7 +498,7 @@ osg::Node* createGrid(Keystone* keystone, const osg::Vec4& colour)
geometry->setCullCallback(new KeystoneCullCallback(keystone));
osg::ref_ptr<osg::Vec4Array> colours = new osg::Vec4Array;
- colours->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
+ colours->push_back(keystone->gridColour);
geometry->setColorArray(colours.get());
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
@@ -579,18 +606,14 @@ osg::Texture* createKestoneDistortionTexture(int width, int height)
osg::Camera* assignKeystoneRenderToTextureCamera(osgViewer::View* view, osg::GraphicsContext* gc, int width, int height, osg::Texture* texture)
{
- osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
- GLenum buffer = GL_FRONT;
-
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setName("Render to texture camera");
camera->setGraphicsContext(gc);
camera->setViewport(new osg::Viewport(0,0,width, height));
- camera->setDrawBuffer(buffer);
- camera->setReadBuffer(buffer);
+ camera->setDrawBuffer(GL_FRONT);
+ camera->setReadBuffer(GL_FRONT);
camera->setAllowEventFocus(false);
- // tell the camera to use OpenGL frame buffer object where supported.
- camera->setRenderTargetImplementation(renderTargetImplementation);
+ camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
// attach the texture and use it as the color buffer.
camera->attach(osg::Camera::COLOR_BUFFER, texture);
@@ -628,7 +651,6 @@ osg::Camera* assignKeystoneDistortionCamera(osgViewer::View* view, osg::DisplayS
camera->setDrawBuffer(buffer);
camera->setReadBuffer(buffer);
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
- camera->setAllowEventFocus(false);
camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
//camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
@@ -822,6 +844,9 @@ void setUpViewForStereo(osgViewer::View* view, osg::DisplaySettings* ds)
ds->setUseSceneViewForStereoHint(false);
+
+ osg::ref_ptr<Keystone> keystone = new Keystone;
+
// set up view's main camera
{
@@ -910,48 +935,142 @@ void setUpViewForStereo(osgViewer::View* view, osg::DisplaySettings* ds)
case(osg::DisplaySettings::ANAGLYPHIC):
{
// left Camera red
- {
- osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0);
- camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
- camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(true, false, false, true));
- camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0);
- }
+ osg::ref_ptr<osg::Camera> left_camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0);
+ left_camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+ left_camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(true, false, false, true));
+ left_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0);
// right Camera cyan
+ osg::ref_ptr<osg::Camera> right_camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0);
+ right_camera->setClearMask(GL_DEPTH_BUFFER_BIT);
+ right_camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(false, true, true, true));
+ right_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1);
+
+ if (keystone.valid())
{
- osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0);
- camera->setClearMask(GL_DEPTH_BUFFER_BIT);
- camera->getOrCreateStateSet()->setAttribute(new osg::ColorMask(false, true, true, true));
- camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1);
- }
+ // for keystone:
+ // left camera to render to texture using red colour mask
+ // right camera to render to same texture using cyan colour mask
+ // keystone camera to render to whole screen without colour masks
+ // one keystone and editing for the one window
- // for keystone:
- // left camera to render to texture using red colour mask
- // right camera to render to same texture using cyan colour mask
- // keystone camera to render to whole screen without colour masks
- // one keystone and editing for the one window
+ // create distortion texture
+ osg::ref_ptr<osg::Texture> texture = createKestoneDistortionTexture(traits->width, traits->height);
+
+ // convert to RTT Camera
+ left_camera->setDrawBuffer(GL_FRONT);
+ left_camera->setReadBuffer(GL_FRONT);
+ left_camera->setAllowEventFocus(false);
+ left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
+
+ // attach the texture and use it as the color buffer.
+ left_camera->attach(osg::Camera::COLOR_BUFFER, texture.get());
+
+
+ // convert to RTT Camera
+ right_camera->setDrawBuffer(GL_FRONT);
+ right_camera->setReadBuffer(GL_FRONT);
+ right_camera->setAllowEventFocus(false);
+ right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
+
+ // attach the texture and use it as the color buffer.
+ right_camera->attach(osg::Camera::COLOR_BUFFER, texture.get());
+
+
+ // create Keystone distortion camera
+ osg::ref_ptr<osg::Camera> camera = assignKeystoneDistortionCamera(view, ds, gc.get(),
+ 0, 0, traits->width, traits->height,
+ traits->doubleBuffer ? GL_BACK : GL_FRONT,
+ texture, keystone.get());
+
+ camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2);
+
+ // attach Keystone editing event handler.
+ camera->addEventCallback(new KeystoneHandler(keystone.get()));
+ }
break;
}
case(osg::DisplaySettings::HORIZONTAL_SPLIT):
{
// left viewport Camera
- assignStereoCamera(view, ds, gc,
+ osg::ref_ptr<osg::Camera> left_camera = assignStereoCamera(view, ds, gc,
0, 0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT,
(ds->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_LEFT_VIEWPORT) ? -1.0 : 1.0);
// right viewport Camera
- assignStereoCamera(view, ds, gc,
+ osg::ref_ptr<osg::Camera> right_camera = assignStereoCamera(view, ds, gc,
traits->width/2,0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT,
(ds->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_RIGHT_VIEWPORT) ? -1.0 : 1.0);
- // for keystone:
- // left camera to render to left texture using whole viewport of left texture
- // right camera to render to right texture using whole viewport of right texture
- // left keystone camera to render to left viewport/window
- // right keystone camera to render to right viewport/window
- // two keystone, one for each of the left and right viewports/windows
+ if (keystone.valid())
+ {
+ // for keystone:
+ // left camera to render to left texture using whole viewport of left texture
+ // right camera to render to right texture using whole viewport of right texture
+ // left keystone camera to render to left viewport/window
+ // right keystone camera to render to right viewport/window
+ // two keystone, one for each of the left and right viewports/windows
+
+ // create distortion texture
+ osg::ref_ptr<osg::Texture> left_texture = createKestoneDistortionTexture(traits->width/2, traits->height);
+
+ // convert to RTT Camera
+ left_camera->setViewport(0, 0, traits->width/2, traits->height);
+ left_camera->setDrawBuffer(GL_FRONT);
+ left_camera->setReadBuffer(GL_FRONT);
+ left_camera->setAllowEventFocus(true);
+ left_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
+
+ // attach the texture and use it as the color buffer.
+ left_camera->attach(osg::Camera::COLOR_BUFFER, left_texture.get());
+
+
+ // create distortion texture
+ osg::ref_ptr<osg::Texture> right_texture = createKestoneDistortionTexture(traits->width/2, traits->height);
+
+ // convert to RTT Camera
+ right_camera->setViewport(0, 0, traits->width/2, traits->height);
+ right_camera->setDrawBuffer(GL_FRONT);
+ right_camera->setReadBuffer(GL_FRONT);
+ right_camera->setAllowEventFocus(true);
+ right_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
+
+ // attach the texture and use it as the color buffer.
+ right_camera->attach(osg::Camera::COLOR_BUFFER, right_texture.get());
+
+
+ // create Keystone left distortion camera
+ keystone->gridColour.set(1.0f,0.0f,0.0,1.0);
+ osg::ref_ptr<osg::Camera> left_keystone_camera = assignKeystoneDistortionCamera(view, ds, gc.get(),
+ 0, 0, traits->width/2, traits->height,
+ traits->doubleBuffer ? GL_BACK : GL_FRONT,
+ left_texture, keystone.get());
+
+ left_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 2);
+
+ // attach Keystone editing event handler.
+ left_keystone_camera->addEventCallback(new KeystoneHandler(keystone.get()));
+
+ osg::ref_ptr<Keystone> right_keystone = new Keystone;
+ right_keystone->gridColour.set(0.0f,1.0f,0.0,1.0);
+
+ // create Keystone right distortion camera
+ osg::ref_ptr<osg::Camera> right_keystone_camera = assignKeystoneDistortionCamera(view, ds, gc.get(),
+ traits->width/2, 0, traits->width/2, traits->height,
+ traits->doubleBuffer ? GL_BACK : GL_FRONT,
+ right_texture, right_keystone.get());
+
+ right_keystone_camera->setRenderOrder(osg::Camera::NESTED_RENDER, 3);
+
+ // attach Keystone editing event handler.
+ right_keystone_camera->addEventCallback(new KeystoneHandler(right_keystone.get()));
+
+ view->getCamera()->setAllowEventFocus(false);
+
+ }
+
break;
}
case(osg::DisplaySettings::VERTICAL_SPLIT):
View
14 examples/osglauncher/osglauncher.cpp
@@ -63,7 +63,7 @@ class PickHandler : public osgGA::GUIEventHandler {
bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
- std::string pick(float x, float y);
+ std::string pick(const osgGA::GUIEventAdapter& event);
void highlight(const std::string& name)
{
@@ -83,15 +83,15 @@ bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapte
case(osgGA::GUIEventAdapter::FRAME):
case(osgGA::GUIEventAdapter::MOVE):
{
- //osg::notify(osg::NOTICE)<<"MOVE "<<ea.getX()<<ea.getY()<<std::endl;
- std::string picked_name = pick(ea.getX(),ea.getY());
+ // osg::notify(osg::NOTICE)<<"MOVE "<<ea.getX()<<", "<<ea.getY()<<std::endl;
+ std::string picked_name = pick(ea);
highlight(picked_name);
return false;
}
case(osgGA::GUIEventAdapter::PUSH):
{
- //osg::notify(osg::NOTICE)<<"PUSH "<<ea.getX()<<ea.getY()<<std::endl;
- std::string picked_name = pick(ea.getX(),ea.getY());
+ // osg::notify(osg::NOTICE)<<"PUSH "<<ea.getX()<<", "<<ea.getY()<<std::endl;
+ std::string picked_name = pick(ea);
if (!picked_name.empty())
{
runApp(picked_name);
@@ -108,10 +108,10 @@ bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapte
}
-std::string PickHandler::pick(float x, float y)
+std::string PickHandler::pick(const osgGA::GUIEventAdapter& event)
{
osgUtil::LineSegmentIntersector::Intersections intersections;
- if (_viewer->computeIntersections(x, y, intersections))
+ if (_viewer->computeIntersections(event, intersections))
{
for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
hitr != intersections.end();
View
4 examples/osgmovie/osgmovie.cpp
@@ -148,8 +148,8 @@ bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction
osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
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));
+ (nv==0 ? view->computeIntersections(ea, intersections) :
+ view->computeIntersections(ea, nv->getNodePath(), intersections));
if (foundIntersection)
{
View
2  examples/osgmultiplemovies/osgmultiplemovies.cpp
@@ -164,7 +164,7 @@ bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction
osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
osgUtil::LineSegmentIntersector::Intersections intersections;
- bool foundIntersection = view==0 ? false : view->computeIntersections(ea.getX(), ea.getY(), intersections);
+ bool foundIntersection = view==0 ? false : view->computeIntersections(ea, intersections);
if (foundIntersection)
{
View
2  examples/osgoccluder/osgoccluder.cpp
@@ -72,7 +72,7 @@ bool OccluderEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAct
{
osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
osgUtil::LineSegmentIntersector::Intersections intersections;
- if (view && view->computeIntersections(ea.getX(), ea.getY(), intersections))
+ if (view && view->computeIntersections(ea, intersections))
{
const osgUtil::LineSegmentIntersector::Intersection& hit = *(intersections.begin());
if (hit.matrix.valid()) addPoint(hit.localIntersectionPoint * (*hit.matrix));
View
11 examples/osgoscdevice/osgoscdevice.cpp
@@ -122,17 +122,8 @@ void PickHandler::pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea)
std::string gdlist="";
float x = ea.getX();
float y = ea.getY();
-#if 0
- osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y);
- osgUtil::IntersectionVisitor iv(picker.get());
- view->getCamera()->accept(iv);
- if (picker->containsIntersections())
+ if (view->computeIntersections(ea, intersections))
{
- intersections = picker->getIntersections();
-#else
- if (view->computeIntersections(x,y,intersections))
- {
-#endif
for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
hitr != intersections.end();
++hitr)
View
4 examples/osgparticleeffects/osgparticleeffects.cpp
@@ -268,9 +268,9 @@ class PickHandler : public osgGA::GUIEventHandler {
{
osg::Group* root = dynamic_cast<osg::Group*>(viewer->getSceneData());
if (!root) return;
-
+
osgUtil::LineSegmentIntersector::Intersections intersections;
- if (viewer->computeIntersections(ea.getX(),ea.getY(),intersections))
+ if (viewer->computeIntersections(ea,intersections))
{
const osgUtil::LineSegmentIntersector::Intersection& hit = *intersections.begin();
View
14 examples/osgpick/osgpick.cpp
@@ -106,19 +106,9 @@ void PickHandler::pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea)
osgUtil::LineSegmentIntersector::Intersections intersections;
std::string gdlist="";
- float x = ea.getX();
- float y = ea.getY();
-#if 0
- osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y);
- osgUtil::IntersectionVisitor iv(picker.get());
- view->getCamera()->accept(iv);
- if (picker->containsIntersections())
- {
- intersections = picker->getIntersections();
-#else
- if (view->computeIntersections(x,y,intersections))
+
+ if (view->computeIntersections(ea,intersections))
{
-#endif
for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
hitr != intersections.end();
++hitr)
View
2  examples/osgwidgetbox/osgwidgetbox.cpp
@@ -38,6 +38,7 @@ struct ColorWidget: public osgWidget::Widget {
}
bool mouseOver(double x, double y, const osgWidget::WindowManager*) {
+
osgWidget::Color c = getImageColorAtPointerXY(x, y);
if(c.a() < 0.001f) {
@@ -45,7 +46,6 @@ struct ColorWidget: public osgWidget::Widget {
return false;
}
-
return true;
}
View
7 include/osgGA/EventQueue
@@ -64,6 +64,13 @@ class OSGGA_EXPORT EventQueue : public osg::Referenced
/** Set the graphics context associated with this event queue.*/
void setGraphicsContext(osg::GraphicsContext* context) { getCurrentEventState()->setGraphicsContext(context); }
+
+ osg::GraphicsContext* getGraphicsContext() { return getCurrentEventState()->getGraphicsContext(); }
+
+ const osg::GraphicsContext* getGraphicsContext() const { return getCurrentEventState()->getGraphicsContext(); }
+
+ /** Read the window record dimensions from the graphics context. */
+ void syncWindowRectangleWithGraphcisContext();
/** Set the mouse input range.*/
View
89 include/osgGA/GUIEventAdapter
@@ -21,7 +21,59 @@
namespace osgGA{
+struct PointerData : public osg::Referenced
+{
+ PointerData():
+ object(0),
+ x(0.0f),
+ xMin(-1.0f),
+ xMax(1.0f),
+ y(0.0f),
+ yMin(-1.0f),
+ yMax(1.0f) {}
+
+ PointerData(osg::Object* obj, float in_x, float in_xMin, float in_xMax, float in_y, float in_yMin, float in_yMax):
+ object(obj),
+ x(in_x),
+ xMin(in_xMin),
+ xMax(in_xMax),
+ y(in_y),
+ yMin(in_yMin),
+ yMax(in_yMax) {}
+
+ PointerData(const PointerData& pd):
+ object(pd.object),
+ x(pd.x),
+ xMin(pd.xMin),
+ xMax(pd.xMax),
+ y(pd.y),
+ yMin(pd.yMin),
+ yMax(pd.yMax) {}
+
+ PointerData& operator = (const PointerData& pd)
+ {
+ if (&pd==this) return *this;
+
+ object = pd.object;
+ x = pd.x;
+ xMin = pd.xMin;
+ xMax = pd.xMax;
+ y = pd.y;
+ yMin = pd.yMin;
+ yMax = pd.yMax;
+
+ return *this;
+ }
+
+ osg::observer_ptr<osg::Object> object;
+ float x, xMin, xMax;
+ float y, yMin, yMax;
+
+ float getXnormalized() const { return (x-xMin)/(xMax-xMin)*2.0f-1.0f; }
+ float getYnormalized() const { return (y-yMin)/(yMax-yMin)*2.0f-1.0f; }
+};
+
/** Event class for storing Keyboard, mouse and window events.
*/
class OSGGA_EXPORT GUIEventAdapter : public osg::Object
@@ -425,6 +477,7 @@ public:
void setGraphicsContext(osg::GraphicsContext* context) { _context = context; }
+ osg::GraphicsContext* getGraphicsContext() { return _context.get(); }
const osg::GraphicsContext* getGraphicsContext() const { return _context.get(); }
@@ -514,6 +567,21 @@ public:
/** get current mouse y position.*/
float getY() const { return _my; }
+#if 1
+ inline float getXnormalized() const
+ {
+ return _pointerDataList.size()>=1 ?
+ _pointerDataList[_pointerDataList.size()-1]->getXnormalized():
+ 2.0f*(getX()-getXmin())/(getXmax()-getXmin())-1.0f;
+ }
+
+ inline float getYnormalized() const
+ {
+ if (_pointerDataList.size()>=1) return _pointerDataList[_pointerDataList.size()-1]->getYnormalized();
+ if (_mouseYOrientation==Y_INCREASING_UPWARDS) return 2.0f*(getY()-getYmin())/(getYmax()-getYmin())-1.0f;
+ else return -(2.0f*(getY()-getYmin())/(getYmax()-getYmin())-1.0f);
+ }
+#else
/**
* return the current mouse x value normalized to the range of -1 to 1.
* -1 would be the left hand side of the window.
@@ -533,7 +601,7 @@ public:
if (_mouseYOrientation==Y_INCREASING_UPWARDS) return 2.0f*(getY()-getYmin())/(getYmax()-getYmin())-1.0f;
else return -(2.0f*(getY()-getYmin())/(getYmax()-getYmin())-1.0f);
}
-
+#endif
/// set mouse-Y orientation (mouse-Y increases upwards or downwards).
void setMouseYOrientation(MouseYOrientation myo) { _mouseYOrientation = myo; }
@@ -616,6 +684,22 @@ public:
TouchData* getTouchData() const { return _touchData.get(); }
bool isMultiTouchEvent() const { return (_touchData.valid()); }
+
+ typedef std::vector< osg::ref_ptr<PointerData> > PointerDataList;
+ void setPointerDataList(const PointerDataList& pdl) { _pointerDataList = pdl; }
+ PointerDataList& getPointerDataList() { return _pointerDataList; }
+ const PointerDataList& getPointerDataList() const { return _pointerDataList; }
+
+ unsigned int getNumPointerData() const { return _pointerDataList.size(); }
+ PointerData* getPointerData(unsigned int i) { return _pointerDataList[i].get(); }
+ const PointerData* getPointerData(unsigned int i) const { return _pointerDataList[i].get(); }
+
+ PointerData* getPointerData(osg::Object* obj) { for(unsigned int i=0;i<_pointerDataList.size(); ++i) { if (_pointerDataList[i]->object==obj) return _pointerDataList[i].get(); } return 0; }
+ const PointerData* getPointerData(osg::Object* obj) const { for(unsigned int i=0;i<_pointerDataList.size(); ++i) { if (_pointerDataList[i]->object==obj) return _pointerDataList[i].get(); } return 0; }
+ void addPointerData(PointerData* pd) { _pointerDataList.push_back(pd); }
+
+ void copyPointerDataFrom(const osgGA::GUIEventAdapter& sourceEvent);
+
protected:
/** Force users to create on heap, so that multiple referencing is safe.*/
@@ -664,6 +748,9 @@ public:
TabletPen _tabletPen;
osg::ref_ptr<TouchData> _touchData;
+
+
+ PointerDataList _pointerDataList;
};
}
View
5 include/osgUtil/LineSegmentIntersector
@@ -63,6 +63,11 @@ class OSGUTIL_EXPORT LineSegmentIntersector : public Intersector
const osg::Vec3& getLocalIntersectNormal() const { return localIntersectionNormal; }
osg::Vec3 getWorldIntersectNormal() const { return matrix.valid() ? osg::Matrix::transform3x3(osg::Matrix::inverse(*matrix),localIntersectionNormal) : localIntersectionNormal; }
+
+ /** convinience function for mapping the intersection point to any textures assigned to the objects intersected.
+ * Returns the Texture pointer and texture coords of object hit when a texture is available on the object, returns NULL otherwise.*/
+ osg::Texture* getTextureLookUp(osg::Vec3& tc) const;
+
};
typedef std::multiset<Intersection> Intersections;
View
6 include/osgViewer/CompositeViewer
@@ -123,6 +123,10 @@ class OSGVIEWER_EXPORT CompositeViewer : public ViewerBase
virtual void viewerInit();
+ void generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event);
+ void generatePointerData(osgGA::GUIEventAdapter& event);
+ void reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event);
+
typedef std::vector< osg::ref_ptr<osgViewer::View> > RefViews;
RefViews _views;
@@ -135,6 +139,8 @@ class OSGVIEWER_EXPORT CompositeViewer : public ViewerBase
osg::observer_ptr<osg::Camera> _cameraWithFocus;
osg::observer_ptr<osgViewer::View> _viewWithFocus;
+
+ osg::ref_ptr<osgGA::GUIEventAdapter> _previousEvent;
};
View
25 include/osgViewer/View
@@ -227,20 +227,29 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter
/** Return true if this view contains a specified camera.*/
bool containsCamera(const osg::Camera* camera) const;
- /** Get the camera which contains the pointer position x,y specified in the master camera's window/eye coordinates.
- * Also passes back the local window coordinatess for the graphics context associated with the camera. */
+
+ /** deprecated. */
const osg::Camera* getCameraContainingPosition(float x, float y, float& local_x, float& local_y) const;
- /** Compute intersections between a ray through the specified master camera's window/eye coordinates and a specified node.
- * Note, when a master camera has slaves and no viewport itself, its coordinate frame will be in clip space i.e. -1,-1 to 1,1,
- * while if it has a viewport the coordintates will be relative to its viewport dimensions.
- * Mouse events handled by the view will automatically be attached to the master camera window/clip coordinates so that they can be passed
- * directly to the computeIntersections method. */
+ /** deprecated. */
bool computeIntersections(float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff);
- /** Compute intersections between a ray through the specified master camera's window/eye coordinates and a specified nodePath's subgraph. */
+ /** deprecated. */
bool computeIntersections(float x,float y, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff);
+
+ /** Compute intersections of a ray, starting the current mouse position, through the specified camera. */
+ bool computeIntersections(const osgGA::GUIEventAdapter& ea, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff);
+
+ /** Compute intersections of a ray, starting the current mouse position, through the specified master camera's window/eye coordinates and a specified nodePath's subgraph. */
+ bool computeIntersections(const osgGA::GUIEventAdapter& ea, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff);
+
+
+ /** Compute intersections of a ray through the specified camera. */
+ bool computeIntersections(const osg::Camera* camera, osgUtil::Intersector::CoordinateFrame cf, float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff);
+
+ /** Compute intersections of a ray through the specified camera and a specified nodePath's subgraph. */
+ bool 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 = 0xffffffff);
virtual void requestRedraw();
virtual void requestContinuousUpdate(bool needed=true);
View
9 include/osgViewer/Viewer
@@ -93,10 +93,6 @@ class OSGVIEWER_EXPORT Viewer : public ViewerBase, public osgViewer::View
virtual void updateTraversal();
- void setCameraWithFocus(osg::Camera* camera) { _cameraWithFocus = camera; }
- osg::Camera* getCameraWithFocus() { return _cameraWithFocus.get(); }
- const osg::Camera* getCameraWithFocus() const { return _cameraWithFocus.get(); }
-
virtual void getCameras(Cameras& cameras, bool onlyActive=true);
virtual void getContexts(Contexts& contexts, bool onlyValid=true);
@@ -119,8 +115,9 @@ class OSGVIEWER_EXPORT Viewer : public ViewerBase, public osgViewer::View
virtual void viewerInit() { init(); }
- osg::observer_ptr<osg::Camera> _cameraWithFocus;
-
+ void generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event);
+ void generatePointerData(osgGA::GUIEventAdapter& event);
+ void reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event);
};
View
1  include/osgViewer/ViewerEventHandlers
@@ -528,7 +528,6 @@ protected:
osg::Object(), osgGA::GUIEventHandler(), osg::Drawable::CullCallback(), _fullscreen(false) {}
bool mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const;
- bool computeIntersections(osgViewer::View* view, float x,float y, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff) const;
void resize(int width, int height);
View
7 src/osgGA/EventQueue.cpp
@@ -132,6 +132,11 @@ bool EventQueue::copyEvents(Events& events) const
}
}
+void EventQueue::syncWindowRectangleWithGraphcisContext()
+{
+ const osg::GraphicsContext::Traits* traits = (getGraphicsContext()!=0) ? getGraphicsContext()->getTraits() : 0;
+ if (traits) _accumulateEventState->setWindowRectangle(traits->x, traits->y, traits->width, traits->height, !_useFixedMouseInputRange);
+}
void EventQueue::windowResize(int x, int y, int width, int height, double time)
{
@@ -490,6 +495,8 @@ void EventQueue::frame(double time)
GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
event->setEventType(GUIEventAdapter::FRAME);
event->setTime(time);
+
+ OSG_NOTICE<<"frame("<<time<<"), event->getX()="<<event->getX()<<", event->getY()="<<event->getY()<<", event->getXmin()="<<event->getXmin()<<", event->getYmin()="<<event->getYmin()<<", event->getXmax()="<<event->getXmax()<<", event->getYmax()="<<event->getYmax()<<std::endl;
addEvent(event);
}
View
11 src/osgGA/GUIEventAdapter.cpp
@@ -122,3 +122,14 @@ void GUIEventAdapter::addTouchPoint(unsigned int id, TouchPhase phase, float x,
_touchData->addTouchPoint(id, phase, x, y, tapCount);
}
+
+void GUIEventAdapter::copyPointerDataFrom(const osgGA::GUIEventAdapter& sourceEvent)
+{
+ setGraphicsContext(const_cast<osg::GraphicsContext*>(sourceEvent.getGraphicsContext()));
+ setX(sourceEvent.getX());
+ setY(sourceEvent.getY());
+ setInputRange(sourceEvent.getXmin(), sourceEvent.getYmin(), sourceEvent.getXmax(), sourceEvent.getYmax());
+ setButtonMask(sourceEvent.getButtonMask());
+ setMouseYOrientation(sourceEvent.getMouseYOrientation());
+ setPointerDataList(sourceEvent.getPointerDataList());
+}
View
2  src/osgManipulator/Dragger.cpp
@@ -368,7 +368,7 @@ bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
_pointer.reset();
- if (view->computeIntersections(ea.getX(),ea.getY(),intersections, _intersectionMask))
+ if (view->computeIntersections(ea ,intersections, _intersectionMask))
{
for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
hitr != intersections.end();
View
4 src/osgPlugins/p3d/ReaderWriterP3D.cpp
@@ -1419,7 +1419,7 @@ bool ReaderWriterP3DXML::getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation
{
keyValue = itr->second;
}
- if (key.find("0x",0,2)!=std::string::npos)
+ else if (key.find("0x",0,2)!=std::string::npos)
{
std::istringstream iss(key);
iss>>std::hex>>keyValue;
@@ -1438,7 +1438,7 @@ bool ReaderWriterP3DXML::getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation
}
else
{
- OSG_NOTICE<<"Warning: invalid key used in <key>"<<key<<"</key>, ignoring tag."<<std::endl;
+ OSG_NOTICE<<"Warning: invalid key used in <key>"<<key<<"</key>, ignoring tag. key=["<<key<<"]"<<std::endl;
return false;
}
View
2  src/osgPresentation/PickEventHandler.cpp
@@ -66,7 +66,7 @@ bool PickEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionA
}
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
osgUtil::LineSegmentIntersector::Intersections intersections;
- if (viewer->computeIntersections(ea.getX(),ea.getY(), nv->getNodePath(), intersections))
+ if (viewer->computeIntersections(ea, nv->getNodePath(), intersections))
{
for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr=intersections.begin();
hitr!=intersections.end();
View
6 src/osgQt/GraphicsWindowQt.cpp
@@ -432,6 +432,9 @@ bool GraphicsWindowQt::init( QWidget* parent, const QGLWidget* shareWidget, Qt::
getState()->setContextID( osg::GraphicsContext::createNewContextID() );
}
+ // make sure the event queue has the correct window rectangle size and input range
+ getEventQueue()->syncWindowRectangleWithGraphcisContext();
+
return true;
}
@@ -647,6 +650,9 @@ bool GraphicsWindowQt::realizeImplementation()
_realized = true;
+ // make sure the event queue has the correct window rectangle size and input range
+ getEventQueue()->syncWindowRectangleWithGraphcisContext();
+
// make this window's context not current
// note: this must be done as we will probably make the context current from another thread
// and it is not allowed to have one context current in two threads
View
109 src/osgUtil/LineSegmentIntersector.cpp
@@ -20,6 +20,7 @@
#include <osg/TriangleFunctor>
#include <osg/KdTree>
#include <osg/Timer>
+#include <osg/TexMat>
using namespace osgUtil;
@@ -613,3 +614,111 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const
return true;
}
+
+osg::Texture* LineSegmentIntersector::Intersection::getTextureLookUp(osg::Vec3& tc) const
+{
+ osg::Geometry* geometry = drawable.valid() ? drawable->asGeometry() : 0;
+ osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0;
+
+ if (vertices)
+ {
+ if (indexList.size()==3 && ratioList.size()==3)
+ {
+ unsigned int i1 = indexList[0];
+ unsigned int i2 = indexList[1];
+ unsigned int i3 = indexList[2];
+
+ float r1 = ratioList[0];
+ float r2 = ratioList[1];
+ float r3 = ratioList[2];
+
+ osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0;
+ osg::FloatArray* texcoords_FloatArray = dynamic_cast<osg::FloatArray*>(texcoords);
+ osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords);
+ osg::Vec3Array* texcoords_Vec3Array = dynamic_cast<osg::Vec3Array*>(texcoords);
+ if (texcoords_FloatArray)
+ {
+ // we have tex coord array so now we can compute the final tex coord at the point of intersection.
+ float tc1 = (*texcoords_FloatArray)[i1];
+ float tc2 = (*texcoords_FloatArray)[i2];
+ float tc3 = (*texcoords_FloatArray)[i3];
+ tc.x() = tc1*r1 + tc2*r2 + tc3*r3;
+ }
+ else if (texcoords_Vec2Array)
+ {
+ // we have tex coord array so now we can compute the final tex coord at the point of intersection.
+ const osg::Vec2& tc1 = (*texcoords_Vec2Array)[i1];
+ const osg::Vec2& tc2 = (*texcoords_Vec2Array)[i2];
+ const osg::Vec2& tc3 = (*texcoords_Vec2Array)[i3];
+ tc.x() = tc1.x()*r1 + tc2.x()*r2 + tc3.x()*r3;
+ tc.y() = tc1.y()*r1 + tc2.y()*r2 + tc3.y()*r3;
+ }
+ else if (texcoords_Vec3Array)
+ {
+ // we have tex coord array so now we can compute the final tex coord at the point of intersection.
+ const osg::Vec3& tc1 = (*texcoords_Vec3Array)[i1];
+ const osg::Vec3& tc2 = (*texcoords_Vec3Array)[i2];
+ const osg::Vec3& tc3 = (*texcoords_Vec3Array)[i3];
+ tc.x() = tc1.x()*r1 + tc2.x()*r2 + tc3.x()*r3;
+ tc.y() = tc1.y()*r1 + tc2.y()*r2 + tc3.y()*r3;
+ tc.z() = tc1.z()*r1 + tc2.z()*r2 + tc3.z()*r3;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ const osg::TexMat* activeTexMat = 0;
+ const osg::Texture* activeTexture = 0;
+
+ if (drawable->getStateSet())
+ {
+ const osg::TexMat* texMat = dynamic_cast<osg::TexMat*>(drawable->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT));
+ if (texMat) activeTexMat = texMat;
+
+ const osg::Texture* texture = dynamic_cast<osg::Texture*>(drawable->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXTURE));
+ if (texture) activeTexture = texture;
+ }
+
+ for(osg::NodePath::const_reverse_iterator itr = nodePath.rbegin();
+ itr != nodePath.rend() && (!activeTexMat || !activeTexture);
+ ++itr)
+ {
+ const osg::Node* node = *itr;
+ if (node->getStateSet())
+ {
+ if (!activeTexMat)
+ {
+ const osg::TexMat* texMat = dynamic_cast<const osg::TexMat*>(node->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT));
+ if (texMat) activeTexMat = texMat;
+ }
+
+ if (!activeTexture)
+ {
+ const osg::Texture* texture = dynamic_cast<const osg::Texture*>(node->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXTURE));
+ if (texture) activeTexture = texture;
+ }
+ }
+ }
+
+ if (activeTexMat)
+ {
+ osg::Vec4 tc_transformed = osg::Vec4(tc.x(), tc.y(), tc.z() ,0.0f) * activeTexMat->getMatrix();
+ tc.x() = tc_transformed.x();
+ tc.y() = tc_transformed.y();
+ tc.z() = tc_transformed.z();
+
+ if (activeTexture && activeTexMat->getScaleByTextureRectangleSize())
+ {
+ tc.x() *= static_cast<float>(activeTexture->getTextureWidth());
+ tc.y() *= static_cast<float>(activeTexture->getTextureHeight());
+ tc.z() *= static_cast<float>(activeTexture->getTextureDepth());
+ }
+ }
+
+ return const_cast<osg::Texture*>(activeTexture);
+
+ }
+ return 0;
+}
View
501 src/osgViewer/CompositeViewer.cpp
@@ -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;
+ (*itr)->setGraphicsContext(gw);
+ }
- float x = event->getX();
- float y = event->getY();
+ all_events.insert(all_events.end(), gw_events.begin(), gw_events.end());
+ }
+ }
- bool invert_y = event->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
- if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
+ // 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();
- switch(event->getEventType())
+ 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)
{
- 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;
+ generatePointerData(*event);
}
-
- if (pointerEvent)
+ else
{
- 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);
-
+ reprojectPointerData(*_previousEvent, *event);
}
- else
+
+#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->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());
+ 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;
+ }
- for(itr = gw_events.begin();
- itr != gw_events.end();
- ++itr)
+ 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())
{
- osgGA::GUIEventAdapter* event = itr->get();
- switch(event->getEventType())
- {
- case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
- {
- bool wasThreading = areThreadsRunning();
- if (wasThreading) stopThreading();
+ // 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);
+ }
- gw->close();
+ _previousEvent = event;
+ }
- if (wasThreading) startThreading();
+ // 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();
- break;
- }
- default:
- break;
+ if (event->getGraphicsContext())
+ {
+ event->getGraphicsContext()->close();
}
- }
- viewEventsMap[masterView].insert( viewEventsMap[masterView].end(), gw_events.begin(), gw_events.end() );
+ if (wasThreading) startThreading();
+ break;
+ }
+ default:
+ break;
}
}
-
-
- // OSG_NOTICE<<"mouseEventState Xmin = "<<eventState->getXmin()<<" Ymin="<<eventState->getYmin()<<" xMax="<<eventState->getXmax()<<" Ymax="<<eventState->getYmax()<<std::endl;
-
+
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
7 src/osgViewer/GraphicsWindowCarbon.cpp
@@ -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
6 src/osgViewer/GraphicsWindowCocoa.mm
@@ -1074,6 +1074,9 @@ virtual void getWindowBounds(CGRect& rect)
_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 @@ virtual void getWindowBounds(CGRect& rect)
// 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
6 src/osgViewer/GraphicsWindowIOS.mm
@@ -727,6 +727,9 @@ - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interf
//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 @@ - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interf
// 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
6 src/osgViewer/GraphicsWindowWin32.cpp
@@ -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
9 src/osgViewer/GraphicsWindowX11.cpp
@@ -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
177 src/osgViewer/View.cpp
@@ -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;
+}
- 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);
+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;
-#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;
+ if (camera) return computeIntersections(camera, (camera->getViewport()==0)?osgUtil::Intersector::PROJECTION : osgUtil::Intersector::WINDOW, local_x, local_y, nodePath, intersections, traversalMask);
+ else return false;
+}
- 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);
+}
- osgUtil::IntersectionVisitor iv(picker.get());
- iv.setTraversalMask(traversalMask);
-
-
+bool View::computeIntersections(const osgGA::GUIEventAdapter& ea, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask 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();
+ 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);
+}
- iv.setDoDummyTraversal(false);
- const_cast<osg::Camera*>(camera)->accept(iv);
- osg::Timer_t after_kdTree_2 = osg::Timer::instance()->tick();
+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;
- int intersectsBeforeConventional = picker->getIntersections().size();
+ osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(cf, x, y);
+ osgUtil::IntersectionVisitor iv(picker.get());
+ iv.setTraversalMask(traversalMask);
- 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
364 src/osgViewer/Viewer.cpp
@@ -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,