void TileNode::load(osg::NodeVisitor& nv) { // Access the context: EngineContext* context = static_cast<EngineContext*>( nv.getUserData() ); // Create a new load request on demand: if ( !_loadRequest.valid() ) { Threading::ScopedMutexLock lock(_mutex); if ( !_loadRequest.valid() ) { _loadRequest = new LoadTileData( this, context ); _loadRequest->setName( _key.str() ); _loadRequest->setTileKey( _key ); } } // Prioritize by LOD. (negated because lower order gets priority) float priority = - (float)getTileKey().getLOD(); if ( context->getOptions().highResolutionFirst() == true ) priority = -priority; // then sort by distance within each LOD. float distance = nv.getDistanceToViewPoint( getBound().center(), true ); priority = 10.0f*priority - log10(distance); // testing intermediate loading idea... //if ( getTileKey().getLOD() == 5 ) // priority += 100.0f; // Submit to the loader. context->getLoader()->load( _loadRequest.get(), priority, nv ); }
void ElevationLOD::traverse( osg::NodeVisitor& nv) { if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR && nv.getTraversalMode() == osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN ) { bool rangeOK = true; bool altitudeOK = true; // first test the range: if ( _minRange.isSet() || _maxRange.isSet() ) { float range = nv.getDistanceToViewPoint( getBound().center(), true ); rangeOK = (!_minRange.isSet() || (range >= *_minRange)) && (!_maxRange.isSet() || (range <= *_maxRange)); } if ( rangeOK ) { if ( _minElevation.isSet() || _maxElevation.isSet() ) { double alt; // first see if we have a precalculated elevation: osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); osg::Vec3d eye = cv->getViewPoint(); if ( _srs && !_srs->isProjected() ) { GeoPoint mapPoint; mapPoint.fromWorld( _srs.get(), eye ); alt = mapPoint.z(); } else { alt = eye.z(); } // account for the LOD scale alt *= cv->getLODScale(); altitudeOK = (!_minElevation.isSet() || (alt >= *_minElevation)) && (!_maxElevation.isSet() || (alt <= *_maxElevation)); } if ( altitudeOK ) { std::for_each(_children.begin(),_children.end(),osg::NodeAcceptOp(nv)); } } } else { osg::Group::traverse( nv ); } }
void HTMNode::traverse(osg::NodeVisitor& nv) { if ( nv.getVisitorType() == nv.CULL_VISITOR ) { //OE_INFO << getName() << std::endl; #if 0 if ( _isLeaf ) { if (_settings._debugFrame != nv.getFrameStamp()->getFrameNumber()) { OE_NOTICE << "Frame " << _settings._debugFrame << ": " << _settings._debugCount << std::endl; _settings._debugCount = 0; _settings._debugFrame = nv.getFrameStamp()->getFrameNumber(); } _settings._debugCount += getNumChildren(); } #endif const osg::BoundingSphere& bs = getBound(); float range = nv.getDistanceToViewPoint(bs.center(), true); bool inRange = false; if (_settings._maxRange.isSet() == false) { inRange = range < (bs.radius() * _settings._rangeFactor.get()); } else { inRange = range < (bs.radius() + _settings._maxRange.get()); } if ( inRange ) { osg::Group::traverse( nv ); if (_debug.valid() && _isLeaf) { _debug->accept(nv); } } else if (_debug.valid()) { _debug->accept(nv); } } else { if (_debug.valid()) { _debug->accept(nv); } osg::Group::traverse( nv ); } }
void TileGroup::traverse(osg::NodeVisitor& nv) { if ( nv.getTraversalMode() == nv.TRAVERSE_ACTIVE_CHILDREN ) { float range = 0.0f; if ( nv.getVisitorType() == nv.CULL_VISITOR ) { range = nv.getDistanceToViewPoint( getBound().center(), true ); } // if all four subtiles have reported that they are upsampling, // don't use any of them. if ( _traverseSubtiles && _numSubtilesUpsampling == 4 ) { _traverseSubtiles = false; } // if we are out of subtile range, or we're in range but the subtiles are // not all loaded yet, or we are skipping subtiles, draw the current tile. if ( range > _subtileRange || _numSubtilesLoaded < 4 || !_traverseSubtiles ) { _tilenode->accept( nv ); } // if we're in range, traverse the subtiles. if ( _traverseSubtiles && range <= _subtileRange ) { for( unsigned q=0; q<4; ++q ) { getChild(1+q)->accept( nv ); } // update the TileNode so it knows what frame we're in. if ( nv.getFrameStamp() ) { _tilenode->setLastTraversalFrame( nv.getFrameStamp()->getFrameNumber() ); } } } else { osg::Group::traverse( nv ); } }
void TileNode::load(osg::NodeVisitor& nv) { // Access the context: EngineContext* context = VisitorData::fetch<EngineContext>(nv, ENGINE_CONTEXT_TAG); // Create a new load request on demand: if ( !_loadRequest.valid() ) { Threading::ScopedMutexLock lock(_mutex); if ( !_loadRequest.valid() ) { _loadRequest = new LoadTileData( this, context ); _loadRequest->setName( _key.str() ); _loadRequest->setTileKey( _key ); } } // Construct the load PRIORITY: 0=lowest, 1=highest. const SelectionInfo& si = context->getSelectionInfo(); int lod = getTileKey().getLOD(); int numLods = si.numLods(); // LOD priority is in the range [0..numLods] float lodPriority = (float)lod; if ( context->getOptions().highResolutionFirst() == false ) lodPriority = (float)(numLods - lod); float distance = nv.getDistanceToViewPoint(getBound().center(), true); // dist priority uis in the range [0..1] float distPriority = 1.0 - distance/si.visParameters(0)._visibilityRange; // add thenm together, and you get tiles sorted first by lodPriority (because of // the biggest range), and second by distance. float priority = lodPriority + distPriority; // normalize the composite priority to [0..1]. priority /= (float)(numLods+1); // Submit to the loader. context->getLoader()->load( _loadRequest.get(), priority, nv ); }
void LOD::traverse(osg::NodeVisitor& nv) { if(_dirty_copy) { osg::Group* prnt = getParent(0); for(unsigned i =0;i<prnt->getNumChildren();++i) { auto chld = prnt->getChild(i); if (!dynamic_cast<avLod::LOD*>(chld)) addChild(chld); } _dirty_copy =false; } switch(nv.getTraversalMode()) { //case(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN): // std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv)); // break; case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN): { float required_range = 0; if (_rangeMode==DISTANCE_FROM_EYE_POINT) { required_range = nv.getDistanceToViewPoint(getCenter(),true); } else { osg::CullStack* cullStack = dynamic_cast<osg::CullStack*>(&nv); if (cullStack && cullStack->getLODScale()) { 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); } } } unsigned int numChildren = _children.size(); if (_rangeList.size()<numChildren) numChildren=_rangeList.size(); for(unsigned int i=0;i<numChildren;++i) { if (_rangeList[i].first<=required_range && required_range<_rangeList[i].second) { _children[i]->setNodeMask(/*0xffffffff*/REFLECTION_MASK);// accept(nv); } else { _children[i]->setNodeMask(0); } } break; } default: break; } }
// 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; } }