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