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

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. //
  3. // VolCarve.cc
  4. //
  5. // Matt Ginzton, Kari Pulli
  6. // Mon Jul 13 11:53:22 PDT 1998
  7. //
  8. // Perform a volumetric space carving on RigidScans.
  9. // Use octrees.
  10. // For occlusion testing, treat octree nodes as spheres.
  11. //
  12. //############################################################
  13. #include <map.h>
  14. #include <stack.h>
  15. #include <deque.h>
  16. #ifdef WIN32
  17. # include <float.h>
  18. # define isnanf _isnan
  19. #endif
  20. #ifdef sgi
  21. # include <ieeefp.h>
  22. #endif
  23. #include "VolCarve.h"
  24. #include "MCEdgeTable.h"
  25. #define VOLCARVE_MAIN 0
  26. // face indices:
  27. // 0, 2, 4 = dimension (x, y, z); +0 negative, +1 positive
  28. // so 0 is left, 1 is right
  29. //    2 is down, 3 is up
  30. //    4 is in,   5 is out
  31. static const int face_negX = 0;
  32. //static const int face_posX = 1;
  33. static const int face_negY = 2;
  34. //static const int face_posY = 3;
  35. static const int face_negZ = 4;
  36. //static const int face_posZ = 5;
  37. vector<Pnt3> vertex_list;
  38. /*
  39. #ifdef WIN32
  40.   typedef __int64 CUBEKEY;
  41. #else
  42.   typedef long long CUBEKEY;
  43. #endif
  44. typedef map<CUBEKEY, int> VERTEXMAP;
  45. VERTEXMAP g_vertexMap;
  46. Pnt3 fblo, fbhi; // full box lower and upper corners
  47. // use the two upper two bits to encode which edge of a cube corner
  48. // the vertex belongs to
  49. static const int encode_bits  = ((8 * sizeof(CUBEKEY))-2) / 3;
  50. static const int encode_shift = (1 << encode_bits);
  51. static float encode_scale;
  52. static inline CUBEKEY
  53. encode(const Pnt3 &p)
  54. {
  55.   CUBEKEY x = (p[0]-fblo[0]) * encode_scale;
  56.   CUBEKEY y = (p[1]-fblo[1]) * encode_scale;
  57.   CUBEKEY z = (p[2]-fblo[2]) * encode_scale;
  58.   return (((x << encode_bits) + y) << encode_bits) + z;
  59. }
  60. */
  61. class CTL_memhandler {
  62. private:
  63.   int blockSize;
  64.   stack<CubeTreeLeafData*> free;
  65.   int count;
  66. public:
  67.   CTL_memhandler(void) : blockSize(0) {}
  68.   ~CTL_memhandler(void) 
  69.     {
  70.       //SHOW(free.size());
  71.       //SHOW(count);
  72.       while (!free.empty()) {
  73. delete[] free.top();
  74. free.pop();
  75.       }
  76.     }
  77.   void set_blocksize(int bs) 
  78.     {
  79.       if (bs != blockSize) {
  80. while (!free.empty()) {
  81.   delete[] free.top();
  82.   free.pop();
  83. }
  84. blockSize = bs;
  85. count     = 0;
  86.       }
  87.     }
  88.   CubeTreeLeafData *operator()(void)
  89.     {
  90.       CubeTreeLeafData *ret;
  91.       if (!free.empty()) { 
  92. ret = free.top(); 
  93. free.pop(); 
  94. return ret; 
  95.       } else {
  96. count++;
  97. return new CubeTreeLeafData[blockSize];
  98.       }
  99.     }
  100.   void store(CubeTreeLeafData *p)
  101.     {
  102.       free.push(p);
  103.     }
  104. };
  105. CTL_memhandler mem_handler;
  106. // first, implementation of methods used by all CubeTrees (CubeTreeBase),
  107. // followed by specifics for octree nodes referenced by pointers
  108. // (CubeTree, which doesn't need to have a complete set of children)
  109. // and octree nodes that store all their children in a flat array
  110. // (CubeTreeLeaf, which always has a complete set of children).
  111. int   CubeTreeBase::leafDepth = CubeTree::defaultLeafDepth;
  112. float CubeTreeBase::leafSize  = 0.0;
  113. int   CubeTreeBase::nVoxels   = 0;
  114. CubeTreeBase::CubeTreeBase (Pnt3 c, float s, CubeTree* _par, int _iParIdx)
  115.   : mCtr(c), mSize(s), parent(_par), parIdx(_iParIdx), type(INDETERMINATE)
  116. { }
  117. CubeTreeBase::~CubeTreeBase()
  118. { }
  119. void
  120. CubeTreeBase::set_leaf_depth (int ld)
  121. {
  122.   if (ld >= 0)  leafDepth = ld;
  123.   else          leafDepth = defaultLeafDepth;
  124. }
  125. CubeTreeBase*
  126. CubeTreeBase::find_neighbor (int face)
  127. {
  128.   if (!parent)
  129.     return NULL;
  130.   int iChild;
  131.   bool sibling = is_neighbor_cell(face, iChild);
  132.   if (sibling) {
  133.     CubeTreeBase* theSibling = parent->child[iChild];
  134.     if (!theSibling) return NULL;
  135.     return theSibling;
  136.   }
  137.   // not a sibling: push child and go up
  138.   stack<int> path;
  139.   path.push (iChild);
  140.   return parent->recursive_find (face, path, false);
  141. }
  142. bool
  143. CubeTreeBase::is_neighbor_cell (int face, int& iChild)
  144. {
  145.   // given a direction, return the child index of the neighbor
  146.   // that lies in that direction.  If that neighbor is a sibling
  147.   // (iChild is valid for the same parent as us), return true.
  148.   // Otherwise, return false.
  149.   int axis = face / 2;
  150.   int sign = face % 2;
  151.   // neighbor will be in same position as we are, except
  152.   // the bit representing the axis we're moving along will be 
  153.   // flipped
  154.   iChild = parIdx ^ (1 << axis);
  155.   // if we have the bit for that axis set and the direction of
  156.   // movement is negative, it's a sibling, but if the direction 
  157.   // of movement is positive, it's not a sibling.  
  158.   // Vice-versa if our child index does
  159.   // not have the bit for the movement axis set.
  160.   int haveSign = (0 < (parIdx & (1 << axis)));
  161.   return (sign != haveSign);
  162. }
  163. //
  164. // Nonmember function to determine the type of a node with respect to
  165. // the views, following the precedence order:
  166. //   OUTSIDE
  167. //   BOUNDARY
  168. //   SILHOUETTE
  169. //   INSIDE
  170. //   NOT_IN_FRUSTUM
  171. //   INDETERMINATE
  172. //
  173. OccSt
  174. view_query_status (vector<RigidScan*> &views,
  175.    vector<RigidScan*> &remaining_views,
  176.    const Pnt3 &ctr, float size,
  177.    OccSt type = INDETERMINATE)
  178. {
  179.   vector<RigidScan*>::iterator vit; 
  180.   for (vit = views.begin(); vit != views.end(); vit++) {
  181.     OccSt t = (*vit)->carve_cube(ctr, size);
  182.     // OccSt types listed in descending precedence order
  183.     if (int(type) > int(t))
  184.       type = t;
  185.     if (t != NOT_IN_FRUSTUM) {
  186.       remaining_views.push_back(*vit);
  187.     }
  188.     if (t == OUTSIDE) {
  189.       // can't get any better than this
  190.       return t;
  191.     }
  192.   }
  193.   return type;
  194. }
  195. float
  196. view_query_distance (vector<RigidScan*> &views, const Pnt3& ctr,
  197.      float& distance)
  198. {
  199.   float totalConf = 0;
  200.   OccSt occ;
  201.   Pnt3 closest;
  202.   distance = 0;
  203.   //
  204.   // HOW SHOULD THE DISTANCES REALLY BE COMBINED????
  205.   //
  206.   float thr  = 15.0;
  207.   float ramp = 30.0;
  208.   vector<RigidScan*>::iterator vit; 
  209.   for (vit = views.begin(); vit != views.end(); vit++) {
  210.     float conf = (*vit)->closest_along_line_of_sight (ctr, closest, occ);
  211.     //float conf = (*vit)->closest_point_on_mesh(ctr, closest, occ);
  212.     float thisDist = dist(ctr, closest);
  213.     if (occ == INSIDE) {
  214.       if (thisDist > thr) {
  215. float d = thisDist - thr;
  216. if (d > ramp) conf = 0;
  217. else          conf *= (ramp - d) / ramp;
  218.       }
  219.     }
  220.     totalConf += conf;
  221.     if (occ == INSIDE)
  222.       thisDist *= -1;
  223.     distance += conf * thisDist;
  224.   }
  225.   if (totalConf) distance /= totalConf;
  226.   else           distance = -1000;
  227.   return totalConf;
  228. }
  229. ///////////////////////////////////////////////////////////////////////////
  230. //
  231. // Pointerized octree nodes: CubeTree
  232. //
  233. ///////////////////////////////////////////////////////////////////////////
  234. void 
  235. CubeTree::delete_children (void)
  236.   for (int i = 0; i < 8; i++) {
  237.     delete child[i]; 
  238.     child[i] = NULL;
  239.   }
  240. }
  241. CubeTreeBase*
  242. CubeTree::recursive_find(int face, stack<int>& path, 
  243.  bool bReachedTop)
  244. {
  245.   if (path.empty()) {
  246.     /*
  247.     CubeTreeLeaf* leaf = dynamic_cast<CubeTreeLeaf*> (this);
  248.     if (!leaf) {
  249.       assert (0);
  250.       return this;
  251.     }
  252.     return leaf;
  253.     */
  254.     return this;
  255.   }
  256.   int iChild;
  257.   if (bReachedTop) {
  258.     // then we want to descend
  259.     iChild = path.top(); path.pop();
  260.     CubeTreeBase* theChild = child[iChild];
  261.     if (!theChild)
  262.       return this; // child does not exist
  263.     return theChild->recursive_find (face, path, true);
  264.   } else {
  265.     // we still need to traverse horizontally...
  266.     if (!parent)
  267.       return NULL;
  268.     bool sibling = is_neighbor_cell (face, iChild);
  269.     if (sibling) {
  270.       // if we have a sibling, we can traverse 
  271.       // (and we've reached the top!)
  272.       CubeTreeBase* sibling = parent->child[iChild];
  273.       if (!sibling) return NULL;
  274.       return sibling->recursive_find (face, path, true);
  275.     } else {
  276.       // otherwise we have to go farther up.
  277.       path.push (iChild);
  278.       return parent->recursive_find (face, path, false);
  279.     }
  280.   }
  281. }
  282. // find the neighbors of child i into negative directions
  283. // in x, y, and z, and tell them that data along that
  284. // face is not needed any more
  285. void
  286. CubeTree::release_space(int i)
  287. {
  288.   if (i&1) {
  289.     child[i-1]->keep_walls(0,1,1);
  290.   } else {
  291.     CubeTreeBase *ctb = find_neighbor(face_negX);
  292.     if (ctb) {
  293.       ctb = (dynamic_cast<CubeTree*>(ctb))->child[i+1];
  294.       if (ctb) ctb->keep_walls(0,1,1);
  295.     }
  296.   }
  297.   if (i&2) {
  298.     child[i-2]->keep_walls(1,0,1);
  299.   } else {
  300.     CubeTreeBase *ctb = find_neighbor(face_negY);
  301.     if (ctb) {
  302.       ctb = (dynamic_cast<CubeTree*>(ctb))->child[i+2];
  303.       if (ctb) ctb->keep_walls(1,0,1);
  304.     }
  305.   }
  306.   if (i&4) {
  307.     child[i-4]->keep_walls(1,1,0);
  308.   } else {
  309.     CubeTreeBase *ctb = find_neighbor(face_negZ);
  310.     if (ctb) {
  311.       ctb = (dynamic_cast<CubeTree*>(ctb))->child[i+4];
  312.       if (ctb) ctb->keep_walls(1,1,0);
  313.     }
  314.   }
  315. }
  316. CubeTree::CubeTree (Pnt3 c, float s, CubeTree* _par, int _i)
  317.   : CubeTreeBase (c, s, _par, _i)
  318. {
  319.   for (int i = 0; i < 8; i++)
  320.     child[i] = NULL; 
  321. }
  322. CubeTree::~CubeTree (void)
  323. {
  324.   delete_children();
  325. }
  326. // recursively descend up to given level
  327. // then if the neighboring cube is outside,
  328. // create a face
  329. void
  330. CubeTree::extract_faces(vector<int> &tri_inds)
  331. {
  332.   // treat NOT_IN_FRUSTUM as OUTSIDE for now
  333.   // for INSIDE should perhaps test that it is truly
  334.   // all the way inside
  335.   //if (!boundary())
  336.   if (!go_on())
  337.     return;
  338.   // descend
  339.   for (int i = 0; i < 8; i++) {
  340.     assert(child[i]);
  341.     child[i]->extract_faces(tri_inds);
  342.   }
  343. }
  344. void
  345. CubeTree::keep_walls(bool x, bool y, bool z)
  346. {
  347.   int l=0;
  348.   for (int i=0; i<2; i++) {
  349.     for (int j=0; j<2; j++) {
  350.       for (int k=0; k<2; k++, l++) {
  351. if (child[l] == NULL) continue;
  352. if (k&&x || j&&y || i&&z) {
  353.   child[l]->keep_walls(x&&k, y&&j, z&&i);
  354. } else {
  355.   delete child[l];
  356.   child[l] = NULL;
  357. }
  358.       }
  359.     }
  360.   }    
  361. }
  362. void 
  363. CubeTree::carve_help(vector<RigidScan*> &views, int levels,
  364.      vector<int> &tri_inds,
  365.      float perc_min, float perc_max)
  366. {
  367.   // When checking status inflate size by the size of a leaf
  368.   // so if the surface goes close to the  CubeTreeLeaf block boundary, 
  369.   // its neighbors exist in the tree. 
  370.   vector<RigidScan*> remaining_views;
  371.   type = ::view_query_status (views, remaining_views,
  372.       mCtr, mSize+leafSize, type);
  373.   SHOW(levels);
  374.   //// only boundary nodes can have children
  375.   //if (!boundary()) return;
  376.   if (!go_on()) return;
  377.   if (levels == 0) return;
  378.   --levels;
  379.   float childSize = mSize*.5;
  380.   float stepSize  = mSize*.25;
  381.   bool allChildrenOut = true;
  382.   bool allChildrenIn  = true;
  383.   Pnt3 childCtr;
  384.   float perc_frac = (perc_max-perc_min) / 8.0;
  385.   for (int i=0; i<8; i++) {
  386.     childCtr.set(mCtr[0] + ((i&1) ? stepSize : -stepSize),
  387.  mCtr[1] + ((i&2) ? stepSize : -stepSize),
  388.  mCtr[2] + ((i&4) ? stepSize : -stepSize));
  389.     if (levels > leafDepth) {
  390.       CubeTree* ct = new CubeTree (childCtr, childSize, this, i);
  391.       child[i] = ct;
  392.       float _perc_min = perc_min + i*perc_frac;
  393.       ct->carve_help(remaining_views, levels, tri_inds,
  394.      _perc_min, _perc_min + perc_frac);
  395.       cout << "Carved " << _perc_min + perc_frac << " percent" << endl;
  396.     } else {
  397.       CubeTreeLeaf* ctl = new CubeTreeLeaf(childCtr, childSize,
  398.    this, i, views);
  399.       child[i] = ctl;
  400.       ctl->extract_faces(tri_inds);
  401.     }
  402.     /*    
  403.     // release unneeded parts of the tree
  404.     if (i&1) child[i-1]->keep_walls(0,1,1);
  405.     else {
  406.       CubeTreeBase *ctb = find_neighbor(face_negX);
  407.       if (ctb) {
  408. CubeTree *ct = dynamic_cast<CubeTree*>(ctb);
  409. if (ct->child[i+1]) ct->child[i+1]->keep_walls(0,1,1);
  410.       }
  411.     }
  412.     if (i&2) child[i-2]->keep_walls(1,0,1);
  413.     if (i&4) child[i-4]->keep_walls(1,1,0);
  414.     */
  415.     release_space(i);
  416.     OccSt t = child[i]->type;
  417.     if (t != OUTSIDE) allChildrenOut = false;
  418.     if (t != INSIDE)  allChildrenIn  = false;
  419.   }
  420.   if (allChildrenOut) {
  421.     delete_children();
  422.     type = OUTSIDE;
  423.   } 
  424.   if (allChildrenIn) {
  425.     delete_children();
  426.     type = INSIDE;
  427.   }
  428. }
  429. //#define VIS_TRIOCTREE
  430. #ifdef VIS_TRIOCTREE
  431. #include "CyraScan.h"
  432. #include "TriOctree.h"
  433. #endif
  434. // first split, then
  435. // extract the boundary between outsides and the rest
  436. void 
  437. CubeTree::carve(vector<RigidScan*> &views, int levels,
  438. vector<Pnt3> &coords, vector<int> &tri_inds)
  439. {
  440. #ifdef VIS_TRIOCTREE
  441.   CyraScan *cs = dynamic_cast<CyraScan*> (views[0]);
  442.   if (cs) cs->TriOctreeMesh(coords, tri_inds);
  443.   return;
  444. #endif
  445.   // Figure out the size of the leaves.
  446.   leafSize = mSize; 
  447.   for (int j = 0; j<levels; j++) leafSize *= .5;
  448.   nVoxels  = 1<<3*leafDepth;
  449.   mem_handler.set_blocksize(nVoxels);
  450.   tri_inds.clear();
  451.   vertex_list.clear();
  452.   /*
  453.   fbhi = fblo = mCtr;
  454.   Pnt3 step(mSize*.5,mSize*.5,mSize*.5);
  455.   fbhi += step;
  456.   fblo -= step;
  457.   encode_scale = .99999 * encode_shift / (fbhi[0] - fblo[0]);
  458.   */
  459.   carve_help(views, levels, tri_inds, 0, 100);
  460.   delete_children();
  461.   coords = vertex_list;
  462.   SHOW(vertex_list.size());
  463.   SHOW(tri_inds.size());
  464.   vertex_list.clear();
  465.   for (int i=0; i<coords.size(); i++) {
  466.     if (isnanf(coords[i][0]) ||
  467. isnanf(coords[i][1]) ||
  468. isnanf(coords[i][2])) {
  469.       SHOW(i); SHOW(coords[i]);
  470.       break;
  471.     }
  472.   }
  473. }
  474. //#define CARVE_TEST
  475. static int leaf_count = 0;
  476. CubeTreeLeaf::CubeTreeLeaf (const Pnt3 &c, float s,
  477.     CubeTree* _par, int _i,
  478.     vector<RigidScan*> &views)
  479.   : CubeTreeBase (c, s, _par, _i), data(NULL)
  480. {
  481.   // When checking status inflate size by the size of a leaf
  482.   // so if the surface goes close to the  CubeTreeLeaf block boundary, 
  483.   // it's neighbors exist in the tree. 
  484.   vector<RigidScan*> remaining_views;
  485.   type = ::view_query_status (views, remaining_views,
  486.       c, s+leafSize);
  487.   //type = ::view_query_status (views, c, 1.25*leafSize);
  488.   //if (!boundary())
  489.   if (!go_on())
  490.     return;
  491.   leaf_count++;
  492.   SHOW(leaf_count);
  493. #ifdef CARVE_TEST
  494.   return;
  495. #endif
  496.   nLeavesPerSide = 1 << leafDepth;
  497.   mask = nLeavesPerSide - 1;
  498.   //data = new CubeTreeLeafData[nVoxels];
  499.   data = mem_handler();
  500.   float tmp = .5 * (nLeavesPerSide - 1) * leafSize;
  501.   Pnt3 base(mCtr[0]-tmp, mCtr[1]-tmp, mCtr[2]-tmp);
  502.   Pnt3 lCtr;
  503.   int depth2 = 2*leafDepth;
  504.   int x, y, z;
  505.   // evaluate the function at all the leaf nodes
  506.   // also interpolate the edges here
  507.   int ofsx = 1;
  508.   int ofsy = 1<<leafDepth;
  509.   int ofsz = 1<<depth2;
  510.   // length of the step to go to the other end along this dimension
  511.   int lenx = ofsy-ofsx;
  512.   int leny = ofsz-ofsy;
  513.   int lenz = (1<<leafDepth+depth2)-ofsz;
  514.   CubeTreeLeafData *vp;
  515.   CubeTreeLeaf* nborX = find_neighbor (face_negX);
  516.   if (nborX && !nborX->data) nborX = NULL;
  517.   CubeTreeLeaf* nborY = find_neighbor (face_negY);
  518.   if (nborY && !nborY->data) nborY = NULL;
  519.   CubeTreeLeaf* nborZ = find_neighbor (face_negZ);
  520.   if (nborZ && !nborZ->data) nborZ = NULL;
  521.   int i = 0;
  522.   for (z=0; z<nLeavesPerSide; z++) {
  523.     for (y=0; y<nLeavesPerSide; y++) {
  524.       for (x=0; x<nLeavesPerSide; x++, i++) {
  525. float &dist = data[i].distance;
  526. lCtr.set(base[0] + leafSize*x, 
  527.  base[1] + leafSize*y, 
  528.  base[2] + leafSize*z);
  529. data[i].confidence = view_query_distance(views, lCtr,dist);
  530. // if zero confidence, assign arbitrarily dist = 1.0
  531. if (data[i].confidence < 1e-5) dist = 1.0;
  532. assert(dist > -1e22 && dist < 1e22);
  533. // interpolate edges
  534. if (x) {
  535.   vp = &data[i-ofsx];
  536. } else {
  537.   if (nborX)  vp = &nborX->data[i+lenx];
  538.   else        vp = NULL;
  539. }
  540. if (vp && dist * vp->distance <= 0.0) {
  541.   // signs differ, interpolate
  542.   vp->eixi = vertex_list.size();
  543.   float d = leafSize * dist / (dist - vp->distance);
  544.   assert(!isnanf(d));
  545.   vertex_list.push_back(Pnt3(lCtr[0]-d, lCtr[1], lCtr[2]));
  546. }
  547. if (y) {
  548.   vp = &data[i-ofsy];
  549. } else {
  550.   if (nborY)  vp = &nborY->data[i+leny];
  551.   else        vp = NULL;
  552. }
  553. if (vp && dist * vp->distance <= 0.0) {
  554.   // signs differ, interpolate
  555.   vp->eiyi = vertex_list.size();
  556.   float d = leafSize * dist / (dist - vp->distance);
  557.   assert(!isnanf(d));
  558.   vertex_list.push_back(Pnt3(lCtr[0], lCtr[1]-d, lCtr[2]));
  559. }
  560. if (z) {
  561.   vp = &data[i-ofsz];
  562. } else {
  563.   if (nborZ)  vp = &nborZ->data[i+lenz];
  564.   else        vp = NULL;
  565. }
  566. if (vp && dist * vp->distance <= 0.0) {
  567.   // signs differ, interpolate
  568.   vp->eizi = vertex_list.size();
  569.   float d = leafSize * dist / (dist - vp->distance);
  570.   assert(!isnanf(d));
  571.   vertex_list.push_back(Pnt3(lCtr[0], lCtr[1], lCtr[2]-d));
  572. }
  573.       }
  574.     }
  575.   }
  576. }
  577. CubeTreeLeaf::~CubeTreeLeaf (void)
  578. {
  579.   //delete[] data;
  580.   if (data) mem_handler.store(data);
  581. }
  582. static void
  583. cube_bdry(const Pnt3 &ctr, float size, 
  584.   vector<Pnt3> &p, vector<int> &i)
  585. {
  586.   float w = .5 * size;
  587.   p.push_back(ctr + Pnt3(-w,-w,-w));
  588.   p.push_back(ctr + Pnt3(-w,-w, w));
  589.   p.push_back(ctr + Pnt3(-w, w,-w));
  590.   p.push_back(ctr + Pnt3(-w, w, w));
  591.   p.push_back(ctr + Pnt3( w,-w,-w));
  592.   p.push_back(ctr + Pnt3( w,-w, w));
  593.   p.push_back(ctr + Pnt3( w, w,-w));
  594.   p.push_back(ctr + Pnt3( w, w, w));
  595.   static int triinds[] = {
  596.     0,1,3,2,0,3, 0,4,5,0,5,1, 2,6,4,2,4,0,
  597.     3,5,7,3,1,5, 2,7,6,2,3,7, 7,4,6,7,5,4
  598.   };
  599.   int   s = vertex_list.size();
  600.   for (int j=0; j<36; j++) 
  601.     i.push_back(s+triinds[j]);
  602. }
  603. static EdgeTable TheEdgeTable;
  604. void
  605. CubeTreeLeaf::extract_faces(vector<int> &tri_inds)
  606. {
  607.   //if (!boundary()) return;
  608.   if (!go_on()) return;
  609. #ifdef CARVE_TEST
  610.   cube_bdry(mCtr, mSize, vertex_list, tri_inds);
  611.   return;
  612. #endif
  613.   int depth2 = 2*leafDepth;
  614.   int x, y, z;
  615.   int ofsx = 1;
  616.   int ofsy = 1<<leafDepth;
  617.   int ofsz = 1<<depth2;
  618.   // length of the step to go to the other end along this dimension
  619.   int lenx = ofsy-ofsx;
  620.   int leny = ofsz-ofsy;
  621.   int lenz = nVoxels-ofsz;
  622.   for (int i = 0; i < nVoxels; i++) {
  623.     // set CubeTreeLeafData static center and size
  624.     // nVoxels has depth bits each for x, y, z
  625.     // find center of corresponding voxel i
  626.     x = (i)              & mask;
  627.     y = (i >> leafDepth) & mask;
  628.     z = (i >> depth2)    & mask;
  629.     //if (x&&y&&z) continue;
  630.     // get the eight pointers to vertices
  631.     // create also the index to the edge table
  632.     CubeTreeLeafData *vp[8];
  633.     int edgeTableIndex = 0;
  634.     CubeTreeLeaf *nborX = NULL, *nborY = NULL, *nborZ = NULL;
  635.     CubeTreeLeaf *nborXY = NULL, *nborXZ = NULL, *nborYZ = NULL;
  636.     // these are the default vertices
  637.     // the ones with a negative index to data will be replaced
  638.     int j;
  639.     vp[0] = ((j=i-ofsx-ofsy-ofsz) < 0 ? NULL : &data[j]);
  640.     vp[1] = ((j=i     -ofsy-ofsz) < 0 ? NULL : &data[j]);
  641.     vp[2] = ((j=i          -ofsz) < 0 ? NULL : &data[j]);
  642.     vp[3] = ((j=i-ofsx     -ofsz) < 0 ? NULL : &data[j]);
  643.     vp[4] = ((j=i-ofsx-ofsy     ) < 0 ? NULL : &data[j]);
  644.     vp[5] = ((j=i     -ofsy     ) < 0 ? NULL : &data[j]);
  645.     vp[6] = &data[i];
  646.     vp[7] = ((j=i-ofsx          ) < 0 ? NULL : &data[j]);
  647.     if (x == 0) {
  648.       nborX = find_neighbor (face_negX);
  649.       if (nborX && nborX->data) {
  650. vp[0] = ((j=i+lenx-ofsy-ofsz) < 0 ? NULL : &nborX->data[j]);
  651. vp[3] = ((j=i+lenx     -ofsz) < 0 ? NULL : &nborX->data[j]);
  652. vp[4] = ((j=i+lenx-ofsy     ) < 0 ? NULL : &nborX->data[j]);
  653. vp[7] = &nborX->data[i+lenx];
  654.       } else {
  655. continue; // no neighbor, skip
  656.       }
  657.     }
  658.     if (y == 0) {
  659.       nborY = find_neighbor (face_negY);
  660.       if (nborY && nborY->data) {
  661. vp[0] = ((j=i+leny-ofsx-ofsz) < 0 ? NULL : &nborY->data[j]);
  662. vp[1] = ((j=i+leny     -ofsz) < 0 ? NULL : &nborY->data[j]);
  663. vp[4] = &nborY->data[i+leny-ofsx];
  664. vp[5] = &nborY->data[i+leny];
  665.       } else {
  666. continue; // no neighbor, skip
  667.       }
  668.     }
  669.     
  670.     if (z == 0) {
  671.       nborZ = find_neighbor (face_negZ);
  672.       if (nborZ && nborZ->data) {
  673. vp[0] = &nborZ->data[i+lenz-ofsx-ofsy];
  674. vp[1] = &nborZ->data[i+lenz     -ofsy];
  675. vp[2] = &nborZ->data[i+lenz          ];
  676. vp[3] = &nborZ->data[i+lenz-ofsx     ];
  677.       } else {
  678. continue; // no neighbor, skip
  679.       }
  680.     }
  681.     if (nborX && nborY) { // then out in both x and y
  682.       nborXY = nborY->find_neighbor (face_negX);
  683.       if (nborXY && nborXY->data) {
  684. vp[0] = ((j=i+lenx+leny-ofsz) < 0 ? NULL : &nborXY->data[j]);
  685. vp[4] = &nborXY->data[i+lenx+leny];
  686.       } else {
  687. continue; // no neighbor, skip
  688.       }
  689.     }
  690.     if (nborX && nborZ) {
  691.       nborXZ = nborX->find_neighbor (face_negZ);
  692.       if (nborXZ && nborXZ->data) {
  693. vp[0] = &nborXZ->data[i+lenx+lenz-ofsy];
  694. vp[3] = &nborXZ->data[i+lenx+lenz];
  695.       } else {
  696. continue; // no neighbor, skip
  697.       }
  698.     }
  699.     if (nborY && nborZ) {
  700.       nborYZ = nborZ->find_neighbor (face_negY);
  701.       if (nborYZ && nborYZ->data) {
  702. vp[0] = &nborYZ->data[i+leny+lenz-ofsx];
  703. vp[1] = &nborYZ->data[i+leny+lenz];
  704.       } else {
  705. continue; // no neighbor, skip
  706.       }
  707.     }
  708.     
  709.     if (nborXY && nborZ) {
  710.       CubeTreeLeaf* nborXYZ = nborXY->find_neighbor (face_negZ);
  711.       if (nborXYZ && nborXYZ->data) {
  712. vp[0] = &nborXYZ->data[i+lenx+leny+lenz];
  713.       } else {
  714. continue; // no neighbor, skip
  715.       }
  716.     }
  717.     for (j=0; j<8; j++) 
  718.       assert(vp[j]->distance > -1e22 && vp[j]->distance < 1e22);
  719.     
  720.     if (vp[0]->distance > 0.0) edgeTableIndex |=   1;
  721.     if (vp[1]->distance > 0.0) edgeTableIndex |=   2;
  722.     if (vp[2]->distance > 0.0) edgeTableIndex |=   4;
  723.     if (vp[3]->distance > 0.0) edgeTableIndex |=   8;
  724.     if (vp[4]->distance > 0.0) edgeTableIndex |=  16;
  725.     if (vp[5]->distance > 0.0) edgeTableIndex |=  32;
  726.     if (vp[6]->distance > 0.0) edgeTableIndex |=  64;
  727.     if (vp[7]->distance > 0.0) edgeTableIndex |= 128;
  728.     // for all the 12 edges, if the table tells that there should
  729.     // be an edge, copy a pointer to the corresponding precalculated vertex
  730.     bool *edge = TheEdgeTable[edgeTableIndex].edge;
  731.     int evtx[12];
  732.     if (edge[0])  evtx[0]  = vp[0]->eixi;
  733.     if (edge[1])  evtx[1]  = vp[1]->eiyi;
  734.     if (edge[2])  evtx[2]  = vp[3]->eixi;
  735.     if (edge[3])  evtx[3]  = vp[0]->eiyi;
  736.     if (edge[4])  evtx[4]  = vp[4]->eixi;
  737.     if (edge[5])  evtx[5]  = vp[5]->eiyi;
  738.     if (edge[6])  evtx[6]  = vp[7]->eixi;
  739.     if (edge[7])  evtx[7]  = vp[4]->eiyi;
  740.     if (edge[8])  evtx[8]  = vp[0]->eizi;
  741.     if (edge[9])  evtx[9]  = vp[1]->eizi;
  742.     if (edge[10]) evtx[10] = vp[3]->eizi;
  743.     if (edge[11]) evtx[11] = vp[2]->eizi;
  744.     int nTrisCreated = TheEdgeTable[edgeTableIndex].Ntriangles;
  745.     Triple *triList  = TheEdgeTable[edgeTableIndex].TriangleList;
  746.     for (j=0; j<nTrisCreated; j++) {
  747. #if 0
  748.       SHOW (evtx[triList[j].A]);
  749.       SHOW (evtx[triList[j].B]);
  750.       SHOW (evtx[triList[j].C]);
  751. #endif
  752.       assert(evtx[triList[j].A]>-1);
  753.       assert(evtx[triList[j].B]>-1);
  754.       assert(evtx[triList[j].C]>-1);
  755.       tri_inds.push_back(evtx[triList[j].A]);
  756.       tri_inds.push_back(evtx[triList[j].B]);
  757.       tri_inds.push_back(evtx[triList[j].C]);
  758.     }
  759.   }
  760. }
  761. void
  762. CubeTreeLeaf::keep_walls(bool , bool , bool )
  763. {
  764. }
  765. OccSt
  766. CubeTreeLeaf::neighbor_status (int face, int child)
  767. {
  768.   // get address, and child status, of neighbor of given child
  769.   bool sibling = is_neighbor_cell (face, child);
  770.   if (sibling)
  771.     return type;
  772.   // not a child of this block; have to go up tree
  773.   CubeTreeBase* ctb = CubeTreeBase::find_neighbor (face);
  774.   CubeTreeLeaf* ctl = dynamic_cast<CubeTreeLeaf*> (ctb);
  775.   if (!ctb)
  776.     return OUTSIDE;
  777.   return ctl->type;
  778. }
  779. CubeTreeBase*
  780. CubeTreeLeaf::recursive_find(int face, 
  781.      stack<int>& path, bool bReachedTop)
  782. {
  783.   return this;
  784. }
  785. CubeTreeLeaf*
  786. CubeTreeLeaf::find_neighbor (int face)
  787. {
  788.   return dynamic_cast<CubeTreeLeaf*> (CubeTreeBase::find_neighbor (face));
  789. }
  790. bool
  791. CubeTreeLeaf::is_neighbor_cell (int face, int& child)
  792. {
  793.   // child is both input and output parameter...
  794.   bool contained = true;
  795.   int axis = face / 2;
  796.   int sign = face % 2;
  797.   // need to extract relevant bits, munge them, and replace them into child:
  798.   // extract
  799.   int shift = axis * leafDepth;
  800.   int coord = (child & (mask << shift)) >> shift;
  801.   // munge
  802.   coord += (sign ? +1 : -1);
  803.   if (coord >= nLeavesPerSide) {
  804.     contained = false;
  805.     coord -= nLeavesPerSide;
  806.   }
  807.   else if (coord < 0) {
  808.     contained = false;
  809.     coord += nLeavesPerSide;
  810.   }
  811.   // replace
  812.   child = (child & ~(mask << shift)) | (coord << shift);
  813.   return contained;
  814. }