Example #1
0
void
MPTerrainEngineNode::traverse(osg::NodeVisitor& nv)
{
    if ( nv.getVisitorType() == nv.CULL_VISITOR )
    {
        // since the root tiles are manually added, the pager never has a change to 
        // register the PagedLODs in their children. So we have to do it manually here.
        if ( !_rootTilesRegistered )
        {
            Threading::ScopedMutexLock lock(_rootTilesRegisteredMutex);

            if ( !_rootTilesRegistered )
            {
                osgDB::DatabasePager* pager = dynamic_cast<osgDB::DatabasePager*>(nv.getDatabaseRequestHandler());
                if ( pager )
                {
                    //OE_WARN << "Registering plods." << std::endl;
                    pager->registerPagedLODs( _terrain );
                    _rootTilesRegistered = true;
                }
            }
        }
    }

#if 0
    static int c = 0;
    if ( ++c % 60 == 0 )
        OE_NOTICE << LC << "Live tiles = " << _liveTiles->size() << std::endl;
#endif

    TerrainEngineNode::traverse( nv );
}
void
MPTerrainEngineNode::traverse(osg::NodeVisitor& nv)
{
    if ( nv.getVisitorType() == nv.CULL_VISITOR )
    {

#if 0 // believe this is now unnecessary

        // since the root tiles are manually added, the pager never has a chance to 
        // register the PagedLODs in their children. So we have to do it manually here.
        if ( !_rootTilesRegistered )
        {
            Threading::ScopedMutexLock lock(_rootTilesRegisteredMutex);

            if ( !_rootTilesRegistered )
            {
                osgDB::DatabasePager* pager = dynamic_cast<osgDB::DatabasePager*>(nv.getDatabaseRequestHandler());
                if ( pager )
                {
                    //OE_WARN << "Registering plods." << std::endl;
                    pager->registerPagedLODs( _terrain );
                    _rootTilesRegistered = true;
                }
            }
        }
#endif

        // Inform the registry of the current frame so that Tiles have access
        // to the information.
        if ( _liveTiles.valid() && nv.getFrameStamp() )
        {
            _liveTiles->setTraversalFrame( nv.getFrameStamp()->getFrameNumber() );
        }
    }

#if 0
    static int c = 0;
    if ( ++c % 60 == 0 )
    {
        OE_NOTICE << LC << "Live = " << _liveTiles->size() << ", Dead = " << _deadTiles->size() << std::endl;
        _liveTiles->run( CheckForOrphans() );
    }
#endif

    TerrainEngineNode::traverse( nv );
}
Example #3
0
bool
PagerLoader::load(Loader::Request* request, float priority, osg::NodeVisitor& nv)
{
    // check that the request is not already completed but unmerged:
    //if ( request && !request->isMerging() && nv.getDatabaseRequestHandler() )
    if ( request && !request->isMerging() && !request->isFinished() && nv.getDatabaseRequestHandler() )
    {
        //OE_INFO << LC << "load (" << request->getTileKey().str() << ")" << std::endl;

        unsigned fn = 0;
        if ( nv.getFrameStamp() )
        {
            fn = nv.getFrameStamp()->getFrameNumber();
            request->setFrameNumber( fn );
        }

        bool addToRequestSet = false;

        // lock the request since multiple cull traversals might hit this function.
        request->lock();
        {
            request->setState(Request::RUNNING);

            // remember the last tick at which this request was submitted
            request->_lastTick = osg::Timer::instance()->tick();

            // update the priority
            request->_priority = priority;

            // timestamp it
            request->setFrameNumber( fn );

            // incremenet the load count.
            request->_loadCount++;

            // if this is the first load request since idle, we need to remember this request.
            addToRequestSet = (request->_loadCount == 1);
        }
        request->unlock();

        char filename[64];
        sprintf(filename, "%u.%u.osgearth_rex_loader", request->_uid, _engineUID);
        //std::string filename = Stringify() << request->_uid << "." << _engineUID << ".osgearth_rex_loader";

        // scale from LOD to 0..1 range, more or less
        // TODO: need to balance this with normal PagedLOD priority setup
        float scaledPriority = priority / 20.0f;

        nv.getDatabaseRequestHandler()->requestNodeFile(
            filename,
            _myNodePath,
            priority,
            nv.getFrameStamp(),
            request->_internalHandle,
            _dboptions.get() );

        // remember the request:
        if ( true ) // addToRequestSet // Not sure whether we need to keep doing this in order keep it sorted -- check it out.
        {
            Threading::ScopedMutexLock lock( _requestsMutex );
            _requests[request->getUID()] = request;
        }

        return true;
    }
    return false;
}
// MOST of this is copied and pasted from OSG's osg::PagedLOD::traverse,
// except where otherwise noted with an "osgEarth" comment.
void
TilePagedLOD::traverse(osg::NodeVisitor& nv)
{
    // set the frame number of the traversal so that external nodes can find out how active this
    // node is.
    if (nv.getFrameStamp() &&
        nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
    {
        setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber());
        
        // osgEarth: update our progress tracker to prevent tile cancelation.
        if (_progress.valid())
        {
            _progress->update( nv.getFrameStamp()->getFrameNumber() );
        }
    }

    double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
    unsigned int frameNumber = nv.getFrameStamp()?nv.getFrameStamp()->getFrameNumber():0;
    bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;

    switch(nv.getTraversalMode())
    {
    case(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN):
            std::for_each(_children.begin(),_children.end(),osg::NodeAcceptOp(nv));
            break;
        case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
        {
            osg::ref_ptr<MPTerrainEngineNode> engine;
            MPTerrainEngineNode::getEngineByUID( _engineUID, engine );
            if (!engine.valid())
                return;

            // Compute the required range.
            float required_range = -1.0;
            if (engine->getComputeRangeCallback())
            {                
                required_range = (*engine->getComputeRangeCallback())(this, nv);
            }            

            // If we don't have a callback or it return a negative number fallback on the original calculation.
            if (required_range < 0.0)
            {
                if (_rangeMode==DISTANCE_FROM_EYE_POINT)
                {
                    required_range = nv.getDistanceToViewPoint(getCenter(),true);

                    if (_rangeFactor.isSet())
                        required_range /= _rangeFactor.get();
                }
                else
                {
                    osg::CullStack* cullStack = dynamic_cast<osg::CullStack*>(&nv);
                    if (cullStack && cullStack->getLODScale()>0.0f)
                    {
                        required_range = cullStack->clampedPixelSize(getBound()) / cullStack->getLODScale();
                    }
                    else
                    {
                        // fallback to selecting the highest res tile by
                        // finding out the max range
                        for(unsigned int i=0;i<_rangeList.size();++i)
                        {
                            required_range = osg::maximum(required_range,_rangeList[i].first);
                        }
                    }
                }
            }

            int lastChildTraversed = -1;
            bool needToLoadChild = false;
            for(unsigned int i=0;i<_rangeList.size();++i)
            {
                if (_rangeList[i].first<=required_range && required_range<_rangeList[i].second)
                {
                    if (i<_children.size())
                    {
                        if (updateTimeStamp)
                        {
                            _perRangeDataList[i]._timeStamp=timeStamp;
                            _perRangeDataList[i]._frameNumber=frameNumber;
                        }

                        _children[i]->accept(nv);
                        lastChildTraversed = (int)i;
                    }
                    else
                    {
                        needToLoadChild = true;
                    }
                }
            }

#ifdef INHERIT_VIEWPOINT_CAMERAS_CANNOT_SUBDIVIDE
            // Prevents an INHERIT_VIEWPOINT camera from invoking tile subdivision
            if (needToLoadChild)
            {
                osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
                if ( cv && cv->getCurrentCamera() && cv->getCurrentCamera()->getReferenceFrame() == osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT )
                    needToLoadChild = false;
            }
#endif

            if (needToLoadChild)
            {
                unsigned int numChildren = _children.size();

                // select the last valid child.
                if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
                {
                    if (updateTimeStamp)
                    {
                        _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
                        _perRangeDataList[numChildren-1]._frameNumber=frameNumber;
                    }
                    _children[numChildren-1]->accept(nv);
                }

                // now request the loading of the next unloaded child.
                if (!_disableExternalChildrenPaging &&
                    nv.getDatabaseRequestHandler() &&
                    numChildren<_perRangeDataList.size())
                {
                    // osgEarth: Perform a tile visibility check before requesting the new tile.
                    // Intersect the tile's earth-aligned bounding box with the current culling frustum.
                    bool tileIsVisible = true;

                    if (nv.getVisitorType() == nv.CULL_VISITOR &&
                        numChildren < _childBBoxes.size() &&
                        _childBBoxes[numChildren].valid())
                    {
                        osgUtil::CullVisitor* cv = Culling::asCullVisitor( nv );
                        // wish that CullStack::createOrReuseRefMatrix() was public
                        osg::ref_ptr<osg::RefMatrix> mvm = new osg::RefMatrix(*cv->getModelViewMatrix());
                        mvm->preMult( _childBBoxMatrices[numChildren] );
                        cv->pushModelViewMatrix( mvm.get(), osg::Transform::RELATIVE_RF );
                        tileIsVisible = !cv->isCulled( _childBBoxes[numChildren] );
                        cv->popModelViewMatrix();
                    }

                    if ( tileIsVisible )
                    {
                        // [end:osgEarth]

                        // compute priority from where abouts in the required range the distance falls.
                        float priority = (_rangeList[numChildren].second-required_range)/(_rangeList[numChildren].second-_rangeList[numChildren].first);

                        // invert priority for PIXEL_SIZE_ON_SCREEN mode
                        if(_rangeMode==PIXEL_SIZE_ON_SCREEN)
                        {
                            priority = -priority;
                        }

                        // modify the priority according to the child's priority offset and scale.
                        priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale;

                        if (_databasePath.empty())
                        {
                            nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,nv.getNodePath(),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get());
                        }
                        else
                        {
                            // prepend the databasePath to the child's filename.
                            nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_perRangeDataList[numChildren]._filename,nv.getNodePath(),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get());
                        }
                    }
                }
            }

           break;
        }
        default:
            break;
    }
}
Example #5
0
void
RexTerrainEngineNode::traverse(osg::NodeVisitor& nv)
{
    if ( nv.getVisitorType() == nv.CULL_VISITOR )
    {
        // Inform the registry of the current frame so that Tiles have access
        // to the information.
        if ( _liveTiles.valid() && nv.getFrameStamp() )
        {
            _liveTiles->setTraversalFrame( nv.getFrameStamp()->getFrameNumber() );
        }
    }

#if 0
    static int c = 0;
    if ( ++c % 60 == 0 )
    {
        OE_NOTICE << LC << "Live = " << _liveTiles->size() << ", Dead = " << _deadTiles->size() << std::endl;
        _liveTiles->run( CheckForOrphans() );
    }
#endif
    
    if ( nv.getVisitorType() == nv.CULL_VISITOR && _loader.valid() ) // ensures that postInitialize has run
    {
        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);

        this->getEngineContext()->startCull( cv );
        
        TerrainCuller culler;
        culler.setFrameStamp(new osg::FrameStamp(*nv.getFrameStamp()));
        culler.setDatabaseRequestHandler(nv.getDatabaseRequestHandler());
        culler.pushReferenceViewPoint(cv->getReferenceViewPoint());
        culler.pushViewport(cv->getViewport());
        culler.pushProjectionMatrix(cv->getProjectionMatrix());
        culler.pushModelViewMatrix(cv->getModelViewMatrix(), cv->getCurrentCamera()->getReferenceFrame());
        culler._camera = cv->getCurrentCamera();
        culler._context = this->getEngineContext();
        culler.setup(*_update_mapf, this->getEngineContext()->getRenderBindings(), getSurfaceStateSet());

        // Assemble the terrain drawable:
        _terrain->accept(culler);

        // If we're using geometry pooling, optimize the drawable for shared state:
        if (getEngineContext()->getGeometryPool()->isEnabled())
        {
            culler._terrain.sortDrawCommands();
        }

        // The common stateset for the terrain:
        cv->pushStateSet(_terrain->getOrCreateStateSet());

        // Push all the layers to draw on to the cull visitor,
        // keeping track of render order.
        LayerDrawable* lastLayer = 0L;
        unsigned order = 0;
        bool surfaceStateSetPushed = false;

//        OE_INFO << "CULL:\n";

        for(LayerDrawableList::iterator i = culler._terrain.layers().begin();
            i != culler._terrain.layers().end();
            ++i)
        {
            if (!i->get()->_tiles.empty())
            {
                lastLayer = i->get();
                lastLayer->_order = -1;

                // if this is a RENDERTYPE_TILE, we need to activate the default surface state set.
                if (lastLayer->_layer && lastLayer->_layer->getRenderType() == Layer::RENDERTYPE_TILE)
                {
                    lastLayer->_order = order++;

                    if (!surfaceStateSetPushed)
                        cv->pushStateSet(getSurfaceStateSet());
                    surfaceStateSetPushed = true;
                }
                else if (surfaceStateSetPushed)
                {
                    cv->popStateSet();
                    surfaceStateSetPushed = false;
                }                    

//                OE_INFO << "   Apply: " << (lastLayer->_layer ? lastLayer->_layer->getName() : "-1") << std::endl;

                cv->apply(*lastLayer);
            }
        }

        // The last layer to render must clear up the OSG state,
        // otherwise it will be corrupt and can lead to crashing.
        if (lastLayer)
        {
            lastLayer->_clearOsgState = true;
        }
                
        if (surfaceStateSetPushed)
        {
            cv->popStateSet();
            surfaceStateSetPushed = false;
        }

        // pop the common terrain state set
        cv->popStateSet();

        this->getEngineContext()->endCull( cv );

        // traverse all the other children (geometry pool, loader/unloader, etc.)
        for (unsigned i = 0; i<getNumChildren(); ++i)
        {
            if (getChild(i) != _terrain.get())
                getChild(i)->accept(nv);
        }
    }

    //else
    {
        TerrainEngineNode::traverse( nv );
    }
}
Example #6
0
void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
{

    //TileMapper* tileMapper = dynamic_cast<TileMapper*>(nv.getUserData());
    //Modified by Brad Anderegg (May-27-08) because the black listing process appears to make tiles switch lods
    //when they clearly shouldnt, in the worst cases a tile will page out that is right in front of you.
    bool forceUseOfFirstChild = /*tileMapper ? (tileMapper->isNodeBlackListed(this)) :*/ false;

    double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
    bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;
    unsigned int frameNumber = nv.getFrameStamp()?nv.getFrameStamp()->getFrameNumber():0;

    // set the frame number of the traversal so that external nodes can find out how active this
    // node is.
    if (nv.getFrameStamp() &&
        nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
    {
        setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber());
    }

    switch(nv.getTraversalMode())
    {
        case(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN):
            std::for_each(_children.begin(),_children.end(),osg::NodeAcceptOp(nv));
            break;
        case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
        {
            float distance = nv.getDistanceToEyePoint(getCenter(),true);

            int lastChildTraversed = -1;
            bool needToLoadChild = false;

            unsigned maxRangeSize = _rangeList.size();
            if (maxRangeSize!=0 && forceUseOfFirstChild)
                maxRangeSize=1;

            for(unsigned int i=0;i<maxRangeSize;++i)
            {
                if (forceUseOfFirstChild ||
                    (_rangeList[i].first<=distance && distance<_rangeList[i].second))
                {
                    if (i<_children.size())
                    {
                        if (updateTimeStamp)
                        {
                            _perRangeDataList[i]._timeStamp=timeStamp;
                            _perRangeDataList[i]._frameNumber=frameNumber;
                        }

                        _children[i]->accept(nv);
                        lastChildTraversed = (int)i;
                    }
                    else
                    {
                        needToLoadChild = true;
                    }
                }
            }

            if (needToLoadChild)
            {
                unsigned int numChildren = _children.size();

                //std::cout<<"PagedLOD::traverse() - falling back "<<std::endl;
                // select the last valid child.
                if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
                {
                    //std::cout<<"    to child "<<numChildren-1<<std::endl;
                    if (updateTimeStamp)
                        _perRangeDataList[numChildren-1]._timeStamp=timeStamp;

                    _children[numChildren-1]->accept(nv);
                }

                // now request the loading of the next unload child.
                if (nv.getDatabaseRequestHandler() && numChildren<_perRangeDataList.size())
                {
                    // compute priority from where abouts in the required range the distance falls.
                    float priority = (_rangeList[numChildren].second-distance)/(_rangeList[numChildren].second-_rangeList[numChildren].first);

                    // modify the priority according to the child's priority offset and scale.
                    priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale;

                    //std::cout<<"    requesting child "<<_fileNameList[numChildren]<<" priotity = "<<priority<<std::endl;
                    nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,
                                                                    nv.getNodePath(),
                                                                    priority,
                                                                    nv.getFrameStamp(),
                                                                    _perRangeDataList[numChildren]._databaseRequest);
                }


            }


           break;
        }
        default:
            break;
    }
}
Example #7
0
void
RexTerrainEngineNode::traverse(osg::NodeVisitor& nv)
{
    if (nv.getVisitorType() == nv.UPDATE_VISITOR)
    {
        if (_renderModelUpdateRequired)
        {
            UpdateRenderModels visitor(_mapFrame);
            _terrain->accept(visitor);
            _renderModelUpdateRequired = false;
        }
        TerrainEngineNode::traverse( nv );
    }
    
    else if ( nv.getVisitorType() == nv.CULL_VISITOR )
    {
        // Inform the registry of the current frame so that Tiles have access
        // to the information.
        if ( _liveTiles.valid() && nv.getFrameStamp() )
        {
            _liveTiles->setTraversalFrame( nv.getFrameStamp()->getFrameNumber() );
        }

        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);

        getEngineContext()->startCull( cv );
        
        TerrainCuller culler;
        culler.setFrameStamp(new osg::FrameStamp(*nv.getFrameStamp()));
        culler.setDatabaseRequestHandler(nv.getDatabaseRequestHandler());
        culler.pushReferenceViewPoint(cv->getReferenceViewPoint());
        culler.pushViewport(cv->getViewport());
        culler.pushProjectionMatrix(cv->getProjectionMatrix());
        culler.pushModelViewMatrix(cv->getModelViewMatrix(), cv->getCurrentCamera()->getReferenceFrame());
        culler._camera = cv->getCurrentCamera();
        culler._context = this->getEngineContext();

        // Prepare the culler with the set of renderable layers:
        culler.setup(_mapFrame, this->getEngineContext()->getRenderBindings());

        // Assemble the terrain drawable:
        _terrain->accept(culler);

        // If we're using geometry pooling, optimize the drawable for shared state:
        if (getEngineContext()->getGeometryPool()->isEnabled())
        {
            culler._terrain.sortDrawCommands();
        }

        // The common stateset for the terrain:
        cv->pushStateSet(_terrain->getOrCreateStateSet());

        // Push all the layers to draw on to the cull visitor,
        // keeping track of render order.
        LayerDrawable* lastLayer = 0L;
        unsigned order = 0;
        bool surfaceStateSetPushed = false;

        //OE_INFO << "CULL\n";

        for(LayerDrawableList::iterator i = culler._terrain.layers().begin();
            i != culler._terrain.layers().end();
            ++i)
        {
            if (!i->get()->_tiles.empty())
            {
                lastLayer = i->get();
                lastLayer->_order = -1;

                // if this is a RENDERTYPE_TILE, we need to activate the default surface state set.
                if (lastLayer->_renderType == Layer::RENDERTYPE_TILE)
                {
                    lastLayer->_order = order++;

                    if (!surfaceStateSetPushed)
                        cv->pushStateSet(getSurfaceStateSet());
                    surfaceStateSetPushed = true;
                }
                else if (surfaceStateSetPushed)
                {
                    cv->popStateSet();
                    surfaceStateSetPushed = false;
                }                    

                //OE_INFO << "   Apply: " << (lastLayer->_layer ? lastLayer->_layer->getName() : "-1") << "; tiles=" << lastLayer->_tiles.size() << std::endl;

                cv->apply(*lastLayer);
            }
        }

        // The last layer to render must clear up the OSG state,
        // otherwise it will be corrupt and can lead to crashing.
        if (lastLayer)
        {
            lastLayer->_clearOsgState = true;
        }
                
        if (surfaceStateSetPushed)
        {
            cv->popStateSet();
            surfaceStateSetPushed = false;
        }

        // pop the common terrain state set
        cv->popStateSet();

        this->getEngineContext()->endCull( cv );

        // If the culler found any orphaned data, we need to update the render model
        // during the next update cycle.
        if (culler._orphanedPassesDetected > 0u)
        {
            _renderModelUpdateRequired = true;
            OE_INFO << LC << "Detected " << culler._orphanedPassesDetected << " orphaned rendering passes\n";
        }

        // we don't call this b/c we don't want _terrain
        //TerrainEngineNode::traverse(nv);

        // traverse all the other children (geometry pool, loader/unloader, etc.)
        _geometryPool->accept(nv);
        _loader->accept(nv);
        _unloader->accept(nv);
        _releaser->accept(nv);
        _rasterizer->accept(nv);
    }

    else
    {
        TerrainEngineNode::traverse( nv );
    }
}