Simple object picking with OpenSceneGraph

Tags: programming, projects, software

Published on
« Previous post: Rectangular selections with Qt and … — Next post: Markov chains for Christmas »

As an extension to my previous post on rectangular selections with Qt and OpenScenegraph, I just updated the example project with a very simple pick handler. A pick handler is a simple event handler that permits picking, i.e. selecting objects in a scene.

Doing it manually

The basic implementation is straightforward. We first inherit from the base class osgGA::GUIEventHandler and provide our own implementation of the handle() function. In this function, we use a line segment intersector class to determine intersections within the window:

bool PickHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{
  if( ea.getEventType() != osgGA::GUIEventAdapter::RELEASE &&
      ea.getButton()    != osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON )
  {
    return false;
  }

  osgViewer::View* viewer = dynamic_cast<osgViewer::View*>( &aa );

  if( viewer )
  {
    osgUtil::LineSegmentIntersector* intersector
        = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::WINDOW, ea.getX(), ea.getY() );

    osgUtil::IntersectionVisitor iv( intersector );

    osg::Camera* camera = viewer->getCamera();
    if( !camera )
      return false;

    camera->accept( iv );

    if( !intersector->containsIntersections() )
      return false;

    auto intersections = intersector->getIntersections();

    std::cout << "Got " << intersections.size() << " intersections:\n";

    for( auto&& intersection : intersections )
      std::cout << "  - Local intersection point = " << intersection.localIntersectionPoint << "\n";
  }

  return true;
}

The localIntersectionPoint variable contains the intersection point in local coordinates. It is also possible to obtain the intersection point in world coordinates by calling the getWorldIntersectPoint() function of the intersection.

A shortcut

Instead of setting up our own line segment intersector, we could also call the osgViewer::View::computeIntersections of our view. This involves a dynamic cast in the handle function. The way outlined above is for instructive purposes only.

Code

As always, the code is available in a git repository.