void
TerrainEngineNode::setMap(const Map* map, const TerrainOptions& options)
{
    if (!map) return;

    _map = map;
    
    // Create a terrain utility interface. This interface can be used
    // to query the in-memory terrain graph, subscribe to tile events, etc.
    _terrainInterface = new Terrain( this, map->getProfile(), map->isGeocentric(), options );

    // Set up the CSN values. We support this because some manipulators look for it,
    // but osgEarth itself doesn't use it.
    _map->getProfile()->getSRS()->populateCoordinateSystemNode( this );
    
    // OSG's CSN likes a NULL ellipsoid to represent projected mode.
    if ( !_map->isGeocentric() )
        this->setEllipsoidModel( NULL );
    
    // Install an object to manage texture image unit usage:
    _textureResourceTracker = new TextureCompositor();
    std::set<int> offLimits = osgEarth::Registry::instance()->getOffLimitsTextureImageUnits();
    for(std::set<int>::const_iterator i = offLimits.begin(); i != offLimits.end(); ++i)
        _textureResourceTracker->setTextureImageUnitOffLimits( *i );

    // Register a callback so we can process further map model changes
    _map->addMapCallback( new TerrainEngineNodeCallbackProxy(this) );

    // Force a render bin if specified in the options
    if ( options.binNumber().isSet() )
    {
        osg::StateSet* set = getOrCreateStateSet();
        set->setRenderBinDetails( options.binNumber().get(), "RenderBin" );
    }
   
    // This is the object that creates the data model for each terrain tile.
    _tileModelFactory = new TerrainTileModelFactory(options);

    // Manually trigger the map callbacks the first time:
    if (_map->getProfile())
        onMapInfoEstablished(MapInfo(_map));

    // Create a layer controller. This object affects the uniforms
    // that control layer appearance properties
    _imageLayerController = new ImageLayerController(_map, this);

    // register the layer Controller it with all pre-existing image layers:
    MapFrame mapf(_map);
    ImageLayerVector imageLayers;
    mapf.getLayers(imageLayers);

    for (ImageLayerVector::const_iterator i = imageLayers.begin(); i != imageLayers.end(); ++i)
    {
        i->get()->addCallback(_imageLayerController.get());
    }

    _initStage = INIT_POSTINIT_COMPLETE;
}
void
TerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options )
{
    _map = map;
    
    // fire up a terrain utility interface
    _terrainInterface = new Terrain( this, map->getProfile(), map->isGeocentric(), options );

    // set up the CSN values   
    _map->getProfile()->getSRS()->populateCoordinateSystemNode( this );
    
    // OSG's CSN likes a NULL ellipsoid to represent projected mode.
    if ( !_map->isGeocentric() )
        this->setEllipsoidModel( NULL );
    
    // install an object to manage texture image unit usage:
    _texCompositor = new TextureCompositor();
    std::set<int> offLimits = osgEarth::Registry::instance()->getOffLimitsTextureImageUnits();
    for(std::set<int>::const_iterator i = offLimits.begin(); i != offLimits.end(); ++i)
        _texCompositor->setTextureImageUnitOffLimits( *i );

    // then register the callback so we can process further map model changes
    _map->addMapCallback( new TerrainEngineNodeCallbackProxy( this ) );

    // apply render bin if necessary
    if ( options.binNumber().isSet() )
    {
        osg::StateSet* set = getOrCreateStateSet();
        set->setRenderBinDetails( options.binNumber().get(), "RenderBin" );
    }

    if ( options.enableMercatorFastPath().isSet() )
    {
        OE_INFO 
            << LC << "Mercator fast path " 
            << (options.enableMercatorFastPath()==true? "enabled" : "DISABLED") << std::endl;
    }
    
    // a default factory - this is the object that creates the data model for
    // each terrain tile.
    _tileModelFactory = new TerrainTileModelFactory(options);

    _initStage = INIT_PREINIT_COMPLETE;
}