BVH.cc

Go to the documentation of this file.
00001 #include <esg/spacesorting/BVH.h>
00002 #include <esg/spacesorting/BVDistRot.h>
00003 #include <esg/iterator/Iterator.h>
00004 #include <esg/iterator/IteratorBVH.h>
00005 #include <esg/InspectorBVH.h>
00006 
00007 using namespace esg;
00008 
00009 bool BVH::_append(SceneGraphObject*  obj,
00010                   Geometry*          bv,
00011                   Node*              node,
00012                   unsigned           depth)
00013 {
00014     if (!node) return false;
00015 
00016     if (node->leaf) {
00017         node->list->append(obj);
00018         // Need/can we  increase tree depth?
00019         if (node->list->length() > _leafLimit && depth < _depthLimit) {
00020             // create new nodes:
00021             Node* newLeftLeaf    = new Node;
00022             Node* newRightLeaf   = new Node;
00023             // setup new right leaf:
00024             newRightLeaf->leaf        = true;
00025 
00026             newRightLeaf->list = _create_list();
00027 
00028             (void) node->list->split(*(newRightLeaf->list), _splitStrategy);
00029             
00030             //newRightLeaf->list        = _split_list(*(node->list));
00031             newRightLeaf->leftChild   = newLeftLeaf;
00032             newRightLeaf->rightChild  = node->rightChild;
00033             newRightLeaf->parent      = node;
00034             newRightLeaf->sibling     = newLeftLeaf;
00035             newRightLeaf->bv          = _create_bv(*(newRightLeaf->list));
00036             // setup new left leaf:
00037             newLeftLeaf->leaf        = true;
00038             newLeftLeaf->list        = node->list;
00039             newLeftLeaf->leftChild   = node->leftChild;
00040             newLeftLeaf->rightChild  = newRightLeaf;
00041             newLeftLeaf->parent      = node;
00042             newLeftLeaf->sibling     = newRightLeaf;
00043             newLeftLeaf->bv          = _create_bv(*(newLeftLeaf->list));
00044             // setup its original right sibling:
00045             if (node->rightChild)
00046                 node->rightChild->leftChild = newRightLeaf;
00047             // setup its original left sibling:
00048             if (node->leftChild)
00049                 node->leftChild->rightChild = newLeftLeaf;
00050             // setup itself:
00051             node->leaf        = false;
00052             node->list        = NULL;
00053             node->leftChild   = newLeftLeaf;
00054             node->rightChild  = newRightLeaf;
00055             delete node->bv;
00056             node->bv          = _create_bv(*(newLeftLeaf->bv),
00057                                            *(newRightLeaf->bv));
00058             if (_leftLeaf == node) _leftLeaf = node->leftChild;
00059             return true;
00060         }
00061         else 
00062             return _enlarge_bv(&(node->bv), *bv);
00063     }
00064     else { // inner node
00065         double dist1 = bv->distance(*(node->leftChild->bv),  NULL);
00066         double dist2 = bv->distance(*(node->rightChild->bv), NULL);
00067         bool   bvChanged;
00068 
00069         if (dist1 <= dist2) // visit the most closed branch
00070             bvChanged = _append(obj, bv, node->leftChild,  depth+1);
00071         else 
00072             bvChanged = _append(obj, bv, node->rightChild, depth+1);
00073 
00074         if (bvChanged) {  // recompute BV if necessarry
00075             Geometry* pNewBV = _create_bv(*(node->leftChild->bv),
00076                                           *(node->rightChild->bv));
00077             bvChanged = _enlarge_bv(&(node->bv), *pNewBV);
00078             delete pNewBV;
00079         }
00080 
00081         return bvChanged;
00082     }
00083 }
00084 
00085 
00086 void BVH::_remove_leaf(Node* leaf)
00087 {
00088     if (!leaf->parent) { // leaf is also root
00089         _leftLeaf = (_root = NULL);
00090         delete leaf->list;
00091         delete leaf->bv;
00092         delete leaf;
00093         return;
00094     }
00095 
00096     Node* grandparent = leaf->parent->parent;
00097     Node* sibling;
00098 
00099     // find leaf's sibling
00100     if (leaf->parent->leftChild == leaf)
00101         sibling = leaf->parent->rightChild;
00102     else
00103         sibling = leaf->parent->leftChild;
00104 
00105     if (grandparent) {
00106         // connect sibling with grandparent
00107         if (grandparent->leftChild == leaf->parent)
00108             grandparent->leftChild = sibling;
00109         else
00110             grandparent->rightChild = sibling;
00111         sibling->parent = grandparent;
00112 
00113         // correct leaves concatenation
00114         if (sibling->leftChild == leaf)
00115             sibling->leftChild  = leaf->leftChild;
00116         else
00117             sibling->rightChild = leaf->rightChild;
00118     } else { // no grandparent
00119         _root               = sibling;
00120         sibling->parent     = NULL;
00121         sibling->leftChild  = NULL;
00122         sibling->rightChild = NULL;
00123     }
00124 
00125     // destroy leaf
00126     delete leaf->parent->bv;
00127     delete leaf->parent;
00128     delete leaf->bv;
00129     delete leaf->list;
00130     delete leaf;
00131 
00132     // recompute BVs
00133     for (Node* node = sibling->parent; node != NULL; node = node->parent) {
00134         delete node->bv;
00135         node->bv = _create_bv(*(node->leftChild->bv),
00136                               *(node->rightChild->bv));
00137     }
00138 
00139     // setup most-left leaf pointer
00140     if (_leftLeaf == leaf) _leftLeaf = sibling;
00141 }
00142 
00143 void BVH::_build_tree(Node* leaf, unsigned depth)
00144 {
00145     if (!leaf || !leaf->leaf || !leaf->list) return;
00146 
00147     // "non-separable" leaf:
00148     if (leaf->list->length() <= _leafLimit || depth >= _depthLimit) {
00149         if (leaf->bv) delete leaf->bv;
00150         leaf->bv = _create_bv(*(leaf->list));
00151         return;
00152     }
00153 
00154     // "separable" leaf:
00155     // store original leaf siblings first
00156     Node* leftSibling            = leaf->leftChild;
00157     Node* rightSibling           = leaf->rightChild;
00158     // allocate new leaves
00159     leaf->leftChild              = new Node;
00160     leaf->rightChild             = new Node;
00161     leaf->leftChild->sibling     = leaf->rightChild;
00162     leaf->rightChild->sibling    = leaf->leftChild;
00163     // change leaf indicators properly
00164     leaf->leftChild->leaf        = true;
00165     leaf->rightChild->leaf       = true;
00166     leaf->leaf                   = false;
00167     // split original list into children
00168     leaf->leftChild->list = _create_list();
00169     (void) leaf->list->split(*(leaf->leftChild->list), _splitStrategy);
00170     leaf->rightChild->list       = leaf->list;
00171     leaf->list                   = NULL;
00172     // set up links of left child
00173     leaf->leftChild->parent      = leaf;
00174     leaf->leftChild->rightChild  = leaf->rightChild;
00175     leaf->leftChild->leftChild   = leftSibling;
00176     if (leftSibling) leftSibling->rightChild = leaf->leftChild;
00177     // set up links of right child
00178     leaf->rightChild->parent     = leaf;
00179     leaf->rightChild->leftChild  = leaf->leftChild;
00180     leaf->rightChild->rightChild = rightSibling;
00181     if (rightSibling) rightSibling->leftChild = leaf->rightChild;
00182     
00183     // set "the most left leaf" pointer
00184     if (_leftLeaf == leaf) _leftLeaf = leaf->leftChild;
00185     
00186     // go recursivelly into the new children
00187     _build_tree(leaf->leftChild,  depth+1);
00188     _build_tree(leaf->rightChild, depth+1);
00189     
00190     // recompute BV of (now) inner node
00191     if (leaf->bv) delete leaf->bv;
00192     leaf->bv = _create_bv(*(leaf->leftChild->bv), *(leaf->rightChild->bv));
00193 }
00194 
00195 void BVH::_destroy_tree(Node* node)
00196 {
00197     if (node->leaf) {
00198         /*
00199         SceneGraphObject* pObj = node->list->firstItem();
00200         while (pObj) {
00201             node->list->remove(pObj);
00202             delete pObj;
00203             pObj = node->list->firstItem();
00204         }
00205         */
00206         delete node->list; // non-destructive
00207     } else {
00208         _destroy_tree(node->leftChild);
00209         _destroy_tree(node->rightChild);
00210     }
00211 
00212     delete node->bv;
00213     delete node;
00214 }
00215 
00216 void BVH::_rebuild_tree(Node* pNode)
00217 {
00218     delete pNode->bv;
00219     if (pNode->leaf)
00220         pNode->bv = _create_bv(*(pNode->list));
00221     else {
00222         _rebuild_tree(pNode->leftChild);
00223         _rebuild_tree(pNode->rightChild);
00224         pNode->bv = _create_bv(*(pNode->leftChild->bv),
00225                                *(pNode->rightChild->bv));
00226     }
00227 }
00228 
00229 Geometry* BVH::_create_bv(BVList& list)
00230 {
00231     List<SceneGraphObject> tmpList;
00232     SceneGraphObject*      pObject = list.firstItem();
00233     while (pObject) {
00234         tmpList.append(pObject);
00235         pObject = list.nextItem();
00236     }
00237 
00238     return _create_bv(tmpList);
00239 }
00240 
00241 void BVH::_collision(Node * pMyNode, Geometry& bv,
00242                      List<SceneGraphObject>* pList)
00243 {
00244     if (pMyNode->bv->separation(bv, NULL)) return;
00245     
00246     if (pMyNode->leaf) {
00247         for (SceneGraphObject * pObj = pMyNode->list->firstItem();
00248              pObj;
00249              pObj = pMyNode->list->nextItem())
00250         {
00251             pList->append(pObj);
00252         }
00253     } else {
00254         _collision(pMyNode->leftChild, bv, pList);
00255         _collision(pMyNode->rightChild, bv, pList);
00256     }
00257 }
00258 
00259 void BVH::_dump(const Node* pNode, const char* intent, const char* tab)
00260 {
00261     char* newIntent = new char [strlen(intent) + strlen(tab) + 2];
00262     newIntent = strcpy(newIntent, intent);
00263     newIntent = strcat(newIntent, " ");
00264     newIntent = strcat(newIntent, tab);
00265     
00266     printf("%s bvhNode {\n", intent);
00267     if (pNode->bv) pNode->bv->dump(newIntent, tab);
00268     if (pNode->leaf && pNode->list) {
00269         for (SceneGraphObject * pObj = pNode->list->firstItem();
00270              pObj;
00271              pObj = pNode->list->nextItem())
00272         {
00273             // to do: dumping of whole scene graph object
00274             if (pObj->geometry()) pObj->geometry()->dump(newIntent,tab);
00275         }
00276     } else {
00277         _dump(pNode->leftChild,  newIntent, tab);
00278         _dump(pNode->rightChild, newIntent, tab);
00279     }
00280     printf("%s }\n", intent);
00281     delete [] newIntent;
00282 }
00283 
00284 DistRot* BVH::_create_dist_rot(BVH::Node * pNode)
00285 {
00286     return new BVDistRot(*(pNode->bv), _coordMat, _scaleRatio);
00287 }
00288 
00289 void BVH::_dr_init(const Matrix4* pMyTr, const Matrix4* pHisTr, BVH* pPartner)
00290 {
00291     (pMyTr) ? _myTrMat.set(*pMyTr) : _myTrMat.setIdentity();
00292     
00293     Matrix4 * m = multiTrans(pHisTr, pMyTr, _scaleRatio);
00294     if (m) {
00295         _coordMat.set(*m);
00296         delete m;
00297     } else {
00298         _coordMat.setIdentity();
00299     }
00300 
00301     _pPartner = pPartner;
00302 }
00303 
00304 void BVH::_dr_primitives(DRInfo& dr, Node* pNode, Vector3* pDir)
00305 {
00306     /*
00307      * Handle primitives - HACK!
00308      */
00309     
00310     for (SceneGraphObject * pA = pNode->list->firstItem();
00311          pA;
00312          pA = pNode->list->nextItem())
00313     {
00314         Geometry * pGA = pA->geometry();
00315         if (!pGA) continue;
00316         
00317         for (SceneGraphObject * pB = dr.pLeaf->list->firstItem();
00318              pB;
00319              pB = dr.pLeaf->list->nextItem())
00320         {
00321             Geometry * pGB = pB->geometry();
00322             if (!pGB) continue;
00323             
00324             switch (dr.strategy) {
00325             case DRInfo::SEPARATION:
00326                 if (! pGA->separation(*pGB, pDir)) {
00327                     dr.minD = -MAXDOUBLE;
00328                     if (dr.leafInMe) {
00329                         dr.pLeafA = dr.pLeaf;
00330                         dr.pLeafB = pNode;
00331                     } else {
00332                         dr.pLeafA = pNode;
00333                         dr.pLeafB = dr.pLeaf;
00334                     }
00335                     return;
00336                 }
00337                 break;
00338             case DRInfo::DISTANCE:
00339                 break;
00340             case DRInfo::POINT_COLLISION:
00341                 break;
00342             }
00343         } 
00344     } // for
00345 }
00346 
00347 void BVH::_dr_leaf(DRInfo & dr, Node * pNode, unsigned depth)
00348 {
00349     if (pNode->leaf || depth >= dr.maxDepth) {
00350         /*
00351          * Both me and partner are in "leaves"
00352          */
00353         
00354         Vector3* pDir = (dr.pDir) ? new Vector3() : NULL;
00355 
00356         // This should be real distance of the objects in the leaf:
00357         double dL = dr.pDistRot->distance(*(pNode->bv), dr.minD, pDir);
00358         
00359         if (dL < dr.minD) {  // Update smallest value, remember leaves
00360 
00361 #ifdef ESG_COLLISION_HACK
00362             if (pNode->leaf) _dr_primitives(dr, pNode, pDir);
00363 #endif //ESG_COLLISION_HACK
00364             
00365             dr.minD = dL;
00366             
00367             if (dr.pDir) {
00368                 Matrix3 rMat;
00369                 Vector3 tVec, sVec;
00370                 
00371                 dr.pDir->set(*pDir); 
00372                 
00373                 if (dr.leafInMe) {
00374                     _coordMat.get(rMat, tVec, sVec);
00375                     ESG_INVERSE_TR_DIR(rMat, *(dr.pDir), *(dr.pDir));
00376                     _myTrMat.transform(*(dr.pDir));
00377                 } else {
00378                     _pPartner->_coordMat.get(rMat, tVec, sVec);
00379                     ESG_INVERSE_TR_DIR(rMat, *(dr.pDir), *(dr.pDir));
00380                     _pPartner->_myTrMat.transform(*(dr.pDir));
00381 
00382                 }
00383             }
00384             
00385             // Is the leaf in the tree of A?
00386             if (pNode->leaf) { 
00387                 if (dr.leafInMe) { dr.pLeafA= dr.pLeaf; dr.pLeafB=pNode;    }
00388                 else             { dr.pLeafA=pNode;     dr.pLeafB=dr.pLeaf; }
00389             }
00390         }
00391 
00392         if (pDir) delete pDir;
00393         
00394     } else { // Either me or partner is "in the leaf"
00395         
00396         // Select the most promising branch
00397         double dL=dr.pDistRot->distance(*(pNode->leftChild->bv), dr.minD,NULL);
00398         double dR=dr.pDistRot->distance(*(pNode->rightChild->bv),dr.minD,NULL);
00399         
00400         if (dL < dR) {
00401             if (dL < dr.minD) {
00402                 _dr_leaf(dr, pNode->leftChild, depth+1);
00403                 if (dR < dr.minD) _dr_leaf(dr, pNode->rightChild, depth+1);
00404             }
00405         } else {
00406             if (dR < dr.minD) {
00407                 _dr_leaf(dr, pNode->rightChild, depth+1);
00408                 if (dL < dr.minD) _dr_leaf(dr, pNode->leftChild, depth+1);
00409             }
00410         }
00411     }
00412 }
00413 
00414 void BVH::_dr_inner(DRInfo& dr, Node* pMyNode, Node* pHisNode, unsigned depth)
00415 {
00416     if (pHisNode->leaf || depth >= dr.hisMaxDepth) {
00417         // partner is in the leaf node;
00418         // dr.pDistRot is set to transformed partner, search only me
00419         dr.leafInMe = false;
00420         dr.pLeaf    = pHisNode;
00421         dr.maxDepth = dr.myMaxDepth;
00422         _dr_leaf(dr, pMyNode, depth);
00423         return;
00424     }
00425 
00426     if (pMyNode->leaf || depth >= dr.myMaxDepth) {
00427         // my node is leaf, partner has inner node 
00428         // Set dr.pDistRot to transformed me, search only the partner
00429         DistRot * pDistRot = this->_create_dist_rot(pMyNode);
00430         dr.pDistRot = pDistRot;
00431         dr.leafInMe = true;
00432         dr.pLeaf    = pMyNode;
00433         dr.maxDepth = dr.hisMaxDepth;
00434         _dr_leaf(dr, pHisNode, depth);
00435         delete pDistRot;
00436         return;
00437     }
00438 
00439     // My node even the partner's node are inner
00440     // Start computing transformed volume of partner
00441     double     d[4], dd;
00442     int        way;
00443     DistRot  * pDistRotL = _pPartner->_create_dist_rot(pHisNode->leftChild);
00444     DistRot  * pDistRotR = _pPartner->_create_dist_rot(pHisNode->rightChild);
00445 
00446     // Compute distances between pairs of volumes
00447     d[0] = pDistRotL->distance(*(pMyNode->leftChild->bv),  dr.minD, NULL);
00448     d[1] = pDistRotR->distance(*(pMyNode->leftChild->bv),  dr.minD, NULL);
00449     d[2] = pDistRotL->distance(*(pMyNode->rightChild->bv), dr.minD, NULL);
00450     d[3] = pDistRotR->distance(*(pMyNode->rightChild->bv), dr.minD, NULL);
00451 
00452     // Search every pair of subtrees that can decrease value dr.minD,
00453     // start with most promising pair
00454     do {
00455         way = -1;
00456         dd  = dr.minD;
00457 
00458         // Find the closest branch
00459         for (int i = 0; i < 4; i++) if (d[i] < dd) { dd = d[i]; way = i; }
00460 
00461         // Inspect it
00462         switch (way) {
00463         case 0:
00464             dr.pDistRot = pDistRotL;
00465             _dr_inner(dr, pMyNode->leftChild, pHisNode->leftChild, depth+1);
00466             d[0] = FLT_MAX;
00467             break;
00468         case 1:
00469             dr.pDistRot = pDistRotR;
00470             _dr_inner(dr, pMyNode->leftChild, pHisNode->rightChild, depth+1);
00471             d[1] = FLT_MAX;
00472             break;
00473         case 2:
00474             dr.pDistRot = pDistRotL;
00475             _dr_inner(dr, pMyNode->rightChild, pHisNode->leftChild, depth+1);
00476             d[2] = FLT_MAX;
00477             break;
00478         case 3:
00479             dr.pDistRot = pDistRotR;
00480             _dr_inner(dr, pMyNode->rightChild, pHisNode->rightChild, depth+1);
00481             d[3] = FLT_MAX;
00482             break;
00483         }
00484     } while (way >= 0 && dr.minD > -MAXDOUBLE);
00485 
00486     delete pDistRotL;
00487     delete pDistRotR;
00488 }
00489 
00490 void BVH::_duplicate_attributes(const SDS& src)
00491 {
00492     SDS::_duplicate_attributes(src);
00493     _leafLimit   = ((BVH&)src)._leafLimit;
00494     _depthLimit  = ((BVH&)src)._depthLimit;
00495     _pPartner    = NULL;
00496     _root        = NULL;
00497     _leftLeaf    = NULL;
00498     _scaleRatio  = ((BVH&)src)._scaleRatio;
00499     _splitStrategy = ((BVH&)src)._splitStrategy;
00500 }
00501 
00502 
00503 // --------- public --------------
00504 
00505 BVH::BVH(unsigned ll, unsigned dl, bool delayBuild, BVList::SplitStrategy ss)
00506     : SDS(delayBuild)
00507 {
00508     _leafLimit       = (ll > 0) ? ll : 1;
00509     _depthLimit      = dl;
00510     _leftLeaf        = NULL;
00511     _root            = NULL;
00512     _pPartner        = NULL;
00513     _scaleRatio      = 1.0;
00514     _splitStrategy   = ss;
00515 }
00516 
00517 BVH::~BVH()
00518 {
00519     if (_root) _destroy_tree(_root);
00520 }
00521 
00522 Iterator* BVH::createIterator()
00523 {
00524     return (Iterator*) new IteratorBVH(this);
00525 }
00526 
00527 InspectorSDS* BVH::createInspector(unsigned level)
00528 {
00529     return new InspectorBVH(this, level);
00530 }
00531 
00532 int BVH::append(SceneGraphObject* obj)
00533 {
00534     if (!obj) return 0;
00535 
00536     if (!obj->tangible()) {
00537         _intangibleChildren.append(obj);
00538         return 1;
00539     }
00540 
00541     if (_delayBuild) {
00542         if (!_root) {
00543             _root       = new Node;
00544             _root->leaf = true;
00545             _root->list = _create_list();
00546             _leftLeaf   = _root;
00547         }
00548         _root->list->append(obj);
00549     } else {
00550         if (_root) {
00551             Geometry* bv = _create_bv(*obj);
00552             (void) _append(obj, bv, _root, 0);
00553             delete bv;
00554         } else {
00555             _root             = new Node;
00556             _root->bv         = _create_bv(*obj);
00557             _root->leaf       = true;
00558             _root->list       = _create_list();
00559             _root->list->append(obj);
00560             _leftLeaf         = _root;
00561         }
00562     }
00563 
00564     return 1;
00565 }
00566 
00567 SceneGraphObject* BVH::detach(SceneGraphObject::OID oid)
00568 {
00569   for (Node* node = _leftLeaf; node != NULL; node = node->rightChild) {
00570     SceneGraphObject* obj = node->list->firstItem();
00571     while (obj) {
00572       if (obj->getOID() == oid) {
00573         SceneGraphObject* retObj = node->list->remove(obj);
00574         if (node->list->length() == 0) _remove_leaf(node);
00575         else {
00576           delete node->bv;
00577           node->bv = _create_bv(*(node->list));
00578         }
00579         return retObj;
00580       }
00581       obj = node->list->nextItem();
00582     }
00583   }
00584   return NULL;
00585 }
00586 
00587 bool BVH::update()
00588 {
00589     if (_delayBuild) return false;
00590     if (_root) _rebuild_tree(_root);
00591     return true;
00592 }
00593 
00594 bool BVH::build()
00595 {
00596     if (!_delayBuild) return false;
00597     if (!_root)       return false;
00598     _build_tree(_root, 0);
00599     _delayBuild = false;
00600     return true;
00601 }
00602 
00603 double BVH::distance(Matrix4  * pTrMy,
00604                      BVH&       bvhB,
00605                      Matrix4  * pTrB,
00606                      Node    ** ppMinA,
00607                      Node    ** ppMinB,
00608                      Vector3  * pDir,
00609                      unsigned   d1,
00610                      unsigned   d2)
00611 {
00612     if (_delayBuild || bvhB._delayBuild) return -MAXDOUBLE;
00613     if (!_root      || !bvhB._root)      return -MAXDOUBLE;
00614     if (!_root->bv  || !bvhB._root->bv)  return -MAXDOUBLE;
00615 
00616     DRInfo dr;
00617     dr.strategy    = DRInfo::DISTANCE;
00618     dr.pDir        = pDir;
00619     dr.pLeafA      = NULL;
00620     dr.pLeafB      = NULL;
00621     dr.minD        = FLT_MAX;
00622     dr.myMaxDepth  = d1;
00623     dr.hisMaxDepth = d2;
00624 
00625     this->_dr_init(pTrMy, pTrB, &bvhB);
00626     bvhB._dr_init(pTrB, pTrMy, this);
00627 
00628     // Get current distance between two nearest leaves from the previous pass
00629     if (ppMinA && ppMinB) {
00630         DistRot * pDRot = bvhB._create_dist_rot(*ppMinB);
00631         dr.minD = pDRot->distance(*((*ppMinA)->bv), FLT_MAX, pDir); //bylo -MAX
00632         delete pDRot;
00633     } 
00634 
00635     DistRot * pDistRot = bvhB._create_dist_rot(bvhB._root);
00636     dr.pDistRot = pDistRot;
00637 
00638     // Get distance of the roots of the trees.
00639     // In this version the condition is always true, but we need it for
00640     // pure collision detection
00642         _dr_inner(dr, _root, bvhB._root, 0);
00643 
00644     if (ppMinA && ppMinB) { *ppMinA = dr.pLeafA; *ppMinB = dr.pLeafB; }
00645 
00646     delete pDistRot;
00647 
00648     return dr.minD;
00649 }
00650 
00651 bool BVH::separation(Matrix4* pTrMy,
00652                      BVH&     bvhB,
00653                      Matrix4* pTrB,
00654                      Vector3* pDir,
00655                      unsigned d1,
00656                      unsigned d2)
00657 {
00658     if (_delayBuild || bvhB._delayBuild) return true;
00659     if (!_root      || !bvhB._root)      return true;
00660     if (!_root->bv  || !bvhB._root->bv)  return true;
00661 
00662     DRInfo dr;
00663     dr.strategy = DRInfo::SEPARATION;
00664     dr.pDir = pDir;
00665 
00666     this->_dr_init(pTrMy, pTrB, &bvhB);
00667     bvhB._dr_init(pTrB, pTrMy, this);
00668 
00669     dr.minD        = 0;  // we check only separation
00670     dr.pLeafA      = NULL;
00671     dr.pLeafB      = NULL;
00672     dr.myMaxDepth  = d1;
00673     dr.hisMaxDepth = d2;
00674 
00675     DistRot * pDistRot = bvhB._create_dist_rot(bvhB._root);
00676     dr.pDistRot = pDistRot;
00677 
00678     // Check collision of top volumes
00679     if (!dr.pDistRot->separation(*(_root->bv), NULL))
00680         _dr_inner(dr, _root, bvhB._root, 0);
00681 
00682     delete pDistRot;
00683 
00684     return (dr.minD >= 0.);
00685 }
00686 
00687 Geometry** BVH::collision(Matrix4 * pTrMy,
00688                          float      x,
00689                          float      y,
00690                          float      z,
00691                          float      radius,
00692                          int      * numLeaves)
00693 {
00694     
00695     Geometry *             pBV;
00696     List<SceneGraphObject> list;
00697     
00698     *numLeaves = 0;
00699 
00700     if (_delayBuild) return NULL;
00701     if (!_root)      return NULL;
00702     if (!_root->bv)  return NULL;
00703 
00704     if (pTrMy) {
00705         Vector3   point(x,y,z);
00706         Matrix4 * pTrMat = multiTrans(pTrMy, NULL, _scaleRatio);
00707         pTrMat->transform(point);
00708         Sphere    sphere(point.x, point.y, point.z, radius);
00709         // scaling factor affects measured distance but never collision
00710         // itself. Therefore we can ignore it here.
00711         pBV = _create_bv(sphere, sphere);
00712     } else {
00713         Sphere sphere(x, y, z, radius);
00714         pBV = _create_bv(sphere, sphere);
00715     }
00716     
00717     if (!pBV) return NULL;
00718 
00719     _collision(_root, *pBV, &list);
00720 
00721     *numLeaves = list.length();
00722     if (*numLeaves == 0) return NULL;
00723 
00724     Geometry** array = new Geometry* [*numLeaves]; 
00725     unsigned   i     = 0;
00726     for (SceneGraphObject * pObj = list.firstItem();
00727          pObj;
00728          pObj = list.nextItem())
00729     {
00730         array[i] = pObj->geometry();
00731         if (!array[i]) (*numLeaves)--;
00732         else i++;
00733     }
00734 
00735     delete pBV;
00736     return array;
00737 }
00738 
00739 void BVH::dump(const char* intent, const char* tab) 
00740 {
00741     char* newIntent = new char [strlen(intent) + strlen(tab) + 2];
00742     newIntent = strcpy(newIntent, intent);
00743     newIntent = strcat(newIntent, " ");
00744     newIntent = strcat(newIntent, tab);
00745     
00746     printf("%s spacialDataStructure BVH {\n", intent);
00747     printf("%s %s leafLimit  %d\n", intent, tab, _leafLimit);
00748     printf("%s %s depthLimit %d\n", intent, tab, _depthLimit);
00749     printf("%s %s treeDepth  %d\n", intent, tab, _treeDepth);
00750     printf("%s %s splitMode  ", intent, tab);
00751     switch (_splitStrategy) {
00752     case BVList::SPLIT_BY_MAX_VARIATION: printf("MAX_VARIATION\n"); break;
00753     case BVList::SPLIT_BY_MAX_EXTENT:    printf("MAX_EXTENT\n");    break;
00754     default:                             printf("UNKNOWN\n");       break;
00755     }
00756     _dump(_root, newIntent, tab);
00757     printf("%s }\n", intent);
00758     delete [] newIntent;
00759 }
00760 
00761 
00762 void BVH::__debug() {
00763     fprintf(stderr,"BVH Debugging:\n");
00764     //if (_leftLeaf) _leftLeaf->list->__debug();
00765     if (_root) __debug(_root,0);
00766     else fprintf(stderr,"BVH: No structure\n");
00767 }
00768     
00769 void BVH::__debug(Node* n, int d) {
00770     if (!n) return;
00771     for (int i=0;i<d;i++) fprintf(stderr,"   ");
00772     n->bv->__debug();
00773     if (n->leaf) {
00774         for (int i=0;i<d;i++) fprintf(stderr,"   ");
00775         n->list->__debug();
00776     } else {
00777         __debug(n->leftChild,d+1);
00778         __debug(n->rightChild,d+1);
00779     }
00780 }
00781 
00782 void BVH::__get_edges(Matrix4 * pTrMat,
00783                       Node*     pNode,
00784                       unsigned  level,
00785                       unsigned  maxLevel,
00786                       int       rot,
00787                       float*    array,
00788                       unsigned& size)
00789 {
00790     if (pNode->leaf || level >= maxLevel) {
00791         Vector3 v;
00792         Geometry * pGeom;
00793 
00794         if      (rot == 1) pGeom = (Geometry*) pNode->bv->clone(pTrMat);
00795         else if (rot == 2) pGeom = (Geometry*) pNode->bv->clone(&_coordMat);
00796         else               pGeom = (Geometry*) pNode->bv->clone();
00797 
00798         if (!pGeom) {
00799             fprintf(stderr,"BVH::__get_edges(): Clonning of BV failed\n");
00800             return;
00801         }
00802 
00803         Mesh * pMesh = pGeom->mesh(0);
00804         if (!pMesh) { delete pGeom; return; }
00805 
00806         pMesh->resetActSolid();
00807         do {
00808             pMesh->resetEdgeWalkInSolid();
00809             do {
00810                 v.set(pMesh->getActVert1(false));
00811                 array[size++] = v.x;
00812                 array[size++] = v.y;
00813                 array[size++] = v.z;
00814                 v.set(pMesh->getActVert2(false));
00815                 array[size++] = v.x;
00816                 array[size++] = v.y;
00817                 array[size++] = v.z;
00818             } while (pMesh->stepInEdgeWalkInSolid());
00819         } while (pMesh->goToNextSolid());
00820 
00821         delete pMesh;
00822         delete pGeom;
00823         return;
00824     }
00825 
00826     if (pNode->leaf) return;
00827     
00828     __get_edges(pTrMat, pNode->leftChild, level+1, maxLevel, rot, array, size);
00829     __get_edges(pTrMat, pNode->rightChild,level+1, maxLevel, rot, array, size);
00830 }
00831 
00832 float* BVH::__getEdges(Matrix4 * pMyTr,
00833                        unsigned  level,
00834                        int       rot,
00835                        unsigned& size)
00836 {
00837     size = 0;
00838     if (!_root) return NULL;
00839     
00840     float * array = new float[100000];
00841     
00842     __get_edges(pMyTr, _root, 0, level, rot, array, size);
00843     return array;
00844 }
00845 
00846 void BVH::__get_meshes(Matrix4 * pTrMat,
00847                        Node*     pNode,
00848                        unsigned  level,
00849                        unsigned  maxLevel,
00850                        int       rot,
00851                        Mesh**    array,
00852                        unsigned& size)
00853 {
00854     if (pNode->leaf || level >= maxLevel) {
00855         Vector3 v;
00856         Geometry * pGeom;
00857         if (rot == 1)      pGeom = (Geometry*) pNode->bv->clone(pTrMat);
00858         else if (rot == 2) pGeom = (Geometry*) pNode->bv->clone(&_coordMat);
00859         else               pGeom = (Geometry*) pNode->bv->clone();
00860         array[size++] = pGeom->mesh(0);
00861         delete pGeom;
00862         return;
00863     }
00864 
00865     if (pNode->leaf) return;
00866     
00867     __get_meshes(pTrMat, pNode->leftChild, level+1, maxLevel, rot, array,size);
00868     __get_meshes(pTrMat, pNode->rightChild,level+1, maxLevel, rot, array,size);
00869 }
00870 
00871 Mesh** BVH::__getMeshes(Matrix4 * pMyTr,
00872                         unsigned  level,
00873                         int       rot,
00874                         unsigned& size)
00875 {
00876     Mesh ** array = new Mesh* [10000];
00877     size = 0;
00878     __get_meshes(pMyTr, _root, 0, level, rot, array, size);
00879     return array;
00880 }
00881 
00882 
00883 
00884 
00885 
00886 
00887 
00888 
00889                  

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