How to use the osgEarth::RTTPicker.

osgEarth documentation is a little light. The following code snippets show how to setup a node for picking via the RTTPicker.

The key to this is that each node that you wish to pick must be tagged. The method addPlaceNode() does this.

void addPlaceNode(osg::Group *labelGroup, PlaceNode *placeNode)
{
    // Tagging the placeNode makes it selectable by the RTT Picker
    auto objectId = osgEarth::Registry::objectIndex()->tagNode(placeNode, placeNode);
    placeNode->setUserValue("registryId", objectId);
    labelGroup->addChild( placeNode );
}
void placemarkers(osg::Group *labelGroup, osg::ref_ptr<osgEarth::MapNode> mapNode_)
{
    // A lat/long SRS for specifying points.
    const SpatialReference* geoSRS = mapNode_->getMapSRS()->getGeographicSRS();

    // A series of place nodes (an icon with a text label)
    Style pm;
    pm.getOrCreate<IconSymbol>()->url()->setLiteral( "../data/placemark32.png" );
    pm.getOrCreate<IconSymbol>()->declutter() = true;
    pm.getOrCreate<TextSymbol>()->halo() = Color("#5f5f5f");


    // bunch of pins:
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS, -74.00, 40.71),
                 "New York"      , pm));
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS, -77.04, 38.85),
                 "Washington, DC", pm));
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS,-118.40, 33.93),
                 "Los Angeles"   , pm));
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS, -71.03, 42.37),
                 "Boston"        , pm));
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS,-157.93, 21.35),
                 "Honolulu"      , pm));
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS, 139.75, 35.68),
                 "Tokyo"         , pm));
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS, -90.25, 29.98),
                 "New Orleans"   , pm));
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS, -80.28, 25.82), 
                 "Miami"         , pm));
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS,-117.17, 32.72), 
                 "San Diego"     , pm));


    // test with an LOD:
    osg::LOD* lod = new osg::LOD();
    auto placeNode = new PlaceNode(mapNode_, GeoPoint(geoSRS, 14.68, 50.0), "Prague",
                                   pm);
    auto objectId = osgEarth::Registry::objectIndex()->tagNode(placeNode, placeNode);
    placeNode->setUserValue("registryId", objectId);
    lod->addChild( placeNode, 0.0, 2e6);
    labelGroup->addChild( lod );


    // absolute altitude:
    addPlaceNode(labelGroup, new PlaceNode(mapNode_, GeoPoint(geoSRS, -87.65, 41.90,
                                           1000, ALTMODE_ABSOLUTE), "Chicago", pm));
}

In the main setup the above is called thus:

  // Make a group for labels
  osg::Group* labelGroup = new osg::Group();
  mapNode_->addChild( labelGroup );
  placemarkers(labelGroup, mapNode_);


The picker code is started:

   // start with a picker running
   startPicker();
   // Hightlight features as we pick'em.
   installHighlighter();

The picker code is from the osgearth_pick.cpp example (slightly reworked for my application).

Notes:
  • RTTPicker halves the framerate at best.
  • You can only pick one item at a time.
  • Not really for editing.



Comments