SG_USING_STD(string);
SG_USING_STD(vector);
-void mouseClickHandler(int button, int updown, int x, int y);
+void mouseClickHandler(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
void mouseMotionHandler(int x, int y);
void keyHandler(int key, int keymod, int mousex, int mousey);
}
void
-FGInput::doMouseClick (int b, int updown, int x, int y)
+FGInput::doMouseClick (int b, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter* ea)
{
int modifiers = fgGetKeyModifiers();
}
if (mode.pass_through) {
- if (puMouse(b, updown, x, y))
+ // The pu stuff seems to need that. May be it does opengl picking ...
+ fgMakeCurrent();
+ if (0 <= x && 0 <= y && puMouse(b, updown, x, y))
return;
- else if ((globals->get_current_panel() != 0) &&
+ else if (0 <= x && 0 <= y && (globals->get_current_panel() != 0) &&
globals->get_current_panel()->getVisibility() &&
globals->get_current_panel()->doMouseAction(b, updown, x, y))
return;
- else if (fgHandle3DPanelMouseEvent(b, updown, x, y))
+ else if (0 <= x && 0 <= y && fgHandle3DPanelMouseEvent(b, updown, x, y))
return;
else {
// pui didn't want the click event so compute a
// The nearest one is the first one and the deepest
// (the most specialized one in the scenegraph) is the first.
std::vector<SGSceneryPick> pickList;
- if (FGRenderer::pick(x, y, pickList)) {
+ if (FGRenderer::pick(x, y, pickList, ea)) {
std::vector<SGSceneryPick>::const_iterator i;
for (i = pickList.begin(); i != pickList.end(); ++i) {
if (i->callback->buttonPressed(b, i->info)) {
default_input->doKey(key, keymod, mousex, mousey);
}
-void mouseClickHandler(int button, int updown, int x, int y)
+void mouseClickHandler(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter* ea)
{
if(default_input)
- default_input->doMouseClick(button, updown, x, y);
+ default_input->doMouseClick(button, updown, x, y, mainWindow, ea);
}
void mouseMotionHandler(int x, int y)
* @param x The X position of the mouse event, in screen coordinates.
* @param y The Y position of the mouse event, in screen coordinates.
*/
- virtual void doMouseClick (int button, int updown, int x, int y);
+ virtual void doMouseClick (int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
/**
return _node.get();
}
-namespace {
// All the usual translation from window system to FG / plib
-int osgToFGModifiers(int modifiers)
+static int osgToFGModifiers(int modifiers)
{
int result = 0;
if (modifiers & (osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT |
result |= KEYMOD_ALT;
return result;
}
-} // namespace
void FGManipulator::init(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& us)
(void)handle(ea, us);
}
-namespace {
-void eventToViewport(const osgGA::GUIEventAdapter& ea,
- osgGA::GUIActionAdapter& us,
- int& x, int& y)
+static bool
+eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
+ int& x, int& y)
{
- x = (int)ea.getX();
- y = (int)ea.getY();
- if (ea.getMouseYOrientation()
- == osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
- y = (int)ea.getWindowHeight() - y;
-}
+ x = -1;
+ y = -1;
+
+ const osgViewer::Viewer* viewer;
+ viewer = dynamic_cast<const osgViewer::Viewer*>(&us);
+ if (!viewer)
+ return false;
+
+ float lx, ly;
+ const osg::Camera* camera;
+ camera = viewer->getCameraContainingPosition(ea.getX(), ea.getY(), lx, ly);
+
+ if (!fgOSIsMainCamera(camera))
+ return false;
+
+ x = int(lx);
+ y = int(camera->getViewport()->height() - ly);
+
+ return true;
}
bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
eventToViewport(ea, us, x, y);
if (keyHandler)
(*keyHandler)(key, modmask, x, y);
+ return true;
}
- return true;
case osgGA::GUIEventAdapter::PUSH:
case osgGA::GUIEventAdapter::RELEASE:
{
- eventToViewport(ea, us, x, y);
+ bool mainWindow = eventToViewport(ea, us, x, y);
int button = 0;
switch (ea.getButton()) {
case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
if (mouseClickHandler)
(*mouseClickHandler)(button,
(ea.getEventType()
- == osgGA::GUIEventAdapter::RELEASE), x, y);
+ == osgGA::GUIEventAdapter::RELEASE), x, y, mainWindow, &ea);
return true;
}
case osgGA::GUIEventAdapter::MOVE:
if (mouseMotionHandler)
(*mouseMotionHandler)(x, y);
return true;
- case osgGA::GUIEventAdapter::RESIZE:
- if (windowResizeHandler)
- (*windowResizeHandler)(ea.getWindowWidth(), ea.getWindowHeight());
- return true;
case osgGA::GUIEventAdapter::CLOSE_WINDOW:
case osgGA::GUIEventAdapter::QUIT_APPLICATION:
fgOSExit(0);
return false;
}
}
-
+
void FGManipulator::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
int& modifiers)
{
static void GLUTmouse (int button, int updown, int x, int y)
{
GlutModifiers = glutGetModifiers();
- if(MouseClickHandler) (*MouseClickHandler)(button, updown, x, y);
+ if(MouseClickHandler) (*MouseClickHandler)(button, updown, x, y, true, 0);
}
static void GLUTspecialkeyup(int k, int x, int y)
void fgMakeCurrent()
{
}
+
+bool fgOSIsMainCamera(const osg::Camera*)
+{
+ return true;
+}
+
+bool fgOSIsMainContext(const osg::GraphicsContext*)
+{
+ return true;
+}
// Callbacks and registration API
//
+namespace osg { class Camera; class GraphicsContext; }
+namespace osgGA { class GUIEventAdapter; }
+
typedef void (*fgIdleHandler)();
typedef void (*fgDrawHandler)();
typedef void (*fgWindowResizeHandler)(int w, int h);
typedef void (*fgKeyHandler)(int key, int keymod, int mousex, int mousey);
-typedef void (*fgMouseClickHandler)(int button, int updown, int x, int y);
+typedef void (*fgMouseClickHandler)(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
typedef void (*fgMouseMotionHandler)(int x, int y);
void fgRegisterIdleHandler(fgIdleHandler func);
void fgRegisterMouseMotionHandler(fgMouseMotionHandler func);
void fgMakeCurrent();
+
+bool fgOSIsMainCamera(const osg::Camera* camera);
+bool fgOSIsMainContext(const osg::GraphicsContext* context);
+
#endif // _FG_OS_HXX
#include <osgGA/MatrixManipulator>
#include "fg_os.hxx"
+#include "fg_props.hxx"
#include "util.hxx"
#include "globals.hxx"
#include "renderer.hxx"
// fg_os implementation
//
-
static osg::ref_ptr<osgViewer::Viewer> viewer;
+static osg::ref_ptr<osg::Camera> mainCamera;
void fgOSOpenWindow(int w, int h, int bpp,
bool alpha, bool stencil, bool fullscreen)
{
+ osg::GraphicsContext::WindowingSystemInterface* wsi;
+ wsi = osg::GraphicsContext::getWindowingSystemInterface();
+
viewer = new osgViewer::Viewer;
// Avoid complications with fg's custom drawables.
- viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
- osg::ref_ptr<osg::GraphicsContext::Traits> traits
- = new osg::GraphicsContext::Traits;
+ std::string mode;
+ mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded");
+ if (mode == "AutomaticSelection")
+ viewer->setThreadingModel(osgViewer::Viewer::AutomaticSelection);
+ else if (mode == "CullDrawThreadPerContext")
+ viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
+ else if (mode == "DrawThreadPerContext")
+ viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
+ else if (mode == "CullThreadPerCameraDrawThreadPerContext")
+ viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
+ else
+ viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
+ osg::ref_ptr<osg::GraphicsContext::Traits> traits;
+ traits = new osg::GraphicsContext::Traits;
int cbits = (bpp <= 16) ? 5 : 8;
int zbits = (bpp <= 16) ? 16 : 24;
- traits->width = w;
- traits->height = h;
traits->red = traits->green = traits->blue = cbits;
traits->depth = zbits;
if (alpha)
traits->alpha = 8;
if (stencil)
traits->stencil = 8;
- if (fullscreen)
+ traits->doubleBuffer = true;
+ traits->mipMapGeneration = true;
+ traits->windowName = "FlightGear";
+ traits->sampleBuffers = fgGetBool("/sim/rendering/multi-sample-buffers", traits->sampleBuffers);
+ traits->samples = fgGetBool("/sim/rendering/multi-samples", traits->samples);
+ traits->vsync = fgGetBool("/sim/rendering/vsync-enable", traits->vsync);
+
+ if (fullscreen) {
+ unsigned width = 0;
+ unsigned height = 0;
+ wsi->getScreenResolution(*traits, width, height);
traits->windowDecoration = false;
- else
+ traits->width = width;
+ traits->height = height;
+ traits->supportsResize = false;
+ } else {
traits->windowDecoration = true;
- traits->supportsResize = true;
- traits->doubleBuffer = true;
- osg::GraphicsContext* gc
- = osg::GraphicsContext::createGraphicsContext(traits.get());
- viewer->getCamera()->setGraphicsContext(gc);
+ traits->width = w;
+ traits->height = h;
+ traits->supportsResize = true;
+ }
+
+ osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
+
+ // Ok, first the children.
+ // that achieves some magic ordering og the slaves so that we end up
+ // in the main window more often.
+ // This can be sorted out better when we got rid of glut and sdl.
+ if (fgHasNode("/sim/rendering/camera")) {
+ SGPropertyNode* renderingNode = fgGetNode("/sim/rendering");
+ for (int i = 0; i < renderingNode->nChildren(); ++i) {
+ SGPropertyNode* cameraNode = renderingNode->getChild(i);
+ if (strcmp(cameraNode->getName(), "camera") != 0)
+ continue;
+
+ // get a new copy of the traits struct
+ osg::ref_ptr<osg::GraphicsContext::Traits> cameraTraits;
+ cameraTraits = new osg::GraphicsContext::Traits(*traits);
+
+ double shearx = cameraNode->getDoubleValue("shear-x", 0);
+ double sheary = cameraNode->getDoubleValue("shear-y", 0);
+ cameraTraits->hostName = cameraNode->getStringValue("host-name", "");
+ cameraTraits->displayNum = cameraNode->getIntValue("display", 0);
+ cameraTraits->screenNum = cameraNode->getIntValue("screen", 0);
+ if (cameraNode->getBoolValue("fullscreen", fullscreen)) {
+ unsigned width = 0;
+ unsigned height = 0;
+ wsi->getScreenResolution(*cameraTraits, width, height);
+ cameraTraits->windowDecoration = false;
+ cameraTraits->width = width;
+ cameraTraits->height = height;
+ cameraTraits->supportsResize = false;
+ } else {
+ cameraTraits->windowDecoration = true;
+ cameraTraits->width = cameraNode->getIntValue("width", w);
+ cameraTraits->height = cameraNode->getIntValue("height", h);
+ cameraTraits->supportsResize = true;
+ }
+ // FIXME, currently this is too much of a problem to route the resize
+ // events. When we do no longer need sdl and such this
+ // can be simplified
+ cameraTraits->supportsResize = false;
+
+ // ok found a camera configuration, add a new slave ...
+ osg::ref_ptr<osg::Camera> camera = new osg::Camera;
+
+ osg::GraphicsContext* gc;
+ gc = osg::GraphicsContext::createGraphicsContext(cameraTraits.get());
+ gc->realize();
+ camera->setGraphicsContext(gc);
+ // If a viewport isn't set on the camera, then it's hard to dig it
+ // out of the SceneView objects in the viewer, and the coordinates
+ // of mouse events are somewhat bizzare.
+ camera->setViewport(new osg::Viewport(0, 0, cameraTraits->width, cameraTraits->height));
+ camera->setProjectionResizePolicy(rsp);
+ viewer->addSlave(camera.get(), osg::Matrix::translate(-shearx, -sheary, 0), osg::Matrix());
+ }
+ }
+
+ // now the main camera ...
+ osg::ref_ptr<osg::Camera> camera = new osg::Camera;
+ mainCamera = camera;
+ osg::GraphicsContext* gc;
+ gc = osg::GraphicsContext::createGraphicsContext(traits.get());
+ gc->realize();
+ gc->makeCurrent();
+ camera->setGraphicsContext(gc);
// If a viewport isn't set on the camera, then it's hard to dig it
// out of the SceneView objects in the viewer, and the coordinates
// of mouse events are somewhat bizzare.
- viewer->getCamera()->setViewport(new osg::Viewport(0, 0,
- traits->width,
- traits->height));
+ camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
+ camera->setProjectionResizePolicy(rsp);
+ viewer->addSlave(camera.get());
+
viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
// Let FG handle the escape key with a confirmation
viewer->setKeyEventSetsDone(0);
void fgWarpMouse(int x, int y)
{
- viewer->requestWarpPointer((float)x, (float)y);
+ // Hack, currently the pointer is just recentered. So, we know the relative coordinates ...
+ viewer->requestWarpPointer(0, 0);
}
// Noop
{
}
+// Noop
void fgOSFullScreen()
{
- // Noop, but is probably doable
+}
+// #define OSG_HAS_MOUSE_CURSOR_PATCH
+#ifdef OSG_HAS_MOUSE_CURSOR_PATCH
+static void setMouseCursor(osg::Camera* camera, int cursor)
+{
+ if (!camera)
+ return;
+ osg::GraphicsContext* gc = camera->getGraphicsContext();
+ if (!gc)
+ return;
+ osgViewer::GraphicsWindow* gw;
+ gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc);
+ if (!gw)
+ return;
+
+ osgViewer::GraphicsWindow::MouseCursor mouseCursor;
+ mouseCursor = osgViewer::GraphicsWindow::InheritCursor;
+ if (cursor == MOUSE_CURSOR_NONE)
+ mouseCursor = osgViewer::GraphicsWindow::NoCursor;
+ else if(cursor == MOUSE_CURSOR_POINTER)
+ mouseCursor = osgViewer::GraphicsWindow::RightArrowCursor;
+ else if(cursor == MOUSE_CURSOR_WAIT)
+ mouseCursor = osgViewer::GraphicsWindow::WaitCursor;
+ else if(cursor == MOUSE_CURSOR_CROSSHAIR)
+ mouseCursor = osgViewer::GraphicsWindow::CrosshairCursor;
+ else if(cursor == MOUSE_CURSOR_LEFTRIGHT)
+ mouseCursor = osgViewer::GraphicsWindow::LeftRightCursor;
+
+ gw->setCursor(mouseCursor);
}
+#endif
+
+static int _cursor = -1;
-// No support in OSG yet
void fgSetMouseCursor(int cursor)
{
+ _cursor = cursor;
+#ifdef OSG_HAS_MOUSE_CURSOR_PATCH
+ setMouseCursor(viewer->getCamera(), cursor);
+ for (unsigned i = 0; i < viewer->getNumSlaves(); ++i)
+ setMouseCursor(viewer->getSlave(i)._camera.get(), cursor);
+#endif
}
int fgGetMouseCursor()
{
- return 0;
+ return _cursor;
}
void fgMakeCurrent()
{
- osg::GraphicsContext* gc = viewer->getCamera()->getGraphicsContext();
+ if (!mainCamera.valid())
+ return;
+ osg::GraphicsContext* gc = mainCamera->getGraphicsContext();
+ if (!gc)
+ return;
gc->makeCurrent();
}
+
+bool fgOSIsMainContext(const osg::GraphicsContext* context)
+{
+ if (!mainCamera.valid())
+ return false;
+ return context == mainCamera->getGraphicsContext();
+}
+
+bool fgOSIsMainCamera(const osg::Camera* camera)
+{
+ if (!camera)
+ return false;
+ if (camera == mainCamera.get())
+ return true;
+ if (!viewer.valid())
+ return false;
+ if (camera == viewer->getCamera())
+ return true;
+ return false;
+}
if(MouseClickHandler)
(*MouseClickHandler)(e.button.button - 1,
e.button.state == SDL_RELEASED,
- e.button.x, e.button.y);
+ e.button.x, e.button.y, true, 0);
break;
case SDL_MOUSEMOTION:
CurrentMouseX = e.motion.x;
void fgMakeCurrent()
{
}
+
+bool fgOSIsMainCamera(const osg::Camera*)
+{
+ return true;
+}
+
+bool fgOSIsMainContext(const osg::GraphicsContext*)
+{
+ return true;
+}
#include <osgUtil/SceneView>
#include <osgUtil/UpdateVisitor>
#include <osgUtil/IntersectVisitor>
+#include <osgUtil/LineSegmentIntersector>
#include <osg/io_utils>
#include <osgDB/WriteFile>
{ drawImplementation(*renderInfo.getState()); }
void drawImplementation(osg::State& state) const
{
+ if (!fgOSIsMainContext(state.getGraphicsContext()))
+ return;
+
state.pushStateSet(getStateSet());
state.apply();
state.setActiveTextureUnit(0);
{ drawImplementation(*renderInfo.getState()); }
void drawImplementation(osg::State& state) const
{
+// std::cout << state.getGraphicsContext() << std::endl;
+ if (!fgOSIsMainContext(state.getGraphicsContext()))
+ return;
+
state.pushStateSet(getStateSet());
state.apply();
state.setActiveTextureUnit(0);
glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
if (viewer) {
- viewer->getCamera()
+ viewer->getCamera()
->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
} else {
sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
// need to call the update visitor once
if (!viewer) {
mFrameStamp->setReferenceTime(globals->get_sim_time_sec());
+ mFrameStamp->setSimulationTime(globals->get_sim_time_sec());
mFrameStamp->setFrameNumber(1+mFrameStamp->getFrameNumber());
}
mFrameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
}
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
if (viewer)
- viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
- width, view_h);
+ ;
+ // viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
+// width, view_h);
else
sceneView->getViewport()->setViewport(0, height - view_h,
width, view_h);
}
-// These are wrapper functions around ssgSetNearFar() and ssgSetFOV()
-// which will post process and rewrite the resulting frustum if we
-// want to do asymmetric view frustums.
-
-static void fgHackFrustum() {
-
- // specify a percent of the configured view frustum to actually
- // display. This is a bit of a hack to achieve asymmetric view
- // frustums. For instance, if you want to display two monitors
- // side by side, you could specify each with a double fov, a 0.5
- // aspect ratio multiplier, and then the left side monitor would
- // have a left_pct = 0.0, a right_pct = 0.5, a bottom_pct = 0.0,
- // and a top_pct = 1.0. The right side monitor would have a
- // left_pct = 0.5 and a right_pct = 1.0.
-
- static SGPropertyNode *left_pct
- = fgGetNode("/sim/current-view/frustum-left-pct");
- static SGPropertyNode *right_pct
- = fgGetNode("/sim/current-view/frustum-right-pct");
- static SGPropertyNode *bottom_pct
- = fgGetNode("/sim/current-view/frustum-bottom-pct");
- static SGPropertyNode *top_pct
- = fgGetNode("/sim/current-view/frustum-top-pct");
- osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
- double left, right;
- double bottom, top;
- double zNear, zFar;
- if (viewer)
- viewer->getCamera()->getProjectionMatrixAsFrustum(left, right,
- bottom, top,
- zNear, zFar);
- else
- sceneView->getProjectionMatrixAsFrustum(left, right, bottom, top,
- zNear, zFar);
- // cout << " l = " << f->getLeft()
- // << " r = " << f->getRight()
- // << " b = " << f->getBot()
- // << " t = " << f->getTop()
- // << " n = " << f->getNear()
- // << " f = " << f->getFar()
- // << endl;
-
- double width = right - left;
- double height = top - bottom;
-
- double l, r, t, b;
-
- if ( left_pct != NULL ) {
- l = left + width * left_pct->getDoubleValue();
- } else {
- l = left;
- }
-
- if ( right_pct != NULL ) {
- r = left + width * right_pct->getDoubleValue();
- } else {
- r = right;
- }
-
- if ( bottom_pct != NULL ) {
- b = bottom + height * bottom_pct->getDoubleValue();
- } else {
- b = bottom;
- }
-
- if ( top_pct != NULL ) {
- t = bottom + height * top_pct->getDoubleValue();
- } else {
- t = top;
- }
- if (viewer)
- viewer->getCamera()->setProjectionMatrixAsFrustum(l, r, b, t,
- zNear, zFar);
- else
- sceneView->setProjectionMatrixAsFrustum(l, r, b, t, zNear, zFar);
-}
-
-
// we need some static storage space for these values. However, we
// can't store it in a renderer class object because the functions
// that manipulate these are static. They are static so they can
fov_height = h;
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
if (viewer)
- viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height,
- fov_width/fov_height,
- fov_near, fov_far);
+ viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
else
sceneView->setProjectionMatrixAsPerspective(fov_height,
fov_width/fov_height,
fov_near, fov_far);
- // fully specify the view frustum before hacking it (so we don't
- // accumulate hacked effects
- fgHackFrustum();
-// sgEnviro.setFOV( w, h );
}
fov_far = f;
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
if (viewer)
- viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height,
- fov_width/fov_height,
- fov_near, fov_far);
- else
+ viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
+ else
sceneView->setProjectionMatrixAsPerspective(fov_height,
fov_width/fov_height,
fov_near, fov_far);
- // fully specify the view frustum before hacking it (so we don't
- // accumulate hacked effects
- fgHackFrustum();
}
bool
FGRenderer::pick( unsigned x, unsigned y,
- std::vector<SGSceneryPick>& pickList )
+ std::vector<SGSceneryPick>& pickList,
+ const osgGA::GUIEventAdapter* ea )
{
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
// wipe out the return ...
pickList.resize(0);
- osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
- if (!sceneData)
- return false;
- osg::Viewport* viewport = 0;
- osg::Matrix projection;
- osg::Matrix modelview;
-
if (sceneView.valid()) {
- viewport = sceneView->getViewport();
+ osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
+ if (!sceneData)
+ return false;
+
+ osg::Viewport* viewport = sceneView->getViewport();
if (!viewport)
return false;
// don't know why, but the update has partly happened somehow,
// accumulated transform
if (!nodePath.empty())
modelview.preMult(computeLocalToWorld(nodePath.front()));
+
+ // swap the y values ...
+ y = viewport->height() - y;
+ // set up the pick visitor
+ osgUtil::PickVisitor pickVisitor(viewport, projection, modelview, x, y);
+ sceneData->accept(pickVisitor);
+ if (!pickVisitor.hits())
+ return false;
+
+ // collect all interaction callbacks on the pick ray.
+ // They get stored in the pickCallbacks list where they are sorted back
+ // to front and croasest to finest wrt the scenery node they are attached to
+ osgUtil::PickVisitor::LineSegmentHitListMap::const_iterator mi;
+ for (mi = pickVisitor.getSegHitList().begin();
+ mi != pickVisitor.getSegHitList().end();
+ ++mi) {
+ osgUtil::IntersectVisitor::HitList::const_iterator hi;
+ for (hi = mi->second.begin(); hi != mi->second.end(); ++hi) {
+ // ok, go back the nodes and ask for intersection callbacks,
+ // execute them in top down order
+ const osg::NodePath& np = hi->getNodePath();
+ osg::NodePath::const_reverse_iterator npi;
+ for (npi = np.rbegin(); npi != np.rend(); ++npi) {
+ SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
+ if (!ud)
+ continue;
+ for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
+ SGPickCallback* pickCallback = ud->getPickCallback(i);
+ if (!pickCallback)
+ continue;
+ SGSceneryPick sceneryPick;
+ /// note that this is done totally in doubles instead of
+ /// just using getWorldIntersectionPoint
+ osg::Vec3d localPt = hi->getLocalIntersectPoint();
+ sceneryPick.info.local = SGVec3d(localPt);
+ if (hi->getMatrix())
+ sceneryPick.info.wgs84 = SGVec3d(localPt*(*hi->getMatrix()));
+ else
+ sceneryPick.info.wgs84 = SGVec3d(localPt);
+ sceneryPick.callback = pickCallback;
+ pickList.push_back(sceneryPick);
+ }
+ }
+ }
+ }
+
+ return !pickList.empty();
+
} else if (viewer) {
- // I don't think the Viewer case needs to update the camera
- // matrices before picking. The user has clicked on the old scene
- // -- that which is displayed in the front buffer -- so we need to
- // use the camera state in effect for that view of the scene.
- osg::Camera *camera = viewer->getCamera();
- viewport = camera->getViewport();
- projection = camera->getProjectionMatrix();
- modelview = camera->getViewMatrix();
- // Accumulated transforms? Don't think that applies for the
- // Viewer's camera.
- } else { // we can get called early ...
- return false;
- }
- // swap the y values ...
- y = viewport->height() - y;
- // set up the pick visitor
- osgUtil::PickVisitor pickVisitor(viewport, projection, modelview, x, y);
- sceneData->accept(pickVisitor);
- if (!pickVisitor.hits())
- return false;
- // collect all interaction callbacks on the pick ray.
- // They get stored in the pickCallbacks list where they are sorted back
- // to front and croasest to finest wrt the scenery node they are attached to
- osgUtil::PickVisitor::LineSegmentHitListMap::const_iterator mi;
- for (mi = pickVisitor.getSegHitList().begin();
- mi != pickVisitor.getSegHitList().end();
- ++mi) {
- osgUtil::IntersectVisitor::HitList::const_iterator hi;
- for (hi = mi->second.begin(); hi != mi->second.end(); ++hi) {
- // ok, go back the nodes and ask for intersection callbacks,
- // execute them in top down order
- const osg::NodePath& np = hi->getNodePath();
+ // just compute intersections in the viewers method ...
+ typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
+ Intersections intersections;
+ viewer->computeIntersections(ea->getX(), ea->getY(), intersections);
+
+ Intersections::iterator hit;
+ for (hit = intersections.begin(); hit != intersections.end(); ++hit) {
+ const osg::NodePath& np = hit->nodePath;
osg::NodePath::const_reverse_iterator npi;
for (npi = np.rbegin(); npi != np.rend(); ++npi) {
SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
if (!pickCallback)
continue;
SGSceneryPick sceneryPick;
- /// note that this is done totally in doubles instead of
- /// just using getWorldIntersectionPoint
- osg::Vec3d localPt = hi->getLocalIntersectPoint();
- sceneryPick.info.local = SGVec3d(localPt);
- if (hi->getMatrix())
- sceneryPick.info.wgs84 = SGVec3d(localPt*(*hi->getMatrix()));
- else
- sceneryPick.info.wgs84 = SGVec3d(localPt);
+ sceneryPick.info.local = SGVec3d(hit->getLocalIntersectPoint());
+ sceneryPick.info.wgs84 = SGVec3d(hit->getWorldIntersectPoint());
sceneryPick.callback = pickCallback;
pickList.push_back(sceneryPick);
}
}
}
- }
- return !pickList.empty();
+ return !pickList.empty();
+ } else { // we can get called early ...
+ return false;
+ }
}
bool fgDumpSceneGraphToFile(const char* filename)
/** Just pick into the scene and return the pick callbacks on the way ...
*/
static bool pick( unsigned x, unsigned y,
- std::vector<SGSceneryPick>& pickList );
+ std::vector<SGSceneryPick>& pickList,
+ const osgGA::GUIEventAdapter* ea );
/** Get and set the OSG Viewer object, if any.
*/