예제 #1
0
void
RexTerrainEngineNode::traverse(osg::NodeVisitor& nv)
{
    if ( nv.getVisitorType() == nv.UPDATE_VISITOR && _quickReleaseInstalled == false )
    {
        osg::Camera* cam = findFirstParentOfType<osg::Camera>( this );
        if ( cam )
        {
            // get the installed PDC so we can nest them:
            osg::Camera::DrawCallback* cbToNest = cam->getPostDrawCallback();

            // if it's another QR callback, we'll just replace it.
            QuickReleaseGLObjects* previousQR = dynamic_cast<QuickReleaseGLObjects*>(cbToNest);
            if ( previousQR )
                cbToNest = previousQR->_next.get();

            cam->setPostDrawCallback( new QuickReleaseGLObjects(_deadTiles.get(), cbToNest) );

            _quickReleaseInstalled = true;
            OE_INFO << LC << "Quick release enabled" << std::endl;

            // knock down the trav count set in the constructor.
            ADJUST_UPDATE_TRAV_COUNT( this, -1 );
        }
    }

    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 ( _loader.valid() ) // ensures that postInitialize has run
    {
        TraversalData* tdata = TraversalData::get(nv);
        if ( tdata )
        {
            RefUID& uid = tdata->getOrCreate<RefUID>("landcover.zone");
            getEngineContext()->_landCoverData->_currentZoneIndex = uid;
        }

        // Pass the tile creation context to the traversal.
        osg::ref_ptr<osg::Referenced> data = nv.getUserData();
        nv.setUserData( this->getEngineContext() );

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

        this->getEngineContext()->startCull( cv );
        TerrainEngineNode::traverse( nv );
        this->getEngineContext()->endCull( cv );

        if ( data.valid() )
            nv.setUserData( data.get() );
    }

    else
    {
        TerrainEngineNode::traverse( nv );
    }
}
예제 #2
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;
}
예제 #3
0
void
PagerLoader::traverse(osg::NodeVisitor& nv)
{
    // only called when _mergesPerFrame > 0
    if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
    {
        if ( nv.getFrameStamp() )
        {
            setFrameStamp(nv.getFrameStamp());
        }

        int count;
        for(count=0; count < _mergesPerFrame && !_mergeQueue.empty(); ++count)
        {
            Request* req = _mergeQueue.begin()->get();
            if ( req && req->_lastTick >= _checkpoint )
            {
                OE_START_TIMER(req_apply);
                req->apply( getFrameStamp() );
                double s = OE_STOP_TIMER(req_apply);

                req->setState(Request::FINISHED);
            }

            _mergeQueue.erase( _mergeQueue.begin() );
        }

        // cull finished requests.
        {
            Threading::ScopedMutexLock lock( _requestsMutex );

            unsigned fn = 0;
            if ( nv.getFrameStamp() )
                fn = nv.getFrameStamp()->getFrameNumber();

            // Purge expired requests.
            for(Requests::iterator i = _requests.begin(); i != _requests.end(); )
            {
                Request* req = i->second.get();

                if ( req->isFinished() )
                {
                    //OE_INFO << LC << req->getName() << "(" << i->second->getUID() << ") finished." << std::endl; 
                    req->setState( Request::IDLE );
                    if ( REPORT_ACTIVITY )
                        Registry::instance()->endActivity( req->getName() );
                    _requests.erase( i++ );
                }

                else if ( !req->isMerging() && (fn - req->getLastFrameSubmitted() > 2) )
                {
                    //OE_INFO << LC << req->getName() << "(" << i->second->getUID() << ") died waiting after " << fn-req->getLastFrameSubmitted() << " frames" << std::endl; 
                    req->setState( Request::IDLE );
                    if ( REPORT_ACTIVITY )
                        Registry::instance()->endActivity( req->getName() );
                    _requests.erase( i++ );
                }

                else // still valid.
                {
                    ++i;
                }
            }

            //OE_NOTICE << LC << "PagerLoader: requests=" << _requests.size() << "; mergeQueue=" << _mergeQueue.size() << std::endl;
        }
    }

    LoaderGroup::traverse( nv );
}
예제 #4
0
// 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;
    }
}
예제 #5
0
void
ClampingCullSet::accept(osg::NodeVisitor& nv)
{
    if ( nv.getVisitorType() == nv.CULL_VISITOR )
    {
        ProxyCullVisitor* cv = dynamic_cast<ProxyCullVisitor*>(&nv);

        // We will use the visitor's path to prevent doubely-applying the statesets
        // of common ancestors
        const osg::NodePath& nvPath = nv.getNodePath();

        int frame = nv.getFrameStamp() ? nv.getFrameStamp()->getFrameNumber() : 0u;

        unsigned passed = 0u;

        for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry )
        {
            if ( frame - entry->_frame > 1 )
                continue;

            // If there's an active (non-identity matrix), apply it
            if ( entry->_matrix.valid() )
            {
                entry->_matrix->postMult( *cv->getModelViewMatrix() );
                cv->pushModelViewMatrix( entry->_matrix.get(), osg::Transform::RELATIVE_RF );
            }

            // After pushing the matrix, we can perform the culling bounds test.
            if (!cv->isCulledByProxyFrustum(*entry->_node.get()))
            {
                // Apply the statesets in the entry's node path, but skip over the ones that are
                // shared with the current visitor's path since they are already in effect.
                // Count them so we can pop them later.
                int numStateSets = 0;
                osg::RefNodePath nodePath;
                if ( entry->_path.getRefNodePath(nodePath) )
                {
                    for(unsigned i=0; i<nodePath.size(); ++i)
                    {
                        if (nodePath[i].valid())
                        {
                            if (i >= nvPath.size() || nvPath[i] != nodePath[i].get())
                            {
                                osg::StateSet* stateSet = nodePath[i]->getStateSet();
                                if ( stateSet )
                                {
                                    cv->getCullVisitor()->pushStateSet( stateSet );
                                    ++numStateSets;
                                }
                            }
                        }
                    }
                }

                // Cull the DrapeableNode's children (but not the DrapeableNode itself!)
                for(unsigned i=0; i<entry->_node->getNumChildren(); ++i)
                {
                    entry->_node->getChild(i)->accept( nv );
                }
            
                // pop the same number we pushed
                for(int i=0; i<numStateSets; ++i)
                {
                    cv->getCullVisitor()->popStateSet();
                }

                ++passed;
            }

            // pop the model view:
            if ( entry->_matrix.valid() )
            {
                cv->popModelViewMatrix();
            }
            
            //Registry::instance()->startActivity("ClampingCullSet", Stringify() << std::hex << this << std::dec << " / " << passed << "/" << _entries.size());
        }

        // mark this set so it will reset for the next frame
        _frameCulled = true;
    }
}
예제 #6
0
void TileNode::cull(osg::NodeVisitor& nv)
{
    if ( nv.getFrameStamp() )
    {
        _lastTraversalFrame.exchange( nv.getFrameStamp()->getFrameNumber() );
    }

    unsigned currLOD = getTileKey().getLOD();

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

    EngineContext* context = static_cast<EngineContext*>( nv.getUserData() );
    const SelectionInfo& selectionInfo = context->getSelectionInfo();

    if ( context->progress() )
        context->progress()->stats()["TileNode::cull"]++;

    // determine whether we can and should subdivide to a higher resolution:
    bool subdivide =
        shouldSubDivide(nv, selectionInfo, cv->getLODScale());

    // whether it is OK to create child TileNodes is necessary.
    bool canCreateChildren = subdivide;

    // whether it is OK to load data if necessary.
    bool canLoadData = true;


    if ( _dirty && context->getOptions().progressive() == true )
    {
        // Don't create children in progressive mode until content is in place
        canCreateChildren = false;
    }
    
    else
    {
        // If this is an inherit-viewpoint camera, we don't need it to invoke subdivision
        // because we want only the tiles loaded by the true viewpoint.
        const osg::Camera* cam = cv->getCurrentCamera();
        if ( cam && cam->getReferenceFrame() == osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT )
        {
            canCreateChildren = false;
            canLoadData = false;
        }
    }

    optional<bool> surfaceVisible;


    // If *any* of the children are visible, subdivide.
    if (subdivide)
    {
        // We are in range of the child nodes. Either draw them or load them.

        // If the children don't exist, create them and inherit the parent's data.
        if ( getNumChildren() == 0 && canCreateChildren )
        {
            Threading::ScopedMutexLock exclusive(_mutex);
            if ( getNumChildren() == 0 )
            {
                createChildren( context );
            }
        }

        // If all are ready, traverse them now.
        if ( getNumChildren() == 4 )
        {
            for(int i=0; i<4; ++i)
            {
                _children[i]->accept( nv );
            }
        }

        // If we don't traverse the children, traverse this node's payload.
        else if ( _surface.valid() )
        {
            surfaceVisible = acceptSurface( cv, context );
        }
    }

    // If children are outside camera range, draw the payload and expire the children.
    else if ( _surface.valid() )
    {
        surfaceVisible = acceptSurface( cv, context );

        if ( getNumChildren() >= 4 && context->maxLiveTilesExceeded() )
        {
            if (getSubTile(0)->isDormant( nv ) &&
                getSubTile(1)->isDormant( nv ) &&
                getSubTile(2)->isDormant( nv ) &&
                getSubTile(3)->isDormant( nv ))
            {
                expireChildren( nv );
            }
        }
    }

    // Traverse land cover data at this LOD.
    int zoneIndex = context->_landCoverData->_currentZoneIndex;
    if ( zoneIndex < (int)context->_landCoverData->_zones.size() )
    {
        unsigned clearMask = cv->getCurrentCamera()->getClearMask();
        bool isDepthCamera = ((clearMask & GL_COLOR_BUFFER_BIT) == 0u) && ((clearMask & GL_DEPTH_BUFFER_BIT) != 0u);
        bool isShadowCamera = osgEarth::Shadowing::isShadowCamera(cv->getCurrentCamera());

        // only consider land cover if we are capturing color OR shadow.
        if ( isShadowCamera || !isDepthCamera )
        {
            const LandCoverZone& zone = context->_landCoverData->_zones.at(zoneIndex);
            for(int i=0; i<zone._bins.size(); ++i)
            {
                bool pushedPayloadSS = false;

                const LandCoverBin& bin = zone._bins.at(i);            
                if ( bin._lod == _key.getLOD() && (!isShadowCamera || bin._castShadows) )
                {
                    if ( !pushedPayloadSS )
                    {
                        cv->pushStateSet( _payloadStateSet.get() );
                        pushedPayloadSS = true;
                    }

                    cv->pushStateSet( bin._stateSet.get() ); // hopefully groups together for rendering.

                    _landCover->accept( nv );

                    cv->popStateSet();
                }

                if ( pushedPayloadSS )
                {
                    cv->popStateSet();
                }
            }
        }
    }

    // If this tile is marked dirty, try loading data.
    if ( _dirty && canLoadData )
    {
        // Only load data if the surface would be visible to the camera
        if ( !surfaceVisible.isSet() )
        {
            surfaceVisible = _surface->isVisible(cv);
        }

        if ( surfaceVisible == true )
        {
            load( nv );
        }
        else
        {
            OE_DEBUG << LC << "load skipped for " << _key.str() << std::endl;
        }
    }
}
예제 #7
0
void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor& nv)
{
    // typecast the NodeVisitor to CullVisitor
    osgUtil::CullVisitor* cv = nv.asCullVisitor();

    // continue only if the visitor actually is a cull visitor
    if (cv) {

        // continue only if the particle system is valid
        if (_ps.valid())
        {
            if (nv.getFrameStamp())
            {
                ParticleSystem::ScopedWriteLock lock(*(_ps->getReadWriteMutex()));

                //added- 1/17/06- [email protected]
                //a check to make sure we havent updated yet this frame
                if(_frameNumber < nv.getFrameStamp()->getFrameNumber())
                {


                    // retrieve the current time
                    double t = nv.getFrameStamp()->getSimulationTime();

                    // reset this processor if we've reached the reset point
                    if ((_currentTime >= _resetTime) && (_resetTime > 0))
                    {
                        _currentTime = 0;
                        _t0 = -1;
                    }

                    // skip if we haven't initialized _t0 yet
                    if (_t0 != -1)
                    {

                        // check whether the processor is alive
                        bool alive = false;
                        if (_currentTime >= _startTime)
                        {
                            if (_endless || (_currentTime < (_startTime + _lifeTime)))
                                alive = true;
                        }

                        // update current time
                        _currentTime += t - _t0;

                        // process only if the particle system is not frozen/culled
                        // We need to allow at least 2 frames difference, because the particle system's lastFrameNumber
                        // is updated in the draw thread which may not have completed yet.
                        if (alive &&
                            _enabled &&
                            !_ps->isFrozen() &&
                            (!_ps->getFreezeOnCull() || ((nv.getFrameStamp()->getFrameNumber()-_ps->getLastFrameNumber()) <= 2)) )
                        {
                            // initialize matrix flags
                            _need_ltw_matrix = true;
                            _need_wtl_matrix = true;
                            _current_nodevisitor = &nv;

                            // do some process (unimplemented in this base class)
                            process( t - _t0 );
                        } else {
                            //The values of _previous_wtl_matrix and _previous_ltw_matrix will be invalid
                            //since processing was skipped for this frame
                            _first_ltw_compute = true;
                            _first_wtl_compute = true;
                        }
                    }
                    _t0 = t;
                }

                //added- 1/17/06- [email protected]
                //updates the _frameNumber, keeping it current
                _frameNumber = nv.getFrameStamp()->getFrameNumber();
            }
            else
            {
                OSG_WARN << "osgParticle::ParticleProcessor::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n";
            }

        } else
        {
            OSG_WARN << "ParticleProcessor \"" << getName() << "\": invalid particle system\n";
        }
    }


    // call the inherited method
    Node::traverse(nv);
}
예제 #8
0
void
SilverLiningContextNode::traverse(osg::NodeVisitor& nv)
{
    if ( _SL && _SL->ready() )
    {
        if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
        {
			int frameNumber = nv.getFrameStamp()->getFrameNumber();
            _skyDrawable->dirtyBound();

            if( _cloudsDrawable )
            {
                if ( _lastAltitude <= *_options.cloudsMaxAltitude() )
                {
                    if ( _cloudsDrawable->getNumParents() == 0 )
                        _geode->addDrawable( _cloudsDrawable.get() );

                    _cloudsDrawable->dirtyBound();
                }
                else
                {
                    if ( _cloudsDrawable->getNumParents() > 0 )
                        _geode->removeDrawable( _cloudsDrawable.get() );
                }
            }
        }

        else if ( nv.getVisitorType() == nv.CULL_VISITOR )
        {
			osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
			osg::Camera* camera  = cv->getCurrentCamera();
			if ( camera )
			{
#ifndef SL_USE_CULL_MASK
				//Check if this is the target camera for this context
				if(getTargetCamera() == camera)
#endif	
     			{

					// TODO: make this multi-camera safe
					_SL->setCameraPosition( nv.getEyePoint() );
					osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
					_SL->getAtmosphere()->SetCameraMatrix( cv->getModelViewMatrix()->ptr() );
					_SL->getAtmosphere()->SetProjectionMatrix( cv->getProjectionMatrix()->ptr() );

					_lastAltitude = _SL->getSRS()->isGeographic() ?
						cv->getEyePoint().length() - _SL->getSRS()->getEllipsoid()->getRadiusEquator() :
					cv->getEyePoint().z();

					_SL->updateLocation();
					_SL->updateLight();
					//_SL->getAtmosphere()->UpdateSkyAndClouds();
					//_SL->getAtmosphere()->CullObjects();
				}
			}
        }
    }

    if ( _geode.valid() )
    {
        _geode->accept(nv);
    }
}
void PrecipitationEffect::traverse(osg::NodeVisitor& nv)
{
    if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
    {
        if (_dirty) update();

        if (nv.getFrameStamp())
        {
            double currentTime = nv.getFrameStamp()->getSimulationTime();
            if (_previousFrameTime==FLT_MAX) _previousFrameTime = currentTime;

            double delta = currentTime - _previousFrameTime;
            _origin += _wind * delta;
            _previousFrameTime = currentTime;
        }

        return;
    }

    if (nv.getVisitorType() == osg::NodeVisitor::NODE_VISITOR)
    {
        if (_dirty) update();

        osgUtil::GLObjectsVisitor* globjVisitor = dynamic_cast<osgUtil::GLObjectsVisitor*>(&nv);
        if (globjVisitor)
        {
            if (globjVisitor->getMode() & osgUtil::GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES)
            {
                compileGLObjects(globjVisitor->getRenderInfo());
            }
        }

        return;
    }


    if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
    {
        return;
    }

    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
    if (!cv)
    {
        return;
    }

    ViewIdentifier viewIndentifier(cv, nv.getNodePath());

    {
        PrecipitationDrawableSet* precipitationDrawableSet = 0;

        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
            precipitationDrawableSet = &(_viewDrawableMap[viewIndentifier]);

            if (!precipitationDrawableSet->_quadPrecipitationDrawable)
            {
                precipitationDrawableSet->_quadPrecipitationDrawable = new PrecipitationDrawable;
                precipitationDrawableSet->_quadPrecipitationDrawable->setRequiresPreviousMatrix(true);
                precipitationDrawableSet->_quadPrecipitationDrawable->setGeometry(_quadGeometry.get());
                precipitationDrawableSet->_quadPrecipitationDrawable->setStateSet(_quadStateSet.get());
                precipitationDrawableSet->_quadPrecipitationDrawable->setDrawType(GL_QUADS);

                precipitationDrawableSet->_linePrecipitationDrawable = new PrecipitationDrawable;
                precipitationDrawableSet->_linePrecipitationDrawable->setRequiresPreviousMatrix(true);
                precipitationDrawableSet->_linePrecipitationDrawable->setGeometry(_lineGeometry.get());
                precipitationDrawableSet->_linePrecipitationDrawable->setStateSet(_lineStateSet.get());
                precipitationDrawableSet->_linePrecipitationDrawable->setDrawType(GL_LINES);

                precipitationDrawableSet->_pointPrecipitationDrawable = new PrecipitationDrawable;
                precipitationDrawableSet->_pointPrecipitationDrawable->setRequiresPreviousMatrix(false);
                precipitationDrawableSet->_pointPrecipitationDrawable->setGeometry(_pointGeometry.get());
                precipitationDrawableSet->_pointPrecipitationDrawable->setStateSet(_pointStateSet.get());
                precipitationDrawableSet->_pointPrecipitationDrawable->setDrawType(GL_POINTS);
            }
        }

        cull(*precipitationDrawableSet, cv);

        cv->pushStateSet(_stateset.get());
        float depth = 0.0f;

        if (!precipitationDrawableSet->_quadPrecipitationDrawable->getCurrentCellMatrixMap().empty())
        {
            cv->pushStateSet(precipitationDrawableSet->_quadPrecipitationDrawable->getStateSet());
            cv->addDrawableAndDepth(precipitationDrawableSet->_quadPrecipitationDrawable.get(),cv->getModelViewMatrix(),depth);
            cv->popStateSet();
        }

        if (!precipitationDrawableSet->_linePrecipitationDrawable->getCurrentCellMatrixMap().empty())
        {
            cv->pushStateSet(precipitationDrawableSet->_linePrecipitationDrawable->getStateSet());
            cv->addDrawableAndDepth(precipitationDrawableSet->_linePrecipitationDrawable.get(),cv->getModelViewMatrix(),depth);
            cv->popStateSet();
        }

        if (!precipitationDrawableSet->_pointPrecipitationDrawable->getCurrentCellMatrixMap().empty())
        {
            cv->pushStateSet(precipitationDrawableSet->_pointPrecipitationDrawable->getStateSet());
            cv->addDrawableAndDepth(precipitationDrawableSet->_pointPrecipitationDrawable.get(),cv->getModelViewMatrix(),depth);
            cv->popStateSet();
        }

        cv->popStateSet();

    }
}
예제 #10
0
void TileNode::cull(osg::NodeVisitor& nv)
{
    osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( &nv );

    EngineContext* context = static_cast<EngineContext*>( nv.getUserData() );
    const SelectionInfo& selectionInfo = context->getSelectionInfo();

    // record the number of drawables before culling this node:
    unsigned before = RenderBinUtils::getTotalNumRenderLeaves( cv->getRenderStage() );

    if ( context->progress() )
        context->progress()->stats()["TileNode::cull"]++;

    // determine whether we can and should subdivide to a higher resolution:
    bool subdivide = shouldSubDivide(nv, selectionInfo, cv->getLODScale());

    // whether it is OK to create child TileNodes is necessary.
    bool canCreateChildren = subdivide;

    // whether it is OK to load data if necessary.
    bool canLoadData = true;


    if ( _dirty && context->getOptions().progressive() == true )
    {
        // Don't create children in progressive mode until content is in place
        canCreateChildren = false;
    }
    
    // If this is an inherit-viewpoint camera, we don't need it to invoke subdivision
    // because we want only the tiles loaded by the true viewpoint.
    const osg::Camera* cam = cv->getCurrentCamera();
    if ( cam && cam->getReferenceFrame() == osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT )
    {
        canCreateChildren = false;
        canLoadData = false;
    }

    optional<bool> surfaceVisible( false );

    if (subdivide)
    {
        // We are in range of the child nodes. Either draw them or load them.

        // If the children don't exist, create them and inherit the parent's data.
        if ( getNumChildren() == 0 && canCreateChildren )
        {
            Threading::ScopedMutexLock exclusive(_mutex);
            if ( getNumChildren() == 0 )
            {
                createChildren( context );
            }
        }

        // If all are ready, traverse them now.
        if ( getNumChildren() == 4 )
        {
            for(int i=0; i<4; ++i)
            {
                // pre-check each child for simple bounding sphere culling, and if the check 
                // fails, unload it's children if them exist. This lets us unload dormant
                // tiles from memory as we go. If those children are visible from another
                // camera, no worries, the unload attempt will fail gracefully.
                if (!cv->isCulled(*_children[i].get()))
                {
                    _children[i]->accept( nv );
                }
                else
                {
                    context->getUnloader()->unloadChildren(getSubTile(i)->getTileKey());
                }
            }
        }

        // If we don't traverse the children, traverse this node's payload.
        else if ( _surface.valid() )
        {
            surfaceVisible = acceptSurface( cv, context );
        }
    }

    // If children are outside camera range, draw the payload and expire the children.
    else if ( _surface.valid() )
    {
        surfaceVisible = acceptSurface( cv, context );

        // if children exists, and are not in the process of loading, unload them now.
        if ( !_dirty && _children.size() > 0 )
        {
            context->getUnloader()->unloadChildren( this->getTileKey() );
        }
    }

    // See whether we actually added any drawables.
    unsigned after = RenderBinUtils::getTotalNumRenderLeaves( cv->getRenderStage() );
    bool addedDrawables = (after > before);
    
    // Only continue if we accepted at least one surface drawable.
    if ( addedDrawables )
    {
        // update the timestamp so this tile doesn't become dormant.
        _lastTraversalFrame.exchange( nv.getFrameStamp()->getFrameNumber() );
    }

    context->invokeTilePatchCallbacks( cv, getTileKey(), _payloadStateSet.get(), _patch.get() );

    // If this tile is marked dirty, try loading data.
    if ( addedDrawables && _dirty && canLoadData )
    {
        // Only load data if the surface would be visible to the camera
        if ( !surfaceVisible.isSet() )
        {
            surfaceVisible = _surface->isVisible(cv);
        }

        if ( surfaceVisible == true )
        {
            load( nv );
        }
        else
        {
            OE_DEBUG << LC << "load skipped for " << _key.str() << std::endl;
        }
    }
}
예제 #11
0
파일: Timeout.cpp 프로젝트: PerhapsCaiv/osg
void Timeout::traverse(osg::NodeVisitor& nv)
{
    if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
        if (_displayTimeout && cv)
        {
            osgUtil::RenderStage* previous_stage = cv->getCurrentRenderBin()->getStage();

            osg::ref_ptr<osgUtil::RenderStage> rs = new osgUtil::RenderStage;

            osg::ColorMask* colorMask = previous_stage->getColorMask();
            rs->setColorMask(colorMask);

            // set up the viewport.
            osg::Viewport* viewport = previous_stage->getViewport();
            rs->setViewport( viewport );

            rs->setClearMask(GL_DEPTH_BUFFER_BIT);

            // record the render bin, to be restored after creation
            // of the render to text
            osgUtil::RenderBin* previousRenderBin = cv->getCurrentRenderBin();

            // set the current renderbin to be the newly created stage.
            cv->setCurrentRenderBin(rs.get());

            // traverse the subgraph
            {
                Transform::traverse(nv);
            }

            // restore the previous renderbin.
            cv->setCurrentRenderBin(previousRenderBin);

            // and the render to texture stage to the current stages
            // dependancy list.
            cv->getCurrentRenderBin()->getStage()->addPostRenderStage(rs.get(),0);
        }
    }
    else if (nv.getVisitorType()==osg::NodeVisitor::EVENT_VISITOR)
    {
        int deltaFrameNumber = (nv.getFrameStamp()->getFrameNumber()-_previousFrameNumber);
        _previousFrameNumber = nv.getFrameStamp()->getFrameNumber();

        bool needToRecordEventTime = false;
        bool needToAction = false;

        if (deltaFrameNumber>1)
        {
            needToRecordEventTime = true;
        }

        bool previous_displayTimeout = _displayTimeout;
        bool needToDismiss = false;

        osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
        osgViewer::Viewer* viewer = ev ? dynamic_cast<osgViewer::Viewer*>(ev->getActionAdapter()) : 0;
        if (ev)
        {
            osgGA::EventQueue::Events& events = ev->getEvents();
            for(osgGA::EventQueue::Events::iterator itr = events.begin();
                itr != events.end();
                ++itr)
            {
                osgGA::GUIEventAdapter* event = itr->get();

                bool keyEvent = event->getEventType()==osgGA::GUIEventAdapter::KEYDOWN ||  event->getEventType()==osgGA::GUIEventAdapter::KEYUP;

                if (keyEvent && event->getKey()==_keyStartsTimoutDisplay)
                {
                    OSG_NOTICE<<"_keyStartsTimoutDisplay pressed"<<std::endl;
                    _displayTimeout = true;
                }
                else if (keyEvent && event->getKey()==_keyDismissTimoutDisplay)
                {
                    OSG_NOTICE<<"_keyDismissTimoutDisplay pressed"<<std::endl;
                    needToRecordEventTime = true;
                    needToDismiss = _displayTimeout;
                    _displayTimeout = false;
                }
                else if (keyEvent && event->getKey()==_keyRunTimeoutAction)
                {
                    OSG_NOTICE<<"_keyRunTimeoutAction pressed"<<std::endl;
                    _displayTimeout = false;
                    needToRecordEventTime = true;
                    needToAction = true;
                }
                else if (event->getEventType()!=osgGA::GUIEventAdapter::FRAME)
                {
                    needToRecordEventTime = true;
                    needToDismiss = _displayTimeout;
                    _displayTimeout = false;
                }
            }
        }
        

        if (needToRecordEventTime)
        {
            _timeOfLastEvent = nv.getFrameStamp()->getReferenceTime();
        }
        
        double timeSinceLastEvent = nv.getFrameStamp() ? nv.getFrameStamp()->getReferenceTime()-_timeOfLastEvent : 0.0;

        if (timeSinceLastEvent>_idleDurationBeforeTimeoutDisplay)
        {
            _displayTimeout = true;
        }

        if (timeSinceLastEvent>_idleDurationBeforeTimeoutAction)
        {
            _displayTimeout = false;
            needToAction = true;
            needToDismiss = false;
        }

        if (!previous_displayTimeout && _displayTimeout)
        {
            if (viewer && (_displayBroadcastKeyPos._key!=0 || _displayBroadcastKeyPos._x!=FLT_MAX || _displayBroadcastKeyPos._y!=FLT_MAX))
            {
                OSG_NOTICE<<"Doing display broadcast key event"<<_displayBroadcastKeyPos._key<<std::endl;
                broadcastEvent(viewer, _displayBroadcastKeyPos);
            }

            OperationVisitor leave(OperationVisitor::ENTER);
            accept(leave);

            if (leave.sleepTime()!=0.0)
            {
                OSG_NOTICE<<"Pausing for "<<leave.sleepTime()<<std::endl;
                OpenThreads::Thread::microSleep(static_cast<unsigned int>(1000000.0*leave.sleepTime()));
                OSG_NOTICE<<"Finished Pause "<<std::endl;
            }

        }


        if (needToDismiss)
        {
            if (viewer && (_dismissBroadcastKeyPos._key!=0 || _dismissBroadcastKeyPos._x!=FLT_MAX || _dismissBroadcastKeyPos._y!=FLT_MAX))
            {
                OSG_NOTICE<<"Doing dismiss broadcast key event"<<_dismissBroadcastKeyPos._key<<std::endl;
                broadcastEvent(viewer, _dismissBroadcastKeyPos);
            }

            OperationVisitor leave(OperationVisitor::LEAVE);
            accept(leave);
        }

        Transform::traverse(nv);


        if (needToAction)
        {
            OSG_NOTICE<<"Do timeout action"<<std::endl;
            _previousFrameNumber = -1;
            _timeOfLastEvent = nv.getFrameStamp()->getReferenceTime();


            if (_actionJumpData.requiresJump())
            {
                OSG_NOTICE<<"Doing timeout jump"<<std::endl;
                _actionJumpData.jump(SlideEventHandler::instance());
            }

            if (_actionKeyPos._key!=0 || _actionKeyPos._x!=FLT_MAX || _actionKeyPos._y!=FLT_MAX)
            {
                OSG_NOTICE<<"Doing timeout key event"<<_actionKeyPos._key<<std::endl;
                if (SlideEventHandler::instance()) SlideEventHandler::instance()->dispatchEvent(_actionKeyPos);
            }

            if (viewer && (_actionBroadcastKeyPos._key!=0 || _actionBroadcastKeyPos._x!=FLT_MAX || _actionBroadcastKeyPos._y!=FLT_MAX))
            {
                OSG_NOTICE<<"Doing timeout broadcast key event"<<_actionBroadcastKeyPos._key<<std::endl;
                broadcastEvent(viewer, _actionBroadcastKeyPos);
            }
            
        }
        
    }
    else if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
    {
        if (_displayTimeout) Transform::traverse(nv);
    }
    else
    {
        if (strcmp(nv.className(),"FindOperatorsVisitor")==0)
        {
            OSG_NOTICE<<"Timout::traverse() "<<nv.className()<<", ignoring traversal"<<std::endl;            
        }
        else
        {
            Transform::traverse(nv);
        }
    }


    
}
예제 #12
0
파일: TXPPagedLOD.cpp 프로젝트: 3dcl/osg
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;
    }
}
예제 #13
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 );
    }
}
예제 #14
0
void TileNode::cull(osg::NodeVisitor& nv)
{
    if ( nv.getFrameStamp() )
    {
        _lastTraversalFrame.exchange( nv.getFrameStamp()->getFrameNumber() );
    }

    unsigned currLOD = getTileKey().getLOD();

#if OSGEARTH_REX_TILE_NODE_DEBUG_TRAVERSAL
    if (currLOD==0)
    {
        OE_INFO << LC <<"Traversing: "<<"\n";    
    }
#endif
    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>( &nv );

    EngineContext* context = static_cast<EngineContext*>( nv.getUserData() );
    const SelectionInfo& selectionInfo = context->getSelectionInfo();

    // determine whether we can and should subdivide to a higher resolution:
    bool subdivide = shouldSubDivide(nv, selectionInfo, cv->getLODScale());

    // If this is an inherit-viewpoint camera, we don't need it to invoke subdivision
    // because we want only the tiles loaded by the true viewpoint.
    bool canCreateChildren = subdivide;
    const osg::Camera* cam = cv->getCurrentCamera();
    if ( cam && cam->getReferenceFrame() == osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT )
    {
        canCreateChildren = false;
    }

    // If *any* of the children are visible, subdivide.
    if (subdivide)
    {
        // We are in range of the child nodes. Either draw them or load them.

        // If the children don't exist, create them and inherit the parent's data.
        if ( getNumChildren() == 0 && canCreateChildren )
        {
            Threading::ScopedMutexLock exclusive(_mutex);
            if ( getNumChildren() == 0 )
            {
                createChildren( context );
            }
        }

        // All 4 children must be ready before we can traverse any of them:
        unsigned numChildrenReady = 0;
        if ( getNumChildren() == 4 )
        {
            for(unsigned i = 0; i < 4; ++i)
            {                
                if ( getSubTile(i)->isReadyToTraverse() )
                {
                    ++numChildrenReady;
                }
            }
        }

        // If all are ready, traverse them now.
        if ( numChildrenReady == 4 )
        {
            // TODO:
            // When we do this, we need to quite sure that all 4 children will be accepted into
            // the draw set. Perhaps isReadyToTraverse() needs to check that.
            _children[0]->accept( nv );
            _children[1]->accept( nv );
            _children[2]->accept( nv );
            _children[3]->accept( nv );
        }

        // If we don't traverse the children, traverse this node's payload.
        else if ( _surface.valid() )
        {
            cullSurface( cv );
        }
    }

    // If children are outside camera range, draw the payload and expire the children.
    else if ( _surface.valid() )
    {
        cullSurface( cv );

        if ( getNumChildren() >= 4 && context->maxLiveTilesExceeded() )
        {
            if (getSubTile(0)->isDormant( nv ) &&
                getSubTile(1)->isDormant( nv ) &&
                getSubTile(2)->isDormant( nv ) &&
                getSubTile(3)->isDormant( nv ))
            {
                expireChildren( nv );
            }
        }
    }

    // Traverse land cover bins at this LOD.
    for(int i=0; i<context->landCoverBins()->size(); ++i)
    {
        bool first = true;
        const LandCoverBin& bin = context->landCoverBins()->at(i);
        if ( bin._lod == getTileKey().getLOD() )
        {
            if ( first )
            {
                cv->pushStateSet( _payloadStateSet.get() );
            }

            cv->pushStateSet( bin._stateSet.get() );
            _landCover->accept( nv );
            cv->popStateSet();

            if ( first )
            {
                cv->popStateSet();
                first = false;
            }
        }
    }

    // If this tile is marked dirty, try loading data.
    if ( _dirty )
    {
        load( nv );
    }
}
예제 #15
0
void
DrapingCullSet::accept(osg::NodeVisitor& nv)
{
    if ( nv.getVisitorType() == nv.CULL_VISITOR )
    {
        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( &nv );

        // We will use the visitor's path to prevent doubely-applying the statesets
        // of common ancestors
        const osg::NodePath& nvPath = nv.getNodePath();

        int frame = nv.getFrameStamp() ? nv.getFrameStamp()->getFrameNumber() : 0u;

        for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry )
        {
            if ( frame - entry->_frame > 1 )
                continue;

            // If there's an active (non-identity matrix), apply it
            if ( entry->_matrix.valid() )
            {
                entry->_matrix->postMult( *cv->getModelViewMatrix() );
                cv->pushModelViewMatrix( entry->_matrix.get(), osg::Transform::RELATIVE_RF );
            }

            // After pushing the matrix, we can perform the culling bounds test.
            if ( !cv->isCulled( entry->_node->getBound() ) )
            {
                // Apply the statesets in the entry's node path, but skip over the ones that are
                // shared with the current visitor's path since they are already in effect.
                // Count them so we can pop them later.
                int numStateSets = 0;
                osg::RefNodePath nodePath;
                if ( entry->_path.getRefNodePath(nodePath) )
                {
                    for(unsigned i=0; i<nodePath.size(); ++i)
                    {
                        if (nodePath[i].valid())
                        {
                            if (i >= nvPath.size() || nvPath[i] != nodePath[i].get())
                            {
                                osg::StateSet* stateSet = nodePath[i]->getStateSet();
                                if ( stateSet )
                                {
                                    cv->pushStateSet( stateSet );
                                    ++numStateSets;
                                }
                            }
                        }
                    }
                }

                // Cull the DrapeableNode's children (but not the DrapeableNode itself!)
                // TODO: make sure we aren't skipping any cull callbacks, etc. by calling traverse 
                // instead of accept. (Cannot call accept b/c that calls traverse)
                for(unsigned i=0; i<entry->_node->getNumChildren(); ++i)
                {
                    entry->_node->getChild(i)->accept( nv );
                }
            
                // pop the same number we pushed
                for(int i=0; i<numStateSets; ++i)
                {
                    cv->popStateSet();
                }
            }

            // pop the model view:
            if ( entry->_matrix.valid() )
            {
                cv->popModelViewMatrix();
            }
        }

        // mark this set so it will reset for the next frame
        _frameCulled = true;
    }

    else
    {
        for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry )
        {
            
        }
    }
}
예제 #16
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 );
    }
}
예제 #17
0
void SoundNode::traverse(osg::NodeVisitor &nv)
{
    // continue only if the visitor actually is a cull visitor
    if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
    {
        // Make sure we only execute this once during this frame.
        // There could be two or more culls for stereo/multipipe...
        if (!m_sound_state.valid()) {
            // call the inherited method
            osg::notify(osg::DEBUG_INFO) << "SoundNode::traverse() No soundstate attached to soundnode" << std::endl;
            Node::traverse(nv);
            return;
        }
        if ( m_sound_state.valid() && nv.getTraversalNumber() != m_last_traversal_number && nv.getFrameStamp())
        {

            m_last_traversal_number = nv.getTraversalNumber();

            // retrieve the current time
            double t = nv.getFrameStamp()->getReferenceTime();
            double time = t - m_last_time;

            if(time >= m_sound_manager->getUpdateFrequency()) {

                osg::Matrix m;
                m = osg::computeLocalToWorld(nv.getNodePath());

                osg::Vec3 pos = m.getTrans();

                m_sound_state->setPosition(pos);

                //Calculate velocity
                osg::Vec3 velocity(0,0,0);

                if (m_first_run) {
                    m_first_run = false;
                    m_last_time = t;
                    m_last_pos = pos;
                }
                else {
                    velocity = pos - m_last_pos;
                    m_last_pos = pos;
                    m_last_time = t;
                    velocity /= time;
                }

                if(m_sound_manager->getClampVelocity()) {
                    float max_vel = m_sound_manager->getMaxVelocity();
                    float len = velocity.length();
                    if ( len > max_vel) {
                        velocity.normalize();
                        velocity *= max_vel;
                    }
                }

                m_sound_state->setVelocity(velocity);

                //Get new direction
                osg::Vec3 dir(0,1,0);

                dir = dir * m;
                dir.normalize();
                m_sound_state->setDirection(dir);      

                // Only do occlusion calculations if the sound is playing
                if (m_sound_state->getPlay() && m_occlude_callback.valid())
                    m_occlude_callback->apply(m_sound_manager->getListenerMatrix(), pos, m_sound_state.get());
            } // if
        }
    } // if cullvisitor

    // call the inherited method
    Node::traverse(nv);
}
예제 #18
0
void
SilverLiningNode::traverse(osg::NodeVisitor& nv)
{
    if ( _SL && _SL->ready() )
    {
        if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
        {
			int frameNumber = nv.getFrameStamp()->getFrameNumber();
            _skyDrawable->dirtyBound();

            if( _cloudsDrawable )
            {
                if ( _lastAltitude <= *_options.cloudsMaxAltitude() )
                {
                    if ( _cloudsDrawable->getNumParents() == 0 )
                        _geode->addDrawable( _cloudsDrawable.get() );

                    _cloudsDrawable->dirtyBound();
                }
                else
                {
                    if ( _cloudsDrawable->getNumParents() > 0 )
                        _geode->removeDrawable( _cloudsDrawable.get() );
                }
            }
        }

        else if ( nv.getVisitorType() == nv.CULL_VISITOR )
        {

            // TODO: make this multi-camera safe
            _SL->setCameraPosition( nv.getEyePoint() );
            osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv);
            _SL->getAtmosphere()->SetCameraMatrix( cv->getModelViewMatrix()->ptr() );
            _SL->getAtmosphere()->SetProjectionMatrix( cv->getProjectionMatrix()->ptr() );

			_lastAltitude = _SL->getSRS()->isGeographic() ?
				cv->getEyePoint().length() - _SL->getSRS()->getEllipsoid()->getRadiusEquator() :
				cv->getEyePoint().z();

			//if (_lastAltitude <= *_options.cloudsMaxAltitude() )
			{
                _SL->updateLocation();
                _SL->updateLight();
                _SL->getAtmosphere()->UpdateSkyAndClouds();
				_SL->getAtmosphere()->CullObjects();
			}
        }
    }

    osgEarth::Util::SkyNode::traverse( nv );

    if ( _geode.valid() )
    {
        _geode->accept(nv);
    }

    if ( _lightSource.valid() )
    {
        _lightSource->accept(nv);
    }
}