diff --git a/examples/osgcompositeviewer/osgcompositeviewer.cpp b/examples/osgcompositeviewer/osgcompositeviewer.cpp index bc1bfbb2f..6cc732653 100644 --- a/examples/osgcompositeviewer/osgcompositeviewer.cpp +++ b/examples/osgcompositeviewer/osgcompositeviewer.cpp @@ -54,7 +54,7 @@ public: ~PickHandler() {} - bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa) + bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgViewer::View* view = dynamic_cast(&aa); if (!view) return false; @@ -71,7 +71,7 @@ public: { if (_mx==ea.getX() && _my==ea.getY()) { - pick(view, ea.getX(), ea.getY()); + pick(view, ea); } break; } @@ -81,13 +81,13 @@ public: 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 @@ public: // 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(parent); if (!parentAsScribe) { diff --git a/examples/osgkeystone/osgkeystone.cpp b/examples/osgkeystone/osgkeystone.cpp index 26c925f91..64aa34ee5 100644 --- a/examples/osgkeystone/osgkeystone.cpp +++ b/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 @@ public: { 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 @@ public: bool keystoneEditingEnabled; + osg::Vec4 gridColour; + osg::Vec2d bottom_left; osg::Vec2d bottom_right; osg::Vec2d top_left; @@ -97,7 +101,7 @@ public: ~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(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; iobject==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 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 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 = 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 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 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 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); - } + osg::ref_ptr 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); - // 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 + if (keystone.valid()) + { + // 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 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 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 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 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 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 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 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 right_keystone = new Keystone; + right_keystone->gridColour.set(0.0f,1.0f,0.0,1.0); + + // create Keystone right distortion camera + osg::ref_ptr 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): diff --git a/examples/osglauncher/osglauncher.cpp b/examples/osglauncher/osglauncher.cpp index c64f5625e..095f94b20 100644 --- a/examples/osglauncher/osglauncher.cpp +++ b/examples/osglauncher/osglauncher.cpp @@ -63,7 +63,7 @@ public: 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 "<computeIntersections(x, y, intersections)) + if (_viewer->computeIntersections(event, intersections)) { for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr != intersections.end(); diff --git a/examples/osgmovie/osgmovie.cpp b/examples/osgmovie/osgmovie.cpp index 23961e776..173608435 100644 --- a/examples/osgmovie/osgmovie.cpp +++ b/examples/osgmovie/osgmovie.cpp @@ -148,8 +148,8 @@ bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction osgViewer::View* view = dynamic_cast(&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) { diff --git a/examples/osgmultiplemovies/osgmultiplemovies.cpp b/examples/osgmultiplemovies/osgmultiplemovies.cpp index e1251cbfb..d265c8fd8 100644 --- a/examples/osgmultiplemovies/osgmultiplemovies.cpp +++ b/examples/osgmultiplemovies/osgmultiplemovies.cpp @@ -164,7 +164,7 @@ bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction osgViewer::View* view = dynamic_cast(&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) { diff --git a/examples/osgoccluder/osgoccluder.cpp b/examples/osgoccluder/osgoccluder.cpp index 2de12f858..59942b47d 100644 --- a/examples/osgoccluder/osgoccluder.cpp +++ b/examples/osgoccluder/osgoccluder.cpp @@ -72,7 +72,7 @@ bool OccluderEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAct { osgViewer::View* view = dynamic_cast(&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)); diff --git a/examples/osgoscdevice/osgoscdevice.cpp b/examples/osgoscdevice/osgoscdevice.cpp index 218a103e4..355aab745 100755 --- a/examples/osgoscdevice/osgoscdevice.cpp +++ b/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) diff --git a/examples/osgparticleeffects/osgparticleeffects.cpp b/examples/osgparticleeffects/osgparticleeffects.cpp index f78f852e6..cf9af6d44 100644 --- a/examples/osgparticleeffects/osgparticleeffects.cpp +++ b/examples/osgparticleeffects/osgparticleeffects.cpp @@ -268,9 +268,9 @@ public: { osg::Group* root = dynamic_cast(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(); diff --git a/examples/osgpick/osgpick.cpp b/examples/osgpick/osgpick.cpp index 8a624baee..c6d3c4c13 100644 --- a/examples/osgpick/osgpick.cpp +++ b/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()) + + 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) diff --git a/examples/osgwidgetbox/osgwidgetbox.cpp b/examples/osgwidgetbox/osgwidgetbox.cpp index a0debef00..df1394f10 100644 --- a/examples/osgwidgetbox/osgwidgetbox.cpp +++ b/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; } diff --git a/include/osgGA/EventQueue b/include/osgGA/EventQueue index 0a9c2f977..613c7689e 100644 --- a/include/osgGA/EventQueue +++ b/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.*/ diff --git a/include/osgGA/GUIEventAdapter b/include/osgGA/GUIEventAdapter index e84b5a2b5..131ed3eb9 100644 --- a/include/osgGA/GUIEventAdapter +++ b/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 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 > 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; + + + PointerDataList _pointerDataList; }; } diff --git a/include/osgUtil/LineSegmentIntersector b/include/osgUtil/LineSegmentIntersector index 5cfe2d04b..f9c8dfe7a 100644 --- a/include/osgUtil/LineSegmentIntersector +++ b/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 Intersections; diff --git a/include/osgViewer/CompositeViewer b/include/osgViewer/CompositeViewer index e9cc6f6fc..bd7380866 100644 --- a/include/osgViewer/CompositeViewer +++ b/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 > RefViews; RefViews _views; @@ -135,6 +139,8 @@ class OSGVIEWER_EXPORT CompositeViewer : public ViewerBase osg::observer_ptr _cameraWithFocus; osg::observer_ptr _viewWithFocus; + + osg::ref_ptr _previousEvent; }; diff --git a/include/osgViewer/View b/include/osgViewer/View index 1dc279233..b4068432e 100644 --- a/include/osgViewer/View +++ b/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); diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index 83eb68eb3..32958e88f 100644 --- a/include/osgViewer/Viewer +++ b/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 _cameraWithFocus; - + void generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event); + void generatePointerData(osgGA::GUIEventAdapter& event); + void reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event); }; diff --git a/include/osgViewer/ViewerEventHandlers b/include/osgViewer/ViewerEventHandlers index 023a9f838..c2458a85f 100644 --- a/include/osgViewer/ViewerEventHandlers +++ b/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); diff --git a/src/osgGA/EventQueue.cpp b/src/osgGA/EventQueue.cpp index f1bdba123..0b64b3261 100644 --- a/src/osgGA/EventQueue.cpp +++ b/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("<getX()="<getX()<<", event->getY()="<getY()<<", event->getXmin()="<getXmin()<<", event->getYmin()="<getYmin()<<", event->getXmax()="<getXmax()<<", event->getYmax()="<getYmax()<addTouchPoint(id, phase, x, y, tapCount); } + +void GUIEventAdapter::copyPointerDataFrom(const osgGA::GUIEventAdapter& sourceEvent) +{ + setGraphicsContext(const_cast(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()); +} diff --git a/src/osgManipulator/Dragger.cpp b/src/osgManipulator/Dragger.cpp index 3f48e1d22..a693f7a4e 100644 --- a/src/osgManipulator/Dragger.cpp +++ b/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(); diff --git a/src/osgPlugins/p3d/ReaderWriterP3D.cpp b/src/osgPlugins/p3d/ReaderWriterP3D.cpp index 699918028..a0e56a7ba 100644 --- a/src/osgPlugins/p3d/ReaderWriterP3D.cpp +++ b/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 "<, ignoring tag."<"<, ignoring tag. key=["<(&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(); diff --git a/src/osgQt/GraphicsWindowQt.cpp b/src/osgQt/GraphicsWindowQt.cpp index df269187a..9141ba785 100644 --- a/src/osgQt/GraphicsWindowQt.cpp +++ b/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 diff --git a/src/osgUtil/LineSegmentIntersector.cpp b/src/osgUtil/LineSegmentIntersector.cpp index 5131449c1..04cfc8eee 100644 --- a/src/osgUtil/LineSegmentIntersector.cpp +++ b/src/osgUtil/LineSegmentIntersector.cpp @@ -20,6 +20,7 @@ #include #include #include +#include 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(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(texcoords); + osg::Vec2Array* texcoords_Vec2Array = dynamic_cast(texcoords); + osg::Vec3Array* texcoords_Vec3Array = dynamic_cast(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(drawable->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT)); + if (texMat) activeTexMat = texMat; + + const osg::Texture* texture = dynamic_cast(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(node->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT)); + if (texMat) activeTexMat = texMat; + } + + if (!activeTexture) + { + const osg::Texture* texture = dynamic_cast(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(activeTexture->getTextureWidth()); + tc.y() *= static_cast(activeTexture->getTextureHeight()); + tc.z() *= static_cast(activeTexture->getTextureDepth()); + } + } + + return const_cast(activeTexture); + + } + return 0; +} diff --git a/src/osgViewer/CompositeViewer.cpp b/src/osgViewer/CompositeViewer.cpp index 514c415b8..f31c741be 100644 --- a/src/osgViewer/CompositeViewer.cpp +++ b/src/osgViewer/CompositeViewer.cpp @@ -12,6 +12,9 @@ */ #include +#include +#include + #include #include #include @@ -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(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(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()="<second._texture.get()<<", "<second._face<(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(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(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(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(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& lhs,const osg::ref_ptr& 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()."< 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()="<getGraphicsContext()<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 = "<getXmin()<<" Ymin="<getYmin()<<" xMax="<getXmax()<<" Ymax="<getYmax()<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(pd->object.get()) : 0; + osgViewer::View* view = camera ? dynamic_cast(camera->getView()) : 0; + + if (!view) + { + if (_viewWithFocus.valid()) + { + // OSG_NOTICE<<"Falling back to using _viewWithFocus"<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 "<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; diff --git a/src/osgViewer/GraphicsWindowCarbon.cpp b/src/osgViewer/GraphicsWindowCarbon.cpp index 5aa55ec2f..aec2de60b 100644 --- a/src/osgViewer/GraphicsWindowCarbon.cpp +++ b/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; } diff --git a/src/osgViewer/GraphicsWindowCocoa.mm b/src/osgViewer/GraphicsWindowCocoa.mm index 598aa590e..2e08601ca 100644 --- a/src/osgViewer/GraphicsWindowCocoa.mm +++ b/src/osgViewer/GraphicsWindowCocoa.mm @@ -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; } diff --git a/src/osgViewer/GraphicsWindowIOS.mm b/src/osgViewer/GraphicsWindowIOS.mm index a54e372bb..0ffacd5e1 100644 --- a/src/osgViewer/GraphicsWindowIOS.mm +++ b/src/osgViewer/GraphicsWindowIOS.mm @@ -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; diff --git a/src/osgViewer/GraphicsWindowWin32.cpp b/src/osgViewer/GraphicsWindowWin32.cpp index de8cf4c42..21622c1fb 100644 --- a/src/osgViewer/GraphicsWindowWin32.cpp +++ b/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; } diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index bb78fff0f..08c935d05 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/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; diff --git a/src/osgViewer/View.cpp b/src/osgViewer/View.cpp index c7be349ee..9acf2d94e 100644 --- a/src/osgViewer/View.cpp +++ b/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("<getCurrentEventState(); const osgViewer::GraphicsWindow* gw = dynamic_cast(eventState->getGraphicsContext()); - bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS; + + // OSG_NOTICE<<"getCameraContainingPosition("<getViewport(); - - double new_x = x; - double new_y = y; - - if (!gw) - { - new_x = static_cast(_camera->getGraphicsContext()->getTraits()->width) * (x - eventState->getXmin())/(eventState->getXmax()-eventState->getXmin()); - new_y = view_invert_y ? - static_cast(_camera->getGraphicsContext()->getTraits()->height) * (1.0 - (y- eventState->getYmin())/(eventState->getYmax()-eventState->getYmin())) : - static_cast(_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(_camera->getGraphicsContext()->getTraits()->width); + new_y *= static_cast(_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"<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("<getViewport()->x()<<","<getViewport()->y()<<","<getViewport()->width()<<","<getViewport()->height()<<")"<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 ("<x<<","<y<<","<width<<","<height<<")"<(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(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(camera)->accept(iv); -#else - - // timing test code paths for comparing KdTree based intersections vs conventional intersections - - iv.setUseKdTreeWhenAvailable(true); - iv.setDoDummyTraversal(true); - - const_cast(camera)->accept(iv); - - - osg::Timer_t before = osg::Timer::instance()->tick(); - const_cast(camera)->accept(iv); - - osg::Timer_t after_dummy = osg::Timer::instance()->tick(); - - int intersectsBeforeKdTree = picker->getIntersections().size(); - - iv.setDoDummyTraversal(false); - const_cast(camera)->accept(iv); - osg::Timer_t after_kdTree_2 = osg::Timer::instance()->tick(); - - int intersectsBeforeConventional = picker->getIntersections().size(); - - iv.setUseKdTreeWhenAvailable(false); - const_cast(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 "<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 ); diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 86e2dd8d0..aaf04cc03 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include @@ -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()"<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(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()="<second._texture.get()<<", "<second._face<(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(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(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(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 "<getName()<<" x="<get(); - switch(event->getEventType()) - { - case(osgGA::GUIEventAdapter::PUSH): - OSG_NOTICE<<" PUSH "<getButton()<<" x="<getX()<<" y="<getY()<getButton()<<" x="<getX()<<" y="<getY()<getButtonMask()<<" x="<getX()<<" y="<getY()<getButtonMask()<<" x="<getX()<<" y="<getY()<getScrollingMotion()<getKey()<<"'"<getKey()<<"'"<getWindowX()<<"/"<getWindowY()<<" x "<getWindowWidth()<<"/"<getWindowHeight() << std::endl; - break; - case(osgGA::GUIEventAdapter::QUIT_APPLICATION): - OSG_NOTICE<<" QUIT_APPLICATION " << std::endl; - break; - case(osgGA::GUIEventAdapter::FRAME): - // OSG_NOTICE<<" FRAME "<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(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) { diff --git a/src/osgWidget/ViewerEventHandlers.cpp b/src/osgWidget/ViewerEventHandlers.cpp index fd2efc1ee..5abd37635 100644 --- a/src/osgWidget/ViewerEventHandlers.cpp +++ b/src/osgWidget/ViewerEventHandlers.cpp @@ -21,7 +21,14 @@ bool MouseHandler::handle( // If we're scrolling, we need to inform the WindowManager of that. _wm->setScrollingMotion(gea.getScrollingMotion()); - return (this->*ma)(gea.getX(), gea.getY(), gea.getButton()); + // osgWidget assumes origin is bottom left of window so make sure mouse coordinate are increaseing y upwards and are scaled to window size. + float x = (gea.getX()-gea.getXmin())/(gea.getXmax()-gea.getXmin())*static_cast(gea.getWindowWidth()); + float y = (gea.getY()-gea.getYmin())/(gea.getYmax()-gea.getYmin())*static_cast(gea.getWindowHeight()); + if (gea.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS) y = static_cast(gea.getWindowHeight())-y; + + //OSG_NOTICE<<"MouseHandler(x="<*ma)(x, y, gea.getButton()); } return false; diff --git a/src/osgWidget/Widget.cpp b/src/osgWidget/Widget.cpp index 246949689..3db3bd46d 100644 --- a/src/osgWidget/Widget.cpp +++ b/src/osgWidget/Widget.cpp @@ -511,7 +511,13 @@ Color Widget::getImageColorAtXY(point_type x, point_type y) const { point_type height = fabs((*texs)[LR].y() - (*texs)[UR].y()); point_type X = ((x / getWidth()) * width) + (*texs)[LL].x(); - point_type Y = (((getHeight() - y) / getHeight()) * height) + (*texs)[UR].y(); + point_type Y = ((y / getHeight()) * height) + (*texs)[LR].y(); + + if (X<0.0 || X>1.0 || Y<0.0 || Y>1.0) + { + OSG_INFO<<"Widget::getImageColorAtXY("<computeIntersections(x, y, intr, _nodeMask)) { + + osg::Camera* camera = _view->getCamera(); + osgViewer::GraphicsWindow* gw = dynamic_cast(camera->getGraphicsContext()); + if (gw) + { + _view->computeIntersections(camera, osgUtil::Intersector::WINDOW, x, y, intr, _nodeMask); + } + + if (!intr.empty()) + { // Get the first Window at the XY coordinates; if you want a Window to be // non-pickable, set the NodeMask to something else. Window* activeWin = 0; @@ -347,48 +357,6 @@ bool WindowManager::pickAtXY(float x, float y, WidgetList& wl) { return false; } -/* -bool WindowManager::pickAtXY(float x, float y, WidgetList& wl) { - Intersections intr; - - if(!_view->computeIntersections(x, y, intr, _nodeMask)) return false; - - typedef std::vector > WindowVector; - - WindowVector windows; - - Window* activeWin = 0; - - for(Intersections::iterator i = intr.begin(); i != intr.end(); i++) { - Window* win = dynamic_cast(i->nodePath.back()->getParent(0)); - - if( - !win || - (win->getVisibilityMode() == Window::VM_PARTIAL && !win->isPointerXYWithinVisible(x, y)) - ) { - continue; - } - - if(activeWin != win) { - activeWin = win; - - windows.push_back(win); - } - } - - if(!windows.size()) return false; - - std::sort(windows.begin(), windows.end(), WindowBinNumberCompare()); - - for(WindowVector::iterator i = windows.begin(); i != windows.end(); i++) { - warn() << "- " << i->get()->getName() << " " << i->get()->getOrCreateStateSet()->getBinNumber() << std::endl; - } - - warn() << std::endl; - - return false; -} -*/ bool WindowManager::setFocused(Window* window) { Event ev(this);