diff options
Diffstat (limited to 'intern/dualcon/intern/octree.cpp')
-rw-r--r-- | intern/dualcon/intern/octree.cpp | 4852 |
1 files changed, 2418 insertions, 2434 deletions
diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp index 878cd2971de..46783176fc1 100644 --- a/intern/dualcon/intern/octree.cpp +++ b/intern/dualcon/intern/octree.cpp @@ -34,2063 +34,2085 @@ #if DC_DEBUG /* enable debug printfs */ -#define dc_printf printf +# define dc_printf printf #else /* disable debug printfs */ -#define dc_printf(...) do {} while (0) +# define dc_printf(...) \ + do { \ + } while (0) #endif Octree::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) - : use_flood_fill(flags & DUALCON_FLOOD_FILL), - /* note on `use_manifold': - - After playing around with this option, the only case I could - find where this option gives different results is on - relatively thin corners. Sometimes along these corners two - vertices from separate sides will be placed in the same - position, so hole gets filled with a 5-sided face, where two - of those vertices are in the same 3D location. If - `use_manifold' is disabled, then the modifier doesn't - generate two separate vertices so the results end up as all - quads. - - Since the results are just as good with all quads, there - doesn't seem any reason to allow this to be toggled in - Blender. -nicholasbishop - */ - use_manifold(false), - hermite_num(sharpness), - mode(dualcon_mode), - alloc_output(alloc_output_func), - add_vert(add_vert_func), - add_quad(add_quad_func) + DualConFlags flags, + DualConMode dualcon_mode, + int depth, + float threshold, + float sharpness) + : use_flood_fill(flags & DUALCON_FLOOD_FILL), + /* note on `use_manifold': + + After playing around with this option, the only case I could + find where this option gives different results is on + relatively thin corners. Sometimes along these corners two + vertices from separate sides will be placed in the same + position, so hole gets filled with a 5-sided face, where two + of those vertices are in the same 3D location. If + `use_manifold' is disabled, then the modifier doesn't + generate two separate vertices so the results end up as all + quads. + + Since the results are just as good with all quads, there + doesn't seem any reason to allow this to be toggled in + Blender. -nicholasbishop + */ + use_manifold(false), + hermite_num(sharpness), + mode(dualcon_mode), + alloc_output(alloc_output_func), + add_vert(add_vert_func), + add_quad(add_quad_func) { - thresh = threshold; - reader = mr; - dimen = 1 << GRID_DIMENSION; - range = reader->getBoundingBox(origin); - nodeCount = nodeSpace = 0; - maxDepth = depth; - mindimen = (dimen >> maxDepth); - minshift = (GRID_DIMENSION - maxDepth); - buildTable(); - - maxTrianglePerCell = 0; - - // Initialize memory + thresh = threshold; + reader = mr; + dimen = 1 << GRID_DIMENSION; + range = reader->getBoundingBox(origin); + nodeCount = nodeSpace = 0; + maxDepth = depth; + mindimen = (dimen >> maxDepth); + minshift = (GRID_DIMENSION - maxDepth); + buildTable(); + + maxTrianglePerCell = 0; + + // Initialize memory #ifdef IN_VERBOSE_MODE - dc_printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2]); - dc_printf("Initialize memory...\n"); + dc_printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2]); + dc_printf("Initialize memory...\n"); #endif - initMemory(); - root = (Node *)createInternal(0); + initMemory(); + root = (Node *)createInternal(0); - // Read MC table + // Read MC table #ifdef IN_VERBOSE_MODE - dc_printf("Reading contour table...\n"); + dc_printf("Reading contour table...\n"); #endif - cubes = new Cubes(); - + cubes = new Cubes(); } Octree::~Octree() { - delete cubes; - freeMemory(); + delete cubes; + freeMemory(); } void Octree::scanConvert() { - // Scan triangles + // Scan triangles #if DC_DEBUG - clock_t start, finish; - start = clock(); + clock_t start, finish; + start = clock(); #endif - addAllTriangles(); - resetMinimalEdges(); - preparePrimalEdgesMask(&root->internal); + addAllTriangles(); + resetMinimalEdges(); + preparePrimalEdgesMask(&root->internal); #if DC_DEBUG - finish = clock(); - dc_printf("Time taken: %f seconds \n", - (double)(finish - start) / CLOCKS_PER_SEC); + finish = clock(); + dc_printf("Time taken: %f seconds \n", + (double)(finish - start) / CLOCKS_PER_SEC); #endif - // Generate signs - // Find holes + // Generate signs + // Find holes #if DC_DEBUG - dc_printf("Patching...\n"); - start = clock(); + dc_printf("Patching...\n"); + start = clock(); #endif - trace(); + trace(); #if DC_DEBUG - finish = clock(); - dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); -#ifdef IN_VERBOSE_MODE - dc_printf("Holes: %d Average Length: %f Max Length: %d \n", numRings, (float)totRingLengths / (float) numRings, maxRingLength); -#endif + finish = clock(); + dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); +# ifdef IN_VERBOSE_MODE + dc_printf("Holes: %d Average Length: %f Max Length: %d \n", + numRings, + (float)totRingLengths / (float)numRings, + maxRingLength); +# endif #endif - // Check again - int tnumRings = numRings; - trace(); + // Check again + int tnumRings = numRings; + trace(); #ifdef IN_VERBOSE_MODE - dc_printf("Holes after patching: %d \n", numRings); + dc_printf("Holes after patching: %d \n", numRings); #endif - numRings = tnumRings; + numRings = tnumRings; #if DC_DEBUG - dc_printf("Building signs...\n"); - start = clock(); + dc_printf("Building signs...\n"); + start = clock(); #endif - buildSigns(); + buildSigns(); #if DC_DEBUG - finish = clock(); - dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); + finish = clock(); + dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); #endif - if (use_flood_fill) { - /* - start = clock(); - floodFill(); - // Check again - tnumRings = numRings; - trace(); - dc_printf("Holes after filling: %d \n", numRings); - numRings = tnumRings; - buildSigns(); - finish = clock(); - dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); - */ + if (use_flood_fill) { + /* + start = clock(); + floodFill(); + // Check again + tnumRings = numRings; + trace(); + dc_printf("Holes after filling: %d \n", numRings); + numRings = tnumRings; + buildSigns(); + finish = clock(); + dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); + */ #if DC_DEBUG - start = clock(); - dc_printf("Removing components...\n"); + start = clock(); + dc_printf("Removing components...\n"); #endif - floodFill(); - buildSigns(); - // dc_printf("Checking...\n"); - // floodFill(); + floodFill(); + buildSigns(); + // dc_printf("Checking...\n"); + // floodFill(); #if DC_DEBUG - finish = clock(); - dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); + finish = clock(); + dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); #endif - } + } - // Output + // Output #if DC_DEBUG - start = clock(); + start = clock(); #endif - writeOut(); + writeOut(); #if DC_DEBUG - finish = clock(); + finish = clock(); #endif - // dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); + // dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC); - // Print info + // Print info #ifdef IN_VERBOSE_MODE - printMemUsage(); + printMemUsage(); #endif } void Octree::initMemory() { - leafalloc[0] = new MemoryAllocator<sizeof(LeafNode)>(); - leafalloc[1] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) *EDGE_FLOATS>(); - leafalloc[2] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) *EDGE_FLOATS * 2>(); - leafalloc[3] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) *EDGE_FLOATS * 3>(); - - alloc[0] = new MemoryAllocator<sizeof(InternalNode)>(); - alloc[1] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *)>(); - alloc[2] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 2>(); - alloc[3] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 3>(); - alloc[4] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 4>(); - alloc[5] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 5>(); - alloc[6] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 6>(); - alloc[7] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 7>(); - alloc[8] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 8>(); + leafalloc[0] = new MemoryAllocator<sizeof(LeafNode)>(); + leafalloc[1] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) * EDGE_FLOATS>(); + leafalloc[2] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) * EDGE_FLOATS * 2>(); + leafalloc[3] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) * EDGE_FLOATS * 3>(); + + alloc[0] = new MemoryAllocator<sizeof(InternalNode)>(); + alloc[1] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *)>(); + alloc[2] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 2>(); + alloc[3] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 3>(); + alloc[4] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 4>(); + alloc[5] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 5>(); + alloc[6] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 6>(); + alloc[7] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 7>(); + alloc[8] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 8>(); } void Octree::freeMemory() { - for (int i = 0; i < 9; i++) { - alloc[i]->destroy(); - delete alloc[i]; - } - - for (int i = 0; i < 4; i++) { - leafalloc[i]->destroy(); - delete leafalloc[i]; - } + for (int i = 0; i < 9; i++) { + alloc[i]->destroy(); + delete alloc[i]; + } + + for (int i = 0; i < 4; i++) { + leafalloc[i]->destroy(); + delete leafalloc[i]; + } } void Octree::printMemUsage() { - int totalbytes = 0; - dc_printf("********* Internal nodes: \n"); - for (int i = 0; i < 9; i++) { - alloc[i]->printInfo(); - - totalbytes += alloc[i]->getAll() * alloc[i]->getBytes(); - } - dc_printf("********* Leaf nodes: \n"); - int totalLeafs = 0; - for (int i = 0; i < 4; i++) { - leafalloc[i]->printInfo(); - - totalbytes += leafalloc[i]->getAll() * leafalloc[i]->getBytes(); - totalLeafs += leafalloc[i]->getAllocated(); - } - - dc_printf("Total allocated bytes on disk: %d \n", totalbytes); - dc_printf("Total leaf nodes: %d\n", totalLeafs); + int totalbytes = 0; + dc_printf("********* Internal nodes: \n"); + for (int i = 0; i < 9; i++) { + alloc[i]->printInfo(); + + totalbytes += alloc[i]->getAll() * alloc[i]->getBytes(); + } + dc_printf("********* Leaf nodes: \n"); + int totalLeafs = 0; + for (int i = 0; i < 4; i++) { + leafalloc[i]->printInfo(); + + totalbytes += leafalloc[i]->getAll() * leafalloc[i]->getBytes(); + totalLeafs += leafalloc[i]->getAllocated(); + } + + dc_printf("Total allocated bytes on disk: %d \n", totalbytes); + dc_printf("Total leaf nodes: %d\n", totalLeafs); } void Octree::resetMinimalEdges() { - cellProcParity(root, 0, maxDepth); + cellProcParity(root, 0, maxDepth); } void Octree::addAllTriangles() { - Triangle *trian; - int count = 0; + Triangle *trian; + int count = 0; #if DC_DEBUG - int total = reader->getNumTriangles(); - int unitcount = 1000; - dc_printf("\nScan converting to depth %d...\n", maxDepth); + int total = reader->getNumTriangles(); + int unitcount = 1000; + dc_printf("\nScan converting to depth %d...\n", maxDepth); #endif - srand(0); + srand(0); - while ((trian = reader->getNextTriangle()) != NULL) { - // Drop triangles - { - addTriangle(trian, count); - } - delete trian; + while ((trian = reader->getNextTriangle()) != NULL) { + // Drop triangles + { + addTriangle(trian, count); + } + delete trian; - count++; + count++; #if DC_DEBUG - if (count % unitcount == 0) { - putchar(13); - - switch ((count / unitcount) % 4) { - case 0: dc_printf("-"); - break; - case 1: dc_printf("/"); - break; - case 2: dc_printf("|"); - break; - case 3: dc_printf("\\"); - break; - } - - float percent = (float) count / total; - - /* - int totbars = 50; - int bars =(int)(percent * totbars); - for(int i = 0; i < bars; i ++) { - putchar(219); - } - for(i = bars; i < totbars; i ++) { - putchar(176); - } - */ - - dc_printf(" %d triangles: ", count); - dc_printf(" %f%% complete.", 100 * percent); - } + if (count % unitcount == 0) { + putchar(13); + + switch ((count / unitcount) % 4) { + case 0: + dc_printf("-"); + break; + case 1: + dc_printf("/"); + break; + case 2: + dc_printf("|"); + break; + case 3: + dc_printf("\\"); + break; + } + + float percent = (float)count / total; + + /* + int totbars = 50; + int bars =(int)(percent * totbars); + for(int i = 0; i < bars; i ++) { + putchar(219); + } + for(i = bars; i < totbars; i ++) { + putchar(176); + } + */ + + dc_printf(" %d triangles: ", count); + dc_printf(" %f%% complete.", 100 * percent); + } #endif - - } - putchar(13); + } + putchar(13); } /* Prepare a triangle for insertion into the octree; call the other addTriangle() to (recursively) build the octree */ void Octree::addTriangle(Triangle *trian, int triind) { - int i, j; - - /* Project the triangle's coordinates into the grid */ - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) - trian->vt[i][j] = dimen * (trian->vt[i][j] - origin[j]) / range; - } - - /* Generate projections */ - int64_t cube[2][3] = {{0, 0, 0}, {dimen, dimen, dimen}}; - int64_t trig[3][3]; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) - trig[i][j] = (int64_t)(trian->vt[i][j]); - } - - /* Add triangle to the octree */ - int64_t errorvec = (int64_t)(0); - CubeTriangleIsect *proj = new CubeTriangleIsect(cube, trig, errorvec, triind); - root = (Node *)addTriangle(&root->internal, proj, maxDepth); - - delete proj->inherit; - delete proj; + int i, j; + + /* Project the triangle's coordinates into the grid */ + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) + trian->vt[i][j] = dimen * (trian->vt[i][j] - origin[j]) / range; + } + + /* Generate projections */ + int64_t cube[2][3] = {{0, 0, 0}, {dimen, dimen, dimen}}; + int64_t trig[3][3]; + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) + trig[i][j] = (int64_t)(trian->vt[i][j]); + } + + /* Add triangle to the octree */ + int64_t errorvec = (int64_t)(0); + CubeTriangleIsect *proj = new CubeTriangleIsect(cube, trig, errorvec, triind); + root = (Node *)addTriangle(&root->internal, proj, maxDepth); + + delete proj->inherit; + delete proj; } #if 0 static void print_depth(int height, int maxDepth) { - for (int i = 0; i < maxDepth - height; i++) - printf(" "); + for (int i = 0; i < maxDepth - height; i++) + printf(" "); } #endif InternalNode *Octree::addTriangle(InternalNode *node, CubeTriangleIsect *p, int height) { - int i; - const int vertdiff[8][3] = { - {0, 0, 0}, - {0, 0, 1}, - {0, 1, -1}, - {0, 0, 1}, - {1, -1, -1}, - {0, 0, 1}, - {0, 1, -1}, - {0, 0, 1}}; - unsigned char boxmask = p->getBoxMask(); - CubeTriangleIsect *subp = new CubeTriangleIsect(p); - - int count = 0; - int tempdiff[3] = {0, 0, 0}; - - /* Check triangle against each of the input node's children */ - for (i = 0; i < 8; i++) { - tempdiff[0] += vertdiff[i][0]; - tempdiff[1] += vertdiff[i][1]; - tempdiff[2] += vertdiff[i][2]; - - /* Quick pruning using bounding box */ - if (boxmask & (1 << i)) { - subp->shift(tempdiff); - tempdiff[0] = tempdiff[1] = tempdiff[2] = 0; - - /* Pruning using intersection test */ - if (subp->isIntersecting()) { - if (!node->has_child(i)) { - if (height == 1) - node = addLeafChild(node, i, count, createLeaf(0)); - else - node = addInternalChild(node, i, count, createInternal(0)); - } - Node *chd = node->get_child(count); - - if (node->is_child_leaf(i)) - node->set_child(count, (Node *)updateCell(&chd->leaf, subp)); - else - node->set_child(count, (Node *)addTriangle(&chd->internal, subp, height - 1)); - } - } - - if (node->has_child(i)) - count++; - } - - delete subp; - - return node; + int i; + const int vertdiff[8][3] = { + {0, 0, 0}, {0, 0, 1}, {0, 1, -1}, {0, 0, 1}, {1, -1, -1}, {0, 0, 1}, {0, 1, -1}, {0, 0, 1}}; + unsigned char boxmask = p->getBoxMask(); + CubeTriangleIsect *subp = new CubeTriangleIsect(p); + + int count = 0; + int tempdiff[3] = {0, 0, 0}; + + /* Check triangle against each of the input node's children */ + for (i = 0; i < 8; i++) { + tempdiff[0] += vertdiff[i][0]; + tempdiff[1] += vertdiff[i][1]; + tempdiff[2] += vertdiff[i][2]; + + /* Quick pruning using bounding box */ + if (boxmask & (1 << i)) { + subp->shift(tempdiff); + tempdiff[0] = tempdiff[1] = tempdiff[2] = 0; + + /* Pruning using intersection test */ + if (subp->isIntersecting()) { + if (!node->has_child(i)) { + if (height == 1) + node = addLeafChild(node, i, count, createLeaf(0)); + else + node = addInternalChild(node, i, count, createInternal(0)); + } + Node *chd = node->get_child(count); + + if (node->is_child_leaf(i)) + node->set_child(count, (Node *)updateCell(&chd->leaf, subp)); + else + node->set_child(count, (Node *)addTriangle(&chd->internal, subp, height - 1)); + } + } + + if (node->has_child(i)) + count++; + } + + delete subp; + + return node; } LeafNode *Octree::updateCell(LeafNode *node, CubeTriangleIsect *p) { - int i; - - // Edge connectivity - int mask[3] = {0, 4, 8 }; - int oldc = 0, newc = 0; - float offs[3]; - float a[3], b[3], c[3]; - - for (i = 0; i < 3; i++) { - if (!getEdgeParity(node, mask[i])) { - if (p->isIntersectingPrimary(i)) { - // actualQuads ++; - setEdge(node, mask[i]); - offs[newc] = p->getIntersectionPrimary(i); - a[newc] = (float) p->inherit->norm[0]; - b[newc] = (float) p->inherit->norm[1]; - c[newc] = (float) p->inherit->norm[2]; - newc++; - } - } - else { - offs[newc] = getEdgeOffsetNormal(node, oldc, a[newc], b[newc], c[newc]); - - oldc++; - newc++; - } - } - - if (newc > oldc) { - // New offsets added, update this node - node = updateEdgeOffsetsNormals(node, oldc, newc, offs, a, b, c); - } - - return node; + int i; + + // Edge connectivity + int mask[3] = {0, 4, 8}; + int oldc = 0, newc = 0; + float offs[3]; + float a[3], b[3], c[3]; + + for (i = 0; i < 3; i++) { + if (!getEdgeParity(node, mask[i])) { + if (p->isIntersectingPrimary(i)) { + // actualQuads ++; + setEdge(node, mask[i]); + offs[newc] = p->getIntersectionPrimary(i); + a[newc] = (float)p->inherit->norm[0]; + b[newc] = (float)p->inherit->norm[1]; + c[newc] = (float)p->inherit->norm[2]; + newc++; + } + } + else { + offs[newc] = getEdgeOffsetNormal(node, oldc, a[newc], b[newc], c[newc]); + + oldc++; + newc++; + } + } + + if (newc > oldc) { + // New offsets added, update this node + node = updateEdgeOffsetsNormals(node, oldc, newc, offs, a, b, c); + } + + return node; } void Octree::preparePrimalEdgesMask(InternalNode *node) { - int count = 0; - for (int i = 0; i < 8; i++) { - if (node->has_child(i)) { - if (node->is_child_leaf(i)) - createPrimalEdgesMask(&node->get_child(count)->leaf); - else - preparePrimalEdgesMask(&node->get_child(count)->internal); - - count++; - } - } + int count = 0; + for (int i = 0; i < 8; i++) { + if (node->has_child(i)) { + if (node->is_child_leaf(i)) + createPrimalEdgesMask(&node->get_child(count)->leaf); + else + preparePrimalEdgesMask(&node->get_child(count)->internal); + + count++; + } + } } void Octree::trace() { - int st[3] = {0, 0, 0, }; - numRings = 0; - totRingLengths = 0; - maxRingLength = 0; - - PathList *chdpath = NULL; - root = trace(root, st, dimen, maxDepth, chdpath); - - if (chdpath != NULL) { - dc_printf("there are incomplete rings.\n"); - printPaths(chdpath); - }; + int st[3] = { + 0, + 0, + 0, + }; + numRings = 0; + totRingLengths = 0; + maxRingLength = 0; + + PathList *chdpath = NULL; + root = trace(root, st, dimen, maxDepth, chdpath); + + if (chdpath != NULL) { + dc_printf("there are incomplete rings.\n"); + printPaths(chdpath); + }; } -Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *& paths) +Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *&paths) { - len >>= 1; - PathList *chdpaths[8]; - Node *chd[8]; - int nst[8][3]; - int i, j; - - // Get children paths - int chdleaf[8]; - newnode->internal.fill_children(chd, chdleaf); - - // int count = 0; - for (i = 0; i < 8; i++) { - for (j = 0; j < 3; j++) { - nst[i][j] = st[j] + len * vertmap[i][j]; - } - - if (chd[i] == NULL || newnode->internal.is_child_leaf(i)) { - chdpaths[i] = NULL; - } - else { - trace(chd[i], nst[i], len, depth - 1, chdpaths[i]); - } - } - - // Get connectors on the faces - PathList *conn[12]; - Node *nf[2]; - int lf[2]; - int df[2] = {depth - 1, depth - 1}; - int *nstf[2]; - - newnode->internal.fill_children(chd, chdleaf); - - for (i = 0; i < 12; i++) { - int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]}; - - for (int j = 0; j < 2; j++) { - lf[j] = chdleaf[c[j]]; - nf[j] = chd[c[j]]; - nstf[j] = nst[c[j]]; - } - - conn[i] = NULL; - - findPaths((Node **)nf, lf, df, nstf, depth - 1, cellProcFaceMask[i][2], conn[i]); - - //if(conn[i]) { - // printPath(conn[i]); - //} - } - - // Connect paths - PathList *rings = NULL; - combinePaths(chdpaths[0], chdpaths[1], conn[8], rings); - combinePaths(chdpaths[2], chdpaths[3], conn[9], rings); - combinePaths(chdpaths[4], chdpaths[5], conn[10], rings); - combinePaths(chdpaths[6], chdpaths[7], conn[11], rings); - - combinePaths(chdpaths[0], chdpaths[2], conn[4], rings); - combinePaths(chdpaths[4], chdpaths[6], conn[5], rings); - combinePaths(chdpaths[0], NULL, conn[6], rings); - combinePaths(chdpaths[4], NULL, conn[7], rings); - - combinePaths(chdpaths[0], chdpaths[4], conn[0], rings); - combinePaths(chdpaths[0], NULL, conn[1], rings); - combinePaths(chdpaths[0], NULL, conn[2], rings); - combinePaths(chdpaths[0], NULL, conn[3], rings); - - // By now, only chdpaths[0] and rings have contents - - // Process rings - if (rings) { - // printPath(rings); - - /* Let's count first */ - PathList *trings = rings; - while (trings) { - numRings++; - totRingLengths += trings->length; - if (trings->length > maxRingLength) { - maxRingLength = trings->length; - } - trings = trings->next; - } - - // printPath(rings); - newnode = patch(newnode, st, (len << 1), rings); - } - - // Return incomplete paths - paths = chdpaths[0]; - return newnode; + len >>= 1; + PathList *chdpaths[8]; + Node *chd[8]; + int nst[8][3]; + int i, j; + + // Get children paths + int chdleaf[8]; + newnode->internal.fill_children(chd, chdleaf); + + // int count = 0; + for (i = 0; i < 8; i++) { + for (j = 0; j < 3; j++) { + nst[i][j] = st[j] + len * vertmap[i][j]; + } + + if (chd[i] == NULL || newnode->internal.is_child_leaf(i)) { + chdpaths[i] = NULL; + } + else { + trace(chd[i], nst[i], len, depth - 1, chdpaths[i]); + } + } + + // Get connectors on the faces + PathList *conn[12]; + Node *nf[2]; + int lf[2]; + int df[2] = {depth - 1, depth - 1}; + int *nstf[2]; + + newnode->internal.fill_children(chd, chdleaf); + + for (i = 0; i < 12; i++) { + int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]}; + + for (int j = 0; j < 2; j++) { + lf[j] = chdleaf[c[j]]; + nf[j] = chd[c[j]]; + nstf[j] = nst[c[j]]; + } + + conn[i] = NULL; + + findPaths((Node **)nf, lf, df, nstf, depth - 1, cellProcFaceMask[i][2], conn[i]); + + //if(conn[i]) { + // printPath(conn[i]); + //} + } + + // Connect paths + PathList *rings = NULL; + combinePaths(chdpaths[0], chdpaths[1], conn[8], rings); + combinePaths(chdpaths[2], chdpaths[3], conn[9], rings); + combinePaths(chdpaths[4], chdpaths[5], conn[10], rings); + combinePaths(chdpaths[6], chdpaths[7], conn[11], rings); + + combinePaths(chdpaths[0], chdpaths[2], conn[4], rings); + combinePaths(chdpaths[4], chdpaths[6], conn[5], rings); + combinePaths(chdpaths[0], NULL, conn[6], rings); + combinePaths(chdpaths[4], NULL, conn[7], rings); + + combinePaths(chdpaths[0], chdpaths[4], conn[0], rings); + combinePaths(chdpaths[0], NULL, conn[1], rings); + combinePaths(chdpaths[0], NULL, conn[2], rings); + combinePaths(chdpaths[0], NULL, conn[3], rings); + + // By now, only chdpaths[0] and rings have contents + + // Process rings + if (rings) { + // printPath(rings); + + /* Let's count first */ + PathList *trings = rings; + while (trings) { + numRings++; + totRingLengths += trings->length; + if (trings->length > maxRingLength) { + maxRingLength = trings->length; + } + trings = trings->next; + } + + // printPath(rings); + newnode = patch(newnode, st, (len << 1), rings); + } + + // Return incomplete paths + paths = chdpaths[0]; + return newnode; } -void Octree::findPaths(Node *node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList *& paths) +void Octree::findPaths( + Node *node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList *&paths) { - if (!(node[0] && node[1])) { - return; - } - - if (!(leaf[0] && leaf[1])) { - // Not at the bottom, recur - - // Fill children nodes - int i, j; - Node *chd[2][8]; - int chdleaf[2][8]; - int nst[2][8][3]; - - for (j = 0; j < 2; j++) { - if (!leaf[j]) { - node[j]->internal.fill_children(chd[j], chdleaf[j]); - - int len = (dimen >> (maxDepth - depth[j] + 1)); - for (i = 0; i < 8; i++) { - for (int k = 0; k < 3; k++) { - nst[j][i][k] = st[j][k] + len * vertmap[i][k]; - } - } - - } - } - - // 4 face calls - Node *nf[2]; - int df[2]; - int lf[2]; - int *nstf[2]; - for (i = 0; i < 4; i++) { - int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]}; - for (int j = 0; j < 2; j++) { - if (leaf[j]) { - lf[j] = leaf[j]; - nf[j] = node[j]; - df[j] = depth[j]; - nstf[j] = st[j]; - } - else { - lf[j] = chdleaf[j][c[j]]; - nf[j] = chd[j][c[j]]; - df[j] = depth[j] - 1; - nstf[j] = nst[j][c[j]]; - } - } - findPaths(nf, lf, df, nstf, maxdep - 1, faceProcFaceMask[dir][i][2], paths); - } - - } - else { - // At the bottom, check this face - int ind = (depth[0] == maxdep ? 0 : 1); - int fcind = 2 * dir + (1 - ind); - if (getFaceParity((LeafNode *)node[ind], fcind)) { - // Add into path - PathElement *ele1 = new PathElement; - PathElement *ele2 = new PathElement; - - ele1->pos[0] = st[0][0]; - ele1->pos[1] = st[0][1]; - ele1->pos[2] = st[0][2]; - - ele2->pos[0] = st[1][0]; - ele2->pos[1] = st[1][1]; - ele2->pos[2] = st[1][2]; - - ele1->next = ele2; - ele2->next = NULL; - - PathList *lst = new PathList; - lst->head = ele1; - lst->tail = ele2; - lst->length = 2; - lst->next = paths; - paths = lst; - - // int l =(dimen >> maxDepth); - } - } - + if (!(node[0] && node[1])) { + return; + } + + if (!(leaf[0] && leaf[1])) { + // Not at the bottom, recur + + // Fill children nodes + int i, j; + Node *chd[2][8]; + int chdleaf[2][8]; + int nst[2][8][3]; + + for (j = 0; j < 2; j++) { + if (!leaf[j]) { + node[j]->internal.fill_children(chd[j], chdleaf[j]); + + int len = (dimen >> (maxDepth - depth[j] + 1)); + for (i = 0; i < 8; i++) { + for (int k = 0; k < 3; k++) { + nst[j][i][k] = st[j][k] + len * vertmap[i][k]; + } + } + } + } + + // 4 face calls + Node *nf[2]; + int df[2]; + int lf[2]; + int *nstf[2]; + for (i = 0; i < 4; i++) { + int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]}; + for (int j = 0; j < 2; j++) { + if (leaf[j]) { + lf[j] = leaf[j]; + nf[j] = node[j]; + df[j] = depth[j]; + nstf[j] = st[j]; + } + else { + lf[j] = chdleaf[j][c[j]]; + nf[j] = chd[j][c[j]]; + df[j] = depth[j] - 1; + nstf[j] = nst[j][c[j]]; + } + } + findPaths(nf, lf, df, nstf, maxdep - 1, faceProcFaceMask[dir][i][2], paths); + } + } + else { + // At the bottom, check this face + int ind = (depth[0] == maxdep ? 0 : 1); + int fcind = 2 * dir + (1 - ind); + if (getFaceParity((LeafNode *)node[ind], fcind)) { + // Add into path + PathElement *ele1 = new PathElement; + PathElement *ele2 = new PathElement; + + ele1->pos[0] = st[0][0]; + ele1->pos[1] = st[0][1]; + ele1->pos[2] = st[0][2]; + + ele2->pos[0] = st[1][0]; + ele2->pos[1] = st[1][1]; + ele2->pos[2] = st[1][2]; + + ele1->next = ele2; + ele2->next = NULL; + + PathList *lst = new PathList; + lst->head = ele1; + lst->tail = ele2; + lst->length = 2; + lst->next = paths; + paths = lst; + + // int l =(dimen >> maxDepth); + } + } } -void Octree::combinePaths(PathList *& list1, PathList *list2, PathList *paths, PathList *& rings) +void Octree::combinePaths(PathList *&list1, PathList *list2, PathList *paths, PathList *&rings) { - // Make new list of paths - PathList *nlist = NULL; - - // Search for each connectors in paths - PathList *tpaths = paths; - PathList *tlist, *pre; - while (tpaths) { - PathList *singlist = tpaths; - PathList *templist; - tpaths = tpaths->next; - singlist->next = NULL; - - // Look for hookup in list1 - tlist = list1; - pre = NULL; - while (tlist) { - if ((templist = combineSinglePath(list1, pre, tlist, singlist, NULL, singlist)) != NULL) { - singlist = templist; - continue; - } - pre = tlist; - tlist = tlist->next; - } - - // Look for hookup in list2 - tlist = list2; - pre = NULL; - while (tlist) { - if ((templist = combineSinglePath(list2, pre, tlist, singlist, NULL, singlist)) != NULL) { - singlist = templist; - continue; - } - pre = tlist; - tlist = tlist->next; - } - - // Look for hookup in nlist - tlist = nlist; - pre = NULL; - while (tlist) { - if ((templist = combineSinglePath(nlist, pre, tlist, singlist, NULL, singlist)) != NULL) { - singlist = templist; - continue; - } - pre = tlist; - tlist = tlist->next; - } - - // Add to nlist or rings - if (isEqual(singlist->head, singlist->tail)) { - PathElement *temp = singlist->head; - singlist->head = temp->next; - delete temp; - singlist->length--; - singlist->tail->next = singlist->head; - - singlist->next = rings; - rings = singlist; - } - else { - singlist->next = nlist; - nlist = singlist; - } - - } - - // Append list2 and nlist to the end of list1 - tlist = list1; - if (tlist != NULL) { - while (tlist->next != NULL) { - tlist = tlist->next; - } - tlist->next = list2; - } - else { - tlist = list2; - list1 = list2; - } - - if (tlist != NULL) { - while (tlist->next != NULL) { - tlist = tlist->next; - } - tlist->next = nlist; - } - else { - tlist = nlist; - list1 = nlist; - } - + // Make new list of paths + PathList *nlist = NULL; + + // Search for each connectors in paths + PathList *tpaths = paths; + PathList *tlist, *pre; + while (tpaths) { + PathList *singlist = tpaths; + PathList *templist; + tpaths = tpaths->next; + singlist->next = NULL; + + // Look for hookup in list1 + tlist = list1; + pre = NULL; + while (tlist) { + if ((templist = combineSinglePath(list1, pre, tlist, singlist, NULL, singlist)) != NULL) { + singlist = templist; + continue; + } + pre = tlist; + tlist = tlist->next; + } + + // Look for hookup in list2 + tlist = list2; + pre = NULL; + while (tlist) { + if ((templist = combineSinglePath(list2, pre, tlist, singlist, NULL, singlist)) != NULL) { + singlist = templist; + continue; + } + pre = tlist; + tlist = tlist->next; + } + + // Look for hookup in nlist + tlist = nlist; + pre = NULL; + while (tlist) { + if ((templist = combineSinglePath(nlist, pre, tlist, singlist, NULL, singlist)) != NULL) { + singlist = templist; + continue; + } + pre = tlist; + tlist = tlist->next; + } + + // Add to nlist or rings + if (isEqual(singlist->head, singlist->tail)) { + PathElement *temp = singlist->head; + singlist->head = temp->next; + delete temp; + singlist->length--; + singlist->tail->next = singlist->head; + + singlist->next = rings; + rings = singlist; + } + else { + singlist->next = nlist; + nlist = singlist; + } + } + + // Append list2 and nlist to the end of list1 + tlist = list1; + if (tlist != NULL) { + while (tlist->next != NULL) { + tlist = tlist->next; + } + tlist->next = list2; + } + else { + tlist = list2; + list1 = list2; + } + + if (tlist != NULL) { + while (tlist->next != NULL) { + tlist = tlist->next; + } + tlist->next = nlist; + } + else { + tlist = nlist; + list1 = nlist; + } } -PathList *Octree::combineSinglePath(PathList *& head1, PathList *pre1, PathList *& list1, PathList *& head2, PathList *pre2, PathList *& list2) +PathList *Octree::combineSinglePath(PathList *&head1, + PathList *pre1, + PathList *&list1, + PathList *&head2, + PathList *pre2, + PathList *&list2) { - if (isEqual(list1->head, list2->head) || isEqual(list1->tail, list2->tail)) { - // Reverse the list - if (list1->length < list2->length) { - // Reverse list1 - PathElement *prev = list1->head; - PathElement *next = prev->next; - prev->next = NULL; - while (next != NULL) { - PathElement *tnext = next->next; - next->next = prev; - - prev = next; - next = tnext; - } - - list1->tail = list1->head; - list1->head = prev; - } - else { - // Reverse list2 - PathElement *prev = list2->head; - PathElement *next = prev->next; - prev->next = NULL; - while (next != NULL) { - PathElement *tnext = next->next; - next->next = prev; - - prev = next; - next = tnext; - } - - list2->tail = list2->head; - list2->head = prev; - } - } - - if (isEqual(list1->head, list2->tail)) { - - // Easy case - PathElement *temp = list1->head->next; - delete list1->head; - list2->tail->next = temp; - - PathList *nlist = new PathList; - nlist->length = list1->length + list2->length - 1; - nlist->head = list2->head; - nlist->tail = list1->tail; - nlist->next = NULL; - - deletePath(head1, pre1, list1); - deletePath(head2, pre2, list2); - - return nlist; - } - else if (isEqual(list1->tail, list2->head)) { - // Easy case - PathElement *temp = list2->head->next; - delete list2->head; - list1->tail->next = temp; - - PathList *nlist = new PathList; - nlist->length = list1->length + list2->length - 1; - nlist->head = list1->head; - nlist->tail = list2->tail; - nlist->next = NULL; - - deletePath(head1, pre1, list1); - deletePath(head2, pre2, list2); - - return nlist; - } - - return NULL; + if (isEqual(list1->head, list2->head) || isEqual(list1->tail, list2->tail)) { + // Reverse the list + if (list1->length < list2->length) { + // Reverse list1 + PathElement *prev = list1->head; + PathElement *next = prev->next; + prev->next = NULL; + while (next != NULL) { + PathElement *tnext = next->next; + next->next = prev; + + prev = next; + next = tnext; + } + + list1->tail = list1->head; + list1->head = prev; + } + else { + // Reverse list2 + PathElement *prev = list2->head; + PathElement *next = prev->next; + prev->next = NULL; + while (next != NULL) { + PathElement *tnext = next->next; + next->next = prev; + + prev = next; + next = tnext; + } + + list2->tail = list2->head; + list2->head = prev; + } + } + + if (isEqual(list1->head, list2->tail)) { + + // Easy case + PathElement *temp = list1->head->next; + delete list1->head; + list2->tail->next = temp; + + PathList *nlist = new PathList; + nlist->length = list1->length + list2->length - 1; + nlist->head = list2->head; + nlist->tail = list1->tail; + nlist->next = NULL; + + deletePath(head1, pre1, list1); + deletePath(head2, pre2, list2); + + return nlist; + } + else if (isEqual(list1->tail, list2->head)) { + // Easy case + PathElement *temp = list2->head->next; + delete list2->head; + list1->tail->next = temp; + + PathList *nlist = new PathList; + nlist->length = list1->length + list2->length - 1; + nlist->head = list1->head; + nlist->tail = list2->tail; + nlist->next = NULL; + + deletePath(head1, pre1, list1); + deletePath(head2, pre2, list2); + + return nlist; + } + + return NULL; } -void Octree::deletePath(PathList *& head, PathList *pre, PathList *& curr) +void Octree::deletePath(PathList *&head, PathList *pre, PathList *&curr) { - PathList *temp = curr; - curr = temp->next; - delete temp; - - if (pre == NULL) { - head = curr; - } - else { - pre->next = curr; - } + PathList *temp = curr; + curr = temp->next; + delete temp; + + if (pre == NULL) { + head = curr; + } + else { + pre->next = curr; + } } void Octree::printElement(PathElement *ele) { - if (ele != NULL) { - dc_printf("(%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2]); - } + if (ele != NULL) { + dc_printf("(%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2]); + } } void Octree::printPath(PathList *path) { - PathElement *n = path->head; - int same = 0; + PathElement *n = path->head; + int same = 0; #if DC_DEBUG - int len = (dimen >> maxDepth); + int len = (dimen >> maxDepth); #endif - while (n && (same == 0 || n != path->head)) { - same++; - dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len); - n = n->next; - } - - if (n == path->head) { - dc_printf(" Ring!\n"); - } - else { - dc_printf(" %p end!\n", n); - } + while (n && (same == 0 || n != path->head)) { + same++; + dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len); + n = n->next; + } + + if (n == path->head) { + dc_printf(" Ring!\n"); + } + else { + dc_printf(" %p end!\n", n); + } } void Octree::printPath(PathElement *path) { - PathElement *n = path; - int same = 0; + PathElement *n = path; + int same = 0; #if DC_DEBUG - int len = (dimen >> maxDepth); + int len = (dimen >> maxDepth); #endif - while (n && (same == 0 || n != path)) { - same++; - dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len); - n = n->next; - } - - if (n == path) { - dc_printf(" Ring!\n"); - } - else { - dc_printf(" %p end!\n", n); - } - + while (n && (same == 0 || n != path)) { + same++; + dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len); + n = n->next; + } + + if (n == path) { + dc_printf(" Ring!\n"); + } + else { + dc_printf(" %p end!\n", n); + } } - void Octree::printPaths(PathList *path) { - PathList *iter = path; - int i = 0; - while (iter != NULL) { - dc_printf("Path %d:\n", i); - printPath(iter); - iter = iter->next; - i++; - } + PathList *iter = path; + int i = 0; + while (iter != NULL) { + dc_printf("Path %d:\n", i); + printPath(iter); + iter = iter->next; + i++; + } } Node *Octree::patch(Node *newnode, int st[3], int len, PathList *rings) { #ifdef IN_DEBUG_MODE - dc_printf("Call to PATCH with rings: \n"); - printPaths(rings); + dc_printf("Call to PATCH with rings: \n"); + printPaths(rings); #endif - /* Do nothing but couting - PathList* tlist = rings; - PathList* ttlist; - PathElement* telem, * ttelem; - while(tlist!= NULL) { - // printPath(tlist); - numRings ++; - totRingLengths += tlist->length; - if(tlist->length > maxRingLength) { - maxRingLength = tlist->length; - } - ttlist = tlist; - tlist = tlist->next; - } - return node; - */ - - - /* Pass onto separate calls in each direction */ - if (len == mindimen) { - dc_printf("Error! should have no list by now.\n"); - exit(0); - } - - // YZ plane - PathList *xlists[2]; - newnode = patchSplit(newnode, st, len, rings, 0, xlists[0], xlists[1]); - - // XZ plane - PathList *ylists[4]; - newnode = patchSplit(newnode, st, len, xlists[0], 1, ylists[0], ylists[1]); - newnode = patchSplit(newnode, st, len, xlists[1], 1, ylists[2], ylists[3]); - - // XY plane - PathList *zlists[8]; - newnode = patchSplit(newnode, st, len, ylists[0], 2, zlists[0], zlists[1]); - newnode = patchSplit(newnode, st, len, ylists[1], 2, zlists[2], zlists[3]); - newnode = patchSplit(newnode, st, len, ylists[2], 2, zlists[4], zlists[5]); - newnode = patchSplit(newnode, st, len, ylists[3], 2, zlists[6], zlists[7]); - - // Recur - len >>= 1; - int count = 0; - for (int i = 0; i < 8; i++) { - if (zlists[i] != NULL) { - int nori[3] = { - st[0] + len * vertmap[i][0], - st[1] + len * vertmap[i][1], - st[2] + len * vertmap[i][2] - }; - patch(newnode->internal.get_child(count), nori, len, zlists[i]); - } - - if (newnode->internal.has_child(i)) { - count++; - } - } + /* Do nothing but couting + PathList* tlist = rings; + PathList* ttlist; + PathElement* telem, * ttelem; + while(tlist!= NULL) { + // printPath(tlist); + numRings ++; + totRingLengths += tlist->length; + if(tlist->length > maxRingLength) { + maxRingLength = tlist->length; + } + ttlist = tlist; + tlist = tlist->next; + } + return node; + */ + + /* Pass onto separate calls in each direction */ + if (len == mindimen) { + dc_printf("Error! should have no list by now.\n"); + exit(0); + } + + // YZ plane + PathList *xlists[2]; + newnode = patchSplit(newnode, st, len, rings, 0, xlists[0], xlists[1]); + + // XZ plane + PathList *ylists[4]; + newnode = patchSplit(newnode, st, len, xlists[0], 1, ylists[0], ylists[1]); + newnode = patchSplit(newnode, st, len, xlists[1], 1, ylists[2], ylists[3]); + + // XY plane + PathList *zlists[8]; + newnode = patchSplit(newnode, st, len, ylists[0], 2, zlists[0], zlists[1]); + newnode = patchSplit(newnode, st, len, ylists[1], 2, zlists[2], zlists[3]); + newnode = patchSplit(newnode, st, len, ylists[2], 2, zlists[4], zlists[5]); + newnode = patchSplit(newnode, st, len, ylists[3], 2, zlists[6], zlists[7]); + + // Recur + len >>= 1; + int count = 0; + for (int i = 0; i < 8; i++) { + if (zlists[i] != NULL) { + int nori[3] = { + st[0] + len * vertmap[i][0], st[1] + len * vertmap[i][1], st[2] + len * vertmap[i][2]}; + patch(newnode->internal.get_child(count), nori, len, zlists[i]); + } + + if (newnode->internal.has_child(i)) { + count++; + } + } #ifdef IN_DEBUG_MODE - dc_printf("Return from PATCH\n"); + dc_printf("Return from PATCH\n"); #endif - return newnode; - + return newnode; } - -Node *Octree::patchSplit(Node *newnode, int st[3], int len, PathList *rings, - int dir, PathList *& nrings1, PathList *& nrings2) +Node *Octree::patchSplit(Node *newnode, + int st[3], + int len, + PathList *rings, + int dir, + PathList *&nrings1, + PathList *&nrings2) { #ifdef IN_DEBUG_MODE - dc_printf("Call to PATCHSPLIT with direction %d and rings: \n", dir); - printPaths(rings); + dc_printf("Call to PATCHSPLIT with direction %d and rings: \n", dir); + printPaths(rings); #endif - nrings1 = NULL; - nrings2 = NULL; - PathList *tmp; - while (rings != NULL) { - // Process this ring - newnode = patchSplitSingle(newnode, st, len, rings->head, dir, nrings1, nrings2); + nrings1 = NULL; + nrings2 = NULL; + PathList *tmp; + while (rings != NULL) { + // Process this ring + newnode = patchSplitSingle(newnode, st, len, rings->head, dir, nrings1, nrings2); - // Delete this ring from the group - tmp = rings; - rings = rings->next; - delete tmp; - } + // Delete this ring from the group + tmp = rings; + rings = rings->next; + delete tmp; + } #ifdef IN_DEBUG_MODE - dc_printf("Return from PATCHSPLIT with \n"); - dc_printf("Rings gourp 1:\n"); - printPaths(nrings1); - dc_printf("Rings group 2:\n"); - printPaths(nrings2); + dc_printf("Return from PATCHSPLIT with \n"); + dc_printf("Rings gourp 1:\n"); + printPaths(nrings1); + dc_printf("Rings group 2:\n"); + printPaths(nrings2); #endif - return newnode; + return newnode; } -Node *Octree::patchSplitSingle(Node *newnode, int st[3], int len, PathElement *head, int dir, PathList *& nrings1, PathList *& nrings2) +Node *Octree::patchSplitSingle(Node *newnode, + int st[3], + int len, + PathElement *head, + int dir, + PathList *&nrings1, + PathList *&nrings2) { #ifdef IN_DEBUG_MODE - dc_printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir); - printPath(head); + dc_printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir); + printPath(head); #endif - if (head == NULL) { + if (head == NULL) { #ifdef IN_DEBUG_MODE - dc_printf("Return from PATCHSPLITSINGLE with head==NULL.\n"); + dc_printf("Return from PATCHSPLITSINGLE with head==NULL.\n"); #endif - return newnode; - } - else { - // printPath(head); - } - - // Walk along the ring to find pair of intersections - PathElement *pre1 = NULL; - PathElement *pre2 = NULL; - int side = findPair(head, st[dir] + len / 2, dir, pre1, pre2); - - /* - if(pre1 == pre2) { - int edgelen =(dimen >> maxDepth); - dc_printf("Location: %d %d %d Direction: %d Reso: %d\n", st[0]/edgelen, st[1]/edgelen, st[2]/edgelen, dir, len/edgelen); - printPath(head); - exit(0); - } - */ - - if (side) { - // Entirely on one side - PathList *nring = new PathList(); - nring->head = head; - - if (side == -1) { - nring->next = nrings1; - nrings1 = nring; - } - else { - nring->next = nrings2; - nrings2 = nring; - } - } - else { - // Break into two parts - PathElement *nxt1 = pre1->next; - PathElement *nxt2 = pre2->next; - pre1->next = nxt2; - pre2->next = nxt1; - - newnode = connectFace(newnode, st, len, dir, pre1, pre2); - - if (isEqual(pre1, pre1->next)) { - if (pre1 == pre1->next) { - delete pre1; - pre1 = NULL; - } - else { - PathElement *temp = pre1->next; - pre1->next = temp->next; - delete temp; - } - } - if (isEqual(pre2, pre2->next)) { - if (pre2 == pre2->next) { - delete pre2; - pre2 = NULL; - } - else { - PathElement *temp = pre2->next; - pre2->next = temp->next; - delete temp; - } - } - - compressRing(pre1); - compressRing(pre2); - - // Recur - newnode = patchSplitSingle(newnode, st, len, pre1, dir, nrings1, nrings2); - newnode = patchSplitSingle(newnode, st, len, pre2, dir, nrings1, nrings2); - - } + return newnode; + } + else { + // printPath(head); + } + + // Walk along the ring to find pair of intersections + PathElement *pre1 = NULL; + PathElement *pre2 = NULL; + int side = findPair(head, st[dir] + len / 2, dir, pre1, pre2); + + /* + if(pre1 == pre2) { + int edgelen =(dimen >> maxDepth); + dc_printf("Location: %d %d %d Direction: %d Reso: %d\n", st[0]/edgelen, st[1]/edgelen, st[2]/edgelen, dir, len/edgelen); + printPath(head); + exit(0); + } + */ + + if (side) { + // Entirely on one side + PathList *nring = new PathList(); + nring->head = head; + + if (side == -1) { + nring->next = nrings1; + nrings1 = nring; + } + else { + nring->next = nrings2; + nrings2 = nring; + } + } + else { + // Break into two parts + PathElement *nxt1 = pre1->next; + PathElement *nxt2 = pre2->next; + pre1->next = nxt2; + pre2->next = nxt1; + + newnode = connectFace(newnode, st, len, dir, pre1, pre2); + + if (isEqual(pre1, pre1->next)) { + if (pre1 == pre1->next) { + delete pre1; + pre1 = NULL; + } + else { + PathElement *temp = pre1->next; + pre1->next = temp->next; + delete temp; + } + } + if (isEqual(pre2, pre2->next)) { + if (pre2 == pre2->next) { + delete pre2; + pre2 = NULL; + } + else { + PathElement *temp = pre2->next; + pre2->next = temp->next; + delete temp; + } + } + + compressRing(pre1); + compressRing(pre2); + + // Recur + newnode = patchSplitSingle(newnode, st, len, pre1, dir, nrings1, nrings2); + newnode = patchSplitSingle(newnode, st, len, pre2, dir, nrings1, nrings2); + } #ifdef IN_DEBUG_MODE - dc_printf("Return from PATCHSPLITSINGLE with \n"); - dc_printf("Rings gourp 1:\n"); - printPaths(nrings1); - dc_printf("Rings group 2:\n"); - printPaths(nrings2); + dc_printf("Return from PATCHSPLITSINGLE with \n"); + dc_printf("Rings gourp 1:\n"); + printPaths(nrings1); + dc_printf("Rings group 2:\n"); + printPaths(nrings2); #endif - return newnode; + return newnode; } -Node *Octree::connectFace(Node *newnode, int st[3], int len, int dir, - PathElement *f1, PathElement *f2) +Node *Octree::connectFace( + Node *newnode, int st[3], int len, int dir, PathElement *f1, PathElement *f2) { #ifdef IN_DEBUG_MODE - dc_printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len); - dc_printf("Path(low side): \n"); - printPath(f1); -// checkPath(f1); - dc_printf("Path(high side): \n"); - printPath(f2); -// checkPath(f2); + dc_printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len); + dc_printf("Path(low side): \n"); + printPath(f1); + // checkPath(f1); + dc_printf("Path(high side): \n"); + printPath(f2); +// checkPath(f2); #endif - // Setup 2D - int pos = st[dir] + len / 2; - int xdir = (dir + 1) % 3; - int ydir = (dir + 2) % 3; - - // Use existing intersections on f1 and f2 - int x1, y1, x2, y2; - float p1, q1, p2, q2; - - getFacePoint(f2->next, dir, x1, y1, p1, q1); - getFacePoint(f2, dir, x2, y2, p2, q2); - - float dx = x2 + p2 - x1 - p1; - float dy = y2 + q2 - y1 - q1; - - // Do adapted Bresenham line drawing - float rx = p1, ry = q1; - int incx = 1, incy = 1; - int lx = x1, ly = y1; - int hx = x2, hy = y2; - int choice; - if (x2 < x1) { - incx = -1; - rx = 1 - rx; - lx = x2; - hx = x1; - } - if (y2 < y1) { - incy = -1; - ry = 1 - ry; - ly = y2; - hy = y1; - } - - float sx = dx * incx; - float sy = dy * incy; - - int ori[3]; - ori[dir] = pos / mindimen; - ori[xdir] = x1; - ori[ydir] = y1; - int walkdir; - int inc; - float alpha; - - PathElement *curEleN = f1; - PathElement *curEleP = f2->next; - Node *nodeN = NULL, *nodeP = NULL; - LeafNode *curN = locateLeaf(&newnode->internal, len, f1->pos); - LeafNode *curP = locateLeaf(&newnode->internal, len, f2->next->pos); - if (curN == NULL || curP == NULL) { - exit(0); - } - int stN[3], stP[3]; - int lenN, lenP; - - /* Unused code, leaving for posterity - - float stpt[3], edpt[3]; - stpt[dir] = edpt[dir] =(float) pos; - stpt[xdir] =(x1 + p1) * mindimen; - stpt[ydir] =(y1 + q1) * mindimen; - edpt[xdir] =(x2 + p2) * mindimen; - edpt[ydir] =(y2 + q2) * mindimen; - */ - while (ori[xdir] != x2 || ori[ydir] != y2) { - int next; - if (sy * (1 - rx) > sx * (1 - ry)) { - choice = 1; - next = ori[ydir] + incy; - if (next < ly || next > hy) { - choice = 4; - next = ori[xdir] + incx; - } - } - else { - choice = 2; - next = ori[xdir] + incx; - if (next < lx || next > hx) { - choice = 3; - next = ori[ydir] + incy; - } - } - - if (choice & 1) { - ori[ydir] = next; - if (choice == 1) { - rx += (sy == 0 ? 0 : (1 - ry) * sx / sy); - ry = 0; - } - - walkdir = 2; - inc = incy; - alpha = x2 < x1 ? 1 - rx : rx; - } - else { - ori[xdir] = next; - if (choice == 2) { - ry += (sx == 0 ? 0 : (1 - rx) * sy / sx); - rx = 0; - } - - walkdir = 1; - inc = incx; - alpha = y2 < y1 ? 1 - ry : ry; - } - - - - // Get the exact location of the marcher - int nori[3] = {ori[0] * mindimen, ori[1] * mindimen, ori[2] * mindimen}; - float spt[3] = {(float) nori[0], (float) nori[1], (float) nori[2]}; - spt[(dir + (3 - walkdir)) % 3] += alpha * mindimen; - if (inc < 0) { - spt[(dir + walkdir) % 3] += mindimen; - } - - // dc_printf("new x,y: %d %d\n", ori[xdir] / edgelen, ori[ydir] / edgelen); - // dc_printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir); - // dc_printf("%f %f %f\n", spt[0], spt[1], spt[2]); - - // Locate the current cells on both sides - newnode = locateCell(&newnode->internal, st, len, nori, dir, 1, nodeN, stN, lenN); - newnode = locateCell(&newnode->internal, st, len, nori, dir, 0, nodeP, stP, lenP); - - updateParent(&newnode->internal, len, st); - - int flag = 0; - // Add the cells to the rings and fill in the patch - PathElement *newEleN; - if (curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2]) { - if (curEleN->next->pos[0] != stN[0] || curEleN->next->pos[1] != stN[1] || curEleN->next->pos[2] != stN[2]) { - newEleN = new PathElement; - newEleN->next = curEleN->next; - newEleN->pos[0] = stN[0]; - newEleN->pos[1] = stN[1]; - newEleN->pos[2] = stN[2]; - - curEleN->next = newEleN; - } - else { - newEleN = curEleN->next; - } - curN = patchAdjacent(&newnode->internal, len, curEleN->pos, curN, - newEleN->pos, (LeafNode *)nodeN, walkdir, - inc, dir, 1, alpha); - - curEleN = newEleN; - flag++; - } - - PathElement *newEleP; - if (curEleP->pos[0] != stP[0] || curEleP->pos[1] != stP[1] || curEleP->pos[2] != stP[2]) { - if (f2->pos[0] != stP[0] || f2->pos[1] != stP[1] || f2->pos[2] != stP[2]) { - newEleP = new PathElement; - newEleP->next = curEleP; - newEleP->pos[0] = stP[0]; - newEleP->pos[1] = stP[1]; - newEleP->pos[2] = stP[2]; - - f2->next = newEleP; - } - else { - newEleP = f2; - } - curP = patchAdjacent(&newnode->internal, len, curEleP->pos, curP, - newEleP->pos, (LeafNode *)nodeP, walkdir, - inc, dir, 0, alpha); - - - - curEleP = newEleP; - flag++; - } - - - /* - if(flag == 0) { - dc_printf("error: non-synchronized patching! at \n"); - } - */ - } + // Setup 2D + int pos = st[dir] + len / 2; + int xdir = (dir + 1) % 3; + int ydir = (dir + 2) % 3; + + // Use existing intersections on f1 and f2 + int x1, y1, x2, y2; + float p1, q1, p2, q2; + + getFacePoint(f2->next, dir, x1, y1, p1, q1); + getFacePoint(f2, dir, x2, y2, p2, q2); + + float dx = x2 + p2 - x1 - p1; + float dy = y2 + q2 - y1 - q1; + + // Do adapted Bresenham line drawing + float rx = p1, ry = q1; + int incx = 1, incy = 1; + int lx = x1, ly = y1; + int hx = x2, hy = y2; + int choice; + if (x2 < x1) { + incx = -1; + rx = 1 - rx; + lx = x2; + hx = x1; + } + if (y2 < y1) { + incy = -1; + ry = 1 - ry; + ly = y2; + hy = y1; + } + + float sx = dx * incx; + float sy = dy * incy; + + int ori[3]; + ori[dir] = pos / mindimen; + ori[xdir] = x1; + ori[ydir] = y1; + int walkdir; + int inc; + float alpha; + + PathElement *curEleN = f1; + PathElement *curEleP = f2->next; + Node *nodeN = NULL, *nodeP = NULL; + LeafNode *curN = locateLeaf(&newnode->internal, len, f1->pos); + LeafNode *curP = locateLeaf(&newnode->internal, len, f2->next->pos); + if (curN == NULL || curP == NULL) { + exit(0); + } + int stN[3], stP[3]; + int lenN, lenP; + + /* Unused code, leaving for posterity + + float stpt[3], edpt[3]; + stpt[dir] = edpt[dir] =(float) pos; + stpt[xdir] =(x1 + p1) * mindimen; + stpt[ydir] =(y1 + q1) * mindimen; + edpt[xdir] =(x2 + p2) * mindimen; + edpt[ydir] =(y2 + q2) * mindimen; + */ + while (ori[xdir] != x2 || ori[ydir] != y2) { + int next; + if (sy * (1 - rx) > sx * (1 - ry)) { + choice = 1; + next = ori[ydir] + incy; + if (next < ly || next > hy) { + choice = 4; + next = ori[xdir] + incx; + } + } + else { + choice = 2; + next = ori[xdir] + incx; + if (next < lx || next > hx) { + choice = 3; + next = ori[ydir] + incy; + } + } + + if (choice & 1) { + ori[ydir] = next; + if (choice == 1) { + rx += (sy == 0 ? 0 : (1 - ry) * sx / sy); + ry = 0; + } + + walkdir = 2; + inc = incy; + alpha = x2 < x1 ? 1 - rx : rx; + } + else { + ori[xdir] = next; + if (choice == 2) { + ry += (sx == 0 ? 0 : (1 - rx) * sy / sx); + rx = 0; + } + + walkdir = 1; + inc = incx; + alpha = y2 < y1 ? 1 - ry : ry; + } + + // Get the exact location of the marcher + int nori[3] = {ori[0] * mindimen, ori[1] * mindimen, ori[2] * mindimen}; + float spt[3] = {(float)nori[0], (float)nori[1], (float)nori[2]}; + spt[(dir + (3 - walkdir)) % 3] += alpha * mindimen; + if (inc < 0) { + spt[(dir + walkdir) % 3] += mindimen; + } + + // dc_printf("new x,y: %d %d\n", ori[xdir] / edgelen, ori[ydir] / edgelen); + // dc_printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir); + // dc_printf("%f %f %f\n", spt[0], spt[1], spt[2]); + + // Locate the current cells on both sides + newnode = locateCell(&newnode->internal, st, len, nori, dir, 1, nodeN, stN, lenN); + newnode = locateCell(&newnode->internal, st, len, nori, dir, 0, nodeP, stP, lenP); + + updateParent(&newnode->internal, len, st); + + int flag = 0; + // Add the cells to the rings and fill in the patch + PathElement *newEleN; + if (curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2]) { + if (curEleN->next->pos[0] != stN[0] || curEleN->next->pos[1] != stN[1] || + curEleN->next->pos[2] != stN[2]) { + newEleN = new PathElement; + newEleN->next = curEleN->next; + newEleN->pos[0] = stN[0]; + newEleN->pos[1] = stN[1]; + newEleN->pos[2] = stN[2]; + + curEleN->next = newEleN; + } + else { + newEleN = curEleN->next; + } + curN = patchAdjacent(&newnode->internal, + len, + curEleN->pos, + curN, + newEleN->pos, + (LeafNode *)nodeN, + walkdir, + inc, + dir, + 1, + alpha); + + curEleN = newEleN; + flag++; + } + + PathElement *newEleP; + if (curEleP->pos[0] != stP[0] || curEleP->pos[1] != stP[1] || curEleP->pos[2] != stP[2]) { + if (f2->pos[0] != stP[0] || f2->pos[1] != stP[1] || f2->pos[2] != stP[2]) { + newEleP = new PathElement; + newEleP->next = curEleP; + newEleP->pos[0] = stP[0]; + newEleP->pos[1] = stP[1]; + newEleP->pos[2] = stP[2]; + + f2->next = newEleP; + } + else { + newEleP = f2; + } + curP = patchAdjacent(&newnode->internal, + len, + curEleP->pos, + curP, + newEleP->pos, + (LeafNode *)nodeP, + walkdir, + inc, + dir, + 0, + alpha); + + curEleP = newEleP; + flag++; + } + + /* + if(flag == 0) { + dc_printf("error: non-synchronized patching! at \n"); + } + */ + } #ifdef IN_DEBUG_MODE - dc_printf("Return from CONNECTFACE with \n"); - dc_printf("Path(low side):\n"); - printPath(f1); - checkPath(f1); - dc_printf("Path(high side):\n"); - printPath(f2); - checkPath(f2); + dc_printf("Return from CONNECTFACE with \n"); + dc_printf("Path(low side):\n"); + printPath(f1); + checkPath(f1); + dc_printf("Path(high side):\n"); + printPath(f2); + checkPath(f2); #endif - - return newnode; + return newnode; } -LeafNode *Octree::patchAdjacent(InternalNode *node, int len, int st1[3], - LeafNode *leaf1, int st2[3], LeafNode *leaf2, - int walkdir, int inc, int dir, int side, +LeafNode *Octree::patchAdjacent(InternalNode *node, + int len, + int st1[3], + LeafNode *leaf1, + int st2[3], + LeafNode *leaf2, + int walkdir, + int inc, + int dir, + int side, float alpha) { #ifdef IN_DEBUG_MODE - dc_printf("Before patching.\n"); - printInfo(st1); - printInfo(st2); - dc_printf("-----------------%d %d %d; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2]); + dc_printf("Before patching.\n"); + printInfo(st1); + printInfo(st2); + dc_printf( + "-----------------%d %d %d; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2]); #endif - // Get edge index on each leaf - int edgedir = (dir + (3 - walkdir)) % 3; - int incdir = (dir + walkdir) % 3; - int ind1 = (edgedir == 1 ? (dir + 3 - edgedir) % 3 - 1 : 2 - (dir + 3 - edgedir) % 3); - int ind2 = (edgedir == 1 ? (incdir + 3 - edgedir) % 3 - 1 : 2 - (incdir + 3 - edgedir) % 3); + // Get edge index on each leaf + int edgedir = (dir + (3 - walkdir)) % 3; + int incdir = (dir + walkdir) % 3; + int ind1 = (edgedir == 1 ? (dir + 3 - edgedir) % 3 - 1 : 2 - (dir + 3 - edgedir) % 3); + int ind2 = (edgedir == 1 ? (incdir + 3 - edgedir) % 3 - 1 : 2 - (incdir + 3 - edgedir) % 3); - int eind1 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 1 : 0) << ind2)); - int eind2 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 0 : 1) << ind2)); + int eind1 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 1 : 0) << ind2)); + int eind2 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 0 : 1) << ind2)); #ifdef IN_DEBUG_MODE - dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha); - /* - if(alpha < 0 || alpha > 1) { - dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha); - printInfo(st1); - printInfo(st2); - } - */ + dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha); + /* + if(alpha < 0 || alpha > 1) { + dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha); + printInfo(st1); + printInfo(st2); + } + */ #endif - // Flip edge parity - LeafNode *nleaf1 = flipEdge(leaf1, eind1, alpha); - LeafNode *nleaf2 = flipEdge(leaf2, eind2, alpha); - - // Update parent link - updateParent(node, len, st1, nleaf1); - updateParent(node, len, st2, nleaf2); - // updateParent(nleaf1, mindimen, st1); - // updateParent(nleaf2, mindimen, st2); - - /* - float m[3]; - dc_printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2]); - getMinimizer(leaf1, m); - dc_printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2]); - getMinimizer(leaf2, m); - dc_printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2]); - */ + // Flip edge parity + LeafNode *nleaf1 = flipEdge(leaf1, eind1, alpha); + LeafNode *nleaf2 = flipEdge(leaf2, eind2, alpha); + + // Update parent link + updateParent(node, len, st1, nleaf1); + updateParent(node, len, st2, nleaf2); + // updateParent(nleaf1, mindimen, st1); + // updateParent(nleaf2, mindimen, st2); + + /* + float m[3]; + dc_printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2]); + getMinimizer(leaf1, m); + dc_printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2]); + getMinimizer(leaf2, m); + dc_printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2]); + */ #ifdef IN_DEBUG_MODE - dc_printf("After patching.\n"); - printInfo(st1); - printInfo(st2); + dc_printf("After patching.\n"); + printInfo(st1); + printInfo(st2); #endif - return nleaf2; + return nleaf2; } -Node *Octree::locateCell(InternalNode *node, int st[3], int len, int ori[3], int dir, int side, Node *& rleaf, int rst[3], int& rlen) +Node *Octree::locateCell(InternalNode *node, + int st[3], + int len, + int ori[3], + int dir, + int side, + Node *&rleaf, + int rst[3], + int &rlen) { #ifdef IN_DEBUG_MODE - // dc_printf("Call to LOCATECELL with node "); - // printNode(node); + // dc_printf("Call to LOCATECELL with node "); + // printNode(node); #endif - int i; - len >>= 1; - int ind = 0; - for (i = 0; i < 3; i++) { - ind <<= 1; - if (i == dir && side == 1) { - ind |= (ori[i] <= (st[i] + len) ? 0 : 1); - } - else { - ind |= (ori[i] < (st[i] + len) ? 0 : 1); - } - } + int i; + len >>= 1; + int ind = 0; + for (i = 0; i < 3; i++) { + ind <<= 1; + if (i == dir && side == 1) { + ind |= (ori[i] <= (st[i] + len) ? 0 : 1); + } + else { + ind |= (ori[i] < (st[i] + len) ? 0 : 1); + } + } #ifdef IN_DEBUG_MODE - // dc_printf("In LOCATECELL index of ori(%d %d %d) with dir %d side %d in st(%d %d %d, %d) is: %d\n", - // ori[0], ori[1], ori[2], dir, side, st[0], st[1], st[2], len, ind); + // dc_printf("In LOCATECELL index of ori(%d %d %d) with dir %d side %d in st(%d %d %d, %d) is: %d\n", + // ori[0], ori[1], ori[2], dir, side, st[0], st[1], st[2], len, ind); #endif - rst[0] = st[0] + vertmap[ind][0] * len; - rst[1] = st[1] + vertmap[ind][1] * len; - rst[2] = st[2] + vertmap[ind][2] * len; - - if (node->has_child(ind)) { - int count = node->get_child_count(ind); - Node *chd = node->get_child(count); - if (node->is_child_leaf(ind)) { - rleaf = chd; - rlen = len; - } - else { - // Recur - node->set_child(count, locateCell(&chd->internal, rst, len, ori, dir, side, rleaf, rst, rlen)); - } - } - else { - // Create a new child here - if (len == mindimen) { - LeafNode *chd = createLeaf(0); - node = addChild(node, ind, (Node *)chd, 1); - rleaf = (Node *)chd; - rlen = len; - } - else { - // Subdivide the empty cube - InternalNode *chd = createInternal(0); - node = addChild(node, ind, - locateCell(chd, rst, len, ori, dir, side, rleaf, rst, rlen), 0); - } - } + rst[0] = st[0] + vertmap[ind][0] * len; + rst[1] = st[1] + vertmap[ind][1] * len; + rst[2] = st[2] + vertmap[ind][2] * len; + + if (node->has_child(ind)) { + int count = node->get_child_count(ind); + Node *chd = node->get_child(count); + if (node->is_child_leaf(ind)) { + rleaf = chd; + rlen = len; + } + else { + // Recur + node->set_child(count, + locateCell(&chd->internal, rst, len, ori, dir, side, rleaf, rst, rlen)); + } + } + else { + // Create a new child here + if (len == mindimen) { + LeafNode *chd = createLeaf(0); + node = addChild(node, ind, (Node *)chd, 1); + rleaf = (Node *)chd; + rlen = len; + } + else { + // Subdivide the empty cube + InternalNode *chd = createInternal(0); + node = addChild(node, ind, locateCell(chd, rst, len, ori, dir, side, rleaf, rst, rlen), 0); + } + } #ifdef IN_DEBUG_MODE - // dc_printf("Return from LOCATECELL with node "); - // printNode(newnode); + // dc_printf("Return from LOCATECELL with node "); + // printNode(newnode); #endif - return (Node *)node; + return (Node *)node; } void Octree::checkElement(PathElement * /*ele*/) { - /* - if(ele != NULL && locateLeafCheck(ele->pos) != ele->node) { - dc_printf("Screwed! at pos: %d %d %d\n", ele->pos[0]>>minshift, ele->pos[1]>>minshift, ele->pos[2]>>minshift); - exit(0); - } - */ + /* + if(ele != NULL && locateLeafCheck(ele->pos) != ele->node) { + dc_printf("Screwed! at pos: %d %d %d\n", ele->pos[0]>>minshift, ele->pos[1]>>minshift, ele->pos[2]>>minshift); + exit(0); + } + */ } void Octree::checkPath(PathElement *path) { - PathElement *n = path; - int same = 0; - while (n && (same == 0 || n != path)) { - same++; - checkElement(n); - n = n->next; - } - + PathElement *n = path; + int same = 0; + while (n && (same == 0 || n != path)) { + same++; + checkElement(n); + n = n->next; + } } void Octree::testFacePoint(PathElement *e1, PathElement *e2) { - int i; - PathElement *e = NULL; - for (i = 0; i < 3; i++) { - if (e1->pos[i] != e2->pos[i]) { - if (e1->pos[i] < e2->pos[i]) { - e = e2; - } - else { - e = e1; - } - break; - } - } - - int x, y; - float p, q; - dc_printf("Test."); - getFacePoint(e, i, x, y, p, q); + int i; + PathElement *e = NULL; + for (i = 0; i < 3; i++) { + if (e1->pos[i] != e2->pos[i]) { + if (e1->pos[i] < e2->pos[i]) { + e = e2; + } + else { + e = e1; + } + break; + } + } + + int x, y; + float p, q; + dc_printf("Test."); + getFacePoint(e, i, x, y, p, q); } -void Octree::getFacePoint(PathElement *leaf, int dir, int& x, int& y, float& p, float& q) +void Octree::getFacePoint(PathElement *leaf, int dir, int &x, int &y, float &p, float &q) { - // Find average intersections - float avg[3] = {0, 0, 0}; - float off[3]; - int num = 0, num2 = 0; - - LeafNode *leafnode = locateLeaf(leaf->pos); - for (int i = 0; i < 4; i++) { - int edgeind = faceMap[dir * 2][i]; - int nst[3]; - for (int j = 0; j < 3; j++) { - nst[j] = leaf->pos[j] + mindimen * vertmap[edgemap[edgeind][0]][j]; - } - - if (getEdgeIntersectionByIndex(nst, edgeind / 4, off, 1)) { - avg[0] += off[0]; - avg[1] += off[1]; - avg[2] += off[2]; - num++; - } - if (getEdgeParity(leafnode, edgeind)) { - num2++; - } - } - if (num == 0) { - dc_printf("Wrong! dir: %d pos: %d %d %d num: %d\n", dir, leaf->pos[0] >> minshift, leaf->pos[1] >> minshift, leaf->pos[2] >> minshift, num2); - avg[0] = (float) leaf->pos[0]; - avg[1] = (float) leaf->pos[1]; - avg[2] = (float) leaf->pos[2]; - } - else { - - avg[0] /= num; - avg[1] /= num; - avg[2] /= num; - - //avg[0] =(float) leaf->pos[0]; - //avg[1] =(float) leaf->pos[1]; - //avg[2] =(float) leaf->pos[2]; - } - - int xdir = (dir + 1) % 3; - int ydir = (dir + 2) % 3; - - float xf = avg[xdir]; - float yf = avg[ydir]; + // Find average intersections + float avg[3] = {0, 0, 0}; + float off[3]; + int num = 0, num2 = 0; + + LeafNode *leafnode = locateLeaf(leaf->pos); + for (int i = 0; i < 4; i++) { + int edgeind = faceMap[dir * 2][i]; + int nst[3]; + for (int j = 0; j < 3; j++) { + nst[j] = leaf->pos[j] + mindimen * vertmap[edgemap[edgeind][0]][j]; + } + + if (getEdgeIntersectionByIndex(nst, edgeind / 4, off, 1)) { + avg[0] += off[0]; + avg[1] += off[1]; + avg[2] += off[2]; + num++; + } + if (getEdgeParity(leafnode, edgeind)) { + num2++; + } + } + if (num == 0) { + dc_printf("Wrong! dir: %d pos: %d %d %d num: %d\n", + dir, + leaf->pos[0] >> minshift, + leaf->pos[1] >> minshift, + leaf->pos[2] >> minshift, + num2); + avg[0] = (float)leaf->pos[0]; + avg[1] = (float)leaf->pos[1]; + avg[2] = (float)leaf->pos[2]; + } + else { + + avg[0] /= num; + avg[1] /= num; + avg[2] /= num; + + //avg[0] =(float) leaf->pos[0]; + //avg[1] =(float) leaf->pos[1]; + //avg[2] =(float) leaf->pos[2]; + } + + int xdir = (dir + 1) % 3; + int ydir = (dir + 2) % 3; + + float xf = avg[xdir]; + float yf = avg[ydir]; #ifdef IN_DEBUG_MODE - // Is it outside? - // PathElement* leaf = leaf1->len < leaf2->len ? leaf1 : leaf2; - /* - float* m =(leaf == leaf1 ? m1 : m2); - if(xf < leaf->pos[xdir] || - yf < leaf->pos[ydir] || - xf > leaf->pos[xdir] + leaf->len || - yf > leaf->pos[ydir] + leaf->len) { - dc_printf("Outside cube(%d %d %d), %d : %d %d %f %f\n", leaf->pos[0], leaf->pos[1], leaf->pos[2], leaf->len, - pos, dir, xf, yf); - - // For now, snap to cell - xf = m[xdir]; - yf = m[ydir]; - } - */ - - /* - if(alpha < 0 || alpha > 1 || - xf < leaf->pos[xdir] || xf > leaf->pos[xdir] + leaf->len || - yf < leaf->pos[ydir] || yf > leaf->pos[ydir] + leaf->len) { - dc_printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node); - dc_printf("GETFACEPOINT result:(%d %d %d) %d min:(%f %f %f);(%d %d %d) %d min:(%f %f %f).\n", - leaf1->pos[0], leaf1->pos[1], leaf1->pos[2], leaf1->len, m1[0], m1[1], m1[2], - leaf2->pos[0], leaf2->pos[1], leaf2->pos[2], leaf2->len, m2[0], m2[1], m2[2]); - dc_printf("Face point at dir %d pos %d: %f %f\n", dir, pos, xf, yf); - } - */ + // Is it outside? + // PathElement* leaf = leaf1->len < leaf2->len ? leaf1 : leaf2; + /* + float* m =(leaf == leaf1 ? m1 : m2); + if(xf < leaf->pos[xdir] || + yf < leaf->pos[ydir] || + xf > leaf->pos[xdir] + leaf->len || + yf > leaf->pos[ydir] + leaf->len) { + dc_printf("Outside cube(%d %d %d), %d : %d %d %f %f\n", leaf->pos[0], leaf->pos[1], leaf->pos[2], leaf->len, + pos, dir, xf, yf); + + // For now, snap to cell + xf = m[xdir]; + yf = m[ydir]; + } + */ + + /* + if(alpha < 0 || alpha > 1 || + xf < leaf->pos[xdir] || xf > leaf->pos[xdir] + leaf->len || + yf < leaf->pos[ydir] || yf > leaf->pos[ydir] + leaf->len) { + dc_printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node); + dc_printf("GETFACEPOINT result:(%d %d %d) %d min:(%f %f %f);(%d %d %d) %d min:(%f %f %f).\n", + leaf1->pos[0], leaf1->pos[1], leaf1->pos[2], leaf1->len, m1[0], m1[1], m1[2], + leaf2->pos[0], leaf2->pos[1], leaf2->pos[2], leaf2->len, m2[0], m2[1], m2[2]); + dc_printf("Face point at dir %d pos %d: %f %f\n", dir, pos, xf, yf); + } + */ #endif + // Get the integer and float part + x = ((leaf->pos[xdir]) >> minshift); + y = ((leaf->pos[ydir]) >> minshift); - // Get the integer and float part - x = ((leaf->pos[xdir]) >> minshift); - y = ((leaf->pos[ydir]) >> minshift); - - p = (xf - leaf->pos[xdir]) / mindimen; - q = (yf - leaf->pos[ydir]) / mindimen; - + p = (xf - leaf->pos[xdir]) / mindimen; + q = (yf - leaf->pos[ydir]) / mindimen; #ifdef IN_DEBUG_MODE - dc_printf("Face point at dir %d : %f %f\n", dir, xf, yf); + dc_printf("Face point at dir %d : %f %f\n", dir, xf, yf); #endif } -int Octree::findPair(PathElement *head, int pos, int dir, PathElement *& pre1, PathElement *& pre2) +int Octree::findPair(PathElement *head, int pos, int dir, PathElement *&pre1, PathElement *&pre2) { - int side = getSide(head, pos, dir); - PathElement *cur = head; - PathElement *anchor; - PathElement *ppre1, *ppre2; - - // Start from this face, find a pair - anchor = cur; - ppre1 = cur; - cur = cur->next; - while (cur != anchor && (getSide(cur, pos, dir) == side)) { - ppre1 = cur; - cur = cur->next; - } - if (cur == anchor) { - // No pair found - return side; - } - - side = getSide(cur, pos, dir); - ppre2 = cur; - cur = cur->next; - while (getSide(cur, pos, dir) == side) { - ppre2 = cur; - cur = cur->next; - } - - - // Switch pre1 and pre2 if we start from the higher side - if (side == -1) { - cur = ppre1; - ppre1 = ppre2; - ppre2 = cur; - } - - pre1 = ppre1; - pre2 = ppre2; - - return 0; + int side = getSide(head, pos, dir); + PathElement *cur = head; + PathElement *anchor; + PathElement *ppre1, *ppre2; + + // Start from this face, find a pair + anchor = cur; + ppre1 = cur; + cur = cur->next; + while (cur != anchor && (getSide(cur, pos, dir) == side)) { + ppre1 = cur; + cur = cur->next; + } + if (cur == anchor) { + // No pair found + return side; + } + + side = getSide(cur, pos, dir); + ppre2 = cur; + cur = cur->next; + while (getSide(cur, pos, dir) == side) { + ppre2 = cur; + cur = cur->next; + } + + // Switch pre1 and pre2 if we start from the higher side + if (side == -1) { + cur = ppre1; + ppre1 = ppre2; + ppre2 = cur; + } + + pre1 = ppre1; + pre2 = ppre2; + + return 0; } int Octree::getSide(PathElement *e, int pos, int dir) { - return (e->pos[dir] < pos ? -1 : 1); + return (e->pos[dir] < pos ? -1 : 1); } int Octree::isEqual(PathElement *e1, PathElement *e2) { - return (e1->pos[0] == e2->pos[0] && e1->pos[1] == e2->pos[1] && e1->pos[2] == e2->pos[2]); + return (e1->pos[0] == e2->pos[0] && e1->pos[1] == e2->pos[1] && e1->pos[2] == e2->pos[2]); } -void Octree::compressRing(PathElement *& ring) +void Octree::compressRing(PathElement *&ring) { - if (ring == NULL) { - return; - } + if (ring == NULL) { + return; + } #ifdef IN_DEBUG_MODE - dc_printf("Call to COMPRESSRING with path: \n"); - printPath(ring); + dc_printf("Call to COMPRESSRING with path: \n"); + printPath(ring); #endif - PathElement *cur = ring->next->next; - PathElement *pre = ring->next; - PathElement *prepre = ring; - PathElement *anchor = prepre; - - do { - while (isEqual(cur, prepre)) { - // Delete - if (cur == prepre) { - // The ring has shrinked to a point - delete pre; - delete cur; - anchor = NULL; - break; - } - else { - prepre->next = cur->next; - delete pre; - delete cur; - pre = prepre->next; - cur = pre->next; - anchor = prepre; - } - } - - if (anchor == NULL) { - break; - } - - prepre = pre; - pre = cur; - cur = cur->next; - } while (prepre != anchor); - - ring = anchor; + PathElement *cur = ring->next->next; + PathElement *pre = ring->next; + PathElement *prepre = ring; + PathElement *anchor = prepre; + + do { + while (isEqual(cur, prepre)) { + // Delete + if (cur == prepre) { + // The ring has shrinked to a point + delete pre; + delete cur; + anchor = NULL; + break; + } + else { + prepre->next = cur->next; + delete pre; + delete cur; + pre = prepre->next; + cur = pre->next; + anchor = prepre; + } + } + + if (anchor == NULL) { + break; + } + + prepre = pre; + pre = cur; + cur = cur->next; + } while (prepre != anchor); + + ring = anchor; #ifdef IN_DEBUG_MODE - dc_printf("Return from COMPRESSRING with path: \n"); - printPath(ring); + dc_printf("Return from COMPRESSRING with path: \n"); + printPath(ring); #endif } void Octree::buildSigns() { - // First build a lookup table - // dc_printf("Building up look up table...\n"); - int size = 1 << 12; - unsigned char table[1 << 12]; - for (int i = 0; i < size; i++) { - table[i] = 0; - } - for (int i = 0; i < 256; i++) { - int ind = 0; - for (int j = 11; j >= 0; j--) { - ind <<= 1; - if (((i >> edgemap[j][0]) & 1) ^ ((i >> edgemap[j][1]) & 1)) { - ind |= 1; - } - } - - table[ind] = i; - } - - // Next, traverse the grid - int sg = 1; - int cube[8]; - buildSigns(table, root, 0, sg, cube); + // First build a lookup table + // dc_printf("Building up look up table...\n"); + int size = 1 << 12; + unsigned char table[1 << 12]; + for (int i = 0; i < size; i++) { + table[i] = 0; + } + for (int i = 0; i < 256; i++) { + int ind = 0; + for (int j = 11; j >= 0; j--) { + ind <<= 1; + if (((i >> edgemap[j][0]) & 1) ^ ((i >> edgemap[j][1]) & 1)) { + ind |= 1; + } + } + + table[ind] = i; + } + + // Next, traverse the grid + int sg = 1; + int cube[8]; + buildSigns(table, root, 0, sg, cube); } void Octree::buildSigns(unsigned char table[], Node *node, int isLeaf, int sg, int rvalue[8]) { - if (node == NULL) { - for (int i = 0; i < 8; i++) { - rvalue[i] = sg; - } - return; - } - - if (isLeaf == 0) { - // Internal node - Node *chd[8]; - int leaf[8]; - node->internal.fill_children(chd, leaf); - - // Get the signs at the corners of the first cube - rvalue[0] = sg; - int oris[8]; - buildSigns(table, chd[0], leaf[0], sg, oris); - - // Get the rest - int cube[8]; - for (int i = 1; i < 8; i++) { - buildSigns(table, chd[i], leaf[i], oris[i], cube); - rvalue[i] = cube[i]; - } - - } - else { - // Leaf node - generateSigns(&node->leaf, table, sg); - - for (int i = 0; i < 8; i++) { - rvalue[i] = getSign(&node->leaf, i); - } - } + if (node == NULL) { + for (int i = 0; i < 8; i++) { + rvalue[i] = sg; + } + return; + } + + if (isLeaf == 0) { + // Internal node + Node *chd[8]; + int leaf[8]; + node->internal.fill_children(chd, leaf); + + // Get the signs at the corners of the first cube + rvalue[0] = sg; + int oris[8]; + buildSigns(table, chd[0], leaf[0], sg, oris); + + // Get the rest + int cube[8]; + for (int i = 1; i < 8; i++) { + buildSigns(table, chd[i], leaf[i], oris[i], cube); + rvalue[i] = cube[i]; + } + } + else { + // Leaf node + generateSigns(&node->leaf, table, sg); + + for (int i = 0; i < 8; i++) { + rvalue[i] = getSign(&node->leaf, i); + } + } } void Octree::floodFill() { - // int threshold =(int)((dimen/mindimen) *(dimen/mindimen) * 0.5f); - int st[3] = {0, 0, 0}; - - // First, check for largest component - // size stored in -threshold - clearProcessBits(root, maxDepth); - int threshold = floodFill(root, st, dimen, maxDepth, 0); - - // Next remove - dc_printf("Largest component: %d\n", threshold); - threshold *= thresh; - dc_printf("Removing all components smaller than %d\n", threshold); - - int st2[3] = {0, 0, 0}; - clearProcessBits(root, maxDepth); - floodFill(root, st2, dimen, maxDepth, threshold); - + // int threshold =(int)((dimen/mindimen) *(dimen/mindimen) * 0.5f); + int st[3] = {0, 0, 0}; + + // First, check for largest component + // size stored in -threshold + clearProcessBits(root, maxDepth); + int threshold = floodFill(root, st, dimen, maxDepth, 0); + + // Next remove + dc_printf("Largest component: %d\n", threshold); + threshold *= thresh; + dc_printf("Removing all components smaller than %d\n", threshold); + + int st2[3] = {0, 0, 0}; + clearProcessBits(root, maxDepth); + floodFill(root, st2, dimen, maxDepth, threshold); } void Octree::clearProcessBits(Node *node, int height) { - int i; - - if (height == 0) { - // Leaf cell, - for (i = 0; i < 12; i++) { - setOutProcess(&node->leaf, i); - } - } - else { - // Internal cell, recur - int count = 0; - for (i = 0; i < 8; i++) { - if (node->internal.has_child(i)) { - clearProcessBits(node->internal.get_child(count), height - 1); - count++; - } - } - } + int i; + + if (height == 0) { + // Leaf cell, + for (i = 0; i < 12; i++) { + setOutProcess(&node->leaf, i); + } + } + else { + // Internal cell, recur + int count = 0; + for (i = 0; i < 8; i++) { + if (node->internal.has_child(i)) { + clearProcessBits(node->internal.get_child(count), height - 1); + count++; + } + } + } } int Octree::floodFill(LeafNode *leaf, int st[3], int len, int /*height*/, int threshold) { - int i, j; - int maxtotal = 0; - - // Leaf cell, - int par, inp; - - // Test if the leaf has intersection edges - for (i = 0; i < 12; i++) { - par = getEdgeParity(leaf, i); - inp = isInProcess(leaf, i); - - if (par == 1 && inp == 0) { - // Intersection edge, hasn't been processed - // Let's start filling - GridQueue *queue = new GridQueue(); - int total = 1; - - // Set to in process - int mst[3]; - mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len; - mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len; - mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len; - int mdir = i / 4; - setInProcessAll(mst, mdir); - - // Put this edge into queue - queue->pushQueue(mst, mdir); - - // Queue processing - int nst[3], dir; - while (queue->popQueue(nst, dir) == 1) { - // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir); - // locations - int stMask[3][3] = { - {0, 0 - len, 0 - len}, - {0 - len, 0, 0 - len}, - {0 - len, 0 - len, 0} - }; - int cst[2][3]; - for (j = 0; j < 3; j++) { - cst[0][j] = nst[j]; - cst[1][j] = nst[j] + stMask[dir][j]; - } - - // cells - LeafNode *cs[2]; - for (j = 0; j < 2; j++) { - cs[j] = locateLeaf(cst[j]); - } - - // Middle sign - int s = getSign(cs[0], 0); - - // Masks - int fcCells[4] = {1, 0, 1, 0}; - int fcEdges[3][4][3] = { - {{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}}, - {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}}, - {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}} - }; - - // Search for neighboring connected intersection edges - for (int find = 0; find < 4; find++) { - int cind = fcCells[find]; - int eind, edge; - if (s == 0) { - // Original order - for (eind = 0; eind < 3; eind++) { - edge = fcEdges[dir][find][eind]; - if (getEdgeParity(cs[cind], edge) == 1) { - break; - } - } - } - else { - // Inverse order - for (eind = 2; eind >= 0; eind--) { - edge = fcEdges[dir][find][eind]; - if (getEdgeParity(cs[cind], edge) == 1) { - break; - } - } - } - - if (eind == 3 || eind == -1) { - dc_printf("Wrong! this is not a consistent sign. %d\n", eind); - } - else { - int est[3]; - est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len; - est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len; - est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len; - int edir = edge / 4; - - if (isInProcess(cs[cind], edge) == 0) { - setInProcessAll(est, edir); - queue->pushQueue(est, edir); - // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir); - total++; - } - } - } - } - - dc_printf("Size of component: %d ", total); - - if (threshold == 0) { - // Measuring stage - if (total > maxtotal) { - maxtotal = total; - } - dc_printf(".\n"); - delete queue; - continue; - } - - if (total >= threshold) { - dc_printf("Maintained.\n"); - delete queue; - continue; - } - dc_printf("Less then %d, removing...\n", threshold); - - // We have to remove this noise - - // Flip parity - // setOutProcessAll(mst, mdir); - flipParityAll(mst, mdir); - - // Put this edge into queue - queue->pushQueue(mst, mdir); - - // Queue processing - while (queue->popQueue(nst, dir) == 1) { - // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir); - // locations - int stMask[3][3] = { - {0, 0 - len, 0 - len}, - {0 - len, 0, 0 - len}, - {0 - len, 0 - len, 0} - }; - int cst[2][3]; - for (j = 0; j < 3; j++) { - cst[0][j] = nst[j]; - cst[1][j] = nst[j] + stMask[dir][j]; - } - - // cells - LeafNode *cs[2]; - for (j = 0; j < 2; j++) - cs[j] = locateLeaf(cst[j]); - - // Middle sign - int s = getSign(cs[0], 0); - - // Masks - int fcCells[4] = {1, 0, 1, 0}; - int fcEdges[3][4][3] = { - {{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}}, - {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}}, - {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}} - }; - - // Search for neighboring connected intersection edges - for (int find = 0; find < 4; find++) { - int cind = fcCells[find]; - int eind, edge; - if (s == 0) { - // Original order - for (eind = 0; eind < 3; eind++) { - edge = fcEdges[dir][find][eind]; - if (isInProcess(cs[cind], edge) == 1) { - break; - } - } - } - else { - // Inverse order - for (eind = 2; eind >= 0; eind--) { - edge = fcEdges[dir][find][eind]; - if (isInProcess(cs[cind], edge) == 1) { - break; - } - } - } - - if (eind == 3 || eind == -1) { - dc_printf("Wrong! this is not a consistent sign. %d\n", eind); - } - else { - int est[3]; - est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len; - est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len; - est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len; - int edir = edge / 4; - - if (getEdgeParity(cs[cind], edge) == 1) { - flipParityAll(est, edir); - queue->pushQueue(est, edir); - // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir); - total++; - } - } - } - } - - delete queue; - } - } - - return maxtotal; + int i, j; + int maxtotal = 0; + + // Leaf cell, + int par, inp; + + // Test if the leaf has intersection edges + for (i = 0; i < 12; i++) { + par = getEdgeParity(leaf, i); + inp = isInProcess(leaf, i); + + if (par == 1 && inp == 0) { + // Intersection edge, hasn't been processed + // Let's start filling + GridQueue *queue = new GridQueue(); + int total = 1; + + // Set to in process + int mst[3]; + mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len; + mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len; + mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len; + int mdir = i / 4; + setInProcessAll(mst, mdir); + + // Put this edge into queue + queue->pushQueue(mst, mdir); + + // Queue processing + int nst[3], dir; + while (queue->popQueue(nst, dir) == 1) { + // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir); + // locations + int stMask[3][3] = {{0, 0 - len, 0 - len}, {0 - len, 0, 0 - len}, {0 - len, 0 - len, 0}}; + int cst[2][3]; + for (j = 0; j < 3; j++) { + cst[0][j] = nst[j]; + cst[1][j] = nst[j] + stMask[dir][j]; + } + + // cells + LeafNode *cs[2]; + for (j = 0; j < 2; j++) { + cs[j] = locateLeaf(cst[j]); + } + + // Middle sign + int s = getSign(cs[0], 0); + + // Masks + int fcCells[4] = {1, 0, 1, 0}; + int fcEdges[3][4][3] = {{{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}}, + {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}}, + {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}}}; + + // Search for neighboring connected intersection edges + for (int find = 0; find < 4; find++) { + int cind = fcCells[find]; + int eind, edge; + if (s == 0) { + // Original order + for (eind = 0; eind < 3; eind++) { + edge = fcEdges[dir][find][eind]; + if (getEdgeParity(cs[cind], edge) == 1) { + break; + } + } + } + else { + // Inverse order + for (eind = 2; eind >= 0; eind--) { + edge = fcEdges[dir][find][eind]; + if (getEdgeParity(cs[cind], edge) == 1) { + break; + } + } + } + + if (eind == 3 || eind == -1) { + dc_printf("Wrong! this is not a consistent sign. %d\n", eind); + } + else { + int est[3]; + est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len; + est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len; + est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len; + int edir = edge / 4; + + if (isInProcess(cs[cind], edge) == 0) { + setInProcessAll(est, edir); + queue->pushQueue(est, edir); + // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir); + total++; + } + } + } + } + + dc_printf("Size of component: %d ", total); + + if (threshold == 0) { + // Measuring stage + if (total > maxtotal) { + maxtotal = total; + } + dc_printf(".\n"); + delete queue; + continue; + } + + if (total >= threshold) { + dc_printf("Maintained.\n"); + delete queue; + continue; + } + dc_printf("Less then %d, removing...\n", threshold); + + // We have to remove this noise + + // Flip parity + // setOutProcessAll(mst, mdir); + flipParityAll(mst, mdir); + + // Put this edge into queue + queue->pushQueue(mst, mdir); + + // Queue processing + while (queue->popQueue(nst, dir) == 1) { + // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir); + // locations + int stMask[3][3] = {{0, 0 - len, 0 - len}, {0 - len, 0, 0 - len}, {0 - len, 0 - len, 0}}; + int cst[2][3]; + for (j = 0; j < 3; j++) { + cst[0][j] = nst[j]; + cst[1][j] = nst[j] + stMask[dir][j]; + } + + // cells + LeafNode *cs[2]; + for (j = 0; j < 2; j++) + cs[j] = locateLeaf(cst[j]); + + // Middle sign + int s = getSign(cs[0], 0); + + // Masks + int fcCells[4] = {1, 0, 1, 0}; + int fcEdges[3][4][3] = {{{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}}, + {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}}, + {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}}}; + + // Search for neighboring connected intersection edges + for (int find = 0; find < 4; find++) { + int cind = fcCells[find]; + int eind, edge; + if (s == 0) { + // Original order + for (eind = 0; eind < 3; eind++) { + edge = fcEdges[dir][find][eind]; + if (isInProcess(cs[cind], edge) == 1) { + break; + } + } + } + else { + // Inverse order + for (eind = 2; eind >= 0; eind--) { + edge = fcEdges[dir][find][eind]; + if (isInProcess(cs[cind], edge) == 1) { + break; + } + } + } + + if (eind == 3 || eind == -1) { + dc_printf("Wrong! this is not a consistent sign. %d\n", eind); + } + else { + int est[3]; + est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len; + est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len; + est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len; + int edir = edge / 4; + + if (getEdgeParity(cs[cind], edge) == 1) { + flipParityAll(est, edir); + queue->pushQueue(est, edir); + // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir); + total++; + } + } + } + } + + delete queue; + } + } + + return maxtotal; } int Octree::floodFill(Node *node, int st[3], int len, int height, int threshold) { - int i; - int maxtotal = 0; - - if (height == 0) { - maxtotal = floodFill(&node->leaf, st, len, height, threshold); - } - else { - // Internal cell, recur - int count = 0; - len >>= 1; - for (i = 0; i < 8; i++) { - if (node->internal.has_child(i)) { - int nst[3]; - nst[0] = st[0] + vertmap[i][0] * len; - nst[1] = st[1] + vertmap[i][1] * len; - nst[2] = st[2] + vertmap[i][2] * len; - - int d = floodFill(node->internal.get_child(count), nst, len, height - 1, threshold); - if (d > maxtotal) { - maxtotal = d; - } - count++; - } - } - } - - - return maxtotal; - + int i; + int maxtotal = 0; + + if (height == 0) { + maxtotal = floodFill(&node->leaf, st, len, height, threshold); + } + else { + // Internal cell, recur + int count = 0; + len >>= 1; + for (i = 0; i < 8; i++) { + if (node->internal.has_child(i)) { + int nst[3]; + nst[0] = st[0] + vertmap[i][0] * len; + nst[1] = st[1] + vertmap[i][1] * len; + nst[2] = st[2] + vertmap[i][2] * len; + + int d = floodFill(node->internal.get_child(count), nst, len, height - 1, threshold); + if (d > maxtotal) { + maxtotal = d; + } + count++; + } + } + } + + return maxtotal; } void Octree::writeOut() { - int numQuads = 0; - int numVertices = 0; - int numEdges = 0; + int numQuads = 0; + int numVertices = 0; + int numEdges = 0; - countIntersection(root, maxDepth, numQuads, numVertices, numEdges); + countIntersection(root, maxDepth, numQuads, numVertices, numEdges); - dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads); - output_mesh = alloc_output(numVertices, numQuads); - int offset = 0; - int st[3] = {0, 0, 0}; + dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads); + output_mesh = alloc_output(numVertices, numQuads); + int offset = 0; + int st[3] = {0, 0, 0}; - // First, output vertices - offset = 0; - actualVerts = 0; - actualQuads = 0; + // First, output vertices + offset = 0; + actualVerts = 0; + actualQuads = 0; - generateMinimizer(root, st, dimen, maxDepth, offset); - cellProcContour(root, 0, maxDepth); - dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads); + generateMinimizer(root, st, dimen, maxDepth, offset); + cellProcContour(root, 0, maxDepth); + dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads); } -void Octree::countIntersection(Node *node, int height, int& nedge, int& ncell, int& nface) +void Octree::countIntersection(Node *node, int height, int &nedge, int &ncell, int &nface) { - if (height > 0) { - int total = node->internal.get_num_children(); - for (int i = 0; i < total; i++) { - countIntersection(node->internal.get_child(i), height - 1, nedge, ncell, nface); - } - } - else { - nedge += getNumEdges2(&node->leaf); - - int smask = getSignMask(&node->leaf); - - if (use_manifold) { - int comps = manifold_table[smask].comps; - ncell += comps; - } - else { - if (smask > 0 && smask < 255) { - ncell++; - } - } - - for (int i = 0; i < 3; i++) { - if (getFaceEdgeNum(&node->leaf, i * 2)) { - nface++; - } - } - } + if (height > 0) { + int total = node->internal.get_num_children(); + for (int i = 0; i < total; i++) { + countIntersection(node->internal.get_child(i), height - 1, nedge, ncell, nface); + } + } + else { + nedge += getNumEdges2(&node->leaf); + + int smask = getSignMask(&node->leaf); + + if (use_manifold) { + int comps = manifold_table[smask].comps; + ncell += comps; + } + else { + if (smask > 0 && smask < 255) { + ncell++; + } + } + + for (int i = 0; i < 3; i++) { + if (getFaceEdgeNum(&node->leaf, i * 2)) { + nface++; + } + } + } } /* from http://eigen.tuxfamily.org/bz/show_bug.cgi?id=257 */ @@ -2099,751 +2121,713 @@ void pseudoInverse(const _Matrix_Type_ &a, _Matrix_Type_ &result, double epsilon = std::numeric_limits<typename _Matrix_Type_::Scalar>::epsilon()) { - Eigen::JacobiSVD< _Matrix_Type_ > svd = a.jacobiSvd(Eigen::ComputeFullU | - Eigen::ComputeFullV); - - typename _Matrix_Type_::Scalar tolerance = epsilon * std::max(a.cols(), - a.rows()) * - svd.singularValues().array().abs().maxCoeff(); - - result = svd.matrixV() * - _Matrix_Type_((svd.singularValues().array().abs() > - tolerance).select(svd.singularValues(). - array().inverse(), 0)).asDiagonal() * - svd.matrixU().adjoint(); + Eigen::JacobiSVD<_Matrix_Type_> svd = a.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV); + + typename _Matrix_Type_::Scalar tolerance = epsilon * std::max(a.cols(), a.rows()) * + svd.singularValues().array().abs().maxCoeff(); + + result = svd.matrixV() * + _Matrix_Type_((svd.singularValues().array().abs() > tolerance) + .select(svd.singularValues().array().inverse(), 0)) + .asDiagonal() * + svd.matrixU().adjoint(); } -static void solve_least_squares(const float halfA[], const float b[], - const float midpoint[], float rvalue[]) +static void solve_least_squares(const float halfA[], + const float b[], + const float midpoint[], + float rvalue[]) { - /* calculate pseudo-inverse */ - Eigen::MatrixXf A(3, 3), pinv(3, 3); - A << halfA[0], halfA[1], halfA[2], - halfA[1], halfA[3], halfA[4], - halfA[2], halfA[4], halfA[5]; - pseudoInverse(A, pinv); - - Eigen::Vector3f b2(b), mp(midpoint), result; - b2 = b2 + A * -mp; - result = pinv * b2 + mp; - - for (int i = 0; i < 3; i++) - rvalue[i] = result(i); + /* calculate pseudo-inverse */ + Eigen::MatrixXf A(3, 3), pinv(3, 3); + A << halfA[0], halfA[1], halfA[2], halfA[1], halfA[3], halfA[4], halfA[2], halfA[4], halfA[5]; + pseudoInverse(A, pinv); + + Eigen::Vector3f b2(b), mp(midpoint), result; + b2 = b2 + A * -mp; + result = pinv * b2 + mp; + + for (int i = 0; i < 3; i++) + rvalue[i] = result(i); } static void mass_point(float mp[3], const float pts[12][3], const int parity[12]) { - int ec = 0; - - for (int i = 0; i < 12; i++) { - if (parity[i]) { - const float *p = pts[i]; - - mp[0] += p[0]; - mp[1] += p[1]; - mp[2] += p[2]; - - ec++; - } - } - - if (ec == 0) { - return; - } - mp[0] /= ec; - mp[1] /= ec; - mp[2] /= ec; + int ec = 0; + + for (int i = 0; i < 12; i++) { + if (parity[i]) { + const float *p = pts[i]; + + mp[0] += p[0]; + mp[1] += p[1]; + mp[2] += p[2]; + + ec++; + } + } + + if (ec == 0) { + return; + } + mp[0] /= ec; + mp[1] /= ec; + mp[2] /= ec; } -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 minimize(float rvalue[3], + float mp[3], + const float pts[12][3], + const float norms[12][3], + const int parity[12]) { - float ata[6] = {0, 0, 0, 0, 0, 0}; - float atb[3] = {0, 0, 0}; - int ec = 0; - - for (int i = 0; i < 12; i++) { - // if(getEdgeParity(leaf, i)) - if (parity[i]) { - const float *norm = norms[i]; - const float *p = pts[i]; - - // QEF - ata[0] += (float)(norm[0] * norm[0]); - ata[1] += (float)(norm[0] * norm[1]); - ata[2] += (float)(norm[0] * norm[2]); - ata[3] += (float)(norm[1] * norm[1]); - ata[4] += (float)(norm[1] * norm[2]); - ata[5] += (float)(norm[2] * norm[2]); - - const float pn = p[0] * norm[0] + p[1] * norm[1] + p[2] * norm[2]; - - atb[0] += (float)(norm[0] * pn); - atb[1] += (float)(norm[1] * pn); - atb[2] += (float)(norm[2] * pn); - - // Minimizer - mp[0] += p[0]; - mp[1] += p[1]; - mp[2] += p[2]; - - ec++; - } - } - - if (ec == 0) { - return; - } - mp[0] /= ec; - mp[1] /= ec; - mp[2] /= ec; - - // Solve least squares - solve_least_squares(ata, atb, mp, rvalue); + float ata[6] = {0, 0, 0, 0, 0, 0}; + float atb[3] = {0, 0, 0}; + int ec = 0; + + for (int i = 0; i < 12; i++) { + // if(getEdgeParity(leaf, i)) + if (parity[i]) { + const float *norm = norms[i]; + const float *p = pts[i]; + + // QEF + ata[0] += (float)(norm[0] * norm[0]); + ata[1] += (float)(norm[0] * norm[1]); + ata[2] += (float)(norm[0] * norm[2]); + ata[3] += (float)(norm[1] * norm[1]); + ata[4] += (float)(norm[1] * norm[2]); + ata[5] += (float)(norm[2] * norm[2]); + + const float pn = p[0] * norm[0] + p[1] * norm[1] + p[2] * norm[2]; + + atb[0] += (float)(norm[0] * pn); + atb[1] += (float)(norm[1] * pn); + atb[2] += (float)(norm[2] * pn); + + // Minimizer + mp[0] += p[0]; + mp[1] += p[1]; + mp[2] += p[2]; + + ec++; + } + } + + if (ec == 0) { + return; + } + mp[0] /= ec; + mp[1] /= ec; + mp[2] /= ec; + + // Solve least squares + solve_least_squares(ata, atb, mp, rvalue); } -void Octree::computeMinimizer(const LeafNode *leaf, int st[3], int len, - float rvalue[3]) const +void Octree::computeMinimizer(const LeafNode *leaf, int st[3], int len, float rvalue[3]) const { - // First, gather all edge intersections - float pts[12][3], norms[12][3]; - int parity[12]; - fillEdgeIntersections(leaf, st, len, pts, norms, parity); - - switch (mode) { - case DUALCON_CENTROID: - rvalue[0] = (float) st[0] + len / 2; - rvalue[1] = (float) st[1] + len / 2; - rvalue[2] = (float) st[2] + len / 2; - break; - - case DUALCON_MASS_POINT: - rvalue[0] = rvalue[1] = rvalue[2] = 0; - mass_point(rvalue, pts, parity); - break; - - default: { - // Sharp features */ - - // construct QEF and minimizer - float mp[3] = {0, 0, 0}; - minimize(rvalue, mp, pts, norms, parity); - - /* Restraining the location of the minimizer */ - float nh1 = hermite_num * len; - float nh2 = (1 + hermite_num) * len; - - if (rvalue[0] < st[0] - nh1 || - rvalue[1] < st[1] - nh1 || - rvalue[2] < st[2] - nh1 || - - rvalue[0] > st[0] + nh2 || - rvalue[1] > st[1] + nh2 || - rvalue[2] > st[2] + nh2) - { - // Use mass point instead - rvalue[0] = mp[0]; - rvalue[1] = mp[1]; - rvalue[2] = mp[2]; - } - break; - } - } + // First, gather all edge intersections + float pts[12][3], norms[12][3]; + int parity[12]; + fillEdgeIntersections(leaf, st, len, pts, norms, parity); + + switch (mode) { + case DUALCON_CENTROID: + rvalue[0] = (float)st[0] + len / 2; + rvalue[1] = (float)st[1] + len / 2; + rvalue[2] = (float)st[2] + len / 2; + break; + + case DUALCON_MASS_POINT: + rvalue[0] = rvalue[1] = rvalue[2] = 0; + mass_point(rvalue, pts, parity); + break; + + default: { + // Sharp features */ + + // construct QEF and minimizer + float mp[3] = {0, 0, 0}; + minimize(rvalue, mp, pts, norms, parity); + + /* Restraining the location of the minimizer */ + float nh1 = hermite_num * len; + float nh2 = (1 + hermite_num) * len; + + if (rvalue[0] < st[0] - nh1 || rvalue[1] < st[1] - nh1 || rvalue[2] < st[2] - nh1 || + + rvalue[0] > st[0] + nh2 || rvalue[1] > st[1] + nh2 || rvalue[2] > st[2] + nh2) { + // Use mass point instead + rvalue[0] = mp[0]; + rvalue[1] = mp[1]; + rvalue[2] = mp[2]; + } + break; + } + } } -void Octree::generateMinimizer(Node *node, int st[3], int len, int height, int& offset) +void Octree::generateMinimizer(Node *node, int st[3], int len, int height, int &offset) { - int i, j; - - if (height == 0) { - // Leaf cell, generate - - // First, find minimizer - float rvalue[3]; - rvalue[0] = (float) st[0] + len / 2; - rvalue[1] = (float) st[1] + len / 2; - rvalue[2] = (float) st[2] + len / 2; - computeMinimizer(&node->leaf, st, len, rvalue); - - // Update - //float fnst[3]; - for (j = 0; j < 3; j++) { - rvalue[j] = rvalue[j] * range / dimen + origin[j]; - //fnst[j] = st[j] * range / dimen + origin[j]; - } - - int mult = 0, smask = getSignMask(&node->leaf); - - if (use_manifold) { - mult = manifold_table[smask].comps; - } - else { - if (smask > 0 && smask < 255) { - mult = 1; - } - } - - for (j = 0; j < mult; j++) { - add_vert(output_mesh, rvalue); - } - - // Store the index - setMinimizerIndex(&node->leaf, offset); - - offset += mult; - } - else { - // Internal cell, recur - int count = 0; - len >>= 1; - for (i = 0; i < 8; i++) { - if (node->internal.has_child(i)) { - int nst[3]; - nst[0] = st[0] + vertmap[i][0] * len; - nst[1] = st[1] + vertmap[i][1] * len; - nst[2] = st[2] + vertmap[i][2] * len; - - generateMinimizer(node->internal.get_child(count), - nst, len, height - 1, offset); - count++; - } - } - } + int i, j; + + if (height == 0) { + // Leaf cell, generate + + // First, find minimizer + float rvalue[3]; + rvalue[0] = (float)st[0] + len / 2; + rvalue[1] = (float)st[1] + len / 2; + rvalue[2] = (float)st[2] + len / 2; + computeMinimizer(&node->leaf, st, len, rvalue); + + // Update + //float fnst[3]; + for (j = 0; j < 3; j++) { + rvalue[j] = rvalue[j] * range / dimen + origin[j]; + //fnst[j] = st[j] * range / dimen + origin[j]; + } + + int mult = 0, smask = getSignMask(&node->leaf); + + if (use_manifold) { + mult = manifold_table[smask].comps; + } + else { + if (smask > 0 && smask < 255) { + mult = 1; + } + } + + for (j = 0; j < mult; j++) { + add_vert(output_mesh, rvalue); + } + + // Store the index + setMinimizerIndex(&node->leaf, offset); + + offset += mult; + } + else { + // Internal cell, recur + int count = 0; + len >>= 1; + for (i = 0; i < 8; i++) { + if (node->internal.has_child(i)) { + int nst[3]; + nst[0] = st[0] + vertmap[i][0] * len; + nst[1] = st[1] + vertmap[i][1] * len; + nst[2] = st[2] + vertmap[i][2] * len; + + generateMinimizer(node->internal.get_child(count), nst, len, height - 1, offset); + count++; + } + } + } } void Octree::processEdgeWrite(Node *node[4], int /*depth*/[4], int /*maxdep*/, int dir) { - //int color = 0; - - int i = 3; - { - if (getEdgeParity((LeafNode *)(node[i]), processEdgeMask[dir][i])) { - int flip = 0; - int edgeind = processEdgeMask[dir][i]; - if (getSign((LeafNode *)node[i], edgemap[edgeind][1]) > 0) { - flip = 1; - } - - int num = 0; - { - int ind[8]; - if (use_manifold) { - int vind[2]; - int seq[4] = {0, 1, 3, 2}; - for (int k = 0; k < 4; k++) { - getMinimizerIndices((LeafNode *)(node[seq[k]]), processEdgeMask[dir][seq[k]], vind); - ind[num] = vind[0]; - num++; - - if (vind[1] != -1) { - ind[num] = vind[1]; - num++; - if (flip == 0) { - ind[num - 1] = vind[0]; - ind[num - 2] = vind[1]; - } - } - } - - /* we don't use the manifold option, but if it is - ever enabled again note that it can output - non-quads */ - } - else { - if (flip) { - ind[0] = getMinimizerIndex((LeafNode *)(node[2])); - ind[1] = getMinimizerIndex((LeafNode *)(node[3])); - ind[2] = getMinimizerIndex((LeafNode *)(node[1])); - ind[3] = getMinimizerIndex((LeafNode *)(node[0])); - } - else { - ind[0] = getMinimizerIndex((LeafNode *)(node[0])); - ind[1] = getMinimizerIndex((LeafNode *)(node[1])); - ind[2] = getMinimizerIndex((LeafNode *)(node[3])); - ind[3] = getMinimizerIndex((LeafNode *)(node[2])); - } - - add_quad(output_mesh, ind); - } - } - return; - } - else { - return; - } - } + //int color = 0; + + int i = 3; + { + if (getEdgeParity((LeafNode *)(node[i]), processEdgeMask[dir][i])) { + int flip = 0; + int edgeind = processEdgeMask[dir][i]; + if (getSign((LeafNode *)node[i], edgemap[edgeind][1]) > 0) { + flip = 1; + } + + int num = 0; + { + int ind[8]; + if (use_manifold) { + int vind[2]; + int seq[4] = {0, 1, 3, 2}; + for (int k = 0; k < 4; k++) { + getMinimizerIndices((LeafNode *)(node[seq[k]]), processEdgeMask[dir][seq[k]], vind); + ind[num] = vind[0]; + num++; + + if (vind[1] != -1) { + ind[num] = vind[1]; + num++; + if (flip == 0) { + ind[num - 1] = vind[0]; + ind[num - 2] = vind[1]; + } + } + } + + /* we don't use the manifold option, but if it is + ever enabled again note that it can output + non-quads */ + } + else { + if (flip) { + ind[0] = getMinimizerIndex((LeafNode *)(node[2])); + ind[1] = getMinimizerIndex((LeafNode *)(node[3])); + ind[2] = getMinimizerIndex((LeafNode *)(node[1])); + ind[3] = getMinimizerIndex((LeafNode *)(node[0])); + } + else { + ind[0] = getMinimizerIndex((LeafNode *)(node[0])); + ind[1] = getMinimizerIndex((LeafNode *)(node[1])); + ind[2] = getMinimizerIndex((LeafNode *)(node[3])); + ind[3] = getMinimizerIndex((LeafNode *)(node[2])); + } + + add_quad(output_mesh, ind); + } + } + return; + } + else { + return; + } + } } - void Octree::edgeProcContour(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir) { - if (!(node[0] && node[1] && node[2] && node[3])) { - return; - } - if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) { - processEdgeWrite(node, depth, maxdep, dir); - } - else { - int i, j; - Node *chd[4][8]; - for (j = 0; j < 4; j++) { - for (i = 0; i < 8; i++) { - chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? - node[j]->internal.get_child( - node[j]->internal.get_child_count(i)) : NULL; - } - } - - // 2 edge calls - Node *ne[4]; - int le[4]; - int de[4]; - for (i = 0; i < 2; i++) { - int c[4] = {edgeProcEdgeMask[dir][i][0], - edgeProcEdgeMask[dir][i][1], - edgeProcEdgeMask[dir][i][2], - edgeProcEdgeMask[dir][i][3]}; - - for (int j = 0; j < 4; j++) { - if (leaf[j]) { - le[j] = leaf[j]; - ne[j] = node[j]; - de[j] = depth[j]; - } - else { - le[j] = node[j]->internal.is_child_leaf(c[j]); - ne[j] = chd[j][c[j]]; - de[j] = depth[j] - 1; - } - } - - edgeProcContour(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]); - } - - } + if (!(node[0] && node[1] && node[2] && node[3])) { + return; + } + if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) { + processEdgeWrite(node, depth, maxdep, dir); + } + else { + int i, j; + Node *chd[4][8]; + for (j = 0; j < 4; j++) { + for (i = 0; i < 8; i++) { + chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? + node[j]->internal.get_child(node[j]->internal.get_child_count(i)) : + NULL; + } + } + + // 2 edge calls + Node *ne[4]; + int le[4]; + int de[4]; + for (i = 0; i < 2; i++) { + int c[4] = {edgeProcEdgeMask[dir][i][0], + edgeProcEdgeMask[dir][i][1], + edgeProcEdgeMask[dir][i][2], + edgeProcEdgeMask[dir][i][3]}; + + for (int j = 0; j < 4; j++) { + if (leaf[j]) { + le[j] = leaf[j]; + ne[j] = node[j]; + de[j] = depth[j]; + } + else { + le[j] = node[j]->internal.is_child_leaf(c[j]); + ne[j] = chd[j][c[j]]; + de[j] = depth[j] - 1; + } + } + + edgeProcContour(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]); + } + } } void Octree::faceProcContour(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir) { - if (!(node[0] && node[1])) { - return; - } - - if (!(leaf[0] && leaf[1])) { - int i, j; - // Fill children nodes - Node *chd[2][8]; - for (j = 0; j < 2; j++) { - for (i = 0; i < 8; i++) { - chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? - node[j]->internal.get_child( - node[j]->internal.get_child_count(i)) : NULL; - } - } - - // 4 face calls - Node *nf[2]; - int df[2]; - int lf[2]; - for (i = 0; i < 4; i++) { - int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]}; - for (int j = 0; j < 2; j++) { - if (leaf[j]) { - lf[j] = leaf[j]; - nf[j] = node[j]; - df[j] = depth[j]; - } - else { - lf[j] = node[j]->internal.is_child_leaf(c[j]); - nf[j] = chd[j][c[j]]; - df[j] = depth[j] - 1; - } - } - faceProcContour(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]); - } - - // 4 edge calls - int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}}; - Node *ne[4]; - int le[4]; - int de[4]; - - for (i = 0; i < 4; i++) { - int c[4] = {faceProcEdgeMask[dir][i][1], faceProcEdgeMask[dir][i][2], - faceProcEdgeMask[dir][i][3], faceProcEdgeMask[dir][i][4]}; - int *order = orders[faceProcEdgeMask[dir][i][0]]; - - for (int j = 0; j < 4; j++) { - if (leaf[order[j]]) { - le[j] = leaf[order[j]]; - ne[j] = node[order[j]]; - de[j] = depth[order[j]]; - } - else { - le[j] = node[order[j]]->internal.is_child_leaf(c[j]); - ne[j] = chd[order[j]][c[j]]; - de[j] = depth[order[j]] - 1; - } - } - - edgeProcContour(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]); - } - } + if (!(node[0] && node[1])) { + return; + } + + if (!(leaf[0] && leaf[1])) { + int i, j; + // Fill children nodes + Node *chd[2][8]; + for (j = 0; j < 2; j++) { + for (i = 0; i < 8; i++) { + chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? + node[j]->internal.get_child(node[j]->internal.get_child_count(i)) : + NULL; + } + } + + // 4 face calls + Node *nf[2]; + int df[2]; + int lf[2]; + for (i = 0; i < 4; i++) { + int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]}; + for (int j = 0; j < 2; j++) { + if (leaf[j]) { + lf[j] = leaf[j]; + nf[j] = node[j]; + df[j] = depth[j]; + } + else { + lf[j] = node[j]->internal.is_child_leaf(c[j]); + nf[j] = chd[j][c[j]]; + df[j] = depth[j] - 1; + } + } + faceProcContour(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]); + } + + // 4 edge calls + int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}}; + Node *ne[4]; + int le[4]; + int de[4]; + + for (i = 0; i < 4; i++) { + int c[4] = {faceProcEdgeMask[dir][i][1], + faceProcEdgeMask[dir][i][2], + faceProcEdgeMask[dir][i][3], + faceProcEdgeMask[dir][i][4]}; + int *order = orders[faceProcEdgeMask[dir][i][0]]; + + for (int j = 0; j < 4; j++) { + if (leaf[order[j]]) { + le[j] = leaf[order[j]]; + ne[j] = node[order[j]]; + de[j] = depth[order[j]]; + } + else { + le[j] = node[order[j]]->internal.is_child_leaf(c[j]); + ne[j] = chd[order[j]][c[j]]; + de[j] = depth[order[j]] - 1; + } + } + + edgeProcContour(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]); + } + } } - void Octree::cellProcContour(Node *node, int leaf, int depth) { - if (node == NULL) { - return; - } - - if (!leaf) { - int i; - - // Fill children nodes - Node *chd[8]; - for (i = 0; i < 8; i++) { - chd[i] = ((!leaf) && node->internal.has_child(i)) ? - node->internal.get_child(node->internal.get_child_count(i)) : NULL; - } - - // 8 Cell calls - for (i = 0; i < 8; i++) { - cellProcContour(chd[i], node->internal.is_child_leaf(i), depth - 1); - } - - // 12 face calls - Node *nf[2]; - int lf[2]; - int df[2] = {depth - 1, depth - 1}; - for (i = 0; i < 12; i++) { - int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]}; - - lf[0] = node->internal.is_child_leaf(c[0]); - lf[1] = node->internal.is_child_leaf(c[1]); - - nf[0] = chd[c[0]]; - nf[1] = chd[c[1]]; - - faceProcContour(nf, lf, df, depth - 1, cellProcFaceMask[i][2]); - } - - // 6 edge calls - Node *ne[4]; - int le[4]; - int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1}; - for (i = 0; i < 6; i++) { - int c[4] = {cellProcEdgeMask[i][0], cellProcEdgeMask[i][1], cellProcEdgeMask[i][2], cellProcEdgeMask[i][3]}; - - for (int j = 0; j < 4; j++) { - le[j] = node->internal.is_child_leaf(c[j]); - ne[j] = chd[c[j]]; - } - - edgeProcContour(ne, le, de, depth - 1, cellProcEdgeMask[i][4]); - } - } - + if (node == NULL) { + return; + } + + if (!leaf) { + int i; + + // Fill children nodes + Node *chd[8]; + for (i = 0; i < 8; i++) { + chd[i] = ((!leaf) && node->internal.has_child(i)) ? + node->internal.get_child(node->internal.get_child_count(i)) : + NULL; + } + + // 8 Cell calls + for (i = 0; i < 8; i++) { + cellProcContour(chd[i], node->internal.is_child_leaf(i), depth - 1); + } + + // 12 face calls + Node *nf[2]; + int lf[2]; + int df[2] = {depth - 1, depth - 1}; + for (i = 0; i < 12; i++) { + int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]}; + + lf[0] = node->internal.is_child_leaf(c[0]); + lf[1] = node->internal.is_child_leaf(c[1]); + + nf[0] = chd[c[0]]; + nf[1] = chd[c[1]]; + + faceProcContour(nf, lf, df, depth - 1, cellProcFaceMask[i][2]); + } + + // 6 edge calls + Node *ne[4]; + int le[4]; + int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1}; + for (i = 0; i < 6; i++) { + int c[4] = {cellProcEdgeMask[i][0], + cellProcEdgeMask[i][1], + cellProcEdgeMask[i][2], + cellProcEdgeMask[i][3]}; + + for (int j = 0; j < 4; j++) { + le[j] = node->internal.is_child_leaf(c[j]); + ne[j] = chd[c[j]]; + } + + edgeProcContour(ne, le, de, depth - 1, cellProcEdgeMask[i][4]); + } + } } void Octree::processEdgeParity(LeafNode *node[4], int /*depth*/[4], int /*maxdep*/, int dir) { - int con = 0; - for (int i = 0; i < 4; i++) { - // Minimal cell - // if(op == 0) - { - if (getEdgeParity(node[i], processEdgeMask[dir][i])) { - con = 1; - break; - } - } - } - - if (con == 1) { - for (int i = 0; i < 4; i++) { - setEdge(node[i], processEdgeMask[dir][i]); - } - } - + int con = 0; + for (int i = 0; i < 4; i++) { + // Minimal cell + // if(op == 0) + { + if (getEdgeParity(node[i], processEdgeMask[dir][i])) { + con = 1; + break; + } + } + } + + if (con == 1) { + for (int i = 0; i < 4; i++) { + setEdge(node[i], processEdgeMask[dir][i]); + } + } } void Octree::edgeProcParity(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir) { - if (!(node[0] && node[1] && node[2] && node[3])) { - return; - } - if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) { - processEdgeParity((LeafNode **)node, depth, maxdep, dir); - } - else { - int i, j; - Node *chd[4][8]; - for (j = 0; j < 4; j++) { - for (i = 0; i < 8; i++) { - chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? - node[j]->internal.get_child( node[j]->internal.get_child_count(i)) : NULL; - } - } - - // 2 edge calls - Node *ne[4]; - int le[4]; - int de[4]; - for (i = 0; i < 2; i++) { - int c[4] = {edgeProcEdgeMask[dir][i][0], - edgeProcEdgeMask[dir][i][1], - edgeProcEdgeMask[dir][i][2], - edgeProcEdgeMask[dir][i][3]}; - - // int allleaf = 1; - for (int j = 0; j < 4; j++) { - - if (leaf[j]) { - le[j] = leaf[j]; - ne[j] = node[j]; - de[j] = depth[j]; - } - else { - le[j] = node[j]->internal.is_child_leaf(c[j]); - ne[j] = chd[j][c[j]]; - de[j] = depth[j] - 1; - - } - - } - - edgeProcParity(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]); - } - - } + if (!(node[0] && node[1] && node[2] && node[3])) { + return; + } + if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) { + processEdgeParity((LeafNode **)node, depth, maxdep, dir); + } + else { + int i, j; + Node *chd[4][8]; + for (j = 0; j < 4; j++) { + for (i = 0; i < 8; i++) { + chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? + node[j]->internal.get_child(node[j]->internal.get_child_count(i)) : + NULL; + } + } + + // 2 edge calls + Node *ne[4]; + int le[4]; + int de[4]; + for (i = 0; i < 2; i++) { + int c[4] = {edgeProcEdgeMask[dir][i][0], + edgeProcEdgeMask[dir][i][1], + edgeProcEdgeMask[dir][i][2], + edgeProcEdgeMask[dir][i][3]}; + + // int allleaf = 1; + for (int j = 0; j < 4; j++) { + + if (leaf[j]) { + le[j] = leaf[j]; + ne[j] = node[j]; + de[j] = depth[j]; + } + else { + le[j] = node[j]->internal.is_child_leaf(c[j]); + ne[j] = chd[j][c[j]]; + de[j] = depth[j] - 1; + } + } + + edgeProcParity(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]); + } + } } void Octree::faceProcParity(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir) { - if (!(node[0] && node[1])) { - return; - } - - if (!(leaf[0] && leaf[1])) { - int i, j; - // Fill children nodes - Node *chd[2][8]; - for (j = 0; j < 2; j++) { - for (i = 0; i < 8; i++) { - chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? - node[j]->internal.get_child( - node[j]->internal.get_child_count(i)) : NULL; - } - } - - // 4 face calls - Node *nf[2]; - int df[2]; - int lf[2]; - for (i = 0; i < 4; i++) { - int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]}; - for (int j = 0; j < 2; j++) { - if (leaf[j]) { - lf[j] = leaf[j]; - nf[j] = node[j]; - df[j] = depth[j]; - } - else { - lf[j] = node[j]->internal.is_child_leaf(c[j]); - nf[j] = chd[j][c[j]]; - df[j] = depth[j] - 1; - } - } - faceProcParity(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]); - } - - // 4 edge calls - int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}}; - Node *ne[4]; - int le[4]; - int de[4]; - - for (i = 0; i < 4; i++) { - int c[4] = {faceProcEdgeMask[dir][i][1], faceProcEdgeMask[dir][i][2], - faceProcEdgeMask[dir][i][3], faceProcEdgeMask[dir][i][4]}; - int *order = orders[faceProcEdgeMask[dir][i][0]]; - - for (int j = 0; j < 4; j++) { - if (leaf[order[j]]) { - le[j] = leaf[order[j]]; - ne[j] = node[order[j]]; - de[j] = depth[order[j]]; - } - else { - le[j] = node[order[j]]->internal.is_child_leaf(c[j]); - ne[j] = chd[order[j]][c[j]]; - de[j] = depth[order[j]] - 1; - } - } - - edgeProcParity(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]); - } - } + if (!(node[0] && node[1])) { + return; + } + + if (!(leaf[0] && leaf[1])) { + int i, j; + // Fill children nodes + Node *chd[2][8]; + for (j = 0; j < 2; j++) { + for (i = 0; i < 8; i++) { + chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? + node[j]->internal.get_child(node[j]->internal.get_child_count(i)) : + NULL; + } + } + + // 4 face calls + Node *nf[2]; + int df[2]; + int lf[2]; + for (i = 0; i < 4; i++) { + int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]}; + for (int j = 0; j < 2; j++) { + if (leaf[j]) { + lf[j] = leaf[j]; + nf[j] = node[j]; + df[j] = depth[j]; + } + else { + lf[j] = node[j]->internal.is_child_leaf(c[j]); + nf[j] = chd[j][c[j]]; + df[j] = depth[j] - 1; + } + } + faceProcParity(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]); + } + + // 4 edge calls + int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}}; + Node *ne[4]; + int le[4]; + int de[4]; + + for (i = 0; i < 4; i++) { + int c[4] = {faceProcEdgeMask[dir][i][1], + faceProcEdgeMask[dir][i][2], + faceProcEdgeMask[dir][i][3], + faceProcEdgeMask[dir][i][4]}; + int *order = orders[faceProcEdgeMask[dir][i][0]]; + + for (int j = 0; j < 4; j++) { + if (leaf[order[j]]) { + le[j] = leaf[order[j]]; + ne[j] = node[order[j]]; + de[j] = depth[order[j]]; + } + else { + le[j] = node[order[j]]->internal.is_child_leaf(c[j]); + ne[j] = chd[order[j]][c[j]]; + de[j] = depth[order[j]] - 1; + } + } + + edgeProcParity(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]); + } + } } - void Octree::cellProcParity(Node *node, int leaf, int depth) { - if (node == NULL) { - return; - } - - if (!leaf) { - int i; - - // Fill children nodes - Node *chd[8]; - for (i = 0; i < 8; i++) { - chd[i] = ((!leaf) && node->internal.has_child(i)) ? - node->internal.get_child(node->internal.get_child_count(i)) : NULL; - } - - // 8 Cell calls - for (i = 0; i < 8; i++) { - cellProcParity(chd[i], node->internal.is_child_leaf(i), depth - 1); - } - - // 12 face calls - Node *nf[2]; - int lf[2]; - int df[2] = {depth - 1, depth - 1}; - for (i = 0; i < 12; i++) { - int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]}; - - lf[0] = node->internal.is_child_leaf(c[0]); - lf[1] = node->internal.is_child_leaf(c[1]); - - nf[0] = chd[c[0]]; - nf[1] = chd[c[1]]; - - faceProcParity(nf, lf, df, depth - 1, cellProcFaceMask[i][2]); - } - - // 6 edge calls - Node *ne[4]; - int le[4]; - int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1}; - for (i = 0; i < 6; i++) { - int c[4] = {cellProcEdgeMask[i][0], cellProcEdgeMask[i][1], cellProcEdgeMask[i][2], cellProcEdgeMask[i][3]}; - - for (int j = 0; j < 4; j++) { - le[j] = node->internal.is_child_leaf(c[j]); - ne[j] = chd[c[j]]; - } - - edgeProcParity(ne, le, de, depth - 1, cellProcEdgeMask[i][4]); - } - } - + if (node == NULL) { + return; + } + + if (!leaf) { + int i; + + // Fill children nodes + Node *chd[8]; + for (i = 0; i < 8; i++) { + chd[i] = ((!leaf) && node->internal.has_child(i)) ? + node->internal.get_child(node->internal.get_child_count(i)) : + NULL; + } + + // 8 Cell calls + for (i = 0; i < 8; i++) { + cellProcParity(chd[i], node->internal.is_child_leaf(i), depth - 1); + } + + // 12 face calls + Node *nf[2]; + int lf[2]; + int df[2] = {depth - 1, depth - 1}; + for (i = 0; i < 12; i++) { + int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]}; + + lf[0] = node->internal.is_child_leaf(c[0]); + lf[1] = node->internal.is_child_leaf(c[1]); + + nf[0] = chd[c[0]]; + nf[1] = chd[c[1]]; + + faceProcParity(nf, lf, df, depth - 1, cellProcFaceMask[i][2]); + } + + // 6 edge calls + Node *ne[4]; + int le[4]; + int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1}; + for (i = 0; i < 6; i++) { + int c[4] = {cellProcEdgeMask[i][0], + cellProcEdgeMask[i][1], + cellProcEdgeMask[i][2], + cellProcEdgeMask[i][3]}; + + for (int j = 0; j < 4; j++) { + le[j] = node->internal.is_child_leaf(c[j]); + ne[j] = chd[c[j]]; + } + + edgeProcParity(ne, le, de, depth - 1, cellProcEdgeMask[i][4]); + } + } } /* definitions for global arrays */ const int edgemask[3] = {5, 3, 6}; const int faceMap[6][4] = { - {4, 8, 5, 9}, - {6, 10, 7, 11}, - {0, 8, 1, 10}, - {2, 9, 3, 11}, - {0, 4, 2, 6}, - {1, 5, 3, 7}, + {4, 8, 5, 9}, + {6, 10, 7, 11}, + {0, 8, 1, 10}, + {2, 9, 3, 11}, + {0, 4, 2, 6}, + {1, 5, 3, 7}, }; const int cellProcFaceMask[12][3] = { - {0, 4, 0}, - {1, 5, 0}, - {2, 6, 0}, - {3, 7, 0}, - {0, 2, 1}, - {4, 6, 1}, - {1, 3, 1}, - {5, 7, 1}, - {0, 1, 2}, - {2, 3, 2}, - {4, 5, 2}, - {6, 7, 2}, + {0, 4, 0}, + {1, 5, 0}, + {2, 6, 0}, + {3, 7, 0}, + {0, 2, 1}, + {4, 6, 1}, + {1, 3, 1}, + {5, 7, 1}, + {0, 1, 2}, + {2, 3, 2}, + {4, 5, 2}, + {6, 7, 2}, }; const int cellProcEdgeMask[6][5] = { - {0, 1, 2, 3, 0}, - {4, 5, 6, 7, 0}, - {0, 4, 1, 5, 1}, - {2, 6, 3, 7, 1}, - {0, 2, 4, 6, 2}, - {1, 3, 5, 7, 2}, + {0, 1, 2, 3, 0}, + {4, 5, 6, 7, 0}, + {0, 4, 1, 5, 1}, + {2, 6, 3, 7, 1}, + {0, 2, 4, 6, 2}, + {1, 3, 5, 7, 2}, }; -const int faceProcFaceMask[3][4][3] = { - {{4, 0, 0}, - {5, 1, 0}, - {6, 2, 0}, - {7, 3, 0}}, - {{2, 0, 1}, - {6, 4, 1}, - {3, 1, 1}, - {7, 5, 1}}, - {{1, 0, 2}, - {3, 2, 2}, - {5, 4, 2}, - {7, 6, 2}} -}; +const int faceProcFaceMask[3][4][3] = {{{4, 0, 0}, {5, 1, 0}, {6, 2, 0}, {7, 3, 0}}, + {{2, 0, 1}, {6, 4, 1}, {3, 1, 1}, {7, 5, 1}}, + {{1, 0, 2}, {3, 2, 2}, {5, 4, 2}, {7, 6, 2}}}; const int faceProcEdgeMask[3][4][6] = { - {{1, 4, 0, 5, 1, 1}, - {1, 6, 2, 7, 3, 1}, - {0, 4, 6, 0, 2, 2}, - {0, 5, 7, 1, 3, 2}}, - {{0, 2, 3, 0, 1, 0}, - {0, 6, 7, 4, 5, 0}, - {1, 2, 0, 6, 4, 2}, - {1, 3, 1, 7, 5, 2}}, - {{1, 1, 0, 3, 2, 0}, - {1, 5, 4, 7, 6, 0}, - {0, 1, 5, 0, 4, 1}, - {0, 3, 7, 2, 6, 1}} -}; + {{1, 4, 0, 5, 1, 1}, {1, 6, 2, 7, 3, 1}, {0, 4, 6, 0, 2, 2}, {0, 5, 7, 1, 3, 2}}, + {{0, 2, 3, 0, 1, 0}, {0, 6, 7, 4, 5, 0}, {1, 2, 0, 6, 4, 2}, {1, 3, 1, 7, 5, 2}}, + {{1, 1, 0, 3, 2, 0}, {1, 5, 4, 7, 6, 0}, {0, 1, 5, 0, 4, 1}, {0, 3, 7, 2, 6, 1}}}; const int edgeProcEdgeMask[3][2][5] = { - {{3, 2, 1, 0, 0}, - {7, 6, 5, 4, 0}}, - {{5, 1, 4, 0, 1}, - {7, 3, 6, 2, 1}}, - {{6, 4, 2, 0, 2}, - {7, 5, 3, 1, 2}}, + {{3, 2, 1, 0, 0}, {7, 6, 5, 4, 0}}, + {{5, 1, 4, 0, 1}, {7, 3, 6, 2, 1}}, + {{6, 4, 2, 0, 2}, {7, 5, 3, 1, 2}}, }; const int processEdgeMask[3][4] = { - {3, 2, 1, 0}, - {7, 5, 6, 4}, - {11, 10, 9, 8}, + {3, 2, 1, 0}, + {7, 5, 6, 4}, + {11, 10, 9, 8}, }; -const int dirCell[3][4][3] = { - {{0, -1, -1}, - {0, -1, 0}, - {0, 0, -1}, - {0, 0, 0}}, - {{-1, 0, -1}, - {-1, 0, 0}, - {0, 0, -1}, - {0, 0, 0}}, - {{-1, -1, 0}, - {-1, 0, 0}, - {0, -1, 0}, - {0, 0, 0}} -}; +const int dirCell[3][4][3] = {{{0, -1, -1}, {0, -1, 0}, {0, 0, -1}, {0, 0, 0}}, + {{-1, 0, -1}, {-1, 0, 0}, {0, 0, -1}, {0, 0, 0}}, + {{-1, -1, 0}, {-1, 0, 0}, {0, -1, 0}, {0, 0, 0}}}; const int dirEdge[3][4] = { - {3, 2, 1, 0}, - {7, 6, 5, 4}, - {11, 10, 9, 8}, + {3, 2, 1, 0}, + {7, 6, 5, 4}, + {11, 10, 9, 8}, }; int InternalNode::numChildrenTable[256]; |