예제 #1
0
파일: TileNode.cpp 프로젝트: caomw/osgearth
void
TileNode::create(const TileKey& key, EngineContext* context)
{
    _key = key;

    // Create mask records
    osg::ref_ptr<MaskGenerator> masks = context ? new MaskGenerator(key, context->getOptions().tileSize().get(), context->getMapFrame()) : 0L;

    // Get a shared geometry from the pool that corresponds to this tile key:
    osg::ref_ptr<osg::Geometry> geom;
    context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom, masks.get());


    // Create the drawable for the terrain surface:
    TileDrawable* surfaceDrawable = new TileDrawable(
        key, 
        context->getRenderBindings(), 
        geom.get(),
        context->getOptions().tileSize().get(),
        context->getGeometryPool()->getNumSkirtElements() );

    surfaceDrawable->setDrawAsPatches(false);

    // Create the node to house the tile drawable:
    _surface = new SurfaceNode(
        key,
        context->getMapFrame().getMapInfo(),
        context->getRenderBindings(),
        surfaceDrawable );

    //_surface->setNodeMask( OSGEARTH_MASK_TERRAIN_SURFACE );
    
    // Slot it into the proper render bin:
    //osg::StateSet* surfaceSS = _surface->getOrCreateStateSet();
    //surfaceSS->setRenderBinDetails(0, "oe.SurfaceBin");
    //surfaceSS->setNestRenderBins(false);

    // Create a drawable for land cover geometry.
    // Land cover will be rendered as patch data instead of triangles.
    TileDrawable* patchDrawable = new TileDrawable(
        key, 
        context->getRenderBindings(),
        geom.get(),
        context->getOptions().tileSize().get(),
        context->getGeometryPool()->getNumSkirtElements() );
    
    patchDrawable->setDrawAsPatches(true);

    // And a node to house that as well:
    _landCover = new SurfaceNode(
        key,
        context->getMapFrame().getMapInfo(),
        context->getRenderBindings(),
        patchDrawable );

    //_landCover->setNodeMask( OSGEARTH_MASK_TERRAIN_LAND_COVER );

    // PPP: Better way to do this rather than here?
    // Can't do it at RexTerrainEngineNode level, because the SurfaceNode is not valid yet
    if (context->getSelectionInfo().initialized()==false)
    {
        static Threading::Mutex s_selInfoMutex;
        Threading::ScopedMutexLock lock(s_selInfoMutex);
        if ( context->getSelectionInfo().initialized()==false)
        {
            SelectionInfo& selectionInfo = const_cast<SelectionInfo&>(context->getSelectionInfo());

            unsigned uiFirstLOD = *(context->_options.firstLOD());
            unsigned uiMaxLod   = std::min( context->_options.maxLOD().get(), 19u ); // beyond LOD 19 or 20, morphing starts to lose precision.
            unsigned uiTileSize = *(context->_options.tileSize());

            selectionInfo.initialize(uiFirstLOD, uiMaxLod, uiTileSize, getVisibilityRangeHint(context)); //uiFirstLOD));
        }
    }

    // initialize all the per-tile uniforms the shaders will need:
    createTileUniforms();
    updateTileUniforms(context->getSelectionInfo());

    // Set up a data container for multipass layer rendering:
    _mptex = new MPTexture();
    surfaceDrawable->setMPTexture( _mptex.get() );

    // need to recompute the bounds after adding payload:
    dirtyBound();

    // signal the tile to start loading data:
    setDirty( true );

    // register me.
    context->liveTiles()->add( this );
}
예제 #2
0
void
TileNode::create(const TileKey& key, TileNode* parent, EngineContext* context)
{
    if (!context)
        return;

    _context = context;

    _key = key;

    // Mask generator creates geometry from masking boundaries when they exist.
    osg::ref_ptr<MaskGenerator> masks = new MaskGenerator(
        key, 
        context->getOptions().tileSize().get(),
        context->getMap());

    MapInfo mapInfo(context->getMap());

    // Get a shared geometry from the pool that corresponds to this tile key:
    osg::ref_ptr<SharedGeometry> geom;
    context->getGeometryPool()->getPooledGeometry(
        key,
        mapInfo,         
        context->getOptions().tileSize().get(),
        masks.get(), 
        geom);

    // If we donget an empty, that most likely means the tile was completely
    // contained by a masking boundary. Mark as empty and we are done.
    if (geom->empty())
    {
        OE_DEBUG << LC << "Tile " << _key.str() << " is empty.\n";
        _empty = true;
        return;
    }

    // Create the drawable for the terrain surface:
    TileDrawable* surfaceDrawable = new TileDrawable(
        key, 
        geom.get(),
        context->getOptions().tileSize().get() );

    // Give the tile Drawable access to the render model so it can properly
    // calculate its bounding box and sphere.
    surfaceDrawable->setModifyBBoxCallback(context->getModifyBBoxCallback());

    // Create the node to house the tile drawable:
    _surface = new SurfaceNode(
        key,
        mapInfo,
        context->getRenderBindings(),
        surfaceDrawable );
    
    // create a data load request for this new tile:
    _loadRequest = new LoadTileData( this, context );
    _loadRequest->setName( _key.str() );
    _loadRequest->setTileKey( _key );

    // whether the stitch together normal maps for adjacent tiles.
    _stitchNormalMap = context->_options.normalizeEdges() == true;

    // Encode the tile key in a uniform. Note! The X and Y components are presented
    // modulo 2^16 form so they don't overrun single-precision space.
    unsigned tw, th;
    _key.getProfile()->getNumTiles(_key.getLOD(), tw, th);

    const double m = 65536; //pow(2.0, 16.0);

    double x = (double)_key.getTileX();
    double y = (double)(th - _key.getTileY()-1);

    _tileKeyValue.set(
        (float)fmod(x, m),
        (float)fmod(y, m),
        (float)_key.getLOD(),
        -1.0f);

    // initialize all the per-tile uniforms the shaders will need:
    float start = (float)context->getSelectionInfo().visParameters(_key.getLOD())._fMorphStart;
    float end   = (float)context->getSelectionInfo().visParameters(_key.getLOD())._fMorphEnd;
    float one_by_end_minus_start = end - start;
    one_by_end_minus_start = 1.0f/one_by_end_minus_start;
    _morphConstants.set( end * one_by_end_minus_start, one_by_end_minus_start );

    // Initialize the data model by copying the parent's rendering data
    // and scale/biasing the matrices.
    if (parent)
    {
        unsigned quadrant = getKey().getQuadrant();

        const RenderBindings& bindings = context->getRenderBindings();

        bool setElevation = false;

        for (unsigned p = 0; p < parent->_renderModel._passes.size(); ++p)
        {
            const RenderingPass& parentPass = parent->_renderModel._passes[p];

            // Copy the parent pass:
            _renderModel._passes.push_back(parentPass);
            RenderingPass& myPass = _renderModel._passes.back();

            // Scale/bias each matrix for this key quadrant.
            Samplers& samplers = myPass.samplers();
            for (unsigned s = 0; s < samplers.size(); ++s)
            {
                samplers[s]._matrix.preMult(scaleBias[quadrant]);
            }

            // Are we using image blending? If so, initialize the color_parent 
            // to the color texture.
            if (bindings[SamplerBinding::COLOR_PARENT].isActive())
            {
                samplers[SamplerBinding::COLOR_PARENT] = samplers[SamplerBinding::COLOR];
            }
        }

        // Copy the parent's shared samplers and scale+bias each matrix to the new quadrant:
        _renderModel._sharedSamplers = parent->_renderModel._sharedSamplers;

        for (unsigned s = 0; s<_renderModel._sharedSamplers.size(); ++s)
        {
            Sampler& sampler = _renderModel._sharedSamplers[s];
            sampler._matrix.preMult(scaleBias[quadrant]);
        }

        // Use the elevation sampler to initialize the elevation raster
        // (used for primitive functors, intersection, etc.)
        if (!setElevation && bindings[SamplerBinding::ELEVATION].isActive())
        {
            const Sampler& elevation = _renderModel._sharedSamplers[SamplerBinding::ELEVATION];
            if (elevation._texture.valid())
            {
                setElevationRaster(elevation._texture->getImage(0), elevation._matrix);
                setElevation = true;
            }
        }
    }

    // need to recompute the bounds after adding payload:
    dirtyBound();

    // signal the tile to start loading data:
    setDirty( true );

    // register me.
    context->liveTiles()->add( this );

    // tell the world.
    OE_DEBUG << LC << "notify (create) key " << getKey().str() << std::endl;
    context->getEngine()->getTerrain()->notifyTileAdded(getKey(), this);
}
예제 #3
0
void
TileNode::create(const TileKey& key, EngineContext* context)
{
    if (!context)
        return;

    _key = key;

    // Create mask records
    osg::ref_ptr<MaskGenerator> masks = new MaskGenerator(key, context->getOptions().tileSize().get(), context->getMapFrame());

    // Get a shared geometry from the pool that corresponds to this tile key:
    osg::ref_ptr<osg::Geometry> geom;
    context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom, masks.get());


    // Create the drawable for the terrain surface:
    TileDrawable* surfaceDrawable = new TileDrawable(
        key, 
        context->getRenderBindings(), 
        geom.get(),
        context->getOptions().tileSize().get(),
        context->getGeometryPool()->getNumSkirtElements() );

    surfaceDrawable->setDrawAsPatches(false);

    // Create the node to house the tile drawable:
    _surface = new SurfaceNode(
        key,
        context->getMapFrame().getMapInfo(),
        context->getRenderBindings(),
        surfaceDrawable );

    // Create a drawable for "patch" geometry, which is rendered as GL patches, not triangles.
    // Patch geometry can be used to place land cover or render other tile-specific data.
    TileDrawable* patchDrawable = new TileDrawable(
        key, 
        context->getRenderBindings(),
        geom.get(),
        context->getOptions().tileSize().get(),
        context->getGeometryPool()->getNumSkirtElements() );
    
    patchDrawable->setDrawAsPatches(true);

    // And a node to house that as well:
    _patch = new SurfaceNode(
        key,
        context->getMapFrame().getMapInfo(),
        context->getRenderBindings(),
        patchDrawable );

    // initialize all the per-tile uniforms the shaders will need:
    createPayloadStateSet(context);

    updateTileUniforms(context->getSelectionInfo());

    // Set up a data container for multipass layer rendering:
    _mptex = new MPTexture();
    surfaceDrawable->setMPTexture( _mptex.get() );

    // need to recompute the bounds after adding payload:
    dirtyBound();

    // signal the tile to start loading data:
    setDirty( true );

    // register me.
    context->liveTiles()->add( this );
}
예제 #4
0
void
TileNode::create(const TileKey& key, EngineContext* context)
{
    _key = key;

    // Get a shared geometry from the pool that corresponds to this tile key:
    osg::ref_ptr<osg::Geometry> geom;
    context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom);

    // Create the drawable for the terrain surface:
    TileDrawable* surfaceDrawable = new TileDrawable(
        key, 
        context->getRenderBindings(), 
        geom.get(),
        context->getOptions().tileSize().get() );

    surfaceDrawable->setDrawAsPatches(false);

    // Create the node to house the tile drawable:
    _surface = new SurfaceNode(
        key,
        context->getMapFrame().getMapInfo(),
        context->getRenderBindings(),
        surfaceDrawable );
    
    // Slot it into the proper render bin:
    osg::StateSet* surfaceSS = _surface->getOrCreateStateSet();
    surfaceSS->setRenderBinDetails(0, "oe.SurfaceBin");
    surfaceSS->setNestRenderBins(false);

    // Create a drawable for land cover geometry.
    // Land cover will be rendered as patch data instead of triangles.
    TileDrawable* patchDrawable = new TileDrawable(
        key, 
        context->getRenderBindings(),
        geom.get(),
        context->getOptions().tileSize().get() );

    patchDrawable->setDrawAsPatches(true);

    // And a node to house that as well:
    _landCover = new SurfaceNode(
        key,
        context->getMapFrame().getMapInfo(),
        context->getRenderBindings(),
        patchDrawable );

    // PPP: Better way to do this rather than here?
    // Can't do it at RexTerrainEngineNode level, because the SurfaceNode is not valid yet
    if (context->getSelectionInfo().initialized()==false)
    {
        SelectionInfo& selectionInfo = const_cast<SelectionInfo&>(context->getSelectionInfo());

        unsigned uiFirstLOD = *(context->_options.firstLOD());
        unsigned uiMaxLod   = *(context->_options.maxLOD());
        unsigned uiTileSize = *(context->_options.tileSize());

        selectionInfo.initialize(uiFirstLOD, uiMaxLod, uiTileSize, getVisibilityRangeHint(uiFirstLOD));
    }

    // initialize all the per-tile uniforms the shaders will need:
    createTileUniforms();
    updateTileUniforms(context->getSelectionInfo());

    // Set up a data container for multipass layer rendering:
    _mptex = new MPTexture();
    surfaceDrawable->setMPTexture( _mptex.get() );

    // need to recompute the bounds after adding payload:
    dirtyBound();

    // signal the tile to start loading data:
    setDirty( true );

    // register me.
    context->liveTiles()->add( this );
}
예제 #5
0
void
TileNode::create(const TileKey& key, EngineContext* context)
{
    if (!context)
        return;

    _key = key;

    // Create mask records
    osg::ref_ptr<MaskGenerator> masks = new MaskGenerator(key, context->getOptions().tileSize().get(), context->getMapFrame());

    // Get a shared geometry from the pool that corresponds to this tile key:
    osg::ref_ptr<osg::Geometry> geom;
    context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom, masks.get());


    // Create the drawable for the terrain surface:
    TileDrawable* surfaceDrawable = new TileDrawable(
        key, 
        context->getRenderBindings(), 
        geom.get(),
        context->getOptions().tileSize().get(),
        context->getGeometryPool()->getNumSkirtElements() );

    surfaceDrawable->setDrawAsPatches(false);

    // Create the node to house the tile drawable:
    _surface = new SurfaceNode(
        key,
        context->getMapFrame().getMapInfo(),
        context->getRenderBindings(),
        surfaceDrawable );

    // Create a drawable for "patch" geometry, which is rendered as GL patches, not triangles.
    // Patch geometry can be used to place land cover or render other tile-specific data.
    TileDrawable* patchDrawable = new TileDrawable(
        key, 
        context->getRenderBindings(),
        geom.get(),
        context->getOptions().tileSize().get(),
        context->getGeometryPool()->getNumSkirtElements() );
    
    patchDrawable->setDrawAsPatches(true);

    // And a node to house that as well:
    _patch = new SurfaceNode(
        key,
        context->getMapFrame().getMapInfo(),
        context->getRenderBindings(),
        patchDrawable );

    // PPP: Better way to do this rather than here?
    // Can't do it at RexTerrainEngineNode level, because the SurfaceNode is not valid yet
    if (context->getSelectionInfo().initialized()==false)
    {
        static Threading::Mutex s_selInfoMutex;
        Threading::ScopedMutexLock lock(s_selInfoMutex);
        if ( context->getSelectionInfo().initialized()==false)
        {
            SelectionInfo& selectionInfo = const_cast<SelectionInfo&>(context->getSelectionInfo());

            unsigned uiFirstLOD = *(context->_options.firstLOD());
            unsigned uiMaxLod   = std::min( context->_options.maxLOD().get(), 19u ); // beyond LOD 19 or 20, morphing starts to lose precision.
            unsigned uiTileSize = *(context->_options.tileSize());

            selectionInfo.initialize(uiFirstLOD, uiMaxLod, uiTileSize, getVisibilityRangeHint(context));
        }
    }

    // initialize all the per-tile uniforms the shaders will need:
    createPayloadStateSet(context);

    updateTileUniforms(context->getSelectionInfo());

    // Set up a data container for multipass layer rendering:
    _mptex = new MPTexture();
    surfaceDrawable->setMPTexture( _mptex.get() );

    // need to recompute the bounds after adding payload:
    dirtyBound();

    // signal the tile to start loading data:
    setDirty( true );

    // register me.
    context->liveTiles()->add( this );
}