void ScreenMVCullVisitor::apply(Billboard& node)
{
    bool status = _cullingStatus;
    bool firstStatus = _firstCullStatus;
    if(isCulled(node))
    {
        _firstCullStatus = firstStatus;
        _cullingStatus = status;
        return;
    }

    // push the node's state.
    StateSet* node_state = node.getStateSet();
    if(node_state)
        pushStateSet(node_state);

    // traverse any call callbacks and traverse any children.
    handle_cull_callbacks_and_traverse(node);

    const Vec3& eye_local = getEyeLocal();
    const RefMatrix& modelview = *getModelViewMatrix();

    for(unsigned int i = 0; i < node.getNumDrawables(); ++i)
    {
        const Vec3& pos = node.getPosition(i);

        Drawable* drawable = node.getDrawable(i);
        // need to modify isCulled to handle the billboard offset.
        // if (isCulled(drawable->getBound())) continue;

        if(drawable->getCullCallback())
        {
            if(drawable->getCullCallback()->cull(this,drawable,&_renderInfo)
                    == true)
                continue;
        }

        RefMatrix* billboard_matrix = createOrReuseMatrix(modelview);

        node.computeMatrix(*billboard_matrix,eye_local,pos);

        if(_computeNearFar && drawable->getBound().valid())
            updateCalculatedNearFar(*billboard_matrix,*drawable,true);
        float depth = distance(pos,modelview);
        /*
         if (_computeNearFar)
         {
         if (d<_computed_znear)
         {
         if (d<0.0) OSG_NOTIFY(osg::WARN)<<"Alerting billboard handling ="<<d<< std::endl;
         _computed_znear = d;
         }
         if (d>_computed_zfar) _computed_zfar = d;
         }
         */
        StateSet* stateset = drawable->getStateSet();
        if(stateset)
            pushStateSet(stateset);

        if(osg::isNaN(depth))
        {
            /*OSG_NOTIFY(osg::NOTICE)<<"CullVisitor::apply(Billboard&) detected NaN,"<<std::endl
             <<"    depth="<<depth<<", pos=("<<pos<<"),"<<std::endl
             <<"    *billboard_matrix="<<*billboard_matrix<<std::endl;
             OSG_NOTIFY(osg::DEBUG_INFO) << "    NodePath:" << std::endl;
             for (NodePath::const_iterator i = getNodePath().begin(); i != getNodePath().end(); ++i)
             {
             OSG_NOTIFY(osg::DEBUG_INFO) << "        \"" << (*i)->getName() << "\"" << std::endl;
             }*/
        }
        else
        {
            addDrawableAndDepth(drawable,billboard_matrix,depth);
        }

        if(stateset)
            popStateSet();

    }

    // pop the node's state off the geostate stack.    
    if(node_state)
        popStateSet();

    _firstCullStatus = firstStatus;
    _cullingStatus = status;
}
void ScreenMVCullVisitor::apply(Geode& node)
{
    bool status = _cullingStatus;
    bool firstStatus = _firstCullStatus;
    if(isCulled(node))
    {
        _firstCullStatus = firstStatus;
        _cullingStatus = status;
        return;
    }

    // push the node's state.
    StateSet* node_state = node.getStateSet();
    if(node_state)
        pushStateSet(node_state);

    // traverse any call callbacks and traverse any children.
    handle_cull_callbacks_and_traverse(node);

    RefMatrix& matrix = *getModelViewMatrix();
    for(unsigned int i = 0; i < node.getNumDrawables(); ++i)
    {
        Drawable* drawable = node.getDrawable(i);
        const BoundingBox &bb = drawable->getBound();

        if(drawable->getCullCallback())
        {
            if(drawable->getCullCallback()->cull(this,drawable,&_renderInfo)
                    == true)
                continue;
        }

        //else
        {
            if(node.isCullingActive() && isCulled(bb))
                continue;
        }

        if(_computeNearFar && bb.valid())
        {
            if(!updateCalculatedNearFar(matrix,*drawable,false))
                continue;
        }

        // need to track how push/pops there are, so we can unravel the stack correctly.
        unsigned int numPopStateSetRequired = 0;

        // push the geoset's state on the geostate stack.    
        StateSet* stateset = drawable->getStateSet();
        if(stateset)
        {
            ++numPopStateSetRequired;
            pushStateSet(stateset);
        }

        CullingSet& cs = getCurrentCullingSet();
        if(!cs.getStateFrustumList().empty())
        {
            osg::CullingSet::StateFrustumList& sfl = cs.getStateFrustumList();
            for(osg::CullingSet::StateFrustumList::iterator itr = sfl.begin();
                    itr != sfl.end(); ++itr)
            {
                if(itr->second.contains(bb))
                {
                    ++numPopStateSetRequired;
                    pushStateSet(itr->first.get());
                }
            }
        }

        float depth = bb.valid() ? distance(bb.center(),matrix) : 0.0f;

        if(osg::isNaN(depth))
        {
            /*OSG_NOTIFY(osg::NOTICE)<<"CullVisitor::apply(Geode&) detected NaN,"<<std::endl
             <<"    depth="<<depth<<", center=("<<bb.center()<<"),"<<std::endl
             <<"    matrix="<<matrix<<std::endl;
             OSG_NOTIFY(osg::DEBUG_INFO) << "    NodePath:" << std::endl;
             for (NodePath::const_iterator i = getNodePath().begin(); i != getNodePath().end(); ++i)
             {
             OSG_NOTIFY(osg::DEBUG_INFO) << "        \"" << (*i)->getName() << "\"" << std::endl;
             }*/
        }
        else
        {
            addDrawableAndDepth(drawable,&matrix,depth);
        }

        for(unsigned int i = 0; i < numPopStateSetRequired; ++i)
        {
            popStateSet();
        }

    }

    // pop the node's state off the geostate stack.    
    if(node_state)
        popStateSet();

    _firstCullStatus = firstStatus;
    _cullingStatus = status;
}
Beispiel #3
0
bool IntersectVisitor::intersect(Drawable& drawable)
{
    bool hitFlag = false;

    IntersectState* cis = _intersectStateStack.back().get();

    const BoundingBox& bb = drawable.getBound();

    for(IntersectState::LineSegmentList::iterator sitr=cis->_segList.begin();
        sitr!=cis->_segList.end();
        ++sitr)
    {
        if (sitr->second->intersect(bb))
        {

            TriangleFunctor<TriangleIntersect> ti;
            ti.set(*sitr->second);
            drawable.accept(ti);
            if (ti._hit)
            {
            
                osg::Geometry* geometry = drawable.asGeometry();
                

                for(TriangleIntersect::TriangleHitList::iterator thitr=ti._thl.begin();
                    thitr!=ti._thl.end();
                    ++thitr)
                {
                
                    Hit hit;
                    hit._nodePath = _nodePath;
                    hit._matrix = cis->_model_matrix;
                    hit._inverse = cis->_model_inverse;
                    hit._drawable = &drawable;
                    if (_nodePath.empty()) hit._geode = NULL;
                    else hit._geode = dynamic_cast<Geode*>(_nodePath.back());

                    TriangleHit& triHit = thitr->second;
                    
                    hit._ratio = thitr->first;
                    hit._primitiveIndex = triHit._index;
                    hit._originalLineSegment = sitr->first;
                    hit._localLineSegment = sitr->second;

                    hit._intersectPoint = sitr->second->start()*(1.0f-hit._ratio)+
                        sitr->second->end()*hit._ratio;

                    hit._intersectNormal = triHit._normal;
                    
                    if (geometry)
                    {
                        osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
                        if (vertices)
                        {
                            osg::Vec3* first = &(vertices->front());
                            if (triHit._v1) hit._vecIndexList.push_back(triHit._v1-first);
                            if (triHit._v2) hit._vecIndexList.push_back(triHit._v2-first);
                            if (triHit._v3) hit._vecIndexList.push_back(triHit._v3-first);
                        }
                    }
                    

                    _segHitList[sitr->first.get()].push_back(hit);

                    std::sort(_segHitList[sitr->first.get()].begin(),_segHitList[sitr->first.get()].end());

                    hitFlag = true;

                }
            }
        }
    }

    return hitFlag;

}