Blender  V2.93
octree.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #ifdef WITH_CXX_GUARDEDALLOC
18 # include "MEM_guardedalloc.h"
19 #endif
20 
21 #include "octree.h"
22 #include <Eigen/Dense>
23 #include <limits>
24 #include <time.h>
25 
32 /* set to non-zero value to enable debugging output */
33 #define DC_DEBUG 0
34 
35 #if DC_DEBUG
36 /* enable debug printfs */
37 # define dc_printf printf
38 #else
39 /* disable debug printfs */
40 # define dc_printf(...) \
41  do { \
42  } while (0)
43 #endif
44 
46  DualConAllocOutput alloc_output_func,
47  DualConAddVert add_vert_func,
48  DualConAddQuad add_quad_func,
49  DualConFlags flags,
50  DualConMode dualcon_mode,
51  int depth,
52  float threshold,
53  float sharpness)
54  : use_flood_fill(flags & DUALCON_FLOOD_FILL),
55  /* note on `use_manifold':
56 
57  After playing around with this option, the only case I could
58  find where this option gives different results is on
59  relatively thin corners. Sometimes along these corners two
60  vertices from separate sides will be placed in the same
61  position, so hole gets filled with a 5-sided face, where two
62  of those vertices are in the same 3D location. If
63  `use_manifold' is disabled, then the modifier doesn't
64  generate two separate vertices so the results end up as all
65  quads.
66 
67  Since the results are just as good with all quads, there
68  doesn't seem any reason to allow this to be toggled in
69  Blender. -nicholasbishop
70  */
71  use_manifold(false),
72  hermite_num(sharpness),
73  mode(dualcon_mode),
74  alloc_output(alloc_output_func),
75  add_vert(add_vert_func),
76  add_quad(add_quad_func)
77 {
78  thresh = threshold;
79  reader = mr;
80  dimen = 1 << GRID_DIMENSION;
82  nodeCount = nodeSpace = 0;
83  maxDepth = depth;
84  mindimen = (dimen >> maxDepth);
86  buildTable();
87 
89 
90  // Initialize memory
91 #ifdef IN_VERBOSE_MODE
92  dc_printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2]);
93  dc_printf("Initialize memory...\n");
94 #endif
95  initMemory();
96  root = (Node *)createInternal(0);
97 
98  // Read MC table
99 #ifdef IN_VERBOSE_MODE
100  dc_printf("Reading contour table...\n");
101 #endif
102  cubes = new Cubes();
103 }
104 
106 {
107  delete cubes;
108  freeMemory();
109 }
110 
112 {
113  // Scan triangles
114 #if DC_DEBUG
115  clock_t start, finish;
116  start = clock();
117 #endif
118 
119  addAllTriangles();
120  resetMinimalEdges();
121  preparePrimalEdgesMask(&root->internal);
122 
123 #if DC_DEBUG
124  finish = clock();
125  dc_printf("Time taken: %f seconds \n",
126  (double)(finish - start) / CLOCKS_PER_SEC);
127 #endif
128 
129  // Generate signs
130  // Find holes
131 #if DC_DEBUG
132  dc_printf("Patching...\n");
133  start = clock();
134 #endif
135  trace();
136 #if DC_DEBUG
137  finish = clock();
138  dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
139 # ifdef IN_VERBOSE_MODE
140  dc_printf("Holes: %d Average Length: %f Max Length: %d \n",
141  numRings,
142  (float)totRingLengths / (float)numRings,
143  maxRingLength);
144 # endif
145 #endif
146 
147  // Check again
148  int tnumRings = numRings;
149  trace();
150 #ifdef IN_VERBOSE_MODE
151  dc_printf("Holes after patching: %d \n", numRings);
152 #endif
153  numRings = tnumRings;
154 
155 #if DC_DEBUG
156  dc_printf("Building signs...\n");
157  start = clock();
158 #endif
159  buildSigns();
160 #if DC_DEBUG
161  finish = clock();
162  dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
163 #endif
164 
165  if (use_flood_fill) {
166  /*
167  start = clock();
168  floodFill();
169  // Check again
170  tnumRings = numRings;
171  trace();
172  dc_printf("Holes after filling: %d \n", numRings);
173  numRings = tnumRings;
174  buildSigns();
175  finish = clock();
176  dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
177  */
178 #if DC_DEBUG
179  start = clock();
180  dc_printf("Removing components...\n");
181 #endif
182  floodFill();
183  buildSigns();
184  // dc_printf("Checking...\n");
185  // floodFill();
186 #if DC_DEBUG
187  finish = clock();
188  dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
189 #endif
190  }
191 
192  // Output
193 #if DC_DEBUG
194  start = clock();
195 #endif
196  writeOut();
197 #if DC_DEBUG
198  finish = clock();
199 #endif
200  // dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
201 
202  // Print info
203 #ifdef IN_VERBOSE_MODE
204  printMemUsage();
205 #endif
206 }
207 
208 void Octree::initMemory()
209 {
214 
224 }
225 
226 void Octree::freeMemory()
227 {
228  for (int i = 0; i < 9; i++) {
229  alloc[i]->destroy();
230  delete alloc[i];
231  }
232 
233  for (int i = 0; i < 4; i++) {
234  leafalloc[i]->destroy();
235  delete leafalloc[i];
236  }
237 }
238 
239 void Octree::printMemUsage()
240 {
241  int totalbytes = 0;
242  dc_printf("********* Internal nodes: \n");
243  for (int i = 0; i < 9; i++) {
244  alloc[i]->printInfo();
245 
246  totalbytes += alloc[i]->getAll() * alloc[i]->getBytes();
247  }
248  dc_printf("********* Leaf nodes: \n");
249  int totalLeafs = 0;
250  for (int i = 0; i < 4; i++) {
251  leafalloc[i]->printInfo();
252 
253  totalbytes += leafalloc[i]->getAll() * leafalloc[i]->getBytes();
254  totalLeafs += leafalloc[i]->getAllocated();
255  }
256 
257  dc_printf("Total allocated bytes on disk: %d \n", totalbytes);
258  dc_printf("Total leaf nodes: %d\n", totalLeafs);
259 }
260 
261 void Octree::resetMinimalEdges()
262 {
263  cellProcParity(root, 0, maxDepth);
264 }
265 
266 void Octree::addAllTriangles()
267 {
268  Triangle *trian;
269  int count = 0;
270 
271 #if DC_DEBUG
272  int total = reader->getNumTriangles();
273  int unitcount = 1000;
274  dc_printf("\nScan converting to depth %d...\n", maxDepth);
275 #endif
276 
277  srand(0);
278 
279  while ((trian = reader->getNextTriangle()) != NULL) {
280  // Drop triangles
281  {
282  addTriangle(trian, count);
283  }
284  delete trian;
285 
286  count++;
287 
288 #if DC_DEBUG
289  if (count % unitcount == 0) {
290  putchar(13);
291 
292  switch ((count / unitcount) % 4) {
293  case 0:
294  dc_printf("-");
295  break;
296  case 1:
297  dc_printf("/");
298  break;
299  case 2:
300  dc_printf("|");
301  break;
302  case 3:
303  dc_printf("\\");
304  break;
305  }
306 
307  float percent = (float)count / total;
308 
309  /*
310  int totbars = 50;
311  int bars =(int)(percent * totbars);
312  for(int i = 0; i < bars; i ++) {
313  putchar(219);
314  }
315  for(i = bars; i < totbars; i ++) {
316  putchar(176);
317  }
318  */
319 
320  dc_printf(" %d triangles: ", count);
321  dc_printf(" %f%% complete.", 100 * percent);
322  }
323 #endif
324  }
325  putchar(13);
326 }
327 
328 /* Prepare a triangle for insertion into the octree; call the other
329  addTriangle() to (recursively) build the octree */
330 void Octree::addTriangle(Triangle *trian, int triind)
331 {
332  int i, j;
333 
334  /* Project the triangle's coordinates into the grid */
335  for (i = 0; i < 3; i++) {
336  for (j = 0; j < 3; j++)
337  trian->vt[i][j] = dimen * (trian->vt[i][j] - origin[j]) / range;
338  }
339 
340  /* Generate projections */
341  int64_t cube[2][3] = {{0, 0, 0}, {dimen, dimen, dimen}};
342  int64_t trig[3][3];
343  for (i = 0; i < 3; i++) {
344  for (j = 0; j < 3; j++)
345  trig[i][j] = (int64_t)(trian->vt[i][j]);
346  }
347 
348  /* Add triangle to the octree */
349  int64_t errorvec = (int64_t)(0);
350  CubeTriangleIsect *proj = new CubeTriangleIsect(cube, trig, errorvec, triind);
351  root = (Node *)addTriangle(&root->internal, proj, maxDepth);
352 
353  delete proj->inherit;
354  delete proj;
355 }
356 
357 #if 0
358 static void print_depth(int height, int maxDepth)
359 {
360  for (int i = 0; i < maxDepth - height; i++)
361  printf(" ");
362 }
363 #endif
364 
365 InternalNode *Octree::addTriangle(InternalNode *node, CubeTriangleIsect *p, int height)
366 {
367  int i;
368  const int vertdiff[8][3] = {
369  {0, 0, 0}, {0, 0, 1}, {0, 1, -1}, {0, 0, 1}, {1, -1, -1}, {0, 0, 1}, {0, 1, -1}, {0, 0, 1}};
370  unsigned char boxmask = p->getBoxMask();
371  CubeTriangleIsect *subp = new CubeTriangleIsect(p);
372 
373  int count = 0;
374  int tempdiff[3] = {0, 0, 0};
375 
376  /* Check triangle against each of the input node's children */
377  for (i = 0; i < 8; i++) {
378  tempdiff[0] += vertdiff[i][0];
379  tempdiff[1] += vertdiff[i][1];
380  tempdiff[2] += vertdiff[i][2];
381 
382  /* Quick pruning using bounding box */
383  if (boxmask & (1 << i)) {
384  subp->shift(tempdiff);
385  tempdiff[0] = tempdiff[1] = tempdiff[2] = 0;
386 
387  /* Pruning using intersection test */
388  if (subp->isIntersecting()) {
389  if (!node->has_child(i)) {
390  if (height == 1)
391  node = addLeafChild(node, i, count, createLeaf(0));
392  else
393  node = addInternalChild(node, i, count, createInternal(0));
394  }
395  Node *chd = node->get_child(count);
396 
397  if (node->is_child_leaf(i))
398  node->set_child(count, (Node *)updateCell(&chd->leaf, subp));
399  else
400  node->set_child(count, (Node *)addTriangle(&chd->internal, subp, height - 1));
401  }
402  }
403 
404  if (node->has_child(i))
405  count++;
406  }
407 
408  delete subp;
409 
410  return node;
411 }
412 
413 LeafNode *Octree::updateCell(LeafNode *node, CubeTriangleIsect *p)
414 {
415  int i;
416 
417  // Edge connectivity
418  int mask[3] = {0, 4, 8};
419  int oldc = 0, newc = 0;
420  float offs[3];
421  float a[3], b[3], c[3];
422 
423  for (i = 0; i < 3; i++) {
424  if (!getEdgeParity(node, mask[i])) {
425  if (p->isIntersectingPrimary(i)) {
426  // actualQuads ++;
427  setEdge(node, mask[i]);
428  offs[newc] = p->getIntersectionPrimary(i);
429  a[newc] = (float)p->inherit->norm[0];
430  b[newc] = (float)p->inherit->norm[1];
431  c[newc] = (float)p->inherit->norm[2];
432  newc++;
433  }
434  }
435  else {
436  offs[newc] = getEdgeOffsetNormal(node, oldc, a[newc], b[newc], c[newc]);
437 
438  oldc++;
439  newc++;
440  }
441  }
442 
443  if (newc > oldc) {
444  // New offsets added, update this node
445  node = updateEdgeOffsetsNormals(node, oldc, newc, offs, a, b, c);
446  }
447 
448  return node;
449 }
450 
451 void Octree::preparePrimalEdgesMask(InternalNode *node)
452 {
453  int count = 0;
454  for (int i = 0; i < 8; i++) {
455  if (node->has_child(i)) {
456  if (node->is_child_leaf(i))
457  createPrimalEdgesMask(&node->get_child(count)->leaf);
458  else
459  preparePrimalEdgesMask(&node->get_child(count)->internal);
460 
461  count++;
462  }
463  }
464 }
465 
466 void Octree::trace()
467 {
468  int st[3] = {
469  0,
470  0,
471  0,
472  };
473  numRings = 0;
474  totRingLengths = 0;
475  maxRingLength = 0;
476 
477  PathList *chdpath = NULL;
478  root = trace(root, st, dimen, maxDepth, chdpath);
479 
480  if (chdpath != NULL) {
481  dc_printf("there are incomplete rings.\n");
482  printPaths(chdpath);
483  }
484 }
485 
486 Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *&paths)
487 {
488  len >>= 1;
489  PathList *chdpaths[8];
490  Node *chd[8];
491  int nst[8][3];
492  int i, j;
493 
494  // Get children paths
495  int chdleaf[8];
496  newnode->internal.fill_children(chd, chdleaf);
497 
498  // int count = 0;
499  for (i = 0; i < 8; i++) {
500  for (j = 0; j < 3; j++) {
501  nst[i][j] = st[j] + len * vertmap[i][j];
502  }
503 
504  if (chd[i] == NULL || newnode->internal.is_child_leaf(i)) {
505  chdpaths[i] = NULL;
506  }
507  else {
508  trace(chd[i], nst[i], len, depth - 1, chdpaths[i]);
509  }
510  }
511 
512  // Get connectors on the faces
513  PathList *conn[12];
514  Node *nf[2];
515  int lf[2];
516  int df[2] = {depth - 1, depth - 1};
517  int *nstf[2];
518 
519  newnode->internal.fill_children(chd, chdleaf);
520 
521  for (i = 0; i < 12; i++) {
522  int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
523 
524  for (int j = 0; j < 2; j++) {
525  lf[j] = chdleaf[c[j]];
526  nf[j] = chd[c[j]];
527  nstf[j] = nst[c[j]];
528  }
529 
530  conn[i] = NULL;
531 
532  findPaths((Node **)nf, lf, df, nstf, depth - 1, cellProcFaceMask[i][2], conn[i]);
533 
534 #if 0
535  if (conn[i]) {
536  printPath(conn[i]);
537  }
538 #endif
539  }
540 
541  // Connect paths
542  PathList *rings = NULL;
543  combinePaths(chdpaths[0], chdpaths[1], conn[8], rings);
544  combinePaths(chdpaths[2], chdpaths[3], conn[9], rings);
545  combinePaths(chdpaths[4], chdpaths[5], conn[10], rings);
546  combinePaths(chdpaths[6], chdpaths[7], conn[11], rings);
547 
548  combinePaths(chdpaths[0], chdpaths[2], conn[4], rings);
549  combinePaths(chdpaths[4], chdpaths[6], conn[5], rings);
550  combinePaths(chdpaths[0], NULL, conn[6], rings);
551  combinePaths(chdpaths[4], NULL, conn[7], rings);
552 
553  combinePaths(chdpaths[0], chdpaths[4], conn[0], rings);
554  combinePaths(chdpaths[0], NULL, conn[1], rings);
555  combinePaths(chdpaths[0], NULL, conn[2], rings);
556  combinePaths(chdpaths[0], NULL, conn[3], rings);
557 
558  // By now, only chdpaths[0] and rings have contents
559 
560  // Process rings
561  if (rings) {
562  // printPath(rings);
563 
564  /* Let's count first */
565  PathList *trings = rings;
566  while (trings) {
567  numRings++;
568  totRingLengths += trings->length;
569  if (trings->length > maxRingLength) {
570  maxRingLength = trings->length;
571  }
572  trings = trings->next;
573  }
574 
575  // printPath(rings);
576  newnode = patch(newnode, st, (len << 1), rings);
577  }
578 
579  // Return incomplete paths
580  paths = chdpaths[0];
581  return newnode;
582 }
583 
584 void Octree::findPaths(
585  Node *node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList *&paths)
586 {
587  if (!(node[0] && node[1])) {
588  return;
589  }
590 
591  if (!(leaf[0] && leaf[1])) {
592  // Not at the bottom, recur
593 
594  // Fill children nodes
595  int i, j;
596  Node *chd[2][8];
597  int chdleaf[2][8];
598  int nst[2][8][3];
599 
600  for (j = 0; j < 2; j++) {
601  if (!leaf[j]) {
602  node[j]->internal.fill_children(chd[j], chdleaf[j]);
603 
604  int len = (dimen >> (maxDepth - depth[j] + 1));
605  for (i = 0; i < 8; i++) {
606  for (int k = 0; k < 3; k++) {
607  nst[j][i][k] = st[j][k] + len * vertmap[i][k];
608  }
609  }
610  }
611  }
612 
613  // 4 face calls
614  Node *nf[2];
615  int df[2];
616  int lf[2];
617  int *nstf[2];
618  for (i = 0; i < 4; i++) {
619  int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
620  for (int j = 0; j < 2; j++) {
621  if (leaf[j]) {
622  lf[j] = leaf[j];
623  nf[j] = node[j];
624  df[j] = depth[j];
625  nstf[j] = st[j];
626  }
627  else {
628  lf[j] = chdleaf[j][c[j]];
629  nf[j] = chd[j][c[j]];
630  df[j] = depth[j] - 1;
631  nstf[j] = nst[j][c[j]];
632  }
633  }
634  findPaths(nf, lf, df, nstf, maxdep - 1, faceProcFaceMask[dir][i][2], paths);
635  }
636  }
637  else {
638  // At the bottom, check this face
639  int ind = (depth[0] == maxdep ? 0 : 1);
640  int fcind = 2 * dir + (1 - ind);
641  if (getFaceParity((LeafNode *)node[ind], fcind)) {
642  // Add into path
643  PathElement *ele1 = new PathElement;
644  PathElement *ele2 = new PathElement;
645 
646  ele1->pos[0] = st[0][0];
647  ele1->pos[1] = st[0][1];
648  ele1->pos[2] = st[0][2];
649 
650  ele2->pos[0] = st[1][0];
651  ele2->pos[1] = st[1][1];
652  ele2->pos[2] = st[1][2];
653 
654  ele1->next = ele2;
655  ele2->next = NULL;
656 
657  PathList *lst = new PathList;
658  lst->head = ele1;
659  lst->tail = ele2;
660  lst->length = 2;
661  lst->next = paths;
662  paths = lst;
663 
664  // int l =(dimen >> maxDepth);
665  }
666  }
667 }
668 
669 void Octree::combinePaths(PathList *&list1, PathList *list2, PathList *paths, PathList *&rings)
670 {
671  // Make new list of paths
672  PathList *nlist = NULL;
673 
674  // Search for each connectors in paths
675  PathList *tpaths = paths;
676  PathList *tlist, *pre;
677  while (tpaths) {
678  PathList *singlist = tpaths;
679  PathList *templist;
680  tpaths = tpaths->next;
681  singlist->next = NULL;
682 
683  // Look for hookup in list1
684  tlist = list1;
685  pre = NULL;
686  while (tlist) {
687  if ((templist = combineSinglePath(list1, pre, tlist, singlist, NULL, singlist)) != NULL) {
688  singlist = templist;
689  continue;
690  }
691  pre = tlist;
692  tlist = tlist->next;
693  }
694 
695  // Look for hookup in list2
696  tlist = list2;
697  pre = NULL;
698  while (tlist) {
699  if ((templist = combineSinglePath(list2, pre, tlist, singlist, NULL, singlist)) != NULL) {
700  singlist = templist;
701  continue;
702  }
703  pre = tlist;
704  tlist = tlist->next;
705  }
706 
707  // Look for hookup in nlist
708  tlist = nlist;
709  pre = NULL;
710  while (tlist) {
711  if ((templist = combineSinglePath(nlist, pre, tlist, singlist, NULL, singlist)) != NULL) {
712  singlist = templist;
713  continue;
714  }
715  pre = tlist;
716  tlist = tlist->next;
717  }
718 
719  // Add to nlist or rings
720  if (isEqual(singlist->head, singlist->tail)) {
721  PathElement *temp = singlist->head;
722  singlist->head = temp->next;
723  delete temp;
724  singlist->length--;
725  singlist->tail->next = singlist->head;
726 
727  singlist->next = rings;
728  rings = singlist;
729  }
730  else {
731  singlist->next = nlist;
732  nlist = singlist;
733  }
734  }
735 
736  // Append list2 and nlist to the end of list1
737  tlist = list1;
738  if (tlist != NULL) {
739  while (tlist->next != NULL) {
740  tlist = tlist->next;
741  }
742  tlist->next = list2;
743  }
744  else {
745  tlist = list2;
746  list1 = list2;
747  }
748 
749  if (tlist != NULL) {
750  while (tlist->next != NULL) {
751  tlist = tlist->next;
752  }
753  tlist->next = nlist;
754  }
755  else {
756  tlist = nlist;
757  list1 = nlist;
758  }
759 }
760 
761 PathList *Octree::combineSinglePath(PathList *&head1,
762  PathList *pre1,
763  PathList *&list1,
764  PathList *&head2,
765  PathList *pre2,
766  PathList *&list2)
767 {
768  if (isEqual(list1->head, list2->head) || isEqual(list1->tail, list2->tail)) {
769  // Reverse the list
770  if (list1->length < list2->length) {
771  // Reverse list1
772  PathElement *prev = list1->head;
773  PathElement *next = prev->next;
774  prev->next = NULL;
775  while (next != NULL) {
776  PathElement *tnext = next->next;
777  next->next = prev;
778 
779  prev = next;
780  next = tnext;
781  }
782 
783  list1->tail = list1->head;
784  list1->head = prev;
785  }
786  else {
787  // Reverse list2
788  PathElement *prev = list2->head;
789  PathElement *next = prev->next;
790  prev->next = NULL;
791  while (next != NULL) {
792  PathElement *tnext = next->next;
793  next->next = prev;
794 
795  prev = next;
796  next = tnext;
797  }
798 
799  list2->tail = list2->head;
800  list2->head = prev;
801  }
802  }
803 
804  if (isEqual(list1->head, list2->tail)) {
805 
806  // Easy case
807  PathElement *temp = list1->head->next;
808  delete list1->head;
809  list2->tail->next = temp;
810 
811  PathList *nlist = new PathList;
812  nlist->length = list1->length + list2->length - 1;
813  nlist->head = list2->head;
814  nlist->tail = list1->tail;
815  nlist->next = NULL;
816 
817  deletePath(head1, pre1, list1);
818  deletePath(head2, pre2, list2);
819 
820  return nlist;
821  }
822  else if (isEqual(list1->tail, list2->head)) {
823  // Easy case
824  PathElement *temp = list2->head->next;
825  delete list2->head;
826  list1->tail->next = temp;
827 
828  PathList *nlist = new PathList;
829  nlist->length = list1->length + list2->length - 1;
830  nlist->head = list1->head;
831  nlist->tail = list2->tail;
832  nlist->next = NULL;
833 
834  deletePath(head1, pre1, list1);
835  deletePath(head2, pre2, list2);
836 
837  return nlist;
838  }
839 
840  return NULL;
841 }
842 
843 void Octree::deletePath(PathList *&head, PathList *pre, PathList *&curr)
844 {
845  PathList *temp = curr;
846  curr = temp->next;
847  delete temp;
848 
849  if (pre == NULL) {
850  head = curr;
851  }
852  else {
853  pre->next = curr;
854  }
855 }
856 
857 void Octree::printElement(PathElement *ele)
858 {
859  if (ele != NULL) {
860  dc_printf("(%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2]);
861  }
862 }
863 
864 void Octree::printPath(PathList *path)
865 {
866  PathElement *n = path->head;
867  int same = 0;
868 
869 #if DC_DEBUG
870  int len = (dimen >> maxDepth);
871 #endif
872  while (n && (same == 0 || n != path->head)) {
873  same++;
874  dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len);
875  n = n->next;
876  }
877 
878  if (n == path->head) {
879  dc_printf(" Ring!\n");
880  }
881  else {
882  dc_printf(" %p end!\n", n);
883  }
884 }
885 
886 void Octree::printPath(PathElement *path)
887 {
888  PathElement *n = path;
889  int same = 0;
890 #if DC_DEBUG
891  int len = (dimen >> maxDepth);
892 #endif
893  while (n && (same == 0 || n != path)) {
894  same++;
895  dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len);
896  n = n->next;
897  }
898 
899  if (n == path) {
900  dc_printf(" Ring!\n");
901  }
902  else {
903  dc_printf(" %p end!\n", n);
904  }
905 }
906 
907 void Octree::printPaths(PathList *path)
908 {
909  PathList *iter = path;
910  int i = 0;
911  while (iter != NULL) {
912  dc_printf("Path %d:\n", i);
913  printPath(iter);
914  iter = iter->next;
915  i++;
916  }
917 }
918 
919 Node *Octree::patch(Node *newnode, int st[3], int len, PathList *rings)
920 {
921 #ifdef IN_DEBUG_MODE
922  dc_printf("Call to PATCH with rings: \n");
923  printPaths(rings);
924 #endif
925 
926  /* Do nothing but couting
927  PathList* tlist = rings;
928  PathList* ttlist;
929  PathElement* telem, * ttelem;
930  while(tlist!= NULL) {
931  // printPath(tlist);
932  numRings ++;
933  totRingLengths += tlist->length;
934  if(tlist->length > maxRingLength) {
935  maxRingLength = tlist->length;
936  }
937  ttlist = tlist;
938  tlist = tlist->next;
939  }
940  return node;
941  */
942 
943  /* Pass onto separate calls in each direction */
944  if (len == mindimen) {
945  dc_printf("Error! should have no list by now.\n");
946  exit(0);
947  }
948 
949  // YZ plane
950  PathList *xlists[2];
951  newnode = patchSplit(newnode, st, len, rings, 0, xlists[0], xlists[1]);
952 
953  // XZ plane
954  PathList *ylists[4];
955  newnode = patchSplit(newnode, st, len, xlists[0], 1, ylists[0], ylists[1]);
956  newnode = patchSplit(newnode, st, len, xlists[1], 1, ylists[2], ylists[3]);
957 
958  // XY plane
959  PathList *zlists[8];
960  newnode = patchSplit(newnode, st, len, ylists[0], 2, zlists[0], zlists[1]);
961  newnode = patchSplit(newnode, st, len, ylists[1], 2, zlists[2], zlists[3]);
962  newnode = patchSplit(newnode, st, len, ylists[2], 2, zlists[4], zlists[5]);
963  newnode = patchSplit(newnode, st, len, ylists[3], 2, zlists[6], zlists[7]);
964 
965  // Recur
966  len >>= 1;
967  int count = 0;
968  for (int i = 0; i < 8; i++) {
969  if (zlists[i] != NULL) {
970  int nori[3] = {
971  st[0] + len * vertmap[i][0], st[1] + len * vertmap[i][1], st[2] + len * vertmap[i][2]};
972  patch(newnode->internal.get_child(count), nori, len, zlists[i]);
973  }
974 
975  if (newnode->internal.has_child(i)) {
976  count++;
977  }
978  }
979 #ifdef IN_DEBUG_MODE
980  dc_printf("Return from PATCH\n");
981 #endif
982  return newnode;
983 }
984 
985 Node *Octree::patchSplit(Node *newnode,
986  int st[3],
987  int len,
988  PathList *rings,
989  int dir,
990  PathList *&nrings1,
991  PathList *&nrings2)
992 {
993 #ifdef IN_DEBUG_MODE
994  dc_printf("Call to PATCHSPLIT with direction %d and rings: \n", dir);
995  printPaths(rings);
996 #endif
997 
998  nrings1 = NULL;
999  nrings2 = NULL;
1000  PathList *tmp;
1001  while (rings != NULL) {
1002  // Process this ring
1003  newnode = patchSplitSingle(newnode, st, len, rings->head, dir, nrings1, nrings2);
1004 
1005  // Delete this ring from the group
1006  tmp = rings;
1007  rings = rings->next;
1008  delete tmp;
1009  }
1010 
1011 #ifdef IN_DEBUG_MODE
1012  dc_printf("Return from PATCHSPLIT with \n");
1013  dc_printf("Rings gourp 1:\n");
1014  printPaths(nrings1);
1015  dc_printf("Rings group 2:\n");
1016  printPaths(nrings2);
1017 #endif
1018 
1019  return newnode;
1020 }
1021 
1022 Node *Octree::patchSplitSingle(Node *newnode,
1023  int st[3],
1024  int len,
1025  PathElement *head,
1026  int dir,
1027  PathList *&nrings1,
1028  PathList *&nrings2)
1029 {
1030 #ifdef IN_DEBUG_MODE
1031  dc_printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir);
1032  printPath(head);
1033 #endif
1034 
1035  if (head == NULL) {
1036 #ifdef IN_DEBUG_MODE
1037  dc_printf("Return from PATCHSPLITSINGLE with head==NULL.\n");
1038 #endif
1039  return newnode;
1040  }
1041  else {
1042  // printPath(head);
1043  }
1044 
1045  // Walk along the ring to find pair of intersections
1046  PathElement *pre1 = NULL;
1047  PathElement *pre2 = NULL;
1048  int side = findPair(head, st[dir] + len / 2, dir, pre1, pre2);
1049 
1050 #if 0
1051  if (pre1 == pre2) {
1052  int edgelen = (dimen >> maxDepth);
1053  dc_printf("Location: %d %d %d Direction: %d Reso: %d\n",
1054  st[0] / edgelen,
1055  st[1] / edgelen,
1056  st[2] / edgelen,
1057  dir,
1058  len / edgelen);
1059  printPath(head);
1060  exit(0);
1061  }
1062 #endif
1063 
1064  if (side) {
1065  // Entirely on one side
1066  PathList *nring = new PathList();
1067  nring->head = head;
1068 
1069  if (side == -1) {
1070  nring->next = nrings1;
1071  nrings1 = nring;
1072  }
1073  else {
1074  nring->next = nrings2;
1075  nrings2 = nring;
1076  }
1077  }
1078  else {
1079  // Break into two parts
1080  PathElement *nxt1 = pre1->next;
1081  PathElement *nxt2 = pre2->next;
1082  pre1->next = nxt2;
1083  pre2->next = nxt1;
1084 
1085  newnode = connectFace(newnode, st, len, dir, pre1, pre2);
1086 
1087  if (isEqual(pre1, pre1->next)) {
1088  if (pre1 == pre1->next) {
1089  delete pre1;
1090  pre1 = NULL;
1091  }
1092  else {
1093  PathElement *temp = pre1->next;
1094  pre1->next = temp->next;
1095  delete temp;
1096  }
1097  }
1098  if (isEqual(pre2, pre2->next)) {
1099  if (pre2 == pre2->next) {
1100  delete pre2;
1101  pre2 = NULL;
1102  }
1103  else {
1104  PathElement *temp = pre2->next;
1105  pre2->next = temp->next;
1106  delete temp;
1107  }
1108  }
1109 
1110  compressRing(pre1);
1111  compressRing(pre2);
1112 
1113  // Recur
1114  newnode = patchSplitSingle(newnode, st, len, pre1, dir, nrings1, nrings2);
1115  newnode = patchSplitSingle(newnode, st, len, pre2, dir, nrings1, nrings2);
1116  }
1117 
1118 #ifdef IN_DEBUG_MODE
1119  dc_printf("Return from PATCHSPLITSINGLE with \n");
1120  dc_printf("Rings gourp 1:\n");
1121  printPaths(nrings1);
1122  dc_printf("Rings group 2:\n");
1123  printPaths(nrings2);
1124 #endif
1125 
1126  return newnode;
1127 }
1128 
1129 Node *Octree::connectFace(
1130  Node *newnode, int st[3], int len, int dir, PathElement *f1, PathElement *f2)
1131 {
1132 #ifdef IN_DEBUG_MODE
1133  dc_printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len);
1134  dc_printf("Path(low side): \n");
1135  printPath(f1);
1136  // checkPath(f1);
1137  dc_printf("Path(high side): \n");
1138  printPath(f2);
1139 // checkPath(f2);
1140 #endif
1141 
1142  // Setup 2D
1143  int pos = st[dir] + len / 2;
1144  int xdir = (dir + 1) % 3;
1145  int ydir = (dir + 2) % 3;
1146 
1147  // Use existing intersections on f1 and f2
1148  int x1, y1, x2, y2;
1149  float p1, q1, p2, q2;
1150 
1151  getFacePoint(f2->next, dir, x1, y1, p1, q1);
1152  getFacePoint(f2, dir, x2, y2, p2, q2);
1153 
1154  float dx = x2 + p2 - x1 - p1;
1155  float dy = y2 + q2 - y1 - q1;
1156 
1157  // Do adapted Bresenham line drawing
1158  float rx = p1, ry = q1;
1159  int incx = 1, incy = 1;
1160  int lx = x1, ly = y1;
1161  int hx = x2, hy = y2;
1162  int choice;
1163  if (x2 < x1) {
1164  incx = -1;
1165  rx = 1 - rx;
1166  lx = x2;
1167  hx = x1;
1168  }
1169  if (y2 < y1) {
1170  incy = -1;
1171  ry = 1 - ry;
1172  ly = y2;
1173  hy = y1;
1174  }
1175 
1176  float sx = dx * incx;
1177  float sy = dy * incy;
1178 
1179  int ori[3];
1180  ori[dir] = pos / mindimen;
1181  ori[xdir] = x1;
1182  ori[ydir] = y1;
1183  int walkdir;
1184  int inc;
1185  float alpha;
1186 
1187  PathElement *curEleN = f1;
1188  PathElement *curEleP = f2->next;
1189  Node *nodeN = NULL, *nodeP = NULL;
1190  LeafNode *curN = locateLeaf(&newnode->internal, len, f1->pos);
1191  LeafNode *curP = locateLeaf(&newnode->internal, len, f2->next->pos);
1192  if (curN == NULL || curP == NULL) {
1193  exit(0);
1194  }
1195  int stN[3], stP[3];
1196  int lenN, lenP;
1197 
1198  /* Unused code, leaving for posterity
1199 
1200  float stpt[3], edpt[3];
1201  stpt[dir] = edpt[dir] =(float) pos;
1202  stpt[xdir] =(x1 + p1) * mindimen;
1203  stpt[ydir] =(y1 + q1) * mindimen;
1204  edpt[xdir] =(x2 + p2) * mindimen;
1205  edpt[ydir] =(y2 + q2) * mindimen;
1206  */
1207  while (ori[xdir] != x2 || ori[ydir] != y2) {
1208  int next;
1209  if (sy * (1 - rx) > sx * (1 - ry)) {
1210  choice = 1;
1211  next = ori[ydir] + incy;
1212  if (next < ly || next > hy) {
1213  choice = 4;
1214  next = ori[xdir] + incx;
1215  }
1216  }
1217  else {
1218  choice = 2;
1219  next = ori[xdir] + incx;
1220  if (next < lx || next > hx) {
1221  choice = 3;
1222  next = ori[ydir] + incy;
1223  }
1224  }
1225 
1226  if (choice & 1) {
1227  ori[ydir] = next;
1228  if (choice == 1) {
1229  rx += (sy == 0 ? 0 : (1 - ry) * sx / sy);
1230  ry = 0;
1231  }
1232 
1233  walkdir = 2;
1234  inc = incy;
1235  alpha = x2 < x1 ? 1 - rx : rx;
1236  }
1237  else {
1238  ori[xdir] = next;
1239  if (choice == 2) {
1240  ry += (sx == 0 ? 0 : (1 - rx) * sy / sx);
1241  rx = 0;
1242  }
1243 
1244  walkdir = 1;
1245  inc = incx;
1246  alpha = y2 < y1 ? 1 - ry : ry;
1247  }
1248 
1249  // Get the exact location of the marcher
1250  int nori[3] = {ori[0] * mindimen, ori[1] * mindimen, ori[2] * mindimen};
1251  float spt[3] = {(float)nori[0], (float)nori[1], (float)nori[2]};
1252  spt[(dir + (3 - walkdir)) % 3] += alpha * mindimen;
1253  if (inc < 0) {
1254  spt[(dir + walkdir) % 3] += mindimen;
1255  }
1256 
1257 #if 0
1258  dc_printf("new x,y: %d %d\n", ori[xdir] / edgelen, ori[ydir] / edgelen);
1259  dc_printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir);
1260  dc_printf("%f %f %f\n", spt[0], spt[1], spt[2]);
1261 #endif
1262 
1263  // Locate the current cells on both sides
1264  newnode = locateCell(&newnode->internal, st, len, nori, dir, 1, nodeN, stN, lenN);
1265  newnode = locateCell(&newnode->internal, st, len, nori, dir, 0, nodeP, stP, lenP);
1266 
1267  updateParent(&newnode->internal, len, st);
1268 
1269  int flag = 0;
1270  // Add the cells to the rings and fill in the patch
1271  PathElement *newEleN;
1272  if (curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2]) {
1273  if (curEleN->next->pos[0] != stN[0] || curEleN->next->pos[1] != stN[1] ||
1274  curEleN->next->pos[2] != stN[2]) {
1275  newEleN = new PathElement;
1276  newEleN->next = curEleN->next;
1277  newEleN->pos[0] = stN[0];
1278  newEleN->pos[1] = stN[1];
1279  newEleN->pos[2] = stN[2];
1280 
1281  curEleN->next = newEleN;
1282  }
1283  else {
1284  newEleN = curEleN->next;
1285  }
1286  curN = patchAdjacent(&newnode->internal,
1287  len,
1288  curEleN->pos,
1289  curN,
1290  newEleN->pos,
1291  (LeafNode *)nodeN,
1292  walkdir,
1293  inc,
1294  dir,
1295  1,
1296  alpha);
1297 
1298  curEleN = newEleN;
1299  flag++;
1300  }
1301 
1302  PathElement *newEleP;
1303  if (curEleP->pos[0] != stP[0] || curEleP->pos[1] != stP[1] || curEleP->pos[2] != stP[2]) {
1304  if (f2->pos[0] != stP[0] || f2->pos[1] != stP[1] || f2->pos[2] != stP[2]) {
1305  newEleP = new PathElement;
1306  newEleP->next = curEleP;
1307  newEleP->pos[0] = stP[0];
1308  newEleP->pos[1] = stP[1];
1309  newEleP->pos[2] = stP[2];
1310 
1311  f2->next = newEleP;
1312  }
1313  else {
1314  newEleP = f2;
1315  }
1316  curP = patchAdjacent(&newnode->internal,
1317  len,
1318  curEleP->pos,
1319  curP,
1320  newEleP->pos,
1321  (LeafNode *)nodeP,
1322  walkdir,
1323  inc,
1324  dir,
1325  0,
1326  alpha);
1327 
1328  curEleP = newEleP;
1329  flag++;
1330  }
1331 
1332  /*
1333  if(flag == 0) {
1334  dc_printf("error: non-synchronized patching! at \n");
1335  }
1336  */
1337  }
1338 
1339 #ifdef IN_DEBUG_MODE
1340  dc_printf("Return from CONNECTFACE with \n");
1341  dc_printf("Path(low side):\n");
1342  printPath(f1);
1343  checkPath(f1);
1344  dc_printf("Path(high side):\n");
1345  printPath(f2);
1346  checkPath(f2);
1347 #endif
1348 
1349  return newnode;
1350 }
1351 
1352 LeafNode *Octree::patchAdjacent(InternalNode *node,
1353  int len,
1354  int st1[3],
1355  LeafNode *leaf1,
1356  int st2[3],
1357  LeafNode *leaf2,
1358  int walkdir,
1359  int inc,
1360  int dir,
1361  int side,
1362  float alpha)
1363 {
1364 #ifdef IN_DEBUG_MODE
1365  dc_printf("Before patching.\n");
1366  printInfo(st1);
1367  printInfo(st2);
1368  dc_printf(
1369  "-----------------%d %d %d; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2]);
1370 #endif
1371 
1372  // Get edge index on each leaf
1373  int edgedir = (dir + (3 - walkdir)) % 3;
1374  int incdir = (dir + walkdir) % 3;
1375  int ind1 = (edgedir == 1 ? (dir + 3 - edgedir) % 3 - 1 : 2 - (dir + 3 - edgedir) % 3);
1376  int ind2 = (edgedir == 1 ? (incdir + 3 - edgedir) % 3 - 1 : 2 - (incdir + 3 - edgedir) % 3);
1377 
1378  int eind1 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 1 : 0) << ind2));
1379  int eind2 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 0 : 1) << ind2));
1380 
1381 #ifdef IN_DEBUG_MODE
1382  dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha);
1383  /*
1384  if(alpha < 0 || alpha > 1) {
1385  dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha);
1386  printInfo(st1);
1387  printInfo(st2);
1388  }
1389  */
1390 #endif
1391 
1392  // Flip edge parity
1393  LeafNode *nleaf1 = flipEdge(leaf1, eind1, alpha);
1394  LeafNode *nleaf2 = flipEdge(leaf2, eind2, alpha);
1395 
1396  // Update parent link
1397  updateParent(node, len, st1, nleaf1);
1398  updateParent(node, len, st2, nleaf2);
1399  // updateParent(nleaf1, mindimen, st1);
1400  // updateParent(nleaf2, mindimen, st2);
1401 
1402  /*
1403  float m[3];
1404  dc_printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2]);
1405  getMinimizer(leaf1, m);
1406  dc_printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2]);
1407  getMinimizer(leaf2, m);
1408  dc_printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2]);
1409  */
1410 
1411 #ifdef IN_DEBUG_MODE
1412  dc_printf("After patching.\n");
1413  printInfo(st1);
1414  printInfo(st2);
1415 #endif
1416  return nleaf2;
1417 }
1418 
1419 Node *Octree::locateCell(InternalNode *node,
1420  int st[3],
1421  int len,
1422  int ori[3],
1423  int dir,
1424  int side,
1425  Node *&rleaf,
1426  int rst[3],
1427  int &rlen)
1428 {
1429 #ifdef IN_DEBUG_MODE
1430  // dc_printf("Call to LOCATECELL with node ");
1431  // printNode(node);
1432 #endif
1433 
1434  int i;
1435  len >>= 1;
1436  int ind = 0;
1437  for (i = 0; i < 3; i++) {
1438  ind <<= 1;
1439  if (i == dir && side == 1) {
1440  ind |= (ori[i] <= (st[i] + len) ? 0 : 1);
1441  }
1442  else {
1443  ind |= (ori[i] < (st[i] + len) ? 0 : 1);
1444  }
1445  }
1446 
1447 #ifdef IN_DEBUG_MODE
1448 # if 0
1449  dc_printf(
1450  "In LOCATECELL index of ori(%d %d %d) with dir %d side %d in st(%d %d %d, %d) is: %d\n",
1451  ori[0],
1452  ori[1],
1453  ori[2],
1454  dir,
1455  side,
1456  st[0],
1457  st[1],
1458  st[2],
1459  len,
1460  ind);
1461 # endif
1462 #endif
1463 
1464  rst[0] = st[0] + vertmap[ind][0] * len;
1465  rst[1] = st[1] + vertmap[ind][1] * len;
1466  rst[2] = st[2] + vertmap[ind][2] * len;
1467 
1468  if (node->has_child(ind)) {
1469  int count = node->get_child_count(ind);
1470  Node *chd = node->get_child(count);
1471  if (node->is_child_leaf(ind)) {
1472  rleaf = chd;
1473  rlen = len;
1474  }
1475  else {
1476  // Recur
1477  node->set_child(count,
1478  locateCell(&chd->internal, rst, len, ori, dir, side, rleaf, rst, rlen));
1479  }
1480  }
1481  else {
1482  // Create a new child here
1483  if (len == mindimen) {
1484  LeafNode *chd = createLeaf(0);
1485  node = addChild(node, ind, (Node *)chd, 1);
1486  rleaf = (Node *)chd;
1487  rlen = len;
1488  }
1489  else {
1490  // Subdivide the empty cube
1491  InternalNode *chd = createInternal(0);
1492  node = addChild(node, ind, locateCell(chd, rst, len, ori, dir, side, rleaf, rst, rlen), 0);
1493  }
1494  }
1495 
1496 #ifdef IN_DEBUG_MODE
1497  // dc_printf("Return from LOCATECELL with node ");
1498  // printNode(newnode);
1499 #endif
1500  return (Node *)node;
1501 }
1502 
1503 void Octree::checkElement(PathElement * /*ele*/)
1504 {
1505 #if 0
1506  if (ele != NULL && locateLeafCheck(ele->pos) != ele->node) {
1507  dc_printf("Screwed! at pos: %d %d %d\n",
1508  ele->pos[0] >> minshift,
1509  ele->pos[1] >> minshift,
1510  ele->pos[2] >> minshift);
1511  exit(0);
1512  }
1513 #endif
1514 }
1515 
1516 void Octree::checkPath(PathElement *path)
1517 {
1518  PathElement *n = path;
1519  int same = 0;
1520  while (n && (same == 0 || n != path)) {
1521  same++;
1522  checkElement(n);
1523  n = n->next;
1524  }
1525 }
1526 
1527 void Octree::testFacePoint(PathElement *e1, PathElement *e2)
1528 {
1529  int i;
1530  PathElement *e = NULL;
1531  for (i = 0; i < 3; i++) {
1532  if (e1->pos[i] != e2->pos[i]) {
1533  if (e1->pos[i] < e2->pos[i]) {
1534  e = e2;
1535  }
1536  else {
1537  e = e1;
1538  }
1539  break;
1540  }
1541  }
1542 
1543  int x, y;
1544  float p, q;
1545  dc_printf("Test.");
1546  getFacePoint(e, i, x, y, p, q);
1547 }
1548 
1549 void Octree::getFacePoint(PathElement *leaf, int dir, int &x, int &y, float &p, float &q)
1550 {
1551  // Find average intersections
1552  float avg[3] = {0, 0, 0};
1553  float off[3];
1554  int num = 0, num2 = 0;
1555 
1556  LeafNode *leafnode = locateLeaf(leaf->pos);
1557  for (int i = 0; i < 4; i++) {
1558  int edgeind = faceMap[dir * 2][i];
1559  int nst[3];
1560  for (int j = 0; j < 3; j++) {
1561  nst[j] = leaf->pos[j] + mindimen * vertmap[edgemap[edgeind][0]][j];
1562  }
1563 
1564  if (getEdgeIntersectionByIndex(nst, edgeind / 4, off, 1)) {
1565  avg[0] += off[0];
1566  avg[1] += off[1];
1567  avg[2] += off[2];
1568  num++;
1569  }
1570  if (getEdgeParity(leafnode, edgeind)) {
1571  num2++;
1572  }
1573  }
1574  if (num == 0) {
1575  dc_printf("Wrong! dir: %d pos: %d %d %d num: %d\n",
1576  dir,
1577  leaf->pos[0] >> minshift,
1578  leaf->pos[1] >> minshift,
1579  leaf->pos[2] >> minshift,
1580  num2);
1581  avg[0] = (float)leaf->pos[0];
1582  avg[1] = (float)leaf->pos[1];
1583  avg[2] = (float)leaf->pos[2];
1584  }
1585  else {
1586 
1587  avg[0] /= num;
1588  avg[1] /= num;
1589  avg[2] /= num;
1590 
1591  // avg[0] =(float) leaf->pos[0];
1592  // avg[1] =(float) leaf->pos[1];
1593  // avg[2] =(float) leaf->pos[2];
1594  }
1595 
1596  int xdir = (dir + 1) % 3;
1597  int ydir = (dir + 2) % 3;
1598 
1599  float xf = avg[xdir];
1600  float yf = avg[ydir];
1601 
1602 #ifdef IN_DEBUG_MODE
1603  // Is it outside?
1604  // PathElement* leaf = leaf1->len < leaf2->len ? leaf1 : leaf2;
1605 # if 0
1606  float *m = (leaf == leaf1 ? m1 : m2);
1607  if (xf < leaf->pos[xdir] || yf < leaf->pos[ydir] || xf > leaf->pos[xdir] + leaf->len ||
1608  yf > leaf->pos[ydir] + leaf->len) {
1609  dc_printf("Outside cube(%d %d %d), %d : %d %d %f %f\n",
1610  leaf->pos[0],
1611  leaf->pos[1],
1612  leaf->pos[2],
1613  leaf->len,
1614  pos,
1615  dir,
1616  xf,
1617  yf);
1618 
1619  // For now, snap to cell
1620  xf = m[xdir];
1621  yf = m[ydir];
1622  }
1623 # endif
1624 
1625 # if 0
1626  if (alpha < 0 || alpha > 1 || xf < leaf->pos[xdir] || xf > leaf->pos[xdir] + leaf->len ||
1627  yf < leaf->pos[ydir] || yf > leaf->pos[ydir] + leaf->len) {
1628  dc_printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node);
1629  dc_printf("GETFACEPOINT result:(%d %d %d) %d min:(%f %f %f);(%d %d %d) %d min:(%f %f %f).\n",
1630  leaf1->pos[0],
1631  leaf1->pos[1],
1632  leaf1->pos[2],
1633  leaf1->len,
1634  m1[0],
1635  m1[1],
1636  m1[2],
1637  leaf2->pos[0],
1638  leaf2->pos[1],
1639  leaf2->pos[2],
1640  leaf2->len,
1641  m2[0],
1642  m2[1],
1643  m2[2]);
1644  dc_printf("Face point at dir %d pos %d: %f %f\n", dir, pos, xf, yf);
1645  }
1646 # endif
1647 #endif
1648 
1649  // Get the integer and float part
1650  x = ((leaf->pos[xdir]) >> minshift);
1651  y = ((leaf->pos[ydir]) >> minshift);
1652 
1653  p = (xf - leaf->pos[xdir]) / mindimen;
1654  q = (yf - leaf->pos[ydir]) / mindimen;
1655 
1656 #ifdef IN_DEBUG_MODE
1657  dc_printf("Face point at dir %d : %f %f\n", dir, xf, yf);
1658 #endif
1659 }
1660 
1661 int Octree::findPair(PathElement *head, int pos, int dir, PathElement *&pre1, PathElement *&pre2)
1662 {
1663  int side = getSide(head, pos, dir);
1664  PathElement *cur = head;
1665  PathElement *anchor;
1666  PathElement *ppre1, *ppre2;
1667 
1668  // Start from this face, find a pair
1669  anchor = cur;
1670  ppre1 = cur;
1671  cur = cur->next;
1672  while (cur != anchor && (getSide(cur, pos, dir) == side)) {
1673  ppre1 = cur;
1674  cur = cur->next;
1675  }
1676  if (cur == anchor) {
1677  // No pair found
1678  return side;
1679  }
1680 
1681  side = getSide(cur, pos, dir);
1682  ppre2 = cur;
1683  cur = cur->next;
1684  while (getSide(cur, pos, dir) == side) {
1685  ppre2 = cur;
1686  cur = cur->next;
1687  }
1688 
1689  // Switch pre1 and pre2 if we start from the higher side
1690  if (side == -1) {
1691  cur = ppre1;
1692  ppre1 = ppre2;
1693  ppre2 = cur;
1694  }
1695 
1696  pre1 = ppre1;
1697  pre2 = ppre2;
1698 
1699  return 0;
1700 }
1701 
1702 int Octree::getSide(PathElement *e, int pos, int dir)
1703 {
1704  return (e->pos[dir] < pos ? -1 : 1);
1705 }
1706 
1707 int Octree::isEqual(PathElement *e1, PathElement *e2)
1708 {
1709  return (e1->pos[0] == e2->pos[0] && e1->pos[1] == e2->pos[1] && e1->pos[2] == e2->pos[2]);
1710 }
1711 
1712 void Octree::compressRing(PathElement *&ring)
1713 {
1714  if (ring == NULL) {
1715  return;
1716  }
1717 #ifdef IN_DEBUG_MODE
1718  dc_printf("Call to COMPRESSRING with path: \n");
1719  printPath(ring);
1720 #endif
1721 
1722  PathElement *cur = ring->next->next;
1723  PathElement *pre = ring->next;
1724  PathElement *prepre = ring;
1725  PathElement *anchor = prepre;
1726 
1727  do {
1728  while (isEqual(cur, prepre)) {
1729  // Delete
1730  if (cur == prepre) {
1731  // The ring has shrinked to a point
1732  delete pre;
1733  delete cur;
1734  anchor = NULL;
1735  break;
1736  }
1737  else {
1738  prepre->next = cur->next;
1739  delete pre;
1740  delete cur;
1741  pre = prepre->next;
1742  cur = pre->next;
1743  anchor = prepre;
1744  }
1745  }
1746 
1747  if (anchor == NULL) {
1748  break;
1749  }
1750 
1751  prepre = pre;
1752  pre = cur;
1753  cur = cur->next;
1754  } while (prepre != anchor);
1755 
1756  ring = anchor;
1757 
1758 #ifdef IN_DEBUG_MODE
1759  dc_printf("Return from COMPRESSRING with path: \n");
1760  printPath(ring);
1761 #endif
1762 }
1763 
1764 void Octree::buildSigns()
1765 {
1766  // First build a lookup table
1767  // dc_printf("Building up look up table...\n");
1768  int size = 1 << 12;
1769  unsigned char table[1 << 12];
1770  for (int i = 0; i < size; i++) {
1771  table[i] = 0;
1772  }
1773  for (int i = 0; i < 256; i++) {
1774  int ind = 0;
1775  for (int j = 11; j >= 0; j--) {
1776  ind <<= 1;
1777  if (((i >> edgemap[j][0]) & 1) ^ ((i >> edgemap[j][1]) & 1)) {
1778  ind |= 1;
1779  }
1780  }
1781 
1782  table[ind] = i;
1783  }
1784 
1785  // Next, traverse the grid
1786  int sg = 1;
1787  int cube[8];
1788  buildSigns(table, root, 0, sg, cube);
1789 }
1790 
1791 void Octree::buildSigns(unsigned char table[], Node *node, int isLeaf, int sg, int rvalue[8])
1792 {
1793  if (node == NULL) {
1794  for (int i = 0; i < 8; i++) {
1795  rvalue[i] = sg;
1796  }
1797  return;
1798  }
1799 
1800  if (isLeaf == 0) {
1801  // Internal node
1802  Node *chd[8];
1803  int leaf[8];
1804  node->internal.fill_children(chd, leaf);
1805 
1806  // Get the signs at the corners of the first cube
1807  rvalue[0] = sg;
1808  int oris[8];
1809  buildSigns(table, chd[0], leaf[0], sg, oris);
1810 
1811  // Get the rest
1812  int cube[8];
1813  for (int i = 1; i < 8; i++) {
1814  buildSigns(table, chd[i], leaf[i], oris[i], cube);
1815  rvalue[i] = cube[i];
1816  }
1817  }
1818  else {
1819  // Leaf node
1820  generateSigns(&node->leaf, table, sg);
1821 
1822  for (int i = 0; i < 8; i++) {
1823  rvalue[i] = getSign(&node->leaf, i);
1824  }
1825  }
1826 }
1827 
1828 void Octree::floodFill()
1829 {
1830  // int threshold =(int)((dimen/mindimen) *(dimen/mindimen) * 0.5f);
1831  int st[3] = {0, 0, 0};
1832 
1833  // First, check for largest component
1834  // size stored in -threshold
1835  clearProcessBits(root, maxDepth);
1836  int threshold = floodFill(root, st, dimen, maxDepth, 0);
1837 
1838  // Next remove
1839  dc_printf("Largest component: %d\n", threshold);
1840  threshold *= thresh;
1841  dc_printf("Removing all components smaller than %d\n", threshold);
1842 
1843  int st2[3] = {0, 0, 0};
1844  clearProcessBits(root, maxDepth);
1845  floodFill(root, st2, dimen, maxDepth, threshold);
1846 }
1847 
1848 void Octree::clearProcessBits(Node *node, int height)
1849 {
1850  int i;
1851 
1852  if (height == 0) {
1853  // Leaf cell,
1854  for (i = 0; i < 12; i++) {
1855  setOutProcess(&node->leaf, i);
1856  }
1857  }
1858  else {
1859  // Internal cell, recur
1860  int count = 0;
1861  for (i = 0; i < 8; i++) {
1862  if (node->internal.has_child(i)) {
1863  clearProcessBits(node->internal.get_child(count), height - 1);
1864  count++;
1865  }
1866  }
1867  }
1868 }
1869 
1870 int Octree::floodFill(LeafNode *leaf, int st[3], int len, int /*height*/, int threshold)
1871 {
1872  int i, j;
1873  int maxtotal = 0;
1874 
1875  // Leaf cell,
1876  int par, inp;
1877 
1878  // Test if the leaf has intersection edges
1879  for (i = 0; i < 12; i++) {
1880  par = getEdgeParity(leaf, i);
1881  inp = isInProcess(leaf, i);
1882 
1883  if (par == 1 && inp == 0) {
1884  // Intersection edge, hasn't been processed
1885  // Let's start filling
1886  GridQueue *queue = new GridQueue();
1887  int total = 1;
1888 
1889  // Set to in process
1890  int mst[3];
1891  mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len;
1892  mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len;
1893  mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len;
1894  int mdir = i / 4;
1895  setInProcessAll(mst, mdir);
1896 
1897  // Put this edge into queue
1898  queue->pushQueue(mst, mdir);
1899 
1900  // Queue processing
1901  int nst[3], dir;
1902  while (queue->popQueue(nst, dir) == 1) {
1903 #if 0
1904  dc_printf("nst: %d %d %d, dir: %d\n",
1905  nst[0] / mindimen,
1906  nst[1] / mindimen,
1907  nst[2] / mindimen,
1908  dir);
1909 #endif
1910  // locations
1911  int stMask[3][3] = {{0, 0 - len, 0 - len}, {0 - len, 0, 0 - len}, {0 - len, 0 - len, 0}};
1912  int cst[2][3];
1913  for (j = 0; j < 3; j++) {
1914  cst[0][j] = nst[j];
1915  cst[1][j] = nst[j] + stMask[dir][j];
1916  }
1917 
1918  // cells
1919  LeafNode *cs[2];
1920  for (j = 0; j < 2; j++) {
1921  cs[j] = locateLeaf(cst[j]);
1922  }
1923 
1924  // Middle sign
1925  int s = getSign(cs[0], 0);
1926 
1927  // Masks
1928  int fcCells[4] = {1, 0, 1, 0};
1929  int fcEdges[3][4][3] = {{{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}},
1930  {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}},
1931  {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}}};
1932 
1933  // Search for neighboring connected intersection edges
1934  for (int find = 0; find < 4; find++) {
1935  int cind = fcCells[find];
1936  int eind, edge;
1937  if (s == 0) {
1938  // Original order
1939  for (eind = 0; eind < 3; eind++) {
1940  edge = fcEdges[dir][find][eind];
1941  if (getEdgeParity(cs[cind], edge) == 1) {
1942  break;
1943  }
1944  }
1945  }
1946  else {
1947  // Inverse order
1948  for (eind = 2; eind >= 0; eind--) {
1949  edge = fcEdges[dir][find][eind];
1950  if (getEdgeParity(cs[cind], edge) == 1) {
1951  break;
1952  }
1953  }
1954  }
1955 
1956  if (eind == 3 || eind == -1) {
1957  dc_printf("Wrong! this is not a consistent sign. %d\n", eind);
1958  }
1959  else {
1960  int est[3];
1961  est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len;
1962  est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len;
1963  est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len;
1964  int edir = edge / 4;
1965 
1966  if (isInProcess(cs[cind], edge) == 0) {
1967  setInProcessAll(est, edir);
1968  queue->pushQueue(est, edir);
1969 #if 0
1970  dc_printf("Pushed: est: %d %d %d, edir: %d\n",
1971  est[0] / len,
1972  est[1] / len,
1973  est[2] / len,
1974  edir);
1975 #endif
1976  total++;
1977  }
1978  }
1979  }
1980  }
1981 
1982  dc_printf("Size of component: %d ", total);
1983 
1984  if (threshold == 0) {
1985  // Measuring stage
1986  if (total > maxtotal) {
1987  maxtotal = total;
1988  }
1989  dc_printf(".\n");
1990  delete queue;
1991  continue;
1992  }
1993 
1994  if (total >= threshold) {
1995  dc_printf("Maintained.\n");
1996  delete queue;
1997  continue;
1998  }
1999  dc_printf("Less than %d, removing...\n", threshold);
2000 
2001  // We have to remove this noise
2002 
2003  // Flip parity
2004  // setOutProcessAll(mst, mdir);
2005  flipParityAll(mst, mdir);
2006 
2007  // Put this edge into queue
2008  queue->pushQueue(mst, mdir);
2009 
2010  // Queue processing
2011  while (queue->popQueue(nst, dir) == 1) {
2012 #if 0
2013  dc_printf("nst: %d %d %d, dir: %d\n",
2014  nst[0] / mindimen,
2015  nst[1] / mindimen,
2016  nst[2] / mindimen,
2017  dir);
2018 #endif
2019  // locations
2020  int stMask[3][3] = {{0, 0 - len, 0 - len}, {0 - len, 0, 0 - len}, {0 - len, 0 - len, 0}};
2021  int cst[2][3];
2022  for (j = 0; j < 3; j++) {
2023  cst[0][j] = nst[j];
2024  cst[1][j] = nst[j] + stMask[dir][j];
2025  }
2026 
2027  // cells
2028  LeafNode *cs[2];
2029  for (j = 0; j < 2; j++)
2030  cs[j] = locateLeaf(cst[j]);
2031 
2032  // Middle sign
2033  int s = getSign(cs[0], 0);
2034 
2035  // Masks
2036  int fcCells[4] = {1, 0, 1, 0};
2037  int fcEdges[3][4][3] = {{{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}},
2038  {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}},
2039  {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}}};
2040 
2041  // Search for neighboring connected intersection edges
2042  for (int find = 0; find < 4; find++) {
2043  int cind = fcCells[find];
2044  int eind, edge;
2045  if (s == 0) {
2046  // Original order
2047  for (eind = 0; eind < 3; eind++) {
2048  edge = fcEdges[dir][find][eind];
2049  if (isInProcess(cs[cind], edge) == 1) {
2050  break;
2051  }
2052  }
2053  }
2054  else {
2055  // Inverse order
2056  for (eind = 2; eind >= 0; eind--) {
2057  edge = fcEdges[dir][find][eind];
2058  if (isInProcess(cs[cind], edge) == 1) {
2059  break;
2060  }
2061  }
2062  }
2063 
2064  if (eind == 3 || eind == -1) {
2065  dc_printf("Wrong! this is not a consistent sign. %d\n", eind);
2066  }
2067  else {
2068  int est[3];
2069  est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len;
2070  est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len;
2071  est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len;
2072  int edir = edge / 4;
2073 
2074  if (getEdgeParity(cs[cind], edge) == 1) {
2075  flipParityAll(est, edir);
2076  queue->pushQueue(est, edir);
2077 #if 0
2078  dc_printf("Pushed: est: %d %d %d, edir: %d\n",
2079  est[0] / len,
2080  est[1] / len,
2081  est[2] / len,
2082  edir);
2083 #endif
2084  total++;
2085  }
2086  }
2087  }
2088  }
2089 
2090  delete queue;
2091  }
2092  }
2093 
2094  return maxtotal;
2095 }
2096 
2097 int Octree::floodFill(Node *node, int st[3], int len, int height, int threshold)
2098 {
2099  int i;
2100  int maxtotal = 0;
2101 
2102  if (height == 0) {
2103  maxtotal = floodFill(&node->leaf, st, len, height, threshold);
2104  }
2105  else {
2106  // Internal cell, recur
2107  int count = 0;
2108  len >>= 1;
2109  for (i = 0; i < 8; i++) {
2110  if (node->internal.has_child(i)) {
2111  int nst[3];
2112  nst[0] = st[0] + vertmap[i][0] * len;
2113  nst[1] = st[1] + vertmap[i][1] * len;
2114  nst[2] = st[2] + vertmap[i][2] * len;
2115 
2116  int d = floodFill(node->internal.get_child(count), nst, len, height - 1, threshold);
2117  if (d > maxtotal) {
2118  maxtotal = d;
2119  }
2120  count++;
2121  }
2122  }
2123  }
2124 
2125  return maxtotal;
2126 }
2127 
2128 void Octree::writeOut()
2129 {
2130  int numQuads = 0;
2131  int numVertices = 0;
2132  int numEdges = 0;
2133 
2134  countIntersection(root, maxDepth, numQuads, numVertices, numEdges);
2135 
2136  dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads);
2137  output_mesh = alloc_output(numVertices, numQuads);
2138  int offset = 0;
2139  int st[3] = {0, 0, 0};
2140 
2141  // First, output vertices
2142  offset = 0;
2143  actualVerts = 0;
2144  actualQuads = 0;
2145 
2146  generateMinimizer(root, st, dimen, maxDepth, offset);
2147  cellProcContour(root, 0, maxDepth);
2148  dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads);
2149 }
2150 
2151 void Octree::countIntersection(Node *node, int height, int &nedge, int &ncell, int &nface)
2152 {
2153  if (height > 0) {
2154  int total = node->internal.get_num_children();
2155  for (int i = 0; i < total; i++) {
2156  countIntersection(node->internal.get_child(i), height - 1, nedge, ncell, nface);
2157  }
2158  }
2159  else {
2160  nedge += getNumEdges2(&node->leaf);
2161 
2162  int smask = getSignMask(&node->leaf);
2163 
2164  if (use_manifold) {
2165  int comps = manifold_table[smask].comps;
2166  ncell += comps;
2167  }
2168  else {
2169  if (smask > 0 && smask < 255) {
2170  ncell++;
2171  }
2172  }
2173 
2174  for (int i = 0; i < 3; i++) {
2175  if (getFaceEdgeNum(&node->leaf, i * 2)) {
2176  nface++;
2177  }
2178  }
2179  }
2180 }
2181 
2182 /* from http://eigen.tuxfamily.org/bz/show_bug.cgi?id=257 */
2183 static void pseudoInverse(const Eigen::Matrix3f &a, Eigen::Matrix3f &result, float tolerance)
2184 {
2185  Eigen::JacobiSVD<Eigen::Matrix3f> svd = a.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
2186 
2187  result = svd.matrixV() *
2188  Eigen::Vector3f((svd.singularValues().array().abs() > tolerance)
2189  .select(svd.singularValues().array().inverse(), 0))
2190  .asDiagonal() *
2191  svd.matrixU().adjoint();
2192 }
2193 
2194 static void solve_least_squares(const float halfA[],
2195  const float b[],
2196  const float midpoint[],
2197  float rvalue[])
2198 {
2199  /* calculate pseudo-inverse */
2200  Eigen::Matrix3f A, pinv;
2201  A << halfA[0], halfA[1], halfA[2], halfA[1], halfA[3], halfA[4], halfA[2], halfA[4], halfA[5];
2202  pseudoInverse(A, pinv, 0.1f);
2203 
2204  Eigen::Vector3f b2(b), mp(midpoint), result;
2205  b2 = b2 + A * -mp;
2206  result = pinv * b2 + mp;
2207 
2208  for (int i = 0; i < 3; i++)
2209  rvalue[i] = result(i);
2210 }
2211 
2212 static void mass_point(float mp[3], const float pts[12][3], const int parity[12])
2213 {
2214  int ec = 0;
2215 
2216  for (int i = 0; i < 12; i++) {
2217  if (parity[i]) {
2218  const float *p = pts[i];
2219 
2220  mp[0] += p[0];
2221  mp[1] += p[1];
2222  mp[2] += p[2];
2223 
2224  ec++;
2225  }
2226  }
2227 
2228  if (ec == 0) {
2229  return;
2230  }
2231  mp[0] /= ec;
2232  mp[1] /= ec;
2233  mp[2] /= ec;
2234 }
2235 
2236 static void minimize(float rvalue[3],
2237  float mp[3],
2238  const float pts[12][3],
2239  const float norms[12][3],
2240  const int parity[12])
2241 {
2242  float ata[6] = {0, 0, 0, 0, 0, 0};
2243  float atb[3] = {0, 0, 0};
2244  int ec = 0;
2245 
2246  for (int i = 0; i < 12; i++) {
2247  // if(getEdgeParity(leaf, i))
2248  if (parity[i]) {
2249  const float *norm = norms[i];
2250  const float *p = pts[i];
2251 
2252  // QEF
2253  ata[0] += (float)(norm[0] * norm[0]);
2254  ata[1] += (float)(norm[0] * norm[1]);
2255  ata[2] += (float)(norm[0] * norm[2]);
2256  ata[3] += (float)(norm[1] * norm[1]);
2257  ata[4] += (float)(norm[1] * norm[2]);
2258  ata[5] += (float)(norm[2] * norm[2]);
2259 
2260  const float pn = p[0] * norm[0] + p[1] * norm[1] + p[2] * norm[2];
2261 
2262  atb[0] += (float)(norm[0] * pn);
2263  atb[1] += (float)(norm[1] * pn);
2264  atb[2] += (float)(norm[2] * pn);
2265 
2266  // Minimizer
2267  mp[0] += p[0];
2268  mp[1] += p[1];
2269  mp[2] += p[2];
2270 
2271  ec++;
2272  }
2273  }
2274 
2275  if (ec == 0) {
2276  return;
2277  }
2278  mp[0] /= ec;
2279  mp[1] /= ec;
2280  mp[2] /= ec;
2281 
2282  // Solve least squares
2283  solve_least_squares(ata, atb, mp, rvalue);
2284 }
2285 
2286 void Octree::computeMinimizer(const LeafNode *leaf, int st[3], int len, float rvalue[3]) const
2287 {
2288  // First, gather all edge intersections
2289  float pts[12][3], norms[12][3];
2290  int parity[12];
2291  fillEdgeIntersections(leaf, st, len, pts, norms, parity);
2292 
2293  switch (mode) {
2294  case DUALCON_CENTROID:
2295  rvalue[0] = (float)st[0] + len / 2;
2296  rvalue[1] = (float)st[1] + len / 2;
2297  rvalue[2] = (float)st[2] + len / 2;
2298  break;
2299 
2300  case DUALCON_MASS_POINT:
2301  rvalue[0] = rvalue[1] = rvalue[2] = 0;
2302  mass_point(rvalue, pts, parity);
2303  break;
2304 
2305  default: {
2306  // Sharp features */
2307 
2308  // construct QEF and minimizer
2309  float mp[3] = {0, 0, 0};
2310  minimize(rvalue, mp, pts, norms, parity);
2311 
2312  /* Restraining the location of the minimizer */
2313  float nh1 = hermite_num * len;
2314  float nh2 = (1 + hermite_num) * len;
2315 
2316  if (rvalue[0] < st[0] - nh1 || rvalue[1] < st[1] - nh1 || rvalue[2] < st[2] - nh1 ||
2317 
2318  rvalue[0] > st[0] + nh2 || rvalue[1] > st[1] + nh2 || rvalue[2] > st[2] + nh2) {
2319  // Use mass point instead
2320  rvalue[0] = mp[0];
2321  rvalue[1] = mp[1];
2322  rvalue[2] = mp[2];
2323  }
2324  break;
2325  }
2326  }
2327 }
2328 
2329 void Octree::generateMinimizer(Node *node, int st[3], int len, int height, int &offset)
2330 {
2331  int i, j;
2332 
2333  if (height == 0) {
2334  // Leaf cell, generate
2335 
2336  // First, find minimizer
2337  float rvalue[3];
2338  rvalue[0] = (float)st[0] + len / 2;
2339  rvalue[1] = (float)st[1] + len / 2;
2340  rvalue[2] = (float)st[2] + len / 2;
2341  computeMinimizer(&node->leaf, st, len, rvalue);
2342 
2343  // Update
2344  // float fnst[3];
2345  for (j = 0; j < 3; j++) {
2346  rvalue[j] = rvalue[j] * range / dimen + origin[j];
2347  // fnst[j] = st[j] * range / dimen + origin[j];
2348  }
2349 
2350  int mult = 0, smask = getSignMask(&node->leaf);
2351 
2352  if (use_manifold) {
2353  mult = manifold_table[smask].comps;
2354  }
2355  else {
2356  if (smask > 0 && smask < 255) {
2357  mult = 1;
2358  }
2359  }
2360 
2361  for (j = 0; j < mult; j++) {
2362  add_vert(output_mesh, rvalue);
2363  }
2364 
2365  // Store the index
2366  setMinimizerIndex(&node->leaf, offset);
2367 
2368  offset += mult;
2369  }
2370  else {
2371  // Internal cell, recur
2372  int count = 0;
2373  len >>= 1;
2374  for (i = 0; i < 8; i++) {
2375  if (node->internal.has_child(i)) {
2376  int nst[3];
2377  nst[0] = st[0] + vertmap[i][0] * len;
2378  nst[1] = st[1] + vertmap[i][1] * len;
2379  nst[2] = st[2] + vertmap[i][2] * len;
2380 
2381  generateMinimizer(node->internal.get_child(count), nst, len, height - 1, offset);
2382  count++;
2383  }
2384  }
2385  }
2386 }
2387 
2388 void Octree::processEdgeWrite(Node *node[4], int /*depth*/[4], int /*maxdep*/, int dir)
2389 {
2390  // int color = 0;
2391 
2392  int i = 3;
2393  {
2394  if (getEdgeParity((LeafNode *)(node[i]), processEdgeMask[dir][i])) {
2395  int flip = 0;
2396  int edgeind = processEdgeMask[dir][i];
2397  if (getSign((LeafNode *)node[i], edgemap[edgeind][1]) > 0) {
2398  flip = 1;
2399  }
2400 
2401  int num = 0;
2402  {
2403  int ind[8];
2404  if (use_manifold) {
2405  int vind[2];
2406  int seq[4] = {0, 1, 3, 2};
2407  for (int k = 0; k < 4; k++) {
2408  getMinimizerIndices((LeafNode *)(node[seq[k]]), processEdgeMask[dir][seq[k]], vind);
2409  ind[num] = vind[0];
2410  num++;
2411 
2412  if (vind[1] != -1) {
2413  ind[num] = vind[1];
2414  num++;
2415  if (flip == 0) {
2416  ind[num - 1] = vind[0];
2417  ind[num - 2] = vind[1];
2418  }
2419  }
2420  }
2421 
2422  /* we don't use the manifold option, but if it is
2423  ever enabled again note that it can output
2424  non-quads */
2425  }
2426  else {
2427  if (flip) {
2428  ind[0] = getMinimizerIndex((LeafNode *)(node[2]));
2429  ind[1] = getMinimizerIndex((LeafNode *)(node[3]));
2430  ind[2] = getMinimizerIndex((LeafNode *)(node[1]));
2431  ind[3] = getMinimizerIndex((LeafNode *)(node[0]));
2432  }
2433  else {
2434  ind[0] = getMinimizerIndex((LeafNode *)(node[0]));
2435  ind[1] = getMinimizerIndex((LeafNode *)(node[1]));
2436  ind[2] = getMinimizerIndex((LeafNode *)(node[3]));
2437  ind[3] = getMinimizerIndex((LeafNode *)(node[2]));
2438  }
2439 
2440  add_quad(output_mesh, ind);
2441  }
2442  }
2443  return;
2444  }
2445  else {
2446  return;
2447  }
2448  }
2449 }
2450 
2451 void Octree::edgeProcContour(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir)
2452 {
2453  if (!(node[0] && node[1] && node[2] && node[3])) {
2454  return;
2455  }
2456  if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) {
2457  processEdgeWrite(node, depth, maxdep, dir);
2458  }
2459  else {
2460  int i, j;
2461  Node *chd[4][8];
2462  for (j = 0; j < 4; j++) {
2463  for (i = 0; i < 8; i++) {
2464  chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
2465  node[j]->internal.get_child(node[j]->internal.get_child_count(i)) :
2466  NULL;
2467  }
2468  }
2469 
2470  // 2 edge calls
2471  Node *ne[4];
2472  int le[4];
2473  int de[4];
2474  for (i = 0; i < 2; i++) {
2475  int c[4] = {edgeProcEdgeMask[dir][i][0],
2476  edgeProcEdgeMask[dir][i][1],
2477  edgeProcEdgeMask[dir][i][2],
2478  edgeProcEdgeMask[dir][i][3]};
2479 
2480  for (int j = 0; j < 4; j++) {
2481  if (leaf[j]) {
2482  le[j] = leaf[j];
2483  ne[j] = node[j];
2484  de[j] = depth[j];
2485  }
2486  else {
2487  le[j] = node[j]->internal.is_child_leaf(c[j]);
2488  ne[j] = chd[j][c[j]];
2489  de[j] = depth[j] - 1;
2490  }
2491  }
2492 
2493  edgeProcContour(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]);
2494  }
2495  }
2496 }
2497 
2498 void Octree::faceProcContour(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir)
2499 {
2500  if (!(node[0] && node[1])) {
2501  return;
2502  }
2503 
2504  if (!(leaf[0] && leaf[1])) {
2505  int i, j;
2506  // Fill children nodes
2507  Node *chd[2][8];
2508  for (j = 0; j < 2; j++) {
2509  for (i = 0; i < 8; i++) {
2510  chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
2511  node[j]->internal.get_child(node[j]->internal.get_child_count(i)) :
2512  NULL;
2513  }
2514  }
2515 
2516  // 4 face calls
2517  Node *nf[2];
2518  int df[2];
2519  int lf[2];
2520  for (i = 0; i < 4; i++) {
2521  int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
2522  for (int j = 0; j < 2; j++) {
2523  if (leaf[j]) {
2524  lf[j] = leaf[j];
2525  nf[j] = node[j];
2526  df[j] = depth[j];
2527  }
2528  else {
2529  lf[j] = node[j]->internal.is_child_leaf(c[j]);
2530  nf[j] = chd[j][c[j]];
2531  df[j] = depth[j] - 1;
2532  }
2533  }
2534  faceProcContour(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]);
2535  }
2536 
2537  // 4 edge calls
2538  int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}};
2539  Node *ne[4];
2540  int le[4];
2541  int de[4];
2542 
2543  for (i = 0; i < 4; i++) {
2544  int c[4] = {faceProcEdgeMask[dir][i][1],
2545  faceProcEdgeMask[dir][i][2],
2546  faceProcEdgeMask[dir][i][3],
2547  faceProcEdgeMask[dir][i][4]};
2548  int *order = orders[faceProcEdgeMask[dir][i][0]];
2549 
2550  for (int j = 0; j < 4; j++) {
2551  if (leaf[order[j]]) {
2552  le[j] = leaf[order[j]];
2553  ne[j] = node[order[j]];
2554  de[j] = depth[order[j]];
2555  }
2556  else {
2557  le[j] = node[order[j]]->internal.is_child_leaf(c[j]);
2558  ne[j] = chd[order[j]][c[j]];
2559  de[j] = depth[order[j]] - 1;
2560  }
2561  }
2562 
2563  edgeProcContour(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]);
2564  }
2565  }
2566 }
2567 
2568 void Octree::cellProcContour(Node *node, int leaf, int depth)
2569 {
2570  if (node == NULL) {
2571  return;
2572  }
2573 
2574  if (!leaf) {
2575  int i;
2576 
2577  // Fill children nodes
2578  Node *chd[8];
2579  for (i = 0; i < 8; i++) {
2580  chd[i] = ((!leaf) && node->internal.has_child(i)) ?
2581  node->internal.get_child(node->internal.get_child_count(i)) :
2582  NULL;
2583  }
2584 
2585  // 8 Cell calls
2586  for (i = 0; i < 8; i++) {
2587  cellProcContour(chd[i], node->internal.is_child_leaf(i), depth - 1);
2588  }
2589 
2590  // 12 face calls
2591  Node *nf[2];
2592  int lf[2];
2593  int df[2] = {depth - 1, depth - 1};
2594  for (i = 0; i < 12; i++) {
2595  int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
2596 
2597  lf[0] = node->internal.is_child_leaf(c[0]);
2598  lf[1] = node->internal.is_child_leaf(c[1]);
2599 
2600  nf[0] = chd[c[0]];
2601  nf[1] = chd[c[1]];
2602 
2603  faceProcContour(nf, lf, df, depth - 1, cellProcFaceMask[i][2]);
2604  }
2605 
2606  // 6 edge calls
2607  Node *ne[4];
2608  int le[4];
2609  int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1};
2610  for (i = 0; i < 6; i++) {
2611  int c[4] = {cellProcEdgeMask[i][0],
2612  cellProcEdgeMask[i][1],
2613  cellProcEdgeMask[i][2],
2614  cellProcEdgeMask[i][3]};
2615 
2616  for (int j = 0; j < 4; j++) {
2617  le[j] = node->internal.is_child_leaf(c[j]);
2618  ne[j] = chd[c[j]];
2619  }
2620 
2621  edgeProcContour(ne, le, de, depth - 1, cellProcEdgeMask[i][4]);
2622  }
2623  }
2624 }
2625 
2626 void Octree::processEdgeParity(LeafNode *node[4], int /*depth*/[4], int /*maxdep*/, int dir)
2627 {
2628  int con = 0;
2629  for (int i = 0; i < 4; i++) {
2630  // Minimal cell
2631  // if(op == 0)
2632  {
2633  if (getEdgeParity(node[i], processEdgeMask[dir][i])) {
2634  con = 1;
2635  break;
2636  }
2637  }
2638  }
2639 
2640  if (con == 1) {
2641  for (int i = 0; i < 4; i++) {
2642  setEdge(node[i], processEdgeMask[dir][i]);
2643  }
2644  }
2645 }
2646 
2647 void Octree::edgeProcParity(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir)
2648 {
2649  if (!(node[0] && node[1] && node[2] && node[3])) {
2650  return;
2651  }
2652  if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) {
2653  processEdgeParity((LeafNode **)node, depth, maxdep, dir);
2654  }
2655  else {
2656  int i, j;
2657  Node *chd[4][8];
2658  for (j = 0; j < 4; j++) {
2659  for (i = 0; i < 8; i++) {
2660  chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
2661  node[j]->internal.get_child(node[j]->internal.get_child_count(i)) :
2662  NULL;
2663  }
2664  }
2665 
2666  // 2 edge calls
2667  Node *ne[4];
2668  int le[4];
2669  int de[4];
2670  for (i = 0; i < 2; i++) {
2671  int c[4] = {edgeProcEdgeMask[dir][i][0],
2672  edgeProcEdgeMask[dir][i][1],
2673  edgeProcEdgeMask[dir][i][2],
2674  edgeProcEdgeMask[dir][i][3]};
2675 
2676  // int allleaf = 1;
2677  for (int j = 0; j < 4; j++) {
2678 
2679  if (leaf[j]) {
2680  le[j] = leaf[j];
2681  ne[j] = node[j];
2682  de[j] = depth[j];
2683  }
2684  else {
2685  le[j] = node[j]->internal.is_child_leaf(c[j]);
2686  ne[j] = chd[j][c[j]];
2687  de[j] = depth[j] - 1;
2688  }
2689  }
2690 
2691  edgeProcParity(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]);
2692  }
2693  }
2694 }
2695 
2696 void Octree::faceProcParity(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir)
2697 {
2698  if (!(node[0] && node[1])) {
2699  return;
2700  }
2701 
2702  if (!(leaf[0] && leaf[1])) {
2703  int i, j;
2704  // Fill children nodes
2705  Node *chd[2][8];
2706  for (j = 0; j < 2; j++) {
2707  for (i = 0; i < 8; i++) {
2708  chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
2709  node[j]->internal.get_child(node[j]->internal.get_child_count(i)) :
2710  NULL;
2711  }
2712  }
2713 
2714  // 4 face calls
2715  Node *nf[2];
2716  int df[2];
2717  int lf[2];
2718  for (i = 0; i < 4; i++) {
2719  int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
2720  for (int j = 0; j < 2; j++) {
2721  if (leaf[j]) {
2722  lf[j] = leaf[j];
2723  nf[j] = node[j];
2724  df[j] = depth[j];
2725  }
2726  else {
2727  lf[j] = node[j]->internal.is_child_leaf(c[j]);
2728  nf[j] = chd[j][c[j]];
2729  df[j] = depth[j] - 1;
2730  }
2731  }
2732  faceProcParity(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]);
2733  }
2734 
2735  // 4 edge calls
2736  int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}};
2737  Node *ne[4];
2738  int le[4];
2739  int de[4];
2740 
2741  for (i = 0; i < 4; i++) {
2742  int c[4] = {faceProcEdgeMask[dir][i][1],
2743  faceProcEdgeMask[dir][i][2],
2744  faceProcEdgeMask[dir][i][3],
2745  faceProcEdgeMask[dir][i][4]};
2746  int *order = orders[faceProcEdgeMask[dir][i][0]];
2747 
2748  for (int j = 0; j < 4; j++) {
2749  if (leaf[order[j]]) {
2750  le[j] = leaf[order[j]];
2751  ne[j] = node[order[j]];
2752  de[j] = depth[order[j]];
2753  }
2754  else {
2755  le[j] = node[order[j]]->internal.is_child_leaf(c[j]);
2756  ne[j] = chd[order[j]][c[j]];
2757  de[j] = depth[order[j]] - 1;
2758  }
2759  }
2760 
2761  edgeProcParity(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]);
2762  }
2763  }
2764 }
2765 
2766 void Octree::cellProcParity(Node *node, int leaf, int depth)
2767 {
2768  if (node == NULL) {
2769  return;
2770  }
2771 
2772  if (!leaf) {
2773  int i;
2774 
2775  // Fill children nodes
2776  Node *chd[8];
2777  for (i = 0; i < 8; i++) {
2778  chd[i] = ((!leaf) && node->internal.has_child(i)) ?
2779  node->internal.get_child(node->internal.get_child_count(i)) :
2780  NULL;
2781  }
2782 
2783  // 8 Cell calls
2784  for (i = 0; i < 8; i++) {
2785  cellProcParity(chd[i], node->internal.is_child_leaf(i), depth - 1);
2786  }
2787 
2788  // 12 face calls
2789  Node *nf[2];
2790  int lf[2];
2791  int df[2] = {depth - 1, depth - 1};
2792  for (i = 0; i < 12; i++) {
2793  int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
2794 
2795  lf[0] = node->internal.is_child_leaf(c[0]);
2796  lf[1] = node->internal.is_child_leaf(c[1]);
2797 
2798  nf[0] = chd[c[0]];
2799  nf[1] = chd[c[1]];
2800 
2801  faceProcParity(nf, lf, df, depth - 1, cellProcFaceMask[i][2]);
2802  }
2803 
2804  // 6 edge calls
2805  Node *ne[4];
2806  int le[4];
2807  int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1};
2808  for (i = 0; i < 6; i++) {
2809  int c[4] = {cellProcEdgeMask[i][0],
2810  cellProcEdgeMask[i][1],
2811  cellProcEdgeMask[i][2],
2812  cellProcEdgeMask[i][3]};
2813 
2814  for (int j = 0; j < 4; j++) {
2815  le[j] = node->internal.is_child_leaf(c[j]);
2816  ne[j] = chd[c[j]];
2817  }
2818 
2819  edgeProcParity(ne, le, de, depth - 1, cellProcEdgeMask[i][4]);
2820  }
2821  }
2822 }
2823 
2824 /* definitions for global arrays */
2825 const int edgemask[3] = {5, 3, 6};
2826 
2827 const int faceMap[6][4] = {
2828  {4, 8, 5, 9},
2829  {6, 10, 7, 11},
2830  {0, 8, 1, 10},
2831  {2, 9, 3, 11},
2832  {0, 4, 2, 6},
2833  {1, 5, 3, 7},
2834 };
2835 
2836 const int cellProcFaceMask[12][3] = {
2837  {0, 4, 0},
2838  {1, 5, 0},
2839  {2, 6, 0},
2840  {3, 7, 0},
2841  {0, 2, 1},
2842  {4, 6, 1},
2843  {1, 3, 1},
2844  {5, 7, 1},
2845  {0, 1, 2},
2846  {2, 3, 2},
2847  {4, 5, 2},
2848  {6, 7, 2},
2849 };
2850 
2851 const int cellProcEdgeMask[6][5] = {
2852  {0, 1, 2, 3, 0},
2853  {4, 5, 6, 7, 0},
2854  {0, 4, 1, 5, 1},
2855  {2, 6, 3, 7, 1},
2856  {0, 2, 4, 6, 2},
2857  {1, 3, 5, 7, 2},
2858 };
2859 
2860 const int faceProcFaceMask[3][4][3] = {{{4, 0, 0}, {5, 1, 0}, {6, 2, 0}, {7, 3, 0}},
2861  {{2, 0, 1}, {6, 4, 1}, {3, 1, 1}, {7, 5, 1}},
2862  {{1, 0, 2}, {3, 2, 2}, {5, 4, 2}, {7, 6, 2}}};
2863 
2864 const int faceProcEdgeMask[3][4][6] = {
2865  {{1, 4, 0, 5, 1, 1}, {1, 6, 2, 7, 3, 1}, {0, 4, 6, 0, 2, 2}, {0, 5, 7, 1, 3, 2}},
2866  {{0, 2, 3, 0, 1, 0}, {0, 6, 7, 4, 5, 0}, {1, 2, 0, 6, 4, 2}, {1, 3, 1, 7, 5, 2}},
2867  {{1, 1, 0, 3, 2, 0}, {1, 5, 4, 7, 6, 0}, {0, 1, 5, 0, 4, 1}, {0, 3, 7, 2, 6, 1}}};
2868 
2869 const int edgeProcEdgeMask[3][2][5] = {
2870  {{3, 2, 1, 0, 0}, {7, 6, 5, 4, 0}},
2871  {{5, 1, 4, 0, 1}, {7, 3, 6, 2, 1}},
2872  {{6, 4, 2, 0, 2}, {7, 5, 3, 1, 2}},
2873 };
2874 
2875 const int processEdgeMask[3][4] = {
2876  {3, 2, 1, 0},
2877  {7, 5, 6, 4},
2878  {11, 10, 9, 8},
2879 };
2880 
2881 const int dirCell[3][4][3] = {{{0, -1, -1}, {0, -1, 0}, {0, 0, -1}, {0, 0, 0}},
2882  {{-1, 0, -1}, {-1, 0, 0}, {0, 0, -1}, {0, 0, 0}},
2883  {{-1, -1, 0}, {-1, 0, 0}, {0, -1, 0}, {0, 0, 0}}};
2884 
2885 const int dirEdge[3][4] = {
2886  {3, 2, 1, 0},
2887  {7, 6, 5, 4},
2888  {11, 10, 9, 8},
2889 };
2890 
typedef float(TangentPoint)[2]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint order
Read Guarded memory(de)allocation.
const int edgemap[12][2]
Definition: Projections.cpp:42
const int vertmap[8][3]
Definition: Projections.cpp:24
#define GRID_DIMENSION
Definition: Projections.h:24
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
#define A
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
int numVertices() const
SIMD_FORCE_INLINE void mult(const btTransform &t1, const btTransform &t2)
Set the current transform as the value of the product of two transforms.
Definition: btTransform.h:76
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
void shift(int off[3])
int isIntersecting() const
int isIntersectingPrimary(int edgeInd) const
unsigned char getBoxMask()
TriangleProjection * inherit
Inheritable portion.
Definition: Projections.h:86
float getIntersectionPrimary(int edgeInd) const
Definition: cubes.h:23
virtual float getBoundingBox(float origin[3])=0
Get bounding box.
virtual Triangle * getNextTriangle()=0
Get next triangle.
virtual int getNumTriangles()=0
Get number of triangles.
int use_flood_fill
Definition: octree.h:261
int use_manifold
Definition: octree.h:264
int dimen
Definition: octree.h:238
float range
Definition: octree.h:246
int maxTrianglePerCell
Definition: octree.h:257
float thresh
Definition: octree.h:262
ModelReader * reader
Definition: octree.h:232
VirtualMemoryAllocator * alloc[9]
Definition: octree.h:225
int maxDepth
Definition: octree.h:242
int nodeSpace
Definition: octree.h:250
VirtualMemoryAllocator * leafalloc[4]
Definition: octree.h:226
~Octree()
Definition: octree.cpp:105
float origin[3]
Definition: octree.h:245
Cubes * cubes
Definition: octree.h:235
int nodeCount
Definition: octree.h:249
float hermite_num
Definition: octree.h:266
int minshift
Definition: octree.h:239
int actualQuads
Definition: octree.h:253
DualConMode mode
Definition: octree.h:268
void scanConvert()
Definition: octree.cpp:111
int mindimen
Definition: octree.h:239
Octree(ModelReader *mr, DualConAllocOutput alloc_output_func, DualConAddVert add_vert_func, DualConAddQuad add_quad_func, DualConFlags flags, DualConMode mode, int depth, float threshold, float hermite_num)
Definition: octree.cpp:45
Node * root
Definition: octree.h:229
int actualVerts
Definition: octree.h:253
virtual int getBytes()=0
virtual int getAllocated()=0
virtual int getAll()=0
virtual void destroy()=0
virtual void printInfo()=0
OperationNode * node
static CCL_NAMESPACE_BEGIN const double alpha
DualConMode
Definition: dualcon.h:61
@ DUALCON_CENTROID
Definition: dualcon.h:63
@ DUALCON_MASS_POINT
Definition: dualcon.h:65
void(* DualConAddQuad)(void *output, const int vert_indices[4])
Definition: dualcon.h:55
void(* DualConAddVert)(void *output, const float co[3])
Definition: dualcon.h:53
DualConFlags
Definition: dualcon.h:57
@ DUALCON_FLOOD_FILL
Definition: dualcon.h:58
void *(* DualConAllocOutput)(int totvert, int totquad)
Definition: dualcon.h:51
uint pos
int count
const ManifoldIndices manifold_table[256]
static ulong * next
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
ThreadQueue * queue
all scheduled work for the cpu
const int processEdgeMask[3][4]
Definition: octree.cpp:2875
const int edgeProcEdgeMask[3][2][5]
Definition: octree.cpp:2869
static void pseudoInverse(const Eigen::Matrix3f &a, Eigen::Matrix3f &result, float tolerance)
Definition: octree.cpp:2183
const int faceProcFaceMask[3][4][3]
Definition: octree.cpp:2860
static void minimize(float rvalue[3], float mp[3], const float pts[12][3], const float norms[12][3], const int parity[12])
Definition: octree.cpp:2236
static void solve_least_squares(const float halfA[], const float b[], const float midpoint[], float rvalue[])
Definition: octree.cpp:2194
const int cellProcFaceMask[12][3]
Definition: octree.cpp:2836
const int faceMap[6][4]
Definition: octree.cpp:2827
const int faceProcEdgeMask[3][4][6]
Definition: octree.cpp:2864
#define dc_printf(...)
Definition: octree.cpp:40
const int cellProcEdgeMask[6][5]
Definition: octree.cpp:2851
const int dirEdge[3][4]
Definition: octree.cpp:2885
static void mass_point(float mp[3], const float pts[12][3], const int parity[12])
Definition: octree.cpp:2212
const int dirCell[3][4][3]
Definition: octree.cpp:2881
const int edgemask[3]
Definition: octree.cpp:2825
__int64 int64_t
Definition: stdint.h:92
Node * get_child(int count)
Definition: octree.h:81
static int childrenCountTable[256][8]
Definition: octree.h:57
static int numChildrenTable[256]
Definition: octree.h:56
int has_child(int index) const
Definition: octree.h:75
static int childrenIndexTable[256][8]
Definition: octree.h:58
void fill_children(Node *children[8], int leaf[8])
Definition: octree.h:112
int is_child_leaf(int index) const
Definition: octree.h:69
Definition: node.h:98
LeafNode leaf
Definition: octree.h:178
InternalNode internal
Definition: octree.h:177
PathElement * next
Definition: octree.h:202
int pos[3]
Definition: octree.h:199
int length
Definition: octree.h:211
PathElement * tail
Definition: octree.h:208
PathList * next
Definition: octree.h:214
PathElement * head
Definition: octree.h:207
double norm[3]
Normal of the triangle.
Definition: Projections.h:66
float vt[3][3]
Definition: GeoCommon.h:43
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
uint len