osgEarth::TrackNode How to change the Image dynamically

As of osgEarth version 2.9 you can not change the Image the TrackNode displays without subclassing and implementing additional logic.

The following is the approach I have taken:
void MyTrackNode::changeImage(osg::ref_ptr<osg::Image> image)
{
    osgEarth::IconSymbol* icon = _style.getOrCreateSymbol<osgEarth::IconSymbol>();
    icon->setImage(image);
    osg::Image* iconImage = icon ? icon->getImage() : 0L;
    if ( icon && iconImage )
    {
        osg::Drawable *oldDrawable = reinterpret_cast<osg::Geometry*>(_geode->getDrawable( 0 ));
        if (nullptr != oldDrawable)
        {
            for (auto drawable : _namedDrawables)
            {
                if (drawable.second == oldDrawable)
                {
                    oldDrawable = nullptr;
                }
            }
        }
        if (oldDrawable == nullptr)
        {
            oldDrawable = getDrawable("track_icon");
        }

        // apply the image icon.
        osg::Geometry* imageGeom = osgEarth::Annotation::AnnotationUtils::createImageGeometry(
            iconImage,                    // image
            osg::Vec2s(0,0),          // offset
            0,                        // tex image unit
            icon->heading()->eval(),
            icon->scale()->eval() );
        if ( imageGeom )
        {
            if (nullptr == oldDrawable)
            {
                addDrawable( "track_icon", imageGeom);
            }
            else
            {
                _geode->replaceDrawable( oldDrawable, imageGeom );
            }

            ScreenSpaceLayoutData* layout = new ScreenSpaceLayoutData();
            layout->setPriority(getPriority());
            imageGeom->setUserData(layout);

            // generate shaders:
             Registry::shaderGenerator().run(
                 this,
                 "osgEarth.TrackNode",
                 Registry::stateSetCache() );

        }
    }
}


The assumption is that the first drawable on the _geode is the image geometry. There is some sanity checking performed in case there is no image geometry. The sanity checking is not 100%.

No attempt is made to modify the image geometry because of the complexity of the setup. You could keep a reference to the geometry we are replacing so that we can swap it back in.

The shaders have to be regenerated.

Ideally the TrackNode should be re-written to allow changing an Image without so much setup.

Because of the complexity of the setup this is not an operation that should be performed frequently. I am using this to indicate that a TrackNode has been selected.

My tracks are normally red. When a track is selected I change the Icon/Image to bright green.


Map data is (c) Open Street Map contributors.

Comments