TriOctree.cc
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:10k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. // 
  3. // TriOctree.cc
  4. //
  5. // Kari Pulli
  6. // Mon Nov 23 16:36:51 CET 1998
  7. //
  8. // Data structure that creates an octree containing all the 
  9. // triangles in a mesh.
  10. // Can also used to quickly evaluate approximate distances
  11. // to the surface.
  12. //
  13. //############################################################
  14. #include "TriOctree.h"
  15. // face indices:
  16. // 0, 2, 4 = dimension (x, y, z); +0 negative, +1 positive
  17. // so 0 is left, 1 is right
  18. //    2 is down, 3 is up
  19. //    4 is in,   5 is out
  20. //static const int face_negX = 0;
  21. //static const int face_posX = 1;
  22. //static const int face_negY = 2;
  23. //static const int face_posY = 3;
  24. //static const int face_negZ = 4;
  25. //static const int face_posZ = 5;
  26. TriOctree*
  27. TriOctree::recursive_find(int face, stack<int>& path, 
  28.   bool bReachedTop)
  29. {
  30.   if (path.empty()) return this;
  31.   int iChild;
  32.   if (bReachedTop) {
  33.     // then we want to descend
  34.     iChild = path.top(); path.pop();
  35.     TriOctree* theChild = child[iChild];
  36.     if (!theChild) return this; // child does not exist
  37.     return theChild->recursive_find (face, path, true);
  38.   } else {
  39.     // we still need to traverse horizontally...
  40.     if (!parent) return NULL;
  41.     if (is_neighbor_cell (face, iChild)) {
  42.       // if we have a sibling, we can traverse 
  43.       // (and we've reached the top!)
  44.       TriOctree* sibling = parent->child[iChild];
  45.       if (!sibling) return NULL;
  46.       return sibling->recursive_find (face, path, true);
  47.     } else {
  48.       // otherwise we have to go farther up.
  49.       path.push (iChild);
  50.       return parent->recursive_find (face, path, false);
  51.     }
  52.   }
  53. }
  54. bool
  55. TriOctree::is_neighbor_cell(int face, int &iChild)
  56. {
  57.   // given a direction, return the child index of the neighbor
  58.   // that lies in that direction.  If that neighbor is a sibling
  59.   // (iChild is valid for the same parent as us), return true.
  60.   // Otherwise, return false.
  61.   int axis = face / 2;
  62.   int sign = face % 2;
  63.   // neighbor will be in same position as we are, except
  64.   // the bit representing the axis we're moving along will be 
  65.   // flipped
  66.   iChild = parIdx ^ (1 << axis);
  67.   // if we have the bit for that axis set and the direction of
  68.   // movement is negative, it's a sibling, but if the direction 
  69.   // of movement is positive, it's not a sibling.  
  70.   // Vice-versa if our child index does
  71.   // not have the bit for the movement axis set.
  72.   int haveSign = (0 < (parIdx & (1 << axis)));
  73.   return (sign != haveSign);
  74. }
  75. TriOctree*
  76. TriOctree::find_neighbor (int face)
  77. {
  78.   if (!parent)
  79.     return NULL;
  80.   int iChild;
  81.   bool sibling = is_neighbor_cell(face, iChild);
  82.   if (sibling) {
  83.     TriOctree* theSibling = parent->child[iChild];
  84.     if (!theSibling) return NULL;
  85.     return theSibling;
  86.   }
  87.   // not a sibling: push child and go up
  88.   stack<int> path;
  89.   path.push (iChild);
  90.   return parent->recursive_find (face, path, false);
  91. }
  92. bool
  93. tri_outside_of_cube(const Pnt3 &c, float s,
  94.     const Pnt3 &t1, const Pnt3 &t2, const Pnt3 &t3);
  95. static int leaftricount = 0;
  96. TriOctree::TriOctree(const Pnt3 &c, float r, const Pnt3 *p,
  97.      const vector<int> &tris, float minRadius,
  98.      int pidx, TriOctree *parent)
  99.   : mCtr(c), mRadius(r), parIdx(pidx)
  100. {
  101.   /*
  102.   SHOW(mCtr);
  103.   SHOW(mRadius);
  104.   SHOW(tris.size()/3);
  105.   SHOW(minRadius);
  106.   */
  107.   // check whether we need to subdivide more
  108.   if (mRadius < 2*minRadius || tris.size() <= 18) {
  109.     pts = p;
  110.     tind = tris;
  111.     leaftricount += tris.size();
  112.     SHOW(leaftricount);
  113.     child[0] = child[1] = child[2] = child[3] = NULL;
  114.     child[4] = child[5] = child[6] = child[7] = NULL;
  115.     return;
  116.   }
  117.   pts = NULL;
  118.   // if so, try for triangle and each child whether they intersect
  119.   float halfR = mRadius*.5;
  120.   Pnt3 childCtr;
  121.   vector<int> xp, xm; // x plus, x minus
  122.   vector<int> yp, ym; // y plus, y minus
  123.   vector<int> zp, zm; // z plus, z minus
  124.   vector<int> uk;     // unknown (triangles going across splits)
  125.   xp.reserve(tris.size());
  126.   xm.reserve(tris.size());
  127.   uk.reserve(tris.size());
  128.   // split about x axis
  129.   vector<int>::const_iterator it = tris.begin();
  130.   int v1,v2,v3, cnt;
  131.   while (it != tris.end()) {
  132.     v1 = *it++; v2 = *it++; v3 = *it++;
  133.     cnt = (p[v1][0] >= mCtr[0]) + (p[v2][0] >= mCtr[0]) +
  134.       (p[v3][0] >= mCtr[0]);
  135.     if (cnt == 3) {
  136.       xp.push_back(v1); xp.push_back(v2); xp.push_back(v3);
  137.     } else if (cnt == 0) {
  138.       xm.push_back(v1); xm.push_back(v2); xm.push_back(v3);
  139.     } else {
  140.       uk.push_back(v1); uk.push_back(v2); uk.push_back(v3);
  141.     }  
  142.   }
  143.   // split about y axis
  144.   vector<int> &xv = xm;
  145.   vector<int> &yv = ym;
  146.   for (int i=0; i<2; i++) {
  147.     if (i) xv = xp;
  148.     else   xv = xm;
  149.     yp.clear(); yp.reserve(xv.size());
  150.     ym.clear(); ym.reserve(xv.size());
  151.        
  152.     it = xv.begin();
  153.     while (it != xv.end()) {
  154.       v1 = *it++; v2 = *it++; v3 = *it++;
  155.       cnt = (p[v1][1] >= mCtr[1]) + (p[v2][1] >= mCtr[1]) +
  156. (p[v3][1] >= mCtr[1]);
  157.       if (cnt == 3) {
  158. yp.push_back(v1); yp.push_back(v2); yp.push_back(v3);
  159.       } else if (cnt == 0) {
  160. ym.push_back(v1); ym.push_back(v2); ym.push_back(v3);
  161.       } else {
  162. uk.push_back(v1); uk.push_back(v2); uk.push_back(v3);
  163.       }  
  164.     }
  165.     for (int j=0; j<2; j++) {
  166.       if (j) yv = yp;
  167.       else   yv = ym;
  168.       zp.clear(); zp.reserve(yv.size());
  169.       zm.clear(); zm.reserve(yv.size());
  170.       it = yv.begin();
  171.       while (it != yv.end()) {
  172. v1 = *it++; v2 = *it++; v3 = *it++;
  173. cnt = (p[v1][2] >= mCtr[2]) + (p[v2][2] >= mCtr[2]) +
  174.   (p[v3][2] >= mCtr[2]);
  175. if (cnt == 3) {
  176.   zp.push_back(v1); zp.push_back(v2); zp.push_back(v3);
  177. } else if (cnt == 0) {
  178.   zm.push_back(v1); zm.push_back(v2); zm.push_back(v3);
  179. } else {
  180.   uk.push_back(v1); uk.push_back(v2); uk.push_back(v3);
  181. }  
  182.       }
  183.       
  184.       // check the unknowns
  185.       childCtr.set(mCtr[0] + (i ? halfR : -halfR),
  186.    mCtr[1] + (j ? halfR : -halfR),
  187.    mCtr[2] - halfR);
  188.       it = uk.begin();
  189.       while (it != uk.end()) {
  190. v1 = *it++; v2 = *it++; v3 = *it++;
  191. if (!tri_outside_of_cube(childCtr, mRadius, p[v1],
  192.  p[v2], p[v3])) {
  193.   zm.push_back(v1); zm.push_back(v2); zm.push_back(v3);
  194. }
  195.       }
  196.       // create the children, if needed
  197.       int k = i+2*j;
  198.       if (zm.size()) {
  199. child[k] = new TriOctree(childCtr, halfR, p, zm, 
  200.  minRadius, k, this);
  201.       } else {
  202. child[k] = NULL;
  203.       }
  204.       // check the unknowns
  205.       childCtr.set(mCtr[0] + (i ? halfR : -halfR),
  206.    mCtr[1] + (j ? halfR : -halfR),
  207.    mCtr[2] + halfR);
  208.       it = uk.begin();
  209.       while (it != uk.end()) {
  210. v1 = *it++; v2 = *it++; v3 = *it++;
  211. if (!tri_outside_of_cube(childCtr, mRadius, p[v1],
  212.  p[v2], p[v3])) {
  213.   zp.push_back(v1); zp.push_back(v2); zp.push_back(v3);
  214. }
  215.       }
  216.       k += 4;
  217.       if (zp.size()) {
  218. child[k] = new TriOctree(childCtr, halfR, p, zp, 
  219.  minRadius, k, this);
  220.       } else {
  221. child[k] = NULL;
  222.       }
  223.     }
  224.   }
  225.   /*
  226.   vector<int> tmptris;
  227.   tmptris.reserve(tris.size());
  228.   for (int i=0; i<8; i++) {
  229.     childCtr.set(mCtr[0] + ((i&1) ? halfR : -halfR),
  230.  mCtr[1] + ((i&2) ? halfR : -halfR),
  231.  mCtr[2] + ((i&4) ? halfR : -halfR));
  232.     tmptris.clear();
  233.     for (int j=0; j<tris.size(); j+=3) {
  234.       if (!tri_outside_of_cube(childCtr, mRadius, p[tris[j]], 
  235.        p[tris[j+1]], p[tris[j+2]])) {
  236. tmptris.push_back(tris[j]);
  237. tmptris.push_back(tris[j+1]);
  238. tmptris.push_back(tris[j+2]);
  239.       }
  240.     }
  241.     if (tmptris.size()) {
  242.       child[i] = new TriOctree(childCtr, halfR, p, tmptris, 
  243.        minRadius, i, this);
  244.     } else {
  245.       child[i] = NULL;
  246.     }
  247.   }
  248. */
  249. }
  250. // the return value tells whether the closest distance (squared)
  251. // has been found for sure
  252. bool
  253. TriOctree::search(const Pnt3 &p, Pnt3 &cp, float &d2)
  254. {
  255.   // is this a leaf node?
  256.   if (pts) {
  257.     // look for a new closest distance
  258.     vector<int>::const_iterator   it  = tind.begin();
  259.     while (it != tind.end()) {
  260.       closer_on_tri(p, cp, pts[*(it++)], pts[*(it++)], 
  261.     pts[*(it++)], d2);
  262.     }
  263.     return ball_within_bounds(p, sqrtf(d2), mCtr, mRadius);
  264.   }
  265.   
  266.   // which child contains p?
  267.   int iChild = 4*(mCtr[2]<p[2]) + 2*(mCtr[1]<p[1]) + (mCtr[0]<p[0]);
  268.   
  269.   // check that child first
  270.   if (child[iChild] && child[iChild]->search(p, cp, d2)) return true;
  271.   // now see if the other children need to be checked
  272.   for (int i=0; i<8; i++) {
  273.     if (i==iChild) continue;
  274.     //if (child[i] && child[i]->bounds_overlap_ball(p,d)) {
  275.     if (child[i] && bounds_overlap_ball(p,sqrtf(d2),child[i]->mCtr, 
  276. child[i]->mRadius)) {
  277.       if (child[i]->search(p, cp, d2)) return true;
  278.     }
  279.   }
  280.   return ball_within_bounds(p, sqrtf(d2), mCtr, mRadius);
  281. }
  282. static void
  283. cube_bdry(const Pnt3 &ctr, float r, 
  284.   vector<Pnt3> &p, vector<int> &i)
  285. {
  286.   int s = p.size();
  287.   p.push_back(ctr + Pnt3(-r,-r,-r));
  288.   p.push_back(ctr + Pnt3( r,-r,-r));
  289.   p.push_back(ctr + Pnt3(-r, r,-r));
  290.   p.push_back(ctr + Pnt3( r, r,-r));
  291.   p.push_back(ctr + Pnt3(-r,-r, r));
  292.   p.push_back(ctr + Pnt3( r,-r, r));
  293.   p.push_back(ctr + Pnt3(-r, r, r));
  294.   p.push_back(ctr + Pnt3( r, r, r));
  295.   i.push_back(s+0);
  296.   i.push_back(s+3);
  297.   i.push_back(s+1);
  298.   i.push_back(s+2);
  299.   i.push_back(s+3);
  300.   i.push_back(s+0);
  301.   i.push_back(s+0);
  302.   i.push_back(s+5);
  303.   i.push_back(s+4);
  304.   i.push_back(s+0);
  305.   i.push_back(s+1);
  306.   i.push_back(s+5);
  307.   i.push_back(s+2);
  308.   i.push_back(s+4);
  309.   i.push_back(s+6);
  310.   i.push_back(s+2);
  311.   i.push_back(s+0);
  312.   i.push_back(s+4);
  313.   i.push_back(s+3);
  314.   i.push_back(s+7);
  315.   i.push_back(s+5);
  316.   i.push_back(s+3);
  317.   i.push_back(s+5);
  318.   i.push_back(s+1);
  319.   i.push_back(s+2);
  320.   i.push_back(s+6);
  321.   i.push_back(s+7);
  322.   i.push_back(s+2);
  323.   i.push_back(s+7);
  324.   i.push_back(s+3);
  325.   i.push_back(s+7);
  326.   i.push_back(s+6);
  327.   i.push_back(s+4);
  328.   i.push_back(s+7);
  329.   i.push_back(s+4);
  330.   i.push_back(s+5);
  331. }
  332. // creates a mesh that shows the structure of the octree
  333. void
  334. TriOctree::visualize(vector<Pnt3> &p, vector<int> &ind)
  335. {
  336.   cube_bdry(mCtr, mRadius, p, ind);
  337.   for (int i=0; i<8; i++) {
  338.     if (child[i]) 
  339.       child[i]->visualize(p,ind);
  340.   }
  341. }
  342. #ifdef TRIOCTREEMAIN
  343. void
  344. main(void)
  345. {
  346.   Pnt3 *p = NULL;
  347.   vector<int> tris;
  348.   TriOctree to(Pnt3(), 1, p, tris, .1);
  349. }
  350. #endif