From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- intern/dualcon/CMakeLists.txt | 36 +- intern/dualcon/dualcon.h | 34 +- intern/dualcon/intern/GeoCommon.h | 18 +- intern/dualcon/intern/MemoryAllocator.h | 289 +- intern/dualcon/intern/ModelReader.h | 45 +- intern/dualcon/intern/Projections.cpp | 504 ++- intern/dualcon/intern/Projections.h | 109 +- intern/dualcon/intern/Queue.h | 143 +- intern/dualcon/intern/cubes.h | 32 +- intern/dualcon/intern/dualcon_c_api.cpp | 251 +- intern/dualcon/intern/manifold_table.cpp | 3586 +++++++++++++++-- intern/dualcon/intern/manifold_table.h | 6 +- intern/dualcon/intern/marching_cubes_table.cpp | 3095 ++++++++++++--- intern/dualcon/intern/octree.cpp | 4852 ++++++++++++------------ intern/dualcon/intern/octree.h | 2524 ++++++------ 15 files changed, 10296 insertions(+), 5228 deletions(-) (limited to 'intern/dualcon') diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt index a5c1137bc65..9a0be94fc75 100644 --- a/intern/dualcon/CMakeLists.txt +++ b/intern/dualcon/CMakeLists.txt @@ -17,32 +17,32 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - . - intern + . + intern ) set(INC_SYS - ${EIGEN3_INCLUDE_DIRS} + ${EIGEN3_INCLUDE_DIRS} ) set(SRC - intern/manifold_table.cpp - intern/marching_cubes_table.cpp - intern/octree.cpp - intern/Projections.cpp + intern/manifold_table.cpp + intern/marching_cubes_table.cpp + intern/octree.cpp + intern/Projections.cpp - intern/cubes.h - intern/GeoCommon.h - intern/manifold_table.h - intern/marching_cubes_table.h - intern/MemoryAllocator.h - intern/ModelReader.h - intern/octree.h - intern/Projections.h - intern/Queue.h + intern/cubes.h + intern/GeoCommon.h + intern/manifold_table.h + intern/marching_cubes_table.h + intern/MemoryAllocator.h + intern/ModelReader.h + intern/octree.h + intern/Projections.h + intern/Queue.h - intern/dualcon_c_api.cpp - dualcon.h + intern/dualcon_c_api.cpp + dualcon.h ) set(LIB diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h index 4e84e60154d..e9bff72a1ce 100644 --- a/intern/dualcon/dualcon.h +++ b/intern/dualcon/dualcon.h @@ -29,22 +29,22 @@ typedef float (*DualConCo)[3]; typedef unsigned int (*DualConTri)[3]; -typedef unsigned int (*DualConLoop); +typedef unsigned int(*DualConLoop); typedef struct DualConInput { - DualConLoop mloop; + DualConLoop mloop; - DualConCo co; - int co_stride; - int totco; + DualConCo co; + int co_stride; + int totco; - DualConTri looptri; - int tri_stride; - int tottri; + DualConTri looptri; + int tri_stride; + int tottri; - int loop_stride; + int loop_stride; - float min[3], max[3]; + float min[3], max[3]; } DualConInput; /* callback for allocating memory for output */ @@ -55,16 +55,16 @@ typedef void (*DualConAddVert)(void *output, const float co[3]); typedef void (*DualConAddQuad)(void *output, const int vert_indices[4]); typedef enum { - DUALCON_FLOOD_FILL = 1, + DUALCON_FLOOD_FILL = 1, } DualConFlags; typedef enum { - /* blocky */ - DUALCON_CENTROID, - /* smooth */ - DUALCON_MASS_POINT, - /* keeps sharp edges */ - DUALCON_SHARP_FEATURES, + /* blocky */ + DUALCON_CENTROID, + /* smooth */ + DUALCON_MASS_POINT, + /* keeps sharp edges */ + DUALCON_SHARP_FEATURES, } DualConMode; /* Usage: diff --git a/intern/dualcon/intern/GeoCommon.h b/intern/dualcon/intern/GeoCommon.h index 3c21b4c36e8..421e2c5e65e 100644 --- a/intern/dualcon/intern/GeoCommon.h +++ b/intern/dualcon/intern/GeoCommon.h @@ -28,31 +28,29 @@ * @author Tao Ju */ - // 3d point with integer coordinates typedef struct { - int x, y, z; + int x, y, z; } Point3i; typedef struct { - Point3i begin; - Point3i end; + Point3i begin; + Point3i end; } BoundingBox; // triangle that points to three vertices typedef struct { - float vt[3][3]; + float vt[3][3]; } Triangle; // 3d point with float coordinates typedef struct { - float x, y, z; + float x, y, z; } Point3f; typedef struct { - Point3f begin; - Point3f end; + Point3f begin; + Point3f end; } BoundingBoxf; - -#endif /* __GEOCOMMON_H__ */ +#endif /* __GEOCOMMON_H__ */ diff --git a/intern/dualcon/intern/MemoryAllocator.h b/intern/dualcon/intern/MemoryAllocator.h index 035348483fc..933b9dea197 100644 --- a/intern/dualcon/intern/MemoryAllocator.h +++ b/intern/dualcon/intern/MemoryAllocator.h @@ -29,29 +29,27 @@ * @author Tao Ju */ - - /** * Base class of memory allocators */ -class VirtualMemoryAllocator -{ -public: -virtual ~VirtualMemoryAllocator() {} +class VirtualMemoryAllocator { + public: + virtual ~VirtualMemoryAllocator() + { + } -virtual void *allocate( ) = 0; -virtual void deallocate(void *obj) = 0; -virtual void destroy( ) = 0; -virtual void printInfo( ) = 0; + virtual void *allocate() = 0; + virtual void deallocate(void *obj) = 0; + virtual void destroy() = 0; + virtual void printInfo() = 0; -virtual int getAllocated( ) = 0; -virtual int getAll( ) = 0; -virtual int getBytes( ) = 0; + virtual int getAllocated() = 0; + virtual int getAll() = 0; + virtual int getBytes() = 0; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:VirtualMemoryAllocator") + MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:VirtualMemoryAllocator") #endif - }; /** @@ -59,167 +57,160 @@ virtual int getBytes( ) = 0; * * Note: there are 4 bytes overhead for each allocated yet unused object. */ -template < int N > -class MemoryAllocator : public VirtualMemoryAllocator -{ -private: +template class MemoryAllocator : public VirtualMemoryAllocator { + private: + /// Constants + int HEAP_UNIT, HEAP_MASK; -/// Constants -int HEAP_UNIT, HEAP_MASK; + /// Data array + UCHAR **data; -/// Data array -UCHAR **data; + /// Allocation stack + UCHAR ***stack; -/// Allocation stack -UCHAR ***stack; + /// Number of data blocks + int datablocknum; -/// Number of data blocks -int datablocknum; + /// Number of stack blocks + int stackblocknum; -/// Number of stack blocks -int stackblocknum; + /// Size of stack + int stacksize; -/// Size of stack -int stacksize; + /// Number of available objects on stack + int available; -/// Number of available objects on stack -int available; - -/** + /** * Allocate a memory block */ -void allocateDataBlock( ) -{ - // Allocate a data block - datablocknum += 1; - data = ( UCHAR ** )realloc(data, sizeof (UCHAR *) * datablocknum); - data[datablocknum - 1] = ( UCHAR * )malloc(HEAP_UNIT * N); - - // Update allocation stack - for (int i = 0; i < HEAP_UNIT; i++) - { - stack[0][i] = (data[datablocknum - 1] + i * N); - } - available = HEAP_UNIT; -} - -/** + void allocateDataBlock() + { + // Allocate a data block + datablocknum += 1; + data = (UCHAR **)realloc(data, sizeof(UCHAR *) * datablocknum); + data[datablocknum - 1] = (UCHAR *)malloc(HEAP_UNIT * N); + + // Update allocation stack + for (int i = 0; i < HEAP_UNIT; i++) { + stack[0][i] = (data[datablocknum - 1] + i * N); + } + available = HEAP_UNIT; + } + + /** * Allocate a stack block, to store more deallocated objects */ -void allocateStackBlock( ) -{ - // Allocate a stack block - stackblocknum += 1; - stacksize += HEAP_UNIT; - stack = ( UCHAR *** )realloc(stack, sizeof (UCHAR * *) * stackblocknum); - stack[stackblocknum - 1] = ( UCHAR ** )malloc(HEAP_UNIT * sizeof (UCHAR *) ); -} - - -public: -/** + void allocateStackBlock() + { + // Allocate a stack block + stackblocknum += 1; + stacksize += HEAP_UNIT; + stack = (UCHAR ***)realloc(stack, sizeof(UCHAR **) * stackblocknum); + stack[stackblocknum - 1] = (UCHAR **)malloc(HEAP_UNIT * sizeof(UCHAR *)); + } + + public: + /** * Constructor */ -MemoryAllocator( ) -{ - HEAP_UNIT = 1 << HEAP_BASE; - HEAP_MASK = (1 << HEAP_BASE) - 1; - - data = ( UCHAR ** )malloc(sizeof(UCHAR *) ); - data[0] = ( UCHAR * )malloc(HEAP_UNIT * N); - datablocknum = 1; - - stack = ( UCHAR *** )malloc(sizeof (UCHAR * *) ); - stack[0] = ( UCHAR ** )malloc(HEAP_UNIT * sizeof (UCHAR *) ); - stackblocknum = 1; - stacksize = HEAP_UNIT; - available = HEAP_UNIT; - - for (int i = 0; i < HEAP_UNIT; i++) - { - stack[0][i] = (data[0] + i * N); - } -} - -/** + MemoryAllocator() + { + HEAP_UNIT = 1 << HEAP_BASE; + HEAP_MASK = (1 << HEAP_BASE) - 1; + + data = (UCHAR **)malloc(sizeof(UCHAR *)); + data[0] = (UCHAR *)malloc(HEAP_UNIT * N); + datablocknum = 1; + + stack = (UCHAR ***)malloc(sizeof(UCHAR **)); + stack[0] = (UCHAR **)malloc(HEAP_UNIT * sizeof(UCHAR *)); + stackblocknum = 1; + stacksize = HEAP_UNIT; + available = HEAP_UNIT; + + for (int i = 0; i < HEAP_UNIT; i++) { + stack[0][i] = (data[0] + i * N); + } + } + + /** * Destructor */ -void destroy( ) -{ - int i; - for (i = 0; i < datablocknum; i++) - { - free(data[i]); - } - for (i = 0; i < stackblocknum; i++) - { - free(stack[i]); - } - free(data); - free(stack); -} - -/** + void destroy() + { + int i; + for (i = 0; i < datablocknum; i++) { + free(data[i]); + } + for (i = 0; i < stackblocknum; i++) { + free(stack[i]); + } + free(data); + free(stack); + } + + /** * Allocation method */ -void *allocate( ) -{ - if (available == 0) - { - allocateDataBlock( ); - } - - // printf("Allocating %d\n", header[ allocated ]) ; - available--; - return (void *)stack[available >> HEAP_BASE][available & HEAP_MASK]; -} - -/** + void *allocate() + { + if (available == 0) { + allocateDataBlock(); + } + + // printf("Allocating %d\n", header[ allocated ]) ; + available--; + return (void *)stack[available >> HEAP_BASE][available & HEAP_MASK]; + } + + /** * De-allocation method */ -void deallocate(void *obj) -{ - if (available == stacksize) - { - allocateStackBlock( ); - } - - // printf("De-allocating %d\n", ( obj - data ) / N ) ; - stack[available >> HEAP_BASE][available & HEAP_MASK] = (UCHAR *)obj; - available++; - // printf("%d %d\n", allocated, header[ allocated ]) ; -} - -/** + void deallocate(void *obj) + { + if (available == stacksize) { + allocateStackBlock(); + } + + // printf("De-allocating %d\n", ( obj - data ) / N ) ; + stack[available >> HEAP_BASE][available & HEAP_MASK] = (UCHAR *)obj; + available++; + // printf("%d %d\n", allocated, header[ allocated ]) ; + } + + /** * Print information */ -void printInfo( ) -{ - printf("Bytes: %d Used: %d Allocated: %d Maxfree: %d\n", getBytes(), getAllocated(), getAll(), stacksize); -} - -/** + void printInfo() + { + printf("Bytes: %d Used: %d Allocated: %d Maxfree: %d\n", + getBytes(), + getAllocated(), + getAll(), + stacksize); + } + + /** * Query methods */ -int getAllocated( ) -{ - return HEAP_UNIT * datablocknum - available; -}; + int getAllocated() + { + return HEAP_UNIT * datablocknum - available; + }; -int getAll( ) -{ - return HEAP_UNIT * datablocknum; -}; + int getAll() + { + return HEAP_UNIT * datablocknum; + }; -int getBytes( ) -{ - return N; -}; + int getBytes() + { + return N; + }; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:MemoryAllocator") + MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:MemoryAllocator") #endif - }; -#endif /* __MEMORYALLOCATOR_H__ */ +#endif /* __MEMORYALLOCATOR_H__ */ diff --git a/intern/dualcon/intern/ModelReader.h b/intern/dualcon/intern/ModelReader.h index ae735b2f1d0..0f056724a62 100644 --- a/intern/dualcon/intern/ModelReader.h +++ b/intern/dualcon/intern/ModelReader.h @@ -24,40 +24,37 @@ * * @author Tao Ju */ -class ModelReader -{ -public: -/// Constructor -ModelReader(){ -}; +class ModelReader { + public: + /// Constructor + ModelReader(){}; -/// Get next triangle -virtual Triangle *getNextTriangle( ) = 0; -virtual int getNextTriangle(int t[3]) = 0; + /// Get next triangle + virtual Triangle *getNextTriangle() = 0; + virtual int getNextTriangle(int t[3]) = 0; -/// Get bounding box -virtual float getBoundingBox(float origin[3]) = 0; + /// Get bounding box + virtual float getBoundingBox(float origin[3]) = 0; -/// Get number of triangles -virtual int getNumTriangles( ) = 0; + /// Get number of triangles + virtual int getNumTriangles() = 0; -/// Get storage size -virtual int getMemory( ) = 0; + /// Get storage size + virtual int getMemory() = 0; -/// Reset file reading location -virtual void reset( ) = 0; + /// Reset file reading location + virtual void reset() = 0; -/// For explicit vertex models -virtual int getNumVertices( ) = 0; + /// For explicit vertex models + virtual int getNumVertices() = 0; -virtual void getNextVertex(float v[3]) = 0; + virtual void getNextVertex(float v[3]) = 0; -virtual void printInfo( ) = 0; + virtual void printInfo() = 0; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:ModelReader") + MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:ModelReader") #endif - }; -#endif /* __MODELREADER_H__ */ +#endif /* __MODELREADER_H__ */ diff --git a/intern/dualcon/intern/Projections.cpp b/intern/dualcon/intern/Projections.cpp index 9fc9f5beb14..b065ba95330 100644 --- a/intern/dualcon/intern/Projections.cpp +++ b/intern/dualcon/intern/Projections.cpp @@ -22,52 +22,45 @@ #include "Projections.h" const int vertmap[8][3] = { - {0, 0, 0}, - {0, 0, 1}, - {0, 1, 0}, - {0, 1, 1}, - {1, 0, 0}, - {1, 0, 1}, - {1, 1, 0}, - {1, 1, 1}, + {0, 0, 0}, + {0, 0, 1}, + {0, 1, 0}, + {0, 1, 1}, + {1, 0, 0}, + {1, 0, 1}, + {1, 1, 0}, + {1, 1, 1}, }; const int centmap[3][3][3][2] = { - {{{0, 0}, {0, 1}, {1, 1}}, - {{0, 2}, {0, 3}, {1, 3}}, - {{2, 2}, {2, 3}, {3, 3}}}, + {{{0, 0}, {0, 1}, {1, 1}}, {{0, 2}, {0, 3}, {1, 3}}, {{2, 2}, {2, 3}, {3, 3}}}, - {{{0, 4}, {0, 5}, {1, 5}}, - {{0, 6}, {0, 7}, {1, 7}}, - {{2, 6}, {2, 7}, {3, 7}}}, + {{{0, 4}, {0, 5}, {1, 5}}, {{0, 6}, {0, 7}, {1, 7}}, {{2, 6}, {2, 7}, {3, 7}}}, - {{{4, 4}, {4, 5}, {5, 5}}, - {{4, 6}, {4, 7}, {5, 7}}, - {{6, 6}, {6, 7}, {7, 7}}} -}; + {{{4, 4}, {4, 5}, {5, 5}}, {{4, 6}, {4, 7}, {5, 7}}, {{6, 6}, {6, 7}, {7, 7}}}}; const int edgemap[12][2] = { - {0, 4}, - {1, 5}, - {2, 6}, - {3, 7}, - {0, 2}, - {1, 3}, - {4, 6}, - {5, 7}, - {0, 1}, - {2, 3}, - {4, 5}, - {6, 7}, + {0, 4}, + {1, 5}, + {2, 6}, + {3, 7}, + {0, 2}, + {1, 3}, + {4, 6}, + {5, 7}, + {0, 1}, + {2, 3}, + {4, 5}, + {6, 7}, }; const int facemap[6][4] = { - {0, 1, 2, 3}, - {4, 5, 6, 7}, - {0, 1, 4, 5}, - {2, 3, 6, 7}, - {0, 2, 4, 6}, - {1, 3, 5, 7}, + {0, 1, 2, 3}, + {4, 5, 6, 7}, + {0, 1, 4, 5}, + {2, 3, 6, 7}, + {0, 2, 4, 6}, + {1, 3, 5, 7}, }; /** @@ -75,16 +68,16 @@ const int facemap[6][4] = { */ static void crossProduct(int64_t res[3], const int64_t a[3], const int64_t b[3]) { - res[0] = a[1] * b[2] - a[2] * b[1]; - res[1] = a[2] * b[0] - a[0] * b[2]; - res[2] = a[0] * b[1] - a[1] * b[0]; + res[0] = a[1] * b[2] - a[2] * b[1]; + res[1] = a[2] * b[0] - a[0] * b[2]; + res[2] = a[0] * b[1] - a[1] * b[0]; } static void crossProduct(double res[3], const double a[3], const double b[3]) { - res[0] = a[1] * b[2] - a[2] * b[1]; - res[1] = a[2] * b[0] - a[0] * b[2]; - res[2] = a[0] * b[1] - a[1] * b[0]; + res[0] = a[1] * b[2] - a[2] * b[1]; + res[1] = a[2] * b[0] - a[0] * b[2]; + res[2] = a[0] * b[1] - a[1] * b[0]; } /** @@ -92,18 +85,18 @@ static void crossProduct(double res[3], const double a[3], const double b[3]) */ static int64_t dotProduct(const int64_t a[3], const int64_t b[3]) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } static void normalize(double a[3]) { - double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2]; - if (mag > 0) { - mag = sqrt(mag); - a[0] /= mag; - a[1] /= mag; - a[2] /= mag; - } + double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2]; + if (mag > 0) { + mag = sqrt(mag); + a[0] /= mag; + a[1] /= mag; + a[2] /= mag; + } } /* Create projection axes for cube+triangle intersection testing. @@ -118,114 +111,115 @@ static void normalize(double a[3]) */ static void create_projection_axes(int64_t axes[NUM_AXES][3], const int64_t tri[3][3]) { - /* Cube face normals */ - axes[0][0] = 1; - axes[0][1] = 0; - axes[0][2] = 0; - axes[1][0] = 0; - axes[1][1] = 1; - axes[1][2] = 0; - axes[2][0] = 0; - axes[2][1] = 0; - axes[2][2] = 1; - - /* Get triangle edge vectors */ - int64_t tri_edges[3][3]; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) - tri_edges[i][j] = tri[(i + 1) % 3][j] - tri[i][j]; - } - - /* Triangle normal */ - crossProduct(axes[3], tri_edges[0], tri_edges[1]); - - // Face edges and triangle edges - int ct = 4; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - crossProduct(axes[ct], axes[j], tri_edges[i]); - ct++; - } - } + /* Cube face normals */ + axes[0][0] = 1; + axes[0][1] = 0; + axes[0][2] = 0; + axes[1][0] = 0; + axes[1][1] = 1; + axes[1][2] = 0; + axes[2][0] = 0; + axes[2][1] = 0; + axes[2][2] = 1; + + /* Get triangle edge vectors */ + int64_t tri_edges[3][3]; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) + tri_edges[i][j] = tri[(i + 1) % 3][j] - tri[i][j]; + } + + /* Triangle normal */ + crossProduct(axes[3], tri_edges[0], tri_edges[1]); + + // Face edges and triangle edges + int ct = 4; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + crossProduct(axes[ct], axes[j], tri_edges[i]); + ct++; + } + } } /** * Construction from a cube (axes aligned) and triangle */ -CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], int64_t tri[3][3], int64_t /*error*/, int triind) +CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], + int64_t tri[3][3], + int64_t /*error*/, + int triind) { - int i; - inherit = new TriangleProjection; - inherit->index = triind; - - int64_t axes[NUM_AXES][3]; - create_projection_axes(axes, tri); - - /* Normalize face normal and store */ - double dedge1[] = {(double)tri[1][0] - (double)tri[0][0], - (double)tri[1][1] - (double)tri[0][1], - (double)tri[1][2] - (double)tri[0][2]}; - double dedge2[] = {(double)tri[2][0] - (double)tri[1][0], - (double)tri[2][1] - (double)tri[1][1], - (double)tri[2][2] - (double)tri[1][2]}; - crossProduct(inherit->norm, dedge1, dedge2); - normalize(inherit->norm); - - int64_t cubeedge[3][3]; - for (i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - cubeedge[i][j] = 0; - } - cubeedge[i][i] = cube[1][i] - cube[0][i]; - } - - /* Project the cube on to each axis */ - for (int axis = 0; axis < NUM_AXES; axis++) { - CubeProjection &cube_proj = cubeProj[axis]; - - /* Origin */ - cube_proj.origin = dotProduct(axes[axis], cube[0]); - - /* 3 direction vectors */ - for (i = 0; i < 3; i++) - cube_proj.edges[i] = dotProduct(axes[axis], cubeedge[i]); - - /* Offsets of 2 ends of cube projection */ - int64_t max = 0; - int64_t min = 0; - for (i = 1; i < 8; i++) { - int64_t proj = (vertmap[i][0] * cube_proj.edges[0] + - vertmap[i][1] * cube_proj.edges[1] + - vertmap[i][2] * cube_proj.edges[2]); - if (proj > max) { - max = proj; - } - if (proj < min) { - min = proj; - } - } - cube_proj.min = min; - cube_proj.max = max; - - } - - /* Project the triangle on to each axis */ - for (int axis = 0; axis < NUM_AXES; axis++) { - const int64_t vts[3] = {dotProduct(axes[axis], tri[0]), - dotProduct(axes[axis], tri[1]), - dotProduct(axes[axis], tri[2])}; - - // Triangle - inherit->tri_proj[axis][0] = vts[0]; - inherit->tri_proj[axis][1] = vts[0]; - for (i = 1; i < 3; i++) { - if (vts[i] < inherit->tri_proj[axis][0]) - inherit->tri_proj[axis][0] = vts[i]; - - if (vts[i] > inherit->tri_proj[axis][1]) - inherit->tri_proj[axis][1] = vts[i]; - } - } + int i; + inherit = new TriangleProjection; + inherit->index = triind; + + int64_t axes[NUM_AXES][3]; + create_projection_axes(axes, tri); + + /* Normalize face normal and store */ + double dedge1[] = {(double)tri[1][0] - (double)tri[0][0], + (double)tri[1][1] - (double)tri[0][1], + (double)tri[1][2] - (double)tri[0][2]}; + double dedge2[] = {(double)tri[2][0] - (double)tri[1][0], + (double)tri[2][1] - (double)tri[1][1], + (double)tri[2][2] - (double)tri[1][2]}; + crossProduct(inherit->norm, dedge1, dedge2); + normalize(inherit->norm); + + int64_t cubeedge[3][3]; + for (i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + cubeedge[i][j] = 0; + } + cubeedge[i][i] = cube[1][i] - cube[0][i]; + } + + /* Project the cube on to each axis */ + for (int axis = 0; axis < NUM_AXES; axis++) { + CubeProjection &cube_proj = cubeProj[axis]; + + /* Origin */ + cube_proj.origin = dotProduct(axes[axis], cube[0]); + + /* 3 direction vectors */ + for (i = 0; i < 3; i++) + cube_proj.edges[i] = dotProduct(axes[axis], cubeedge[i]); + + /* Offsets of 2 ends of cube projection */ + int64_t max = 0; + int64_t min = 0; + for (i = 1; i < 8; i++) { + int64_t proj = (vertmap[i][0] * cube_proj.edges[0] + vertmap[i][1] * cube_proj.edges[1] + + vertmap[i][2] * cube_proj.edges[2]); + if (proj > max) { + max = proj; + } + if (proj < min) { + min = proj; + } + } + cube_proj.min = min; + cube_proj.max = max; + } + + /* Project the triangle on to each axis */ + for (int axis = 0; axis < NUM_AXES; axis++) { + const int64_t vts[3] = {dotProduct(axes[axis], tri[0]), + dotProduct(axes[axis], tri[1]), + dotProduct(axes[axis], tri[2])}; + + // Triangle + inherit->tri_proj[axis][0] = vts[0]; + inherit->tri_proj[axis][1] = vts[0]; + for (i = 1; i < 3; i++) { + if (vts[i] < inherit->tri_proj[axis][0]) + inherit->tri_proj[axis][0] = vts[i]; + + if (vts[i] > inherit->tri_proj[axis][1]) + inherit->tri_proj[axis][1] = vts[i]; + } + } } /** @@ -234,67 +228,64 @@ CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], int64_t tri[3][3], int6 */ CubeTriangleIsect::CubeTriangleIsect(CubeTriangleIsect *parent) { - // Copy inheritable projections - this->inherit = parent->inherit; + // Copy inheritable projections + this->inherit = parent->inherit; - // Shrink cube projections - for (int i = 0; i < NUM_AXES; i++) { - cubeProj[i].origin = parent->cubeProj[i].origin; + // Shrink cube projections + for (int i = 0; i < NUM_AXES; i++) { + cubeProj[i].origin = parent->cubeProj[i].origin; - for (int j = 0; j < 3; j++) - cubeProj[i].edges[j] = parent->cubeProj[i].edges[j] >> 1; + for (int j = 0; j < 3; j++) + cubeProj[i].edges[j] = parent->cubeProj[i].edges[j] >> 1; - cubeProj[i].min = parent->cubeProj[i].min >> 1; - cubeProj[i].max = parent->cubeProj[i].max >> 1; - } + cubeProj[i].min = parent->cubeProj[i].min >> 1; + cubeProj[i].max = parent->cubeProj[i].max >> 1; + } } -unsigned char CubeTriangleIsect::getBoxMask( ) +unsigned char CubeTriangleIsect::getBoxMask() { - int i, j, k; - int bmask[3][2] = {{0, 0}, {0, 0}, {0, 0}}; - unsigned char boxmask = 0; - int64_t child_len = cubeProj[0].edges[0] >> 1; - - for (i = 0; i < 3; i++) { - int64_t mid = cubeProj[i].origin + child_len; - - // Check bounding box - if (mid >= inherit->tri_proj[i][0]) { - bmask[i][0] = 1; - } - if (mid < inherit->tri_proj[i][1]) { - bmask[i][1] = 1; - } - - } - - // Fill in masks - int ct = 0; - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - for (k = 0; k < 2; k++) { - boxmask |= ( (bmask[0][i] & bmask[1][j] & bmask[2][k]) << ct); - ct++; - } - } - } - - // Return bounding box masks - return boxmask; + int i, j, k; + int bmask[3][2] = {{0, 0}, {0, 0}, {0, 0}}; + unsigned char boxmask = 0; + int64_t child_len = cubeProj[0].edges[0] >> 1; + + for (i = 0; i < 3; i++) { + int64_t mid = cubeProj[i].origin + child_len; + + // Check bounding box + if (mid >= inherit->tri_proj[i][0]) { + bmask[i][0] = 1; + } + if (mid < inherit->tri_proj[i][1]) { + bmask[i][1] = 1; + } + } + + // Fill in masks + int ct = 0; + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 2; k++) { + boxmask |= ((bmask[0][i] & bmask[1][j] & bmask[2][k]) << ct); + ct++; + } + } + } + + // Return bounding box masks + return boxmask; } - /** * Shifting a cube to a new origin */ void CubeTriangleIsect::shift(int off[3]) { - for (int i = 0; i < NUM_AXES; i++) { - cubeProj[i].origin += (off[0] * cubeProj[i].edges[0] + - off[1] * cubeProj[i].edges[1] + - off[2] * cubeProj[i].edges[2]); - } + for (int i = 0; i < NUM_AXES; i++) { + cubeProj[i].origin += (off[0] * cubeProj[i].edges[0] + off[1] * cubeProj[i].edges[1] + + off[2] * cubeProj[i].edges[2]); + } } /** @@ -302,75 +293,70 @@ void CubeTriangleIsect::shift(int off[3]) */ int CubeTriangleIsect::isIntersecting() const { - for (int i = 0; i < NUM_AXES; i++) { - /* - int64_t proj0 = cubeProj[i][0] + - vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] + - vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] + - vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ; - int64_t proj1 = cubeProj[i][0] + - vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] + - vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] + - vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ; - */ - - int64_t proj0 = cubeProj[i].origin + cubeProj[i].min; - int64_t proj1 = cubeProj[i].origin + cubeProj[i].max; - - if (proj0 > inherit->tri_proj[i][1] || - proj1 < inherit->tri_proj[i][0]) { - return 0; - } - } - - return 1; + for (int i = 0; i < NUM_AXES; i++) { + /* + int64_t proj0 = cubeProj[i][0] + + vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] + + vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] + + vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ; + int64_t proj1 = cubeProj[i][0] + + vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] + + vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] + + vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ; + */ + + int64_t proj0 = cubeProj[i].origin + cubeProj[i].min; + int64_t proj1 = cubeProj[i].origin + cubeProj[i].max; + + if (proj0 > inherit->tri_proj[i][1] || proj1 < inherit->tri_proj[i][0]) { + return 0; + } + } + + return 1; } int CubeTriangleIsect::isIntersectingPrimary(int edgeInd) const { - for (int i = 0; i < NUM_AXES; i++) { - - int64_t proj0 = cubeProj[i].origin; - int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd]; - - if (proj0 < proj1) { - if (proj0 > inherit->tri_proj[i][1] || - proj1 < inherit->tri_proj[i][0]) { - return 0; - } - } - else { - if (proj1 > inherit->tri_proj[i][1] || - proj0 < inherit->tri_proj[i][0]) { - return 0; - } - } - - } - - // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ; - return 1; + for (int i = 0; i < NUM_AXES; i++) { + + int64_t proj0 = cubeProj[i].origin; + int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd]; + + if (proj0 < proj1) { + if (proj0 > inherit->tri_proj[i][1] || proj1 < inherit->tri_proj[i][0]) { + return 0; + } + } + else { + if (proj1 > inherit->tri_proj[i][1] || proj0 < inherit->tri_proj[i][0]) { + return 0; + } + } + } + + // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ; + return 1; } float CubeTriangleIsect::getIntersectionPrimary(int edgeInd) const { - int i = 3; - + int i = 3; - int64_t proj0 = cubeProj[i].origin; - int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd]; - int64_t proj2 = inherit->tri_proj[i][1]; - int64_t d = proj1 - proj0; - double alpha; + int64_t proj0 = cubeProj[i].origin; + int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd]; + int64_t proj2 = inherit->tri_proj[i][1]; + int64_t d = proj1 - proj0; + double alpha; - if (d == 0) - alpha = 0.5; - else { - alpha = (double)((proj2 - proj0)) / (double)d; + if (d == 0) + alpha = 0.5; + else { + alpha = (double)((proj2 - proj0)) / (double)d; - if (alpha < 0 || alpha > 1) - alpha = 0.5; - } + if (alpha < 0 || alpha > 1) + alpha = 0.5; + } - return (float)alpha; + return (float)alpha; } diff --git a/intern/dualcon/intern/Projections.h b/intern/dualcon/intern/Projections.h index e77c234b058..fc650158a0b 100644 --- a/intern/dualcon/intern/Projections.h +++ b/intern/dualcon/intern/Projections.h @@ -24,11 +24,11 @@ #define GRID_DIMENSION 20 #if defined(_WIN32) && !(_MSC_VER >= 1900) -#define isnan(n) _isnan(n) -#define LONG __int64 -#define int64_t __int64 +# define isnan(n) _isnan(n) +# define LONG __int64 +# define int64_t __int64 #else -#include +# include #endif /** @@ -59,71 +59,70 @@ extern const int facemap[6][4]; * Structure for the projections inheritable from parent */ struct TriangleProjection { - /// Projections of triangle (min and max) - int64_t tri_proj[NUM_AXES][2]; + /// Projections of triangle (min and max) + int64_t tri_proj[NUM_AXES][2]; - /// Normal of the triangle - double norm[3]; + /// Normal of the triangle + double norm[3]; - /// Index of polygon - int index; + /// Index of polygon + int index; }; /* This is a projection for the cube against a single projection axis, see CubeTriangleIsect.cubeProj */ struct CubeProjection { - int64_t origin; - int64_t edges[3]; - int64_t min, max; + int64_t origin; + int64_t edges[3]; + int64_t min, max; }; - /** * Class for projections of cube / triangle vertices on the separating axes */ -class CubeTriangleIsect -{ -public: - /// Inheritable portion - TriangleProjection *inherit; - - /// Projections of the cube vertices - CubeProjection cubeProj[NUM_AXES]; - -public: - CubeTriangleIsect() {} - - /** - * Construction from a cube (axes aligned) and triangle - */ - CubeTriangleIsect(int64_t cube[2][3], int64_t trig[3][3], int64_t error, int triind); - - /** - * Construction from a parent CubeTriangleIsect object and the index of - * the children - */ - CubeTriangleIsect(CubeTriangleIsect *parent); - - unsigned char getBoxMask( ); - - /** - * Shifting a cube to a new origin - */ - void shift(int off[3]); - - /** - * Method to test intersection of the triangle and the cube - */ - int isIntersecting() const; - - int isIntersectingPrimary(int edgeInd) const; - - float getIntersectionPrimary(int edgeInd) const; +class CubeTriangleIsect { + public: + /// Inheritable portion + TriangleProjection *inherit; + + /// Projections of the cube vertices + CubeProjection cubeProj[NUM_AXES]; + + public: + CubeTriangleIsect() + { + } + + /** + * Construction from a cube (axes aligned) and triangle + */ + CubeTriangleIsect(int64_t cube[2][3], int64_t trig[3][3], int64_t error, int triind); + + /** + * Construction from a parent CubeTriangleIsect object and the index of + * the children + */ + CubeTriangleIsect(CubeTriangleIsect *parent); + + unsigned char getBoxMask(); + + /** + * Shifting a cube to a new origin + */ + void shift(int off[3]); + + /** + * Method to test intersection of the triangle and the cube + */ + int isIntersecting() const; + + int isIntersectingPrimary(int edgeInd) const; + + float getIntersectionPrimary(int edgeInd) const; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:CubeTriangleIsect") + MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:CubeTriangleIsect") #endif - }; -#endif /* __PROJECTIONS_H__ */ +#endif /* __PROJECTIONS_H__ */ diff --git a/intern/dualcon/intern/Queue.h b/intern/dualcon/intern/Queue.h index 1a257aa9a85..2620ab6cb32 100644 --- a/intern/dualcon/intern/Queue.h +++ b/intern/dualcon/intern/Queue.h @@ -18,85 +18,78 @@ #define __QUEUE_H__ struct gridQueueEle { - int x, y, z; - UCHAR dir; - gridQueueEle *next; + int x, y, z; + UCHAR dir; + gridQueueEle *next; }; -class GridQueue -{ -gridQueueEle *head; -gridQueueEle *tail; -int numEles; - -public: - -GridQueue( ) -{ - head = NULL; - tail = NULL; - numEles = 0; -} - -gridQueueEle *getHead( ) -{ - return head; -} - -int getNumElements( ) -{ - return numEles; -} - - -void pushQueue(int st[3], int dir) -{ - gridQueueEle *ele = new gridQueueEle; - ele->x = st[0]; - ele->y = st[1]; - ele->z = st[2]; - ele->dir = (UCHAR) dir; - ele->next = NULL; - if (head == NULL) - { - head = ele; - } - else { - tail->next = ele; - } - tail = ele; - numEles++; -} - -int popQueue(int st[3], int& dir) -{ - if (head == NULL) - { - return 0; - } - - st[0] = head->x; - st[1] = head->y; - st[2] = head->z; - dir = (int) (head->dir); - - gridQueueEle *temp = head; - head = head->next; - delete temp; - - if (head == NULL) - { - tail = NULL; - } - numEles--; - - return 1; -} +class GridQueue { + gridQueueEle *head; + gridQueueEle *tail; + int numEles; + + public: + GridQueue() + { + head = NULL; + tail = NULL; + numEles = 0; + } + + gridQueueEle *getHead() + { + return head; + } + + int getNumElements() + { + return numEles; + } + + void pushQueue(int st[3], int dir) + { + gridQueueEle *ele = new gridQueueEle; + ele->x = st[0]; + ele->y = st[1]; + ele->z = st[2]; + ele->dir = (UCHAR)dir; + ele->next = NULL; + if (head == NULL) { + head = ele; + } + else { + tail->next = ele; + } + tail = ele; + numEles++; + } + + int popQueue(int st[3], int &dir) + { + if (head == NULL) { + return 0; + } + + st[0] = head->x; + st[1] = head->y; + st[2] = head->z; + dir = (int)(head->dir); + + gridQueueEle *temp = head; + head = head->next; + delete temp; + + if (head == NULL) { + tail = NULL; + } + numEles--; + + return 1; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:GridQueue") + MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:GridQueue") #endif - }; -#endif /* __QUEUE_H__ */ +#endif /* __QUEUE_H__ */ diff --git a/intern/dualcon/intern/cubes.h b/intern/dualcon/intern/cubes.h index 1a8413524d4..3561ce008c2 100644 --- a/intern/dualcon/intern/cubes.h +++ b/intern/dualcon/intern/cubes.h @@ -20,26 +20,24 @@ #include "marching_cubes_table.h" /* simple wrapper for auto-generated marching cubes data */ -class Cubes -{ -public: -/// Get number of triangles -int getNumTriangle(int mask) -{ - return marching_cubes_numtri[mask]; -} +class Cubes { + public: + /// Get number of triangles + int getNumTriangle(int mask) + { + return marching_cubes_numtri[mask]; + } -/// Get a triangle -void getTriangle(int mask, int index, int indices[3]) -{ - for (int i = 0; i < 3; i++) - indices[i] = marching_cubes_tris[mask][index][i]; -} + /// Get a triangle + void getTriangle(int mask, int index, int indices[3]) + { + for (int i = 0; i < 3; i++) + indices[i] = marching_cubes_tris[mask][index][i]; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Cubes") + MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Cubes") #endif - }; -#endif /* __CUBES_H__ */ +#endif /* __CUBES_H__ */ diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp index 01aa8a608db..459bb711e13 100644 --- a/intern/dualcon/intern/dualcon_c_api.cpp +++ b/intern/dualcon/intern/dualcon_c_api.cpp @@ -23,141 +23,139 @@ #include #if defined(_WIN32) -#define isnan(n) _isnan(n) +# define isnan(n) _isnan(n) #endif static void veccopy(float dst[3], const float src[3]) { - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; } #define GET_TRI(_mesh, _n) \ - (*(DualConTri)(((char *)(_mesh)->looptri) + ((_n) * (_mesh)->tri_stride))) + (*(DualConTri)(((char *)(_mesh)->looptri) + ((_n) * (_mesh)->tri_stride))) -#define GET_CO(_mesh, _n) \ - (*(DualConCo)(((char *)(_mesh)->co) + ((_n) * (_mesh)->co_stride))) +#define GET_CO(_mesh, _n) (*(DualConCo)(((char *)(_mesh)->co) + ((_n) * (_mesh)->co_stride))) #define GET_LOOP(_mesh, _n) \ - (*(DualConLoop)(((char *)(_mesh)->mloop) + ((_n) * (_mesh)->loop_stride))) - -class DualConInputReader : public ModelReader -{ -private: -const DualConInput *input_mesh; -int tottri, curtri; -float min[3], max[3], maxsize; -float scale; -public: -DualConInputReader(const DualConInput *mesh, float _scale) - : input_mesh(mesh), scale(_scale) -{ - reset(); -} - -void reset() -{ - curtri = 0; - maxsize = 0; - tottri = input_mesh->tottri; - - veccopy(min, input_mesh->min); - veccopy(max, input_mesh->max); - - /* initialize maxsize */ - for (int i = 0; i < 3; i++) { - float d = max[i] - min[i]; - if (d > maxsize) - maxsize = d; - } - - /* redo the bounds */ - for (int i = 0; i < 3; i++) - { - min[i] = (max[i] + min[i]) / 2 - maxsize / 2; - max[i] = (max[i] + min[i]) / 2 + maxsize / 2; - } - - for (int i = 0; i < 3; i++) - min[i] -= maxsize * (1 / scale - 1) / 2; - maxsize *= 1 / scale; -} - -Triangle *getNextTriangle() -{ - if (curtri == input_mesh->tottri) - return NULL; - - Triangle *t = new Triangle(); - - unsigned int *tr = GET_TRI(input_mesh, curtri); - veccopy(t->vt[0], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[0]))); - veccopy(t->vt[1], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[1]))); - veccopy(t->vt[2], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[2]))); - - curtri++; - - /* remove triangle if it contains invalid coords */ - for (int i = 0; i < 3; i++) { - const float *co = t->vt[i]; - if (isnan(co[0]) || isnan(co[1]) || isnan(co[2])) { - delete t; - return getNextTriangle(); - } - } - - return t; -} - -int getNextTriangle(int t[3]) -{ - if (curtri == input_mesh->tottri) - return 0; - - unsigned int *tr = GET_TRI(input_mesh, curtri); - t[0] = tr[0]; - t[1] = tr[1]; - t[2] = tr[2]; - - curtri++; - - return 1; -} - -int getNumTriangles() -{ - return tottri; -} - -int getNumVertices() -{ - return input_mesh->totco; -} - -float getBoundingBox(float origin[3]) -{ - veccopy(origin, min); - return maxsize; -} - -/* output */ -void getNextVertex(float /*v*/[3]) -{ - /* not used */ -} - -/* stubs */ -void printInfo() { -} -int getMemory() { - return sizeof(DualConInputReader); -} + (*(DualConLoop)(((char *)(_mesh)->mloop) + ((_n) * (_mesh)->loop_stride))) + +class DualConInputReader : public ModelReader { + private: + const DualConInput *input_mesh; + int tottri, curtri; + float min[3], max[3], maxsize; + float scale; + + public: + DualConInputReader(const DualConInput *mesh, float _scale) : input_mesh(mesh), scale(_scale) + { + reset(); + } + + void reset() + { + curtri = 0; + maxsize = 0; + tottri = input_mesh->tottri; + + veccopy(min, input_mesh->min); + veccopy(max, input_mesh->max); + + /* initialize maxsize */ + for (int i = 0; i < 3; i++) { + float d = max[i] - min[i]; + if (d > maxsize) + maxsize = d; + } + + /* redo the bounds */ + for (int i = 0; i < 3; i++) { + min[i] = (max[i] + min[i]) / 2 - maxsize / 2; + max[i] = (max[i] + min[i]) / 2 + maxsize / 2; + } + + for (int i = 0; i < 3; i++) + min[i] -= maxsize * (1 / scale - 1) / 2; + maxsize *= 1 / scale; + } + + Triangle *getNextTriangle() + { + if (curtri == input_mesh->tottri) + return NULL; + + Triangle *t = new Triangle(); + + unsigned int *tr = GET_TRI(input_mesh, curtri); + veccopy(t->vt[0], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[0]))); + veccopy(t->vt[1], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[1]))); + veccopy(t->vt[2], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[2]))); + + curtri++; + + /* remove triangle if it contains invalid coords */ + for (int i = 0; i < 3; i++) { + const float *co = t->vt[i]; + if (isnan(co[0]) || isnan(co[1]) || isnan(co[2])) { + delete t; + return getNextTriangle(); + } + } + + return t; + } + + int getNextTriangle(int t[3]) + { + if (curtri == input_mesh->tottri) + return 0; + + unsigned int *tr = GET_TRI(input_mesh, curtri); + t[0] = tr[0]; + t[1] = tr[1]; + t[2] = tr[2]; + + curtri++; + + return 1; + } + + int getNumTriangles() + { + return tottri; + } + + int getNumVertices() + { + return input_mesh->totco; + } + + float getBoundingBox(float origin[3]) + { + veccopy(origin, min); + return maxsize; + } + + /* output */ + void getNextVertex(float /*v*/[3]) + { + /* not used */ + } + + /* stubs */ + void printInfo() + { + } + int getMemory() + { + return sizeof(DualConInputReader); + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:DualConInputReader") + MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:DualConInputReader") #endif - }; void *dualcon(const DualConInput *input_mesh, @@ -173,9 +171,8 @@ void *dualcon(const DualConInput *input_mesh, float scale, int depth) { - DualConInputReader r(input_mesh, scale); - Octree o(&r, alloc_output, add_vert, add_quad, - flags, mode, depth, threshold, hermite_num); - o.scanConvert(); - return o.getOutputMesh(); + DualConInputReader r(input_mesh, scale); + Octree o(&r, alloc_output, add_vert, add_quad, flags, mode, depth, threshold, hermite_num); + o.scanConvert(); + return o.getOutputMesh(); } diff --git a/intern/dualcon/intern/manifold_table.cpp b/intern/dualcon/intern/manifold_table.cpp index baa6b82a91f..d08e1fd27c0 100644 --- a/intern/dualcon/intern/manifold_table.cpp +++ b/intern/dualcon/intern/manifold_table.cpp @@ -16,261 +16,3331 @@ #include "manifold_table.h" -const ManifoldIndices manifold_table[256] = { - {0, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}}, - {3, {{1, 1}, {2, 2}, {3, 3}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {3, 3}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}}, - {2, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {0, 0}}}, - {2, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}}, - {3, {{1, 1}, {2, 2}, {0, 0}, {3, 3}, {1, 1}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}, {2, 2}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {2, {{0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 2}, {2, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {1, 2}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}}, - {2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}}, - {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}}, - {3, {{1, 1}, {0, 0}, {2, 2}, {3, 3}, {1, 1}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}, {0, 0}, {2, 2}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}}, - {2, {{1, 1}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}}, - {2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}}, - {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}}}, - {2, {{1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {1, 1}}}, - {2, {{0, 0}, {1, 2}, {1, 1}, {2, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}}, - {2, {{2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 2}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}}, - {3, {{1, 1}, {2, 2}, {3, 3}, {0, 0}, {1, 1}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {3, 3}}}, - {2, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {2, 2}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {1, 1}}}, - {2, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {1, 1}}}, - {2, {{2, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 2}, {1, 1}, {2, 2}}}, - {3, {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {3, 3}, {1, 1}, {2, 2}}}, - {4, {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 1}, {4, 4}, {3, 3}, {2, 2}, {1, 1}, {4, 4}, {2, 2}, {3, 3}}}, - {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {1, 1}}}, - {2, {{0, 0}, {0, 0}, {0, 0}, {2, 1}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 2}, {0, 0}, {2, 2}, {1, 1}}}, - {2, {{1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}}}, - {1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}}, - {2, {{2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 2}, {2, 2}, {1, 1}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}}, - {2, {{1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}}, - {2, {{0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}}}, - {2, {{1, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}}, - {2, {{0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}}, - {2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}}}, - {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}}, - {2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}}}, - {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}}, - {2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}}, - {3, {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {3, 3}, {1, 1}, {2, 2}, {0, 0}, {3, 3}}}, - {2, {{1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}}, - {2, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}}}, - {3, {{1, 1}, {2, 2}, {0, 0}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}}, - {3, {{1, 1}, {0, 0}, {2, 2}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}}}, - {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}}}, - {4, {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {3, 3}, {2, 2}, {1, 1}, {4, 4}, {2, 2}, {3, 3}, {1, 1}, {4, 4}}}, - {2, {{0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}}}, - {2, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}}}, - {2, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {2, 2}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {2, 2}}}, - {2, {{0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}}, - {2, {{0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 2}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}}}, - {2, {{1, 1}, {2, 2}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}}}, - {2, {{0, 0}, {1, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}}, - {2, {{1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {2, 2}}}, - {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {2, 2}}}, - {2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 2}, {2, 2}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}}, - {2, {{2, 2}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {2, {{1, 1}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 2}, {2, 2}, {0, 0}, {1, 1}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}}}, - {2, {{0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 2}, {2, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}}, - {2, {{0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 2}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}}, - {2, {{2, 2}, {1, 2}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 1}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}}, - {2, {{2, 2}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}}, - {2, {{1, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 1}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 2}, {0, 0}, {2, 1}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {1, 2}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 2}, {2, 1}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{0, 0}, {0, 0}, {2, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 2}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 2}, {1, 1}, {0, 0}}}, - {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}}}, - {2, {{0, 0}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 1}, {1, 2}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 1}, {1, 2}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {1, 2}, {2, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{1, 2}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {2, {{0, 0}, {1, 2}, {2, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}}, - {0, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}} -}; +const ManifoldIndices manifold_table[256] = {{0, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {3, + {{1, 1}, + {2, 2}, + {3, 3}, + {0, 0}, + {3, 3}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {3, 3}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}}}, + {2, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {2, 2}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {2, 2}, + {2, 2}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {2, 2}, + {2, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}}}, + {2, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}}}, + {3, + {{1, 1}, + {2, 2}, + {0, 0}, + {3, 3}, + {1, 1}, + {3, 3}, + {0, 0}, + {2, 2}, + {1, 1}, + {3, 3}, + {2, 2}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {2, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {1, 1}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {1, 1}, + {2, 2}, + {2, 2}, + {2, 2}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {2, + {{0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 2}, + {2, 2}, + {2, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {1, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}}}, + {2, + {{1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {2, + {{0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}}}, + {3, + {{1, 1}, + {0, 0}, + {2, 2}, + {3, 3}, + {1, 1}, + {3, 3}, + {2, 2}, + {0, 0}, + {1, 1}, + {3, 3}, + {0, 0}, + {2, 2}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}}}, + {2, + {{1, 1}, + {1, 1}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {2, + {{1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {1, 1}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}}}, + {2, + {{0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {1, 1}}}, + {2, + {{1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {2, 2}, + {1, 1}, + {1, 1}}}, + {2, + {{0, 0}, + {1, 2}, + {1, 1}, + {2, 2}, + {2, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {2, + {{2, 2}, + {1, 1}, + {0, 0}, + {1, 1}, + {2, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 2}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {3, + {{1, 1}, + {2, 2}, + {3, 3}, + {0, 0}, + {1, 1}, + {0, 0}, + {3, 3}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {3, 3}}}, + {2, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {1, 1}, + {2, 2}, + {1, 1}}}, + {2, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {2, 2}, + {1, 1}, + {2, 2}, + {1, 1}}}, + {2, + {{2, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {1, 2}, + {1, 1}, + {2, 2}}}, + {3, + {{0, 0}, + {1, 1}, + {2, 2}, + {3, 3}, + {0, 0}, + {3, 3}, + {2, 2}, + {1, 1}, + {0, 0}, + {3, 3}, + {1, 1}, + {2, 2}}}, + {4, + {{1, 1}, + {2, 2}, + {3, 3}, + {4, 4}, + {1, 1}, + {4, 4}, + {3, 3}, + {2, 2}, + {1, 1}, + {4, 4}, + {2, 2}, + {3, 3}}}, + {2, + {{0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {2, 2}, + {2, 2}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {2, 2}, + {2, 2}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}}}, + {2, + {{0, 0}, + {0, 0}, + {0, 0}, + {2, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 2}, + {0, 0}, + {2, 2}, + {1, 1}}}, + {2, + {{1, 2}, + {0, 0}, + {0, 0}, + {2, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}}}, + {1, + {{1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {2, + {{2, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 2}, + {2, 2}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {2, + {{1, 1}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}}}, + {2, + {{0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}}}, + {2, + {{1, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}}}, + {2, + {{0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 2}, + {0, 0}, + {0, 0}, + {2, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}}}, + {2, + {{1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 1}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 2}, + {0, 0}, + {0, 0}, + {2, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}}}, + {2, + {{1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}}}, + {2, + {{0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}}}, + {2, + {{1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}}}, + {3, + {{0, 0}, + {1, 1}, + {2, 2}, + {3, 3}, + {2, 2}, + {1, 1}, + {0, 0}, + {3, 3}, + {1, 1}, + {2, 2}, + {0, 0}, + {3, 3}}}, + {2, + {{1, 1}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {2, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}}}, + {3, + {{1, 1}, + {2, 2}, + {0, 0}, + {3, 3}, + {0, 0}, + {2, 2}, + {1, 1}, + {3, 3}, + {2, 2}, + {0, 0}, + {1, 1}, + {3, 3}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {3, + {{1, 1}, + {0, 0}, + {2, 2}, + {3, 3}, + {2, 2}, + {0, 0}, + {1, 1}, + {3, 3}, + {0, 0}, + {2, 2}, + {1, 1}, + {3, 3}}}, + {2, + {{0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {1, 1}, + {1, 1}, + {2, 2}}}, + {4, + {{1, 1}, + {2, 2}, + {3, 3}, + {4, 4}, + {3, 3}, + {2, 2}, + {1, 1}, + {4, 4}, + {2, 2}, + {3, 3}, + {1, 1}, + {4, 4}}}, + {2, + {{0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}}}, + {2, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}}}, + {2, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {2, 2}, + {1, 1}, + {2, 2}}}, + {2, + {{0, 0}, + {2, 1}, + {0, 0}, + {0, 0}, + {1, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {2, + {{0, 0}, + {0, 0}, + {2, 1}, + {0, 0}, + {0, 0}, + {1, 2}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {2, + {{1, 1}, + {2, 2}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {2, + {{0, 0}, + {1, 2}, + {2, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {2, 2}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}}}, + {2, + {{1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {2, 2}}}, + {2, + {{0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {2, 2}}}, + {2, + {{1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 2}, + {2, 2}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {2, 2}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {2, + {{2, 2}, + {1, 1}, + {1, 2}, + {0, 0}, + {0, 0}, + {2, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {2, + {{1, 1}, + {1, 1}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 1}, + {0, 0}, + {1, 2}, + {2, 2}, + {0, 0}, + {1, 1}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}}}, + {2, + {{0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {1, 2}, + {2, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {2, + {{0, 0}, + {2, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 2}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}}}, + {2, + {{2, 2}, + {1, 2}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 1}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}}}, + {2, + {{2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 2}, + {0, 0}, + {0, 0}, + {2, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {1, 1}, + {2, 2}, + {2, 2}, + {1, 1}, + {1, 1}, + {2, 2}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {2, 2}, + {1, 1}, + {2, 2}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {2, 2}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 2}, + {0, 0}, + {2, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {1, 2}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {2, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 2}, + {2, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{0, 0}, + {0, 0}, + {2, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {1, 2}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 1}, + {2, 2}, + {1, 2}, + {1, 1}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {1, 2}, + {0, 0}, + {0, 0}, + {2, 1}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {2, 2}, + {2, 2}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{2, 2}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {1, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {2, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {1, 2}, + {0, 0}, + {0, 0}, + {2, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {2, 2}, + {0, 0}}}, + {2, + {{0, 0}, + {0, 0}, + {0, 0}, + {2, 1}, + {2, 2}, + {1, 1}, + {1, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {0, 0}, + {1, 1}, + {2, 2}, + {2, 2}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}, + {0, 0}, + {2, 1}, + {1, 2}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {2, + {{1, 1}, + {2, 2}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 2}, + {2, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {2, 2}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{1, 2}, + {0, 0}, + {0, 0}, + {2, 1}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {2, 2}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {2, + {{0, 0}, + {1, 2}, + {2, 1}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}, + {2, 2}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {1, + {{1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}, + {1, 1}, + {0, 0}, + {0, 0}, + {0, 0}}}, + {0, + {{0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}}}; diff --git a/intern/dualcon/intern/manifold_table.h b/intern/dualcon/intern/manifold_table.h index 2d60041312a..4f15afefa75 100644 --- a/intern/dualcon/intern/manifold_table.h +++ b/intern/dualcon/intern/manifold_table.h @@ -18,10 +18,10 @@ #define __MANIFOLD_TABLE_H__ typedef struct { - int comps; - int pairs[12][2]; + int comps; + int pairs[12][2]; } ManifoldIndices; extern const ManifoldIndices manifold_table[256]; -#endif /* __MANIFOLD_TABLE_H__ */ +#endif /* __MANIFOLD_TABLE_H__ */ diff --git a/intern/dualcon/intern/marching_cubes_table.cpp b/intern/dualcon/intern/marching_cubes_table.cpp index 85b6813f483..5270be25033 100644 --- a/intern/dualcon/intern/marching_cubes_table.cpp +++ b/intern/dualcon/intern/marching_cubes_table.cpp @@ -18,531 +18,2574 @@ /* number of triangles in each configuration */ const int marching_cubes_numtri[TOTCONF] = { - 0, 1, 1, 2, 1, 2, 4, 3, 1, 4, 2, 3, 2, 3, 3, 2, 1, 2, 4, 3, 4, 3, 5, 4, - 6, 5, 5, 4, 5, 4, 4, 3, 1, 4, 2, 3, 6, 5, 5, 4, 4, 5, 3, 4, 5, 4, 4, 3, - 2, 3, 3, 2, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 1, 4, 6, 5, 2, 3, 5, 4, - 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 2, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, - 4, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, - 4, 3, 3, 2, 3, 2, 2, 1, 1, 6, 4, 5, 4, 5, 5, 4, 2, 5, 3, 4, 3, 4, 4, 3, - 4, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 2, 5, 3, 4, 5, 4, 4, 3, - 3, 4, 2, 3, 4, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, - 2, 5, 5, 4, 3, 4, 4, 3, 3, 4, 4, 3, 2, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, - 4, 3, 3, 2, 3, 2, 2, 1, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, - 2, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0 -}; + 0, 1, 1, 2, 1, 2, 4, 3, 1, 4, 2, 3, 2, 3, 3, 2, 1, 2, 4, 3, 4, 3, 5, 4, 6, 5, 5, 4, 5, + 4, 4, 3, 1, 4, 2, 3, 6, 5, 5, 4, 4, 5, 3, 4, 5, 4, 4, 3, 2, 3, 3, 2, 5, 4, 4, 3, 5, 4, + 4, 3, 4, 3, 3, 2, 1, 4, 6, 5, 2, 3, 5, 4, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 2, 4, + 3, 5, 4, 4, 3, 4, 3, 3, 2, 4, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 3, 4, 4, 3, + 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 1, 6, 4, 5, 4, 5, 5, 4, 2, 5, 3, 4, 3, 4, 4, 3, 4, + 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 2, 5, 3, 4, 5, 4, 4, 3, 3, 4, 2, 3, 4, 3, + 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 2, 5, 5, 4, 3, 4, 4, 3, 3, 4, 4, + 3, 2, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 3, 4, 4, 3, 4, 3, 3, 2, + 4, 3, 3, 2, 3, 2, 2, 1, 2, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; /* table of triangles in each configuration */ -const int marching_cubes_tris[TOTCONF][MAX_TRIS][3] = { - {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 0, 8}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 1, 5}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 0, 1}, {4, 1, 5}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 9, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 8, 9}, {0, 9, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 5, 9}, {1, 9, 2}, {1, 2, 4}, {1, 4, 8}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 1, 5}, {0, 5, 9}, {0, 9, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 3, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 8, 5}, {0, 5, 3}, {0, 3, 9}, {0, 9, 4}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 1, 3}, {8, 3, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 0, 1}, {4, 1, 3}, {4, 3, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 5, 3}, {4, 3, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 8, 5}, {0, 5, 3}, {0, 3, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 1}, {4, 1, 3}, {4, 3, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 1, 3}, {0, 3, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 6, 10}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 4, 6}, {8, 6, 10}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 10, 1}, {6, 1, 5}, {6, 5, 8}, {6, 8, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 6, 10}, {4, 10, 1}, {4, 1, 5}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 0, 4}, {10, 4, 9}, {10, 9, 2}, {10, 2, 6}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 10, 8}, {6, 8, 9}, {6, 9, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {6, 10, 1}, {6, 1, 5}, {6, 5, 9}, {6, 9, 2}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 10, 1}, {6, 1, 5}, {6, 5, 9}, {6, 9, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 0, 5}, {0, 6, 9}, {9, 5, 0}, {6, 10, 3}, {5, 3, 10}, - {3, 9, 6}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 8, 5}, {10, 5, 3}, {9, 4, 6}, {6, 10, 3}, {6, 3, 9}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 3}, {9, 8, 0}, {9, 0, 6}, {6, 10, 3}, {6, 3, 9}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 6, 10}, {4, 10, 1}, {4, 1, 3}, {4, 3, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 4, 5}, {3, 2, 6}, {3, 6, 10}, {10, 0, 5}, {10, 5, 3}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 10, 8}, {6, 8, 5}, {6, 5, 3}, {6, 3, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {6, 10, 1}, {6, 1, 3}, {6, 3, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 10, 1}, {6, 1, 3}, {6, 3, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 7, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 0, 10}, {4, 10, 7}, {4, 7, 1}, {4, 1, 8}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 10, 7}, {8, 7, 5}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 0, 10}, {4, 10, 7}, {4, 7, 5}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 2, 4}, {10, 4, 1}, {7, 2, 10}, {1, 9, 7}, {1, 4, 9}, - {9, 2, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 8, 9}, {2, 0, 10}, {2, 10, 7}, {7, 1, 9}, {7, 9, 2}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 10}, {7, 5, 9}, {7, 9, 2}, {2, 4, 10}, {2, 10, 7}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 7}, {0, 7, 5}, {0, 5, 9}, {0, 9, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 7, 3}, {10, 3, 9}, {10, 9, 5}, {10, 5, 1}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {4, 0, 10}, {4, 10, 7}, {4, 7, 3}, {4, 3, 9}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 10, 7}, {8, 7, 3}, {8, 3, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 0, 10}, {4, 10, 7}, {4, 7, 3}, {4, 3, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 5, 1}, {4, 1, 10}, {7, 3, 2}, {2, 4, 10}, {2, 10, 7}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {0, 10, 7}, {0, 7, 3}, {0, 3, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 10}, {4, 10, 7}, {4, 7, 3}, {4, 3, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 7}, {0, 7, 3}, {0, 3, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 6, 7}, {0, 7, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 4, 6}, {8, 6, 7}, {8, 7, 1}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 0, 6}, {8, 6, 7}, {8, 7, 5}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 6, 7}, {4, 7, 5}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 0, 4}, {1, 4, 9}, {2, 6, 7}, {7, 1, 9}, {7, 9, 2}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 7, 1}, {6, 1, 8}, {6, 8, 9}, {6, 9, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {6, 7, 5}, {6, 5, 9}, {6, 9, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 7, 5}, {6, 5, 9}, {6, 9, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 1, 0}, {6, 7, 3}, {6, 3, 9}, {9, 5, 0}, {9, 0, 6}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {4, 6, 7}, {4, 7, 3}, {4, 3, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 0, 6}, {8, 6, 7}, {8, 7, 3}, {8, 3, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 6, 7}, {4, 7, 3}, {4, 3, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 4, 5}, {0, 5, 1}, {6, 7, 3}, {6, 3, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {6, 7, 3}, {6, 3, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {6, 7, 3}, {6, 3, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 7, 3}, {6, 3, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 2, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 4, 2}, {8, 2, 11}, {8, 11, 6}, {8, 6, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 1, 6}, {6, 1, 11}, {11, 1, 5}, {2, 11, 5}, {2, 5, 8}, - {6, 2, 8}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 1}, {5, 4, 2}, {5, 2, 11}, {11, 6, 1}, {11, 1, 5}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 4, 9}, {6, 9, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 8}, {6, 8, 9}, {6, 9, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 4, 8}, {6, 8, 1}, {5, 9, 11}, {11, 6, 1}, {11, 1, 5}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 1}, {6, 1, 5}, {6, 5, 9}, {6, 9, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 2, 9}, {6, 9, 5}, {6, 5, 3}, {6, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 2, 9}, {6, 0, 8}, {6, 8, 5}, {6, 5, 3}, {6, 3, 11}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{2, 9, 8}, {1, 3, 11}, {1, 11, 6}, {6, 2, 8}, {6, 8, 1}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 2, 9}, {6, 0, 1}, {6, 1, 3}, {6, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 4, 5}, {6, 5, 3}, {6, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 8}, {6, 8, 5}, {6, 5, 3}, {6, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 4, 8}, {6, 8, 1}, {6, 1, 3}, {6, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 1}, {6, 1, 3}, {6, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 0, 2}, {10, 2, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 8, 4}, {10, 4, 2}, {10, 2, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 0, 2}, {11, 10, 1}, {11, 1, 5}, {5, 8, 2}, {5, 2, 11}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 5}, {10, 5, 4}, {10, 4, 2}, {10, 2, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 0, 4}, {10, 4, 9}, {10, 9, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 8, 9}, {10, 9, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {10, 1, 5}, {10, 5, 9}, {10, 9, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 5}, {10, 5, 9}, {10, 9, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 2, 9}, {0, 9, 5}, {3, 11, 10}, {10, 0, 5}, {10, 5, 3}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 2, 9}, {10, 8, 5}, {10, 5, 3}, {10, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 0, 2}, {8, 2, 9}, {10, 1, 3}, {10, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 2, 9}, {10, 1, 3}, {10, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 0, 4}, {10, 4, 5}, {10, 5, 3}, {10, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 8, 5}, {10, 5, 3}, {10, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {10, 1, 3}, {10, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 3}, {10, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 10, 6}, {1, 6, 2}, {1, 2, 11}, {1, 11, 7}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {7, 1, 8}, {7, 8, 4}, {7, 4, 2}, {7, 2, 11}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 10, 6}, {8, 6, 2}, {11, 7, 5}, {5, 8, 2}, {5, 2, 11}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {7, 5, 4}, {7, 4, 2}, {7, 2, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 6, 4}, {9, 11, 7}, {9, 7, 1}, {1, 10, 4}, {1, 4, 9}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {7, 1, 8}, {7, 8, 9}, {7, 9, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 10}, {4, 10, 6}, {7, 5, 9}, {7, 9, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {7, 5, 9}, {7, 9, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 1, 10}, {5, 10, 6}, {5, 6, 2}, {5, 2, 9}, {7, 3, 11}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {8, 5, 1}, {4, 2, 9}, {7, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 10, 6}, {8, 6, 2}, {8, 2, 9}, {7, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {4, 2, 9}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 6, 4}, {10, 4, 5}, {10, 5, 1}, {7, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {8, 5, 1}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 10}, {4, 10, 6}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 1, 0}, {7, 0, 2}, {7, 2, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 1, 8}, {7, 8, 4}, {7, 4, 2}, {7, 2, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 5, 8}, {7, 8, 0}, {7, 0, 2}, {7, 2, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 5, 4}, {7, 4, 2}, {7, 2, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 1, 0}, {7, 0, 4}, {7, 4, 9}, {7, 9, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 1, 8}, {7, 8, 9}, {7, 9, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {7, 5, 9}, {7, 9, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 5, 9}, {7, 9, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 1, 0}, {5, 0, 2}, {5, 2, 9}, {7, 3, 11}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {4, 2, 9}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 0, 2}, {8, 2, 9}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 2, 9}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 4, 5}, {0, 5, 1}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 11, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 11, 0}, {7, 0, 8}, {0, 11, 4}, {8, 3, 7}, {11, 3, 4}, - {3, 8, 4}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 1, 7}, {8, 7, 11}, {8, 11, 3}, {8, 3, 5}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 1, 7}, {0, 7, 11}, {3, 5, 4}, {4, 0, 11}, {4, 11, 3}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 9, 3}, {4, 3, 7}, {4, 7, 11}, {4, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 9, 3}, {8, 3, 7}, {11, 2, 0}, {0, 8, 7}, {0, 7, 11}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 9, 3}, {4, 8, 1}, {4, 1, 7}, {4, 7, 11}, {4, 11, 2}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 9, 3}, {0, 1, 7}, {0, 7, 11}, {0, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 7, 11}, {5, 11, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 7}, {11, 9, 4}, {11, 4, 0}, {0, 8, 7}, {0, 7, 11}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 1, 7}, {8, 7, 11}, {8, 11, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 0, 1}, {4, 1, 7}, {4, 7, 11}, {4, 11, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 5, 7}, {4, 7, 11}, {4, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 8, 5}, {0, 5, 7}, {0, 7, 11}, {0, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 1}, {4, 1, 7}, {4, 7, 11}, {4, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 1, 7}, {0, 7, 11}, {0, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 6, 11}, {0, 11, 3}, {0, 3, 7}, {0, 7, 10}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 10, 8}, {4, 6, 11}, {4, 11, 3}, {3, 7, 8}, {3, 8, 4}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {5, 8, 0}, {5, 0, 6}, {5, 6, 11}, {5, 11, 3}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {5, 4, 6}, {5, 6, 11}, {5, 11, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 10, 0}, {7, 0, 4}, {7, 4, 9}, {7, 9, 3}, {6, 11, 2}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 10, 8}, {7, 8, 9}, {7, 9, 3}, {6, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {10, 1, 7}, {5, 9, 3}, {6, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {5, 9, 3}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 7, 10}, {5, 10, 0}, {6, 11, 9}, {9, 5, 0}, {9, 0, 6}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 8, 5}, {10, 5, 7}, {4, 6, 11}, {4, 11, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {8, 0, 6}, {8, 6, 11}, {8, 11, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {4, 6, 11}, {4, 11, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 0, 4}, {10, 4, 5}, {10, 5, 7}, {6, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 8, 5}, {10, 5, 7}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {10, 1, 7}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 10, 11}, {1, 11, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 11}, {3, 1, 8}, {3, 8, 4}, {4, 0, 11}, {4, 11, 3}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 8, 10}, {5, 10, 11}, {5, 11, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 4, 0}, {5, 0, 10}, {5, 10, 11}, {5, 11, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{9, 3, 1}, {10, 11, 2}, {10, 2, 4}, {4, 9, 1}, {4, 1, 10}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 8, 9}, {1, 9, 3}, {0, 10, 11}, {0, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 9, 3}, {4, 8, 10}, {4, 10, 11}, {4, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 9, 3}, {0, 10, 11}, {0, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 1, 10}, {5, 10, 11}, {5, 11, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {4, 0, 10}, {4, 10, 11}, {4, 11, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 10, 11}, {8, 11, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 0, 10}, {4, 10, 11}, {4, 11, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 5, 1}, {4, 1, 10}, {4, 10, 11}, {4, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {0, 10, 11}, {0, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 10}, {4, 10, 11}, {4, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 11}, {0, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 0, 6}, {1, 6, 11}, {1, 11, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 8, 4}, {1, 4, 6}, {1, 6, 11}, {1, 11, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 8, 0}, {5, 0, 6}, {5, 6, 11}, {5, 11, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 4, 6}, {5, 6, 11}, {5, 11, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 0, 4}, {1, 4, 9}, {1, 9, 3}, {6, 11, 2}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 8, 9}, {1, 9, 3}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {5, 9, 3}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 9, 3}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 1, 0}, {5, 0, 6}, {5, 6, 11}, {5, 11, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {4, 6, 11}, {4, 11, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 0, 6}, {8, 6, 11}, {8, 11, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 6, 11}, {4, 11, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 4, 5}, {0, 5, 1}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 6, 2}, {7, 2, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 6, 0}, {7, 0, 8}, {4, 2, 3}, {3, 7, 8}, {3, 8, 4}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 7, 6}, {2, 3, 5}, {2, 5, 8}, {8, 1, 6}, {8, 6, 2}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 1}, {6, 1, 7}, {5, 4, 2}, {5, 2, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 6, 4}, {7, 4, 9}, {7, 9, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 6, 0}, {7, 0, 8}, {7, 8, 9}, {7, 9, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 4, 8}, {6, 8, 1}, {6, 1, 7}, {5, 9, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 1}, {6, 1, 7}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 7, 6}, {5, 6, 2}, {5, 2, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 8}, {6, 8, 5}, {6, 5, 7}, {4, 2, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 1, 7}, {8, 7, 6}, {8, 6, 2}, {8, 2, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 1}, {6, 1, 7}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 4, 5}, {6, 5, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 8}, {6, 8, 5}, {6, 5, 7}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 4, 8}, {6, 8, 1}, {6, 1, 7}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{6, 0, 1}, {6, 1, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 10, 0}, {7, 0, 2}, {7, 2, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 10, 8}, {7, 8, 4}, {7, 4, 2}, {7, 2, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {5, 8, 0}, {5, 0, 2}, {5, 2, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {5, 4, 2}, {5, 2, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 10, 0}, {7, 0, 4}, {7, 4, 9}, {7, 9, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{7, 10, 8}, {7, 8, 9}, {7, 9, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {10, 1, 7}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 7, 10}, {5, 10, 0}, {5, 0, 2}, {5, 2, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 8, 5}, {10, 5, 7}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {8, 0, 2}, {8, 2, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 0, 4}, {10, 4, 5}, {10, 5, 7}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 8, 5}, {10, 5, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {10, 1, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 1, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 10, 6}, {1, 6, 2}, {1, 2, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {1, 8, 4}, {1, 4, 2}, {1, 2, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 8, 10}, {5, 10, 6}, {5, 6, 2}, {5, 2, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {5, 4, 2}, {5, 2, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 10, 6}, {1, 6, 4}, {1, 4, 9}, {1, 9, 3}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {1, 8, 9}, {1, 9, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 10}, {4, 10, 6}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 1, 10}, {5, 10, 6}, {5, 6, 2}, {5, 2, 9}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {8, 5, 1}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 10, 6}, {8, 6, 2}, {8, 2, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{10, 6, 4}, {10, 4, 5}, {10, 5, 1}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {8, 5, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 10}, {4, 10, 6}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 10, 6}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 0, 2}, {1, 2, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 8, 4}, {1, 4, 2}, {1, 2, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 8, 0}, {5, 0, 2}, {5, 2, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 4, 2}, {5, 2, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 0, 4}, {1, 4, 9}, {1, 9, 3}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{1, 8, 9}, {1, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{5, 1, 0}, {5, 0, 2}, {5, 2, 9}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 0, 2}, {8, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 4, 5}, {0, 5, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{8, 5, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{4, 8, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}} -}; +const int marching_cubes_tris[TOTCONF][MAX_TRIS][3] = {{{0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 0, 8}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 1, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 0, 1}, + {4, 1, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 8, 9}, + {0, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 5, 9}, + {1, 9, 2}, + {1, 2, 4}, + {1, 4, 8}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 1, 5}, + {0, 5, 9}, + {0, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 8, 5}, + {0, 5, 3}, + {0, 3, 9}, + {0, 9, 4}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 1, 3}, + {8, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 0, 1}, + {4, 1, 3}, + {4, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 5, 3}, + {4, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 8, 5}, + {0, 5, 3}, + {0, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 1}, + {4, 1, 3}, + {4, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 1, 3}, + {0, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 6, 10}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 4, 6}, + {8, 6, 10}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 10, 1}, + {6, 1, 5}, + {6, 5, 8}, + {6, 8, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 6, 10}, + {4, 10, 1}, + {4, 1, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 0, 4}, + {10, 4, 9}, + {10, 9, 2}, + {10, 2, 6}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 10, 8}, + {6, 8, 9}, + {6, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {6, 10, 1}, + {6, 1, 5}, + {6, 5, 9}, + {6, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 10, 1}, + {6, 1, 5}, + {6, 5, 9}, + {6, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 0, 5}, + {0, 6, 9}, + {9, 5, 0}, + {6, 10, 3}, + {5, 3, 10}, + {3, 9, 6}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 8, 5}, + {10, 5, 3}, + {9, 4, 6}, + {6, 10, 3}, + {6, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 3}, + {9, 8, 0}, + {9, 0, 6}, + {6, 10, 3}, + {6, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 6, 10}, + {4, 10, 1}, + {4, 1, 3}, + {4, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 4, 5}, + {3, 2, 6}, + {3, 6, 10}, + {10, 0, 5}, + {10, 5, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 10, 8}, + {6, 8, 5}, + {6, 5, 3}, + {6, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {6, 10, 1}, + {6, 1, 3}, + {6, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 10, 1}, + {6, 1, 3}, + {6, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 7, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 0, 10}, + {4, 10, 7}, + {4, 7, 1}, + {4, 1, 8}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 10, 7}, + {8, 7, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 0, 10}, + {4, 10, 7}, + {4, 7, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 2, 4}, + {10, 4, 1}, + {7, 2, 10}, + {1, 9, 7}, + {1, 4, 9}, + {9, 2, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 8, 9}, + {2, 0, 10}, + {2, 10, 7}, + {7, 1, 9}, + {7, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 10}, + {7, 5, 9}, + {7, 9, 2}, + {2, 4, 10}, + {2, 10, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 7}, + {0, 7, 5}, + {0, 5, 9}, + {0, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 7, 3}, + {10, 3, 9}, + {10, 9, 5}, + {10, 5, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {4, 0, 10}, + {4, 10, 7}, + {4, 7, 3}, + {4, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 10, 7}, + {8, 7, 3}, + {8, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 0, 10}, + {4, 10, 7}, + {4, 7, 3}, + {4, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 5, 1}, + {4, 1, 10}, + {7, 3, 2}, + {2, 4, 10}, + {2, 10, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {0, 10, 7}, + {0, 7, 3}, + {0, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 10}, + {4, 10, 7}, + {4, 7, 3}, + {4, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 7}, + {0, 7, 3}, + {0, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 6, 7}, + {0, 7, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 4, 6}, + {8, 6, 7}, + {8, 7, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 0, 6}, + {8, 6, 7}, + {8, 7, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 6, 7}, + {4, 7, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 0, 4}, + {1, 4, 9}, + {2, 6, 7}, + {7, 1, 9}, + {7, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 7, 1}, + {6, 1, 8}, + {6, 8, 9}, + {6, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {6, 7, 5}, + {6, 5, 9}, + {6, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 7, 5}, + {6, 5, 9}, + {6, 9, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 1, 0}, + {6, 7, 3}, + {6, 3, 9}, + {9, 5, 0}, + {9, 0, 6}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {4, 6, 7}, + {4, 7, 3}, + {4, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 0, 6}, + {8, 6, 7}, + {8, 7, 3}, + {8, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 6, 7}, + {4, 7, 3}, + {4, 3, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 4, 5}, + {0, 5, 1}, + {6, 7, 3}, + {6, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {6, 7, 3}, + {6, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {6, 7, 3}, + {6, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 7, 3}, + {6, 3, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 4, 2}, + {8, 2, 11}, + {8, 11, 6}, + {8, 6, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 1, 6}, + {6, 1, 11}, + {11, 1, 5}, + {2, 11, 5}, + {2, 5, 8}, + {6, 2, 8}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 1}, + {5, 4, 2}, + {5, 2, 11}, + {11, 6, 1}, + {11, 1, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 4, 9}, + {6, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 8}, + {6, 8, 9}, + {6, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 4, 8}, + {6, 8, 1}, + {5, 9, 11}, + {11, 6, 1}, + {11, 1, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 1}, + {6, 1, 5}, + {6, 5, 9}, + {6, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 2, 9}, + {6, 9, 5}, + {6, 5, 3}, + {6, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 2, 9}, + {6, 0, 8}, + {6, 8, 5}, + {6, 5, 3}, + {6, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{2, 9, 8}, + {1, 3, 11}, + {1, 11, 6}, + {6, 2, 8}, + {6, 8, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 2, 9}, + {6, 0, 1}, + {6, 1, 3}, + {6, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 4, 5}, + {6, 5, 3}, + {6, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 8}, + {6, 8, 5}, + {6, 5, 3}, + {6, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 4, 8}, + {6, 8, 1}, + {6, 1, 3}, + {6, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 1}, + {6, 1, 3}, + {6, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 0, 2}, + {10, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 8, 4}, + {10, 4, 2}, + {10, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 0, 2}, + {11, 10, 1}, + {11, 1, 5}, + {5, 8, 2}, + {5, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 5}, + {10, 5, 4}, + {10, 4, 2}, + {10, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 0, 4}, + {10, 4, 9}, + {10, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 8, 9}, + {10, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {10, 1, 5}, + {10, 5, 9}, + {10, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 5}, + {10, 5, 9}, + {10, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 2, 9}, + {0, 9, 5}, + {3, 11, 10}, + {10, 0, 5}, + {10, 5, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 2, 9}, + {10, 8, 5}, + {10, 5, 3}, + {10, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 0, 2}, + {8, 2, 9}, + {10, 1, 3}, + {10, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 2, 9}, + {10, 1, 3}, + {10, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 0, 4}, + {10, 4, 5}, + {10, 5, 3}, + {10, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 8, 5}, + {10, 5, 3}, + {10, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {10, 1, 3}, + {10, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 3}, + {10, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 10, 6}, + {1, 6, 2}, + {1, 2, 11}, + {1, 11, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {7, 1, 8}, + {7, 8, 4}, + {7, 4, 2}, + {7, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 10, 6}, + {8, 6, 2}, + {11, 7, 5}, + {5, 8, 2}, + {5, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {7, 5, 4}, + {7, 4, 2}, + {7, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 6, 4}, + {9, 11, 7}, + {9, 7, 1}, + {1, 10, 4}, + {1, 4, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {7, 1, 8}, + {7, 8, 9}, + {7, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 10}, + {4, 10, 6}, + {7, 5, 9}, + {7, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {7, 5, 9}, + {7, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 1, 10}, + {5, 10, 6}, + {5, 6, 2}, + {5, 2, 9}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {8, 5, 1}, + {4, 2, 9}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 10, 6}, + {8, 6, 2}, + {8, 2, 9}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {4, 2, 9}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 6, 4}, + {10, 4, 5}, + {10, 5, 1}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {8, 5, 1}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 10}, + {4, 10, 6}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 1, 0}, + {7, 0, 2}, + {7, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 1, 8}, + {7, 8, 4}, + {7, 4, 2}, + {7, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 5, 8}, + {7, 8, 0}, + {7, 0, 2}, + {7, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 5, 4}, + {7, 4, 2}, + {7, 2, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 1, 0}, + {7, 0, 4}, + {7, 4, 9}, + {7, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 1, 8}, + {7, 8, 9}, + {7, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {7, 5, 9}, + {7, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 5, 9}, + {7, 9, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 1, 0}, + {5, 0, 2}, + {5, 2, 9}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {4, 2, 9}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 0, 2}, + {8, 2, 9}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 2, 9}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 4, 5}, + {0, 5, 1}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 3, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 11, 0}, + {7, 0, 8}, + {0, 11, 4}, + {8, 3, 7}, + {11, 3, 4}, + {3, 8, 4}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 1, 7}, + {8, 7, 11}, + {8, 11, 3}, + {8, 3, 5}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 1, 7}, + {0, 7, 11}, + {3, 5, 4}, + {4, 0, 11}, + {4, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 9, 3}, + {4, 3, 7}, + {4, 7, 11}, + {4, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 9, 3}, + {8, 3, 7}, + {11, 2, 0}, + {0, 8, 7}, + {0, 7, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 9, 3}, + {4, 8, 1}, + {4, 1, 7}, + {4, 7, 11}, + {4, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 9, 3}, + {0, 1, 7}, + {0, 7, 11}, + {0, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 7, 11}, + {5, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 7}, + {11, 9, 4}, + {11, 4, 0}, + {0, 8, 7}, + {0, 7, 11}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 1, 7}, + {8, 7, 11}, + {8, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 0, 1}, + {4, 1, 7}, + {4, 7, 11}, + {4, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 5, 7}, + {4, 7, 11}, + {4, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 8, 5}, + {0, 5, 7}, + {0, 7, 11}, + {0, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 1}, + {4, 1, 7}, + {4, 7, 11}, + {4, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 1, 7}, + {0, 7, 11}, + {0, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 6, 11}, + {0, 11, 3}, + {0, 3, 7}, + {0, 7, 10}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 10, 8}, + {4, 6, 11}, + {4, 11, 3}, + {3, 7, 8}, + {3, 8, 4}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {5, 8, 0}, + {5, 0, 6}, + {5, 6, 11}, + {5, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {5, 4, 6}, + {5, 6, 11}, + {5, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 10, 0}, + {7, 0, 4}, + {7, 4, 9}, + {7, 9, 3}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 10, 8}, + {7, 8, 9}, + {7, 9, 3}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {10, 1, 7}, + {5, 9, 3}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {5, 9, 3}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 7, 10}, + {5, 10, 0}, + {6, 11, 9}, + {9, 5, 0}, + {9, 0, 6}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 8, 5}, + {10, 5, 7}, + {4, 6, 11}, + {4, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {8, 0, 6}, + {8, 6, 11}, + {8, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {4, 6, 11}, + {4, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 0, 4}, + {10, 4, 5}, + {10, 5, 7}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 8, 5}, + {10, 5, 7}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {10, 1, 7}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 10, 11}, + {1, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 11}, + {3, 1, 8}, + {3, 8, 4}, + {4, 0, 11}, + {4, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 8, 10}, + {5, 10, 11}, + {5, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 4, 0}, + {5, 0, 10}, + {5, 10, 11}, + {5, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{9, 3, 1}, + {10, 11, 2}, + {10, 2, 4}, + {4, 9, 1}, + {4, 1, 10}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 8, 9}, + {1, 9, 3}, + {0, 10, 11}, + {0, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 9, 3}, + {4, 8, 10}, + {4, 10, 11}, + {4, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 9, 3}, + {0, 10, 11}, + {0, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 1, 10}, + {5, 10, 11}, + {5, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {4, 0, 10}, + {4, 10, 11}, + {4, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 10, 11}, + {8, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 0, 10}, + {4, 10, 11}, + {4, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 5, 1}, + {4, 1, 10}, + {4, 10, 11}, + {4, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {0, 10, 11}, + {0, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 10}, + {4, 10, 11}, + {4, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 11}, + {0, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 0, 6}, + {1, 6, 11}, + {1, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 8, 4}, + {1, 4, 6}, + {1, 6, 11}, + {1, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 8, 0}, + {5, 0, 6}, + {5, 6, 11}, + {5, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 4, 6}, + {5, 6, 11}, + {5, 11, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 0, 4}, + {1, 4, 9}, + {1, 9, 3}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 8, 9}, + {1, 9, 3}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {5, 9, 3}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 9, 3}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 1, 0}, + {5, 0, 6}, + {5, 6, 11}, + {5, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {4, 6, 11}, + {4, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 0, 6}, + {8, 6, 11}, + {8, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 6, 11}, + {4, 11, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 4, 5}, + {0, 5, 1}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 11, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 6, 2}, + {7, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 6, 0}, + {7, 0, 8}, + {4, 2, 3}, + {3, 7, 8}, + {3, 8, 4}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 7, 6}, + {2, 3, 5}, + {2, 5, 8}, + {8, 1, 6}, + {8, 6, 2}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 1}, + {6, 1, 7}, + {5, 4, 2}, + {5, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 6, 4}, + {7, 4, 9}, + {7, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 6, 0}, + {7, 0, 8}, + {7, 8, 9}, + {7, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 4, 8}, + {6, 8, 1}, + {6, 1, 7}, + {5, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 1}, + {6, 1, 7}, + {5, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 7, 6}, + {5, 6, 2}, + {5, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 8}, + {6, 8, 5}, + {6, 5, 7}, + {4, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 1, 7}, + {8, 7, 6}, + {8, 6, 2}, + {8, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 1}, + {6, 1, 7}, + {4, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 4, 5}, + {6, 5, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 8}, + {6, 8, 5}, + {6, 5, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 4, 8}, + {6, 8, 1}, + {6, 1, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{6, 0, 1}, + {6, 1, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 10, 0}, + {7, 0, 2}, + {7, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 10, 8}, + {7, 8, 4}, + {7, 4, 2}, + {7, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {5, 8, 0}, + {5, 0, 2}, + {5, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {5, 4, 2}, + {5, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 10, 0}, + {7, 0, 4}, + {7, 4, 9}, + {7, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{7, 10, 8}, + {7, 8, 9}, + {7, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {10, 1, 7}, + {5, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {5, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 7, 10}, + {5, 10, 0}, + {5, 0, 2}, + {5, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 8, 5}, + {10, 5, 7}, + {4, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {8, 0, 2}, + {8, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {4, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 0, 4}, + {10, 4, 5}, + {10, 5, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 8, 5}, + {10, 5, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {10, 1, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 1, 7}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 10, 6}, + {1, 6, 2}, + {1, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {1, 8, 4}, + {1, 4, 2}, + {1, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 8, 10}, + {5, 10, 6}, + {5, 6, 2}, + {5, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {5, 4, 2}, + {5, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 10, 6}, + {1, 6, 4}, + {1, 4, 9}, + {1, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {1, 8, 9}, + {1, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 10}, + {4, 10, 6}, + {5, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {5, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 1, 10}, + {5, 10, 6}, + {5, 6, 2}, + {5, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {8, 5, 1}, + {4, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 10, 6}, + {8, 6, 2}, + {8, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {4, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{10, 6, 4}, + {10, 4, 5}, + {10, 5, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {8, 5, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 10}, + {4, 10, 6}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 10, 6}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 0, 2}, + {1, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 8, 4}, + {1, 4, 2}, + {1, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 8, 0}, + {5, 0, 2}, + {5, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 4, 2}, + {5, 2, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 0, 4}, + {1, 4, 9}, + {1, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{1, 8, 9}, + {1, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {5, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 9, 3}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{5, 1, 0}, + {5, 0, 2}, + {5, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {4, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 0, 2}, + {8, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 2, 9}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 4, 5}, + {0, 5, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{8, 5, 1}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{4, 8, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}, + {{0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}}; 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(); - leafalloc[1] = new MemoryAllocator(); - leafalloc[2] = new MemoryAllocator(); - leafalloc[3] = new MemoryAllocator(); - - alloc[0] = new MemoryAllocator(); - alloc[1] = new MemoryAllocator(); - alloc[2] = new MemoryAllocator(); - alloc[3] = new MemoryAllocator(); - alloc[4] = new MemoryAllocator(); - alloc[5] = new MemoryAllocator(); - alloc[6] = new MemoryAllocator(); - alloc[7] = new MemoryAllocator(); - alloc[8] = new MemoryAllocator(); + leafalloc[0] = new MemoryAllocator(); + leafalloc[1] = new MemoryAllocator(); + leafalloc[2] = new MemoryAllocator(); + leafalloc[3] = new MemoryAllocator(); + + alloc[0] = new MemoryAllocator(); + alloc[1] = new MemoryAllocator(); + alloc[2] = new MemoryAllocator(); + alloc[3] = new MemoryAllocator(); + alloc[4] = new MemoryAllocator(); + alloc[5] = new MemoryAllocator(); + alloc[6] = new MemoryAllocator(); + alloc[7] = new MemoryAllocator(); + alloc[8] = new MemoryAllocator(); } 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::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]; diff --git a/intern/dualcon/intern/octree.h b/intern/dualcon/intern/octree.h index 5075a5603b6..db945e36390 100644 --- a/intern/dualcon/intern/octree.h +++ b/intern/dualcon/intern/octree.h @@ -37,7 +37,6 @@ * @author Tao Ju */ - /* Global defines */ // Uncomment to see debug information // #define IN_DEBUG_MODE @@ -53,98 +52,97 @@ union Node; struct LeafNode; struct InternalNode { - /* Initialized in Octree::BuildTable */ - static int numChildrenTable[256]; - static int childrenCountTable[256][8]; - static int childrenIndexTable[256][8]; - - /* Bit N indicates whether child N exists or not */ - unsigned char has_child_bitfield; - /* Bit N indicates whether child N is a leaf or not */ - unsigned char child_is_leaf_bitfield; - - /* Can have up to eight children */ - Node *children[0]; - - /// Test if child is leaf - int is_child_leaf(int index) const - { - return (child_is_leaf_bitfield >> index) & 1; - } - - /// If child index exists - int has_child(int index) const - { - return (has_child_bitfield >> index) & 1; - } - - /// Get the pointer to child index - Node *get_child(int count) - { - return children[count]; - } - - const Node *get_child(int count) const - { - return children[count]; - } - - /// Get total number of children - int get_num_children() const - { - return numChildrenTable[has_child_bitfield]; - } - - /// Get the count of children - int get_child_count(int index) const - { - return childrenCountTable[has_child_bitfield][index]; - } - int get_child_index(int count) - { - return childrenIndexTable[has_child_bitfield][count]; - } - const int *get_child_counts() const - { - return childrenCountTable[has_child_bitfield]; - } - - /// Get all children - void fill_children(Node *children[8], int leaf[8]) - { - int count = 0; - for (int i = 0; i < 8; i++) { - leaf[i] = is_child_leaf(i); - if (has_child(i)) { - children[i] = get_child(count); - count++; - } - else { - children[i] = NULL; - leaf[i] = 0; - } - } - } - - /// Sets the child pointer - void set_child(int count, Node *chd) - { - children[count] = chd; - } - void set_internal_child(int index, int count, InternalNode *chd) - { - set_child(count, (Node *)chd); - has_child_bitfield |= (1 << index); - } - void set_leaf_child(int index, int count, LeafNode *chd) - { - set_child(count, (Node *)chd); - has_child_bitfield |= (1 << index); - child_is_leaf_bitfield |= (1 << index); - } + /* Initialized in Octree::BuildTable */ + static int numChildrenTable[256]; + static int childrenCountTable[256][8]; + static int childrenIndexTable[256][8]; + + /* Bit N indicates whether child N exists or not */ + unsigned char has_child_bitfield; + /* Bit N indicates whether child N is a leaf or not */ + unsigned char child_is_leaf_bitfield; + + /* Can have up to eight children */ + Node *children[0]; + + /// Test if child is leaf + int is_child_leaf(int index) const + { + return (child_is_leaf_bitfield >> index) & 1; + } + + /// If child index exists + int has_child(int index) const + { + return (has_child_bitfield >> index) & 1; + } + + /// Get the pointer to child index + Node *get_child(int count) + { + return children[count]; + } + + const Node *get_child(int count) const + { + return children[count]; + } + + /// Get total number of children + int get_num_children() const + { + return numChildrenTable[has_child_bitfield]; + } + + /// Get the count of children + int get_child_count(int index) const + { + return childrenCountTable[has_child_bitfield][index]; + } + int get_child_index(int count) + { + return childrenIndexTable[has_child_bitfield][count]; + } + const int *get_child_counts() const + { + return childrenCountTable[has_child_bitfield]; + } + + /// Get all children + void fill_children(Node *children[8], int leaf[8]) + { + int count = 0; + for (int i = 0; i < 8; i++) { + leaf[i] = is_child_leaf(i); + if (has_child(i)) { + children[i] = get_child(count); + count++; + } + else { + children[i] = NULL; + leaf[i] = 0; + } + } + } + + /// Sets the child pointer + void set_child(int count, Node *chd) + { + children[count] = chd; + } + void set_internal_child(int index, int count, InternalNode *chd) + { + set_child(count, (Node *)chd); + has_child_bitfield |= (1 << index); + } + void set_leaf_child(int index, int count, LeafNode *chd) + { + set_child(count, (Node *)chd); + has_child_bitfield |= (1 << index); + child_is_leaf_bitfield |= (1 << index); + } }; - /** * Bits order * @@ -157,27 +155,27 @@ struct InternalNode { * Byte 5: edge intersections(4 bytes per inter, or 12 bytes if USE_HERMIT) */ struct LeafNode /* TODO: remove this attribute once everything is fixed */ { - unsigned short edge_parity : 12; - unsigned short primary_edge_intersections : 3; + unsigned short edge_parity : 12; + unsigned short primary_edge_intersections : 3; - /* XXX: maybe actually unused? */ - unsigned short in_process : 1; + /* XXX: maybe actually unused? */ + unsigned short in_process : 1; - /* bitfield */ - char signs; + /* bitfield */ + char signs; - int minimizer_index; + int minimizer_index; - unsigned short flood_fill; + unsigned short flood_fill; - float edge_intersections[0]; + float edge_intersections[0]; }; /* Doesn't get directly allocated anywhere, just used for passing pointers to nodes that could be internal or leaf. */ union Node { - InternalNode internal; - LeafNode leaf; + InternalNode internal; + LeafNode leaf; }; /* Global variables */ @@ -197,1195 +195,1209 @@ extern const int dirEdge[3][4]; */ struct PathElement { - // Origin - int pos[3]; + // Origin + int pos[3]; - // link - PathElement *next; + // link + PathElement *next; }; struct PathList { - // Head - PathElement *head; - PathElement *tail; + // Head + PathElement *head; + PathElement *tail; - // Length of the list - int length; + // Length of the list + int length; - // Next list - PathList *next; + // Next list + PathList *next; }; - /** * Class for building and processing an octree */ -class Octree -{ +class Octree { public: - /* Public members */ + /* Public members */ - /// Memory allocators - VirtualMemoryAllocator *alloc[9]; - VirtualMemoryAllocator *leafalloc[4]; + /// Memory allocators + VirtualMemoryAllocator *alloc[9]; + VirtualMemoryAllocator *leafalloc[4]; - /// Root node - Node *root; + /// Root node + Node *root; - /// Model reader - ModelReader *reader; + /// Model reader + ModelReader *reader; - /// Marching cubes table - Cubes *cubes; + /// Marching cubes table + Cubes *cubes; - /// Length of grid - int dimen; - int mindimen, minshift; + /// Length of grid + int dimen; + int mindimen, minshift; - /// Maximum depth - int maxDepth; + /// Maximum depth + int maxDepth; - /// The lower corner of the bounding box and the size - float origin[3]; - float range; + /// The lower corner of the bounding box and the size + float origin[3]; + float range; - /// Counting information - int nodeCount; - int nodeSpace; - int nodeCounts[9]; + /// Counting information + int nodeCount; + int nodeSpace; + int nodeCounts[9]; - int actualQuads, actualVerts; + int actualQuads, actualVerts; - PathList *ringList; + PathList *ringList; - int maxTrianglePerCell; - int outType; // 0 for OFF, 1 for PLY, 2 for VOL + int maxTrianglePerCell; + int outType; // 0 for OFF, 1 for PLY, 2 for VOL - // For flood filling - int use_flood_fill; - float thresh; + // For flood filling + int use_flood_fill; + float thresh; - int use_manifold; + int use_manifold; - float hermite_num; + float hermite_num; - DualConMode mode; + DualConMode mode; public: - /** - * Construtor - */ - Octree(ModelReader *mr, - DualConAllocOutput alloc_output_func, - DualConAddVert add_vert_func, - DualConAddQuad add_quad_func, - DualConFlags flags, DualConMode mode, int depth, - float threshold, float hermite_num); - - /** - * Destructor - */ - ~Octree(); - - /** - * Scan convert - */ - void scanConvert(); - - void *getOutputMesh() { - return output_mesh; - } + /** + * Construtor + */ + Octree(ModelReader *mr, + DualConAllocOutput alloc_output_func, + DualConAddVert add_vert_func, + DualConAddQuad add_quad_func, + DualConFlags flags, + DualConMode mode, + int depth, + float threshold, + float hermite_num); + + /** + * Destructor + */ + ~Octree(); + + /** + * Scan convert + */ + void scanConvert(); + + void *getOutputMesh() + { + return output_mesh; + } private: - /* Helper functions */ - - /** - * Initialize memory allocators - */ - void initMemory(); - - /** - * Release memory - */ - void freeMemory(); - - /** - * Print memory usage - */ - void printMemUsage(); - - - /** - * Methods to set / restore minimum edges - */ - void resetMinimalEdges(); - - void cellProcParity(Node *node, int leaf, int depth); - void faceProcParity(Node * node[2], int leaf[2], int depth[2], int maxdep, int dir); - void edgeProcParity(Node * node[4], int leaf[4], int depth[4], int maxdep, int dir); - - void processEdgeParity(LeafNode * node[4], int depths[4], int maxdep, int dir); - - /** - * Add triangles to the tree - */ - void addAllTriangles(); - void addTriangle(Triangle *trian, int triind); - InternalNode *addTriangle(InternalNode *node, CubeTriangleIsect *p, int height); - - /** - * Method to update minimizer in a cell: update edge intersections instead - */ - LeafNode *updateCell(LeafNode *node, CubeTriangleIsect *p); - - /* Routines to detect and patch holes */ - int numRings; - int totRingLengths; - int maxRingLength; - - /** - * Entry routine. - */ - void trace(); - /** - * Trace the given node, find patches and fill them in - */ - Node *trace(Node *node, int *st, int len, int depth, PathList *& paths); - /** - * Look for path on the face and add to paths - */ - void findPaths(Node * node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList * &paths); - /** - * Combine two list1 and list2 into list1 using connecting paths list3, - * while closed paths are appended to rings - */ - void combinePaths(PathList *& list1, PathList *list2, PathList *paths, PathList *& rings); - /** - * Helper function: combine current paths in list1 and list2 to a single path and append to list3 - */ - PathList *combineSinglePath(PathList *& head1, PathList *pre1, PathList *& list1, PathList *& head2, PathList *pre2, PathList *& list2); - - /** - * Functions to patch rings in a node - */ - Node *patch(Node *node, int st[3], int len, PathList * rings); - Node *patchSplit(Node *node, int st[3], int len, PathList * rings, int dir, PathList * &nrings1, PathList * &nrings2); - Node *patchSplitSingle(Node *node, int st[3], int len, PathElement *head, int dir, PathList * &nrings1, PathList * &nrings2); - Node *connectFace(Node *node, int st[3], int len, int dir, PathElement * f1, PathElement * f2); - Node *locateCell(InternalNode *node, int st[3], int len, int ori[3], int dir, int side, Node * &rleaf, int rst[3], int& rlen); - void compressRing(PathElement *& ring); - void getFacePoint(PathElement *leaf, int dir, int& x, int& y, float& p, float& q); - LeafNode *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); - int findPair(PathElement *head, int pos, int dir, PathElement *& pre1, PathElement *& pre2); - int getSide(PathElement *e, int pos, int dir); - int isEqual(PathElement *e1, PathElement *e2); - void preparePrimalEdgesMask(InternalNode *node); - void testFacePoint(PathElement *e1, PathElement *e2); - - /** - * Path-related functions - */ - void deletePath(PathList *& head, PathList *pre, PathList *& curr); - void printPath(PathList *path); - void printPath(PathElement *path); - void printElement(PathElement *ele); - void printPaths(PathList *path); - void checkElement(PathElement *ele); - void checkPath(PathElement *path); - - - /** - * Routines to build signs to create a partitioned volume - *(after patching rings) - */ - void buildSigns(); - void buildSigns(unsigned char table[], Node * node, int isLeaf, int sg, int rvalue[8]); - - /************************************************************************/ - /* To remove disconnected components */ - /************************************************************************/ - void floodFill(); - void clearProcessBits(Node *node, int height); - int floodFill(LeafNode *leaf, int st[3], int len, int height, int threshold); - int floodFill(Node *node, int st[3], int len, int height, int threshold); - - /** - * Write out polygon file - */ - void writeOut(); - - void countIntersection(Node *node, int height, int& nedge, int& ncell, int& nface); - void generateMinimizer(Node *node, int st[3], int len, int height, int& offset); - void computeMinimizer(const LeafNode * leaf, int st[3], int len, - float rvalue[3]) const; - /** - * Traversal functions to generate polygon model - * op: 0 for counting, 1 for writing OBJ, 2 for writing OFF, 3 for writing PLY - */ - void cellProcContour(Node *node, int leaf, int depth); - void faceProcContour(Node * node[2], int leaf[2], int depth[2], int maxdep, int dir); - void edgeProcContour(Node * node[4], int leaf[4], int depth[4], int maxdep, int dir); - void processEdgeWrite(Node * node[4], int depths[4], int maxdep, int dir); - - /* output callbacks/data */ - DualConAllocOutput alloc_output; - DualConAddVert add_vert; - DualConAddQuad add_quad; - void *output_mesh; + /* Helper functions */ + + /** + * Initialize memory allocators + */ + void initMemory(); + + /** + * Release memory + */ + void freeMemory(); + + /** + * Print memory usage + */ + void printMemUsage(); + + /** + * Methods to set / restore minimum edges + */ + void resetMinimalEdges(); + + void cellProcParity(Node *node, int leaf, int depth); + void faceProcParity(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir); + void edgeProcParity(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir); + + void processEdgeParity(LeafNode *node[4], int depths[4], int maxdep, int dir); + + /** + * Add triangles to the tree + */ + void addAllTriangles(); + void addTriangle(Triangle *trian, int triind); + InternalNode *addTriangle(InternalNode *node, CubeTriangleIsect *p, int height); + + /** + * Method to update minimizer in a cell: update edge intersections instead + */ + LeafNode *updateCell(LeafNode *node, CubeTriangleIsect *p); + + /* Routines to detect and patch holes */ + int numRings; + int totRingLengths; + int maxRingLength; + + /** + * Entry routine. + */ + void trace(); + /** + * Trace the given node, find patches and fill them in + */ + Node *trace(Node *node, int *st, int len, int depth, PathList *&paths); + /** + * Look for path on the face and add to paths + */ + void findPaths( + Node *node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList *&paths); + /** + * Combine two list1 and list2 into list1 using connecting paths list3, + * while closed paths are appended to rings + */ + void combinePaths(PathList *&list1, PathList *list2, PathList *paths, PathList *&rings); + /** + * Helper function: combine current paths in list1 and list2 to a single path and append to list3 + */ + PathList *combineSinglePath(PathList *&head1, + PathList *pre1, + PathList *&list1, + PathList *&head2, + PathList *pre2, + PathList *&list2); + + /** + * Functions to patch rings in a node + */ + Node *patch(Node *node, int st[3], int len, PathList *rings); + Node *patchSplit(Node *node, + int st[3], + int len, + PathList *rings, + int dir, + PathList *&nrings1, + PathList *&nrings2); + Node *patchSplitSingle(Node *node, + int st[3], + int len, + PathElement *head, + int dir, + PathList *&nrings1, + PathList *&nrings2); + Node *connectFace(Node *node, int st[3], int len, int dir, PathElement *f1, PathElement *f2); + Node *locateCell(InternalNode *node, + int st[3], + int len, + int ori[3], + int dir, + int side, + Node *&rleaf, + int rst[3], + int &rlen); + void compressRing(PathElement *&ring); + void getFacePoint(PathElement *leaf, int dir, int &x, int &y, float &p, float &q); + LeafNode *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); + int findPair(PathElement *head, int pos, int dir, PathElement *&pre1, PathElement *&pre2); + int getSide(PathElement *e, int pos, int dir); + int isEqual(PathElement *e1, PathElement *e2); + void preparePrimalEdgesMask(InternalNode *node); + void testFacePoint(PathElement *e1, PathElement *e2); + + /** + * Path-related functions + */ + void deletePath(PathList *&head, PathList *pre, PathList *&curr); + void printPath(PathList *path); + void printPath(PathElement *path); + void printElement(PathElement *ele); + void printPaths(PathList *path); + void checkElement(PathElement *ele); + void checkPath(PathElement *path); + + /** + * Routines to build signs to create a partitioned volume + *(after patching rings) + */ + void buildSigns(); + void buildSigns(unsigned char table[], Node *node, int isLeaf, int sg, int rvalue[8]); + + /************************************************************************/ + /* To remove disconnected components */ + /************************************************************************/ + void floodFill(); + void clearProcessBits(Node *node, int height); + int floodFill(LeafNode *leaf, int st[3], int len, int height, int threshold); + int floodFill(Node *node, int st[3], int len, int height, int threshold); + + /** + * Write out polygon file + */ + void writeOut(); + + void countIntersection(Node *node, int height, int &nedge, int &ncell, int &nface); + void generateMinimizer(Node *node, int st[3], int len, int height, int &offset); + void computeMinimizer(const LeafNode *leaf, int st[3], int len, float rvalue[3]) const; + /** + * Traversal functions to generate polygon model + * op: 0 for counting, 1 for writing OBJ, 2 for writing OFF, 3 for writing PLY + */ + void cellProcContour(Node *node, int leaf, int depth); + void faceProcContour(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir); + void edgeProcContour(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir); + void processEdgeWrite(Node *node[4], int depths[4], int maxdep, int dir); + + /* output callbacks/data */ + DualConAllocOutput alloc_output; + DualConAddVert add_vert; + DualConAddQuad add_quad; + void *output_mesh; private: - /************ Operators for all nodes ************/ - - /// Lookup table - int numEdgeTable[8]; - int edgeCountTable[8][3]; - - /// Build up lookup table - void buildTable() - { - for (int i = 0; i < 256; i++) { - InternalNode::numChildrenTable[i] = 0; - int count = 0; - for (int j = 0; j < 8; j++) { - InternalNode::numChildrenTable[i] += ((i >> j) & 1); - InternalNode::childrenCountTable[i][j] = count; - InternalNode::childrenIndexTable[i][count] = j; - count += ((i >> j) & 1); - } - } - - for (int i = 0; i < 8; i++) { - numEdgeTable[i] = 0; - int count = 0; - for (int j = 0; j < 3; j++) { - numEdgeTable[i] += ((i >> j) & 1); - edgeCountTable[i][j] = count; - count += ((i >> j) & 1); - } - } - } - - int getSign(Node *node, int height, int index) - { - if (height == 0) { - return getSign(&node->leaf, index); - } - else { - if (node->internal.has_child(index)) { - return getSign(node->internal.get_child(node->internal.get_child_count(index)), - height - 1, - index); - } - else { - return getSign(node->internal.get_child(0), - height - 1, - 7 - node->internal.get_child_index(0)); - } - } - } - - /************ Operators for leaf nodes ************/ - - void printInfo(int st[3]) - { - printf("INFO AT: %d %d %d\n", st[0] >> minshift, st[1] >> minshift, st[2] >> minshift); - LeafNode *leaf = (LeafNode *)locateLeafCheck(st); - if (leaf) - printInfo(leaf); - else - printf("Leaf not exists!\n"); - } - - void printInfo(const LeafNode *leaf) - { - /* - printf("Edge mask: "); - for(int i = 0; i < 12; i ++) - { - printf("%d ", getEdgeParity(leaf, i)); - } - printf("\n"); - printf("Stored edge mask: "); - for(i = 0; i < 3; i ++) - { - printf("%d ", getStoredEdgesParity(leaf, i)); - } - printf("\n"); - */ - printf("Sign mask: "); - for (int i = 0; i < 8; i++) { - printf("%d ", getSign(leaf, i)); - } - printf("\n"); - - } - - /// Retrieve signs - int getSign(const LeafNode *leaf, int index) - { - return ((leaf->signs >> index) & 1); - } - - /// Set sign - void setSign(LeafNode *leaf, int index) - { - leaf->signs |= (1 << index); - } - - void setSign(LeafNode *leaf, int index, int sign) - { - leaf->signs &= (~(1 << index)); - leaf->signs |= ((sign & 1) << index); - } - - int getSignMask(const LeafNode *leaf) const - { - return leaf->signs; - } - - void setInProcessAll(int st[3], int dir) - { - int nst[3], eind; - for (int i = 0; i < 4; i++) { - nst[0] = st[0] + dirCell[dir][i][0] * mindimen; - nst[1] = st[1] + dirCell[dir][i][1] * mindimen; - nst[2] = st[2] + dirCell[dir][i][2] * mindimen; - eind = dirEdge[dir][i]; - - LeafNode *cell = locateLeafCheck(nst); - assert(cell); - - setInProcess(cell, eind); - } - } - - void flipParityAll(int st[3], int dir) - { - int nst[3], eind; - for (int i = 0; i < 4; i++) { - nst[0] = st[0] + dirCell[dir][i][0] * mindimen; - nst[1] = st[1] + dirCell[dir][i][1] * mindimen; - nst[2] = st[2] + dirCell[dir][i][2] * mindimen; - eind = dirEdge[dir][i]; - - LeafNode *cell = locateLeaf(nst); - flipEdge(cell, eind); - } - } - - void setInProcess(LeafNode *leaf, int eind) - { - assert(eind >= 0 && eind <= 11); - - leaf->flood_fill |= (1 << eind); - } - - void setOutProcess(LeafNode *leaf, int eind) - { - assert(eind >= 0 && eind <= 11); - - leaf->flood_fill &= ~(1 << eind); - } - - int isInProcess(LeafNode *leaf, int eind) - { - assert(eind >= 0 && eind <= 11); - - return (leaf->flood_fill >> eind) & 1; - } - - /// Generate signs at the corners from the edge parity - void generateSigns(LeafNode *leaf, unsigned char table[], int start) - { - leaf->signs = table[leaf->edge_parity]; - - if ((start ^ leaf->signs) & 1) { - leaf->signs = ~(leaf->signs); - } - } - - /// Get edge parity - int getEdgeParity(const LeafNode *leaf, int index) const - { - assert(index >= 0 && index <= 11); - - return (leaf->edge_parity >> index) & 1; - } - - /// Get edge parity on a face - int getFaceParity(LeafNode *leaf, int index) - { - int a = getEdgeParity(leaf, faceMap[index][0]) + - getEdgeParity(leaf, faceMap[index][1]) + - getEdgeParity(leaf, faceMap[index][2]) + - getEdgeParity(leaf, faceMap[index][3]); - return (a & 1); - } - int getFaceEdgeNum(LeafNode *leaf, int index) - { - int a = getEdgeParity(leaf, faceMap[index][0]) + - getEdgeParity(leaf, faceMap[index][1]) + - getEdgeParity(leaf, faceMap[index][2]) + - getEdgeParity(leaf, faceMap[index][3]); - return a; - } - - /// Set edge parity - void flipEdge(LeafNode *leaf, int index) - { - assert(index >= 0 && index <= 11); - - leaf->edge_parity ^= (1 << index); - } - - /// Set 1 - void setEdge(LeafNode *leaf, int index) - { - assert(index >= 0 && index <= 11); - - leaf->edge_parity |= (1 << index); - } - - /// Set 0 - void resetEdge(LeafNode *leaf, int index) - { - assert(index >= 0 && index <= 11); - - leaf->edge_parity &= ~(1 << index); - } - - /// Flipping with a new intersection offset - void createPrimalEdgesMask(LeafNode *leaf) - { - leaf->primary_edge_intersections = getPrimalEdgesMask2(leaf); - } - - void setStoredEdgesParity(LeafNode *leaf, int pindex) - { - assert(pindex <= 2 && pindex >= 0); - - leaf->primary_edge_intersections |= (1 << pindex); - } - - int getStoredEdgesParity(const LeafNode *leaf, int pindex) const - { - assert(pindex <= 2 && pindex >= 0); - - return (leaf->primary_edge_intersections >> pindex) & 1; - } - - LeafNode *flipEdge(LeafNode *leaf, int index, float alpha) - { - flipEdge(leaf, index); - - if ((index & 3) == 0) { - int ind = index / 4; - if (getEdgeParity(leaf, index) && !getStoredEdgesParity(leaf, ind)) { - // Create a new node - int num = getNumEdges(leaf) + 1; - setStoredEdgesParity(leaf, ind); - int count = getEdgeCount(leaf, ind); - LeafNode *nleaf = createLeaf(num); - *nleaf = *leaf; - - setEdgeOffset(nleaf, alpha, count); - - if (num > 1) { - float *pts = leaf->edge_intersections; - float *npts = nleaf->edge_intersections; - for (int i = 0; i < count; i++) { - for (int j = 0; j < EDGE_FLOATS; j++) { - npts[i * EDGE_FLOATS + j] = pts[i * EDGE_FLOATS + j]; - } - } - for (int i = count + 1; i < num; i++) { - for (int j = 0; j < EDGE_FLOATS; j++) { - npts[i * EDGE_FLOATS + j] = pts[(i - 1) * EDGE_FLOATS + j]; - } - } - } - - - removeLeaf(num - 1, (LeafNode *)leaf); - leaf = nleaf; - } - } - - return leaf; - } - - /// Update parent link - void updateParent(InternalNode *node, int len, int st[3], LeafNode *leaf) - { - // First, locate the parent - int count; - InternalNode *parent = locateParent(node, len, st, count); - - // Update - parent->set_child(count, (Node *)leaf); - } - - void updateParent(InternalNode *node, int len, int st[3]) - { - if (len == dimen) { - root = (Node *)node; - return; - } - - // First, locate the parent - int count; - InternalNode *parent = locateParent(len, st, count); - - // UPdate - parent->set_child(count, (Node *)node); - } - - /// Find edge intersection on a given edge - int getEdgeIntersectionByIndex(int st[3], int index, float pt[3], int check) const - { - // First, locat the leaf - const LeafNode *leaf; - if (check) { - leaf = locateLeafCheck(st); - } - else { - leaf = locateLeaf(st); - } - - if (leaf && getStoredEdgesParity(leaf, index)) { - float off = getEdgeOffset(leaf, getEdgeCount(leaf, index)); - pt[0] = (float) st[0]; - pt[1] = (float) st[1]; - pt[2] = (float) st[2]; - pt[index] += off * mindimen; - - return 1; - } - else { - return 0; - } - } - - /// Retrieve number of edges intersected - int getPrimalEdgesMask(const LeafNode *leaf) const - { - return leaf->primary_edge_intersections; - } - - int getPrimalEdgesMask2(LeafNode *leaf) - { - return (((leaf->edge_parity & 0x1) >> 0) | - ((leaf->edge_parity & 0x10) >> 3) | - ((leaf->edge_parity & 0x100) >> 6)); - } - - /// Get the count for a primary edge - int getEdgeCount(const LeafNode *leaf, int index) const - { - return edgeCountTable[getPrimalEdgesMask(leaf)][index]; - } - int getNumEdges(LeafNode *leaf) - { - return numEdgeTable[getPrimalEdgesMask(leaf)]; - } - - int getNumEdges2(LeafNode *leaf) - { - return numEdgeTable[getPrimalEdgesMask2(leaf)]; - } - - /// Set edge intersection - void setEdgeOffset(LeafNode *leaf, float pt, int count) - { - float *pts = leaf->edge_intersections; - pts[EDGE_FLOATS * count] = pt; - pts[EDGE_FLOATS * count + 1] = 0; - pts[EDGE_FLOATS * count + 2] = 0; - pts[EDGE_FLOATS * count + 3] = 0; - } - - /// Set multiple edge intersections - void setEdgeOffsets(LeafNode *leaf, float pt[3], int len) - { - float *pts = leaf->edge_intersections; - for (int i = 0; i < len; i++) { - pts[i] = pt[i]; - } - } - - /// Retrieve edge intersection - float getEdgeOffset(const LeafNode *leaf, int count) const - { - return leaf->edge_intersections[4 * count]; - } - - /// Update method - LeafNode *updateEdgeOffsets(LeafNode *leaf, int oldlen, int newlen, float offs[3]) - { - // First, create a new leaf node - LeafNode *nleaf = createLeaf(newlen); - *nleaf = *leaf; - - // Next, fill in the offsets - setEdgeOffsets(nleaf, offs, newlen); - - // Finally, delete the old leaf - removeLeaf(oldlen, leaf); - - return nleaf; - } - - /// Set minimizer index - void setMinimizerIndex(LeafNode *leaf, int index) - { - leaf->minimizer_index = index; - } - - /// Get minimizer index - int getMinimizerIndex(LeafNode *leaf) - { - return leaf->minimizer_index; - } - - int getMinimizerIndex(LeafNode *leaf, int eind) - { - int add = manifold_table[getSignMask(leaf)].pairs[eind][0] - 1; - assert(add >= 0); - return leaf->minimizer_index + add; - } - - void getMinimizerIndices(LeafNode *leaf, int eind, int inds[2]) - { - const int *add = manifold_table[getSignMask(leaf)].pairs[eind]; - inds[0] = leaf->minimizer_index + add[0] - 1; - if (add[0] == add[1]) { - inds[1] = -1; - } - else { - inds[1] = leaf->minimizer_index + add[1] - 1; - } - } - - - /// Set edge intersection - void setEdgeOffsetNormal(LeafNode *leaf, float pt, float a, float b, float c, int count) - { - float *pts = leaf->edge_intersections; - pts[4 * count] = pt; - pts[4 * count + 1] = a; - pts[4 * count + 2] = b; - pts[4 * count + 3] = c; - } - - float getEdgeOffsetNormal(LeafNode *leaf, int count, float& a, float& b, float& c) - { - float *pts = leaf->edge_intersections; - a = pts[4 * count + 1]; - b = pts[4 * count + 2]; - c = pts[4 * count + 3]; - return pts[4 * count]; - } - - /// Set multiple edge intersections - void setEdgeOffsetsNormals(LeafNode *leaf, const float pt[], - const float a[], const float b[], - const float c[], int len) - { - float *pts = leaf->edge_intersections; - for (int i = 0; i < len; i++) { - if (pt[i] > 1 || pt[i] < 0) { - printf("\noffset: %f\n", pt[i]); - } - pts[i * 4] = pt[i]; - pts[i * 4 + 1] = a[i]; - pts[i * 4 + 2] = b[i]; - pts[i * 4 + 3] = c[i]; - } - } - - /// Retrieve complete edge intersection - void getEdgeIntersectionByIndex(const LeafNode *leaf, int index, int st[3], - int len, float pt[3], float nm[3]) const - { - int count = getEdgeCount(leaf, index); - const float *pts = leaf->edge_intersections; - - float off = pts[4 * count]; - - pt[0] = (float) st[0]; - pt[1] = (float) st[1]; - pt[2] = (float) st[2]; - pt[index] += (off * len); - - nm[0] = pts[4 * count + 1]; - nm[1] = pts[4 * count + 2]; - nm[2] = pts[4 * count + 3]; - } - - float getEdgeOffsetNormalByIndex(LeafNode *leaf, int index, float nm[3]) - { - int count = getEdgeCount(leaf, index); - float *pts = leaf->edge_intersections; - - float off = pts[4 * count]; - - nm[0] = pts[4 * count + 1]; - nm[1] = pts[4 * count + 2]; - nm[2] = pts[4 * count + 3]; - - return off; - } - - void fillEdgeIntersections(const LeafNode *leaf, int st[3], int len, - float pts[12][3], float norms[12][3]) const - { - int i; - // int stt[3] = {0, 0, 0}; - - // The three primal edges are easy - int pmask[3] = {0, 4, 8}; - for (i = 0; i < 3; i++) { - if (getEdgeParity(leaf, pmask[i])) { - // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]); - getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]); - } - } - - // 3 face adjacent cubes - int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}}; - int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}}; - for (i = 0; i < 3; i++) { - int e1 = getEdgeParity(leaf, fmask[i][0]); - int e2 = getEdgeParity(leaf, fmask[i][1]); - if (e1 || e2) { - int nst[3] = {st[0], st[1], st[2]}; - nst[i] += len; - // int nstt[3] = {0, 0, 0}; - // nstt[i] += 1; - const LeafNode *node = locateLeaf(nst); - - if (e1) { - // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]); - getEdgeIntersectionByIndex(node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]); - } - if (e2) { - // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]], norms[fmask[i][1]]); - getEdgeIntersectionByIndex(node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]); - } - } - } - - // 3 edge adjacent cubes - int emask[3] = {3, 7, 11}; - int eemask[3] = {0, 1, 2}; - for (i = 0; i < 3; i++) { - if (getEdgeParity(leaf, emask[i])) { - int nst[3] = {st[0] + len, st[1] + len, st[2] + len}; - nst[i] -= len; - // int nstt[3] = {1, 1, 1}; - // nstt[i] -= 1; - const LeafNode *node = locateLeaf(nst); - - // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]); - getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]); - } - } - } - - - void fillEdgeIntersections(const LeafNode *leaf, int st[3], int len, - float pts[12][3], float norms[12][3], - int parity[12]) const - { - int i; - for (i = 0; i < 12; i++) { - parity[i] = 0; - } - // int stt[3] = {0, 0, 0}; - - // The three primal edges are easy - int pmask[3] = {0, 4, 8}; - for (i = 0; i < 3; i++) { - if (getStoredEdgesParity(leaf, i)) { - // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]); - getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]); - parity[pmask[i]] = 1; - } - } - - // 3 face adjacent cubes - int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}}; - int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}}; - for (i = 0; i < 3; i++) { - { - int nst[3] = {st[0], st[1], st[2]}; - nst[i] += len; - // int nstt[3] = {0, 0, 0}; - // nstt[i] += 1; - const LeafNode *node = locateLeafCheck(nst); - if (node == NULL) { - continue; - } - - int e1 = getStoredEdgesParity(node, femask[i][0]); - int e2 = getStoredEdgesParity(node, femask[i][1]); - - if (e1) { - // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]); - getEdgeIntersectionByIndex(node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]); - parity[fmask[i][0]] = 1; - } - if (e2) { - // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]], norms[fmask[i][1]]); - getEdgeIntersectionByIndex(node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]); - parity[fmask[i][1]] = 1; - } - } - } - - // 3 edge adjacent cubes - int emask[3] = {3, 7, 11}; - int eemask[3] = {0, 1, 2}; - for (i = 0; i < 3; i++) { - // if(getEdgeParity(leaf, emask[i])) - { - int nst[3] = {st[0] + len, st[1] + len, st[2] + len}; - nst[i] -= len; - // int nstt[3] = {1, 1, 1}; - // nstt[i] -= 1; - const LeafNode *node = locateLeafCheck(nst); - if (node == NULL) { - continue; - } - - if (getStoredEdgesParity(node, eemask[i])) { - // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]); - getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]); - parity[emask[i]] = 1; - } - } - } - } - - void fillEdgeOffsetsNormals(LeafNode *leaf, int st[3], int len, float pts[12], float norms[12][3], int parity[12]) - { - int i; - for (i = 0; i < 12; i++) { - parity[i] = 0; - } - // int stt[3] = {0, 0, 0}; - - // The three primal edges are easy - int pmask[3] = {0, 4, 8}; - for (i = 0; i < 3; i++) { - if (getStoredEdgesParity(leaf, i)) { - pts[pmask[i]] = getEdgeOffsetNormalByIndex(leaf, i, norms[pmask[i]]); - parity[pmask[i]] = 1; - } - } - - // 3 face adjacent cubes - int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}}; - int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}}; - for (i = 0; i < 3; i++) { - { - int nst[3] = {st[0], st[1], st[2]}; - nst[i] += len; - // int nstt[3] = {0, 0, 0}; - // nstt[i] += 1; - LeafNode *node = locateLeafCheck(nst); - if (node == NULL) { - continue; - } - - int e1 = getStoredEdgesParity(node, femask[i][0]); - int e2 = getStoredEdgesParity(node, femask[i][1]); - - if (e1) { - pts[fmask[i][0]] = getEdgeOffsetNormalByIndex(node, femask[i][0], norms[fmask[i][0]]); - parity[fmask[i][0]] = 1; - } - if (e2) { - pts[fmask[i][1]] = getEdgeOffsetNormalByIndex(node, femask[i][1], norms[fmask[i][1]]); - parity[fmask[i][1]] = 1; - } - } - } - - // 3 edge adjacent cubes - int emask[3] = {3, 7, 11}; - int eemask[3] = {0, 1, 2}; - for (i = 0; i < 3; i++) { - // if(getEdgeParity(leaf, emask[i])) - { - int nst[3] = {st[0] + len, st[1] + len, st[2] + len}; - nst[i] -= len; - // int nstt[3] = {1, 1, 1}; - // nstt[i] -= 1; - LeafNode *node = locateLeafCheck(nst); - if (node == NULL) { - continue; - } - - if (getStoredEdgesParity(node, eemask[i])) { - pts[emask[i]] = getEdgeOffsetNormalByIndex(node, eemask[i], norms[emask[i]]); - parity[emask[i]] = 1; - } - } - } - } - - - /// Update method - LeafNode *updateEdgeOffsetsNormals(LeafNode *leaf, int oldlen, int newlen, float offs[3], float a[3], float b[3], float c[3]) - { - // First, create a new leaf node - LeafNode *nleaf = createLeaf(newlen); - *nleaf = *leaf; - - // Next, fill in the offsets - setEdgeOffsetsNormals(nleaf, offs, a, b, c, newlen); - - // Finally, delete the old leaf - removeLeaf(oldlen, leaf); - - return nleaf; - } - - /// Locate a leaf - /// WARNING: assuming this leaf already exists! - - LeafNode *locateLeaf(int st[3]) - { - Node *node = (Node *)root; - for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { - int index = (((st[0] >> i) & 1) << 2) | - (((st[1] >> i) & 1) << 1) | - (((st[2] >> i) & 1)); - node = node->internal.get_child(node->internal.get_child_count(index)); - } - - return &node->leaf; - } - - const LeafNode *locateLeaf(int st[3]) const - { - const Node *node = root; - for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { - int index = (((st[0] >> i) & 1) << 2) | - (((st[1] >> i) & 1) << 1) | - (((st[2] >> i) & 1)); - node = node->internal.get_child(node->internal.get_child_count(index)); - } - - return &node->leaf; - } - - LeafNode *locateLeaf(InternalNode *parent, int len, int st[3]) - { - Node *node = (Node *)parent; - int index; - for (int i = len / 2; i >= mindimen; i >>= 1) { - index = (((st[0] & i) ? 4 : 0) | - ((st[1] & i) ? 2 : 0) | - ((st[2] & i) ? 1 : 0)); - node = node->internal.get_child(node->internal.get_child_count(index)); - } - - return &node->leaf; - } - - LeafNode *locateLeafCheck(int st[3]) - { - Node *node = (Node *)root; - for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { - int index = (((st[0] >> i) & 1) << 2) | - (((st[1] >> i) & 1) << 1) | - (((st[2] >> i) & 1)); - if (!node->internal.has_child(index)) { - return NULL; - } - node = node->internal.get_child(node->internal.get_child_count(index)); - } - - return &node->leaf; - } - - const LeafNode *locateLeafCheck(int st[3]) const - { - const Node *node = root; - for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { - int index = (((st[0] >> i) & 1) << 2) | - (((st[1] >> i) & 1) << 1) | - (((st[2] >> i) & 1)); - if (!node->internal.has_child(index)) { - return NULL; - } - node = node->internal.get_child(node->internal.get_child_count(index)); - } - - return &node->leaf; - } - - InternalNode *locateParent(int len, int st[3], int& count) - { - InternalNode *node = (InternalNode *)root; - InternalNode *pre = NULL; - int index = 0; - for (int i = dimen / 2; i >= len; i >>= 1) { - index = (((st[0] & i) ? 4 : 0) | - ((st[1] & i) ? 2 : 0) | - ((st[2] & i) ? 1 : 0)); - pre = node; - node = &node->get_child(node->get_child_count(index))->internal; - } - - count = pre->get_child_count(index); - return pre; - } - - InternalNode *locateParent(InternalNode *parent, int len, int st[3], int& count) - { - InternalNode *node = parent; - InternalNode *pre = NULL; - int index = 0; - for (int i = len / 2; i >= mindimen; i >>= 1) { - index = (((st[0] & i) ? 4 : 0) | - ((st[1] & i) ? 2 : 0) | - ((st[2] & i) ? 1 : 0)); - pre = node; - node = &node->get_child(node->get_child_count(index))->internal; - } - - count = pre->get_child_count(index); - return pre; - } - - /************ Operators for internal nodes ************/ - - - /// Add a kid to an existing internal node - InternalNode *addChild(InternalNode *node, int index, Node *child, int aLeaf) - { - // Create new internal node - int num = node->get_num_children(); - InternalNode *rnode = createInternal(num + 1); - - // Establish children - int i; - int count1 = 0, count2 = 0; - for (i = 0; i < 8; i++) { - if (i == index) { - if (aLeaf) { - rnode->set_leaf_child(i, count2, &child->leaf); - } - else { - rnode->set_internal_child(i, count2, &child->internal); - } - count2++; - } - else if (node->has_child(i)) { - if (node->is_child_leaf(i)) { - rnode->set_leaf_child(i, count2, &node->get_child(count1)->leaf); - } - else { - rnode->set_internal_child(i, count2, &node->get_child(count1)->internal); - } - count1++; - count2++; - } - } - - removeInternal(num, node); - return rnode; - } - - /// Allocate a node - InternalNode *createInternal(int length) - { - InternalNode *inode = (InternalNode *)alloc[length]->allocate(); - inode->has_child_bitfield = 0; - inode->child_is_leaf_bitfield = 0; - return inode; - } - - LeafNode *createLeaf(int length) - { - assert(length <= 3); - - LeafNode *lnode = (LeafNode *)leafalloc[length]->allocate(); - lnode->edge_parity = 0; - lnode->primary_edge_intersections = 0; - lnode->signs = 0; - - return lnode; - } - - void removeInternal(int num, InternalNode *node) - { - alloc[num]->deallocate(node); - } - - void removeLeaf(int num, LeafNode *leaf) - { - assert(num >= 0 && num <= 3); - leafalloc[num]->deallocate(leaf); - } - - /// Add a leaf (by creating a new par node with the leaf added) - InternalNode *addLeafChild(InternalNode *par, int index, int count, - LeafNode *leaf) - { - int num = par->get_num_children() + 1; - InternalNode *npar = createInternal(num); - *npar = *par; - - if (num == 1) { - npar->set_leaf_child(index, 0, leaf); - } - else { - int i; - for (i = 0; i < count; i++) { - npar->set_child(i, par->get_child(i)); - } - npar->set_leaf_child(index, count, leaf); - for (i = count + 1; i < num; i++) { - npar->set_child(i, par->get_child(i - 1)); - } - } - - removeInternal(num - 1, par); - return npar; - } - - InternalNode *addInternalChild(InternalNode *par, int index, int count, - InternalNode *node) - { - int num = par->get_num_children() + 1; - InternalNode *npar = createInternal(num); - *npar = *par; - - if (num == 1) { - npar->set_internal_child(index, 0, node); - } - else { - int i; - for (i = 0; i < count; i++) { - npar->set_child(i, par->get_child(i)); - } - npar->set_internal_child(index, count, node); - for (i = count + 1; i < num; i++) { - npar->set_child(i, par->get_child(i - 1)); - } - } - - removeInternal(num - 1, par); - return npar; - } + /************ Operators for all nodes ************/ + + /// Lookup table + int numEdgeTable[8]; + int edgeCountTable[8][3]; + + /// Build up lookup table + void buildTable() + { + for (int i = 0; i < 256; i++) { + InternalNode::numChildrenTable[i] = 0; + int count = 0; + for (int j = 0; j < 8; j++) { + InternalNode::numChildrenTable[i] += ((i >> j) & 1); + InternalNode::childrenCountTable[i][j] = count; + InternalNode::childrenIndexTable[i][count] = j; + count += ((i >> j) & 1); + } + } + + for (int i = 0; i < 8; i++) { + numEdgeTable[i] = 0; + int count = 0; + for (int j = 0; j < 3; j++) { + numEdgeTable[i] += ((i >> j) & 1); + edgeCountTable[i][j] = count; + count += ((i >> j) & 1); + } + } + } + + int getSign(Node *node, int height, int index) + { + if (height == 0) { + return getSign(&node->leaf, index); + } + else { + if (node->internal.has_child(index)) { + return getSign( + node->internal.get_child(node->internal.get_child_count(index)), height - 1, index); + } + else { + return getSign( + node->internal.get_child(0), height - 1, 7 - node->internal.get_child_index(0)); + } + } + } + + /************ Operators for leaf nodes ************/ + + void printInfo(int st[3]) + { + printf("INFO AT: %d %d %d\n", st[0] >> minshift, st[1] >> minshift, st[2] >> minshift); + LeafNode *leaf = (LeafNode *)locateLeafCheck(st); + if (leaf) + printInfo(leaf); + else + printf("Leaf not exists!\n"); + } + + void printInfo(const LeafNode *leaf) + { + /* + printf("Edge mask: "); + for(int i = 0; i < 12; i ++) + { + printf("%d ", getEdgeParity(leaf, i)); + } + printf("\n"); + printf("Stored edge mask: "); + for(i = 0; i < 3; i ++) + { + printf("%d ", getStoredEdgesParity(leaf, i)); + } + printf("\n"); + */ + printf("Sign mask: "); + for (int i = 0; i < 8; i++) { + printf("%d ", getSign(leaf, i)); + } + printf("\n"); + } + + /// Retrieve signs + int getSign(const LeafNode *leaf, int index) + { + return ((leaf->signs >> index) & 1); + } + + /// Set sign + void setSign(LeafNode *leaf, int index) + { + leaf->signs |= (1 << index); + } + + void setSign(LeafNode *leaf, int index, int sign) + { + leaf->signs &= (~(1 << index)); + leaf->signs |= ((sign & 1) << index); + } + + int getSignMask(const LeafNode *leaf) const + { + return leaf->signs; + } + + void setInProcessAll(int st[3], int dir) + { + int nst[3], eind; + for (int i = 0; i < 4; i++) { + nst[0] = st[0] + dirCell[dir][i][0] * mindimen; + nst[1] = st[1] + dirCell[dir][i][1] * mindimen; + nst[2] = st[2] + dirCell[dir][i][2] * mindimen; + eind = dirEdge[dir][i]; + + LeafNode *cell = locateLeafCheck(nst); + assert(cell); + + setInProcess(cell, eind); + } + } + + void flipParityAll(int st[3], int dir) + { + int nst[3], eind; + for (int i = 0; i < 4; i++) { + nst[0] = st[0] + dirCell[dir][i][0] * mindimen; + nst[1] = st[1] + dirCell[dir][i][1] * mindimen; + nst[2] = st[2] + dirCell[dir][i][2] * mindimen; + eind = dirEdge[dir][i]; + + LeafNode *cell = locateLeaf(nst); + flipEdge(cell, eind); + } + } + + void setInProcess(LeafNode *leaf, int eind) + { + assert(eind >= 0 && eind <= 11); + + leaf->flood_fill |= (1 << eind); + } + + void setOutProcess(LeafNode *leaf, int eind) + { + assert(eind >= 0 && eind <= 11); + + leaf->flood_fill &= ~(1 << eind); + } + + int isInProcess(LeafNode *leaf, int eind) + { + assert(eind >= 0 && eind <= 11); + + return (leaf->flood_fill >> eind) & 1; + } + + /// Generate signs at the corners from the edge parity + void generateSigns(LeafNode *leaf, unsigned char table[], int start) + { + leaf->signs = table[leaf->edge_parity]; + + if ((start ^ leaf->signs) & 1) { + leaf->signs = ~(leaf->signs); + } + } + + /// Get edge parity + int getEdgeParity(const LeafNode *leaf, int index) const + { + assert(index >= 0 && index <= 11); + + return (leaf->edge_parity >> index) & 1; + } + + /// Get edge parity on a face + int getFaceParity(LeafNode *leaf, int index) + { + int a = getEdgeParity(leaf, faceMap[index][0]) + getEdgeParity(leaf, faceMap[index][1]) + + getEdgeParity(leaf, faceMap[index][2]) + getEdgeParity(leaf, faceMap[index][3]); + return (a & 1); + } + int getFaceEdgeNum(LeafNode *leaf, int index) + { + int a = getEdgeParity(leaf, faceMap[index][0]) + getEdgeParity(leaf, faceMap[index][1]) + + getEdgeParity(leaf, faceMap[index][2]) + getEdgeParity(leaf, faceMap[index][3]); + return a; + } + + /// Set edge parity + void flipEdge(LeafNode *leaf, int index) + { + assert(index >= 0 && index <= 11); + + leaf->edge_parity ^= (1 << index); + } + + /// Set 1 + void setEdge(LeafNode *leaf, int index) + { + assert(index >= 0 && index <= 11); + + leaf->edge_parity |= (1 << index); + } + + /// Set 0 + void resetEdge(LeafNode *leaf, int index) + { + assert(index >= 0 && index <= 11); + + leaf->edge_parity &= ~(1 << index); + } + + /// Flipping with a new intersection offset + void createPrimalEdgesMask(LeafNode *leaf) + { + leaf->primary_edge_intersections = getPrimalEdgesMask2(leaf); + } + + void setStoredEdgesParity(LeafNode *leaf, int pindex) + { + assert(pindex <= 2 && pindex >= 0); + + leaf->primary_edge_intersections |= (1 << pindex); + } + + int getStoredEdgesParity(const LeafNode *leaf, int pindex) const + { + assert(pindex <= 2 && pindex >= 0); + + return (leaf->primary_edge_intersections >> pindex) & 1; + } + + LeafNode *flipEdge(LeafNode *leaf, int index, float alpha) + { + flipEdge(leaf, index); + + if ((index & 3) == 0) { + int ind = index / 4; + if (getEdgeParity(leaf, index) && !getStoredEdgesParity(leaf, ind)) { + // Create a new node + int num = getNumEdges(leaf) + 1; + setStoredEdgesParity(leaf, ind); + int count = getEdgeCount(leaf, ind); + LeafNode *nleaf = createLeaf(num); + *nleaf = *leaf; + + setEdgeOffset(nleaf, alpha, count); + + if (num > 1) { + float *pts = leaf->edge_intersections; + float *npts = nleaf->edge_intersections; + for (int i = 0; i < count; i++) { + for (int j = 0; j < EDGE_FLOATS; j++) { + npts[i * EDGE_FLOATS + j] = pts[i * EDGE_FLOATS + j]; + } + } + for (int i = count + 1; i < num; i++) { + for (int j = 0; j < EDGE_FLOATS; j++) { + npts[i * EDGE_FLOATS + j] = pts[(i - 1) * EDGE_FLOATS + j]; + } + } + } + + removeLeaf(num - 1, (LeafNode *)leaf); + leaf = nleaf; + } + } + + return leaf; + } + + /// Update parent link + void updateParent(InternalNode *node, int len, int st[3], LeafNode *leaf) + { + // First, locate the parent + int count; + InternalNode *parent = locateParent(node, len, st, count); + + // Update + parent->set_child(count, (Node *)leaf); + } + + void updateParent(InternalNode *node, int len, int st[3]) + { + if (len == dimen) { + root = (Node *)node; + return; + } + + // First, locate the parent + int count; + InternalNode *parent = locateParent(len, st, count); + + // UPdate + parent->set_child(count, (Node *)node); + } + + /// Find edge intersection on a given edge + int getEdgeIntersectionByIndex(int st[3], int index, float pt[3], int check) const + { + // First, locat the leaf + const LeafNode *leaf; + if (check) { + leaf = locateLeafCheck(st); + } + else { + leaf = locateLeaf(st); + } + + if (leaf && getStoredEdgesParity(leaf, index)) { + float off = getEdgeOffset(leaf, getEdgeCount(leaf, index)); + pt[0] = (float)st[0]; + pt[1] = (float)st[1]; + pt[2] = (float)st[2]; + pt[index] += off * mindimen; + + return 1; + } + else { + return 0; + } + } + + /// Retrieve number of edges intersected + int getPrimalEdgesMask(const LeafNode *leaf) const + { + return leaf->primary_edge_intersections; + } + + int getPrimalEdgesMask2(LeafNode *leaf) + { + return (((leaf->edge_parity & 0x1) >> 0) | ((leaf->edge_parity & 0x10) >> 3) | + ((leaf->edge_parity & 0x100) >> 6)); + } + + /// Get the count for a primary edge + int getEdgeCount(const LeafNode *leaf, int index) const + { + return edgeCountTable[getPrimalEdgesMask(leaf)][index]; + } + int getNumEdges(LeafNode *leaf) + { + return numEdgeTable[getPrimalEdgesMask(leaf)]; + } + + int getNumEdges2(LeafNode *leaf) + { + return numEdgeTable[getPrimalEdgesMask2(leaf)]; + } + + /// Set edge intersection + void setEdgeOffset(LeafNode *leaf, float pt, int count) + { + float *pts = leaf->edge_intersections; + pts[EDGE_FLOATS * count] = pt; + pts[EDGE_FLOATS * count + 1] = 0; + pts[EDGE_FLOATS * count + 2] = 0; + pts[EDGE_FLOATS * count + 3] = 0; + } + + /// Set multiple edge intersections + void setEdgeOffsets(LeafNode *leaf, float pt[3], int len) + { + float *pts = leaf->edge_intersections; + for (int i = 0; i < len; i++) { + pts[i] = pt[i]; + } + } + + /// Retrieve edge intersection + float getEdgeOffset(const LeafNode *leaf, int count) const + { + return leaf->edge_intersections[4 * count]; + } + + /// Update method + LeafNode *updateEdgeOffsets(LeafNode *leaf, int oldlen, int newlen, float offs[3]) + { + // First, create a new leaf node + LeafNode *nleaf = createLeaf(newlen); + *nleaf = *leaf; + + // Next, fill in the offsets + setEdgeOffsets(nleaf, offs, newlen); + + // Finally, delete the old leaf + removeLeaf(oldlen, leaf); + + return nleaf; + } + + /// Set minimizer index + void setMinimizerIndex(LeafNode *leaf, int index) + { + leaf->minimizer_index = index; + } + + /// Get minimizer index + int getMinimizerIndex(LeafNode *leaf) + { + return leaf->minimizer_index; + } + + int getMinimizerIndex(LeafNode *leaf, int eind) + { + int add = manifold_table[getSignMask(leaf)].pairs[eind][0] - 1; + assert(add >= 0); + return leaf->minimizer_index + add; + } + + void getMinimizerIndices(LeafNode *leaf, int eind, int inds[2]) + { + const int *add = manifold_table[getSignMask(leaf)].pairs[eind]; + inds[0] = leaf->minimizer_index + add[0] - 1; + if (add[0] == add[1]) { + inds[1] = -1; + } + else { + inds[1] = leaf->minimizer_index + add[1] - 1; + } + } + + /// Set edge intersection + void setEdgeOffsetNormal(LeafNode *leaf, float pt, float a, float b, float c, int count) + { + float *pts = leaf->edge_intersections; + pts[4 * count] = pt; + pts[4 * count + 1] = a; + pts[4 * count + 2] = b; + pts[4 * count + 3] = c; + } + + float getEdgeOffsetNormal(LeafNode *leaf, int count, float &a, float &b, float &c) + { + float *pts = leaf->edge_intersections; + a = pts[4 * count + 1]; + b = pts[4 * count + 2]; + c = pts[4 * count + 3]; + return pts[4 * count]; + } + + /// Set multiple edge intersections + void setEdgeOffsetsNormals( + LeafNode *leaf, const float pt[], const float a[], const float b[], const float c[], int len) + { + float *pts = leaf->edge_intersections; + for (int i = 0; i < len; i++) { + if (pt[i] > 1 || pt[i] < 0) { + printf("\noffset: %f\n", pt[i]); + } + pts[i * 4] = pt[i]; + pts[i * 4 + 1] = a[i]; + pts[i * 4 + 2] = b[i]; + pts[i * 4 + 3] = c[i]; + } + } + + /// Retrieve complete edge intersection + void getEdgeIntersectionByIndex( + const LeafNode *leaf, int index, int st[3], int len, float pt[3], float nm[3]) const + { + int count = getEdgeCount(leaf, index); + const float *pts = leaf->edge_intersections; + + float off = pts[4 * count]; + + pt[0] = (float)st[0]; + pt[1] = (float)st[1]; + pt[2] = (float)st[2]; + pt[index] += (off * len); + + nm[0] = pts[4 * count + 1]; + nm[1] = pts[4 * count + 2]; + nm[2] = pts[4 * count + 3]; + } + + float getEdgeOffsetNormalByIndex(LeafNode *leaf, int index, float nm[3]) + { + int count = getEdgeCount(leaf, index); + float *pts = leaf->edge_intersections; + + float off = pts[4 * count]; + + nm[0] = pts[4 * count + 1]; + nm[1] = pts[4 * count + 2]; + nm[2] = pts[4 * count + 3]; + + return off; + } + + void fillEdgeIntersections( + const LeafNode *leaf, int st[3], int len, float pts[12][3], float norms[12][3]) const + { + int i; + // int stt[3] = {0, 0, 0}; + + // The three primal edges are easy + int pmask[3] = {0, 4, 8}; + for (i = 0; i < 3; i++) { + if (getEdgeParity(leaf, pmask[i])) { + // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]); + getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]); + } + } + + // 3 face adjacent cubes + int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}}; + int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}}; + for (i = 0; i < 3; i++) { + int e1 = getEdgeParity(leaf, fmask[i][0]); + int e2 = getEdgeParity(leaf, fmask[i][1]); + if (e1 || e2) { + int nst[3] = {st[0], st[1], st[2]}; + nst[i] += len; + // int nstt[3] = {0, 0, 0}; + // nstt[i] += 1; + const LeafNode *node = locateLeaf(nst); + + if (e1) { + // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]); + getEdgeIntersectionByIndex( + node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]); + } + if (e2) { + // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]], norms[fmask[i][1]]); + getEdgeIntersectionByIndex( + node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]); + } + } + } + + // 3 edge adjacent cubes + int emask[3] = {3, 7, 11}; + int eemask[3] = {0, 1, 2}; + for (i = 0; i < 3; i++) { + if (getEdgeParity(leaf, emask[i])) { + int nst[3] = {st[0] + len, st[1] + len, st[2] + len}; + nst[i] -= len; + // int nstt[3] = {1, 1, 1}; + // nstt[i] -= 1; + const LeafNode *node = locateLeaf(nst); + + // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]); + getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]); + } + } + } + + void fillEdgeIntersections(const LeafNode *leaf, + int st[3], + int len, + float pts[12][3], + float norms[12][3], + int parity[12]) const + { + int i; + for (i = 0; i < 12; i++) { + parity[i] = 0; + } + // int stt[3] = {0, 0, 0}; + + // The three primal edges are easy + int pmask[3] = {0, 4, 8}; + for (i = 0; i < 3; i++) { + if (getStoredEdgesParity(leaf, i)) { + // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]); + getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]); + parity[pmask[i]] = 1; + } + } + + // 3 face adjacent cubes + int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}}; + int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}}; + for (i = 0; i < 3; i++) { + { + int nst[3] = {st[0], st[1], st[2]}; + nst[i] += len; + // int nstt[3] = {0, 0, 0}; + // nstt[i] += 1; + const LeafNode *node = locateLeafCheck(nst); + if (node == NULL) { + continue; + } + + int e1 = getStoredEdgesParity(node, femask[i][0]); + int e2 = getStoredEdgesParity(node, femask[i][1]); + + if (e1) { + // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]); + getEdgeIntersectionByIndex( + node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]); + parity[fmask[i][0]] = 1; + } + if (e2) { + // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]], norms[fmask[i][1]]); + getEdgeIntersectionByIndex( + node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]); + parity[fmask[i][1]] = 1; + } + } + } + + // 3 edge adjacent cubes + int emask[3] = {3, 7, 11}; + int eemask[3] = {0, 1, 2}; + for (i = 0; i < 3; i++) { + // if(getEdgeParity(leaf, emask[i])) + { + int nst[3] = {st[0] + len, st[1] + len, st[2] + len}; + nst[i] -= len; + // int nstt[3] = {1, 1, 1}; + // nstt[i] -= 1; + const LeafNode *node = locateLeafCheck(nst); + if (node == NULL) { + continue; + } + + if (getStoredEdgesParity(node, eemask[i])) { + // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]); + getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]); + parity[emask[i]] = 1; + } + } + } + } + + void fillEdgeOffsetsNormals( + LeafNode *leaf, int st[3], int len, float pts[12], float norms[12][3], int parity[12]) + { + int i; + for (i = 0; i < 12; i++) { + parity[i] = 0; + } + // int stt[3] = {0, 0, 0}; + + // The three primal edges are easy + int pmask[3] = {0, 4, 8}; + for (i = 0; i < 3; i++) { + if (getStoredEdgesParity(leaf, i)) { + pts[pmask[i]] = getEdgeOffsetNormalByIndex(leaf, i, norms[pmask[i]]); + parity[pmask[i]] = 1; + } + } + + // 3 face adjacent cubes + int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}}; + int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}}; + for (i = 0; i < 3; i++) { + { + int nst[3] = {st[0], st[1], st[2]}; + nst[i] += len; + // int nstt[3] = {0, 0, 0}; + // nstt[i] += 1; + LeafNode *node = locateLeafCheck(nst); + if (node == NULL) { + continue; + } + + int e1 = getStoredEdgesParity(node, femask[i][0]); + int e2 = getStoredEdgesParity(node, femask[i][1]); + + if (e1) { + pts[fmask[i][0]] = getEdgeOffsetNormalByIndex(node, femask[i][0], norms[fmask[i][0]]); + parity[fmask[i][0]] = 1; + } + if (e2) { + pts[fmask[i][1]] = getEdgeOffsetNormalByIndex(node, femask[i][1], norms[fmask[i][1]]); + parity[fmask[i][1]] = 1; + } + } + } + + // 3 edge adjacent cubes + int emask[3] = {3, 7, 11}; + int eemask[3] = {0, 1, 2}; + for (i = 0; i < 3; i++) { + // if(getEdgeParity(leaf, emask[i])) + { + int nst[3] = {st[0] + len, st[1] + len, st[2] + len}; + nst[i] -= len; + // int nstt[3] = {1, 1, 1}; + // nstt[i] -= 1; + LeafNode *node = locateLeafCheck(nst); + if (node == NULL) { + continue; + } + + if (getStoredEdgesParity(node, eemask[i])) { + pts[emask[i]] = getEdgeOffsetNormalByIndex(node, eemask[i], norms[emask[i]]); + parity[emask[i]] = 1; + } + } + } + } + + /// Update method + LeafNode *updateEdgeOffsetsNormals( + LeafNode *leaf, int oldlen, int newlen, float offs[3], float a[3], float b[3], float c[3]) + { + // First, create a new leaf node + LeafNode *nleaf = createLeaf(newlen); + *nleaf = *leaf; + + // Next, fill in the offsets + setEdgeOffsetsNormals(nleaf, offs, a, b, c, newlen); + + // Finally, delete the old leaf + removeLeaf(oldlen, leaf); + + return nleaf; + } + + /// Locate a leaf + /// WARNING: assuming this leaf already exists! + + LeafNode *locateLeaf(int st[3]) + { + Node *node = (Node *)root; + for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { + int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1)); + node = node->internal.get_child(node->internal.get_child_count(index)); + } + + return &node->leaf; + } + + const LeafNode *locateLeaf(int st[3]) const + { + const Node *node = root; + for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { + int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1)); + node = node->internal.get_child(node->internal.get_child_count(index)); + } + + return &node->leaf; + } + + LeafNode *locateLeaf(InternalNode *parent, int len, int st[3]) + { + Node *node = (Node *)parent; + int index; + for (int i = len / 2; i >= mindimen; i >>= 1) { + index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0)); + node = node->internal.get_child(node->internal.get_child_count(index)); + } + + return &node->leaf; + } + + LeafNode *locateLeafCheck(int st[3]) + { + Node *node = (Node *)root; + for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { + int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1)); + if (!node->internal.has_child(index)) { + return NULL; + } + node = node->internal.get_child(node->internal.get_child_count(index)); + } + + return &node->leaf; + } + + const LeafNode *locateLeafCheck(int st[3]) const + { + const Node *node = root; + for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { + int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1)); + if (!node->internal.has_child(index)) { + return NULL; + } + node = node->internal.get_child(node->internal.get_child_count(index)); + } + + return &node->leaf; + } + + InternalNode *locateParent(int len, int st[3], int &count) + { + InternalNode *node = (InternalNode *)root; + InternalNode *pre = NULL; + int index = 0; + for (int i = dimen / 2; i >= len; i >>= 1) { + index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0)); + pre = node; + node = &node->get_child(node->get_child_count(index))->internal; + } + + count = pre->get_child_count(index); + return pre; + } + + InternalNode *locateParent(InternalNode *parent, int len, int st[3], int &count) + { + InternalNode *node = parent; + InternalNode *pre = NULL; + int index = 0; + for (int i = len / 2; i >= mindimen; i >>= 1) { + index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0)); + pre = node; + node = &node->get_child(node->get_child_count(index))->internal; + } + + count = pre->get_child_count(index); + return pre; + } + + /************ Operators for internal nodes ************/ + + /// Add a kid to an existing internal node + InternalNode *addChild(InternalNode *node, int index, Node *child, int aLeaf) + { + // Create new internal node + int num = node->get_num_children(); + InternalNode *rnode = createInternal(num + 1); + + // Establish children + int i; + int count1 = 0, count2 = 0; + for (i = 0; i < 8; i++) { + if (i == index) { + if (aLeaf) { + rnode->set_leaf_child(i, count2, &child->leaf); + } + else { + rnode->set_internal_child(i, count2, &child->internal); + } + count2++; + } + else if (node->has_child(i)) { + if (node->is_child_leaf(i)) { + rnode->set_leaf_child(i, count2, &node->get_child(count1)->leaf); + } + else { + rnode->set_internal_child(i, count2, &node->get_child(count1)->internal); + } + count1++; + count2++; + } + } + + removeInternal(num, node); + return rnode; + } + + /// Allocate a node + InternalNode *createInternal(int length) + { + InternalNode *inode = (InternalNode *)alloc[length]->allocate(); + inode->has_child_bitfield = 0; + inode->child_is_leaf_bitfield = 0; + return inode; + } + + LeafNode *createLeaf(int length) + { + assert(length <= 3); + + LeafNode *lnode = (LeafNode *)leafalloc[length]->allocate(); + lnode->edge_parity = 0; + lnode->primary_edge_intersections = 0; + lnode->signs = 0; + + return lnode; + } + + void removeInternal(int num, InternalNode *node) + { + alloc[num]->deallocate(node); + } + + void removeLeaf(int num, LeafNode *leaf) + { + assert(num >= 0 && num <= 3); + leafalloc[num]->deallocate(leaf); + } + + /// Add a leaf (by creating a new par node with the leaf added) + InternalNode *addLeafChild(InternalNode *par, int index, int count, LeafNode *leaf) + { + int num = par->get_num_children() + 1; + InternalNode *npar = createInternal(num); + *npar = *par; + + if (num == 1) { + npar->set_leaf_child(index, 0, leaf); + } + else { + int i; + for (i = 0; i < count; i++) { + npar->set_child(i, par->get_child(i)); + } + npar->set_leaf_child(index, count, leaf); + for (i = count + 1; i < num; i++) { + npar->set_child(i, par->get_child(i - 1)); + } + } + + removeInternal(num - 1, par); + return npar; + } + + InternalNode *addInternalChild(InternalNode *par, int index, int count, InternalNode *node) + { + int num = par->get_num_children() + 1; + InternalNode *npar = createInternal(num); + *npar = *par; + + if (num == 1) { + npar->set_internal_child(index, 0, node); + } + else { + int i; + for (i = 0; i < count; i++) { + npar->set_child(i, par->get_child(i)); + } + npar->set_internal_child(index, count, node); + for (i = count + 1; i < num; i++) { + npar->set_child(i, par->get_child(i - 1)); + } + } + + removeInternal(num - 1, par); + return npar; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Octree") + MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Octree") #endif }; -#endif /* __OCTREE_H__ */ +#endif /* __OCTREE_H__ */ -- cgit v1.2.3