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 VisibilityGroup::traverse(osg::NodeVisitor &nv) { if (nv.getTraversalMode() == osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN && nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { // cast to cullvisitor osgUtil::CullVisitor &cv = (osgUtil::CullVisitor&) nv; // here we test if we are inside the visibilityvolume // first get the eyepoint and in local coordinates osg::Vec3 eye = cv.getEyeLocal(); osg::Vec3 look = cv.getLookVectorLocal(); // now scale the segment to the segment length - if 0 use the group bounding sphere radius float length = _segmentLength; if (length == 0.f) length = 2.0f * getBound().radius(); look *= length; osg::Vec3 center = eye + look; osg::Vec3 seg = center - eye; // perform the intersection using the given mask osgUtil::IntersectVisitor iv; osg::ref_ptr<osg::LineSegment> lineseg = new osg::LineSegment; lineseg->set(eye, center); iv.addLineSegment(lineseg.get()); iv.setTraversalMask(_volumeIntersectionMask); if (_visibilityVolume.valid()) _visibilityVolume->accept(iv); // now examine the hit record if (iv.hits()) { osgUtil::IntersectVisitor::HitList &hitList = iv.getHitList(lineseg.get()); if (!hitList.empty()) // we actually hit something { // OSG_INFO << "Hit obstruction"<< std::endl; osg::Vec3 normal = hitList.front().getWorldIntersectNormal(); if ((normal * seg) > 0.f) // we are inside Group::traverse(nv); } } } else { 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.getDistanceFromEyePoint( 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 MultiSwitch::traverse(osg::NodeVisitor& nv) { if (nv.getTraversalMode()==osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) { if (_activeSwitchSet<_values.size()) { for(unsigned int pos=0;pos<_children.size();++pos) { if (_values[_activeSwitchSet][pos]) _children[pos]->accept(nv); } } } else { Group::traverse(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; } }
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 Effect::traverse(osg::NodeVisitor& nv) { // if this effect is not enabled, then go for default traversal if (!_enabled) { inherited_traverse(nv); return; } // ensure that at least one technique is defined if (!_techs_defined) { // clear existing techniques _techs.clear(); // clear technique selection indices _sel_tech.clear(); // clear technique selection flags _tech_selected.clear(); // define new techniques _techs_defined = define_techniques(); // check for errors, return on failure if (!_techs_defined) { OSG_WARN << "Warning: osgFX::Effect: could not define techniques for effect " << className() << std::endl; return; } // ensure that at least one technique has been defined if (_techs.empty()) { OSG_WARN << "Warning: osgFX::Effect: no techniques defined for effect " << className() << std::endl; return; } } Technique *tech = 0; // if the selection mode is set to AUTO_DETECT then we have to // choose the active technique! if (_global_sel_tech == AUTO_DETECT) { // test whether at least one technique has been selected bool none_selected = true; for (unsigned i=0; i<_tech_selected.size(); ++i) { if (_tech_selected[i] != 0) { none_selected = false; break; } } // no techniques selected, traverse a dummy node that // contains the Validator (it will select a technique) if (none_selected) { _dummy_for_validation->accept(nv); } // find the highest priority technique that could be validated // in all active rendering contexts int max_index = -1; for (unsigned j=0; j<_sel_tech.size(); ++j) { if (_tech_selected[j] != 0) { if (_sel_tech[j] > max_index) { max_index = _sel_tech[j]; } } } // found a valid technique? if (max_index >= 0) { tech = _techs[max_index].get(); } } else { // the active technique was selected manually tech = _techs[_global_sel_tech].get(); } // if we could find an active technique, then continue with traversal, // else go for default traversal (no effect) if (tech) { tech->traverse(nv, this); } else { if (nv.getTraversalMode() == osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { inherited_traverse(nv); } } // wow, we're finished! :) }