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