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 ); } }
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; }
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 ); }
// 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; } }
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; } }
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; } } }
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); }
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(); } }
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; } } }
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); } } }
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; } }
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 ); } }
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 ); } }
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 ) { } } }
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 ); } }
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); }
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); } }