IteratorBVH.cc

Go to the documentation of this file.
00001 #include <esg/iterator/IteratorBVH.h>
00002 #include <esg/Statistics.h>
00003 
00004 using namespace esg;
00005 
00006 #ifdef ESG_STATISTICS
00007 #define BVH_INC_TEST     { _bvTestsCounter++; }
00008 #define BVH_INC_SUC_TEST { _bvTestsSucCounter++; }
00009 #define BVH_UPDATE_STAT  { \
00010     ((Counter*)Statistics::instance()->get(Statistics::OID_BV_TESTS)->receptor())->add(_bvTestsCounter); \
00011     ((Counter*)Statistics::instance()->get(Statistics::OID_BV_TESTS_SUC)->receptor())->add(_bvTestsSucCounter); \
00012     _bvTestsCounter = (_bvTestsSucCounter = 0); \
00013 }
00014 #else
00015 #define BVH_INC_TEST     {}
00016 #define BVH_INC_SUC_TEST {}
00017 #define BVH_UPDATE_STAT  {}
00018 #endif // ESG_STATISTICS
00019 
00020 #define BVH_BACKTRACK { \
00021     do { \
00022         pNode = _stack.back(); _stack.pop_back(); \
00023         BVH_INC_TEST; \
00024         pNode->bv->rayIntersection(&(_riAttr->iEnv), \
00025                                    ENV_WANT_INTERFERENCE|ENV_USE_CACHE, \
00026                                    _riAttr->origin, \
00027                                    _riAttr->direction, \
00028                                    _riAttr->distLimit); \
00029         if (!_riAttr->iEnv.mask & ENV_HAVE_INTERFERENCE) pNode = NULL; \
00030         else BVH_INC_SUC_TEST; \
00031     } while (!pNode && !_stack.empty()); \
00032 }
00033 
00034 
00035 SceneGraphObject* IteratorBVH::_first_ray_intersection(BVH::Node* pNode)
00036 {
00037     /*
00038      * Initial preconditions for this non-recursive top-down traversal:
00039      *    _pLastUsedChild == NULL
00040      *    [_pBottomUpNode  == NULL]
00041      *    _stack.empty()  == true
00042      *
00043      * Output:
00044      *    succcessful leaf 
00045      *    _stack filled by unchecked branches
00046      */
00047 
00048     while (pNode) {
00049         if (pNode->leaf) { // we are in leaf in the first time
00050             _pLastUsedChild = pNode;
00051             return pNode->list->firstItem();
00052         }
00053 
00054         // we are in inner node
00055         BVH_INC_TEST;
00056         pNode->leftChild->bv->rayIntersection(&(_riAttr->iEnv),
00057                                               ENV_WANT_INTERFERENCE|ENV_USE_CACHE,
00058                                               _riAttr->origin,
00059                                               _riAttr->direction,
00060                                               _riAttr->distLimit);
00061         if (_riAttr->iEnv.mask & ENV_HAVE_INTERFERENCE) {
00062             BVH_INC_SUC_TEST;
00063             _stack.push_back(pNode->rightChild);
00064             pNode = pNode->leftChild;
00065             continue;
00066         }
00067 
00068         BVH_INC_TEST;
00069         pNode = pNode->rightChild;
00070         pNode->bv->rayIntersection(&(_riAttr->iEnv),
00071                                    ENV_WANT_INTERFERENCE|ENV_USE_CACHE,
00072                                    _riAttr->origin,
00073                                    _riAttr->direction,
00074                                    _riAttr->distLimit);
00075         if (_riAttr->iEnv.mask & ENV_HAVE_INTERFERENCE) {
00076             BVH_INC_SUC_TEST;
00077             continue;
00078         }
00079 
00080         if (_stack.empty()) return NULL;
00081         
00082         BVH_BACKTRACK;
00083     } // while (pNode)
00084 
00085     return NULL;
00086 }
00087 
00088 SceneGraphObject* IteratorBVH::_next_ray_intersection(void)
00089 {
00090     /*
00091      * Initial preconditions:
00092      *    _pLastUsedChild != NULL
00093      *    _stack contain untraversed branches
00094      *    inspection of _pLastUsedChild is done
00095      */
00096     
00097     /*
00098      * Inspection of actual leaf is done here
00099      */
00100     BVH::Node * pNode;
00101     do {
00102         if (_stack.empty()) {
00103             /*
00104              * Stack is empty => actual sub-tree is inspected 
00105              */
00106             
00107             if (!_pBottomUpNode) return NULL; // Entire tree is inspected
00108             
00109             pNode = _pBottomUpNode; // Store branch for following inspection
00110             
00111             /*
00112              * Find and store upper colliding branch
00113              */
00114             while (true) {
00115                 if (!_pBottomUpNode->parent||!_pBottomUpNode->parent->sibling){
00116                     _pBottomUpNode = NULL;
00117                     break;
00118                 }
00119 
00120                 BVH_INC_TEST;
00121                 _pBottomUpNode = _pBottomUpNode->parent->sibling;
00122                 _pBottomUpNode->bv->rayIntersection(&(_riAttr->iEnv),
00123                                                     ENV_WANT_INTERFERENCE|
00124                                                     ENV_USE_CACHE,
00125                                                     _riAttr->origin,
00126                                                     _riAttr->direction,
00127                                                     _riAttr->distLimit);
00128                 if (_riAttr->iEnv.mask & ENV_HAVE_INTERFERENCE) {
00129                     BVH_INC_SUC_TEST;
00130                     break;
00131                 }
00132             }
00133         } else {
00134             /*
00135              * Node in stack => traverse down this branch
00136              */
00137             BVH_BACKTRACK;
00138         }
00139         
00140         /*
00141          * Now we have branch for inspection in pNode and upper colliding
00142          * branch for future inspection in _pBottomUpNode (if exists)
00143          */
00144         
00145         while (pNode) {
00146             if (pNode->leaf) { // we are in leaf in the first time
00147                 _pLastUsedChild = pNode;
00148                 return pNode->list->firstItem();
00149             }
00150 
00151             BVH_INC_TEST;
00152             // we are in inner node
00153             pNode->leftChild->bv->rayIntersection(&(_riAttr->iEnv),
00154                                                   ENV_WANT_INTERFERENCE|ENV_USE_CACHE,
00155                                                   _riAttr->origin,
00156                                                   _riAttr->direction,
00157                                                   _riAttr->distLimit);
00158             if (_riAttr->iEnv.mask & ENV_HAVE_INTERFERENCE) {
00159                 BVH_INC_SUC_TEST;
00160                 _stack.push_back(pNode->rightChild);
00161                 pNode = pNode->leftChild;
00162                 continue;
00163             }
00164 
00165             BVH_INC_TEST;
00166             pNode = pNode->rightChild;
00167             pNode->bv->rayIntersection(&(_riAttr->iEnv),
00168                                        ENV_WANT_INTERFERENCE|ENV_USE_CACHE,
00169                                        _riAttr->origin,
00170                                        _riAttr->direction,
00171                                        _riAttr->distLimit);
00172             if (_riAttr->iEnv.mask & ENV_HAVE_INTERFERENCE) {
00173                 BVH_INC_SUC_TEST;
00174                 continue;
00175             }
00176             
00177             if (_stack.empty()) { pNode = NULL; continue; }
00178 
00179             BVH_BACKTRACK;
00180         } // while (pNode)
00181     } while (_pBottomUpNode);
00182 
00183     return NULL;
00184 }
00185 
00186 #undef BVH_BACKTRACK
00187 
00188 SceneGraphObject* IteratorBVH::_halfspace_search(void)
00189 {
00190     SceneGraphObject * pObj;
00191     BVH::Node        * pNode;
00192     Interval           interval;
00193     float              dist;
00194 
00195     if (_pLastUsedChild) {
00196         pObj = _pLastUsedChild->list->nextItem();
00197         if (pObj) return pObj;
00198     }
00199 
00200     while (!_stack.empty()) {
00201         pNode = _stack.back();
00202         _stack.pop_back();
00203 
00204         // is the actual node "interesting"?
00205         interval = pNode->bv->extent(_hsAttr->direction);
00206         dist     = _hsAttr->origin.dot(_hsAttr->direction);
00207         if (interval.max < dist) continue;
00208 
00209         if (pNode->leaf) { // first visit during this traverse
00210             _pLastUsedChild = pNode;
00211             return pNode->list->firstItem();
00212         }
00213 
00214         _stack.push_back(pNode->rightChild);
00215         _stack.push_back(pNode->leftChild);
00216     }
00217 
00218     return NULL;
00219 }
00220 
00221 SceneGraphObject* IteratorBVH::_area_search(void)
00222 {
00223     SceneGraphObject * pObj;
00224     BVH::Node        * pNode;
00225 
00226     if (_pLastUsedChild) {
00227         pObj = _pLastUsedChild->list->nextItem();
00228         if (pObj) return pObj;
00229     }
00230 
00231     while (!_stack.empty()) {
00232         pNode = _stack.back();
00233         _stack.pop_back();
00234 
00235         // is the actual node "interesting"?
00236         if (pNode->bv->separation(*(_arAttr->area), NULL)) continue;
00237 
00238         if (pNode->leaf) { // first visit during this traverse
00239             _pLastUsedChild = pNode;
00240             return pNode->list->firstItem();
00241         }
00242 
00243         _stack.push_back(pNode->rightChild);
00244         _stack.push_back(pNode->leftChild);
00245     }
00246     
00247     return NULL;
00248 }
00249 
00250 SceneGraphObject* IteratorBVH::_children_search(void)
00251 {
00252     // we are in leaf and we was there already in the past:
00253     if (_pLastUsedChild) {
00254         SceneGraphObject* pObject = _pLastUsedChild->list->nextItem();
00255         if (pObject) return pObject;
00256         _pLastUsedChild = _pLastUsedChild->rightChild;
00257     }
00258     else 
00259         _pLastUsedChild = ((BVH*)_pAggregate)->_leftLeaf;
00260   
00261     if (_pLastUsedChild) return _pLastUsedChild->list->firstItem();
00262     else return NULL;
00263 }
00264 
00265 SceneGraphObject* IteratorBVH::_first_child()
00266 {
00267     while (!_stack.empty()) _stack.pop_back();
00268     
00269 #ifdef ESG_STATISTICS
00270     SceneGraphObject * pRet;
00271 
00272     if (_traverse == RAY_INTERSECTION && _riAttr) {
00273         if (_riAttr->parentElement) {
00274             _pLastUsedChild = (BVH::Node*) _riAttr->parentElement;
00275             _pBottomUpNode = _pLastUsedChild->sibling;
00276             return _pLastUsedChild->list->firstItem();
00277         } else {
00278             _pLastUsedChild = NULL;
00279             _pBottomUpNode  = NULL;
00280             if (!(pRet = _first_ray_intersection(((BVH*)_pAggregate)->_root)))
00281                 BVH_UPDATE_STAT;
00282             return pRet;
00283         }
00284     }
00285     
00286     _pLastUsedChild = NULL;
00287     _pBottomUpNode = NULL;
00288 
00289     if (!((BVH*)_pAggregate)->_root) return NULL;
00290   
00291     if (_traverse == HALF_SPACE && _hsAttr) {
00292         _stack.push_back(((BVH*)_pAggregate)->_root);
00293         if (!(pRet = _halfspace_search())) BVH_UPDATE_STAT;
00294         return pRet;
00295     }
00296     
00297     if (_traverse == AREA && _arAttr) {
00298         _stack.push_back(((BVH*)_pAggregate)->_root);
00299         if (!(pRet = _area_search())) BVH_UPDATE_STAT;
00300         return pRet;
00301     }
00302     
00303     if (_traverse == CHILDREN) {
00304         if (!(pRet = _children_search())) BVH_UPDATE_STAT;
00305         return pRet;
00306     }
00307 
00308 #else
00309     if (_traverse == RAY_INTERSECTION && _riAttr) {
00310         if (_riAttr->parentElement) {
00311             _pLastUsedChild = (BVH::Node*) _riAttr->parentElement;
00312             _pBottomUpNode = _pLastUsedChild->sibling;
00313             return _pLastUsedChild->list->firstItem();
00314         } else {
00315             _pLastUsedChild = NULL;
00316             _pBottomUpNode  = NULL;
00317             return _first_ray_intersection(((BVH*)_pAggregate)->_root);
00318         }
00319     }
00320 
00321     _pLastUsedChild = NULL;
00322     _pBottomUpNode = NULL;
00323 
00324     if (!((BVH*)_pAggregate)->_root) return NULL;
00325   
00326     if (_traverse == HALF_SPACE && _hsAttr) {
00327         _stack.push_back(((BVH*)_pAggregate)->_root);
00328         return _halfspace_search();
00329     }
00330     
00331     if (_traverse == AREA && _arAttr) {
00332         _stack.push_back(((BVH*)_pAggregate)->_root);
00333         return _area_search();
00334     }
00335     
00336     if (_traverse == CHILDREN)
00337         return _children_search();
00338 #endif // ESG_STATISTICS        
00339 
00340     return NULL;
00341 }
00342 
00343 SceneGraphObject* IteratorBVH::_next_child()
00344 {
00345 #ifdef ESG_STATISTICS
00346     SceneGraphObject* pRet;
00347 
00348     if (!_pLastUsedChild) { BVH_UPDATE_STAT; return NULL; }
00349   
00350     if (_traverse == RAY_INTERSECTION && _riAttr) {
00351         SceneGraphObject * pObj = _pLastUsedChild->list->nextItem();
00352         if (pObj) return pObj;
00353         else {
00354             if (!(pRet = _next_ray_intersection())) BVH_UPDATE_STAT;
00355             return pRet;
00356         }
00357     }
00358     
00359     if (_traverse == HALF_SPACE && _hsAttr) {
00360         if (!(pRet = _halfspace_search())) BVH_UPDATE_STAT;
00361         return pRet;
00362     }
00363   
00364     if (_traverse == AREA && _arAttr) {
00365         if (!(pRet = _area_search())) BVH_UPDATE_STAT;
00366         return pRet;
00367     }
00368   
00369     if (_traverse == CHILDREN) {
00370         if (!(pRet = _children_search())) BVH_UPDATE_STAT;
00371         return pRet;
00372     }
00373 
00374 #else 
00375     if (!_pLastUsedChild) return NULL; 
00376     if (_traverse == RAY_INTERSECTION && _riAttr) {
00377         SceneGraphObject * pObj = _pLastUsedChild->list->nextItem();
00378         if (pObj) return pObj; else return _next_ray_intersection();
00379     }
00380     if (_traverse == HALF_SPACE && _hsAttr) return _halfspace_search();
00381     if (_traverse == AREA && _arAttr)       return _area_search();
00382     if (_traverse == CHILDREN)              return _children_search();
00383 #endif // ESG_STATISTICS    
00384 
00385     return NULL;
00386 }
00387 
00388 
00389 //--------- public ---------
00390 
00391 IteratorBVH::IteratorBVH(BVH* bvh)
00392     : IteratorSDS((SDS*) bvh)
00393 {
00394     _pLastUsedChild = NULL;
00395 #ifdef ESG_STATISTICS
00396     _bvTestsCounter = 0;
00397     _bvTestsSucCounter = 0;
00398 #endif // ESG_STATISTICS
00399 }
00400 
00401 #if 0
00402 Geometry* IteratorBVH::delimitBoundary(void) const
00403 {
00404     if (!((BVH*)_pAggregate)->_root) return NULL;
00405     else return (Geometry*) ((BVH*)_pAggregate)->_root->bv->clone();
00406 }
00407 #endif
00408 
00409 
00410 
00411 #ifdef ESG_STATISTICS
00412 #undef BVH_INC_TEST    
00413 #undef BVH_INC_SUC_TEST
00414 #undef BVH_UPDATE_STAT
00415 #endif // ESG_STATISTICS
00416 
00417 

Generated on Wed Jun 28 12:24:31 2006 for esg by  doxygen 1.4.6