Changeset 8546

Show
Ignore:
Timestamp:
07/07/08 22:27:56
Author:
robert
Message:

Implement hierachy culling in KdTree?::intersect(..)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • OpenSceneGraph/trunk/include/osg/KdTree

    r8544 r8546  
    3535        struct BuildOptions 
    3636        { 
    37             BuildOptions(): 
    38                 _numVerticesProcessed(0), 
    39                 _targetNumTrianglesPerLeaf(4), 
    40                 _maxNumLevels(24) {} 
     37            BuildOptions(); 
    4138                         
    4239            int _numVerticesProcessed; 
     
    164161        } 
    165162 
     163        const KdLeaf& getLeaf(int leafNum) const 
     164        { 
     165            int num = -leafNum-1; 
     166            if (num<0 || num>static_cast<int>(_kdLeaves.size())-1) 
     167            { 
     168                osg::notify(osg::NOTICE)<<"Warning: getLeaf("<<leafNum<<", num = "<<num<<") _kdLeaves.size()="<<_kdLeaves.size()<<std::endl; 
     169            } 
     170 
     171            return _kdLeaves[num]; 
     172        } 
     173 
    166174        int addNode(const KdNode& node) 
    167175        { 
     
    180188            return _kdNodes[nodeNum]; 
    181189        } 
    182          
    183         osg::BoundingBox& getBounindingBox(int nodeNum) 
     190 
     191        /// note, nodeNum is positive to distinguish from leftNum 
     192        const KdNode& getNode(int nodeNum) const 
     193        { 
     194            if (nodeNum<0 || nodeNum>static_cast<int>(_kdNodes.size())-1) 
     195            { 
     196                osg::notify(osg::NOTICE)<<"Warning: getNode("<<nodeNum<<") _kdNodes.size()="<<_kdNodes.size()<<std::endl; 
     197            } 
     198            return _kdNodes[nodeNum]; 
     199        } 
     200         
     201        osg::BoundingBox& getBoundingBox(int nodeNum) 
    184202        { 
    185203            if (nodeNum<0) 
     
    200218 
    201219        bool intersect(const KdLeaf& leaf, const osg::Vec3& start, const osg::Vec3& end, LineSegmentIntersections& intersections) const; 
     220        bool intersect(const KdNode& node, const osg::Vec3& start, const osg::Vec3& end, const osg::Vec3& s, const osg::Vec3& e, LineSegmentIntersections& intersections) const; 
     221        bool intersectAndClip(osg::Vec3& s, osg::Vec3& e, const osg::BoundingBox& bb) const; 
    202222 
    203223        typedef std::vector< osg::BoundingBox >                 BoundingBoxList; 
  • OpenSceneGraph/trunk/src/osg/KdTree.cpp

    r8544 r8546  
    2020using namespace osg; 
    2121 
    22 //#define VERBOSE_OUTPUT 
     22// #define VERBOSE_OUTPUT 
    2323 
    2424//////////////////////////////////////////////////////////////////////////////// 
     
    5858// KdTree 
    5959 
     60KdTree::BuildOptions::BuildOptions(): 
     61        _numVerticesProcessed(0), 
     62        _targetNumTrianglesPerLeaf(8), 
     63        _maxNumLevels(24) 
     64{ 
     65} 
     66 
     67//////////////////////////////////////////////////////////////////////////////// 
     68// 
     69// KdTree 
     70 
    6071KdTree::KdTree() 
    6172{ 
     
    118129    int nodeNum = divide(options, bb, leafNum, 0); 
    119130 
     131#if 0     
     132    for(KdLeafList::iterator itr = _kdLeaves.begin(); 
     133        itr != _kdLeaves.end(); 
     134        ++itr) 
     135    { 
     136        KdLeaf& leaf = *itr; 
     137        leaf.bb.init(); 
     138        int iend = leaf.first+leaf.second; 
     139        for(int i=leaf.first; i<iend; ++i) 
     140        { 
     141            const Triangle& tri = _triangles[_primitiveIndices[i]]; 
     142            const osg::Vec3& v1 = (*_vertices)[tri._p1]; 
     143            const osg::Vec3& v2 = (*_vertices)[tri._p2]; 
     144            const osg::Vec3& v3 = (*_vertices)[tri._p3]; 
     145            leaf.bb.expandBy(v1); 
     146            leaf.bb.expandBy(v2); 
     147            leaf.bb.expandBy(v3); 
     148        } 
     149        // osg::notify(osg::NOTICE)<<"leaf.bb.min("<<leaf.bb._min<<") max("<<leaf.bb._max<<")"<<std::endl; 
     150 
     151    } 
     152#endif 
     153     
    120154#ifdef VERBOSE_OUTPUT     
    121155    osg::notify(osg::NOTICE)<<"Root nodeNum="<<nodeNum<<std::endl; 
     
    187221    {     
    188222 
    189         if (getLeaf(nodeIndex).second<=options._targetNumTrianglesPerLeaf) return nodeIndex; 
     223        if (getLeaf(nodeIndex).second<=options._targetNumTrianglesPerLeaf)  
     224        { 
     225            // leaf is done, now compute bound on it. 
     226            KdLeaf& leaf = getLeaf(nodeIndex); 
     227            leaf.bb.init(); 
     228            int iend = leaf.first+leaf.second; 
     229            for(int i=leaf.first; i<iend; ++i) 
     230            { 
     231                const Triangle& tri = _triangles[_primitiveIndices[i]]; 
     232                const osg::Vec3& v1 = (*_vertices)[tri._p1]; 
     233                const osg::Vec3& v2 = (*_vertices)[tri._p2]; 
     234                const osg::Vec3& v3 = (*_vertices)[tri._p3]; 
     235                leaf.bb.expandBy(v1); 
     236                leaf.bb.expandBy(v2); 
     237                leaf.bb.expandBy(v3); 
     238            } 
     239 
     240            return nodeIndex; 
     241        } 
    190242 
    191243        //osg::notify(osg::NOTICE)<<"  divide leaf"<<std::endl; 
     
    293345        getNode(nodeNum).second = rightChildIndex;  
    294346         
     347        getNode(nodeNum).bb.init(); 
     348        if (leftChildIndex!=0) getNode(nodeNum).bb.expandBy(getBoundingBox(leftChildIndex)); 
     349        if (rightChildIndex!=0) getNode(nodeNum).bb.expandBy(getBoundingBox(rightChildIndex)); 
     350         
    295351        return nodeNum; 
    296352    } 
     
    424480        intersections.insert(intersection); 
    425481 
    426         osg::notify(osg::NOTICE)<<"  got intersection ("<<in<<") ratio="<<r<<std::endl; 
     482        // osg::notify(osg::NOTICE)<<"  got intersection ("<<in<<") ratio="<<r<<std::endl; 
    427483 
    428484        intersects = true; 
     
    432488} 
    433489 
     490bool KdTree::intersect(const KdNode& node, const osg::Vec3& start, const osg::Vec3& end, const osg::Vec3& s, const osg::Vec3& e, LineSegmentIntersections& intersections) const 
     491{ 
     492    //osg::notify(osg::NOTICE)<<"  Intersect "<<&node<<std::endl; 
     493    //osg::Vec3 ls(start), le(end); 
     494    osg::Vec3 ls(s), le(e); 
     495    int numIntersectionsBefore = intersections.size(); 
     496    if (intersectAndClip(ls, le, node.bb)) 
     497    { 
     498        if (node.first>0) intersect(getNode(node.first), start, end, ls, le, intersections); 
     499        else if (node.first<0) intersect(getLeaf(node.first), start, end, intersections); 
     500 
     501        if (node.second>0) intersect(getNode(node.second), start, end, ls, le, intersections); 
     502        else if (node.second<0) intersect(getLeaf(node.second), start, end, intersections); 
     503    } 
     504    return numIntersectionsBefore != intersections.size(); 
     505} 
     506 
     507bool KdTree::intersectAndClip(osg::Vec3& s, osg::Vec3& e, const osg::BoundingBox& bb) const 
     508{ 
     509    // compate s and e against the xMin to xMax range of bb. 
     510    if (s.x()<=e.x()) 
     511    { 
     512 
     513        // trivial reject of segment wholely outside. 
     514        if (e.x()<bb.xMin()) return false; 
     515        if (s.x()>bb.xMax()) return false; 
     516 
     517        if (s.x()<bb.xMin()) 
     518        { 
     519            // clip s to xMin. 
     520            s = s+(e-s)*(bb.xMin()-s.x())/(e.x()-s.x()); 
     521        } 
     522 
     523        if (e.x()>bb.xMax()) 
     524        { 
     525            // clip e to xMax. 
     526            e = s+(e-s)*(bb.xMax()-s.x())/(e.x()-s.x()); 
     527        } 
     528    } 
     529    else 
     530    { 
     531        if (s.x()<bb.xMin()) return false; 
     532        if (e.x()>bb.xMax()) return false; 
     533 
     534        if (e.x()<bb.xMin()) 
     535        { 
     536            // clip s to xMin. 
     537            e = s+(e-s)*(bb.xMin()-s.x())/(e.x()-s.x()); 
     538        } 
     539 
     540        if (s.x()>bb.xMax()) 
     541        { 
     542            // clip e to xMax. 
     543            s = s+(e-s)*(bb.xMax()-s.x())/(e.x()-s.x()); 
     544        } 
     545    } 
     546 
     547    // compate s and e against the yMin to yMax range of bb. 
     548    if (s.y()<=e.y()) 
     549    { 
     550 
     551        // trivial reject of segment wholely outside. 
     552        if (e.y()<bb.yMin()) return false; 
     553        if (s.y()>bb.yMax()) return false; 
     554 
     555        if (s.y()<bb.yMin()) 
     556        { 
     557            // clip s to yMin. 
     558            s = s+(e-s)*(bb.yMin()-s.y())/(e.y()-s.y()); 
     559        } 
     560 
     561        if (e.y()>bb.yMax()) 
     562        { 
     563            // clip e to yMax. 
     564            e = s+(e-s)*(bb.yMax()-s.y())/(e.y()-s.y()); 
     565        } 
     566    } 
     567    else 
     568    { 
     569        if (s.y()<bb.yMin()) return false; 
     570        if (e.y()>bb.yMax()) return false; 
     571 
     572        if (e.y()<bb.yMin()) 
     573        { 
     574            // clip s to yMin. 
     575            e = s+(e-s)*(bb.yMin()-s.y())/(e.y()-s.y()); 
     576        } 
     577 
     578        if (s.y()>bb.yMax()) 
     579        { 
     580            // clip e to yMax. 
     581            s = s+(e-s)*(bb.yMax()-s.y())/(e.y()-s.y()); 
     582        } 
     583    } 
     584 
     585    // compate s and e against the zMin to zMax range of bb. 
     586    if (s.z()<=e.z()) 
     587    { 
     588 
     589        // trivial reject of segment wholely outside. 
     590        if (e.z()<bb.zMin()) return false; 
     591        if (s.z()>bb.zMax()) return false; 
     592 
     593        if (s.z()<bb.zMin()) 
     594        { 
     595            // clip s to zMin. 
     596            s = s+(e-s)*(bb.zMin()-s.z())/(e.z()-s.z()); 
     597        } 
     598 
     599        if (e.z()>bb.zMax()) 
     600        { 
     601            // clip e to zMax. 
     602            e = s+(e-s)*(bb.zMax()-s.z())/(e.z()-s.z()); 
     603        } 
     604    } 
     605    else 
     606    { 
     607        if (s.z()<bb.zMin()) return false; 
     608        if (e.z()>bb.zMax()) return false; 
     609 
     610        if (e.z()<bb.zMin()) 
     611        { 
     612            // clip s to zMin. 
     613            e = s+(e-s)*(bb.zMin()-s.z())/(e.z()-s.z()); 
     614        } 
     615 
     616        if (s.z()>bb.zMax()) 
     617        { 
     618            // clip e to zMax. 
     619            s = s+(e-s)*(bb.zMax()-s.z())/(e.z()-s.z()); 
     620        } 
     621    } 
     622     
     623    // osg::notify(osg::NOTICE)<<"clampped segment "<<s<<" "<<e<<std::endl; 
     624     
     625    // if (s==e) return false; 
     626 
     627    return true;     
     628} 
     629 
    434630bool KdTree::intersect(const osg::Vec3& start, const osg::Vec3& end, LineSegmentIntersections& intersections) const 
    435631{ 
    436     // osg::notify(osg::NOTICE)<<"KdTree::intersect("<<start<<","<<end<<")"<<std::endl; 
    437  
     632    //osg::notify(osg::NOTICE)<<"KdTree::intersect("<<start<<","<<end<<")"<<std::endl; 
    438633    bool intersects = false; 
    439     for(KdLeafList::const_iterator itr = _kdLeaves.begin(); 
    440         itr != _kdLeaves.end(); 
    441         ++itr) 
    442     { 
    443         if (intersect(*itr, start, end, intersections)) intersects = true; 
     634     
     635    int option = 2; 
     636    switch(option) 
     637    { 
     638        case(0): 
     639        { 
     640            for(KdLeafList::const_iterator itr = _kdLeaves.begin(); 
     641                itr != _kdLeaves.end(); 
     642                ++itr) 
     643            { 
     644                if (intersect(*itr, start, end, intersections)) intersects = true; 
     645            } 
     646            break; 
     647        } 
     648 
     649        case(1): 
     650        { 
     651            for(KdLeafList::const_iterator itr = _kdLeaves.begin(); 
     652                itr != _kdLeaves.end(); 
     653                ++itr) 
     654            { 
     655                osg::Vec3 s(start), e(end); 
     656                if (intersectAndClip(s,e,itr->bb)) 
     657                { 
     658                    if (intersect(*itr, start, end, intersections)) intersects = true; 
     659                } 
     660            } 
     661            break; 
     662        } 
     663 
     664        case(2): 
     665        { 
     666            //osg::notify(osg::NOTICE)<<"_kdNodes.size()="<<_kdNodes.size()<<std::endl; 
     667            osg::Vec3 s(start), e(end); 
     668            if (intersect(getNode(0), start, end, s,e, intersections)) intersects = true; 
     669            break; 
     670        } 
    444671    } 
    445672 
  • OpenSceneGraph/trunk/src/osgUtil/LineSegmentIntersector.cpp

    r8545 r8546  
    2020#include <osg/TriangleFunctor> 
    2121#include <osg/KdTree> 
     22#include <osg/Timer> 
    2223 
    2324using namespace osgUtil; 
     
    295296    } 
    296297     
     298    osg::Timer_t before_kdTree = osg::Timer::instance()->tick(); 
     299    unsigned int numKdTreeHits = 0; 
     300    unsigned int numConventionalHits = 0; 
     301     
    297302    osg::KdTree* kdTree = dynamic_cast<osg::KdTree*>(drawable->getShape()); 
     303    osg::Vec3d kdTreeHit; 
    298304    if (kdTree) 
    299305    { 
     
    301307        if (kdTree->intersect(s,e,intersections)) 
    302308        { 
    303             osg::notify(osg::NOTICE)<<"Got KdTree intersections"<<std::endl; 
     309            // osg::notify(osg::NOTICE)<<"Got KdTree intersections"<<std::endl; 
    304310            for(osg::KdTree::LineSegmentIntersections::iterator itr = intersections.begin(); 
    305311                itr != intersections.end(); 
     
    323329 
    324330                hit.localIntersectionPoint = _start*(1.0-remap_ratio) + _end*remap_ratio; 
     331                kdTreeHit = hit.localIntersectionPoint; 
    325332                 
    326                 osg::notify(osg::NOTICE)<<"KdTree: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl; 
     333                // osg::notify(osg::NOTICE)<<"KdTree: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl; 
    327334                 
    328335                hit.localIntersectionNormal = lsi.intersectionNormal; 
     
    331338                hit.ratioList.swap(lsi.ratioList); 
    332339 
     340                ++numKdTreeHits; 
    333341                insertIntersection(hit); 
    334342 
     
    336344        } 
    337345         
    338         return; 
     346        // return; 
    339347    } 
    340348    else 
     
    342350        // osg::notify(osg::NOTICE)<<"Not KdTree available"<<std::endl; 
    343351    } 
     352 
     353    osg::Timer_t after_kdTree = osg::Timer::instance()->tick(); 
    344354 
    345355    osg::TriangleFunctor<LineSegmentIntersectorUtils::TriangleIntersector> ti; 
     
    347357    drawable->accept(ti); 
    348358 
     359    osg::Vec3d conventionalHit; 
    349360    if (ti._hit) 
    350361    { 
     
    372383 
    373384            hit.localIntersectionPoint = _start*(1.0-remap_ratio) + _end*remap_ratio; 
     385            conventionalHit = hit.localIntersectionPoint; 
    374386 
    375387            // osg::notify(osg::NOTICE)<<"Conventional: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl; 
     
    402414             
    403415            insertIntersection(hit); 
    404  
    405         } 
    406     } 
    407      
     416            ++numConventionalHits; 
     417 
     418        } 
     419    } 
     420     
     421    osg::Timer_t after_conventional = osg::Timer::instance()->tick(); 
     422     
     423    double timeKdTree = osg::Timer::instance()->delta_m(before_kdTree, after_kdTree); 
     424    double timeConventional = osg::Timer::instance()->delta_m(after_kdTree, after_conventional); 
     425 
     426#if 1 
     427    if (kdTree) 
     428    { 
     429        osg::notify(osg::NOTICE)<<"KdTree       ("<<kdTreeHit<<") intersections = "<<numKdTreeHits<< " time = "<<timeKdTree<<std::endl; 
     430        osg::notify(osg::NOTICE)<<"Conventional ("<<conventionalHit<<") intersections = "<<numConventionalHits<< " time = "<<timeConventional<<std::endl; 
     431        osg::notify(osg::NOTICE)<<"Ratio = "<<timeConventional/timeKdTree<<std::endl; 
     432        osg::notify(osg::NOTICE)<<std::endl; 
     433    } 
     434#endif 
    408435} 
    409436