23# define dc_printf printf
26# define dc_printf(...) \
60 alloc_output(alloc_output_func),
61 add_vert(add_vert_func),
62 add_quad(add_quad_func)
101 clock_t start, finish;
107 preparePrimalEdgesMask(&
root->internal);
112 (
double)(finish - start) / CLOCKS_PER_SEC);
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",
128 (
float)totRingLengths / (
float)numRings,
134 int tnumRings = numRings;
136#ifdef IN_VERBOSE_MODE
137 dc_printf(
"Holes after patching: %d \n", numRings);
139 numRings = tnumRings;
148 dc_printf(
"Time taken: %f seconds \n", (
double)(finish - start) / CLOCKS_PER_SEC);
174 dc_printf(
"Time taken: %f seconds \n", (
double)(finish - start) / CLOCKS_PER_SEC);
189#ifdef IN_VERBOSE_MODE
194void Octree::initMemory()
212void Octree::freeMemory()
214 for (
int i = 0;
i < 9;
i++) {
219 for (
int i = 0;
i < 4;
i++) {
225void Octree::printMemUsage()
228 dc_printf(
"********* Internal nodes: \n");
229 for (
int i = 0;
i < 9;
i++) {
232 totalbytes +=
alloc[
i]->getAll() *
alloc[
i]->getBytes();
236 for (
int i = 0;
i < 4;
i++) {
243 dc_printf(
"Total allocated bytes on disk: %d \n", totalbytes);
244 dc_printf(
"Total leaf nodes: %d\n", totalLeafs);
251void Octree::resetMinimalEdges()
256void Octree::addAllTriangles()
262 int total =
reader->getNumTriangles();
263 int unitcount = 1000;
269 while ((trian =
reader->getNextTriangle()) !=
nullptr) {
272 addTriangle(trian,
count);
279 if (
count % unitcount == 0) {
282 switch ((
count / unitcount) % 4) {
297 float percent = (float)
count / total;
311 dc_printf(
" %f%% complete.", 100 * percent);
320void Octree::addTriangle(
Triangle *trian,
int triind)
325 for (
i = 0;
i < 3;
i++) {
326 for (j = 0; j < 3; j++) {
334 for (
i = 0;
i < 3;
i++) {
335 for (j = 0; j < 3; j++) {
342 CubeTriangleIsect *proj =
new CubeTriangleIsect(cube, trig, errorvec, triind);
350static void print_depth(
int height,
int maxDepth)
352 for (
int i = 0;
i < maxDepth - height;
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}};
363 CubeTriangleIsect *subp =
new CubeTriangleIsect(p);
366 int tempdiff[3] = {0, 0, 0};
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];
375 if (boxmask & (1 <<
i)) {
376 subp->
shift(tempdiff);
377 tempdiff[0] = tempdiff[1] = tempdiff[2] = 0;
383 node = addLeafChild(node,
i,
count, createLeaf(0));
386 node = addInternalChild(node,
i,
count, createInternal(0));
415 int mask[3] = {0, 4, 8};
416 int oldc = 0, newc = 0;
418 float a[3],
b[3], c[3];
420 for (
i = 0;
i < 3;
i++) {
421 if (!getEdgeParity(node,
mask[
i])) {
424 setEdge(node,
mask[
i]);
433 offs[newc] = getEdgeOffsetNormal(node, oldc, a[newc],
b[newc], c[newc]);
442 node = updateEdgeOffsetsNormals(node, oldc, newc, offs, a,
b, c);
451 for (
int i = 0;
i < 8;
i++) {
476 PathList *chdpath =
nullptr;
479 if (chdpath !=
nullptr) {
480 dc_printf(
"there are incomplete rings.\n");
488 PathList *chdpaths[8];
498 for (
i = 0;
i < 8;
i++) {
499 for (j = 0; j < 3; j++) {
504 chdpaths[
i] =
nullptr;
507 trace(chd[
i], nst[
i],
len, depth - 1, chdpaths[
i]);
515 int df[2] = {depth - 1, depth - 1};
520 for (
i = 0;
i < 12;
i++) {
523 for (
int j = 0; j < 2; j++) {
524 lf[j] = chdleaf[c[j]];
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);
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);
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);
564 PathList *trings = rings;
567 totRingLengths += trings->
length;
568 maxRingLength = std::max(trings->
length, maxRingLength);
569 trings = trings->
next;
573 newnode = patch(newnode, st, (
len << 1), rings);
581void Octree::findPaths(
Node *node[2],
589 if (!(node[0] && node[1])) {
593 if (!(leaf[0] && leaf[1])) {
602 for (j = 0; j < 2; j++) {
607 for (
i = 0;
i < 8;
i++) {
608 for (
int k = 0; k < 3; k++) {
620 for (
i = 0;
i < 4;
i++) {
622 for (
int j = 0; j < 2; j++) {
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]];
641 int ind = (depth[0] == maxdep ? 0 : 1);
642 int fcind = 2 * dir + (1 - ind);
643 if (getFaceParity((LeafNode *)node[ind], fcind)) {
645 PathElement *ele1 =
new PathElement;
646 PathElement *ele2 =
new PathElement;
648 ele1->
pos[0] = st[0][0];
649 ele1->
pos[1] = st[0][1];
650 ele1->
pos[2] = st[0][2];
652 ele2->
pos[0] = st[1][0];
653 ele2->
pos[1] = st[1][1];
654 ele2->
pos[2] = st[1][2];
657 ele2->
next =
nullptr;
659 PathList *lst =
new PathList;
674 PathList *nlist =
nullptr;
677 PathList *tpaths = paths;
678 PathList *tlist, *pre;
680 PathList *singlist = tpaths;
682 tpaths = tpaths->
next;
683 singlist->
next =
nullptr;
689 if ((templist = combineSinglePath(list1, pre, tlist, singlist,
nullptr, singlist)) !=
703 if ((templist = combineSinglePath(list2, pre, tlist, singlist,
nullptr, singlist)) !=
717 if ((templist = combineSinglePath(nlist, pre, tlist, singlist,
nullptr, singlist)) !=
728 if (isEqual(singlist->
head, singlist->
tail)) {
729 PathElement *temp = singlist->
head;
735 singlist->
next = rings;
739 singlist->
next = nlist;
746 if (tlist !=
nullptr) {
747 while (tlist->
next !=
nullptr) {
757 if (tlist !=
nullptr) {
758 while (tlist->
next !=
nullptr) {
776 if (isEqual(list1->
head, list2->
head) || isEqual(list1->
tail, list2->
tail)) {
782 prev->next =
nullptr;
783 while (
next !=
nullptr) {
784 PathElement *tnext =
next->next;
798 prev->next =
nullptr;
799 while (
next !=
nullptr) {
800 PathElement *tnext =
next->next;
812 if (isEqual(list1->
head, list2->
tail)) {
815 PathElement *temp = list1->
head->
next;
819 PathList *nlist =
new PathList;
823 nlist->
next =
nullptr;
825 deletePath(head1, pre1, list1);
826 deletePath(head2, pre2, list2);
830 if (isEqual(list1->
tail, list2->
head)) {
832 PathElement *temp = list2->
head->
next;
836 PathList *nlist =
new PathList;
840 nlist->
next =
nullptr;
842 deletePath(head1, pre1, list1);
843 deletePath(head2, pre2, list2);
853 PathList *temp = curr;
857 if (pre ==
nullptr) {
867 if (ele !=
nullptr) {
872void Octree::printPath(
PathList *path)
874 PathElement *n = path->
head;
880 while (n && (same == 0 || n != path->
head)) {
886 if (n == path->
head) {
896 PathElement *n = path;
901 while (n && (same == 0 || n != path)) {
915void Octree::printPaths(
PathList *path)
917 PathList *iter = path;
918 while (iter !=
nullptr) {
928 dc_printf(
"Call to PATCH with rings: \n");
951 dc_printf(
"Error! should have no list by now.\n");
957 newnode = patchSplit(newnode, st,
len, rings, 0, xlists[0], xlists[1]);
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]);
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]);
974 for (
int i = 0;
i < 8;
i++) {
975 if (zlists[
i] !=
nullptr) {
991Node *Octree::patchSplit(
Node *newnode,
1000 dc_printf(
"Call to PATCHSPLIT with direction %d and rings: \n", dir);
1007 while (rings !=
nullptr) {
1009 newnode = patchSplitSingle(newnode, st,
len, rings->
head, dir, nrings1, nrings2);
1013 rings = rings->
next;
1018 dc_printf(
"Return from PATCHSPLIT with \n");
1020 printPaths(nrings1);
1022 printPaths(nrings2);
1028Node *Octree::patchSplitSingle(
Node *newnode,
1037 dc_printf(
"Call to PATCHSPLITSINGLE with direction %d and path: \n", dir);
1041 if (head ==
nullptr) {
1043 dc_printf(
"Return from PATCHSPLITSINGLE with head==nullptr.\n");
1051 PathElement *pre1 =
nullptr;
1052 PathElement *pre2 =
nullptr;
1053 int side = findPair(head, st[dir] +
len / 2, dir, pre1, pre2);
1058 dc_printf(
"Location: %d %d %d Direction: %d Reso: %d\n",
1071 PathList *nring =
new PathList();
1075 nring->
next = nrings1;
1079 nring->
next = nrings2;
1085 PathElement *nxt1 = pre1->
next;
1086 PathElement *nxt2 = pre2->
next;
1090 newnode = connectFace(newnode, st,
len, dir, pre1, pre2);
1092 if (isEqual(pre1, pre1->
next)) {
1093 if (pre1 == pre1->
next) {
1098 PathElement *temp = pre1->
next;
1103 if (isEqual(pre2, pre2->
next)) {
1104 if (pre2 == pre2->
next) {
1109 PathElement *temp = pre2->
next;
1119 newnode = patchSplitSingle(newnode, st,
len, pre1, dir, nrings1, nrings2);
1120 newnode = patchSplitSingle(newnode, st,
len, pre2, dir, nrings1, nrings2);
1124 dc_printf(
"Return from PATCHSPLITSINGLE with \n");
1126 printPaths(nrings1);
1128 printPaths(nrings2);
1134Node *Octree::connectFace(
1138 dc_printf(
"Call to CONNECTFACE with direction %d and length %d path: \n", dir,
len);
1148 int pos = st[dir] +
len / 2;
1149 int xdir = (dir + 1) % 3;
1150 int ydir = (dir + 2) % 3;
1154 float p1, q1, p2, q2;
1156 getFacePoint(f2->
next, dir, x1, y1, p1, q1);
1157 getFacePoint(f2, dir, x2, y2, p2, q2);
1159 float dx = x2 + p2 - x1 - p1;
1160 float dy = y2 + q2 - y1 - q1;
1163 float rx = p1, ry = q1;
1164 int incx = 1, incy = 1;
1165 int lx = x1, ly = y1;
1166 int hx = x2, hy = y2;
1181 float sx = dx * incx;
1182 float sy = dy * incy;
1192 PathElement *curEleN = f1;
1193 PathElement *curEleP = f2->
next;
1194 Node *nodeN =
nullptr, *nodeP =
nullptr;
1197 if (curN ==
nullptr || curP ==
nullptr) {
1212 while (ori[xdir] != x2 || ori[ydir] != y2) {
1214 if (sy * (1 - rx) > sx * (1 - ry)) {
1216 next = ori[ydir] + incy;
1219 next = ori[xdir] + incx;
1224 next = ori[xdir] + incx;
1227 next = ori[ydir] + incy;
1234 rx += (sy == 0 ? 0 : (1 - ry) * sx / sy);
1240 alpha = x2 < x1 ? 1 - rx : rx;
1245 ry += (sx == 0 ? 0 : (1 - rx) * sy / sx);
1251 alpha = y2 < y1 ? 1 - ry : ry;
1256 float spt[3] = {(float)nori[0], (
float)nori[1], (float)nori[2]};
1257 spt[(dir + (3 - walkdir)) % 3] += alpha *
mindimen;
1259 spt[(dir + walkdir) % 3] +=
mindimen;
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]);
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);
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])
1280 newEleN =
new PathElement;
1282 newEleN->
pos[0] = stN[0];
1283 newEleN->
pos[1] = stN[1];
1284 newEleN->
pos[2] = stN[2];
1286 curEleN->
next = newEleN;
1289 newEleN = curEleN->
next;
1291 curN = patchAdjacent(&newnode->
internal,
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];
1320 curP = patchAdjacent(&newnode->
internal,
1343 dc_printf(
"Return from CONNECTFACE with \n");
1372 "-----------------%d %d %d; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2]);
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);
1381 int eind1 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 1 : 0) << ind2));
1382 int eind2 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 0 : 1) << ind2));
1385 dc_printf(
"Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha);
1396 LeafNode *nleaf1 = flipEdge(leaf1, eind1, alpha);
1397 LeafNode *nleaf2 = flipEdge(leaf2, eind2, alpha);
1400 updateParent(node,
len, st1, nleaf1);
1401 updateParent(node,
len, st2, nleaf2);
1440 for (
i = 0;
i < 3;
i++) {
1442 if (
i == dir && side == 1) {
1443 ind |= (ori[
i] <= (st[
i] +
len) ? 0 : 1);
1446 ind |= (ori[
i] < (st[
i] +
len) ? 0 : 1);
1453 "In LOCATECELL index of ori(%d %d %d) with dir %d side %d in st(%d %d %d, %d) is: %d\n",
1481 locateCell(&chd->
internal, rst,
len, ori, dir, side, rleaf, rst, rlen));
1487 LeafNode *chd = createLeaf(0);
1488 node = addChild(node, ind, (Node *)chd, 1);
1489 rleaf = (Node *)chd;
1494 InternalNode *chd = createInternal(0);
1495 node = addChild(node, ind, locateCell(chd, rst,
len, ori, dir, side, rleaf, rst, rlen), 0);
1503 return (Node *)node;
1509 if (ele !=
nullptr && locateLeafCheck(ele->
pos) != ele->node) {
1510 dc_printf(
"Screwed! at pos: %d %d %d\n",
1521 PathElement *n = path;
1523 while (n && (same == 0 || n != path)) {
1533 PathElement *
e =
nullptr;
1534 for (
i = 0;
i < 3;
i++) {
1549 getFacePoint(
e,
i,
x,
y, p, q);
1552void Octree::getFacePoint(
PathElement *leaf,
int dir,
int &
x,
int &
y,
float &p,
float &q)
1555 float avg[3] = {0, 0, 0};
1557 int num = 0, num2 = 0;
1561 LeafNode *leafnode = locateLeaf(leaf->
pos);
1562 for (
int i = 0;
i < 4;
i++) {
1565 for (
int j = 0; j < 3; j++) {
1569 if (getEdgeIntersectionByIndex(nst, edgeind / 4, off, 1)) {
1575 if (getEdgeParity(leafnode, edgeind)) {
1580 dc_printf(
"Wrong! dir: %d pos: %d %d %d num: %d\n",
1586 avg[0] = (float)leaf->
pos[0];
1587 avg[1] = (float)leaf->
pos[1];
1588 avg[2] = (float)leaf->
pos[2];
1601 int xdir = (dir + 1) % 3;
1602 int ydir = (dir + 2) % 3;
1604 float xf = avg[xdir];
1605 float yf = avg[ydir];
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",
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",
1649 dc_printf(
"Face point at dir %d pos %d: %f %f\n", dir,
pos, xf, yf);
1662 dc_printf(
"Face point at dir %d : %f %f\n", dir, xf, yf);
1668 int side = getSide(head,
pos, dir);
1669 PathElement *cur = head;
1670 PathElement *anchor;
1671 PathElement *ppre1, *ppre2;
1677 while (cur != anchor && (getSide(cur,
pos, dir) == side)) {
1681 if (cur == anchor) {
1686 side = getSide(cur,
pos, dir);
1689 while (getSide(cur,
pos, dir) == side) {
1709 return (
e->pos[dir] <
pos ? -1 : 1);
1714 return (e1->
pos[0] == e2->
pos[0] && e1->
pos[1] == e2->
pos[1] && e1->
pos[2] == e2->
pos[2]);
1719 if (ring ==
nullptr) {
1723 dc_printf(
"Call to COMPRESSRING with path: \n");
1727 PathElement *cur = ring->
next->
next;
1728 PathElement *pre = ring->
next;
1729 PathElement *prepre = ring;
1730 PathElement *anchor = prepre;
1733 while (isEqual(cur, prepre)) {
1735 if (cur == prepre) {
1750 if (anchor ==
nullptr) {
1757 }
while (prepre != anchor);
1762 dc_printf(
"Return from COMPRESSRING with path: \n");
1767void Octree::buildSigns()
1772 unsigned char table[1 << 12];
1773 for (
int i = 0;
i <
size;
i++) {
1776 for (
int i = 0;
i < 256;
i++) {
1778 for (
int j = 11; j >= 0; j--) {
1791 buildSigns(table,
root, 0, sg, cube);
1794void Octree::buildSigns(
unsigned char table[],
Node *node,
int isLeaf,
int sg,
int rvalue[8])
1796 if (node ==
nullptr) {
1797 for (
int i = 0;
i < 8;
i++) {
1812 buildSigns(table, chd[0], leaf[0], sg, oris);
1816 for (
int i = 1;
i < 8;
i++) {
1817 buildSigns(table, chd[
i], leaf[
i], oris[
i], cube);
1818 rvalue[
i] = cube[
i];
1823 generateSigns(&node->
leaf, table, sg);
1825 for (
int i = 0;
i < 8;
i++) {
1826 rvalue[
i] = getSign(&node->
leaf,
i);
1831void Octree::floodFill()
1834 int st[3] = {0, 0, 0};
1842 dc_printf(
"Largest component: %d\n", threshold);
1844 dc_printf(
"Removing all components smaller than %d\n", threshold);
1846 int st2[3] = {0, 0, 0};
1851void Octree::clearProcessBits(
Node *node,
int height)
1857 for (
i = 0;
i < 12;
i++) {
1858 setOutProcess(&node->
leaf,
i);
1864 for (
i = 0;
i < 8;
i++) {
1873int Octree::floodFill(
LeafNode *leaf,
const int st[3],
int len,
int ,
int threshold)
1882 for (
i = 0;
i < 12;
i++) {
1883 par = getEdgeParity(leaf,
i);
1884 inp = isInProcess(leaf,
i);
1886 if (par == 1 && inp == 0) {
1889 GridQueue *queue =
new GridQueue();
1898 setInProcessAll(mst, mdir);
1905 while (queue->
popQueue(nst, dir) == 1) {
1914 int stMask[3][3] = {{0, 0 -
len, 0 -
len}, {0 -
len, 0, 0 -
len}, {0 -
len, 0 -
len, 0}};
1916 for (j = 0; j < 3; j++) {
1918 cst[1][j] = nst[j] + stMask[dir][j];
1923 for (j = 0; j < 2; j++) {
1924 cs[j] = locateLeaf(cst[j]);
1928 int s = getSign(cs[0], 0);
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}}};
1937 for (
int find = 0; find < 4; find++) {
1938 int cind = fcCells[find];
1942 for (eind = 0; eind < 3; eind++) {
1943 edge = fcEdges[dir][find][eind];
1944 if (getEdgeParity(cs[cind], edge) == 1) {
1951 for (eind = 2; eind >= 0; eind--) {
1952 edge = fcEdges[dir][find][eind];
1953 if (getEdgeParity(cs[cind], edge) == 1) {
1959 if (eind == 3 || eind == -1) {
1960 dc_printf(
"Wrong! this is not a consistent sign. %d\n", eind);
1967 int edir = edge / 4;
1969 if (isInProcess(cs[cind], edge) == 0) {
1970 setInProcessAll(est, edir);
1973 dc_printf(
"Pushed: est: %d %d %d, edir: %d\n",
1985 dc_printf(
"Size of component: %d ", total);
1987 if (threshold == 0) {
1989 maxtotal = std::max(total, maxtotal);
1995 if (total >= threshold) {
2000 dc_printf(
"Less than %d, removing...\n", threshold);
2006 flipParityAll(mst, mdir);
2012 while (queue->
popQueue(nst, dir) == 1) {
2021 int stMask[3][3] = {{0, 0 -
len, 0 -
len}, {0 -
len, 0, 0 -
len}, {0 -
len, 0 -
len, 0}};
2023 for (j = 0; j < 3; j++) {
2025 cst[1][j] = nst[j] + stMask[dir][j];
2030 for (j = 0; j < 2; j++) {
2031 cs[j] = locateLeaf(cst[j]);
2035 int s = getSign(cs[0], 0);
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}}};
2044 for (
int find = 0; find < 4; find++) {
2045 int cind = fcCells[find];
2049 for (eind = 0; eind < 3; eind++) {
2050 edge = fcEdges[dir][find][eind];
2051 if (isInProcess(cs[cind], edge) == 1) {
2058 for (eind = 2; eind >= 0; eind--) {
2059 edge = fcEdges[dir][find][eind];
2060 if (isInProcess(cs[cind], edge) == 1) {
2066 if (eind == 3 || eind == -1) {
2067 dc_printf(
"Wrong! this is not a consistent sign. %d\n", eind);
2074 int edir = edge / 4;
2076 if (getEdgeParity(cs[cind], edge) == 1) {
2077 flipParityAll(est, edir);
2080 dc_printf(
"Pushed: est: %d %d %d, edir: %d\n",
2099int Octree::floodFill(
Node *node,
int st[3],
int len,
int height,
int threshold)
2105 maxtotal = floodFill(&node->
leaf, st,
len, height, threshold);
2111 for (
i = 0;
i < 8;
i++) {
2119 maxtotal = std::max(d, maxtotal);
2128void Octree::writeOut()
2137 output_mesh = alloc_output(
numVertices, numQuads);
2139 int st[3] = {0, 0, 0};
2151void Octree::countIntersection(
Node *node,
int height,
int &nedge,
int &ncell,
int &nface)
2155 for (
int i = 0;
i < total;
i++) {
2160 nedge += getNumEdges2(&node->
leaf);
2162 int smask = getSignMask(&node->
leaf);
2169 if (smask > 0 && smask < 255) {
2174 for (
int i = 0;
i < 3;
i++) {
2175 if (getFaceEdgeNum(&node->
leaf,
i * 2)) {
2185 Eigen::JacobiSVD<Eigen::Matrix3f> svd = a.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
2188 Eigen::Vector3f((svd.singularValues().array().abs() > tolerance)
2189 .select(svd.singularValues().array().inverse(), 0))
2191 svd.matrixU().adjoint();
2196 const float midpoint[],
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];
2204 Eigen::Vector3f b2(
b), mp(midpoint),
result;
2208 for (
int i = 0;
i < 3;
i++) {
2213static void mass_point(
float mp[3],
const float pts[12][3],
const int parity[12])
2217 for (
int i = 0;
i < 12;
i++) {
2219 const float *p = pts[
i];
2239 const float pts[12][3],
2240 const float norms[12][3],
2241 const int parity[12])
2243 float ata[6] = {0, 0, 0, 0, 0, 0};
2244 float atb[3] = {0, 0, 0};
2247 for (
int i = 0;
i < 12;
i++) {
2250 const float *
norm = norms[
i];
2251 const float *p = pts[
i];
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]);
2261 const float pn = p[0] *
norm[0] + p[1] *
norm[1] + p[2] *
norm[2];
2263 atb[0] += (float)(
norm[0] * pn);
2264 atb[1] += (float)(
norm[1] * pn);
2265 atb[2] += (float)(
norm[2] * pn);
2287void Octree::computeMinimizer(
const LeafNode *leaf,
int st[3],
int len,
float rvalue[3])
const
2290 float pts[12][3], norms[12][3];
2292 fillEdgeIntersections(leaf, st,
len, pts, norms, parity);
2296 rvalue[0] = (float)st[0] +
len / 2;
2297 rvalue[1] = (float)st[1] +
len / 2;
2298 rvalue[2] = (float)st[2] +
len / 2;
2302 rvalue[0] = rvalue[1] = rvalue[2] = 0;
2310 float mp[3] = {0, 0, 0};
2311 minimize(rvalue, mp, pts, norms, parity);
2317 if (rvalue[0] < st[0] - nh1 || rvalue[1] < st[1] - nh1 || rvalue[2] < st[2] - nh1 ||
2319 rvalue[0] > st[0] + nh2 || rvalue[1] > st[1] + nh2 || rvalue[2] > st[2] + nh2)
2331void Octree::generateMinimizer(
Node *node,
int st[3],
int len,
int height,
int &offset)
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);
2347 for (j = 0; j < 3; j++) {
2352 int mult = 0, smask = getSignMask(&node->
leaf);
2358 if (smask > 0 && smask < 255) {
2363 for (j = 0; j <
mult; j++) {
2364 add_vert(output_mesh, rvalue);
2368 setMinimizerIndex(&node->
leaf, offset);
2376 for (
i = 0;
i < 8;
i++) {
2390void Octree::processEdgeWrite(
Node *node[4],
int [4],
int ,
int dir)
2399 if (getSign((LeafNode *)node[
i],
edgemap[edgeind][1]) > 0) {
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);
2414 if (vind[1] != -1) {
2418 ind[
num - 1] = vind[0];
2419 ind[
num - 2] = vind[1];
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]));
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]));
2442 add_quad(output_mesh, ind);
2451void Octree::edgeProcContour(
Node *node[4],
const int leaf[4],
int depth[4],
int maxdep,
int dir)
2453 if (!(node[0] && node[1] && node[2] && node[3])) {
2456 if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) {
2457 processEdgeWrite(node, depth, maxdep, dir);
2462 for (j = 0; j < 4; j++) {
2463 for (
i = 0;
i < 8;
i++) {
2474 for (
i = 0;
i < 2;
i++) {
2480 for (
int j = 0; j < 4; j++) {
2488 ne[j] = chd[j][c[j]];
2489 de[j] = depth[j] - 1;
2498void Octree::faceProcContour(
2499 Node *node[2],
const int leaf[2],
const int depth[2],
int maxdep,
int dir)
2501 if (!(node[0] && node[1])) {
2505 if (!(leaf[0] && leaf[1])) {
2509 for (j = 0; j < 2; j++) {
2510 for (
i = 0;
i < 8;
i++) {
2521 for (
i = 0;
i < 4;
i++) {
2523 for (
int j = 0; j < 2; j++) {
2531 nf[j] = chd[j][c[j]];
2532 df[j] = depth[j] - 1;
2539 int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}};
2544 for (
i = 0;
i < 4;
i++) {
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]];
2559 ne[j] = chd[order[j]][c[j]];
2560 de[j] = depth[order[j]] - 1;
2569void Octree::cellProcContour(
Node *node,
int leaf,
int depth)
2571 if (node ==
nullptr) {
2580 for (
i = 0;
i < 8;
i++) {
2587 for (
i = 0;
i < 8;
i++) {
2594 int df[2] = {depth - 1, depth - 1};
2595 for (
i = 0;
i < 12;
i++) {
2610 int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1};
2611 for (
i = 0;
i < 6;
i++) {
2617 for (
int j = 0; j < 4; j++) {
2627void Octree::processEdgeParity(
LeafNode *node[4],
const int [4],
int ,
int dir)
2630 for (
int i = 0;
i < 4;
i++) {
2642 for (
int i = 0;
i < 4;
i++) {
2648void Octree::edgeProcParity(
2649 Node *node[4],
const int leaf[4],
const int depth[4],
int maxdep,
int dir)
2651 if (!(node[0] && node[1] && node[2] && node[3])) {
2654 if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) {
2655 processEdgeParity((LeafNode **)node, depth, maxdep, dir);
2660 for (j = 0; j < 4; j++) {
2661 for (
i = 0;
i < 8;
i++) {
2672 for (
i = 0;
i < 2;
i++) {
2679 for (
int j = 0; j < 4; j++) {
2688 ne[j] = chd[j][c[j]];
2689 de[j] = depth[j] - 1;
2698void Octree::faceProcParity(
2699 Node *node[2],
const int leaf[2],
const int depth[2],
int maxdep,
int dir)
2701 if (!(node[0] && node[1])) {
2705 if (!(leaf[0] && leaf[1])) {
2709 for (j = 0; j < 2; j++) {
2710 for (
i = 0;
i < 8;
i++) {
2721 for (
i = 0;
i < 4;
i++) {
2723 for (
int j = 0; j < 2; j++) {
2731 nf[j] = chd[j][c[j]];
2732 df[j] = depth[j] - 1;
2739 int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}};
2744 for (
i = 0;
i < 4;
i++) {
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]];
2759 ne[j] = chd[order[j]][c[j]];
2760 de[j] = depth[order[j]] - 1;
2769void Octree::cellProcParity(
Node *node,
int leaf,
int depth)
2771 if (node ==
nullptr) {
2780 for (
i = 0;
i < 8;
i++) {
2787 for (
i = 0;
i < 8;
i++) {
2794 int df[2] = {depth - 1, depth - 1};
2795 for (
i = 0;
i < 12;
i++) {
2810 int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1};
2811 for (
i = 0;
i < 6;
i++) {
2817 for (
int j = 0; j < 4; j++) {
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}}};
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}}};
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}},
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}}};
ATTR_WARN_UNUSED_RESULT const size_t num
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
void shift(const int off[3])
int isIntersecting() const
int isIntersectingPrimary(int edgeInd) const
unsigned char getBoxMask()
TriangleProjection * inherit
Inheritable portion.
float getIntersectionPrimary(int edgeInd) const
void pushQueue(const int st[3], int dir)
int popQueue(int st[3], int &dir)
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)
VirtualMemoryAllocator * alloc[9]
VirtualMemoryAllocator * leafalloc[4]
void(* DualConAddQuad)(void *output, const int vert_indices[4])
void(* DualConAddVert)(void *output, const float co[3])
void *(* DualConAllocOutput)(int totvert, int totquad)
const ManifoldIndices manifold_table[256]
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
SymEdge< T > * prev(const SymEdge< T > *se)
const int processEdgeMask[3][4]
const int edgeProcEdgeMask[3][2][5]
static void pseudoInverse(const Eigen::Matrix3f &a, Eigen::Matrix3f &result, float tolerance)
const int faceProcFaceMask[3][4][3]
static void minimize(float rvalue[3], float mp[3], const float pts[12][3], const float norms[12][3], const int parity[12])
static void solve_least_squares(const float halfA[], const float b[], const float midpoint[], float rvalue[])
const int cellProcFaceMask[12][3]
const int faceProcEdgeMask[3][4][6]
const int cellProcEdgeMask[6][5]
static void mass_point(float mp[3], const float pts[12][3], const int parity[12])
const int dirCell[3][4][3]
const int processEdgeMask[3][4]
const int edgeProcEdgeMask[3][2][5]
const int faceProcFaceMask[3][4][3]
const int cellProcFaceMask[12][3]
const int faceProcEdgeMask[3][4][6]
const int cellProcEdgeMask[6][5]
Node * get_child(int count)
static int childrenCountTable[256][8]
static int numChildrenTable[256]
int has_child(int index) const
static int childrenIndexTable[256][8]
int get_num_children() const
void fill_children(Node *children[8], int leaf[8])
int is_child_leaf(int index) const
void set_child(int count, Node *chd)
int get_child_count(int index) const
double norm[3]
Normal of the triangle.