Example #1
0
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 );
    }
}
Example #2
0
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);
    }
}
Example #3
0
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 );
    }
}
Example #4
0
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);
    }
}
Example #5
0
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;
    }
}
Example #7
0
void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
{

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

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

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

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

            int lastChildTraversed = -1;
            bool needToLoadChild = false;

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

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

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

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

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

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

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

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

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


            }


           break;
        }
        default:
            break;
    }
}
Example #8
0
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! :)
}