Paste Code
Paste Blends
Paste Images
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 33bf9bb..3245d90 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -34,6 +34,7 @@ add_subdirectory(iksolver)
add_subdirectory(opennl)
add_subdirectory(smoke)
add_subdirectory(mikktspace)
+add_subdirectory(dualcon)

if(WITH_MOD_FLUID)
add_subdirectory(elbeem)
diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt
new file mode 100644
index 0000000..38251f3
--- /dev/null
+++ b/intern/dualcon/CMakeLists.txt
@@ -0,0 +1,48 @@
+# $Id$
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ intern
+)
+
+set(SRC
+ intern/eigen.cpp
+ intern/manifold_table.cpp
+ intern/marching_cubes_table.cpp
+ intern/octree.cpp
+
+ intern/cubes.h
+ intern/eigen.h
+ intern/GeoCommon.h
+ intern/IntegerGrid.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
+)
+
+blender_add_lib(bf_intern_dualcon "${SRC}" "${INC}")
+
diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h
new file mode 100644
index 0000000..3a8c486
--- /dev/null
+++ b/intern/dualcon/dualcon.h
@@ -0,0 +1,62 @@
+#ifndef DUALCON_H
+#define DUALCON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef float (*DualConCo)[3];
+typedef unsigned int (*DualConFaces)[4];
+struct DerivedMesh;
+
+typedef struct {
+ DualConCo co;
+ int co_stride;
+ int totco;
+
+ DualConFaces faces;
+ int face_stride;
+ int totface;
+
+ /* input only */
+ float min[3], max[3];
+
+ /* output only */
+ int curco, curface;
+ struct DerivedMesh *dm;
+} DualConMesh;
+
+/* only used internally */
+void dualcon_mesh_add_co(DualConMesh *mesh, const float v[3]);
+void dualcon_mesh_add_polygon(DualConMesh *mesh, int totndx,
+ const int *ndx, int flip);
+
+/* callback for allocating memory for output */
+typedef DualConMesh *(*DualConCreateMesh)(int totco, int totface);
+
+typedef enum {
+ DUALCON_HERMITE = 1,
+ DUALCON_FLOOD_FILL = 2,
+ DUALCON_MANIFOLD = 4,
+} DualConFlags;
+
+typedef enum {
+ DUALCON_CENTROID,
+ DUALCON_MASS_POINT,
+ DUALCON_SHARP_FEATURES,
+} DualConMode;
+
+DualConMesh *dualcon(const DualConMesh *input_mesh,
+ DualConCreateMesh create_mesh,
+ DualConFlags flags,
+ DualConMode mode,
+ float threshold,
+ float hermite_num,
+ float scale,
+ int depth);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/intern/dualcon/intern/GeoCommon.h b/intern/dualcon/intern/GeoCommon.h
new file mode 100644
index 0000000..1d3831d
--- /dev/null
+++ b/intern/dualcon/intern/GeoCommon.h
@@ -0,0 +1,47 @@
+#ifndef GEOCOMMON_H
+#define GEOCOMMON_H
+
+#define UCHAR unsigned char
+#define USHORT unsigned short
+
+#define USE_MINIMIZER
+
+/**
+ * Structure definitions for points and triangles.
+ *
+ * @author Tao Ju
+ */
+
+
+// 3d point with integer coordinates
+typedef struct
+{
+ int x, y, z;
+} Point3i;
+
+typedef struct
+{
+ Point3i begin;
+ Point3i end;
+} BoundingBox;
+
+// triangle that points to three vertices
+typedef struct
+{
+ float vt[3][3] ;
+} Triangle;
+
+// 3d point with float coordinates
+typedef struct
+{
+ float x, y, z;
+} Point3f;
+
+typedef struct
+{
+ Point3f begin;
+ Point3f end;
+} BoundingBoxf;
+
+
+#endif
\ No newline at end of file
diff --git a/intern/dualcon/intern/IntegerGrid.h b/intern/dualcon/intern/IntegerGrid.h
new file mode 100644
index 0000000..f3e43de
--- /dev/null
+++ b/intern/dualcon/intern/IntegerGrid.h
@@ -0,0 +1,751 @@
+#ifndef INTEGERGRID_H
+#define INTEGERGRID_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#define GRID_DIMENSION 20
+
+#define LONG _int64
+
+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}} ;
+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,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}}}} ;
+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}};
+
+/**
+ * Structure for the projections inheritable from parent
+ */
+struct InheritableProjections
+{
+ /// Projections of the triangle vertices
+ LONG trigProj[13][2] ;
+
+ /// End points along each axis
+ //int cubeEnds[13][2] ;
+
+ /// Error range on each axis
+ /// LONG errorProj[13];
+};
+
+
+/**
+ * Class for projections of cube / triangle vertices on the separating axes
+ */
+class Projections
+{
+public:
+ /// Inheritable portion
+ InheritableProjections* inherit ;
+
+ /// Projections of the cube vertices
+ LONG cubeProj[13][6] ;
+
+public:
+
+ /**
+ * Default constructor
+ */
+ Projections( )
+ {
+ };
+
+ /**
+ * Construction
+ * from a cube (axes aligned) and triangle
+ */
+ Projections( LONG cube[2][3], LONG trig[3][3], LONG error )
+ {
+ int i, j ;
+ inherit = new InheritableProjections ;
+
+ /// Create axes
+ LONG axes[13][3] ;
+
+ // Cube faces
+ 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 ;
+
+ // Triangle face
+ LONG trigedge[3][3] ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trigedge[i][j] = trig[(i+1)%3][j] - trig[i][j] ;
+ }
+ }
+ crossProduct( trigedge[0], trigedge[1], axes[3] ) ;
+
+ // Face edges and triangle edges
+ int ct = 4 ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ crossProduct( axes[i], trigedge[j], axes[ct] ) ;
+ ct ++ ;
+ }
+
+ /// Generate projections
+ LONG cubeedge[3][3] ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ cubeedge[i][j] = 0 ;
+ }
+ cubeedge[i][i] = cube[1][i] - cube[0][i] ;
+ }
+
+ for ( j = 0 ; j < 13 ; j ++ )
+ {
+ // Origin
+ cubeProj[j][0] = dotProduct( axes[j], cube[0] ) ;
+
+ // 3 direction vectors
+ for ( i = 1 ; i < 4 ; i ++ )
+ {
+ cubeProj[j][i] = dotProduct( axes[j], cubeedge[i-1] ) ;
+ }
+
+ // Offsets of 2 ends of cube projection
+ LONG max = 0 ;
+ LONG min = 0 ;
+ int maxind = 0, minind = 0 ;
+ for ( i = 1 ; i < 8 ; i ++ )
+ {
+ LONG proj = vertmap[i][0] * cubeProj[j][1] + vertmap[i][1] * cubeProj[j][2] + vertmap[i][2] * cubeProj[j][3] ;
+ if ( proj > max )
+ {
+ max = proj ;
+ maxind = i ;
+ }
+ if ( proj < min )
+ {
+ min = proj ;
+ minind = i ;
+ }
+ }
+ cubeProj[j][4] = min ;
+ cubeProj[j][5] = max ;
+
+ }
+
+ for ( j = 0 ; j < 13 ; j ++ )
+ {
+ inherit->trigProj[j][0] = dotProduct( axes[j], trig[0] ) ;
+ inherit->trigProj[j][1] = inherit->trigProj[j][0] ;
+
+ for ( i = 1 ; i < 3 ; i ++ )
+ {
+ LONG proj = dotProduct( axes[j], trig[i] ) ;
+ if ( proj < inherit->trigProj[j][0] )
+ {
+ inherit->trigProj[j][0] = proj ;
+ }
+ if ( proj > inherit->trigProj[j][1] )
+ {
+ inherit->trigProj[j][1] = proj ;
+ }
+ }
+ }
+
+ // Get ends of projections
+ /*
+ for ( i = 0 ; i < 13 ; i ++ )
+ {
+ int maxind = 0, minind = 0 ;
+ LONG max = cubeProj[i][0] ;
+ LONG min = cubeProj[i][0] ;
+ for ( j = 1 ; j < 8 ; j ++ )
+ {
+ LONG proj = cubeProj[i][0] + vertmap[j][0] * cubeProj[i][1] + vertmap[j][1] * cubeProj[i][2] + vertmap[j][2] * cubeProj[i][3] ;
+ if ( proj > max )
+ {
+ max = proj ;
+ maxind = j ;
+ }
+ if ( proj < min )
+ {
+ min = proj ;
+ minind = j ;
+ }
+ }
+
+ inherit->cubeEnds[i][0] = minind ;
+ inherit->cubeEnds[i][1] = maxind ;
+ }
+ */
+
+ // exit(0) ;
+ }
+
+ /**
+ * Construction
+ * from a parent Projections object and the index of the children
+ */
+ Projections ( Projections* parent )
+ {
+ // Copy inheritable projections
+ this->inherit = parent->inherit ;
+
+ // Shrink cube projections
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ cubeProj[i][0] = parent->cubeProj[i][0] ;
+ for ( int j = 1 ; j < 6 ; j ++ )
+ {
+ cubeProj[i][j] = parent->cubeProj[i][j] >> 1 ;
+ }
+ }
+ };
+
+ /**
+ * Get projections for sub-cubes (simple axes)
+ */
+ void getSubProjectionsSimple( Projections* p[8] )
+ {
+ // Process the axes cooresponding to the triangle's normal
+ int ind = 3 ;
+ int len = cubeProj[ 0 ][ 1 ] >> 1 ;
+ int trigproj[3] = { cubeProj[ ind ][ 1 ] >> 1, cubeProj[ ind ][ 2 ] >> 1, cubeProj[ ind ][ 3 ] >> 1 } ;
+
+ int ct = 0 ;
+ for ( int i = 0 ; i < 2 ; i ++ )
+ for ( int j = 0 ; j < 2 ; j ++ )
+ for ( int k = 0 ; k < 2 ; k ++ )
+ {
+ p[ct] = new Projections( ) ;
+
+ p[ct]->cubeProj[ 0 ][ 0 ] = cubeProj[ 0 ][ 0 ] + i * len ;
+ p[ct]->cubeProj[ 1 ][ 0 ] = cubeProj[ 1 ][ 0 ] + j * len ;
+ p[ct]->cubeProj[ 2 ][ 0 ] = cubeProj[ 2 ][ 0 ] + k * len ;
+ p[ct]->cubeProj[ 0 ][ 1 ] = len ;
+
+ for ( int m = 1 ; m < 3 ; m ++ )
+ {
+ p[ct]->cubeProj[ ind ][ m ] = trigproj[ m - 1 ] ;
+ }
+ p[ct]->cubeProj[ ind ][ 0 ] = cubeProj[ ind ][0] + i * trigproj[0] + j * trigproj[1] + k * trigproj[2] ;
+
+ ct ++ ;
+ }
+ }
+
+ /**
+ * Shifting a cube to a new origin
+ */
+ void shift ( int off[3] )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
+ }
+ }
+
+ void shiftNoPrimary ( int off[3] )
+ {
+ for ( int i = 3 ; i < 13 ; i ++ )
+ {
+ cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
+ }
+ }
+
+ /**
+ * Method to test intersection of the triangle and the cube
+ */
+ int isIntersecting ( )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ /*
+ LONG 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] ;
+ LONG 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] ;
+ */
+
+ LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
+
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ };
+
+ int isIntersectingNoPrimary ( )
+ {
+ for ( int i = 3 ; i < 13 ; i ++ )
+ {
+ /*
+ LONG 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] ;
+ LONG 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] ;
+ */
+
+ LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
+
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ };
+
+ /**
+ * Method to test intersection of the triangle and one edge
+ */
+ int isIntersecting ( int edgeInd )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+
+ LONG proj0 = cubeProj[i][0] +
+ vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
+ vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
+ vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
+ LONG proj1 = cubeProj[i][0] +
+ vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
+ vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
+ vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
+
+
+ if ( proj0 < proj1 )
+ {
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+ else
+ {
+ if ( proj1 > inherit->trigProj[i][1] ||
+ proj0 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+ }
+
+ // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
+ return 1 ;
+ };
+
+ int isIntersectingPrimary ( int edgeInd )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+
+ LONG proj0 = cubeProj[i][0] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
+
+ if ( proj0 < proj1 )
+ {
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+ else
+ {
+ if ( proj1 > inherit->trigProj[i][1] ||
+ proj0 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+
+ }
+
+ // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
+ return 1 ;
+ };
+
+ float getIntersection ( int edgeInd )
+ {
+ int i = 3 ;
+
+ LONG proj0 = cubeProj[i][0] +
+ vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
+ vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
+ vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
+ LONG proj1 = cubeProj[i][0] +
+ vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
+ vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
+ vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
+ LONG proj2 = inherit->trigProj[i][1] ;
+
+ double alpha = (double)( proj2 - proj0 ) / (double)( proj1 - proj0 ) ;
+ if ( alpha < 0 )
+ {
+ alpha = 0.5 ;
+ }
+ else if ( alpha > 1 )
+ {
+ alpha = 0.5 ;
+ }
+
+ return (float)alpha ;
+ };
+
+ float getIntersectionPrimary ( int edgeInd )
+ {
+ int i = 3 ;
+
+ LONG proj0 = cubeProj[i][0] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
+ LONG proj2 = inherit->trigProj[i][1] ;
+
+ double alpha = (double)( proj2 - proj0 ) / (double)( proj1 - proj0 ) ;
+ if ( alpha < 0 )
+ {
+ alpha = 0.5 ;
+ }
+ else if ( alpha > 1 )
+ {
+ alpha = 0.5 ;
+ }
+
+ return (float)alpha ;
+ };
+
+ /**
+ * Method to perform cross-product
+ */
+ void crossProduct ( LONG a[3], LONG b[3], LONG res[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] ;
+ }
+
+ /**
+ * Method to perform dot product
+ */
+ LONG dotProduct ( LONG a[3], LONG b[3] )
+ {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ;
+ }
+
+};
+
+/**
+ * Class for projections of cube / triangle vertices on the separating axes
+ */
+class Projections2
+{
+public:
+ /// Projections of the cube vertices
+ LONG cubeProj[13][8] ;
+
+ /// Projections of the triangle vertices
+ LONG trigProj[13][3] ;
+
+ /// Min max indices
+ int cubeEnds[13][2] ;
+ int trigEnds[13][2] ;
+
+public:
+
+ /**
+ * Default construction
+ */
+ Projections2 ( )
+ {
+ };
+
+ /**
+ * Construction
+ * from a cube (axes aligned) and triangle
+ */
+ Projections2 ( LONG cube[2][3], LONG trig[3][3] )
+ {
+ int i, j ;
+
+ /// Create axes
+ LONG axes[13][3] ;
+
+ // Cube faces
+ 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 ;
+
+ // Triangle face
+ LONG trigedge[3][3] ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trigedge[i][j] = trig[(i+1)%3][j] - trig[i][j] ;
+ }
+ }
+ crossProduct( trigedge[0], trigedge[1], axes[3] ) ;
+
+ // Face edges and triangle edges
+ int ct = 4 ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ crossProduct( axes[i], trigedge[j], axes[ct] ) ;
+ ct ++ ;
+ }
+
+
+ /// Generate projections
+ LONG theCube[8][3] ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ theCube[i][j] = cube[vertmap[i][j]][j] ;
+ }
+
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ for ( j = 0 ; j < 13 ; j ++ )
+ {
+ cubeProj[j][i] = dotProduct( axes[j], theCube[i] ) ;
+ }
+ }
+
+ for ( i = 0 ; i < 3 ; i ++ )
+ for ( j = 0 ; j < 13 ; j ++ )
+ {
+ trigProj[j][i] = dotProduct( axes[j], trig[i] ) ;
+ }
+
+ // Get ends of projections
+ for ( i = 0 ; i < 13 ; i ++ )
+ {
+ int maxind = 0, minind = 0 ;
+ LONG max = cubeProj[i][0] ;
+ LONG min = cubeProj[i][0] ;
+ for ( j = 1 ; j < 8 ; j ++ )
+ {
+ if ( cubeProj[i][j] > max )
+ {
+ max = cubeProj[i][j] ;
+ maxind = j ;
+ }
+ if ( cubeProj[i][j] < min )
+ {
+ min = cubeProj[i][j] ;
+ minind = j ;
+ }
+ }
+
+ cubeEnds[i][0] = minind ;
+ cubeEnds[i][1] = maxind ;
+
+ maxind = 0 ;
+ minind = 0 ;
+ max = trigProj[i][0] ;
+ min = trigProj[i][0] ;
+ for ( j = 1 ; j < 3 ; j ++ )
+ {
+ if ( trigProj[i][j] > max )
+ {
+ max = trigProj[i][j] ;
+ maxind = j ;
+ }
+ if ( trigProj[i][j] < min )
+ {
+ min = trigProj[i][j] ;
+ minind = j ;
+ }
+ }
+
+ trigEnds[i][0] = minind ;
+ trigEnds[i][1] = maxind ;
+
+ }
+
+ };
+
+ /**
+ * Construction
+ * from a parent Projections object and the index of the children
+ */
+ Projections2 ( Projections2* parent, int childInd )
+ {
+ int i, j ;
+
+ // Copy triangle projections
+ for ( i = 0 ; i < 13 ; i ++ )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trigProj[i][j] = parent->trigProj[i][j] ;
+ }
+
+ trigEnds[i][0] = parent->trigEnds[i][0] ;
+ trigEnds[i][1] = parent->trigEnds[i][1] ;
+ }
+
+
+ // Divide cube projections
+ for ( i = 0 ; i < 13 ; i ++ )
+ {
+ for ( j = 0 ; j < 8 ; j ++ )
+ {
+ const int* ind = centmap[vertmap[childInd][0] + vertmap[j][0]]
+ [vertmap[childInd][1] + vertmap[j][1]]
+ [vertmap[childInd][2] + vertmap[j][2]] ;
+ cubeProj[i][j] = ( parent->cubeProj[i][ind[0]] + parent->cubeProj[i][ind[1]] ) >> 1 ;
+ }
+
+ cubeEnds[i][0] = parent->cubeEnds[i][0] ;
+ cubeEnds[i][1] = parent->cubeEnds[i][1] ;
+ }
+
+ };
+
+ /**
+ * Inherit projections from father
+ */
+ void inherit ( Projections2* parent, int childInd )
+ {
+ int i, j ;
+
+ // Copy triangle projections
+ for ( i = 0 ; i < 13 ; i ++ )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trigProj[i][j] = parent->trigProj[i][j] ;
+ }
+
+ trigEnds[i][0] = parent->trigEnds[i][0] ;
+ trigEnds[i][1] = parent->trigEnds[i][1] ;
+ }
+
+ // Divide cube projections
+ for ( i = 0 ; i < 13 ; i ++ )
+ {
+ for ( j = 0 ; j < 8 ; j ++ )
+ {
+ const int* ind = centmap[vertmap[childInd][0] + vertmap[j][0]]
+ [vertmap[childInd][1] + vertmap[j][1]]
+ [vertmap[childInd][2] + vertmap[j][2]] ;
+ cubeProj[i][j] = ( parent->cubeProj[i][ind[0]] + parent->cubeProj[i][ind[1]] ) >> 1 ;
+ }
+
+ cubeEnds[i][0] = parent->cubeEnds[i][0] ;
+ cubeEnds[i][1] = parent->cubeEnds[i][1] ;
+ }
+
+ }
+
+ /**
+ * Destruction
+ */
+ ~Projections2 ( )
+ {
+
+ };
+
+ /**
+ * Method to test intersection of the triangle and the cube
+ */
+ int isIntersecting ( )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ if ( cubeProj[i][cubeEnds[i][0]] > trigProj[i][trigEnds[i][1]] ||
+ cubeProj[i][cubeEnds[i][1]] < trigProj[i][trigEnds[i][0]] )
+ {
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ };
+
+ /**
+ * Method to test intersection of the triangle and one edge
+ */
+ int isIntersecting ( int edgeInd )
+ {
+
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ LONG proj0 = cubeProj[i][edgemap[edgeInd][0]] ;
+ LONG proj1 = cubeProj[i][edgemap[edgeInd][1]] ;
+
+ // Put in order
+ if ( proj0 > proj1 )
+ {
+ LONG temp = proj0 ;
+ proj0 = proj1 ;
+ proj1 = temp ;
+ }
+
+ if ( proj0 > trigProj[i][trigEnds[i][1]] ||
+ proj1 < trigProj[i][trigEnds[i][0]] )
+ {
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ };
+
+ /**
+ * Method to perform cross-product
+ */
+ void crossProduct ( LONG a[3], LONG b[3], LONG res[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] ;
+ }
+
+ /**
+ * Method to perform dot product
+ */
+ LONG dotProduct ( LONG a[3], LONG b[3] )
+ {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ;
+ }
+};
+
+#endif
\ No newline at end of file
diff --git a/intern/dualcon/intern/MemoryAllocator.h b/intern/dualcon/intern/MemoryAllocator.h
new file mode 100644
index 0000000..5f7ed09
--- /dev/null
+++ b/intern/dualcon/intern/MemoryAllocator.h
@@ -0,0 +1,471 @@
+#ifndef MEMORYALLOCATOR_H
+#define MEMORYALLOCATOR_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define HEAP_BASE 16
+#define UCHAR unsigned char
+
+/**
+ * Customized memory allocators that allocates/deallocates memory in chunks
+ *
+ * @author Tao Ju
+ */
+
+
+
+/**
+ * Base class of memory allocators
+ */
+class VirtualMemoryAllocator
+{
+public:
+ virtual UCHAR * allocate( ) = 0 ;
+ virtual void deallocate( UCHAR * obj ) = 0 ;
+ virtual void destroy( ) = 0 ;
+ virtual void printInfo( ) = 0 ;
+
+ virtual int getAllocated( ) = 0 ;
+ virtual int getAll( ) = 0 ;
+ virtual int getBytes( ) = 0 ;
+};
+
+/**
+ * Dynamic memory allocator - allows allocation/deallocation
+ *
+ * Note: there are 4 bytes overhead for each allocated yet unused object.
+ */
+template < int N >
+class MemoryAllocator : public VirtualMemoryAllocator
+{
+private:
+
+ /// Constants
+ int HEAP_UNIT, HEAP_MASK ;
+
+ /// Data array
+ UCHAR ** data ;
+
+ /// Allocation stack
+ UCHAR *** stack ;
+
+ /// Number of data blocks
+ int datablocknum ;
+
+ /// Number of stack blocks
+ int stackblocknum ;
+
+ /// Size of stack
+ int stacksize ;
+
+ /// 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 ;
+ }
+
+ /**
+ * 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:
+ /**
+ * 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 ) ;
+ }
+ }
+
+ /**
+ * 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 ) ;
+ }
+
+ /**
+ * Allocation method
+ */
+ UCHAR * allocate ( )
+ {
+ if ( available == 0 )
+ {
+ allocateDataBlock ( ) ;
+ }
+
+ // printf("Allocating %d\n", header[ allocated ]) ;
+ available -- ;
+ return stack[ available >> HEAP_BASE ][ available & HEAP_MASK ] ;
+ }
+
+ /**
+ * De-allocation method
+ */
+ void deallocate ( UCHAR * obj )
+ {
+ if ( available == stacksize )
+ {
+ allocateStackBlock ( ) ;
+ }
+
+ // printf("De-allocating %d\n", ( obj - data ) / N ) ;
+ stack[ available >> HEAP_BASE ][ available & HEAP_MASK ] = 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 ) ;
+ }
+
+ /**
+ * Query methods
+ */
+ int getAllocated( )
+ {
+ return HEAP_UNIT * datablocknum - available ;
+ };
+
+ int getAll( )
+ {
+ return HEAP_UNIT * datablocknum ;
+ };
+
+ int getBytes( )
+ {
+ return N ;
+ };
+};
+
+/**
+ * Monotonic memory allocator - allows for allocation only
+ *
+ * Note: does not provide de-allocation method
+ */
+template < int N >
+class MonotonicMemoryAllocator : public VirtualMemoryAllocator
+{
+private:
+
+ /// Constants
+ int HEAP_UNIT, HEAP_MASK ;
+
+ /// Data array
+ UCHAR ** data ;
+
+ /// Number of blocks
+ int blocknum ;
+
+ /// Total size of objects
+ int totalsize ;
+
+ /// Number of allocated objects
+ int allocated ;
+
+ /// Size of the first block
+ int firstblocksize ;
+
+ /**
+ * Allocate a block
+ */
+ void allocateBlock ( )
+ {
+ int oldsize = totalsize ;
+ totalsize += HEAP_UNIT ;
+ blocknum += 1 ;
+
+ // printf("Allocating... block size: %d %d\n", totalsize, totalsize * N ) ;
+ data = ( UCHAR ** )realloc( data, sizeof ( UCHAR * ) * blocknum ) ;
+ data[ blocknum - 1 ] = ( UCHAR * )malloc( HEAP_UNIT * N ) ;
+ }
+
+
+public:
+ /**
+ * Constructor
+ */
+ MonotonicMemoryAllocator( int length )
+ {
+ HEAP_UNIT = 1 << HEAP_BASE ;
+ HEAP_MASK = ( 1 << HEAP_BASE ) - 1 ;
+
+ firstblocksize = length ;
+ totalsize = length ;
+ blocknum = 1 ;
+ allocated = 0 ;
+ data = ( UCHAR ** )malloc( sizeof( UCHAR * ) ) ;
+ data[ 0 ] = ( UCHAR * )malloc( totalsize * N ) ;
+ }
+
+ /**
+ * Destructor
+ */
+ void destroy( )
+ {
+ for ( int i = 0 ; i < blocknum ; i ++ )
+ {
+ free(data[ i ]) ;
+ }
+ free( data ) ;
+ }
+
+ /**
+ * Allocation method
+ */
+ UCHAR * allocate ( )
+ {
+ if ( allocated == totalsize )
+ {
+ allocateBlock ( ) ;
+ }
+
+ // printf("Allocating %d\n", header[ allocated ]) ;
+ int nallocated = allocated ;
+ allocated ++ ;
+
+ if ( nallocated < firstblocksize )
+ {
+ return ( data[ 0 ] + nallocated * N ) ;
+ }
+ else
+ {
+ nallocated -= firstblocksize ;
+ return ( data[ 1 + ( nallocated >> HEAP_BASE ) ] + ( nallocated & HEAP_MASK ) * N ) ;
+ }
+ }
+
+ /**
+ * De-allocation method
+ */
+ void deallocate ( UCHAR * obj )
+ {
+ printf("Attempt to deallocate from an allocation-only heap...Exit.\n") ;
+ exit( 0 ) ;
+ } ;
+
+ /**
+ * Print information
+ */
+ void printInfo ( )
+ {
+ printf("Bytes: %d Allocated: %d All: %d\n", N, allocated, totalsize ) ;
+ }
+
+ /**
+ * Query methods
+ */
+ int getAllocated( )
+ {
+ return allocated ;
+ };
+
+ int getAll( )
+ {
+ return totalsize ;
+ };
+
+ int getBytes( )
+ {
+ return N ;
+ };
+};
+
+/**
+ * Serial memory allocator - allows for serial allocation and deallocation
+ */
+template < int N >
+class SerialMemoryAllocator : public VirtualMemoryAllocator
+{
+private:
+
+ /// Constants
+ int HEAP_UNIT, HEAP_MASK ;
+
+ /// Data array
+ UCHAR ** data ;
+
+ /// Number of blocks
+ int blocknum ;
+
+ /// Total size of objects
+ int totalsize ;
+
+ /// Number of allocated objects
+ int allocated ;
+
+ /**
+ * Allocate a block
+ */
+ void allocateBlock ( )
+ {
+ int oldsize = totalsize ;
+ totalsize += HEAP_UNIT ;
+ blocknum += 1 ;
+
+ // printf("Allocating... block size: %d %d\n", totalsize, totalsize * N ) ;
+ data = ( UCHAR ** )realloc( data, sizeof ( UCHAR * ) * blocknum ) ;
+ data[ blocknum - 1 ] = ( UCHAR * )malloc( HEAP_UNIT * N ) ;
+ }
+
+
+public:
+ /**
+ * Constructor
+ */
+ SerialMemoryAllocator( )
+ {
+ HEAP_UNIT = 1 << HEAP_BASE ;
+ HEAP_MASK = ( 1 << HEAP_BASE ) - 1 ;
+
+ totalsize = HEAP_UNIT ;
+ blocknum = 1 ;
+ allocated = 0 ;
+ data = ( UCHAR ** )malloc( sizeof( UCHAR * ) ) ;
+ data[ 0 ] = ( UCHAR * )malloc( totalsize * N ) ;
+ }
+
+ /**
+ * Destructor
+ */
+ void destroy( )
+ {
+ for ( int i = 0 ; i < blocknum ; i ++ )
+ {
+ free( data[ i ] ) ;
+ }
+ free( data ) ;
+ }
+
+ /**
+ * Allocation method
+ */
+ UCHAR * allocate ( )
+ {
+ if ( allocated == totalsize )
+ {
+ allocateBlock ( ) ;
+ }
+
+ // printf("Allocating %d\n", header[ allocated ]) ;
+ int nallocated = allocated ;
+ allocated ++ ;
+ return ( data[ nallocated >> HEAP_BASE ] + ( nallocated & HEAP_MASK ) * N ) ;
+ }
+
+ /**
+ * Random-access de-allocation method: not implemented
+ */
+ void deallocate ( UCHAR * obj )
+ {
+ printf("Attempt to deallocate from an allocation-only heap...Exit.\n") ;
+ exit( 0 ) ;
+ } ;
+
+ /**
+ * Serial De-allocation method
+ */
+ void deallocateSerial ( int num )
+ {
+ allocated -= num ;
+ }
+
+ /**
+ * Get element
+ */
+ UCHAR * getAllocatedAt ( int index )
+ {
+ if ( index >= 0 )
+ {
+ return ( data[ index >> HEAP_BASE ] + ( index & HEAP_MASK ) * N ) ;
+ }
+
+ return NULL ;
+ }
+
+ /**
+ * Print information
+ */
+ void printInfo ( )
+ {
+ printf("Bytes: %d Allocated: %d All: %d\n", N, allocated, totalsize ) ;
+ }
+
+ /**
+ * Query methods
+ */
+ int getAllocated( )
+ {
+ return allocated ;
+ };
+
+ int getAll( )
+ {
+ return totalsize ;
+ };
+
+ int getBytes( )
+ {
+ return N ;
+ };
+};
+
+
+
+#endif
diff --git a/intern/dualcon/intern/ModelReader.h b/intern/dualcon/intern/ModelReader.h
new file mode 100644
index 0000000..4948aa1
--- /dev/null
+++ b/intern/dualcon/intern/ModelReader.h
@@ -0,0 +1,42 @@
+#ifndef MODELREADER_H
+#define MODELREADER_H
+
+#include "GeoCommon.h"
+
+/*
+ * Virtual class for input file readers
+ *
+ * @author Tao Ju
+ */
+class ModelReader
+{
+public:
+ /// Constructor
+ ModelReader(){} ;
+
+ /// 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 number of triangles
+ virtual int getNumTriangles ( ) = 0 ;
+
+ /// Get storage size
+ virtual int getMemory ( ) = 0 ;
+
+ /// Reset file reading location
+ virtual void reset( ) = 0 ;
+
+ /// For explicit vertex models
+ virtual int getNumVertices( ) = 0 ;
+
+ virtual void getNextVertex( float v[3] ) = 0 ;
+
+ virtual void printInfo ( ) = 0 ;
+};
+
+
+#endif
\ No newline at end of file
diff --git a/intern/dualcon/intern/Projections.h b/intern/dualcon/intern/Projections.h
new file mode 100644
index 0000000..1a5b105
--- /dev/null
+++ b/intern/dualcon/intern/Projections.h
@@ -0,0 +1,827 @@
+#ifndef PROJECTIONS_H
+#define PROJECTIONS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define CONTAINS_INDEX
+#define GRID_DIMENSION 20
+
+#define LONG int64_t
+#define UCHAR unsigned char
+
+/**
+ * Structures and classes for computing projections of triangles
+ * onto separating axes during scan conversion
+ *
+ * @author Tao Ju
+ */
+
+
+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}} ;
+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,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}}}} ;
+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}};
+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 }} ;
+
+/**
+ * Structure for the projections inheritable from parent
+ */
+struct InheritableProjections
+{
+ /// Projections of triangle
+ LONG trigProj[13][2] ;
+
+ /// Projections of triangle vertices on primary axes
+ LONG trigVertProj[13][3] ;
+
+ /// Projections of triangle edges
+ LONG trigEdgeProj[13][3][2] ;
+
+ /// Normal of the triangle
+ double norm[3] ;
+ double normA, normB ;
+
+ /// End points along each axis
+ //int cubeEnds[13][2] ;
+
+ /// Error range on each axis
+ /// LONG errorProj[13];
+
+#ifdef CONTAINS_INDEX
+ /// Index of polygon
+ int index ;
+#endif
+};
+
+
+/**
+ * Class for projections of cube / triangle vertices on the separating axes
+ */
+class Projections
+{
+public:
+ /// Inheritable portion
+ InheritableProjections* inherit ;
+
+ /// Projections of the cube vertices
+ LONG cubeProj[13][6] ;
+
+public:
+
+ Projections( )
+ {
+ }
+
+ /**
+ * Construction
+ * from a cube (axes aligned) and triangle
+ */
+ Projections( LONG cube[2][3], LONG trig[3][3], LONG error, int triind )
+ {
+ int i, j ;
+ inherit = new InheritableProjections ;
+#ifdef CONTAINS_INDEX
+ inherit->index = triind ;
+#endif
+ /// Create axes
+ LONG axes[13][3] ;
+
+ // Cube faces
+ 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 ;
+
+ // Triangle face
+ LONG trigedge[3][3] ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trigedge[i][j] = trig[(i+1)%3][j] - trig[i][j] ;
+ }
+ }
+ crossProduct( trigedge[0], trigedge[1], axes[3] ) ;
+
+ /// Normalize face normal and store
+ double dedge1[] = { (double) trig[1][0] - (double) trig[0][0],
+ (double) trig[1][1] - (double) trig[0][1],
+ (double) trig[1][2] - (double) trig[0][2] } ;
+ double dedge2[] = { (double) trig[2][0] - (double) trig[1][0],
+ (double) trig[2][1] - (double) trig[1][1],
+ (double) trig[2][2] - (double) trig[1][2] } ;
+ crossProduct( dedge1, dedge2, inherit->norm ) ;
+ normalize( inherit->norm ) ;
+// inherit->normA = norm[ 0 ] ;
+// inherit->normB = norm[ 2 ] > 0 ? norm[ 1 ] : 2 + norm[ 1 ] ;
+
+ // Face edges and triangle edges
+ int ct = 4 ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ crossProduct( axes[j], trigedge[i], axes[ct] ) ;
+ ct ++ ;
+ }
+
+ /// Generate projections
+ LONG cubeedge[3][3] ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ cubeedge[i][j] = 0 ;
+ }
+ cubeedge[i][i] = cube[1][i] - cube[0][i] ;
+ }
+
+ for ( j = 0 ; j < 13 ; j ++ )
+ {
+ // Origin
+ cubeProj[j][0] = dotProduct( axes[j], cube[0] ) ;
+
+ // 3 direction vectors
+ for ( i = 1 ; i < 4 ; i ++ )
+ {
+ cubeProj[j][i] = dotProduct( axes[j], cubeedge[i-1] ) ;
+ }
+
+ // Offsets of 2 ends of cube projection
+ LONG max = 0 ;
+ LONG min = 0 ;
+ for ( i = 1 ; i < 8 ; i ++ )
+ {
+ LONG proj = vertmap[i][0] * cubeProj[j][1] + vertmap[i][1] * cubeProj[j][2] + vertmap[i][2] * cubeProj[j][3] ;
+ if ( proj > max )
+ {
+ max = proj ;
+ }
+ if ( proj < min )
+ {
+ min = proj ;
+ }
+ }
+ cubeProj[j][4] = min ;
+ cubeProj[j][5] = max ;
+
+ }
+
+ for ( j = 0 ; j < 13 ; j ++ )
+ {
+ LONG vts[3] = { dotProduct( axes[j], trig[0] ),
+ dotProduct( axes[j], trig[1] ),
+ dotProduct( axes[j], trig[2] ) } ;
+
+ // Vertex
+ inherit->trigVertProj[j][0] = vts[0] ;
+ inherit->trigVertProj[j][1] = vts[1] ;
+ inherit->trigVertProj[j][2] = vts[2] ;
+
+ // Edge
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ if ( vts[i] < vts[(i+1) % 3] )
+ {
+ inherit->trigEdgeProj[j][i][0] = vts[i] ;
+ inherit->trigEdgeProj[j][i][1] = vts[(i+1) % 3] ;
+ }
+ else
+ {
+ inherit->trigEdgeProj[j][i][1] = vts[i] ;
+ inherit->trigEdgeProj[j][i][0] = vts[(i+1) % 3] ;
+ }
+ }
+
+ // Triangle
+ inherit->trigProj[j][0] = vts[0] ;
+ inherit->trigProj[j][1] = vts[0] ;
+ for ( i = 1 ; i < 3 ; i ++ )
+ {
+ if ( vts[i] < inherit->trigProj[j][0] )
+ {
+ inherit->trigProj[j][0] = vts[i] ;
+ }
+ if ( vts[i] > inherit->trigProj[j][1] )
+ {
+ inherit->trigProj[j][1] = vts[i] ;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Construction
+ * from a parent Projections object and the index of the children
+ */
+ Projections ( Projections* parent )
+ {
+ // Copy inheritable projections
+ this->inherit = parent->inherit ;
+
+ // Shrink cube projections
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ cubeProj[i][0] = parent->cubeProj[i][0] ;
+ for ( int j = 1 ; j < 6 ; j ++ )
+ {
+ cubeProj[i][j] = parent->cubeProj[i][j] >> 1 ;
+ }
+ }
+ };
+
+ Projections ( Projections* parent, int box[3], int depth )
+ {
+ int mask = ( 1 << depth ) - 1 ;
+ int nbox[3] = { box[0] & mask, box[1] & mask, box[2] & mask } ;
+
+ // Copy inheritable projections
+ this->inherit = parent->inherit ;
+
+ // Shrink cube projections
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ for ( int j = 1 ; j < 6 ; j ++ )
+ {
+ cubeProj[i][j] = parent->cubeProj[i][j] >> depth ;
+ }
+
+ cubeProj[i][0] = parent->cubeProj[i][0] + nbox[0] * cubeProj[i][1] + nbox[1] * cubeProj[i][2] + nbox[2] * cubeProj[i][3] ;
+ }
+ };
+
+ /**
+ * Testing intersection based on vertex/edge masks
+ */
+ int getIntersectionMasks( UCHAR cedgemask, UCHAR& edgemask )
+ {
+ int i, j ;
+ edgemask = cedgemask ;
+
+ // Pre-processing
+ /*
+ if ( cvertmask & 1 )
+ {
+ edgemask |= 5 ;
+ }
+ if ( cvertmask & 2 )
+ {
+ edgemask |= 3 ;
+ }
+ if ( cvertmask & 4 )
+ {
+ edgemask |= 6 ;
+ }
+
+ */
+
+ // Test axes for edge intersection
+ UCHAR bit = 1 ;
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ if ( edgemask & bit )
+ {
+ for ( i = 0 ; i < 13 ; i ++ )
+ {
+ LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
+
+ if ( proj0 > inherit->trigEdgeProj[i][j][1] ||
+ proj1 < inherit->trigEdgeProj[i][j][0] )
+ {
+ edgemask &= ( ~ bit ) ;
+ break ;
+ }
+ }
+ }
+ bit <<= 1 ;
+ }
+
+ /*
+ if ( edgemask != 0 )
+ {
+ printf("%d %d\n", cedgemask, edgemask) ;
+ }
+ */
+
+ // Test axes for triangle intersection
+ if ( edgemask )
+ {
+ return 1 ;
+ }
+
+ for ( i = 3 ; i < 13 ; i ++ )
+ {
+ LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
+
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ }
+
+ /**
+ * Retrieving children masks using PRIMARY AXES
+ */
+ UCHAR getChildrenMasks( UCHAR cvertmask, UCHAR vertmask[8] )
+ {
+ int i, j, k ;
+ int bmask[3][2] = {{0,0},{0,0},{0,0}} ;
+ int vmask[3][3][2] = {{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}}} ;
+ UCHAR boxmask = 0 ;
+ LONG len = cubeProj[0][1] >> 1 ;
+
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ LONG mid = cubeProj[i][0] + len ;
+
+ // Check bounding box
+ if ( mid >= inherit->trigProj[i][0] )
+ {
+ bmask[i][0] = 1 ;
+ }
+ if ( mid <= inherit->trigProj[i][1] )
+ {
+ bmask[i][1] = 1 ;
+ }
+
+ // Check vertex mask
+ if ( cvertmask )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ if ( cvertmask & ( 1 << j ) )
+ {
+ // Only check if it's contained this node
+ if ( mid >= inherit->trigVertProj[i][j] )
+ {
+ vmask[i][j][0] = 1 ;
+ }
+ if ( mid <= inherit->trigVertProj[i][j] )
+ {
+ vmask[i][j][1] = 1 ;
+ }
+ }
+ }
+ }
+
+ /*
+ // Check edge mask
+ if ( cedgemask )
+ {
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ if ( cedgemask & ( 1 << j ) )
+ {
+ // Only check if it's contained this node
+ if ( mid >= inherit->trigEdgeProj[i][j][0] )
+ {
+ emask[i][j][0] = 1 ;
+ }
+ if ( mid <= inherit->trigEdgeProj[i][j][1] )
+ {
+ emask[i][j][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 ) ;
+ vertmask[ct] = (( vmask[0][0][i] & vmask[1][0][j] & vmask[2][0][k] ) |
+ (( vmask[0][1][i] & vmask[1][1][j] & vmask[2][1][k] ) << 1 ) |
+ (( vmask[0][2][i] & vmask[1][2][j] & vmask[2][2][k] ) << 2 ) ) ;
+ /*
+ edgemask[ct] = (( emask[0][0][i] & emask[1][0][j] & emask[2][0][k] ) |
+ (( emask[0][1][i] & emask[1][1][j] & emask[2][1][k] ) << 1 ) |
+ (( emask[0][2][i] & emask[1][2][j] & emask[2][2][k] ) << 2 ) ) ;
+ edgemask[ct] = cedgemask ;
+ */
+ ct ++ ;
+ }
+
+ // Return bounding box masks
+ return boxmask ;
+ }
+
+ UCHAR getBoxMask( )
+ {
+ int i, j, k ;
+ int bmask[3][2] = {{0,0},{0,0},{0,0}} ;
+ UCHAR boxmask = 0 ;
+ LONG len = cubeProj[0][1] >> 1 ;
+
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ LONG mid = cubeProj[i][0] + len ;
+
+ // Check bounding box
+ if ( mid >= inherit->trigProj[i][0] )
+ {
+ bmask[i][0] = 1 ;
+ }
+ if ( mid <= inherit->trigProj[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 ;
+ }
+
+
+ /**
+ * Get projections for sub-cubes (simple axes)
+ */
+ void getSubProjectionsSimple( Projections* p[8] )
+ {
+ // Process the axes cooresponding to the triangle's normal
+ int ind = 3 ;
+ LONG len = cubeProj[ 0 ][ 1 ] >> 1 ;
+ LONG trigproj[3] = { cubeProj[ ind ][ 1 ] >> 1, cubeProj[ ind ][ 2 ] >> 1, cubeProj[ ind ][ 3 ] >> 1 } ;
+
+ int ct = 0 ;
+ for ( int i = 0 ; i < 2 ; i ++ )
+ for ( int j = 0 ; j < 2 ; j ++ )
+ for ( int k = 0 ; k < 2 ; k ++ )
+ {
+ p[ct] = new Projections( ) ;
+ p[ct]->inherit = inherit ;
+
+ p[ct]->cubeProj[ 0 ][ 0 ] = cubeProj[ 0 ][ 0 ] + i * len ;
+ p[ct]->cubeProj[ 1 ][ 0 ] = cubeProj[ 1 ][ 0 ] + j * len ;
+ p[ct]->cubeProj[ 2 ][ 0 ] = cubeProj[ 2 ][ 0 ] + k * len ;
+ p[ct]->cubeProj[ 0 ][ 1 ] = len ;
+
+ for ( int m = 1 ; m < 4 ; m ++ )
+ {
+ p[ct]->cubeProj[ ind ][ m ] = trigproj[ m - 1 ] ;
+ }
+ p[ct]->cubeProj[ ind ][ 0 ] = cubeProj[ ind ][0] + i * trigproj[0] + j * trigproj[1] + k * trigproj[2] ;
+
+ ct ++ ;
+ }
+ }
+
+ /**
+ * Shifting a cube to a new origin
+ */
+ void shift ( int off[3] )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
+ }
+ }
+
+ void shiftNoPrimary ( int off[3] )
+ {
+ for ( int i = 3 ; i < 13 ; i ++ )
+ {
+ cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
+ }
+ }
+
+ /**
+ * Method to test intersection of the triangle and the cube
+ */
+ int isIntersecting ( )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ /*
+ LONG 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] ;
+ LONG 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] ;
+ */
+
+ LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
+
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ };
+
+ int isIntersectingNoPrimary ( )
+ {
+ for ( int i = 3 ; i < 13 ; i ++ )
+ {
+ /*
+ LONG 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] ;
+ LONG 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] ;
+ */
+
+ LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
+
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ };
+
+ /**
+ * Method to test intersection of the triangle and one edge
+ */
+ int isIntersecting ( int edgeInd )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+
+ LONG proj0 = cubeProj[i][0] +
+ vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
+ vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
+ vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
+ LONG proj1 = cubeProj[i][0] +
+ vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
+ vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
+ vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
+
+
+ if ( proj0 < proj1 )
+ {
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+ else
+ {
+ if ( proj1 > inherit->trigProj[i][1] ||
+ proj0 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+ }
+
+ // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
+ return 1 ;
+ };
+
+ /**
+ * Method to test intersection of one triangle edge and one cube face
+ */
+ int isIntersecting ( int edgeInd, int faceInd )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+ LONG trigproj0 = inherit->trigVertProj[i][edgeInd] ;
+ LONG trigproj1 = inherit->trigVertProj[i][(edgeInd+1)%3] ;
+
+ if ( trigproj0 < trigproj1 )
+ {
+ int t1 = 1 , t2 = 1 ;
+ for ( int j = 0 ; j < 4 ; j ++ )
+ {
+ LONG proj = cubeProj[i][0] +
+ vertmap[facemap[faceInd][j]][0] * cubeProj[i][1] +
+ vertmap[facemap[faceInd][j]][1] * cubeProj[i][2] +
+ vertmap[facemap[faceInd][j]][2] * cubeProj[i][3] ;
+ if ( proj >= trigproj0 )
+ {
+ t1 = 0 ;
+ }
+ if ( proj <= trigproj1 )
+ {
+ t2 = 0 ;
+ }
+ }
+ if ( t1 || t2 )
+ {
+ return 0 ;
+ }
+ }
+ else
+ {
+ int t1 = 1 , t2 = 1 ;
+ for ( int j = 0 ; j < 4 ; j ++ )
+ {
+ LONG proj = cubeProj[i][0] +
+ vertmap[facemap[faceInd][j]][0] * cubeProj[i][1] +
+ vertmap[facemap[faceInd][j]][1] * cubeProj[i][2] +
+ vertmap[facemap[faceInd][j]][2] * cubeProj[i][3] ;
+ if ( proj >= trigproj1 )
+ {
+ t1 = 0 ;
+ }
+ if ( proj <= trigproj0 )
+ {
+ t2 = 0 ;
+ }
+ }
+ if ( t1 || t2 )
+ {
+ return 0 ;
+ }
+ }
+ }
+
+ return 1 ;
+ };
+
+
+ int isIntersectingPrimary ( int edgeInd )
+ {
+ for ( int i = 0 ; i < 13 ; i ++ )
+ {
+
+ LONG proj0 = cubeProj[i][0] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
+
+ if ( proj0 < proj1 )
+ {
+ if ( proj0 > inherit->trigProj[i][1] ||
+ proj1 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+ else
+ {
+ if ( proj1 > inherit->trigProj[i][1] ||
+ proj0 < inherit->trigProj[i][0] )
+ {
+ return 0 ;
+ }
+ }
+
+ }
+
+ // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
+ return 1 ;
+ };
+
+ double getIntersection ( int edgeInd )
+ {
+ int i = 3 ;
+
+ LONG proj0 = cubeProj[i][0] +
+ vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
+ vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
+ vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
+ LONG proj1 = cubeProj[i][0] +
+ vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
+ vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
+ vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
+ LONG proj2 = inherit->trigProj[i][1] ;
+
+ /*
+ if ( proj0 < proj1 )
+ {
+ if ( proj2 < proj0 || proj2 > proj1 )
+ {
+ return -1 ;
+ }
+ }
+ else
+ {
+ if ( proj2 < proj1 || proj2 > proj0 )
+ {
+ return -1 ;
+ }
+ }
+ */
+
+ double alpha = (double)( proj2 - proj0 ) / (double)( proj1 - proj0 ) ;
+ /*
+ if ( alpha < 0 )
+ {
+ alpha = 0.5 ;
+ }
+ else if ( alpha > 1 )
+ {
+ alpha = 0.5 ;
+ }
+ */
+
+ return alpha ;
+ };
+
+ float getIntersectionPrimary ( int edgeInd )
+ {
+ int i = 3 ;
+
+
+ LONG proj0 = cubeProj[i][0] ;
+ LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
+ LONG proj2 = inherit->trigProj[i][1] ;
+
+ // double alpha = (double)( ( proj2 - proj0 ) * cubeProj[edgeInd][edgeInd + 1] ) / (double)( proj1 - proj0 ) ;
+ double alpha = (double)( ( proj2 - proj0 ) ) / (double)( proj1 - proj0 ) ;
+
+ if ( alpha < 0 )
+ {
+ alpha = 0.5 ;
+ }
+ else if ( alpha > 1 )
+ {
+ alpha = 0.5 ;
+ }
+
+
+ return (float)alpha ;
+ };
+
+ /**
+ * Method to perform cross-product
+ */
+ void crossProduct ( LONG a[3], LONG b[3], LONG res[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] ;
+ }
+ void crossProduct ( double a[3], double b[3], double res[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] ;
+ }
+
+ /**
+ * Method to perform dot product
+ */
+ LONG dotProduct ( LONG a[3], LONG b[3] )
+ {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ;
+ }
+
+ 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 ;
+ }
+ }
+
+};
+
+#endif
diff --git a/intern/dualcon/intern/Queue.h b/intern/dualcon/intern/Queue.h
new file mode 100644
index 0000000..084143a
--- /dev/null
+++ b/intern/dualcon/intern/Queue.h
@@ -0,0 +1,88 @@
+#ifndef QUEUE_H
+#define QUEUE_H
+
+struct gridQueueEle
+{
+ 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 ;
+ }
+
+};
+
+
+
+
+
+#endif
\ No newline at end of file
diff --git a/intern/dualcon/intern/cubes.h b/intern/dualcon/intern/cubes.h
new file mode 100644
index 0000000..cd24fed
--- /dev/null
+++ b/intern/dualcon/intern/cubes.h
@@ -0,0 +1,27 @@
+/* all code originally contributed by Tao Ju */
+/* modifications by Nicholas Bishop */
+
+#ifndef CUBES_H
+#define CUBES_H
+
+#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];
+ }
+
+ /// 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];
+ }
+};
+
+#endif
diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp
new file mode 100644
index 0000000..d12fdee
--- /dev/null
+++ b/intern/dualcon/intern/dualcon_c_api.cpp
@@ -0,0 +1,202 @@
+#include <cassert>
+#include "dualcon.h"
+#include "ModelReader.h"
+#include "octree.h"
+
+#include <cstdio>
+
+void veccopy(float dst[3], const float src[3])
+{
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+}
+
+#define GET_FACE(_mesh, _n) \
+ (*(DualConFaces)(((char*)(_mesh)->faces) + ((_n) * (_mesh)->face_stride)))
+
+#define GET_CO(_mesh, _n) \
+ (*(DualConCo)(((char*)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
+
+void dualcon_mesh_add_co(DualConMesh *mesh, const float v[3])
+{
+ assert(mesh->curco < mesh->totco);
+
+ veccopy(GET_CO(mesh, mesh->curco), v);
+ mesh->curco++;
+}
+
+void dualcon_mesh_add_face(DualConMesh *mesh, int totndx, const int *ndx, int flip)
+{
+ int i;
+
+ assert(mesh->curface < mesh->totface);
+
+ unsigned int *f = GET_FACE(mesh, mesh->curface);
+
+ f[3] = 0;
+ for(i = 0; i < totndx; i++)
+ f[i] = ndx[flip ? (totndx - i - 1) : i];
+ /* TODO: handle quad with last vert zero */
+
+ mesh->curface++;
+}
+
+void dualcon_mesh_add_polygon(DualConMesh *mesh, int totndx, const int *ndx, int flip)
+{
+ if(totndx <= 4) {
+ dualcon_mesh_add_face(mesh, totndx, ndx, flip);
+ }
+ else {
+ /* >4 sides, do a simple triangle fan for now */
+ for(int i = 1; i+1 < totndx; i++) {
+ int v[3] = {ndx[0], ndx[i], ndx[i+1]};
+ dualcon_mesh_add_face(mesh, 3, v, flip);
+ }
+ }
+}
+
+class DualConMeshReader : public ModelReader
+{
+private:
+ const DualConMesh *input_mesh;
+ int tottri, curface, offset;
+ float min[3], max[3], maxsize;
+ float scale;
+public:
+ DualConMeshReader(const DualConMesh *mesh, float _scale)
+ : input_mesh(mesh), scale(_scale)
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ tottri = 0;
+ curface = 0;
+ offset = 0;
+ maxsize = 0;
+
+ /* initialize tottri */
+ for(int i = 0; i < input_mesh->totface; i++)
+ tottri += GET_FACE(input_mesh, i)[3] ? 2 : 1;
+
+ 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(curface == input_mesh->totface)
+ return 0;
+
+ Triangle* t = new Triangle();
+
+ unsigned int *f = GET_FACE(input_mesh, curface);
+ if(offset == 0) {
+ veccopy(t->vt[0], GET_CO(input_mesh, f[0]));
+ veccopy(t->vt[1], GET_CO(input_mesh, f[1]));
+ veccopy(t->vt[2], GET_CO(input_mesh, f[2]));
+ }
+ else {
+ veccopy(t->vt[0], GET_CO(input_mesh, f[2]));
+ veccopy(t->vt[1], GET_CO(input_mesh, f[3]));
+ veccopy(t->vt[2], GET_CO(input_mesh, f[0]));
+ }
+
+ if(offset == 0 && f[3])
+ offset++;
+ else {
+ offset = 0;
+ curface++;
+ }
+
+ return t;
+ }
+
+ int getNextTriangle(int t[3])
+ {
+ if(curface == input_mesh->totface)
+ return 0;
+
+ unsigned int *f = GET_FACE(input_mesh, curface);
+ if(offset == 0) {
+ t[0] = f[0];
+ t[1] = f[1];
+ t[2] = f[2];
+ }
+ else {
+ t[0] = f[2];
+ t[1] = f[3];
+ t[2] = f[0];
+ }
+
+ if(offset == 0 && f[3])
+ offset++;
+ else {
+ offset = 0;
+ curface++;
+ }
+
+ 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])
+ {
+ /* TODO */
+ printf("BAD BAD BAD\n");
+ }
+
+ /* stubs */
+ void printInfo() {}
+ int getMemory() { return sizeof(DualConMeshReader); }
+};
+
+DualConMesh *dualcon(const DualConMesh *input_mesh,
+ DualConCreateMesh create_mesh,
+ DualConFlags flags,
+ DualConMode mode,
+ float threshold,
+ float hermite_num,
+ float scale,
+ int depth)
+{
+ DualConMeshReader r(input_mesh, scale);
+ Octree o(&r, flags, mode, depth, threshold, hermite_num);
+ return o.scanConvert(create_mesh);
+}
diff --git a/intern/dualcon/intern/eigen.cpp b/intern/dualcon/intern/eigen.cpp
new file mode 100644
index 0000000..43388f9
--- /dev/null
+++ b/intern/dualcon/intern/eigen.cpp
@@ -0,0 +1,757 @@
+#include "eigen.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);a[k][l]=h+s*(g-h*tau);
+
+int method = 3;
+
+// for reducing two upper triangular systems of equations into 1
+void qr ( float *mat1, float *mat2, float *rvalue )
+{
+ int i, j;
+ float temp1 [ 8 ] [ 4 ];
+
+ for ( i = 0; i < 4; i++ )
+ {
+ for ( j = 0; j < i; j++ )
+ {
+ temp1 [ i ] [ j ] = 0;
+ temp1 [ i + 4 ] [ j ] = 0;
+ }
+ for ( j = i; j < 4; j++ )
+ {
+ temp1 [ i ] [ j ] = mat1 [ ( 7 * i - i * i ) / 2 + j ];
+ temp1 [ i + 4 ] [ j ] = mat2 [ ( 7 * i - i * i ) / 2 + j ];
+ }
+ }
+
+ qr ( temp1, 8, rvalue );
+}
+
+// WARNING: destroys eqs in the process
+void qr ( float eqs[][4], int num, float *rvalue )
+{
+ int i, j, k;
+
+ qr ( eqs, num, 0.000001f );
+ for ( i = 0; i < 10; i++ )
+ {
+ rvalue [ i ] = 0;
+ }
+
+ k = 0;
+ for ( i = 0; i < num && i < 4; i++ )
+ {
+ for ( j = i; j < 4; j++ )
+ {
+ rvalue [ k++ ] = eqs [ i ] [ j ];
+ }
+ }
+}
+
+void qr ( float eqs[][4], int num, float tol )
+{
+ int i, j, k;
+ float a, b, mag, temp;
+
+ for ( i = 0; i < 4 && i < num; i++ )
+ {
+ for ( j = i + 1; j < num; j++ )
+ {
+ a = eqs [ i ] [ i ];
+ b = eqs [ j ] [ i ];
+
+ if ( fabs ( a ) > 0.000001f || fabs ( b ) > 0.000001f )
+ {
+ mag = (float)sqrt ( a * a + b * b );
+ a /= mag;
+ b /= mag;
+
+ for ( k = 0; k < 4; k++ )
+ {
+ temp = a * eqs [ i ] [ k ] + b * eqs [ j ] [ k ];
+ eqs [ j ] [ k ] = b * eqs [ i ] [ k ] - a * eqs [ j ] [ k ];
+ eqs [ i ] [ k ] = temp;
+ }
+ }
+ }
+ for ( j = i - 1; j >= 0; j-- )
+ {
+ if ( eqs [ j ] [ j ] < 0.000001f && eqs [ j ] [ j ] > -0.000001f )
+ {
+ a = eqs [ i ] [ i ];
+ b = eqs [ j ] [ i ];
+
+ if ( fabs ( a ) > 0.000001f || fabs ( b ) > 0.000001f )
+ {
+ mag = (float)sqrt ( a * a + b * b );
+ a /= mag;
+ b /= mag;
+
+ for ( k = 0; k < 4; k++ )
+ {
+ temp = a * eqs [ i ] [ k ] + b * eqs [ j ] [ k ];
+ eqs [ j ] [ k ] = b * eqs [ i ] [ k ] - a * eqs [ j ] [ k ];
+ eqs [ i ] [ k ] = temp;
+ }
+ }
+ }
+ }
+ }
+
+}
+
+void jacobi ( float u[][3], float d[], float v[][3] )
+{
+ int j, iq, ip, i;
+ float tresh, theta, tau, t, sm, s, h, g, c, b [ 3 ], z [ 3 ];
+ float a [ 3 ] [ 3 ];
+
+ a [ 0 ] [ 0 ] = u [ 0 ] [ 0 ];
+ a [ 0 ] [ 1 ] = u [ 0 ] [ 1 ];
+ a [ 0 ] [ 2 ] = u [ 0 ] [ 2 ];
+ a [ 1 ] [ 0 ] = u [ 1 ] [ 0 ];
+ a [ 1 ] [ 1 ] = u [ 1 ] [ 1 ];
+ a [ 1 ] [ 2 ] = u [ 1 ] [ 2 ];
+ a [ 2 ] [ 0 ] = u [ 2 ] [ 0 ];
+ a [ 2 ] [ 1 ] = u [ 2 ] [ 1 ];
+ a [ 2 ] [ 2 ] = u [ 2 ] [ 2 ];
+
+ for ( ip = 0; ip < 3; ip++ )
+ {
+ for ( iq = 0; iq < 3; iq++ )
+ {
+ v [ ip ] [ iq ] = 0.0f;
+ }
+ v [ ip ] [ ip ] = 1.0f;
+ }
+
+ for ( ip = 0; ip < 3; ip++ )
+ {
+ b [ ip ] = a [ ip ] [ ip ];
+ d [ ip ] = b [ ip ];
+ z [ ip ] = 0.0f;
+ }
+
+ for ( i = 1; i <= 50; i++ )
+ {
+ sm = 0.0f;
+ for ( ip = 0; ip < 2; ip++ )
+ {
+ for ( iq = ip + 1; iq < 3; iq++ )
+ {
+ sm += (float)fabs ( a [ ip ] [ iq ] );
+ }
+ }
+
+ if ( sm == 0.0f )
+ {
+ // sort the stupid things and transpose
+ a [ 0 ] [ 0 ] = v [ 0 ] [ 0 ];
+ a [ 0 ] [ 1 ] = v [ 1 ] [ 0 ];
+ a [ 0 ] [ 2 ] = v [ 2 ] [ 0 ];
+ a [ 1 ] [ 0 ] = v [ 0 ] [ 1 ];
+ a [ 1 ] [ 1 ] = v [ 1 ] [ 1 ];
+ a [ 1 ] [ 2 ] = v [ 2 ] [ 1 ];
+ a [ 2 ] [ 0 ] = v [ 0 ] [ 2 ];
+ a [ 2 ] [ 1 ] = v [ 1 ] [ 2 ];
+ a [ 2 ] [ 2 ] = v [ 2 ] [ 2 ];
+
+ if ( fabs ( d [ 0 ] ) < fabs ( d [ 1 ] ) )
+ {
+ sm = d [ 0 ];
+ d [ 0 ] = d [ 1 ];
+ d [ 1 ] = sm;
+
+ sm = a [ 0 ] [ 0 ];
+ a [ 0 ] [ 0 ] = a [ 1 ] [ 0 ];
+ a [ 1 ] [ 0 ] = sm;
+ sm = a [ 0 ] [ 1 ];
+ a [ 0 ] [ 1 ] = a [ 1 ] [ 1 ];
+ a [ 1 ] [ 1 ] = sm;
+ sm = a [ 0 ] [ 2 ];
+ a [ 0 ] [ 2 ] = a [ 1 ] [ 2 ];
+ a [ 1 ] [ 2 ] = sm;
+ }
+ if ( fabs ( d [ 1 ] ) < fabs ( d [ 2 ] ) )
+ {
+ sm = d [ 1 ];
+ d [ 1 ] = d [ 2 ];
+ d [ 2 ] = sm;
+
+ sm = a [ 1 ] [ 0 ];
+ a [ 1] [ 0 ] = a [ 2 ] [ 0 ];
+ a [ 2 ] [ 0 ] = sm;
+ sm = a [ 1 ] [ 1 ];
+ a [ 1 ] [ 1 ] = a [ 2 ] [ 1 ];
+ a [ 2 ] [ 1 ] = sm;
+ sm = a [ 1 ] [ 2 ];
+ a [ 1 ] [ 2 ] = a [ 2 ] [ 2 ];
+ a [ 2 ] [ 2 ] = sm;
+ }
+ if ( fabs ( d [ 0 ] ) < fabs ( d [ 1 ] ) )
+ {
+ sm = d [ 0 ];
+ d [ 0 ] = d [ 1 ];
+ d [ 1 ] = sm;
+
+ sm = a [ 0 ] [ 0 ];
+ a [ 0 ] [ 0 ] = a [ 1 ] [ 0 ];
+ a [ 1 ] [ 0 ] = sm;
+ sm = a [ 0 ] [ 1 ];
+ a [ 0 ] [ 1 ] = a [ 1 ] [ 1 ];
+ a [ 1 ] [ 1 ] = sm;
+ sm = a [ 0 ] [ 2 ];
+ a [ 0 ] [ 2 ] = a [ 1 ] [ 2 ];
+ a [ 1 ] [ 2 ] = sm;
+ }
+
+ v [ 0 ] [ 0 ] = a [ 0 ] [ 0 ];
+ v [ 0 ] [ 1 ] = a [ 0 ] [ 1 ];
+ v [ 0 ] [ 2 ] = a [ 0 ] [ 2 ];
+ v [ 1 ] [ 0 ] = a [ 1 ] [ 0 ];
+ v [ 1 ] [ 1 ] = a [ 1 ] [ 1 ];
+ v [ 1 ] [ 2 ] = a [ 1 ] [ 2 ];
+ v [ 2 ] [ 0 ] = a [ 2 ] [ 0 ];
+ v [ 2 ] [ 1 ] = a [ 2 ] [ 1 ];
+ v [ 2 ] [ 2 ] = a [ 2 ] [ 2 ];
+
+ return;
+ }
+
+ if ( i < 4 )
+ {
+ tresh = 0.2f * sm / 9;
+ }
+ else
+ {
+ tresh = 0.0f;
+ }
+
+ for ( ip = 0; ip < 2; ip++ )
+ {
+ for ( iq = ip + 1; iq < 3; iq++ )
+ {
+ g = 100.0f * (float)fabs ( a [ ip ] [ iq ] );
+ if ( i > 4 && (float)( fabs ( d [ ip ] ) + g ) == (float)fabs ( d [ ip ] )
+ && (float)( fabs ( d [ iq ] ) + g ) == (float)fabs ( d [ iq ] ) )
+ {
+ a [ ip ] [ iq ] = 0.0f;
+ }
+ else
+ {
+ if ( fabs ( a [ ip ] [ iq ] ) > tresh )
+ {
+ h = d [ iq ] - d [ ip ];
+ if ( (float)( fabs ( h ) + g ) == (float)fabs ( h ) )
+ {
+ t = ( a [ ip ] [ iq ] ) / h;
+ }
+ else
+ {
+ theta = 0.5f * h / ( a [ ip ] [ iq ] );
+ t = 1.0f / ( (float)fabs ( theta ) + (float)sqrt ( 1.0f + theta * theta ) );
+ if ( theta < 0.0f )
+ {
+ t = -1.0f * t;
+ }
+ }
+
+ c = 1.0f / (float)sqrt ( 1 + t * t );
+ s = t * c;
+ tau = s / ( 1.0f + c );
+ h = t * a [ ip ] [ iq ];
+ z [ ip ] -= h;
+ z [ iq ] += h;
+ d [ ip ] -= h;
+ d [ iq ] += h;
+ a [ ip ] [ iq ] = 0.0f;
+ for ( j = 0; j <= ip - 1; j++ )
+ {
+ ROTATE ( a, j, ip, j, iq )
+ }
+ for ( j = ip + 1; j <= iq - 1; j++ )
+ {
+ ROTATE ( a, ip, j, j, iq )
+ }
+ for ( j = iq + 1; j < 3; j++ )
+ {
+ ROTATE ( a, ip, j, iq, j )
+ }
+ for ( j = 0; j < 3; j++ )
+ {
+ ROTATE ( v, j, ip, j, iq )
+ }
+ }
+ }
+ }
+ }
+
+ for ( ip = 0; ip < 3; ip++ )
+ {
+ b [ ip ] += z [ ip ];
+ d [ ip ] = b [ ip ];
+ z [ ip ] = 0.0f;
+ }
+ }
+ printf ( "too many iterations in jacobi\n" );
+ exit ( 1 );
+}
+
+int estimateRank ( float *a )
+{
+ float w [ 3 ];
+ float u [ 3 ] [ 3 ];
+ float mat [ 3 ] [ 3 ];
+ int i;
+
+ mat [ 0 ] [ 0 ] = a [ 0 ];
+ mat [ 0 ] [ 1 ] = a [ 1 ];
+ mat [ 0 ] [ 2 ] = a [ 2 ];
+ mat [ 1 ] [ 1 ] = a [ 3 ];
+ mat [ 1 ] [ 2 ] = a [ 4 ];
+ mat [ 2 ] [ 2 ] = a [ 5 ];
+ mat [ 1 ] [ 0 ] = a [ 1 ];
+ mat [ 2 ] [ 0 ] = a [ 2 ];
+ mat [ 2 ] [ 1 ] = a [ 4 ];
+
+ jacobi ( mat, w, u );
+
+ if ( w [ 0 ] == 0.0f )
+ {
+ return 0;
+ }
+ else
+ {
+ for ( i = 1; i < 3; i++ )
+ {
+ if ( w [ i ] < 0.1f )
+ {
+ return i;
+ }
+ }
+
+ return 3;
+ }
+
+}
+
+void matInverse ( float mat[][3], float midpoint[], float rvalue[][3], float w[], float u[][3] )
+{
+ // there is an implicit assumption that mat is symmetric and real
+ // U and V in the SVD will then be the same matrix whose rows are the eigenvectors of mat
+ // W will just be the eigenvalues of mat
+// float w [ 3 ];
+// float u [ 3 ] [ 3 ];
+ int i;
+
+ jacobi ( mat, w, u );
+
+ if ( w [ 0 ] == 0.0f )
+ {
+// printf ( "error: largest eigenvalue is 0!\n" );
+ }
+ else
+ {
+ for ( i = 1; i < 3; i++ )
+ {
+ if ( w [ i ] < 0.001f ) // / w [ 0 ] < TOLERANCE )
+ {
+ w [ i ] = 0;
+ }
+ else
+ {
+ w [ i ] = 1.0f / w [ i ];
+ }
+ }
+ w [ 0 ] = 1.0f / w [ 0 ];
+ }
+
+ rvalue [ 0 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 0 ] +
+ w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 0 ] +
+ w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 0 ];
+ rvalue [ 0 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 1 ] +
+ w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 1 ] +
+ w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 1 ];
+ rvalue [ 0 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 2 ] +
+ w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 2 ] +
+ w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 2 ];
+ rvalue [ 1 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 0 ] +
+ w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 0 ] +
+ w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 0 ];
+ rvalue [ 1 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 1 ] +
+ w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 1 ] +
+ w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 1 ];
+ rvalue [ 1 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 2 ] +
+ w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 2 ] +
+ w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 2 ];
+ rvalue [ 2 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 0 ] +
+ w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 0 ] +
+ w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 0 ];
+ rvalue [ 2 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 1 ] +
+ w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 1 ] +
+ w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 1 ];
+ rvalue [ 2 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 2 ] +
+ w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 2 ] +
+ w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 2 ];
+}
+
+float calcError ( float a[][3], float b[], float btb, float point[] )
+{
+ float rvalue = btb;
+
+ rvalue += -2.0f * ( point [ 0 ] * b [ 0 ] + point [ 1 ] * b [ 1 ] + point [ 2 ] * b [ 2 ] );
+ rvalue += point [ 0 ] * ( a [ 0 ] [ 0 ] * point [ 0 ] + a [ 0 ] [ 1 ] * point [ 1 ] + a [ 0 ] [ 2 ] * point [ 2 ] );
+ rvalue += point [ 1 ] * ( a [ 1 ] [ 0 ] * point [ 0 ] + a [ 1 ] [ 1 ] * point [ 1 ] + a [ 1 ] [ 2 ] * point [ 2 ] );
+ rvalue += point [ 2 ] * ( a [ 2 ] [ 0 ] * point [ 0 ] + a [ 2 ] [ 1 ] * point [ 1 ] + a [ 2 ] [ 2 ] * point [ 2 ] );
+
+ return rvalue;
+}
+
+float *calcNormal ( float halfA[], float norm[], float expectedNorm[] )
+{
+/*
+ float a [ 3 ] [ 3 ];
+ float w [ 3 ];
+ float u [ 3 ] [ 3 ];
+
+ a [ 0 ] [ 0 ] = halfA [ 0 ];
+ a [ 0 ] [ 1 ] = halfA [ 1 ];
+ a [ 0 ] [ 2 ] = halfA [ 2 ];
+ a [ 1 ] [ 1 ] = halfA [ 3 ];
+ a [ 1 ] [ 2 ] = halfA [ 4 ];
+ a [ 1 ] [ 0 ] = halfA [ 1 ];
+ a [ 2 ] [ 0 ] = halfA [ 2 ];
+ a [ 2 ] [ 1 ] = halfA [ 4 ];
+ a [ 2 ] [ 2 ] = halfA [ 5 ];
+
+ jacobi ( a, w, u );
+
+ if ( u [ 1 ] != 0 )
+ {
+ if ( w [ 1 ] / w [ 0 ] > 0.2f )
+ {
+ // two dominant eigen values, just return the expectedNorm
+ norm [ 0 ] = expectedNorm [ 0 ];
+ norm [ 1 ] = expectedNorm [ 1 ];
+ norm [ 2 ] = expectedNorm [ 2 ];
+ return;
+ }
+ }
+
+ norm [ 0 ] = u [ 0 ] [ 0 ];
+ norm [ 1 ] = u [ 0 ] [ 1 ];
+ norm [ 2 ] = u [ 0 ] [ 2 ];
+*/
+ float dot = norm [ 0 ] * expectedNorm [ 0 ] + norm [ 1 ] * expectedNorm [ 1 ] +
+ norm [ 2 ] * expectedNorm [ 2 ];
+
+ if ( dot < 0 )
+ {
+ norm [ 0 ] *= -1.0f;
+ norm [ 1 ] *= -1.0f;
+ norm [ 2 ] *= -1.0f;
+
+ dot *= -1.0f;
+ }
+
+ if ( dot < 0.707f )
+ {
+ return expectedNorm;
+ }
+ else
+ {
+ return norm;
+ }
+}
+
+void descent ( float A[][3], float B[], float guess[], BoundingBoxf *box )
+{
+ int i;
+ float r [ 3 ];
+ float delta, delta0;
+ int n = 10;
+ float alpha, div;
+ float newPoint [ 3 ];
+ float c;
+ float store [ 3 ];
+
+ store [ 0 ] = guess [ 0 ];
+ store [ 1 ] = guess [ 1 ];
+ store [ 2 ] = guess [ 2 ];
+
+ if ( method == 2 || method == 0 )
+ {
+
+ i = 0;
+ r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] );
+ r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] );
+ r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] );
+
+ delta = r [ 0 ] * r [ 0 ] + r [ 1 ] * r [ 1 ] + r [ 2 ] * r [ 2 ];
+ delta0 = delta * TOLERANCE * TOLERANCE;
+
+ while ( i < n && delta > delta0 )
+ {
+ div = r [ 0 ] * ( A [ 0 ] [ 0 ] * r [ 0 ] + A [ 0 ] [ 1 ] * r [ 1 ] + A [ 0 ] [ 2 ] * r [ 2 ] );
+ div += r [ 1 ] * ( A [ 1 ] [ 0 ] * r [ 0 ] + A [ 1 ] [ 1 ] * r [ 1 ] + A [ 1 ] [ 2 ] * r [ 2 ] );
+ div += r [ 2 ] * ( A [ 2 ] [ 0 ] * r [ 0 ] + A [ 2 ] [ 1 ] * r [ 1 ] + A [ 2 ] [ 2 ] * r [ 2 ] );
+
+ if ( fabs ( div ) < 0.0000001f )
+ {
+ break;
+ }
+
+ alpha = delta / div;
+
+ newPoint [ 0 ] = guess [ 0 ] + alpha * r [ 0 ];
+ newPoint [ 1 ] = guess [ 1 ] + alpha * r [ 1 ];
+ newPoint [ 2 ] = guess [ 2 ] + alpha * r [ 2 ];
+
+ guess [ 0 ] = newPoint [ 0 ];
+ guess [ 1 ] = newPoint [ 1 ];
+ guess [ 2 ] = newPoint [ 2 ];
+
+ r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] );
+ r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] );
+ r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] );
+
+ delta = r [ 0 ] * r [ 0 ] + r [ 1 ] * r [ 1 ] + r [ 2 ] * r [ 2 ];
+
+ i++;
+ }
+
+ if ( guess [ 0 ] >= box->begin.x && guess [ 0 ] <= box->end.x &&
+ guess [ 1 ] >= box->begin.y && guess [ 1 ] <= box->end.y &&
+ guess [ 2 ] >= box->begin.z && guess [ 2 ] <= box->end.z )
+ {
+ return;
+ }
+ }
+
+ if ( method == 0 || method == 1 )
+ {
+ c = A [ 0 ] [ 0 ] + A [ 1 ] [ 1 ] + A [ 2 ] [ 2 ];
+ if ( c == 0 )
+ {
+ return;
+ }
+ c = ( 0.75f / c );
+
+ guess [ 0 ] = store [ 0 ];
+ guess [ 1 ] = store [ 1 ];
+ guess [ 2 ] = store [ 2 ];
+
+ r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] );
+ r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] );
+ r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] );
+
+ for ( i = 0; i < n; i++ )
+ {
+ guess [ 0 ] = guess [ 0 ] + c * r [ 0 ];
+ guess [ 1 ] = guess [ 1 ] + c * r [ 1 ];
+ guess [ 2 ] = guess [ 2 ] + c * r [ 2 ];
+
+ r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] );
+ r [ 1 ] = B [ 1 ] - ( A [ 1 ] [ 0 ] * guess [ 0 ] + A [ 1 ] [ 1 ] * guess [ 1 ] + A [ 1 ] [ 2 ] * guess [ 2 ] );
+ r [ 2 ] = B [ 2 ] - ( A [ 2 ] [ 0 ] * guess [ 0 ] + A [ 2 ] [ 1 ] * guess [ 1 ] + A [ 2 ] [ 2 ] * guess [ 2 ] );
+ }
+ }
+/*
+ if ( guess [ 0 ] > store [ 0 ] + 1 || guess [ 0 ] < store [ 0 ] - 1 ||
+ guess [ 1 ] > store [ 1 ] + 1 || guess [ 1 ] < store [ 1 ] - 1 ||
+ guess [ 2 ] > store [ 2 ] + 1 || guess [ 2 ] < store [ 2 ] - 1 )
+ {
+ printf ( "water let point go from %f,%f,%f to %f,%f,%f\n",
+ store [ 0 ], store [ 1 ], store [ 2 ], guess [ 0 ], guess [ 1 ], guess [ 2 ] );
+ printf ( "A is %f,%f,%f %f,%f,%f %f,%f,%f\n", A [ 0 ] [ 0 ], A [ 0 ] [ 1 ], A [ 0 ] [ 2 ],
+ A [ 1 ] [ 0 ] , A [ 1 ] [ 1 ], A [ 1 ] [ 2 ], A [ 2 ] [ 0 ], A [ 2 ] [ 1 ], A [ 2 ] [ 2 ] );
+ printf ( "B is %f,%f,%f\n", B [ 0 ], B [ 1 ], B [ 2 ] );
+ printf ( "bounding box is %f,%f,%f to %f,%f,%f\n",
+ box->begin.x, box->begin.y, box->begin.z, box->end.x, box->end.y, box->end.z );
+ }
+*/
+}
+
+float calcPoint ( float halfA[], float b[], float btb, float midpoint[], float rvalue[], BoundingBoxf *box, float *mat )
+{
+ float newB [ 3 ];
+ float a [ 3 ] [ 3 ];
+ float inv [ 3 ] [ 3 ];
+ float w [ 3 ];
+ float u [ 3 ] [ 3 ];
+
+ a [ 0 ] [ 0 ] = halfA [ 0 ];
+ a [ 0 ] [ 1 ] = halfA [ 1 ];
+ a [ 0 ] [ 2 ] = halfA [ 2 ];
+ a [ 1 ] [ 1 ] = halfA [ 3 ];
+ a [ 1 ] [ 2 ] = halfA [ 4 ];
+ a [ 1 ] [ 0 ] = halfA [ 1 ];
+ a [ 2 ] [ 0 ] = halfA [ 2 ];
+ a [ 2 ] [ 1 ] = halfA [ 4 ];
+ a [ 2 ] [ 2 ] = halfA [ 5 ];
+
+ switch ( method )
+ {
+ case 0:
+ case 1:
+ case 2:
+ rvalue [ 0 ] = midpoint [ 0 ];
+ rvalue [ 1 ] = midpoint [ 1 ];
+ rvalue [ 2 ] = midpoint [ 2 ];
+
+ descent ( a, b, rvalue, box );
+ return calcError ( a, b, btb, rvalue );
+ break;
+ case 3:
+ matInverse ( a, midpoint, inv, w, u );
+
+
+ newB [ 0 ] = b [ 0 ] - a [ 0 ] [ 0 ] * midpoint [ 0 ] - a [ 0 ] [ 1 ] * midpoint [ 1 ] - a [ 0 ] [ 2 ] * midpoint [ 2 ];
+ newB [ 1 ] = b [ 1 ] - a [ 1 ] [ 0 ] * midpoint [ 0 ] - a [ 1 ] [ 1 ] * midpoint [ 1 ] - a [ 1 ] [ 2 ] * midpoint [ 2 ];
+ newB [ 2 ] = b [ 2 ] - a [ 2 ] [ 0 ] * midpoint [ 0 ] - a [ 2 ] [ 1 ] * midpoint [ 1 ] - a [ 2 ] [ 2 ] * midpoint [ 2 ];
+
+ rvalue [ 0 ] = inv [ 0 ] [ 0 ] * newB [ 0 ] + inv [ 1 ] [ 0 ] * newB [ 1 ] + inv [ 2 ] [ 0 ] * newB [ 2 ] + midpoint [ 0 ];
+ rvalue [ 1 ] = inv [ 0 ] [ 1 ] * newB [ 0 ] + inv [ 1 ] [ 1 ] * newB [ 1 ] + inv [ 2 ] [ 1 ] * newB [ 2 ] + midpoint [ 1 ];
+ rvalue [ 2 ] = inv [ 0 ] [ 2 ] * newB [ 0 ] + inv [ 1 ] [ 2 ] * newB [ 1 ] + inv [ 2 ] [ 2 ] * newB [ 2 ] + midpoint [ 2 ];
+ return calcError ( a, b, btb, rvalue );
+ break;
+ case 4:
+ method = 3;
+ calcPoint ( halfA, b, btb, midpoint, rvalue, box, mat );
+ method = 4;
+/*
+ int rank;
+ float eqs [ 4 ] [ 4 ];
+
+ // form the square matrix
+ eqs [ 0 ] [ 0 ] = mat [ 0 ];
+ eqs [ 0 ] [ 1 ] = mat [ 1 ];
+ eqs [ 0 ] [ 2 ] = mat [ 2 ];
+ eqs [ 0 ] [ 3 ] = mat [ 3 ];
+ eqs [ 1 ] [ 1 ] = mat [ 4 ];
+ eqs [ 1 ] [ 2 ] = mat [ 5 ];
+ eqs [ 1 ] [ 3 ] = mat [ 6 ];
+ eqs [ 2 ] [ 2 ] = mat [ 7 ];
+ eqs [ 2 ] [ 3 ] = mat [ 8 ];
+ eqs [ 3 ] [ 3 ] = mat [ 9 ];
+ eqs [ 1 ] [ 0 ] = eqs [ 2 ] [ 0 ] = eqs [ 2 ] [ 1 ] = eqs [ 3 ] [ 0 ] = eqs [ 3 ] [ 1 ] = eqs [ 3 ] [ 2 ] = 0;
+
+ // compute the new QR decomposition and rank
+ rank = qr ( eqs );
+
+ method = 2;
+ calcPoint ( halfA, b, btb, midpoint, rvalue, box, mat );
+ method = 4;
+
+ if ( rank == 0 )
+ {
+ // it's zero, no equations
+ rvalue [ 0 ] = midpoint [ 0 ];
+ rvalue [ 1 ] = midpoint [ 1 ];
+ rvalue [ 2 ] = midpoint [ 2 ];
+ }
+ else
+ {
+ if ( rank == 1 )
+ {
+ // one equation, it's a plane
+ float temp = ( eqs [ 0 ] [ 0 ] * midpoint [ 0 ] + eqs [ 0 ] [ 1 ] * midpoint [ 1 ] + eqs [ 0 ] [ 2 ] * midpoint [ 2 ] - eqs [ 0 ] [ 3 ] ) /
+ ( eqs [ 0 ] [ 0 ] * eqs [ 0 ] [ 0 ] + eqs [ 0 ] [ 1 ] * eqs [ 0 ] [ 1 ] + eqs [ 0 ] [ 2 ] * eqs [ 0 ] [ 2 ] );
+
+ rvalue [ 0 ] = midpoint [ 0 ] - temp * eqs [ 0 ] [ 0 ];
+ rvalue [ 1 ] = midpoint [ 1 ] - temp * eqs [ 0 ] [ 1 ];
+ rvalue [ 2 ] = midpoint [ 2 ] - temp * eqs [ 0 ] [ 2 ];
+ }
+ else
+ {
+ if ( rank == 2 )
+ {
+ // two equations, it's a line
+ float a, b, c, d, e, f, g;
+
+ // reduce back to upper triangular
+ qr ( eqs, 2, 0.000001f );
+
+ a = eqs [ 0 ] [ 0 ];
+ b = eqs [ 0 ] [ 1 ];
+ c = eqs [ 0 ] [ 2 ];
+ d = eqs [ 0 ] [ 3 ];
+ e = eqs [ 1 ] [ 1 ];
+ f = eqs [ 1 ] [ 2 ];
+ g = eqs [ 1 ] [ 3 ];
+
+ // solved using the equations
+ // ax + by + cz = d
+ // ey + fz = g
+ // minimize (x-px)^2 + (y-py)^2 + (z-pz)^2
+ if ( a > 0.000001f || a < -0.000001f )
+ {
+ if ( e > 0.00000f || e < -0.000001f )
+ {
+ rvalue [ 2 ] = ( -1 * b * d * e * f + ( a * a + b * b ) * g * f + c * e * ( d * e - b * g ) +
+ a * e * ( ( b * f - c * e ) * midpoint [ 0 ] - a * f * midpoint [ 1 ] + a * e * midpoint [ 2 ] ) ) /
+ ( a * a * ( e * e + f * f ) + ( c * e - b * f ) * ( c * e - b * f ) );
+ rvalue [ 1 ] = ( g - f * rvalue [ 2 ] ) / e;
+ rvalue [ 0 ] = ( d - b * rvalue [ 1 ] - c * rvalue [ 2 ] ) / a;
+ }
+ else
+ {
+ // slightly degenerate case where e==0
+ rvalue [ 2 ] = g / f;
+ rvalue [ 1 ] = ( b * d * f - b * c * g - a * b * f * midpoint [ 0 ] + a * a * f * midpoint [ 1 ] ) /
+ ( a * a * f + b * b * f );
+ rvalue [ 0 ] = ( d - b * rvalue [ 1 ] - c * rvalue [ 2 ] ) / a;
+ }
+ }
+ else
+ {
+ // degenerate case where a==0 so e == 0 (upper triangular)
+
+ rvalue [ 2 ] = g / f;
+ rvalue [ 1 ] = ( d - c * rvalue [ 2 ] ) / b;
+ rvalue [ 0 ] = midpoint [ 0 ];
+ }
+
+ }
+ else
+ {
+ // must be three equations or more now... solve using back-substitution
+ rvalue [ 2 ] = mat [ 8 ] / mat [ 7 ];
+ rvalue [ 1 ] = ( mat [ 6 ] - mat [ 5 ] * rvalue [ 2 ] ) / mat [ 4 ];
+ rvalue [ 0 ] = ( mat [ 3 ] - mat [ 2 ] * rvalue [ 2 ] - mat [ 1 ] * rvalue [ 1 ] ) / mat [ 0 ];
+ }
+ }
+ }
+*/
+
+ float ret;
+ float tmp;
+
+ ret = mat [ 9 ] * mat [ 9 ];
+
+ tmp = mat [ 0 ] * rvalue [ 0 ] + mat [ 1 ] * rvalue [ 1 ] + mat [ 2 ] * rvalue [ 2 ] - mat [ 3 ];
+ ret += tmp * tmp;
+
+ tmp = mat [ 4 ] * rvalue [ 1 ] + mat [ 5 ] * rvalue [ 2 ] - mat [ 6 ];
+ ret += tmp * tmp;
+
+ tmp = mat [ 7 ] * rvalue [ 2 ] - mat [ 8 ];
+ ret += tmp * tmp;
+
+ return ret;
+
+ break;
+ case 5:
+ rvalue [ 0 ] = midpoint [ 0 ];
+ rvalue [ 1 ] = midpoint [ 1 ];
+ rvalue [ 2 ] = midpoint [ 2 ];
+
+ return calcError ( a, b, btb, rvalue );
+ }
+
+ return 0 ;
+}
diff --git a/intern/dualcon/intern/eigen.h b/intern/dualcon/intern/eigen.h
new file mode 100644
index 0000000..53871bd
--- /dev/null
+++ b/intern/dualcon/intern/eigen.h
@@ -0,0 +1,80 @@
+#ifndef EIGEN_H
+#define EIGEN_H
+
+#define TOLERANCE 0.0001f
+
+#include "GeoCommon.h"
+
+/**
+ * Numerical functions for computing minimizers of a least-squares system
+ * of equations.
+ *
+ * @author Scott Schaefer
+ */
+
+
+/**
+ * Uses a jacobi method to return the eigenvectors and eigenvalues
+ * of a 3x3 symmetric matrix. Note: "a" will be destroyed in this
+ * process. "d" will contain the eigenvalues sorted in order of
+ * decreasing modulus and v will contain the corresponding eigenvectors.
+ *
+ * @param a the 3x3 symmetric matrix to calculate the eigensystem for
+ * @param d the variable to hold the eigenvalues
+ * @param v the variables to hold the eigenvectors
+ */
+void jacobi ( float a[][3], float d[], float v[][3] );
+
+/**
+ * Inverts a 3x3 symmetric matrix by computing the pseudo-inverse.
+ *
+ * @param mat the matrix to invert
+ * @param midpoint the point to minimize towards
+ * @param rvalue the variable to store the pseudo-inverse in
+ * @param w the place to store the inverse of the eigenvalues
+ * @param u the place to store the eigenvectors
+ */
+void matInverse ( float mat[][3], float midpoint[], float rvalue[][3], float w[], float u[][3] );
+
+/**
+ * Calculates the L2 norm of the residual (the error)
+ * (Transpose[A].A).x = Transpose[A].B
+ *
+ * @param a the matrix Transpose[A].A
+ * @param b the matrix Transpose[A].B
+ * @param btb the value Transpose[B].B
+ * @param point the minimizer found
+ *
+ * @return the error of the minimizer
+ */
+float calcError ( float a[][3], float b[], float btb, float point[] );
+
+/**
+ * Calculates the normal. This function is not called and doesn't do
+ * anything right now. It was originally meant to orient the normals
+ * correctly that came from the principle eigenvector, but we're flat
+ * shading now.
+ */
+float *calcNormal ( float halfA[], float norm[], float expectedNorm[] );
+
+/**
+ * Calculates the minimizer of the given system and returns its error.
+ *
+ * @param halfA the compressed form of the symmetric matrix Transpose[A].A
+ * @param b the matrix Transpose[A].B
+ * @param btb the value Transpose[B].B
+ * @param midpoint the point to minimize towards
+ * @param rvalue the place to store the minimizer
+ * @param box the volume bounding the voxel this QEF is for
+ *
+ * @return the error of the minimizer
+ */
+float calcPoint ( float halfA[], float b[], float btb, float midpoint[], float rvalue[], BoundingBoxf *box, float *mat );
+
+void qr ( float eqs[][4], int num, float *rvalue );
+void qr ( float *mat1, float *mat2, float *rvalue );
+void qr ( float eqs[][4], int num = 4, float tol = 0.000001f );
+
+int estimateRank ( float *a );
+
+#endif
\ No newline at end of file
diff --git a/intern/dualcon/intern/manifold_table.cpp b/intern/dualcon/intern/manifold_table.cpp
new file mode 100644
index 0000000..aaa89fa
--- /dev/null
+++ b/intern/dualcon/intern/manifold_table.cpp
@@ -0,0 +1,260 @@
+#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}}}
+};
diff --git a/intern/dualcon/intern/manifold_table.h b/intern/dualcon/intern/manifold_table.h
new file mode 100644
index 0000000..0837e9c
--- /dev/null
+++ b/intern/dualcon/intern/manifold_table.h
@@ -0,0 +1,11 @@
+#ifndef MANIFOLD_TABLE_H
+#define MANIFOLD_TABLE_H
+
+typedef struct {
+ int comps;
+ int pairs[12][2];
+} ManifoldIndices;
+
+extern const ManifoldIndices manifold_table[256];
+
+#endif
diff --git a/intern/dualcon/intern/marching_cubes_table.cpp b/intern/dualcon/intern/marching_cubes_table.cpp
new file mode 100644
index 0000000..1f5e99f
--- /dev/null
+++ b/intern/dualcon/intern/marching_cubes_table.cpp
@@ -0,0 +1,532 @@
+#include "marching_cubes_table.h"
+
+/* 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
+};
+
+/* 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}}
+};
diff --git a/intern/dualcon/intern/marching_cubes_table.h b/intern/dualcon/intern/marching_cubes_table.h
new file mode 100644
index 0000000..42f8a35
--- /dev/null
+++ b/intern/dualcon/intern/marching_cubes_table.h
@@ -0,0 +1,16 @@
+#ifndef MARCHING_CUBES_TABLE_H
+#define MARCHING_CUBES_TABLE_H
+
+/* number of configurations */
+#define TOTCONF 256
+
+/* maximum number of triangles per configuration */
+#define MAX_TRIS 10
+
+/* number of triangles in each configuration */
+extern const int marching_cubes_numtri[TOTCONF];
+
+/* table of triangles in each configuration */
+extern const int marching_cubes_tris[TOTCONF][MAX_TRIS][3];
+
+#endif
diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp
new file mode 100644
index 0000000..c1b063b
--- /dev/null
+++ b/intern/dualcon/intern/octree.cpp
@@ -0,0 +1,4094 @@
+#include "octree.h"
+
+#include <time.h>
+
+/**
+ * Implementations of Octree member functions.
+ *
+ * @author Tao Ju
+ */
+
+
+Octree::Octree( ModelReader* mr, DualConFlags flags, DualConMode _mode, int depth, float threshold, float _hermite_num )
+ : use_flood_fill(flags & DUALCON_FLOOD_FILL),
+ use_manifold(flags & DUALCON_MANIFOLD),
+ hermite_num(_hermite_num),
+ mode(_mode)
+{
+ this->thresh = threshold ;
+ this->reader = mr ;
+ this->dimen = 1 << GRID_DIMENSION ;
+ this->range = reader->getBoundingBox( this->origin ) ;
+ this->nodeCount = this->nodeSpace = 0;
+ this->maxDepth = depth ;
+ this->mindimen = ( dimen >> maxDepth ) ;
+ this->minshift = ( GRID_DIMENSION - maxDepth ) ;
+ this->buildTable( ) ;
+
+ flood_bytes = use_flood_fill ? FLOOD_FILL_BYTES : 0;
+ leaf_extra_bytes = flood_bytes + CINDY_BYTES;
+
+#ifdef USE_HERMIT
+ leaf_node_bytes = 7 + leaf_extra_bytes;
+#else
+ leaf_node_bytes = 3 + leaf_extra_bytes;
+#endif
+
+#ifdef QIANYI
+ printf("Origin: (%f %f %f), Dimension: %f\n", origin[0], origin[1], origin[2], range) ;
+#endif
+
+ this->maxTrianglePerCell = 0 ;
+
+ // Initialize memory
+#ifdef IN_VERBOSE_MODE
+ printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2] ) ;
+ printf("Initialize memory...\n") ;
+#endif
+ initMemory( ) ;
+ this->root = createInternal( 0 ) ;
+
+ // Read MC table
+#ifdef IN_VERBOSE_MODE
+ printf("Reading contour table...\n") ;
+#endif
+ this->cubes = new Cubes();
+
+}
+
+Octree::~Octree( )
+{
+ freeMemory( ) ;
+}
+
+DualConMesh *Octree::scanConvert(DualConCreateMesh create_mesh)
+{
+ // Scan triangles
+ clock_t start, finish ;
+ start = clock( ) ;
+
+ this->addTrian( ) ;
+ this->resetMinimalEdges( ) ;
+ this->preparePrimalEdgesMask( this->root ) ;
+
+ finish = clock( ) ;
+ printf("Time taken: %f seconds \n",
+ (double)(finish - start) / CLOCKS_PER_SEC ) ;
+
+ // Generate signs
+ // Find holes
+ printf("Patching...\n") ;
+ start = clock( ) ;
+ this->trace( ) ;
+ finish = clock( ) ;
+ printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ;
+#ifdef IN_VERBOSE_MODE
+ printf("Holes: %d Average Length: %f Max Length: %d \n", numRings, (float)totRingLengths / (float) numRings, maxRingLength ) ;
+#endif
+ // Check again
+ int tnumRings = numRings ;
+ this->trace( ) ;
+#ifdef IN_VERBOSE_MODE
+ printf("Holes after patching: %d \n", numRings) ;
+#endif
+ numRings = tnumRings ;
+
+ printf("Building signs...\n") ;
+ start = clock( ) ;
+ this->buildSigns( ) ;
+ finish = clock( ) ;
+ printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ;
+
+ if(use_flood_fill) {
+ /*
+ start = clock( ) ;
+ this->floodFill( ) ;
+ // Check again
+ tnumRings = numRings ;
+ this->trace( ) ;
+ printf("Holes after filling: %d \n", numRings) ;
+ numRings = tnumRings ;
+ this->buildSigns( ) ;
+ finish = clock( ) ;
+ printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ;
+ */
+ start = clock( ) ;
+ printf("Removing components...\n");
+ this->floodFill( ) ;
+ this->buildSigns( ) ;
+ // printf("Checking...\n");
+ // this->floodFill( ) ;
+ finish = clock( ) ;
+ printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ;
+ }
+
+ // Output
+#ifdef OUTPUT_REPAIRED
+ start = clock( ) ;
+ DualConMesh *output_mesh = writeOut(create_mesh);
+ finish = clock( ) ;
+ // printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ;
+#ifdef CINDY
+ this->writeTags( "tags.txt" ) ;
+ printf("Tags output to tags.txt\n") ;
+#endif
+
+#endif
+
+ // Print info
+#ifdef IN_VERBOSE_MODE
+ printMemUsage( ) ;
+#endif
+
+ return output_mesh;
+}
+
+#if 0
+void Octree::writeOut( char* fname )
+{
+ printf( "\n" ) ;
+ if ( strstr( fname, ".ply" ) != NULL )
+ {
+ printf("Writing PLY file format.\n") ;
+ this->outType = 1 ;
+ writePLY( fname ) ;
+ }
+ else if ( strstr( fname, ".off" ) != NULL )
+ {
+ printf("Writing OFF file format.\n") ;
+ this->outType = 0 ;
+ writeOFF( fname ) ;
+ }
+ else if ( strstr( fname, ".sof" ) != NULL )
+ {
+ printf("Writing Signed Octree File format.\n") ;
+ this->outType = 2 ;
+ writeOctree( fname ) ;
+ }
+ else if ( strstr( fname, ".dcf" ) != NULL )
+ {
+#ifdef USE_HERMIT
+ printf("Writing Dual Contouring File format.\n") ;
+ this->outType = 3 ;
+ writeDCF( fname ) ;
+#else
+ printf("Can not write Dual Contouring File format in non-DC mode.\n") ;
+#endif
+ }
+#ifdef USE_HERMIT
+ else if ( strstr( fname, ".sog" ) != NULL )
+ {
+ printf("Writing signed octree with geometry.\n") ;
+ this->outType = 4 ;
+ writeOctreeGeom( fname ) ;
+ }
+#endif
+ /*
+ else if ( strstr( fname, ".sof" ) != NULL )
+ {
+ printf("Writing SOF file format.\n") ;
+ this->outType = 2 ;
+ writeOctree( fname ) ;
+ }
+ */
+ else
+ {
+ printf("Unknown output format.\n") ;
+ }
+
+}
+#endif
+
+void Octree::initMemory( )
+{
+#ifdef USE_HERMIT
+ const int leaf_node_bytes = 7;
+#else
+ const int leaf_node_bytes = 3;
+#endif
+
+ if(use_flood_fill) {
+ const int bytes = leaf_node_bytes + CINDY_BYTES + FLOOD_FILL_BYTES;
+ this->leafalloc[ 0 ] = new MemoryAllocator< bytes > ( ) ;
+ this->leafalloc[ 1 ] = new MemoryAllocator< bytes + EDGE_BYTES > ( ) ;
+ this->leafalloc[ 2 ] = new MemoryAllocator< bytes + EDGE_BYTES * 2 > ( ) ;
+ this->leafalloc[ 3 ] = new MemoryAllocator< bytes + EDGE_BYTES * 3 > ( ) ;
+ }
+ else {
+ const int bytes = leaf_node_bytes + CINDY_BYTES;
+ this->leafalloc[ 0 ] = new MemoryAllocator< bytes > ( ) ;
+ this->leafalloc[ 1 ] = new MemoryAllocator< bytes + EDGE_BYTES > ( ) ;
+ this->leafalloc[ 2 ] = new MemoryAllocator< bytes + EDGE_BYTES * 2 > ( ) ;
+ this->leafalloc[ 3 ] = new MemoryAllocator< bytes + EDGE_BYTES * 3 > ( ) ;
+ }
+
+ this->alloc[ 0 ] = new MemoryAllocator< INTERNAL_NODE_BYTES > ( ) ;
+ this->alloc[ 1 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES > ( ) ;
+ this->alloc[ 2 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*2 > ( ) ;
+ this->alloc[ 3 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*3 > ( ) ;
+ this->alloc[ 4 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*4 > ( ) ;
+ this->alloc[ 5 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*5 > ( ) ;
+ this->alloc[ 6 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*6 > ( ) ;
+ this->alloc[ 7 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*7 > ( ) ;
+ this->alloc[ 8 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*8 > ( ) ;
+}
+
+void Octree::freeMemory( )
+{
+ for ( int i = 0 ; i < 9 ; i ++ )
+ {
+ alloc[i]->destroy() ;
+ delete alloc[i] ;
+ }
+
+ for ( int i = 0 ; i < 4 ; i ++ )
+ {
+ leafalloc[i]->destroy() ;
+ delete leafalloc[i] ;
+ }
+}
+
+void Octree::printMemUsage( )
+{
+ int totalbytes = 0 ;
+ printf("********* Internal nodes: \n") ;
+ for ( int i = 0 ; i < 9 ; i ++ )
+ {
+ this->alloc[ i ]->printInfo() ;
+
+ totalbytes += alloc[i]->getAll( ) * alloc[i]->getBytes() ;
+ }
+ printf("********* Leaf nodes: \n") ;
+ int totalLeafs = 0 ;
+ for ( int i = 0 ; i < 4 ; i ++ )
+ {
+ this->leafalloc[ i ]->printInfo() ;
+
+ totalbytes += leafalloc[i]->getAll( ) * leafalloc[i]->getBytes() ;
+ totalLeafs += leafalloc[i]->getAllocated() ;
+ }
+
+ printf("Total allocated bytes on disk: %d \n", totalbytes) ;
+ printf("Total leaf nodes: %d\n", totalLeafs ) ;
+}
+
+void Octree::resetMinimalEdges( )
+{
+ this->cellProcParity( this->root, 0, maxDepth ) ;
+}
+
+void Octree::writeModel( char* fname )
+{
+ reader->reset() ;
+
+ int nFace = reader->getNumTriangles() ;
+ Triangle* trian ;
+ // int unitcount = 10000;
+ int count = 0 ;
+ int nVert = nFace * 3 ;
+ FILE* modelfout = fopen( "model.off", "w" ) ;
+ fprintf( modelfout, "OFF\n" ) ;
+ fprintf( modelfout, "%d %d 0\n", nVert, nFace ) ;
+
+ //int total = this->reader->getNumTriangles() ;
+ printf( "Start writing model to OFF...\n" ) ;
+ srand(0) ;
+ while ( ( trian = reader->getNextTriangle() ) != NULL )
+ {
+ // Drop polygons
+ {
+ int i, j ;
+
+ // Blow up the triangle
+ float mid[3] = {0, 0, 0} ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trian->vt[i][j] = dimen * ( trian->vt[i][j] - origin[j] ) / range ;
+
+ mid[j] += trian->vt[i][j] / 3 ;
+ }
+
+ // Generate projections
+ // LONG cube[2][3] = { { 0, 0, 0 }, { dimen, dimen, dimen } } ;
+ int trig[3][3] ;
+
+ // Blowing up the triangle to the grid
+ for ( i = 0 ; i < 3 ; i ++ )
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trig[i][j] = (int) (trian->vt[i][j]) ;
+ // Perturb end points, if set so
+ }
+
+
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ fprintf( modelfout, "%f %f %f\n",
+ (float)(((double) trig[i][0] / dimen) * range + origin[0]) ,
+ (float)(((double) trig[i][1] / dimen) * range + origin[1]) ,
+ (float)(((double) trig[i][2] / dimen) * range + origin[2]) ) ;
+ }
+ }
+ delete trian ;
+
+ count ++ ;
+
+ }
+
+ for ( int i = 0 ; i < nFace ; i ++ )
+ {
+ fprintf( modelfout, "3 %d %d %d\n", 3 * i + 2, 3 * i + 1, 3 * i ) ;
+ }
+
+ fclose( modelfout ) ;
+
+}
+
+#ifdef CINDY
+void Octree::writeTags( char* fname )
+{
+ FILE* fout = fopen( fname, "w" ) ;
+
+ clearCindyBits( root, maxDepth ) ;
+ readVertices() ;
+ outputTags( root, maxDepth, fout ) ;
+
+ fclose ( fout ) ;
+}
+
+void Octree::readVertices( )
+{
+ int total = this->reader->getNumVertices() ;
+ reader->reset() ;
+ float v[3] ;
+ int st[3] = {0,0,0};
+ int unitcount = 1000 ;
+ printf( "\nRead in original %d vertices...\n", total ) ;
+
+ for ( int i = 0 ; i < total ; i ++ )
+ {
+ reader->getNextVertex( v ) ;
+ // Blowing up the triangle to the grid
+ float mid[3] = {0, 0, 0} ;
+ for ( int j = 0 ; j < 3 ; j ++ )
+ {
+ v[j] = dimen * ( v[j] - origin[j] ) / range ;
+ }
+
+// printf("vertex: %f %f %f, dimen: %d\n", v[0], v[1], v[2], dimen ) ;
+ readVertex ( root, st, dimen, maxDepth, v, i ) ;
+
+
+ if ( i % unitcount == 0 )
+ {
+ putchar ( 13 ) ;
+
+ switch ( ( i / unitcount ) % 4 )
+ {
+ case 0 : printf("-");
+ break ;
+ case 1 : printf("/") ;
+ break ;
+ case 2 : printf("|");
+ break ;
+ case 3 : printf("\\") ;
+ break ;
+ }
+
+ float percent = (float) i / 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 ) ;
+ }
+ */
+
+ printf(" %d vertices: ", i ) ;
+ printf( " %f%% complete.", 100 * percent ) ;
+ }
+
+ }
+ putchar ( 13 ) ;
+ printf(" \n");
+}
+
+void Octree::readVertex( UCHAR* node, int st[3], int len, int height, float v[3], int index )
+{
+ int nst[3] ;
+ nst[0] = ( (int) v[0] / mindimen ) * mindimen ;
+ nst[1] = ( (int) v[1] / mindimen ) * mindimen ;
+ nst[2] = ( (int) v[2] / mindimen ) * mindimen ;
+
+ UCHAR* cell = this->locateLeafCheck( nst ) ;
+ if ( cell == NULL )
+ {
+ printf("Cell %d %d %d is not found!\n", nst[0]/ mindimen, nst[1]/ mindimen, nst[2]/ mindimen) ;
+ return ;
+ }
+
+ setOriginalIndex( cell, index ) ;
+
+
+ /*
+ int i ;
+ if ( height == 0 )
+ {
+ // Leaf cell, assign index
+ printf("Setting: %d\n", index ) ;
+ setOriginalIndex( node, index ) ;
+ }
+ else
+ {
+ len >>= 1 ;
+ // Internal cell, check and recur
+ int x = ( v[0] > st[0] + len ) ? 1 : 0 ;
+ int y = ( v[1] > st[1] + len ) ? 1 : 0 ;
+ int z = ( v[2] > st[2] + len ) ? 1 : 0 ;
+ int child = x * 4 + y * 2 + z ;
+
+ int count = 0 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( i == child && hasChild( node, 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 ;
+
+ printf("Depth: %d -- child %d vertex: %f %f %f in %f %f %f\n", height - 1, child, v[0]/mindimen, v[1]/mindimen, v[2]/mindimen,
+ nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, len/mindimen ) ;
+
+ readVertex( getChild( node, count ), nst, len, height - 1, v, index ) ;
+ count ++ ;
+ }
+ }
+ }
+ */
+}
+
+void Octree::outputTags( UCHAR* node, int height, FILE* fout )
+{
+ int i ;
+
+ if ( height == 0 )
+ {
+ // Leaf cell, generate
+ int smask = getSignMask( node ) ;
+
+ if(use_manifold) {
+ int comps = manifold_table[ smask ].comps ;
+ if ( comps != 1 )
+ {
+ return ;
+ }
+ }
+ else
+ {
+ if ( smask == 0 || smask == 255 )
+ {
+ return ;
+ }
+ }
+
+ int rindex = getMinimizerIndex( node ) ;
+ int oindex = getOriginalIndex( node ) ;
+
+ if ( oindex >= 0 )
+ {
+ fprintf( fout, "%d: %d\n", rindex, oindex ) ;
+ }
+
+ }
+ else
+ {
+ // Internal cell, recur
+ int count = 0 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, i ) )
+ {
+ outputTags( getChild( node, count ), height - 1, fout ) ;
+ count ++ ;
+ }
+ }
+ }
+}
+
+void Octree::clearCindyBits( UCHAR* node, int height )
+{
+ int i;
+
+ if ( height == 0 )
+ {
+ // Leaf cell,
+ {
+ setOriginalIndex( node, - 1 ) ;
+ }
+ }
+ else
+ {
+ // Internal cell, recur
+ int count = 0 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, i ) )
+ {
+ clearCindyBits( getChild( node, count ), height - 1 ) ;
+ count ++ ;
+ }
+ }
+ }
+}
+#endif
+
+void Octree::addTrian( )
+{
+ int total = this->reader->getNumTriangles() ;
+ Triangle* trian ;
+ int unitcount = 1000, count = 0 ;
+ printf( "\nScan converting to depth %d...\n", maxDepth ) ;
+
+ srand(0) ;
+
+ while ( ( trian = reader->getNextTriangle() ) != NULL )
+ {
+ // Drop triangles
+ {
+ addTrian ( trian, count ) ;
+ }
+ delete trian ;
+
+ count ++ ;
+
+ if ( count % unitcount == 0 )
+ {
+ putchar ( 13 ) ;
+
+ switch ( ( count / unitcount ) % 4 )
+ {
+ case 0 : printf("-");
+ break ;
+ case 1 : printf("/") ;
+ break ;
+ case 2 : printf("|");
+ break ;
+ case 3 : 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 ) ;
+ }
+ */
+
+ printf(" %d triangles: ", count ) ;
+ printf( " %f%% complete.", 100 * percent ) ;
+ }
+
+ }
+ putchar ( 13 ) ;
+}
+
+void Octree::addTrian( Triangle* trian, int triind )
+{
+ int i, j ;
+
+ // Blowing up the triangle to the grid
+ float mid[3] = {0, 0, 0} ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trian->vt[i][j] = dimen * ( trian->vt[i][j] - origin[j] ) / range ;
+ mid[j] += trian->vt[i][j] / 3 ;
+ }
+
+ // Generate projections
+ LONG cube[2][3] = { { 0, 0, 0 }, { dimen, dimen, dimen } } ;
+ LONG trig[3][3] ;
+
+ for ( i = 0 ; i < 3 ; i ++ )
+ for ( j = 0 ; j < 3 ; j ++ )
+ {
+ trig[i][j] = (LONG) (trian->vt[i][j]) ;
+ // Perturb end points, if set so
+ }
+
+ // Add to the octree
+ // int start[3] = { 0, 0, 0 } ;
+ LONG errorvec = (LONG) ( 0 ) ;
+ Projections* proj = new Projections( cube, trig, errorvec, triind ) ;
+ root = addTrian( root, proj, maxDepth ) ;
+
+ delete proj->inherit ;
+ delete proj ;
+}
+
+
+UCHAR* Octree::addTrian( UCHAR* node, Projections* p, int height )
+{
+ int i ;
+ 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}} ;
+ UCHAR boxmask = p->getBoxMask( ) ;
+ Projections* subp = new Projections( p ) ;
+
+ int count = 0 ;
+ int tempdiff[3] = {0,0,0} ;
+ 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 ( subp->getIntersectionMasks( cedgemask, edgemask ) )
+ {
+ if ( ! hasChild( node, i ) )
+ {
+ if ( height == 1 )
+ {
+ node = addLeafChild( node, i, count, createLeaf(0) ) ;
+ }
+ else
+ {
+ node = addInternalChild( node, i, count, createInternal(0) ) ;
+ }
+ }
+ UCHAR* chd = getChild( node, count ) ;
+
+ if ( ! isLeaf( node, i ) )
+ {
+ // setChild( node, count, addTrian ( chd, subp, height - 1, vertmask[i], edgemask ) ) ;
+ setChild( node, count, addTrian ( chd, subp, height - 1 ) ) ;
+ }
+ else
+ {
+ setChild( node, count, updateCell( chd, subp ) ) ;
+ }
+ }
+ }
+
+ if ( hasChild( node, i ) )
+ {
+ count ++ ;
+ }
+ }
+
+ delete subp ;
+ return node ;
+}
+
+UCHAR* Octree::updateCell( UCHAR* node, Projections* p )
+{
+ int i ;
+
+ // Edge connectivity
+ int mask[3] = { 0, 4, 8 } ;
+ int oldc = 0, newc = 0 ;
+ float offs[3] ;
+#ifdef USE_HERMIT
+ float a[3], b[3], c[3] ;
+#endif
+
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ if ( ! getEdgeParity( node, mask[i] ) )
+ {
+ if ( p->isIntersectingPrimary( i ) )
+ {
+ // this->actualQuads ++ ;
+ setEdge( node, mask[i] ) ;
+ offs[ newc ] = p->getIntersectionPrimary( i ) ;
+#ifdef USE_HERMIT
+ a[ newc ] = (float) p->inherit->norm[0] ;
+ b[ newc ] = (float) p->inherit->norm[1] ;
+ c[ newc ] = (float) p->inherit->norm[2] ;
+#endif
+ newc ++ ;
+ }
+ }
+ else
+ {
+#ifndef USE_HERMIT
+ offs[ newc ] = getEdgeOffset( node, oldc ) ;
+#else
+ offs[ newc ] = getEdgeOffsetNormal( node, oldc, a[ newc ], b[ newc ], c[ newc ] ) ;
+#endif
+
+// if ( p->isIntersectingPrimary( i ) )
+ {
+ // printf("Multiple intersections!\n") ;
+
+// setPatchEdge( node, i ) ;
+ }
+
+ oldc ++ ;
+ newc ++ ;
+ }
+ }
+
+ if ( newc > oldc )
+ {
+ // New offsets added, update this node
+#ifndef USE_HERMIT
+ node = updateEdgeOffsets( node, oldc, newc, offs ) ;
+#else
+ node = updateEdgeOffsetsNormals( node, oldc, newc, offs, a, b, c ) ;
+#endif
+ }
+
+
+
+ return node ;
+}
+
+void Octree::preparePrimalEdgesMask( UCHAR* node )
+{
+ int count = 0 ;
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, i ) )
+ {
+ if ( isLeaf( node, i ) )
+ {
+ createPrimalEdgesMask( getChild( node, count ) ) ;
+ }
+ else
+ {
+ preparePrimalEdgesMask( getChild( node, count ) ) ;
+ }
+
+ count ++ ;
+ }
+ }
+}
+
+void Octree::trace( )
+{
+ int st[3] = { 0, 0, 0, } ;
+ this->numRings = 0 ;
+ this->totRingLengths = 0 ;
+ this->maxRingLength = 0 ;
+
+ PathList* chdpath = NULL ;
+ this->root = trace( this->root, st, dimen, maxDepth, chdpath ) ;
+
+ if ( chdpath != NULL )
+ {
+ printf("there are incomplete rings.\n") ;
+ printPaths( chdpath ) ;
+ };
+}
+
+UCHAR* Octree::trace( UCHAR* node, int* st, int len, int depth, PathList*& paths)
+{
+ UCHAR* newnode = node ;
+ len >>= 1 ;
+ PathList* chdpaths[ 8 ] ;
+ UCHAR* chd[ 8 ] ;
+ int nst[ 8 ][ 3 ] ;
+ int i, j ;
+
+ // Get children paths
+ int chdleaf[ 8 ] ;
+ fillChildren( newnode, 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 || isLeaf( node, i ) )
+ {
+ chdpaths[ i ] = NULL ;
+ }
+ else
+ {
+ trace( chd[ i ], nst[i], len, depth - 1, chdpaths[ i ] ) ;
+ }
+ }
+
+ // Get connectors on the faces
+ PathList* conn[ 12 ] ;
+ UCHAR* nf[2] ;
+ int lf[2] ;
+ int df[2] = { depth - 1, depth - 1 } ;
+ int* nstf[ 2 ];
+
+ fillChildren( newnode, 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( 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 )
+ {
+ this->numRings ++ ;
+ this->totRingLengths += trings->length ;
+ if ( trings->length > this->maxRingLength )
+ {
+ this->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( UCHAR* 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 ;
+ UCHAR* chd[ 2 ][ 8 ] ;
+ int chdleaf[ 2 ][ 8 ] ;
+ int nst[ 2 ][ 8 ][ 3 ] ;
+
+ for ( j = 0 ; j < 2 ; j ++ )
+ {
+ if ( ! leaf[j] )
+ {
+ fillChildren( node[j], 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
+ UCHAR* 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( 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 )
+{
+ // 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 )
+{
+ 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 )
+{
+ 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 )
+ {
+ printf( " (%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2] ) ;
+ }
+}
+
+void Octree::printPath( PathList* path )
+{
+ PathElement* n = path->head, *pre ;
+ int len = ( dimen >> maxDepth ) ;
+ int same = 0 ;
+ while ( n && ( same == 0 || n != path->head ) )
+ {
+ same ++ ;
+ printf( " (%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len ) ;
+ pre = n ;
+ n = n->next ;
+ }
+
+ if ( n == path->head )
+ {
+ printf(" Ring!\n") ;
+ }
+ else
+ {
+ printf(" %p end!\n", n) ;
+ }
+}
+
+void Octree::printPath( PathElement* path )
+{
+ PathElement *n = path, *pre ;
+ int len = ( dimen >> maxDepth ) ;
+ int same = 0 ;
+ while ( n && ( same == 0 || n != path ) )
+ {
+ same ++ ;
+ printf( " (%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len ) ;
+ pre = n ;
+ n = n->next ;
+ }
+
+ if ( n == path )
+ {
+ printf(" Ring!\n") ;
+ }
+ else
+ {
+ printf(" %p end!\n", n) ;
+ }
+
+}
+
+
+void Octree::printPaths( PathList* path )
+{
+ PathList* iter = path ;
+ int i = 0 ;
+ while ( iter != NULL )
+ {
+ printf("Path %d:\n", i) ;
+ printPath( iter ) ;
+ iter = iter->next ;
+ i ++ ;
+ }
+}
+
+UCHAR* Octree::patch( UCHAR* node, int st[3], int len, PathList* rings )
+{
+#ifdef IN_DEBUG_MODE
+ 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 ) ;
+ this->numRings ++ ;
+ this->totRingLengths += tlist->length ;
+ if ( tlist->length > this->maxRingLength )
+ {
+ this->maxRingLength = tlist->length ;
+ }
+ ttlist = tlist ;
+ tlist = tlist->next ;
+ }
+ return node ;
+ */
+
+
+ /* Pass onto separate calls in each direction */
+ UCHAR* newnode = node ;
+ if ( len == mindimen )
+ {
+ 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( getChild( newnode , count ), nori, len, zlists[i] ) ;
+ }
+
+ if ( hasChild( newnode, i ) )
+ {
+ count ++ ;
+ }
+ }
+#ifdef IN_DEBUG_MODE
+ printf("Return from PATCH\n") ;
+#endif
+ return newnode ;
+
+}
+
+
+UCHAR* Octree::patchSplit( UCHAR* node, int st[3], int len, PathList* rings, int dir, PathList*& nrings1, PathList*& nrings2 )
+{
+#ifdef IN_DEBUG_MODE
+ printf("Call to PATCHSPLIT with direction %d and rings: \n", dir);
+ printPaths( rings ) ;
+#endif
+
+ UCHAR* newnode = node ;
+ 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 ;
+ }
+
+#ifdef IN_DEBUG_MODE
+ printf("Return from PATCHSPLIT with \n");
+ printf("Rings gourp 1:\n") ;
+ printPaths( nrings1 ) ;
+ printf("Rings group 2:\n") ;
+ printPaths( nrings2 ) ;
+#endif
+
+ return newnode ;
+}
+
+UCHAR* Octree::patchSplitSingle( UCHAR* node, int st[3], int len, PathElement* head, int dir, PathList*& nrings1, PathList*& nrings2 )
+{
+#ifdef IN_DEBUG_MODE
+ printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir );
+ printPath( head ) ;
+#endif
+
+ UCHAR* newnode = node ;
+
+ if ( head == NULL )
+ {
+#ifdef IN_DEBUG_MODE
+ 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 ) ;
+ 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
+ printf("Return from PATCHSPLITSINGLE with \n");
+ printf("Rings gourp 1:\n") ;
+ printPaths( nrings1 ) ;
+ printf("Rings group 2:\n") ;
+ printPaths( nrings2 ) ;
+#endif
+
+ return newnode ;
+}
+
+UCHAR* Octree::connectFace( UCHAR* node, int st[3], int len, int dir, PathElement* f1, PathElement* f2 )
+{
+#ifdef IN_DEBUG_MODE
+ printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len );
+ printf("Path (low side): \n" ) ;
+ printPath( f1 ) ;
+// checkPath( f1 ) ;
+ printf("Path (high side): \n" ) ;
+ printPath( f2 ) ;
+// checkPath( f2 ) ;
+#endif
+
+ UCHAR* newnode = node ;
+
+ // 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 ;
+ UCHAR *nodeN = NULL, *nodeP = NULL ;
+ UCHAR *curN = locateLeaf( newnode, len, f1->pos ) ;
+ UCHAR *curP = locateLeaf( newnode, len, f2->next->pos ) ;
+ if ( curN == NULL || curP == NULL )
+ {
+ exit(0) ;
+ }
+ int stN[3], stP[3] ;
+ int lenN, lenP ;
+
+ 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 ;
+ }
+
+ // printf("new x,y: %d %d\n", ori[ xdir ] / edgelen, ori[ ydir ] / edgelen ) ;
+ // printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir ) ;
+ // printf("%f %f %f\n", spt[0], spt[1], spt[2] ) ;
+
+ // Locate the current cells on both sides
+ newnode = locateCell( newnode, st, len, nori, dir, 1, nodeN, stN, lenN ) ;
+ newnode = locateCell( newnode, st, len, nori, dir, 0, nodeP, stP, lenP ) ;
+
+ updateParent( newnode, 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, len, curEleN->pos, curN, newEleN->pos, 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, len, curEleP->pos, curP, newEleP->pos, nodeP, walkdir, inc, dir, 0, alpha ) ;
+
+
+
+ curEleP = newEleP ;
+ flag ++ ;
+ }
+
+
+ /*
+ if ( flag == 0 )
+ {
+ printf("error: non-synchronized patching! at \n") ;
+ }
+ */
+ }
+
+#ifdef IN_DEBUG_MODE
+ printf("Return from CONNECTFACE with \n");
+ printf("Path (low side):\n") ;
+ printPath( f1 ) ;
+ checkPath( f1 ) ;
+ printf("Path (high side):\n") ;
+ printPath( f2 ) ;
+ checkPath( f2 ) ;
+#endif
+
+
+ return newnode ;
+}
+
+UCHAR* Octree::patchAdjacent( UCHAR* node, int len, int st1[3], UCHAR* leaf1, int st2[3], UCHAR* leaf2, int walkdir, int inc, int dir, int side, float alpha )
+{
+#ifdef IN_DEBUG_MODE
+ printf("Before patching.\n") ;
+ printInfo( st1 ) ;
+ printInfo( st2 ) ;
+ 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 ) ;
+
+ 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
+ printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha ) ;
+ /*
+ if ( alpha < 0 || alpha > 1 )
+ {
+ 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
+ UCHAR* nleaf1 = flipEdge( leaf1, eind1, alpha ) ;
+ UCHAR* 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] ;
+ printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2] ) ;
+ getMinimizer( leaf1, m ) ;
+ printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2] ) ;
+ getMinimizer( leaf2, m ) ;
+ printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2] ) ;
+ */
+
+#ifdef IN_DEBUG_MODE
+ printf("After patching.\n") ;
+ printInfo( st1 ) ;
+ printInfo( st2 ) ;
+#endif
+ return nleaf2 ;
+}
+
+UCHAR* Octree::locateCell( UCHAR* node, int st[3], int len, int ori[3], int dir, int side, UCHAR*& rleaf, int rst[3], int& rlen )
+{
+#ifdef IN_DEBUG_MODE
+ // printf("Call to LOCATECELL with node ") ;
+ // printNode( node ) ;
+#endif
+ UCHAR* newnode = node ;
+ 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
+ // 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 ( hasChild( newnode, ind ) )
+ {
+ int count = getChildCount( newnode, ind ) ;
+ UCHAR* chd = getChild( newnode, count ) ;
+ if ( isLeaf( newnode, ind ) )
+ {
+ rleaf = chd ;
+ rlen = len ;
+ }
+ else
+ {
+ // Recur
+ setChild( newnode, count, locateCell( chd, rst, len, ori, dir, side, rleaf, rst, rlen ) ) ;
+ }
+ }
+ else
+ {
+ // Create a new child here
+ if ( len == this->mindimen )
+ {
+ UCHAR* chd = createLeaf( 0 ) ;
+ newnode = addChild( newnode, ind, chd, 1 ) ;
+ rleaf = chd ;
+ rlen = len ;
+ }
+ else
+ {
+ // Subdivide the empty cube
+ UCHAR* chd = createInternal( 0 ) ;
+ newnode = addChild( newnode, ind, locateCell( chd, rst, len, ori, dir, side, rleaf, rst, rlen ), 0 ) ;
+ }
+ }
+
+#ifdef IN_DEBUG_MODE
+ // printf("Return from LOCATECELL with node ") ;
+ // printNode( newnode ) ;
+#endif
+ return newnode ;
+}
+
+void Octree::checkElement( PathElement* ele )
+{
+ /*
+ if ( ele != NULL && locateLeafCheck( ele->pos ) != ele->node )
+ {
+ 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 ;
+ }
+
+}
+
+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 ;
+ printf("Test.") ;
+ getFacePoint( e, i, x, y, p, 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 ;
+
+ UCHAR* 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[ edgevmap[ 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 )
+ {
+ 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)
+ {
+ 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 )
+ {
+ printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node ) ;
+ 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]);
+ 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 ) ;
+
+ p = ( xf - leaf->pos[ xdir ] ) / mindimen ;
+ q = ( yf - leaf->pos[ ydir ] ) / mindimen ;
+
+
+#ifdef IN_DEBUG_MODE
+ 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 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 ) ;
+}
+
+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] ) ;
+}
+
+void Octree::compressRing( PathElement*& ring )
+{
+ if ( ring == NULL )
+ {
+ return ;
+ }
+#ifdef IN_DEBUG_MODE
+ 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 ;
+
+#ifdef IN_DEBUG_MODE
+ printf("Return from COMPRESSRING with path: \n" );
+ printPath( ring ) ;
+#endif
+}
+
+void Octree::buildSigns( )
+{
+ // First build a lookup table
+ // 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 >> edgevmap[j][0] ) & 1 ) ^ ( ( i >> edgevmap[j][1] ) & 1 ) )
+ {
+ ind |= 1 ;
+ }
+ }
+
+ table[ ind ] = i ;
+ }
+
+ // Next, traverse the grid
+ int sg = 1 ;
+ int cube[8] ;
+ buildSigns( table, this->root, 0, sg, cube ) ;
+}
+
+void Octree::buildSigns( unsigned char table[], UCHAR* 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
+ UCHAR* chd[8] ;
+ int leaf[8] ;
+ fillChildren( node, 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, table, sg ) ;
+
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ rvalue[i] = getSign( node, 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
+ this->clearProcessBits( root, maxDepth ) ;
+ int threshold = this->floodFill( root, st, dimen, maxDepth, 0 ) ;
+
+ // Next remove
+ printf("Largest component: %d\n", threshold);
+ threshold *= thresh ;
+ printf("Removing all components smaller than %d\n", threshold) ;
+
+ int st2[3] = { 0, 0, 0 } ;
+ this->clearProcessBits( root, maxDepth ) ;
+ this->floodFill( root, st2, dimen, maxDepth, threshold ) ;
+
+}
+
+void Octree::clearProcessBits( UCHAR* node, int height )
+{
+ int i;
+
+ if ( height == 0 )
+ {
+ // Leaf cell,
+ for ( i = 0 ; i < 12 ; i ++ )
+ {
+ setOutProcess( node, i ) ;
+ }
+ }
+ else
+ {
+ // Internal cell, recur
+ int count = 0 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, i ) )
+ {
+ clearProcessBits( getChild( node, count ), height - 1 ) ;
+ count ++ ;
+ }
+ }
+ }
+}
+
+/*
+void Octree::floodFill( UCHAR* node, int st[3], int len, int height, int threshold )
+{
+ int i, j;
+
+ if ( height == 0 )
+ {
+ // Leaf cell,
+ int par, inp ;
+
+ // Test if the leaf has intersection edges
+ for ( i = 0 ; i < 12 ; i ++ )
+ {
+ par = getEdgeParity( node, i ) ;
+ inp = isInProcess( node, 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[edgevmap[i][0]][0] * len ;
+ mst[1] = st[1] + vertmap[edgevmap[i][0]][1] * len ;
+ mst[2] = st[2] + vertmap[edgevmap[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 )
+ {
+ // 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
+ UCHAR* 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 )
+ {
+ printf("Wrong! this is not a consistent sign. %d\n", eind );
+ }
+ else
+ {
+ int est[3] ;
+ est[0] = cst[cind][0] + vertmap[edgevmap[edge][0]][0] * len ;
+ est[1] = cst[cind][1] + vertmap[edgevmap[edge][0]][1] * len ;
+ est[2] = cst[cind][2] + vertmap[edgevmap[edge][0]][2] * len ;
+ int edir = edge / 4 ;
+
+ if ( isInProcess( cs[cind], edge ) == 0 )
+ {
+ setInProcessAll( est, edir ) ;
+ queue->pushQueue( est, edir ) ;
+ // printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+ total ++ ;
+ }
+ else
+ {
+ // printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+ }
+ }
+
+ }
+
+ }
+
+ printf("Size of component: %d ", total) ;
+
+ if ( total > threshold )
+ {
+ printf("Maintained.\n") ;
+ continue ;
+ }
+ 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 )
+ {
+ // 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
+ UCHAR* 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 )
+ {
+ printf("Wrong! this is not a consistent sign. %d\n", eind );
+ }
+ else
+ {
+ int est[3] ;
+ est[0] = cst[cind][0] + vertmap[edgevmap[edge][0]][0] * len ;
+ est[1] = cst[cind][1] + vertmap[edgevmap[edge][0]][1] * len ;
+ est[2] = cst[cind][2] + vertmap[edgevmap[edge][0]][2] * len ;
+ int edir = edge / 4 ;
+
+ if ( getEdgeParity( cs[cind], edge ) == 1 )
+ {
+ flipParityAll( est, edir ) ;
+ queue->pushQueue( est, edir ) ;
+ // printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+ total ++ ;
+ }
+ else
+ {
+ // printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+ }
+ }
+
+ }
+
+ }
+
+ }
+ }
+ }
+ else
+ {
+ // Internal cell, recur
+ int count = 0 ;
+ len >>= 1 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, 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 ;
+
+ floodFill( getChild( node, count ), nst, len, height - 1, threshold ) ;
+ count ++ ;
+ }
+ }
+ }
+}
+*/
+
+int Octree::floodFill( UCHAR* node, int st[3], int len, int height, int threshold )
+{
+ int i, j;
+ int maxtotal = 0 ;
+
+ if ( height == 0 )
+ {
+ // Leaf cell,
+ int par, inp ;
+
+ // Test if the leaf has intersection edges
+ for ( i = 0 ; i < 12 ; i ++ )
+ {
+ par = getEdgeParity( node, i ) ;
+ inp = isInProcess( node, 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[edgevmap[i][0]][0] * len ;
+ mst[1] = st[1] + vertmap[edgevmap[i][0]][1] * len ;
+ mst[2] = st[2] + vertmap[edgevmap[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 )
+ {
+ // 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
+ UCHAR* 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 )
+ {
+ printf("Wrong! this is not a consistent sign. %d\n", eind );
+ }
+ else
+ {
+ int est[3] ;
+ est[0] = cst[cind][0] + vertmap[edgevmap[edge][0]][0] * len ;
+ est[1] = cst[cind][1] + vertmap[edgevmap[edge][0]][1] * len ;
+ est[2] = cst[cind][2] + vertmap[edgevmap[edge][0]][2] * len ;
+ int edir = edge / 4 ;
+
+ if ( isInProcess( cs[cind], edge ) == 0 )
+ {
+ setInProcessAll( est, edir ) ;
+ queue->pushQueue( est, edir ) ;
+ // printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+ total ++ ;
+ }
+ else
+ {
+ // printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+ }
+ }
+
+ }
+
+ }
+
+ printf("Size of component: %d ", total) ;
+
+ if ( threshold == 0 )
+ {
+ // Measuring stage
+ if ( total > maxtotal )
+ {
+ maxtotal = total ;
+ }
+ printf(".\n") ;
+ continue ;
+ }
+
+ if ( total >= threshold )
+ {
+ printf("Maintained.\n") ;
+ continue ;
+ }
+ 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 )
+ {
+ // 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
+ UCHAR* 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 )
+ {
+ printf("Wrong! this is not a consistent sign. %d\n", eind );
+ }
+ else
+ {
+ int est[3] ;
+ est[0] = cst[cind][0] + vertmap[edgevmap[edge][0]][0] * len ;
+ est[1] = cst[cind][1] + vertmap[edgevmap[edge][0]][1] * len ;
+ est[2] = cst[cind][2] + vertmap[edgevmap[edge][0]][2] * len ;
+ int edir = edge / 4 ;
+
+ if ( getEdgeParity( cs[cind], edge ) == 1 )
+ {
+ flipParityAll( est, edir ) ;
+ queue->pushQueue( est, edir ) ;
+ // printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+ total ++ ;
+ }
+ else
+ {
+ // printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
+ }
+ }
+
+ }
+
+ }
+
+ }
+ }
+
+ }
+ else
+ {
+ // Internal cell, recur
+ int count = 0 ;
+ len >>= 1 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, 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( getChild( node, count ), nst, len, height - 1, threshold ) ;
+ if ( d > maxtotal)
+ {
+ maxtotal = d ;
+ }
+ count ++ ;
+ }
+ }
+ }
+
+
+ return maxtotal ;
+
+}
+
+DualConMesh *Octree::writeOut(DualConCreateMesh create_mesh)
+{
+ int numQuads = 0 ;
+ int numVertices = 0 ;
+ int numEdges = 0 ;
+#ifdef USE_HERMIT
+ countIntersection( root, maxDepth, numQuads, numVertices, numEdges ) ;
+#else
+ countIntersection( root, maxDepth, numQuads, numVertices ) ;
+ numEdges = numQuads * 3 / 2 ;
+#endif
+ printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads ) ;
+ DualConMesh *output_mesh = create_mesh(numVertices, numQuads);
+ int offset = 0 ;
+ int st[3] = { 0, 0, 0 } ;
+
+ // First, output vertices
+ offset = 0 ;
+ actualVerts = 0 ;
+ actualQuads = 0 ;
+#ifdef USE_HERMIT
+ generateMinimizer( root, st, dimen, maxDepth, offset, output_mesh ) ;
+ cellProcContour( this->root, 0, maxDepth, output_mesh ) ;
+ printf("Vertices written: %d Quads written: %d \n", offset, actualQuads ) ;
+#else
+ writeVertex( root, st, dimen, maxDepth, offset, out ) ;
+ writeQuad( root, st, dimen, maxDepth, out ) ;
+ printf("Vertices written: %d Triangles written: %d \n", offset, actualQuads ) ;
+#endif
+
+ return output_mesh;
+}
+
+#if 0
+void Octree::writePLY( char* fname )
+{
+ int numQuads = 0 ;
+ int numVertices = 0 ;
+ int numEdges = 0 ;
+#ifdef USE_HERMIT
+ countIntersection( root, maxDepth, numQuads, numVertices, numEdges ) ;
+#else
+ countIntersection( root, maxDepth, numQuads, numVertices ) ;
+ numEdges = numQuads * 3 / 2 ;
+#endif
+ // int euler = numVertices + numQuads - numEdges ;
+ // int genus = ( 2 - euler ) / 2 ;
+ // printf("%d vertices %d quads %d edges\n", numVertices, numQuads, numEdges ) ;
+ // printf("Genus: %d Euler: %d\n", genus, euler ) ;
+
+ FILE* fout = fopen ( fname, "wb" ) ;
+ printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads ) ;
+ PLYWriter::writeHeader( fout, numVertices, numQuads ) ;
+ int offset = 0 ;
+ int st[3] = { 0, 0, 0 } ;
+
+ // First, output vertices
+ offset = 0 ;
+ actualVerts = 0 ;
+ actualQuads = 0 ;
+#ifdef USE_HERMIT
+ generateMinimizer( root, st, dimen, maxDepth, offset, fout ) ;
+#ifdef TESTMANIFOLD
+ testfout = fopen("test.txt", "w");
+ fprintf(testfout, "{");
+#endif
+ cellProcContour( this->root, 0, maxDepth, fout ) ;
+#ifdef TESTMANIFOLD
+ fprintf(testfout, "}");
+ fclose( testfout ) ;
+#endif
+ printf("Vertices written: %d Quads written: %d \n", offset, actualQuads ) ;
+#else
+ writeVertex( root, st, dimen, maxDepth, offset, fout ) ;
+ writeQuad( root, st, dimen, maxDepth, fout ) ;
+ printf("Vertices written: %d Triangles written: %d \n", offset, actualQuads ) ;
+#endif
+
+
+ fclose( fout ) ;
+}
+#endif
+
+void Octree::writeOctree( char* fname )
+{
+ FILE* fout = fopen ( fname, "wb" ) ;
+
+ int sized = ( 1 << maxDepth ) ;
+ fwrite( &sized, sizeof( int ), 1, fout ) ;
+ writeOctree( fout, root, maxDepth ) ;
+ printf("Grid dimension: %d\n", sized ) ;
+
+
+ fclose( fout ) ;
+}
+void Octree::writeOctree( FILE* fout, UCHAR* node, int depth )
+{
+ char type ;
+ if ( depth > 0 )
+ {
+ type = 0 ;
+ fwrite( &type, sizeof( char ), 1, fout ) ;
+
+ // Get sign at the center
+ char sg = (char) getSign( getChild( node, 0 ), depth - 1, 7 - getChildIndex( node, 0 ) ) ;
+
+ int t = 0 ;
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, i ) )
+ {
+ writeOctree( fout, getChild( node, t ), depth - 1 ) ;
+ t ++ ;
+ }
+ else
+ {
+ type = 1 ;
+ fwrite( &type, sizeof( char ), 1, fout ) ;
+ fwrite( &sg, sizeof( char ), 1, fout ) ;
+ }
+ }
+ }
+ else
+ {
+ type = 2 ;
+ fwrite( &type, sizeof( char ), 1, fout ) ;
+ fwrite( &(node[2]), sizeof ( UCHAR ), 1, fout );
+ }
+}
+
+#ifdef USE_HERMIT
+#if 0
+void Octree::writeOctreeGeom( char* fname )
+{
+ FILE* fout = fopen ( fname, "wb" ) ;
+
+ // Write header
+ char header[]="SOG.Format 1.0";
+ int nlen = 128 - 4 * 4 - strlen(header) - 1 ;
+ char* header2 = new char[ nlen ];
+ for ( int i = 0 ; i < nlen ; i ++ )
+ {
+ header2[i] = '\0';
+ }
+ fwrite( header, sizeof( char ), strlen(header) + 1, fout ) ;
+ fwrite( origin, sizeof( float ), 3, fout ) ;
+ fwrite( &range, sizeof( float ), 1, fout ) ;
+ fwrite( header2, sizeof( char ), nlen, fout ) ;
+
+
+ int sized = ( 1 << maxDepth ) ;
+ int st[3] = {0,0,0};
+ fwrite( &sized, sizeof( int ), 1, fout ) ;
+
+ writeOctreeGeom( fout, root, st, dimen, maxDepth ) ;
+ printf("Grid dimension: %d\n", sized ) ;
+
+
+ fclose( fout ) ;
+}
+#endif
+void Octree::writeOctreeGeom( FILE* fout, UCHAR* node, int st[3], int len, int depth )
+{
+ char type ;
+ if ( depth > 0 )
+ {
+ type = 0 ;
+ fwrite( &type, sizeof( char ), 1, fout ) ;
+
+ // Get sign at the center
+ char sg = (char) getSign( getChild( node, 0 ), depth - 1, 7 - getChildIndex( node, 0 ) ) ;
+
+ int t = 0 ;
+ len >>= 1 ;
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, 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 ;
+ writeOctreeGeom( fout, getChild( node, t ), nst, len, depth - 1 ) ;
+ t ++ ;
+ }
+ else
+ {
+ type = 1 ;
+ fwrite( &type, sizeof( char ), 1, fout ) ;
+ fwrite( &sg, sizeof( char ), 1, fout ) ;
+ }
+ }
+ }
+ else
+ {
+ type = 2 ;
+ fwrite( &type, sizeof( char ), 1, fout ) ;
+ fwrite( &(node[2]), sizeof ( UCHAR ), 1, fout );
+
+ // Compute minimizer
+ // 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, st, len, rvalue ) ;
+
+ // Update
+ // float flen = len * range / dimen ;
+ for ( int j = 0 ; j < 3 ; j ++ )
+ {
+ rvalue[ j ] = rvalue[ j ] * range / dimen + origin[ j ] ;
+ }
+
+ fwrite( rvalue, sizeof ( float ), 3, fout );
+ }
+}
+#endif
+
+#ifdef USE_HERMIT
+void Octree::writeDCF( char* fname )
+{
+ FILE* fout = fopen ( fname, "wb" ) ;
+
+ // Writing out version
+ char version[10] = "multisign";
+ fwrite ( &version, sizeof ( char ), 10, fout );
+
+ // Writing out size
+ int sized = ( 1 << maxDepth ) ;
+ fwrite( &sized, sizeof( int ), 1, fout ) ;
+ fwrite( &sized, sizeof( int ), 1, fout ) ;
+ fwrite( &sized, sizeof( int ), 1, fout ) ;
+
+ int st[3] = {0, 0, 0} ;
+ writeDCF( fout, root, maxDepth, st, dimen ) ;
+
+ printf("Grid dimension: %d\n", sized ) ;
+ fclose( fout ) ;
+}
+
+void Octree::writeDCF( FILE* fout, UCHAR* node, int height, int st[3], int len )
+{
+ nodetype type ;
+ if ( height > 0 )
+ {
+ type = 0 ;
+ len >>= 1 ;
+ fwrite( &type, sizeof( nodetype ), 1, fout ) ;
+
+ // Get sign at the center
+ signtype sg = 1 - (signtype) getSign( getChild( node, 0 ), height - 1, 7 - getChildIndex( node, 0 ) ) ;
+
+ int t = 0 ;
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, 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 ;
+
+
+ writeDCF( fout, getChild( node, t ), height - 1, nst, len ) ;
+ t ++ ;
+ }
+ else
+ {
+ type = 1 ;
+ fwrite( &type, sizeof( nodetype ), 1, fout ) ;
+ fwrite ( &(sg), sizeof ( signtype ), 1, fout );
+ }
+ }
+ }
+ else
+ {
+ type = 2 ;
+ fwrite( &type, sizeof( nodetype ), 1, fout ) ;
+
+ // Write signs
+ signtype sgn[8] ;
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ sgn[ i ] = 1 - (signtype) getSign( node, i ) ;
+ }
+ fwrite (sgn, sizeof (signtype), 8, fout );
+
+ // Write edge data
+ float pts[12], norms[12][3] ;
+ int parity[12] ;
+ fillEdgeOffsetsNormals( node, st, len, pts, norms, parity ) ;
+
+ numtype zero = 0, one = 1 ;
+ for ( int i = 0 ; i < 12 ; i ++ )
+ {
+ int par = getEdgeParity( node, i ) ;
+ // Let's check first
+ if ( par )
+ {
+ if ( sgn[ edgevmap[i][0] ] == sgn[ edgevmap[i][1] ] )
+ {
+ printf("Wrong! Parity: %d Sign: %d %d\n", parity[i], sgn[ edgevmap[i][0] ], sgn[ edgevmap[i][1] ]);
+ exit(0) ;
+ }
+ if ( parity[ i ] == 0 )
+ {
+ printf("Wrong! No intersection found.\n");
+ exit(0) ;
+ }
+ fwrite( &one, sizeof ( numtype ) , 1, fout ) ;
+ fwrite( &(pts[i]), sizeof( float ), 1, fout ) ;
+ fwrite( norms[i], sizeof( float ), 3, fout ) ;
+
+ }
+ else
+ {
+ if ( sgn[ edgevmap[i][0] ] != sgn[ edgevmap[i][1] ] )
+ {
+ printf("Wrong! Parity: %d Sign: %d %d\n", parity[i], sgn[ edgevmap[i][0] ], sgn[ edgevmap[i][1] ]);
+ exit(0) ;
+ }
+ fwrite ( &zero, sizeof ( numtype ) , 1, fout );
+ }
+ }
+ }
+}
+#endif
+
+
+void Octree::writeOpenEdges( FILE* fout )
+{
+ // Total number of rings
+ fprintf( fout, "%d\n", numRings ) ;
+ printf("Number of rings to write: %d\n", numRings) ;
+
+ // Write each ring
+ PathList* tlist = ringList ;
+ for ( int i = 0 ; i < numRings ; i ++ )
+ {
+ fprintf(fout, "%d\n", tlist->length) ;
+ // printf("Ring length: %d\n", tlist->length ) ;
+ PathElement* cur = tlist->head ;
+ for ( int j = 0 ; j < tlist->length ; j ++ )
+ {
+ float cent[3] ;
+ float flen = mindimen * range / dimen ;
+ for ( int k = 0 ; k < 3 ; k ++ )
+ {
+ cent[ k ] = cur->pos[ k ] * range / dimen + origin[ k ] + flen / 2 ;
+ }
+ fprintf(fout, "%f %f %f\n", cent[0], cent[1], cent[2]) ;
+ cur = cur->next ;
+ }
+
+ tlist = tlist->next ;
+ }
+}
+
+#ifndef USE_HERMIT
+void Octree::countIntersection( UCHAR* node, int height, int& nquad, int& nvert )
+{
+ if ( height > 0 )
+ {
+ int total = getNumChildren( node ) ;
+ for ( int i = 0 ; i < total ; i ++ )
+ {
+ countIntersection( getChild( node, i ), height - 1, nquad, nvert ) ;
+ }
+ }
+ else
+ {
+ int mask = getSignMask( node ) ;
+ nvert += getNumEdges2( node ) ;
+ nquad += cubes->getNumTriangle( mask ) ;
+
+ }
+}
+
+void Octree::writeVertex( UCHAR* node, int st[3], int len, int height, int& offset, FILE* fout )
+{
+ int i ;
+
+ if ( height == 0 )
+ {
+ // Leaf cell, generate
+ int emap[] = { 0, 4, 8 } ;
+ for ( int i = 0 ; i < 3 ; i ++ )
+ {
+ if ( getEdgeParity( node, emap[i] ) )
+ {
+ // Get intersection location
+ int count = getEdgeCount( node, i ) ;
+ float off = getEdgeOffset( node, count ) ;
+
+ float rvalue[3] ;
+ rvalue[0] = (float) st[0] ;
+ rvalue[1] = (float) st[1] ;
+ rvalue[2] = (float) st[2] ;
+ rvalue[i] += off * mindimen ;
+
+ // Update
+ float fnst[3] ;
+ float flen = len * range / dimen ;
+ for ( int j = 0 ; j < 3 ; j ++ )
+ {
+ rvalue[ j ] = rvalue[ j ] * range / dimen + origin[ j ] ;
+ fnst[ j ] = st[ j ] * range / dimen + origin[ j ] ;
+ }
+
+ if ( this->outType == 0 )
+ {
+ fprintf( fout, "%f %f %f\n", rvalue[0], rvalue[1], rvalue[2] ) ;
+ }
+ else if ( this->outType == 1 )
+ {
+ PLYWriter::writeVertex( fout, rvalue ) ;
+ }
+
+ // Store the index
+ setEdgeIntersectionIndex( node, count, offset ) ;
+ offset ++ ;
+ }
+ }
+
+ }
+ else
+ {
+ // Internal cell, recur
+ int count = 0 ;
+ len >>= 1 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, 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 ;
+
+ writeVertex( getChild( node, count ), nst, len, height - 1, offset, fout ) ;
+ count ++ ;
+ }
+ }
+ }
+}
+
+void Octree::writeQuad( UCHAR* node, int st[3], int len, int height, FILE* fout )
+{
+ int i ;
+ if ( height == 0 )
+ {
+ int mask = getSignMask( node ) ;
+ int num = cubes->getNumTriangle( mask ) ;
+ int indices[12] ;
+ fillEdgeIntersectionIndices( node, st, len, indices ) ;
+ int einds[3], ind[3] ;
+
+ //int flag1 = 0 ;
+ //int flag2 = 0 ;
+ for ( i = 0 ; i < num ; i ++ )
+ {
+ int color = 0 ;
+ cubes->getTriangle( mask, i, einds ) ;
+ // printf("(%d %d %d) ", einds[0], einds[1], einds[2] ) ;
+
+ for ( int j = 0 ; j < 3 ; j ++ )
+ {
+ ind[j] = indices[ einds[j] ] ;
+ /*
+ if ( ind[j] == 78381 )
+ {
+ flag1 = 1 ;
+ }
+ if ( ind[j] == 78384 )
+ {
+ flag2 = 1 ;
+ }
+ */
+ }
+
+ if ( this->outType == 0 )
+ {
+ // OFF
+ int numpoly = ( color ? -3 : 3 ) ;
+ fprintf(fout, "%d %d %d %d\n", numpoly, ind[0], ind[1], ind[2] ) ;
+ actualQuads ++ ;
+ }
+ else if ( this->outType == 1 )
+ {
+ // PLY
+ PLYWriter::writeFace( fout, 3, ind ) ;
+ actualQuads ++ ;
+ }
+ }
+
+ /*
+ if (flag1 && flag2)
+ {
+ printf("%d\n", mask);
+ cubes->printTriangles( mask ) ;
+ }
+ */
+ }
+ else
+ {
+ // Internal cell, recur
+ int count = 0 ;
+ len >>= 1 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, 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 ;
+
+ writeQuad( getChild( node, count ), nst, len, height - 1, fout ) ;
+ count ++ ;
+ }
+ }
+ }
+}
+
+#endif
+
+
+#ifdef USE_HERMIT
+void Octree::countIntersection( UCHAR* node, int height, int& nedge, int& ncell, int& nface )
+{
+ if ( height > 0 )
+ {
+ int total = getNumChildren( node ) ;
+ for ( int i = 0 ; i < total ; i ++ )
+ {
+ countIntersection( getChild( node, i ), height - 1, nedge, ncell, nface ) ;
+ }
+ }
+ else
+ {
+ nedge += getNumEdges2( node ) ;
+
+ int smask = getSignMask( node ) ;
+
+ 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, i * 2 ) )
+ {
+ nface ++ ;
+ }
+ }
+ }
+}
+
+void Octree::computeMinimizer( UCHAR* leaf, int st[3], int len, float rvalue[3] )
+{
+ int i ;
+
+ // First, gather all edge intersections
+ float pts[12][3], norms[12][3] ;
+ // fillEdgeIntersections( leaf, st, len, pts, norms ) ;
+ int parity[12] ;
+ fillEdgeIntersections( leaf, st, len, pts, norms, parity ) ;
+
+ // Next, construct QEF and minimizer
+ float mp[3] = {0, 0, 0 } ;
+ float ata[6] = { 0, 0, 0, 0, 0, 0 };
+ float atb[3] = { 0, 0, 0 } ;
+ float btb = 0 ;
+ int ec = 0 ;
+
+ for ( i = 0 ; i < 12 ; i ++ )
+ {
+ // if ( getEdgeParity( leaf, i) )
+ if ( parity[ i ] )
+ {
+ float* norm = norms[i] ;
+ float* p = pts[i] ;
+
+ // printf("Norm: %f, %f, %f Pts: %f, %f, %f\n", norm[0], norm[1], norm[2], p[0], p[1], p[2] ) ;
+
+ /*
+ if ( p[0] < 0 || p[1] < 0 || p[2] < 0 ||
+ p[0] > dimen || p[1] > dimen || p[2] > dimen )
+ {
+ printf("Bad@!!! At: (%d %d %d) \n", p[0], p[1], p[2] ) ;
+ }
+ */
+
+ // 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 ] );
+
+ double 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 ) ;
+
+ btb += (float) pn * (float) 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
+ BoundingBoxf * box = new BoundingBoxf ;
+ box->begin.x = (float) st[0] ;
+ box->begin.y = (float) st[1] ;
+ box->begin.z = (float) st[2] ;
+ box->end.x = (float) st[0] + len ;
+ box->end.y = (float) st[1] + len ;
+ box->end.z = (float) st[2] + len ;
+
+ float mat[10] ;
+ calcPoint( ata, atb, btb, mp, rvalue, box, mat ) ;
+ // printf("%f ", error) ;
+
+ /* Restraining the location of the minimizer */
+ float nh1 = hermite_num * len ;
+ float nh2 = ( 1 + hermite_num ) * len ;
+ if((mode == DUALCON_MASS_POINT || mode == DUALCON_CENTROID) ||
+ ( 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 ))
+ {
+ if(mode == DUALCON_CENTROID) {
+ // Use centroids
+ rvalue[0] = (float) st[0] + len / 2 ; // mp[0] ;
+ rvalue[1] = (float) st[1] + len / 2 ; // mp[1] ;
+ rvalue[2] = (float) st[2] + len / 2 ; // mp[2] ;
+ }
+ else {
+ // Use mass point instead
+ rvalue[0] = mp[0] ;
+ rvalue[1] = mp[1] ;
+ rvalue[2] = mp[2] ;
+ }
+ }
+}
+
+void Octree::generateMinimizer( UCHAR* node, int st[3], int len, int height, int& offset, DualConMesh *out )
+{
+ 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, 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 ) ;
+
+ if(use_manifold)
+ {
+ mult = manifold_table[ smask ].comps ;
+ }
+ else
+ {
+ if ( smask > 0 && smask < 255 )
+ {
+ mult = 1 ;
+ }
+ }
+
+ for ( j = 0 ; j < mult ; j ++ )
+ {
+ dualcon_mesh_add_co(out, rvalue);
+ }
+
+ // Store the index
+ setMinimizerIndex( node, offset ) ;
+
+ offset += mult ;
+ }
+ else
+ {
+ // Internal cell, recur
+ int count = 0 ;
+ len >>= 1 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( hasChild( node, 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( getChild( node, count ), nst, len, height - 1, offset, out ) ;
+ count ++ ;
+ }
+ }
+ }
+}
+
+void Octree::processEdgeWrite( UCHAR* node[4], int depth[4], int maxdep, int dir, DualConMesh *out )
+{
+ //int color = 0 ;
+
+ int i = 3 ;
+ {
+ if ( getEdgeParity( node[i], processEdgeMask[dir][i] ) )
+ {
+ int flip = 0 ;
+ int edgeind = processEdgeMask[dir][i] ;
+ if ( getSign( node[i], edgevmap[ edgeind ][ 1 ] ) > 0 )
+ {
+ flip = 1 ;
+ }
+
+ int num = 0 ;
+ {
+ int ind[8];
+ if(use_manifold)
+ {
+ /* Deprecated
+ int ind[4] = {
+ getMinimizerIndex( node[0], processEdgeMask[dir][0] ),
+ getMinimizerIndex( node[1], processEdgeMask[dir][1] ),
+ getMinimizerIndex( node[3], processEdgeMask[dir][3] ),
+ getMinimizerIndex( node[2], processEdgeMask[dir][2] )
+ } ;
+ num = 4 ;
+ */
+ int vind[2] ;
+ int seq[4] = {0,1,3,2};
+ for ( int k = 0 ; k < 4 ; k ++ )
+ {
+ getMinimizerIndices( 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] ;
+ }
+ }
+ }
+#ifdef TESTMANIFOLD
+ if ( num != 4 )
+ {
+ printf("Polygon: %d\n", num);
+ }
+ for ( k = 0 ; k < num ; k ++ )
+ {
+ fprintf(testfout, "{%d,%d},", ind[k], ind[(k+1)%num] );
+ }
+#endif
+ }
+ else
+ {
+ ind[0] = getMinimizerIndex( node[0] );
+ ind[1] = getMinimizerIndex( node[1] );
+ ind[2] = getMinimizerIndex( node[3] );
+ ind[3] = getMinimizerIndex( node[2] );
+ num = 4 ;
+ }
+
+ dualcon_mesh_add_polygon(out, num, ind, flip);
+ /*
+ if ( this->outType == 0 )
+ {
+ // OFF
+
+ num = ( color ? -num : num ) ;
+
+ fprintf(fout, "%d ", num);
+
+ if ( flip )
+ {
+ for ( int k = num - 1 ; k >= 0 ; k -- )
+ {
+ fprintf(fout, "%d ", ind[k] ) ;
+ }
+ }
+ else
+ {
+ for ( int k = 0 ; k < num ; k ++ )
+ {
+ fprintf(fout, "%d ", ind[k] ) ;
+ }
+ }
+
+ fprintf( fout, "\n") ;
+
+ actualQuads ++ ;
+ }
+ else if ( this->outType == 1 )
+ {
+ // PLY
+
+ if ( flip )
+ {
+ int tind[8];
+ for ( int k = num - 1 ; k >= 0 ; k -- )
+ {
+ tind[k] = ind[num-1-k] ;
+ }
+ // PLYWriter::writeFace( fout, num, tind ) ;
+ }
+ else
+ {
+ // PLYWriter::writeFace( fout, num, ind ) ;
+ }
+
+ actualQuads ++ ;
+ }*/
+ }
+ return ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+}
+
+
+void Octree::edgeProcContour( UCHAR* node[4], int leaf[4], int depth[4], int maxdep, int dir, DualConMesh *out )
+{
+ if ( ! ( node[0] && node[1] && node[2] && node[3] ) )
+ {
+ return ;
+ }
+ if ( leaf[0] && leaf[1] && leaf[2] && leaf[3] )
+ {
+ processEdgeWrite( node, depth, maxdep, dir, out ) ;
+ }
+ else
+ {
+ int i, j ;
+ UCHAR* chd[ 4 ][ 8 ] ;
+ for ( j = 0 ; j < 4 ; j ++ )
+ {
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i ) )? getChild( node[j], getChildCount( node[j], i ) ) : NULL ;
+ }
+ }
+
+ // 2 edge calls
+ UCHAR* 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] = isLeaf( node[j], c[j] ) ;
+ ne[j] = chd[ j ][ c[j] ] ;
+ de[j] = depth[j] - 1 ;
+ }
+ }
+
+ edgeProcContour( ne, le, de, maxdep - 1, edgeProcEdgeMask[ dir ][ i ][ 4 ], out ) ;
+ }
+
+ }
+}
+
+void Octree::faceProcContour( UCHAR* node[2], int leaf[2], int depth[2], int maxdep, int dir, DualConMesh *out )
+{
+ if ( ! ( node[0] && node[1] ) )
+ {
+ return ;
+ }
+
+ if ( ! ( leaf[0] && leaf[1] ) )
+ {
+ int i, j ;
+ // Fill children nodes
+ UCHAR* chd[ 2 ][ 8 ] ;
+ for ( j = 0 ; j < 2 ; j ++ )
+ {
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i )) ? getChild( node[j], getChildCount( node[j], i ) ) : NULL ;
+ }
+ }
+
+ // 4 face calls
+ UCHAR* 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] = isLeaf( node[j], c[j] ) ;
+ nf[j] = chd[ j ][ c[j] ] ;
+ df[j] = depth[j] - 1 ;
+ }
+ }
+ faceProcContour( nf, lf, df, maxdep - 1, faceProcFaceMask[ dir ][ i ][ 2 ], out ) ;
+ }
+
+ // 4 edge calls
+ int orders[2][4] = {{ 0, 0, 1, 1 }, { 0, 1, 0, 1 }} ;
+ UCHAR* 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] = isLeaf( node[order[j]], 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 ], out ) ;
+ }
+ }
+}
+
+
+void Octree::cellProcContour( UCHAR* node, int leaf, int depth, DualConMesh *out )
+{
+ if ( node == NULL )
+ {
+ return ;
+ }
+
+ if ( ! leaf )
+ {
+ int i ;
+
+ // Fill children nodes
+ UCHAR* chd[ 8 ] ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ chd[ i ] = ((!leaf) && hasChild( node, i )) ? getChild( node, getChildCount( node, i ) ) : NULL ;
+ }
+
+ // 8 Cell calls
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ cellProcContour( chd[ i ], isLeaf( node, i ), depth - 1, out ) ;
+ }
+
+ // 12 face calls
+ UCHAR* 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] = isLeaf( node, c[0] ) ;
+ lf[1] = isLeaf( node, c[1] ) ;
+
+ nf[0] = chd[ c[0] ] ;
+ nf[1] = chd[ c[1] ] ;
+
+ faceProcContour( nf, lf, df, depth - 1, cellProcFaceMask[ i ][ 2 ], out ) ;
+ }
+
+ // 6 edge calls
+ UCHAR* 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] = isLeaf( node, c[j] ) ;
+ ne[j] = chd[ c[j] ] ;
+ }
+
+ edgeProcContour( ne, le, de, depth - 1, cellProcEdgeMask[ i ][ 4 ], out ) ;
+ }
+ }
+
+}
+
+#endif
+
+
+
+void Octree::processEdgeParity( UCHAR* 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] ) ;
+ }
+ }
+
+}
+
+void Octree::edgeProcParity( UCHAR* 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( node, depth, maxdep, dir ) ;
+ }
+ else
+ {
+ int i, j ;
+ UCHAR* chd[ 4 ][ 8 ] ;
+ for ( j = 0 ; j < 4 ; j ++ )
+ {
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i ) )? getChild( node[j], getChildCount( node[j], i ) ) : NULL ;
+ }
+ }
+
+ // 2 edge calls
+ UCHAR* 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] = isLeaf( node[j], 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( UCHAR* 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
+ UCHAR* chd[ 2 ][ 8 ] ;
+ for ( j = 0 ; j < 2 ; j ++ )
+ {
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i )) ? getChild( node[j], getChildCount( node[j], i ) ) : NULL ;
+ }
+ }
+
+ // 4 face calls
+ UCHAR* 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] = isLeaf( node[j], 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 }} ;
+ UCHAR* 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] = isLeaf( node[order[j]], 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( UCHAR* node, int leaf, int depth )
+{
+ if ( node == NULL )
+ {
+ return ;
+ }
+
+ if ( ! leaf )
+ {
+ int i ;
+
+ // Fill children nodes
+ UCHAR* chd[ 8 ] ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ chd[ i ] = ((!leaf) && hasChild( node, i )) ? getChild( node, getChildCount( node, i ) ) : NULL ;
+ }
+
+ // 8 Cell calls
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ cellProcParity( chd[ i ], isLeaf( node, i ), depth - 1 ) ;
+ }
+
+ // 12 face calls
+ UCHAR* 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] = isLeaf( node, c[0] ) ;
+ lf[1] = isLeaf( node, c[1] ) ;
+
+ nf[0] = chd[ c[0] ] ;
+ nf[1] = chd[ c[1] ] ;
+
+ faceProcParity( nf, lf, df, depth - 1, cellProcFaceMask[ i ][ 2 ] ) ;
+ }
+
+ // 6 edge calls
+ UCHAR* 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] = isLeaf( node, c[j] ) ;
+ ne[j] = chd[ c[j] ] ;
+ }
+
+ edgeProcParity( ne, le, de, depth - 1, cellProcEdgeMask[ i ][ 4 ] ) ;
+ }
+ }
+
+}
+
diff --git a/intern/dualcon/intern/octree.h b/intern/dualcon/intern/octree.h
new file mode 100644
index 0000000..a8df43a
--- /dev/null
+++ b/intern/dualcon/intern/octree.h
@@ -0,0 +1,1587 @@
+#ifndef OCTREE_H
+#define OCTREE_H
+
+#include <stdio.h>
+#include <math.h>
+#include "GeoCommon.h"
+#include "Projections.h"
+#include "ModelReader.h"
+#include "MemoryAllocator.h"
+#include "eigen.h"
+#include "cubes.h"
+#include "Queue.h"
+#include "manifold_table.h"
+#include "dualcon.h"
+
+/**
+ * Main class and structures for scan-convertion, sign-generation,
+ * and surface reconstruction.
+ *
+ * @author Tao Ju
+ */
+
+
+/* Global defines */
+// Uncomment to see debug information
+// #define IN_DEBUG_MODE
+
+// Uncomment to see more output messages during repair
+// #define IN_VERBOSE_MODE
+
+/* Set scan convert params */
+// Uncomment to use Dual Contouring on Hermit representation
+// for better sharp feature reproduction, but more mem is required
+// The number indicates how far do we allow the minimizer to shoot
+// outside the cell
+#define USE_HERMIT 1.0f
+
+#ifdef USE_HERMIT
+//#define CINDY
+#endif
+
+///#define QIANYI
+
+//#define TESTMANIFOLD
+
+
+/* Set output options */
+// Comment out to prevent writing output files
+#define OUTPUT_REPAIRED
+
+
+/* Set node bytes */
+#ifdef USE_HERMIT
+#define EDGE_BYTES 16
+#define EDGE_FLOATS 4
+#else
+#define EDGE_BYTES 4
+#define EDGE_FLOATS 1
+#endif
+
+#define CINDY_BYTES 0
+
+/*#define LEAF_EXTRA_BYTES FLOOD_BYTES + CINDY_BYTES
+
+#ifdef USE_HERMIT
+#define LEAF_NODE_BYTES 7 + LEAF_EXTRA_BYTES
+#else
+#define LEAF_NODE_BYTES 3 + LEAF_EXTRA_BYTES
+#endif*/
+
+#define INTERNAL_NODE_BYTES 2
+#define POINTER_BYTES 8
+#define FLOOD_FILL_BYTES 2
+
+#define signtype short
+#define nodetype int
+#define numtype int
+
+/* Global variables */
+const int edgevmap[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}};
+const int edgemask[3] = { 5, 3, 6 } ;
+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}} ;
+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}} ;
+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}} ;
+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}} ;
+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}}
+};
+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}},
+};
+const int processEdgeMask[3][4] = {{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 dirEdge[3][4] = {
+ {3,2,1,0},
+ {7,6,5,4},
+ {11,10,9,8}
+};
+
+
+/**
+ * Structures for detecting/patching open cycles on the dual surface
+ */
+
+struct PathElement
+{
+ // Origin
+ int pos[3] ;
+
+ // link
+ PathElement* next ;
+};
+
+struct PathList
+{
+ // Head
+ PathElement* head ;
+ PathElement* tail ;
+
+ // Length of the list
+ int length ;
+
+ // Next list
+ PathList* next ;
+};
+
+
+/**
+ * Class for building and processing an octree
+ */
+class Octree
+{
+public:
+ /* Public members */
+
+ /// Memory allocators
+ VirtualMemoryAllocator * alloc[ 9 ] ;
+ VirtualMemoryAllocator * leafalloc[ 4 ] ;
+
+ /// Root node
+ UCHAR* root ;
+
+ /// Model reader
+ ModelReader* reader ;
+
+ /// Marching cubes table
+ Cubes* cubes ;
+
+ /// Length of grid
+ int dimen ;
+ int mindimen, minshift ;
+
+ /// Maximum depth
+ int maxDepth ;
+
+ /// The lower corner of the bounding box and the size
+ float origin[3];
+ float range;
+
+ /// Counting information
+ int nodeCount ;
+ int nodeSpace ;
+ int nodeCounts[ 9 ] ;
+
+ int actualQuads, actualVerts ;
+
+ PathList* ringList ;
+
+ int maxTrianglePerCell ;
+ int outType ; // 0 for OFF, 1 for PLY, 2 for VOL
+
+ // For flood filling
+ int use_flood_fill;
+ float thresh ;
+
+ int use_manifold;
+
+ // testing
+ FILE* testfout ;
+
+ float hermite_num;
+
+ DualConMode mode;
+
+ int leaf_node_bytes;
+ int leaf_extra_bytes;
+ int flood_bytes;
+
+public:
+ /**
+ * Construtor
+ */
+ Octree ( ModelReader* mr, DualConFlags flags, DualConMode mode, int depth, float threshold, float hermite_num ) ;
+
+ /**
+ * Destructor
+ */
+ ~Octree ( ) ;
+
+ /**
+ * Scan convert
+ */
+ DualConMesh *scanConvert(DualConCreateMesh create_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 ( UCHAR* node, int leaf, int depth ) ;
+ void faceProcParity ( UCHAR* node[2], int leaf[2], int depth[2], int maxdep, int dir ) ;
+ void edgeProcParity ( UCHAR* node[4], int leaf[4], int depth[4], int maxdep, int dir ) ;
+
+ void processEdgeParity ( UCHAR* node[4], int depths[4], int maxdep, int dir ) ;
+
+ /**
+ * Add triangles to the tree
+ */
+ void addTrian ( );
+ void addTrian ( Triangle* trian, int triind );
+ UCHAR* addTrian ( UCHAR* node, Projections* p, int height );
+
+ /**
+ * Method to update minimizer in a cell: update edge intersections instead
+ */
+ UCHAR* updateCell( UCHAR* node, Projections* 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
+ */
+ UCHAR* trace ( UCHAR* node, int* st, int len, int depth, PathList*& paths ) ;
+ /**
+ * Look for path on the face and add to paths
+ */
+ void findPaths ( UCHAR* 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
+ */
+ UCHAR* patch ( UCHAR* node, int st[3], int len, PathList* rings ) ;
+ UCHAR* patchSplit ( UCHAR* node, int st[3], int len, PathList* rings, int dir, PathList*& nrings1, PathList*& nrings2 ) ;
+ UCHAR* patchSplitSingle ( UCHAR* node, int st[3], int len, PathElement* head, int dir, PathList*& nrings1, PathList*& nrings2 ) ;
+ UCHAR* connectFace ( UCHAR* node, int st[3], int len, int dir, PathElement* f1, PathElement* f2 ) ;
+ UCHAR* locateCell( UCHAR* node, int st[3], int len, int ori[3], int dir, int side, UCHAR*& rleaf, int rst[3], int& rlen ) ;
+ void compressRing ( PathElement*& ring ) ;
+ void getFacePoint( PathElement* leaf, int dir, int& x, int& y, float& p, float& q ) ;
+ UCHAR* patchAdjacent( UCHAR* node, int len, int st1[3], UCHAR* leaf1, int st2[3], UCHAR* 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( UCHAR* 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[], UCHAR* node, int isLeaf, int sg, int rvalue[8] ) ;
+
+ /************************************************************************/
+ /* To remove disconnected components */
+ /************************************************************************/
+ void floodFill( ) ;
+ void clearProcessBits( UCHAR* node, int height ) ;
+ int floodFill( UCHAR* node, int st[3], int len, int height, int threshold ) ;
+
+ /**
+ * Write out polygon file
+ */
+ DualConMesh *writeOut(DualConCreateMesh create_mesh);
+ void writeOFF ( char* fname ) ;
+ void writePLY ( char* fname ) ;
+ void writeOpenEdges( FILE* fout ) ;
+ void writeAllEdges( FILE* fout, int mode ) ;
+ void writeAllEdges( FILE* fout, UCHAR* node, int height, int st[3], int len, int mode ) ;
+
+ void writeOctree( char* fname ) ;
+ void writeOctree( FILE* fout, UCHAR* node, int depth ) ;
+#ifdef USE_HERMIT
+ void writeOctreeGeom( char* fname ) ;
+ void writeOctreeGeom( FILE* fout, UCHAR* node, int st[3], int len, int depth ) ;
+#endif
+#ifdef USE_HERMIT
+ void writeDCF ( char* fname ) ;
+ void writeDCF ( FILE* fout, UCHAR* node, int height, int st[3], int len ) ;
+ void countEdges ( UCHAR* node, int height, int& nedge, int mode ) ;
+ void countIntersection( UCHAR* node, int height, int& nedge, int& ncell, int& nface ) ;
+ void generateMinimizer( UCHAR* node, int st[3], int len, int height, int& offset, DualConMesh *out ) ;
+ void computeMinimizer( UCHAR* leaf, int st[3], int len, float rvalue[3] ) ;
+ /**
+ * Traversal functions to generate polygon model
+ * op: 0 for counting, 1 for writing OBJ, 2 for writing OFF, 3 for writing PLY
+ */
+ void cellProcContour ( UCHAR* node, int leaf, int depth, DualConMesh *out ) ;
+ void faceProcContour ( UCHAR* node[2], int leaf[2], int depth[2], int maxdep, int dir, DualConMesh *out ) ;
+ void edgeProcContour ( UCHAR* node[4], int leaf[4], int depth[4], int maxdep, int dir, DualConMesh *out ) ;
+ void processEdgeWrite ( UCHAR* node[4], int depths[4], int maxdep, int dir, DualConMesh *out ) ;
+#else
+ void countIntersection( UCHAR* node, int height, int& nquad, int& nvert ) ;
+ void writeVertex( UCHAR* node, int st[3], int len, int height, int& offset, FILE* fout ) ;
+ void writeQuad( UCHAR* node, int st[3], int len, int height, FILE* fout ) ;
+#endif
+
+ /**
+ * Write out original model
+ */
+ void writeModel( char* fname ) ;
+
+ /************************************************************************/
+ /* Write out original vertex tags */
+ /************************************************************************/
+#ifdef CINDY
+ void writeTags( char* fname ) ;
+ void readVertices( ) ;
+ void readVertex( UCHAR* node, int st[3], int len, int height, float v[3], int index ) ;
+ void outputTags( UCHAR* node, int height, FILE* fout ) ;
+ void clearCindyBits( UCHAR* node, int height ) ;
+#endif
+
+private:
+ /************ Operators for all nodes ************/
+
+ /**
+ * Bits order
+ *
+ * Leaf node:
+ * Byte 0,1 (0-11): edge parity
+ * Byte 1 (4,5,6): mask of primary edges intersections stored
+ * Byte 1 (7): in flood fill mode, whether the cell is in process
+ * Byte 2 (0-8): signs
+ * Byte 3 (or 5) -- : edge intersections ( 4 bytes per inter, or 12 bytes if USE_HERMIT )
+ * Byte 3,4: in coloring mode, the mask for edges
+ *
+ * Internal node:
+ * Byte 0: child mask
+ * Byte 1: leaf child mask
+ */
+
+ /// Lookup table
+ int numChildrenTable[ 256 ] ;
+ int childrenCountTable[ 256 ][ 8 ] ;
+ int childrenIndexTable[ 256 ][ 8 ] ;
+ int numEdgeTable[ 8 ] ;
+ int edgeCountTable[ 8 ][ 3 ] ;
+
+ /// Build up lookup table
+ void buildTable ( )
+ {
+ for ( int i = 0 ; i < 256 ; i ++ )
+ {
+ numChildrenTable[ i ] = 0 ;
+ int count = 0 ;
+ for ( int j = 0 ; j < 8 ; j ++ )
+ {
+ numChildrenTable[ i ] += ( ( i >> j ) & 1 ) ;
+ childrenCountTable[ i ][ j ] = count ;
+ 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( UCHAR* node, int height, int index )
+ {
+ if ( height == 0 )
+ {
+ return getSign( node, index ) ;
+ }
+ else
+ {
+ if ( hasChild( node, index ) )
+ {
+ return getSign( getChild( node, getChildCount( node, index ) ), height - 1, index ) ;
+ }
+ else
+ {
+ return getSign( getChild( node, 0 ), height - 1, 7 - getChildIndex( node, 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 ) ;
+ UCHAR* leaf = locateLeafCheck( st ) ;
+ if ( leaf == NULL )
+ {
+ printf("Leaf not exists!\n") ;
+ }
+ else
+ {
+ printInfo( leaf ) ;
+ }
+ }
+
+ void printInfo( UCHAR* 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 ( UCHAR* leaf, int index )
+ {
+ return (( leaf[2] >> index ) & 1 );
+ };
+
+ /// Set sign
+ void setSign ( UCHAR* leaf, int index )
+ {
+ leaf[2] |= ( 1 << index ) ;
+ };
+
+ void setSign ( UCHAR* leaf, int index, int sign )
+ {
+ leaf[2] &= ( ~ ( 1 << index ) ) ;
+ leaf[2] |= ( ( sign & 1 ) << index ) ;
+ };
+
+ int getSignMask( UCHAR* leaf )
+ {
+ return leaf[2] ;
+ }
+
+ 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] ;
+
+ UCHAR* cell = locateLeafCheck( nst ) ;
+ if ( cell == NULL )
+ {
+ printf("Wrong!\n") ;
+ }
+ 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] ;
+
+ UCHAR* cell = locateLeaf( nst ) ;
+ flipEdge( cell, eind ) ;
+ }
+ }
+
+ void setInProcess( UCHAR* leaf, int eind )
+ {
+ // leaf[1] |= ( 1 << 7 ) ;
+ ( (USHORT*) (leaf + leaf_node_bytes - (flood_bytes + CINDY_BYTES)))[0] |= ( 1 << eind ) ;
+ }
+ void setOutProcess( UCHAR* leaf, int eind )
+ {
+ // leaf[1] &= ( ~ ( 1 << 7 ) ) ;
+ ( (USHORT*) (leaf + leaf_node_bytes - (flood_bytes + CINDY_BYTES)))[0] &= ( ~ ( 1 << eind ) ) ;
+ }
+
+ int isInProcess( UCHAR* leaf, int eind )
+ {
+ //int a = ( ( leaf[1] >> 7 ) & 1 ) ;
+ int a = ( ( ( (USHORT*) (leaf + leaf_node_bytes - (flood_bytes + CINDY_BYTES)))[0] >> eind ) & 1 ) ;
+ return a ;
+ }
+
+#ifndef USE_HERMIT
+ /// Set minimizer index
+ void setEdgeIntersectionIndex( UCHAR* leaf, int count, int index )
+ {
+ ((int *)( leaf + leaf_node_bytes ))[ count ] = index ;
+ }
+
+ /// Get minimizer index
+ int getEdgeIntersectionIndex( UCHAR* leaf, int count )
+ {
+ return ((int *)( leaf + leaf_node_bytes ))[ count ] ;
+ }
+
+ /// Get all intersection indices associated with a cell
+ void fillEdgeIntersectionIndices( UCHAR* leaf, int st[3], int len, int inds[12] )
+ {
+ int i ;
+
+ // The three primal edges are easy
+ int pmask[3] = { 0, 4, 8 } ;
+ for ( i = 0 ; i < 3 ; i ++ )
+ {
+ if ( getEdgeParity( leaf, pmask[i] ) )
+ {
+ inds[pmask[i]] = getEdgeIntersectionIndex( leaf, getEdgeCount( leaf, 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 ;
+ UCHAR* node = locateLeaf( nst ) ;
+
+ if ( e1 )
+ {
+ inds[ fmask[i][0] ] = getEdgeIntersectionIndex( node, getEdgeCount( node, femask[i][0] ) ) ;
+ }
+ if ( e2 )
+ {
+ inds[ fmask[i][1] ] = getEdgeIntersectionIndex( node, getEdgeCount( node, femask[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 ;
+ UCHAR* node = locateLeaf( nst ) ;
+
+ inds[ emask[i] ] = getEdgeIntersectionIndex( node, getEdgeCount( node, eemask[i] ) ) ;
+ }
+ }
+ }
+
+
+#endif
+
+ /// Generate signs at the corners from the edge parity
+ void generateSigns ( UCHAR* leaf, UCHAR table[], int start )
+ {
+ leaf[2] = table[ ( ((USHORT *) leaf)[ 0 ] ) & ( ( 1 << 12 ) - 1 ) ] ;
+
+ if ( ( start ^ leaf[2] ) & 1 )
+ {
+ leaf[2] = ~ ( leaf[2] ) ;
+ }
+ }
+
+ /// Get edge parity
+ int getEdgeParity( UCHAR* leaf, int index )
+ {
+ int a = ( ( ((USHORT *) leaf)[ 0 ] >> index ) & 1 ) ;
+ return a ;
+ };
+
+ /// Get edge parity on a face
+ int getFaceParity ( UCHAR* 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 ( UCHAR* 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( UCHAR* leaf, int index )
+ {
+ ((USHORT *) leaf)[ 0 ] ^= ( 1 << index ) ;
+ };
+ /// Set 1
+ void setEdge( UCHAR* leaf, int index )
+ {
+ ((USHORT *) leaf)[ 0 ] |= ( 1 << index ) ;
+ };
+ /// Set 0
+ void resetEdge( UCHAR* leaf, int index )
+ {
+ ((USHORT *) leaf)[ 0 ] &= ( ~ ( 1 << index ) ) ;
+ };
+
+ /// Flipping with a new intersection offset
+ void createPrimalEdgesMask( UCHAR* leaf )
+ {
+ int mask = (( leaf[0] & 1 ) | ( (leaf[0] >> 3) & 2 ) | ( (leaf[1] & 1) << 2 ) ) ;
+ leaf[1] |= ( mask << 4 ) ;
+
+ }
+
+ void setStoredEdgesParity( UCHAR* leaf, int pindex )
+ {
+ leaf[1] |= ( 1 << ( 4 + pindex ) ) ;
+ }
+ int getStoredEdgesParity( UCHAR* leaf, int pindex )
+ {
+ return ( ( leaf[1] >> ( 4 + pindex ) ) & 1 ) ;
+ }
+
+ UCHAR* flipEdge( UCHAR* 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 ) ;
+ UCHAR* nleaf = createLeaf( num ) ;
+ for ( int i = 0 ; i < leaf_node_bytes ; i ++ )
+ {
+ nleaf[i] = leaf[i] ;
+ }
+
+ setEdgeOffset( nleaf, alpha, count ) ;
+
+ if ( num > 1 )
+ {
+ float * pts = ( float * ) ( leaf + leaf_node_bytes ) ;
+ float * npts = ( float * ) ( nleaf + leaf_node_bytes ) ;
+ 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, leaf ) ;
+ leaf = nleaf ;
+ }
+ }
+
+ return leaf ;
+ };
+
+ /// Update parent link
+ void updateParent( UCHAR* node, int len, int st[3], UCHAR* leaf )
+ {
+ // First, locate the parent
+ int count ;
+ UCHAR* parent = locateParent( node, len, st, count ) ;
+
+ // UPdate
+ setChild( parent, count, leaf ) ;
+ }
+
+ void updateParent( UCHAR* node, int len, int st[3] )
+ {
+ if ( len == dimen )
+ {
+ root = node ;
+ return ;
+ }
+
+ // First, locate the parent
+ int count ;
+ UCHAR* parent = locateParent( len, st, count ) ;
+
+ // UPdate
+ setChild( parent, count, node ) ;
+ }
+
+ /// Find edge intersection on a given edge
+ int getEdgeIntersectionByIndex( int st[3], int index, float pt[3], int check )
+ {
+ // First, locat the leaf
+ UCHAR* 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( UCHAR* leaf )
+ {
+ // return (( leaf[0] & 1 ) | ( (leaf[0] >> 3) & 2 ) | ( (leaf[1] & 1) << 2 ) ) ;
+ return ( ( leaf[1] >> 4 ) & 7 ) ;
+ }
+
+ int getPrimalEdgesMask2( UCHAR* leaf )
+ {
+ return (( leaf[0] & 1 ) | ( (leaf[0] >> 3) & 2 ) | ( (leaf[1] & 1) << 2 ) ) ;
+ }
+
+ /// Get the count for a primary edge
+ int getEdgeCount( UCHAR* leaf, int index )
+ {
+ return edgeCountTable[ getPrimalEdgesMask( leaf ) ][ index ] ;
+ }
+ int getNumEdges( UCHAR* leaf )
+ {
+ return numEdgeTable[ getPrimalEdgesMask( leaf ) ] ;
+ }
+
+ int getNumEdges2( UCHAR* leaf )
+ {
+ return numEdgeTable[ getPrimalEdgesMask2( leaf ) ] ;
+ }
+
+ /// Set edge intersection
+ void setEdgeOffset( UCHAR* leaf, float pt, int count )
+ {
+ float * pts = ( float * ) ( leaf + leaf_node_bytes ) ;
+#ifdef USE_HERMIT
+ pts[ EDGE_FLOATS * count ] = pt ;
+ pts[ EDGE_FLOATS * count + 1 ] = 0 ;
+ pts[ EDGE_FLOATS * count + 2 ] = 0 ;
+ pts[ EDGE_FLOATS * count + 3 ] = 0 ;
+#else
+ pts[ count ] = pt ;
+#endif
+ }
+
+ /// Set multiple edge intersections
+ void setEdgeOffsets( UCHAR* leaf, float pt[3], int len )
+ {
+ float * pts = ( float * ) ( leaf + leaf_node_bytes ) ;
+ for ( int i = 0 ; i < len ; i ++ )
+ {
+ pts[i] = pt[i] ;
+ }
+ }
+
+ /// Retrieve edge intersection
+ float getEdgeOffset( UCHAR* leaf, int count )
+ {
+#ifdef USE_HERMIT
+ return (( float * ) ( leaf + leaf_node_bytes ))[ 4 * count ] ;
+#else
+ return (( float * ) ( leaf + leaf_node_bytes ))[ count ] ;
+#endif
+ }
+
+ /// Update method
+ UCHAR* updateEdgeOffsets( UCHAR* leaf, int oldlen, int newlen, float offs[3] )
+ {
+ // First, create a new leaf node
+ UCHAR* nleaf = createLeaf( newlen ) ;
+ for ( int i = 0 ; i < leaf_node_bytes ; i ++ )
+ {
+ nleaf[i] = leaf[i] ;
+ }
+
+ // Next, fill in the offsets
+ setEdgeOffsets( nleaf, offs, newlen ) ;
+
+ // Finally, delete the old leaf
+ removeLeaf( oldlen, leaf ) ;
+
+ return nleaf ;
+ }
+
+ /// Set original vertex index
+ void setOriginalIndex( UCHAR* leaf, int index )
+ {
+ ((int *)( leaf + leaf_node_bytes ))[ 0 ] = index ;
+ }
+ int getOriginalIndex( UCHAR* leaf )
+ {
+ return ((int *)( leaf + leaf_node_bytes ))[ 0 ] ;
+ }
+#ifdef USE_HERMIT
+ /// Set minimizer index
+ void setMinimizerIndex( UCHAR* leaf, int index )
+ {
+ ((int *)( leaf + leaf_node_bytes - leaf_extra_bytes - 4 ))[ 0 ] = index ;
+ }
+
+ /// Get minimizer index
+ int getMinimizerIndex( UCHAR* leaf )
+ {
+ return ((int *)( leaf + leaf_node_bytes - leaf_extra_bytes - 4 ))[ 0 ] ;
+ }
+
+ int getMinimizerIndex( UCHAR* leaf, int eind )
+ {
+ int add = manifold_table[ getSignMask( leaf ) ].pairs[ eind ][ 0 ] - 1 ;
+ if ( add < 0 )
+ {
+ printf("Manifold components wrong!\n") ;
+ }
+ return ((int *)( leaf + leaf_node_bytes - leaf_extra_bytes - 4 ))[ 0 ] + add ;
+ }
+
+ void getMinimizerIndices( UCHAR* leaf, int eind, int inds[2] )
+ {
+ const int* add = manifold_table[ getSignMask( leaf ) ].pairs[ eind ] ;
+ inds[0] = ((int *)( leaf + leaf_node_bytes - leaf_extra_bytes - 4 ))[ 0 ] + add[0] - 1 ;
+ if ( add[0] == add[1] )
+ {
+ inds[1] = -1 ;
+ }
+ else
+ {
+ inds[1] = ((int *)( leaf + leaf_node_bytes - leaf_extra_bytes - 4 ))[ 0 ] + add[1] - 1 ;
+ }
+ }
+
+
+ /// Set edge intersection
+ void setEdgeOffsetNormal( UCHAR* leaf, float pt, float a, float b, float c, int count )
+ {
+ float * pts = ( float * ) ( leaf + leaf_node_bytes ) ;
+ pts[ 4 * count ] = pt ;
+ pts[ 4 * count + 1 ] = a ;
+ pts[ 4 * count + 2 ] = b ;
+ pts[ 4 * count + 3 ] = c ;
+ }
+
+ float getEdgeOffsetNormal( UCHAR* leaf, int count, float& a, float& b, float& c )
+ {
+ float * pts = ( float * ) ( leaf + leaf_node_bytes ) ;
+ 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( UCHAR* leaf, float pt[], float a[], float b[], float c[], int len )
+ {
+ float * pts = ( float * ) ( leaf + leaf_node_bytes ) ;
+ 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( UCHAR* leaf, int index, int st[3], int len, float pt[3], float nm[3] )
+ {
+ int count = getEdgeCount( leaf, index ) ;
+ float * pts = ( float * ) ( leaf + leaf_node_bytes ) ;
+
+ 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( UCHAR* leaf, int index, float nm[3] )
+ {
+ int count = getEdgeCount( leaf, index ) ;
+ float * pts = ( float * ) ( leaf + leaf_node_bytes ) ;
+
+ 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( UCHAR* leaf, int st[3], int len, float pts[12][3], float norms[12][3] )
+ {
+ 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 ;
+ UCHAR* 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 ;
+ UCHAR* 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( UCHAR* leaf, int st[3], int len, float pts[12][3], 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 ) )
+ {
+ // 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 ;
+ UCHAR* 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 ;
+ UCHAR* 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( UCHAR* 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 ;
+ UCHAR* 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 ;
+ UCHAR* 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
+ UCHAR* updateEdgeOffsetsNormals( UCHAR* leaf, int oldlen, int newlen, float offs[3], float a[3], float b[3], float c[3] )
+ {
+ // First, create a new leaf node
+ UCHAR* nleaf = createLeaf( newlen ) ;
+ for ( int i = 0 ; i < leaf_node_bytes ; i ++ )
+ {
+ nleaf[i] = leaf[i] ;
+ }
+
+ // Next, fill in the offsets
+ setEdgeOffsetsNormals( nleaf, offs, a, b, c, newlen ) ;
+
+ // Finally, delete the old leaf
+ removeLeaf( oldlen, leaf ) ;
+
+ return nleaf ;
+ }
+#endif
+
+ /// Locate a leaf
+ /// WARNING: assuming this leaf already exists!
+
+ UCHAR* locateLeaf( int st[3] )
+ {
+ UCHAR* 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 = getChild( node, getChildCount( node, index ) ) ;
+ }
+
+ return node ;
+ }
+
+ UCHAR* locateLeaf( UCHAR* node, int len, int st[3] )
+ {
+ 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 = getChild( node, getChildCount( node, index ) ) ;
+ }
+
+ return node ;
+ }
+ UCHAR* locateLeafCheck( int st[3] )
+ {
+ UCHAR* 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 ( ! hasChild( node, index ) )
+ {
+ return NULL ;
+ }
+ node = getChild( node, getChildCount( node, index ) ) ;
+ }
+
+ return node ;
+ }
+ UCHAR* locateParent( int len, int st[3], int& count )
+ {
+ UCHAR* node = root ;
+ UCHAR* pre = NULL ;
+ int index ;
+ 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 = getChild( node, getChildCount( node, index ) ) ;
+ }
+
+ count = getChildCount( pre, index ) ;
+ return pre ;
+ }
+ UCHAR* locateParent( UCHAR* papa, int len, int st[3], int& count )
+ {
+ UCHAR* node = papa ;
+ UCHAR* pre = NULL ;
+ 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 ) ) ;
+ pre = node ;
+ node = getChild( node, getChildCount( node, index ) ) ;
+ }
+
+ count = getChildCount( pre, index ) ;
+ return pre ;
+ }
+ /************ Operators for internal nodes ************/
+
+ /// Print the node information
+ void printNode( UCHAR* node )
+ {
+ printf("Address: %p ", node ) ;
+ printf("Leaf Mask: ") ;
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ printf( "%d ", isLeaf( node, i ) ) ;
+ }
+ printf("Child Mask: ") ;
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ printf( "%d ", hasChild( node, i ) ) ;
+ }
+ printf("\n") ;
+ }
+
+ /// Get size of an internal node
+ int getSize ( int length )
+ {
+ return INTERNAL_NODE_BYTES + length * 4 ;
+ };
+
+ /// If child index exists
+ int hasChild( UCHAR* node, int index )
+ {
+ return ( node[0] >> index ) & 1 ;
+ };
+
+ /// Test if child is leaf
+ int isLeaf ( UCHAR* node, int index )
+ {
+ return ( node[1] >> index ) & 1 ;
+ };
+
+ /// Get the pointer to child index
+ UCHAR* getChild ( UCHAR* node, int count )
+ {
+ return (( UCHAR ** ) ( node + INTERNAL_NODE_BYTES )) [ count ] ;
+ };
+
+ /// Get total number of children
+ int getNumChildren( UCHAR* node )
+ {
+ return numChildrenTable[ node[0] ] ;
+ };
+
+ /// Get the count of children
+ int getChildCount( UCHAR* node, int index )
+ {
+ return childrenCountTable[ node[0] ][ index ] ;
+ }
+ int getChildIndex( UCHAR* node, int count )
+ {
+ return childrenIndexTable[ node[0] ][ count ] ;
+ }
+ int* getChildCounts( UCHAR* node )
+ {
+ return childrenCountTable[ node[0] ] ;
+ }
+
+ /// Get all children
+ void fillChildren( UCHAR* node, UCHAR* chd[ 8 ], int leaf[ 8 ] )
+ {
+ int count = 0 ;
+ for ( int i = 0 ; i < 8 ; i ++ )
+ {
+ leaf[ i ] = isLeaf( node, i ) ;
+ if ( hasChild( node, i ) )
+ {
+ chd[ i ] = getChild( node, count ) ;
+ count ++ ;
+ }
+ else
+ {
+ chd[ i ] = NULL ;
+ leaf[ i ] = 0 ;
+ }
+ }
+ }
+
+ /// Sets the child pointer
+ void setChild ( UCHAR* node, int count, UCHAR* chd )
+ {
+ (( UCHAR ** ) ( node + INTERNAL_NODE_BYTES )) [ count ] = chd ;
+ }
+ void setInternalChild ( UCHAR* node, int index, int count, UCHAR* chd )
+ {
+ setChild( node, count, chd ) ;
+ node[0] |= ( 1 << index ) ;
+ };
+ void setLeafChild ( UCHAR* node, int index, int count, UCHAR* chd )
+ {
+ setChild( node, count, chd ) ;
+ node[0] |= ( 1 << index ) ;
+ node[1] |= ( 1 << index ) ;
+ };
+
+ /// Add a kid to an existing internal node
+ /// Fix me: can we do this without wasting memory ?
+ /// Fixed: using variable memory
+ UCHAR* addChild( UCHAR* node, int index, UCHAR* chd, int aLeaf )
+ {
+ // Create new internal node
+ int num = getNumChildren( node ) ;
+ UCHAR* rnode = createInternal( num + 1 ) ;
+
+ // Establish children
+ int i ;
+ int count1 = 0, count2 = 0 ;
+ for ( i = 0 ; i < 8 ; i ++ )
+ {
+ if ( i == index )
+ {
+ if ( aLeaf )
+ {
+ setLeafChild( rnode, i, count2, chd ) ;
+ }
+ else
+ {
+ setInternalChild( rnode, i, count2, chd ) ;
+ }
+ count2 ++ ;
+ }
+ else if ( hasChild( node, i ) )
+ {
+ if ( isLeaf( node, i ) )
+ {
+ setLeafChild( rnode, i, count2, getChild( node, count1 ) ) ;
+ }
+ else
+ {
+ setInternalChild( rnode, i, count2, getChild( node, count1 ) ) ;
+ }
+ count1 ++ ;
+ count2 ++ ;
+ }
+ }
+
+ removeInternal( num, node ) ;
+ return rnode ;
+ }
+
+ /// Allocate a node
+ UCHAR* createInternal( int length )
+ {
+ UCHAR* inode = alloc[ length ]->allocate( ) ;
+ inode[0] = inode[1] = 0 ;
+ return inode ;
+ };
+ UCHAR* createLeaf( int length )
+ {
+ if ( length > 3 )
+ {
+ printf("wierd");
+ }
+ UCHAR* lnode = leafalloc[ length ]->allocate( ) ;
+ lnode[0] = lnode[1] = lnode[2] = 0 ;
+
+ return lnode ;
+ };
+
+ void removeInternal ( int num, UCHAR* node )
+ {
+ alloc[ num ]->deallocate( node ) ;
+ }
+
+ void removeLeaf ( int num, UCHAR* leaf )
+ {
+ if ( num > 3 || num < 0 )
+ {
+ printf("wierd");
+ }
+ leafalloc[ num ]->deallocate( leaf ) ;
+ }
+
+ /// Add a leaf (by creating a new par node with the leaf added)
+ UCHAR* addLeafChild ( UCHAR* par, int index, int count, UCHAR* leaf )
+ {
+ int num = getNumChildren( par ) + 1 ;
+ UCHAR* npar = createInternal( num ) ;
+ npar[0] = par[0] ;
+ npar[1] = par[1] ;
+
+ if ( num == 1 )
+ {
+ setLeafChild( npar, index, 0, leaf ) ;
+ }
+ else
+ {
+ int i ;
+ for ( i = 0 ; i < count ; i ++ )
+ {
+ setChild( npar, i, getChild( par, i ) ) ;
+ }
+ setLeafChild( npar, index, count, leaf ) ;
+ for ( i = count + 1 ; i < num ; i ++ )
+ {
+ setChild( npar, i, getChild( par, i - 1 ) ) ;
+ }
+ }
+
+ removeInternal( num-1, par ) ;
+ return npar ;
+ };
+
+ UCHAR* addInternalChild ( UCHAR* par, int index, int count, UCHAR* node )
+ {
+ int num = getNumChildren( par ) + 1 ;
+ UCHAR* npar = createInternal( num ) ;
+ npar[0] = par[0] ;
+ npar[1] = par[1] ;
+
+ if ( num == 1 )
+ {
+ setInternalChild( npar, index, 0, node ) ;
+ }
+ else
+ {
+ int i ;
+ for ( i = 0 ; i < count ; i ++ )
+ {
+ setChild( npar, i, getChild( par, i ) ) ;
+ }
+ setInternalChild( npar, index, count, node ) ;
+ for ( i = count + 1 ; i < num ; i ++ )
+ {
+ setChild( npar, i, getChild( par, i - 1 ) ) ;
+ }
+ }
+
+ removeInternal( num-1, par ) ;
+ return npar ;
+ };
+};
+
+
+
+#endif
diff --git a/intern/dualcon/intern/readme.txt b/intern/dualcon/intern/readme.txt
new file mode 100644
index 0000000..fc88eca
--- /dev/null
+++ b/intern/dualcon/intern/readme.txt
@@ -0,0 +1,112 @@
+PolyMender program for robustly repairing a polygonal model.
+
+Author: Tao Ju (jutao@cs.wustl.edu)
+
+Version: 1.6 (Updated: Oct. 12, 2006)
+
+Platform: Windows
+
+
+I. What's new in v1.6:
+
+
+> Removal of disconnected components
+
+> Topologically manifold dual contouring
+
+> Output signed octree with geometry
+
+
+
+II. Introduction
+
+
+PolyMender is based on the algorithm presented in the paper "Robust Repair of Polygonal Models" (SIGGRAPH 2004). The program reads in a polygonal model (i.e., a bag of polygons) and produces a closed surface that approximates the original model. PolyMender consumes a small amount of time and memory space, and can accurately reproduce the original geometry. PolyMender is suitable for repairing CAD models and gigantic polygonal models. Alternatively, PolyMender can also be used to generate a signed volume from any polygonal models.
+
+
+
+III. How to run
+
+
+The executable package contains three programs:
+
+1. PolyMender, PolyMender-clean
+
+Purpose: repairs general purpose models, such as those created from range scanners. The repaired surface is constructed using Marching Cubes. Consumes minimal memory and time and generates closed, manifold triangular surfaces. The -clean option removes isolated pieces.
+
+2. PolyMender-qd, PolyMender-qd-clean
+
+Purpose: same as PolyMender and PolyMender-clean, but outputs a quad-mesh.
+
+3. PolyMender-dc, PolyMender-dc-clean
+
+Purpose: repairs models containing sharp features, such as CAD models. The repaired surface is constructed using Dual Contouring with a manifold topology, which is capable of reproducing sharp edges and corners. However, more memory is required. Generates closed triangular and quadrilateral surfaces. The -clean option removes isolated pieces.
+
+
+Type the program names (e.g., PolyMender) on the DOS prompt and you will see their usages:
+
+Usage: PolyMender <input_file> <octree_depth> <scale> <output_file>
+
+Example: PolyMender bunny.ply 6 0.9 closedbunny.ply
+
+Description:
+
+<input_file> Polygonal file of format STL (binary only), ASC, or PLY.
+
+<octree_depth> Integer depth of octree. The dimension of the volumetric
+ grid is 2^<octree_depth> on each side.
+
+<scale> Floating point number between 0 and 1 denoting the ratio of
+ the largest dimension of the model over the size of the grid.
+
+<output_file> Output in polygonal format PLY or signed-octree format SOF (or SOG).
+
+
+Additional notes:
+
+1. STL(binary) is preferred input format, since the program does not need to store the model in memory at all. ASC or PLY formats require additional storage of vertices, due to their topology-geometry file structure.
+
+2. The running time and memory consumption of the program depends on several factors: the number of input polygons, the depth of the octree, and the surface area of the model (hence the number of leaf nodes on the octree). To give an idea, processing the David model with 56 million triangles at depth 13 takes 45 minutes using 500 MB RAM (excluding the mem allocated for storing vertices when reading PLY format) on a PC with AMD 1.5Hz CPU.
+
+3. The number of output polygons can be finely controlled using the scale argument. The large the scale, the more polygons are generated, since the model occupies a larger portion of the volume grid.
+
+4. As an alternative of output repaired models, the intermediate signed octree can be generated as a SOF or SOG file. The signed octree can be used for generating signed distance field, extracting isosurfaces, or multiresolution spatial representation of the polygonal model.
+
+
+IV SOF format
+
+SOF (Signed Octree Format) records an octree grid with signes attached to the 8 corners of each leaf node. All leaf nodes appear at the same depth that is specified by the <octree_depth> argument to the program. The tree is recorded in SOF file using pre-order traversal. Here is the structure of a SOF file (binary):
+
+<header>
+
+<node>
+
+<header> is a 4-bytes integer that equals 2 ^ octree_depth. The first byte of a <node> is either 0 (denoting an intermediate node) or 1 (denoting an empty node) or 2 (denoting a leaf node). After the first byte, an intermediate node <node> contains (after the first byte) eight <node> structures for its eight children; an empty node <node> contains one byte of value 0 or 1 denoting if it is inside or outside; and a leaf node contains one byte whose eight bits correspond to the signs at its eight corners (0 for inside and 1 for outside). The order of enumeration of the eight children nodes in an intermediate nodeis the following (expressed in coordinates <x,y,z> ): <0,0,0>,<0,0,1>,<0,1,0>,<0,1,1>,<1,0,0>,<1,0,1>,<1,1,0>,<1,1,1>. The enumeration of the eight corners in a leaf node follows the same order (e.g., the lowest bit records the sign at <0,0,0>).
+
+
+
+V SOG format
+
+SOF (Signed Octree with Geometry) has the same data structure with SOG, with the addition of following features:
+
+1. The file starts with a 128-byte long header. Currently, the header begins with the string "SOG.Format 1.0" followed by 3 floats representing the lower-left-near corner of the octree follwed by 1 float denoting the length of the octree (in one direction). The locations and lengths are in the input model's coordinate space. The rest of the header is left empty.
+
+2. Each leaf node has additioanl three floats {x,y,z} (following the signs) denoting the geometric location of a feature vertex within the cell.
+
+
+
+VI Test data
+
+Three models are included in the testmodels package. (Suggested arguments are provided in the parathesis).
+
+bunny.ply (octree depth: 7, scale: 0.9)
+
+- The Stanford Bunny (containing big holes at the bottom)
+
+horse.stl (octree depth: 8, scale: 0.9)
+
+- The horse model with 1/3 of all polygons removed and vertices randomly perturbed.
+
+mechanic.asc (octree depth: 6, scale: 0.9)
+
+- A mechanic part with hanging triangles
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 848779c..9e4bc25 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -699,3 +699,33 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col = split.column()
col.prop(md, "width", slider=True)
col.prop(md, "narrowness", slider=True)
+
+
+ def REMESH(self, layout, ob, md):
+ layout.prop(md, "mode")
+
+ layout.prop(md, "octree_depth")
+ layout.prop(md, "scale")
+
+ layout.prop(md, "remove_disconnected_pieces")
+ row = layout.row()
+ row.prop(md, "threshold")
+ row.active = md.remove_disconnected_pieces
+
+ #layout.prop(md, "dual_contouring")
+ #row = layout.row()
+ #row.prop(md, "hermite_param")
+ #row.active = md.dual_contouring
+
+ layout.prop(md, "manifold")
+
+
+def register():
+ bpy.utils.register_module(__name__)
+
+
+def unregister():
+ bpy.utils.unregister_module(__name__)
+
+if __name__ == "__main__":
+ register()
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index de84f69..e468291 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -73,6 +73,7 @@ typedef enum ModifierType {
/* placeholder, keep this so durian files load in
* trunk with the correct modifier once its merged */
eModifierType_Warp,
+ eModifierType_Remesh,
NUM_MODIFIER_TYPES
} ModifierType;

@@ -733,5 +734,35 @@ typedef struct ScrewModifierData {
#define MOD_SCREW_OBJECT_OFFSET (1<<2)
// #define MOD_SCREW_OBJECT_ANGLE (1<<4)

+typedef enum RemeshModifierFlags {
+ MOD_REMESH_FLOOD_FILL = 1,
+ MOD_REMESH_MANIFOLD = 2,
+} RemeshModifierFlags;
+
+typedef enum RemeshModifierMode {
+ MOD_REMESH_CENTROID,
+ MOD_REMESH_MASS_POINT,
+ MOD_REMESH_SHARP_FEATURES,
+} RemeshModifierMode;
+
+typedef struct RemeshModifierData {
+ ModifierData modifier;
+
+ /* floodfill option, controls how small components can be
+ before they are removed */
+ float threshold;
+
+ /* ratio between size of model and grid */
+ float scale;
+
+ float hermite_num;
+
+ /* octree depth */
+ char depth;
+
+ char flag;
+ char mode;
+ char pad;
+} RemeshModifierData;

#endif
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 140a4b4..b6980e5 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -64,6 +64,7 @@ EnumPropertyItem modifier_type_items[] ={
{eModifierType_Mask, "MASK", ICON_MOD_MASK, "Mask", ""},
{eModifierType_Mirror, "MIRROR", ICON_MOD_MIRROR, "Mirror", ""},
{eModifierType_Multires, "MULTIRES", ICON_MOD_MULTIRES, "Multiresolution", ""},
+ {eModifierType_Remesh, "REMESH", ICON_MOD_DECIM /* TODO */, "Remesh", ""},
{eModifierType_Screw, "SCREW", ICON_MOD_SCREW, "Screw", ""},
{eModifierType_Solidify, "SOLIDIFY", ICON_MOD_SOLIDIFY, "Solidify", ""},
{eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""},
@@ -180,6 +181,8 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_SolidifyModifier;
case eModifierType_Screw:
return &RNA_ScrewModifier;
+ case eModifierType_Remesh:
+ return &RNA_RemeshModifier;
default:
return &RNA_Modifier;
}
@@ -2281,6 +2284,67 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");*/
}

+static void rna_def_modifier_remesh(BlenderRNA *brna)
+{
+ static EnumPropertyItem mode_items[]= {
+ {MOD_REMESH_CENTROID, "BLOCKS", 0, "Blocks", ""},
+ {MOD_REMESH_MASS_POINT, "SMOOTH", 0, "Smooth", ""},
+ {MOD_REMESH_SHARP_FEATURES, "SHARP", 0, "Sharp", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "RemeshModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Remesh Modifier", "Revolve edges");
+ RNA_def_struct_sdna(srna, "RemeshModifierData");
+ /* TODO: RNA_def_struct_ui_icon(srna, ICON_MOD_REMESH); */
+
+ prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_range(prop, 0, 0.999, 0.01, 3);
+ RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_ui_text(prop, "Scale", "The ratio of the largest dimension of the model over the size of the grid.");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
+ RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_ui_text(prop, "Threshold", "Minimum size of components to preserve, as a ratio of the number of polygons in the largest component.");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "octree_depth", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "depth");
+ RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_ui_text(prop, "Octree Depth", "Resolution of the octree; higher values give finer details.");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /*prop= RNA_def_property(srna, "dual_contouring", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_REMESH_HERMITE);
+ RNA_def_property_ui_text(prop, "Dual Contouring", "Use dual contouring for reproducing sharp features.");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");*/
+
+ prop= RNA_def_property(srna, "hermite_param", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "hermite_num");
+ RNA_def_property_ui_range(prop, 0, 2, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Hermite Param", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "manifold", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_REMESH_MANIFOLD);
+ RNA_def_property_ui_text(prop, "Manifold", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "remove_disconnected_pieces", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_REMESH_FLOOD_FILL);
+ RNA_def_property_ui_text(prop, "Remove Disconnected Pieces", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
void RNA_def_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2377,6 +2441,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_smoke(brna);
rna_def_modifier_solidify(brna);
rna_def_modifier_screw(brna);
+ rna_def_modifier_remesh(brna);
}

#endif
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index c610a2f..5950623 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
../render/extern/include
../../../intern/guardedalloc
../../../intern/elbeem/extern
+ ../../../intern/dualcon
${ZLIB_INCLUDE_DIRS}
)

@@ -62,6 +63,7 @@ set(SRC
intern/MOD_none.c
intern/MOD_particleinstance.c
intern/MOD_particlesystem.c
+ intern/MOD_remesh.c
intern/MOD_screw.c
intern/MOD_shapekey.c
intern/MOD_shrinkwrap.c
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 8486e2b..efc422e 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -71,6 +71,7 @@ extern ModifierTypeInfo modifierType_Smoke;
extern ModifierTypeInfo modifierType_ShapeKey;
extern ModifierTypeInfo modifierType_Solidify;
extern ModifierTypeInfo modifierType_Screw;
+extern ModifierTypeInfo modifierType_Remesh;

/* MOD_util.c */
void modifier_type_init(ModifierTypeInfo *types[]);
diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c
new file mode 100644
index 0000000..ac9d6c5
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_remesh.c
@@ -0,0 +1,172 @@
+/*
+* $Id$
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2011 by Nicholas Bishop.
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+/** \file blender/modifiers/intern/MOD_remesh.c
+ * \ingroup modifiers
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_DerivedMesh.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+#include "MOD_modifiertypes.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dualcon.h"
+
+static void initData(ModifierData *md)
+{
+ RemeshModifierData *rmd = (RemeshModifierData*) md;
+
+ rmd->scale = 0.9;
+ rmd->depth = 4;
+ rmd->hermite_num = 1;
+ rmd->flag = MOD_REMESH_FLOOD_FILL | MOD_REMESH_MANIFOLD;
+ rmd->mode = MOD_REMESH_SHARP_FEATURES;
+ rmd->threshold = 1;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ RemeshModifierData *rmd = (RemeshModifierData*) md;
+ RemeshModifierData *trmd = (RemeshModifierData*) target;
+
+ trmd->scale = rmd->scale;
+ trmd->depth = rmd->depth;
+}
+
+void init_dualcon_mesh(DualConMesh *mesh, DerivedMesh *dm)
+{
+ mesh->co = (void*)dm->getVertArray(dm);
+ mesh->co_stride = sizeof(MVert);
+ mesh->totco = dm->getNumVerts(dm);
+
+ mesh->faces = (void*)dm->getFaceArray(dm);
+ mesh->face_stride = sizeof(MFace);
+ mesh->totface = dm->getNumFaces(dm);
+}
+
+DualConMesh *dualcon_create_mesh(int totco, int totface)
+{
+ DualConMesh *mesh;
+
+ /* TODO: padding for now, but need better way to deal with ngons */
+ totface *= 2;
+
+ if(!(mesh = MEM_callocN(sizeof(DualConMesh), "DualConMesh output")))
+ return NULL;
+
+ if(!(mesh->dm = CDDM_new(totco, 0, totface)))
+ return NULL;
+
+ init_dualcon_mesh(mesh, mesh->dm);
+
+ return mesh;
+}
+
+static DerivedMesh *applyModifier(ModifierData *md,
+ Object *UNUSED(ob),
+ DerivedMesh *dm,
+ int UNUSED(useRenderParams),
+ int UNUSED(isFinalCalc))
+{
+ RemeshModifierData *rmd;
+ DualConMesh input, *output;
+ DerivedMesh *result;
+ DualConFlags flags = 0;
+ DualConMode mode;
+
+ rmd = (RemeshModifierData*)md;
+
+ memset(&input, 0, sizeof(input));
+ init_dualcon_mesh(&input, dm);
+ dm->getMinMax(dm, input.min, input.max);
+
+ if(rmd->flag & MOD_REMESH_FLOOD_FILL)
+ flags |= DUALCON_FLOOD_FILL;
+ if(rmd->flag & MOD_REMESH_MANIFOLD)
+ flags |= DUALCON_MANIFOLD;
+
+ switch(rmd->mode) {
+ case MOD_REMESH_CENTROID:
+ mode = DUALCON_CENTROID;
+ break;
+ case MOD_REMESH_MASS_POINT:
+ mode = DUALCON_MASS_POINT;
+ break;
+ case MOD_REMESH_SHARP_FEATURES:
+ mode = DUALCON_SHARP_FEATURES;
+ break;
+ }
+
+ output = dualcon(&input, dualcon_create_mesh,
+ flags,
+ mode,
+ rmd->threshold,
+ rmd->hermite_num,
+ rmd->scale,
+ rmd->depth);
+ result = output->dm;
+ CDDM_lower_num_faces(result, output->curface);
+ MEM_freeN(output);
+
+ CDDM_calc_edges(result);
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+ModifierTypeInfo modifierType_Remesh = {
+ /* name */ "Remesh",
+ /* structName */ "RemeshModifierData",
+ /* structSize */ sizeof(RemeshModifierData),
+ /* type */ eModifierTypeType_Nonconstructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode,
+ /* copyData */ copyData,
+ /* deformVerts */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ NULL,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 8c94e6f..ef46e6f 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -189,5 +189,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(ShapeKey);
INIT_TYPE(Solidify);
INIT_TYPE(Screw);
+ INIT_TYPE(Remesh);
#undef INIT_TYPE
}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index f13f3f7..69827c6 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -750,6 +750,7 @@ endif()
bf_blenfont
bf_intern_audaspace
bf_intern_mikktspace
+ bf_intern_dualcon
)

if(WITH_BINRELOC)
  1. diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
  2. index 33bf9bb..3245d90 100644
  3. --- a/intern/CMakeLists.txt
  4. +++ b/intern/CMakeLists.txt
  5. @@ -34,6 +34,7 @@ add_subdirectory(iksolver)
  6.  add_subdirectory(opennl)
  7.  add_subdirectory(smoke)
  8.  add_subdirectory(mikktspace)
  9. +add_subdirectory(dualcon)
  10.  
  11.  if(WITH_MOD_FLUID)
  12.         add_subdirectory(elbeem)
  13. diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt
  14. new file mode 100644
  15. index 0000000..38251f3
  16. --- /dev/null
  17. +++ b/intern/dualcon/CMakeLists.txt
  18. @@ -0,0 +1,48 @@
  19. +# $Id$
  20. +# ***** BEGIN GPL LICENSE BLOCK *****
  21. +#
  22. +# This program is free software; you can redistribute it and/or
  23. +# modify it under the terms of the GNU General Public License
  24. +# as published by the Free Software Foundation; either version 2
  25. +# of the License, or (at your option) any later version.
  26. +#
  27. +# This program is distributed in the hope that it will be useful,
  28. +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  29. +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30. +# GNU General Public License for more details.
  31. +#
  32. +# You should have received a copy of the GNU General Public License
  33. +# along with this program; if not, write to the Free Software Foundation,
  34. +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  35. +#
  36. +# ***** END GPL LICENSE BLOCK *****
  37. +
  38. +set(INC
  39. +       .
  40. +       intern
  41. +)
  42. +
  43. +set(SRC
  44. +       intern/eigen.cpp
  45. +       intern/manifold_table.cpp
  46. +       intern/marching_cubes_table.cpp
  47. +       intern/octree.cpp
  48. +       
  49. +       intern/cubes.h
  50. +       intern/eigen.h
  51. +       intern/GeoCommon.h
  52. +       intern/IntegerGrid.h
  53. +       intern/manifold_table.h
  54. +       intern/marching_cubes_table.h
  55. +       intern/MemoryAllocator.h
  56. +       intern/ModelReader.h
  57. +       intern/octree.h
  58. +       intern/Projections.h
  59. +       intern/Queue.h
  60. +
  61. +       intern/dualcon_c_api.cpp
  62. +       dualcon.h
  63. +)
  64. +
  65. +blender_add_lib(bf_intern_dualcon "${SRC}" "${INC}")
  66. +
  67. diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h
  68. new file mode 100644
  69. index 0000000..3a8c486
  70. --- /dev/null
  71. +++ b/intern/dualcon/dualcon.h
  72. @@ -0,0 +1,62 @@
  73. +#ifndef DUALCON_H
  74. +#define DUALCON_H
  75. +
  76. +#ifdef __cplusplus
  77. +extern "C" {
  78. +#endif
  79. +
  80. +typedef float (*DualConCo)[3];
  81. +typedef unsigned int (*DualConFaces)[4];
  82. +struct DerivedMesh;
  83. +
  84. +typedef struct {
  85. +       DualConCo co;
  86. +       int co_stride;
  87. +       int totco;
  88. +       
  89. +       DualConFaces faces;
  90. +       int face_stride;
  91. +       int totface;
  92. +       
  93. +       /* input only */
  94. +       float min[3], max[3];
  95. +
  96. +       /* output only */
  97. +       int curco, curface;
  98. +       struct DerivedMesh *dm;
  99. +} DualConMesh;
  100. +
  101. +/* only used internally */
  102. +void dualcon_mesh_add_co(DualConMesh *mesh, const float v[3]);
  103. +void dualcon_mesh_add_polygon(DualConMesh *mesh, int totndx,
  104. +                             const int *ndx, int flip);
  105. +
  106. +/* callback for allocating memory for output */
  107. +typedef DualConMesh *(*DualConCreateMesh)(int totco, int totface);
  108. +
  109. +typedef enum {
  110. +       DUALCON_HERMITE = 1,
  111. +       DUALCON_FLOOD_FILL = 2,
  112. +       DUALCON_MANIFOLD = 4,
  113. +} DualConFlags;
  114. +
  115. +typedef enum {
  116. +       DUALCON_CENTROID,
  117. +       DUALCON_MASS_POINT,
  118. +       DUALCON_SHARP_FEATURES,
  119. +} DualConMode;
  120. +
  121. +DualConMesh *dualcon(const DualConMesh *input_mesh,
  122. +                    DualConCreateMesh create_mesh,
  123. +                    DualConFlags flags,
  124. +                    DualConMode mode,
  125. +                    float threshold,
  126. +                    float hermite_num,
  127. +                    float scale,
  128. +                    int depth);
  129. +
  130. +#ifdef __cplusplus
  131. +}
  132. +#endif
  133. +
  134. +#endif
  135. diff --git a/intern/dualcon/intern/GeoCommon.h b/intern/dualcon/intern/GeoCommon.h
  136. new file mode 100644
  137. index 0000000..1d3831d
  138. --- /dev/null
  139. +++ b/intern/dualcon/intern/GeoCommon.h
  140. @@ -0,0 +1,47 @@
  141. +#ifndef GEOCOMMON_H
  142. +#define GEOCOMMON_H
  143. +
  144. +#define UCHAR unsigned char
  145. +#define USHORT unsigned short
  146. +
  147. +#define USE_MINIMIZER
  148. +
  149. +/**
  150. + * Structure definitions for points and triangles.
  151. + *
  152. + * @author Tao Ju
  153. + */
  154. +
  155. +
  156. +// 3d point with integer coordinates
  157. +typedef struct
  158. +{
  159. +       int x, y, z;
  160. +} Point3i;
  161. +
  162. +typedef struct
  163. +{
  164. +       Point3i begin;
  165. +       Point3i end;
  166. +} BoundingBox;
  167. +
  168. +// triangle that points to three vertices
  169. +typedef struct
  170. +{
  171. +       float vt[3][3] ;
  172. +} Triangle;
  173. +
  174. +// 3d point with float coordinates
  175. +typedef struct
  176. +{
  177. +       float x, y, z;
  178. +} Point3f;
  179. +
  180. +typedef struct
  181. +{
  182. +       Point3f begin;
  183. +       Point3f end;
  184. +} BoundingBoxf;
  185. +
  186. +
  187. +#endif
  188. \ No newline at end of file
  189. diff --git a/intern/dualcon/intern/IntegerGrid.h b/intern/dualcon/intern/IntegerGrid.h
  190. new file mode 100644
  191. index 0000000..f3e43de
  192. --- /dev/null
  193. +++ b/intern/dualcon/intern/IntegerGrid.h
  194. @@ -0,0 +1,751 @@
  195. +#ifndef INTEGERGRID_H
  196. +#define INTEGERGRID_H
  197. +
  198. +#include <stdio.h>
  199. +#include <stdlib.h>
  200. +
  201. +
  202. +#define GRID_DIMENSION 20
  203. +
  204. +#define LONG _int64
  205. +
  206. +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}} ;
  207. +const int centmap[3][3][3][2] =
  208. +{{{{0,0},{0,1},{1,1}},{{0,2},{0,3},{1,3}},{{2,2},{2,3},{3,3}}},
  209. +{{{0,4},{0,5},{1,5}},{{0,6},{0,7},{1,7}},{{2,6},{2,7},{3,7}}},
  210. +{{{4,4},{4,5},{5,5}},{{4,6},{4,7},{5,7}},{{6,6},{6,7},{7,7}}}} ;
  211. +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}};
  212. +
  213. +/**
  214. + * Structure for the projections inheritable from parent
  215. + */
  216. +struct InheritableProjections
  217. +{
  218. +       /// Projections of the triangle vertices
  219. +       LONG trigProj[13][2] ;
  220. +
  221. +       /// End points along each axis
  222. +       //int cubeEnds[13][2] ;
  223. +
  224. +       /// Error range on each axis
  225. +       /// LONG errorProj[13];
  226. +};
  227. +
  228. +
  229. +/**
  230. + * Class for projections of cube / triangle vertices on the separating axes
  231. + */
  232. +class Projections
  233. +{
  234. +public:
  235. +       /// Inheritable portion
  236. +       InheritableProjections* inherit ;
  237. +
  238. +       /// Projections of the cube vertices
  239. +       LONG cubeProj[13][6] ;
  240. +
  241. +public:
  242. +
  243. +       /**
  244. +        * Default constructor
  245. +        */
  246. +       Projections( )
  247. +       {
  248. +       };
  249. +
  250. +       /**
  251. +        * Construction
  252. +        * from a cube (axes aligned) and triangle
  253. +        */
  254. +       Projections( LONG cube[2][3], LONG trig[3][3], LONG error )
  255. +       {
  256. +               int i, j ;
  257. +               inherit = new InheritableProjections ;
  258. +
  259. +               /// Create axes
  260. +               LONG axes[13][3] ;
  261. +
  262. +               // Cube faces
  263. +               axes[0][0] = 1 ;
  264. +               axes[0][1] = 0 ;
  265. +               axes[0][2] = 0 ;
  266. +
  267. +               axes[1][0] = 0 ;
  268. +               axes[1][1] = 1 ;
  269. +               axes[1][2] = 0 ;
  270. +
  271. +               axes[2][0] = 0 ;
  272. +               axes[2][1] = 0 ;
  273. +               axes[2][2] = 1 ;
  274. +
  275. +               // Triangle face
  276. +               LONG trigedge[3][3] ;
  277. +               for ( i = 0 ; i < 3 ; i ++ )
  278. +               {
  279. +                       for ( j = 0 ; j < 3 ; j ++ )
  280. +                       {
  281. +                               trigedge[i][j] = trig[(i+1)%3][j] - trig[i][j] ;
  282. +                       }
  283. +               }
  284. +               crossProduct( trigedge[0], trigedge[1], axes[3] ) ;
  285. +
  286. +               // Face edges and triangle edges
  287. +               int ct = 4 ;
  288. +               for ( i = 0 ; i < 3 ; i ++ )
  289. +                       for ( j = 0 ; j < 3 ; j ++ )
  290. +                       {
  291. +                               crossProduct( axes[i], trigedge[j], axes[ct] ) ;
  292. +                               ct ++ ;
  293. +                       }              
  294. +
  295. +               /// Generate projections
  296. +               LONG cubeedge[3][3] ;
  297. +               for ( i = 0 ; i < 3 ; i ++ )
  298. +               {
  299. +                       for ( j = 0 ; j < 3 ; j ++ )
  300. +                       {
  301. +                               cubeedge[i][j] = 0 ;
  302. +                       }
  303. +                       cubeedge[i][i] = cube[1][i] - cube[0][i] ;
  304. +               }
  305. +
  306. +               for ( j = 0 ; j < 13 ; j ++ )
  307. +               {
  308. +                       // Origin
  309. +                       cubeProj[j][0] = dotProduct( axes[j], cube[0] ) ;
  310. +
  311. +                       // 3 direction vectors
  312. +                       for ( i = 1 ; i < 4 ; i ++ )
  313. +                       {
  314. +                               cubeProj[j][i] = dotProduct( axes[j], cubeedge[i-1] ) ;
  315. +                       }
  316. +
  317. +                       // Offsets of 2 ends of cube projection
  318. +                       LONG max = 0 ;
  319. +                       LONG min = 0 ;
  320. +                       int maxind = 0, minind = 0 ;
  321. +                       for ( i = 1 ; i < 8 ; i ++ )
  322. +                       {
  323. +                               LONG proj = vertmap[i][0] * cubeProj[j][1] + vertmap[i][1] * cubeProj[j][2] + vertmap[i][2] * cubeProj[j][3] ;
  324. +                               if ( proj > max )
  325. +                               {
  326. +                                       max = proj ;
  327. +                                       maxind = i ;
  328. +                               }
  329. +                               if ( proj < min )
  330. +                               {
  331. +                                       min = proj ;
  332. +                                       minind = i ;
  333. +                               }
  334. +                       }
  335. +                       cubeProj[j][4] = min ;
  336. +                       cubeProj[j][5] = max ;
  337. +
  338. +               }
  339. +
  340. +               for ( j = 0 ; j < 13 ; j ++ )
  341. +               {
  342. +                       inherit->trigProj[j][0] = dotProduct( axes[j], trig[0] ) ;
  343. +                       inherit->trigProj[j][1] = inherit->trigProj[j][0] ;
  344. +
  345. +                       for ( i = 1 ; i < 3 ; i ++ )
  346. +                       {
  347. +                               LONG proj = dotProduct( axes[j], trig[i] ) ;
  348. +                               if ( proj < inherit->trigProj[j][0] )
  349. +                               {
  350. +                                       inherit->trigProj[j][0] = proj ;
  351. +                               }
  352. +                               if ( proj > inherit->trigProj[j][1] )
  353. +                               {
  354. +                                       inherit->trigProj[j][1] = proj ;
  355. +                               }
  356. +                       }
  357. +               }
  358. +
  359. +               // Get ends of projections
  360. +               /*
  361. +               for ( i = 0 ; i < 13 ; i ++ )
  362. +               {
  363. +                       int maxind = 0, minind = 0 ;
  364. +                       LONG max = cubeProj[i][0] ;
  365. +                       LONG min = cubeProj[i][0] ;
  366. +                       for ( j = 1 ; j < 8 ; j ++ )
  367. +                       {
  368. +                               LONG proj = cubeProj[i][0] + vertmap[j][0] * cubeProj[i][1] + vertmap[j][1] * cubeProj[i][2] + vertmap[j][2] * cubeProj[i][3] ;
  369. +                               if ( proj > max )
  370. +                               {
  371. +                                       max = proj ;
  372. +                                       maxind = j ;
  373. +                               }
  374. +                               if ( proj < min )
  375. +                               {
  376. +                                       min = proj ;
  377. +                                       minind = j ;
  378. +                               }
  379. +                       }
  380. +
  381. +                       inherit->cubeEnds[i][0] = minind ;
  382. +                       inherit->cubeEnds[i][1] = maxind ;
  383. +               }
  384. +               */
  385. +
  386. +               // exit(0) ;
  387. +       }
  388. +
  389. +       /**
  390. +        * Construction
  391. +        * from a parent Projections object and the index of the children
  392. +        */
  393. +       Projections ( Projections* parent )
  394. +       {
  395. +               // Copy inheritable projections
  396. +               this->inherit = parent->inherit ;
  397. +
  398. +               // Shrink cube projections
  399. +               for ( int i = 0 ; i < 13 ; i ++ )
  400. +               {
  401. +                       cubeProj[i][0] = parent->cubeProj[i][0] ;
  402. +                       for ( int j = 1 ; j < 6 ; j ++ )
  403. +                       {
  404. +                               cubeProj[i][j] = parent->cubeProj[i][j] >> 1 ;
  405. +                       }
  406. +               }
  407. +       };
  408. +
  409. +       /**
  410. +        * Get projections for sub-cubes (simple axes)
  411. +        */
  412. +       void getSubProjectionsSimple( Projections* p[8] )
  413. +       {
  414. +               // Process the axes cooresponding to the triangle's normal
  415. +               int ind = 3 ;
  416. +               int len = cubeProj[ 0 ][ 1 ] >> 1 ;
  417. +               int trigproj[3] = { cubeProj[ ind ][ 1 ] >> 1, cubeProj[ ind ][ 2 ] >> 1, cubeProj[ ind ][ 3 ] >> 1 } ;
  418. +
  419. +               int ct = 0 ;
  420. +               for ( int i = 0 ; i < 2 ; i ++ )
  421. +                       for ( int j = 0 ; j < 2 ; j ++ )
  422. +                               for ( int k = 0 ; k < 2 ; k ++ )
  423. +                               {
  424. +                                       p[ct] = new Projections( ) ;
  425. +
  426. +                                       p[ct]->cubeProj[ 0 ][ 0 ] = cubeProj[ 0 ][ 0 ] + i * len ;
  427. +                                       p[ct]->cubeProj[ 1 ][ 0 ] = cubeProj[ 1 ][ 0 ] + j * len ;
  428. +                                       p[ct]->cubeProj[ 2 ][ 0 ] = cubeProj[ 2 ][ 0 ] + k * len ;
  429. +                                       p[ct]->cubeProj[ 0 ][ 1 ] = len ;
  430. +
  431. +                                       for ( int m = 1 ; m < 3 ; m ++ )
  432. +                                       {
  433. +                                               p[ct]->cubeProj[ ind ][ m ] = trigproj[ m - 1 ] ;
  434. +                                       }
  435. +                                       p[ct]->cubeProj[ ind ][ 0 ] = cubeProj[ ind ][0] + i * trigproj[0] + j * trigproj[1] + k * trigproj[2] ;
  436. +
  437. +                                       ct ++ ;
  438. +                               }
  439. +       }
  440. +
  441. +       /**
  442. +        * Shifting a cube to a new origin
  443. +        */
  444. +       void shift ( int off[3] )
  445. +       {
  446. +               for ( int i = 0 ; i < 13 ; i ++ )
  447. +               {
  448. +                       cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
  449. +               }
  450. +       }
  451. +
  452. +       void shiftNoPrimary ( int off[3] )
  453. +       {
  454. +               for ( int i = 3 ; i < 13 ; i ++ )
  455. +               {
  456. +                       cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
  457. +               }
  458. +       }
  459. +
  460. +       /**
  461. +        * Method to test intersection of the triangle and the cube
  462. +        */
  463. +       int isIntersecting ( )
  464. +       {
  465. +               for ( int i = 0 ; i < 13 ; i ++ )
  466. +               {
  467. +                       /*
  468. +                       LONG proj0 = cubeProj[i][0] +
  469. +                               vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
  470. +                               vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
  471. +                               vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
  472. +                       LONG proj1 = cubeProj[i][0] +
  473. +                               vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
  474. +                               vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
  475. +                               vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
  476. +                       */
  477. +
  478. +                       LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
  479. +                       LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
  480. +
  481. +                       if ( proj0 > inherit->trigProj[i][1] ||
  482. +                                proj1 < inherit->trigProj[i][0] )
  483. +                       {
  484. +                               return 0 ;
  485. +                       }
  486. +               }
  487. +              
  488. +               return 1 ;
  489. +       };
  490. +
  491. +       int isIntersectingNoPrimary ( )
  492. +       {
  493. +               for ( int i = 3 ; i < 13 ; i ++ )
  494. +               {
  495. +                       /*
  496. +                       LONG proj0 = cubeProj[i][0] +
  497. +                               vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
  498. +                               vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
  499. +                               vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
  500. +                       LONG proj1 = cubeProj[i][0] +
  501. +                               vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
  502. +                               vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
  503. +                               vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
  504. +                       */
  505. +
  506. +                       LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
  507. +                       LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
  508. +
  509. +                       if ( proj0 > inherit->trigProj[i][1] ||
  510. +                                proj1 < inherit->trigProj[i][0] )
  511. +                       {
  512. +                               return 0 ;
  513. +                       }
  514. +               }
  515. +              
  516. +               return 1 ;
  517. +       };     
  518. +       
  519. +       /**
  520. +        * Method to test intersection of the triangle and one edge
  521. +        */
  522. +       int isIntersecting ( int edgeInd )
  523. +       {
  524. +               for ( int i = 0 ; i < 13 ; i ++ )
  525. +               {
  526. +                      
  527. +                       LONG proj0 = cubeProj[i][0] +
  528. +                               vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
  529. +                               vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
  530. +                               vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
  531. +                       LONG proj1 = cubeProj[i][0] +
  532. +                               vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
  533. +                               vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
  534. +                               vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
  535. +
  536. +
  537. +                       if ( proj0 < proj1 )
  538. +                       {
  539. +                               if ( proj0 > inherit->trigProj[i][1] ||
  540. +                                        proj1 < inherit->trigProj[i][0] )
  541. +                               {
  542. +                                       return 0 ;
  543. +                               }
  544. +                       }
  545. +                       else
  546. +                       {
  547. +                               if ( proj1 > inherit->trigProj[i][1] ||
  548. +                                        proj0 < inherit->trigProj[i][0] )
  549. +                               {
  550. +                                       return 0 ;
  551. +                               }
  552. +                       }
  553. +               }
  554. +              
  555. +               // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] )  ;
  556. +               return 1 ;
  557. +       };
  558. +
  559. +       int isIntersectingPrimary ( int edgeInd )
  560. +       {
  561. +               for ( int i = 0 ; i < 13 ; i ++ )
  562. +               {
  563. +                      
  564. +                       LONG proj0 = cubeProj[i][0] ;
  565. +                       LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
  566. +
  567. +                       if ( proj0 < proj1 )
  568. +                       {
  569. +                               if ( proj0 > inherit->trigProj[i][1] ||
  570. +                                        proj1 < inherit->trigProj[i][0] )
  571. +                               {
  572. +                                       return 0 ;
  573. +                               }
  574. +                       }
  575. +                       else
  576. +                       {
  577. +                               if ( proj1 > inherit->trigProj[i][1] ||
  578. +                                        proj0 < inherit->trigProj[i][0] )
  579. +                               {
  580. +                                       return 0 ;
  581. +                               }
  582. +                       }
  583. +
  584. +               }
  585. +              
  586. +               // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] )  ;
  587. +               return 1 ;
  588. +       };
  589. +
  590. +       float getIntersection ( int edgeInd )
  591. +       {
  592. +               int i = 3 ;
  593. +
  594. +               LONG proj0 = cubeProj[i][0] +
  595. +                       vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
  596. +                       vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
  597. +                       vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
  598. +               LONG proj1 = cubeProj[i][0] +
  599. +                       vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
  600. +                       vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
  601. +                       vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
  602. +               LONG proj2 = inherit->trigProj[i][1] ;
  603. +
  604. +               double alpha = (double)( proj2 - proj0 ) / (double)( proj1 - proj0 ) ;
  605. +               if ( alpha < 0 )
  606. +               {
  607. +                       alpha = 0.5 ;
  608. +               }
  609. +               else if ( alpha > 1 )
  610. +               {
  611. +                       alpha = 0.5 ;
  612. +               }
  613. +
  614. +               return (float)alpha ;
  615. +       };
  616. +
  617. +       float getIntersectionPrimary ( int edgeInd )
  618. +       {
  619. +               int i = 3 ;
  620. +              
  621. +               LONG proj0 = cubeProj[i][0] ;
  622. +               LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
  623. +               LONG proj2 = inherit->trigProj[i][1] ;
  624. +
  625. +               double alpha = (double)( proj2 - proj0 ) / (double)( proj1 - proj0 ) ;
  626. +               if ( alpha < 0 )
  627. +               {
  628. +                       alpha = 0.5 ;
  629. +               }
  630. +               else if ( alpha > 1 )
  631. +               {
  632. +                       alpha = 0.5 ;
  633. +               }
  634. +
  635. +               return (float)alpha ;
  636. +       };
  637. +
  638. +       /**
  639. +        * Method to perform cross-product
  640. +        */
  641. +       void crossProduct ( LONG a[3], LONG b[3], LONG res[3] )
  642. +       {
  643. +               res[0] = a[1] * b[2] - a[2] * b[1] ;
  644. +               res[1] = a[2] * b[0] - a[0] * b[2] ;
  645. +               res[2] = a[0] * b[1] - a[1] * b[0] ;
  646. +       }
  647. +
  648. +       /**
  649. +        * Method to perform dot product
  650. +        */
  651. +       LONG dotProduct ( LONG a[3], LONG b[3] )
  652. +       {
  653. +               return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ;
  654. +       }
  655. +
  656. +};
  657. +
  658. +/**
  659. + * Class for projections of cube / triangle vertices on the separating axes
  660. + */
  661. +class Projections2
  662. +{
  663. +public:
  664. +       /// Projections of the cube vertices
  665. +       LONG cubeProj[13][8] ;
  666. +
  667. +       /// Projections of the triangle vertices
  668. +       LONG trigProj[13][3] ;
  669. +
  670. +       /// Min max indices
  671. +       int cubeEnds[13][2] ;
  672. +       int trigEnds[13][2] ;
  673. +
  674. +public:
  675. +
  676. +       /**
  677. +        * Default construction
  678. +        */
  679. +       Projections2 (  )
  680. +       {
  681. +       };
  682. +
  683. +       /**
  684. +        * Construction
  685. +        * from a cube (axes aligned) and triangle
  686. +        */
  687. +       Projections2 ( LONG cube[2][3], LONG trig[3][3] )
  688. +       {
  689. +               int i, j ;
  690. +
  691. +               /// Create axes
  692. +               LONG axes[13][3] ;
  693. +
  694. +               // Cube faces
  695. +               axes[0][0] = 1 ;
  696. +               axes[0][1] = 0 ;
  697. +               axes[0][2] = 0 ;
  698. +
  699. +               axes[1][0] = 0 ;
  700. +               axes[1][1] = 1 ;
  701. +               axes[1][2] = 0 ;
  702. +
  703. +               axes[2][0] = 0 ;
  704. +               axes[2][1] = 0 ;
  705. +               axes[2][2] = 1 ;
  706. +
  707. +               // Triangle face
  708. +               LONG trigedge[3][3] ;
  709. +               for ( i = 0 ; i < 3 ; i ++ )
  710. +               {
  711. +                       for ( j = 0 ; j < 3 ; j ++ )
  712. +                       {
  713. +                               trigedge[i][j] = trig[(i+1)%3][j] - trig[i][j] ;
  714. +                       }
  715. +               }
  716. +               crossProduct( trigedge[0], trigedge[1], axes[3] ) ;
  717. +
  718. +               // Face edges and triangle edges
  719. +               int ct = 4 ;
  720. +               for ( i = 0 ; i < 3 ; i ++ )
  721. +                       for ( j = 0 ; j < 3 ; j ++ )
  722. +                       {
  723. +                               crossProduct( axes[i], trigedge[j], axes[ct] ) ;
  724. +                               ct ++ ;
  725. +                       }
  726. +              
  727. +
  728. +               /// Generate projections
  729. +               LONG theCube[8][3] ;
  730. +               for ( i = 0 ; i < 8 ; i ++ )
  731. +                       for ( j = 0 ; j < 3 ; j ++ )
  732. +                       {
  733. +                               theCube[i][j] = cube[vertmap[i][j]][j] ;
  734. +                       }
  735. +
  736. +               for ( i = 0 ; i < 8 ; i ++ )
  737. +               {
  738. +                       for ( j = 0 ; j < 13 ; j ++ )
  739. +                       {
  740. +                               cubeProj[j][i] = dotProduct( axes[j], theCube[i] ) ;
  741. +                       }
  742. +               }
  743. +
  744. +               for ( i = 0 ; i < 3 ; i ++ )
  745. +                       for ( j = 0 ; j < 13 ; j ++ )
  746. +                       {
  747. +                               trigProj[j][i] = dotProduct( axes[j], trig[i] ) ;
  748. +                       }
  749. +
  750. +               // Get ends of projections
  751. +               for ( i = 0 ; i < 13 ; i ++ )
  752. +               {
  753. +                       int maxind = 0, minind = 0 ;
  754. +                       LONG max = cubeProj[i][0] ;
  755. +                       LONG min = cubeProj[i][0] ;
  756. +                       for ( j = 1 ; j < 8 ; j ++ )
  757. +                       {
  758. +                               if ( cubeProj[i][j] > max )
  759. +                               {
  760. +                                       max = cubeProj[i][j] ;
  761. +                                       maxind = j ;
  762. +                               }
  763. +                               if ( cubeProj[i][j] < min )
  764. +                               {
  765. +                                       min = cubeProj[i][j] ;
  766. +                                       minind = j ;
  767. +                               }
  768. +                       }
  769. +
  770. +                       cubeEnds[i][0] = minind ;
  771. +                       cubeEnds[i][1] = maxind ;
  772. +
  773. +                       maxind = 0 ;
  774. +                       minind = 0 ;
  775. +                       max = trigProj[i][0] ;
  776. +                       min = trigProj[i][0] ;
  777. +                       for ( j = 1 ; j < 3 ; j ++ )
  778. +                       {
  779. +                               if ( trigProj[i][j] > max )
  780. +                               {
  781. +                                       max = trigProj[i][j] ;
  782. +                                       maxind = j ;
  783. +                               }
  784. +                               if ( trigProj[i][j] < min )
  785. +                               {
  786. +                                       min = trigProj[i][j] ;
  787. +                                       minind = j ;
  788. +                               }
  789. +                       }
  790. +
  791. +                       trigEnds[i][0] = minind ;
  792. +                       trigEnds[i][1] = maxind ;
  793. +              
  794. +               }
  795. +       
  796. +       };
  797. +
  798. +       /**
  799. +        * Construction
  800. +        * from a parent Projections object and the index of the children
  801. +        */
  802. +       Projections2 ( Projections2* parent, int childInd )
  803. +       {
  804. +               int i, j ;
  805. +              
  806. +               // Copy triangle projections
  807. +               for ( i = 0 ; i < 13 ; i ++ )
  808. +               {
  809. +                       for ( j = 0 ; j < 3 ; j ++ )
  810. +                       {
  811. +                               trigProj[i][j] = parent->trigProj[i][j] ;
  812. +                       }
  813. +
  814. +                       trigEnds[i][0] = parent->trigEnds[i][0] ;
  815. +                       trigEnds[i][1] = parent->trigEnds[i][1] ;
  816. +               }
  817. +              
  818. +
  819. +               // Divide cube projections
  820. +               for ( i = 0 ; i < 13 ; i ++ )
  821. +               {
  822. +                       for ( j = 0 ; j < 8 ; j ++ )
  823. +                       {
  824. +                               const int* ind = centmap[vertmap[childInd][0] + vertmap[j][0]]
  825. +                                                                       [vertmap[childInd][1] + vertmap[j][1]]
  826. +                                                                       [vertmap[childInd][2] + vertmap[j][2]] ;
  827. +                               cubeProj[i][j] = ( parent->cubeProj[i][ind[0]] + parent->cubeProj[i][ind[1]] ) >> 1 ;
  828. +                       }
  829. +
  830. +                       cubeEnds[i][0] = parent->cubeEnds[i][0] ;
  831. +                       cubeEnds[i][1] = parent->cubeEnds[i][1] ;
  832. +               }
  833. +
  834. +       };
  835. +
  836. +       /**
  837. +        * Inherit projections from father
  838. +        */
  839. +       void inherit ( Projections2* parent, int childInd )
  840. +       {
  841. +               int i, j ;
  842. +
  843. +               // Copy triangle projections
  844. +               for ( i = 0 ; i < 13 ; i ++ )
  845. +               {
  846. +                       for ( j = 0 ; j < 3 ; j ++ )
  847. +                       {
  848. +                               trigProj[i][j] = parent->trigProj[i][j] ;
  849. +                       }
  850. +
  851. +                       trigEnds[i][0] = parent->trigEnds[i][0] ;
  852. +                       trigEnds[i][1] = parent->trigEnds[i][1] ;
  853. +               }
  854. +
  855. +               // Divide cube projections
  856. +               for ( i = 0 ; i < 13 ; i ++ )
  857. +               {
  858. +                       for ( j = 0 ; j < 8 ; j ++ )
  859. +                       {
  860. +                               const int* ind = centmap[vertmap[childInd][0] + vertmap[j][0]]
  861. +                                                                       [vertmap[childInd][1] + vertmap[j][1]]
  862. +                                                                       [vertmap[childInd][2] + vertmap[j][2]] ;
  863. +                               cubeProj[i][j] = ( parent->cubeProj[i][ind[0]] + parent->cubeProj[i][ind[1]] ) >> 1 ;
  864. +                       }
  865. +
  866. +                       cubeEnds[i][0] = parent->cubeEnds[i][0] ;
  867. +                       cubeEnds[i][1] = parent->cubeEnds[i][1] ;
  868. +               }
  869. +
  870. +       }
  871. +
  872. +       /**
  873. +        * Destruction
  874. +        */
  875. +       ~Projections2 ( )
  876. +       {
  877. +                      
  878. +       };
  879. +
  880. +       /**
  881. +        * Method to test intersection of the triangle and the cube
  882. +        */
  883. +       int isIntersecting ( )
  884. +       {
  885. +               for ( int i = 0 ; i < 13 ; i ++ )
  886. +               {
  887. +                       if ( cubeProj[i][cubeEnds[i][0]] > trigProj[i][trigEnds[i][1]] ||
  888. +                                cubeProj[i][cubeEnds[i][1]] < trigProj[i][trigEnds[i][0]] )
  889. +                       {
  890. +                               return 0 ;
  891. +                       }
  892. +               }
  893. +              
  894. +               return 1 ;
  895. +       };
  896. +
  897. +       /**
  898. +        * Method to test intersection of the triangle and one edge
  899. +        */
  900. +       int isIntersecting ( int edgeInd )
  901. +       {
  902. +              
  903. +               for ( int i = 0 ; i < 13 ; i ++ )
  904. +               {
  905. +                       LONG proj0 = cubeProj[i][edgemap[edgeInd][0]] ;
  906. +                       LONG proj1 = cubeProj[i][edgemap[edgeInd][1]] ;
  907. +
  908. +                       // Put in order
  909. +                       if ( proj0 > proj1 )
  910. +                       {
  911. +                               LONG temp = proj0 ;
  912. +                               proj0 = proj1 ;
  913. +                               proj1 = temp ;
  914. +                       }
  915. +
  916. +                       if ( proj0 > trigProj[i][trigEnds[i][1]] ||
  917. +                                proj1 < trigProj[i][trigEnds[i][0]] )
  918. +                       {
  919. +                               return 0 ;
  920. +                       }
  921. +               }
  922. +              
  923. +               return 1 ;
  924. +       };
  925. +
  926. +       /**
  927. +        * Method to perform cross-product
  928. +        */
  929. +       void crossProduct ( LONG a[3], LONG b[3], LONG res[3] )
  930. +       {
  931. +               res[0] = a[1] * b[2] - a[2] * b[1] ;
  932. +               res[1] = a[2] * b[0] - a[0] * b[2] ;
  933. +               res[2] = a[0] * b[1] - a[1] * b[0] ;
  934. +       }
  935. +
  936. +       /**
  937. +        * Method to perform dot product
  938. +        */
  939. +       LONG dotProduct ( LONG a[3], LONG b[3] )
  940. +       {
  941. +               return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ;
  942. +       }
  943. +};
  944. +
  945. +#endif
  946. \ No newline at end of file
  947. diff --git a/intern/dualcon/intern/MemoryAllocator.h b/intern/dualcon/intern/MemoryAllocator.h
  948. new file mode 100644
  949. index 0000000..5f7ed09
  950. --- /dev/null
  951. +++ b/intern/dualcon/intern/MemoryAllocator.h
  952. @@ -0,0 +1,471 @@
  953. +#ifndef MEMORYALLOCATOR_H
  954. +#define MEMORYALLOCATOR_H
  955. +
  956. +#include <stdio.h>
  957. +#include <stdlib.h>
  958. +
  959. +#define HEAP_BASE 16
  960. +#define UCHAR unsigned char
  961. +
  962. +/**
  963. + * Customized memory allocators that allocates/deallocates memory in chunks
  964. + *
  965. + * @author Tao Ju
  966. + */
  967. +
  968. +
  969. +
  970. +/**
  971. + * Base class of memory allocators
  972. + */
  973. +class VirtualMemoryAllocator
  974. +{
  975. +public:
  976. +       virtual UCHAR * allocate( ) = 0 ;
  977. +       virtual void deallocate( UCHAR * obj ) = 0 ;
  978. +       virtual void destroy( ) = 0 ;
  979. +       virtual void printInfo( ) = 0 ;
  980. +
  981. +       virtual int getAllocated( ) = 0 ;
  982. +       virtual int getAll( ) = 0 ;
  983. +       virtual int getBytes( ) = 0 ;
  984. +};
  985. +
  986. +/**
  987. + * Dynamic memory allocator - allows allocation/deallocation
  988. + *
  989. + * Note: there are 4 bytes overhead for each allocated yet unused object.
  990. + */
  991. +template < int N >
  992. +class MemoryAllocator : public VirtualMemoryAllocator
  993. +{
  994. +private:
  995. +
  996. +       /// Constants
  997. +       int HEAP_UNIT, HEAP_MASK ;
  998. +
  999. +       /// Data array
  1000. +       UCHAR ** data ;
  1001. +
  1002. +       /// Allocation stack
  1003. +       UCHAR *** stack ;
  1004. +
  1005. +       /// Number of data blocks
  1006. +       int datablocknum ;
  1007. +
  1008. +       /// Number of stack blocks
  1009. +       int stackblocknum ;
  1010. +
  1011. +       /// Size of stack
  1012. +       int stacksize ;
  1013. +
  1014. +       /// Number of available objects on stack
  1015. +       int available ;
  1016. +
  1017. +       /**
  1018. +        * Allocate a memory block
  1019. +        */
  1020. +       void allocateDataBlock ( )
  1021. +       {
  1022. +               // Allocate a data block
  1023. +               datablocknum += 1 ;
  1024. +               data = ( UCHAR ** )realloc( data, sizeof ( UCHAR * ) * datablocknum ) ;
  1025. +               data[ datablocknum - 1 ] = ( UCHAR * )malloc( HEAP_UNIT * N ) ;
  1026. +
  1027. +               // Update allocation stack
  1028. +               for ( int i = 0 ; i < HEAP_UNIT ; i ++ )
  1029. +               {
  1030. +                       stack[ 0 ][ i ] = ( data[ datablocknum - 1 ] + i * N ) ;
  1031. +               }
  1032. +               available = HEAP_UNIT ;
  1033. +       }
  1034. +
  1035. +       /**
  1036. +        * Allocate a stack block, to store more deallocated objects
  1037. +        */
  1038. +       void allocateStackBlock( )
  1039. +       {
  1040. +               // Allocate a stack block
  1041. +               stackblocknum += 1 ;
  1042. +               stacksize += HEAP_UNIT ;
  1043. +               stack = ( UCHAR *** )realloc( stack, sizeof ( UCHAR ** ) * stackblocknum ) ;
  1044. +               stack[ stackblocknum - 1 ] = ( UCHAR ** )malloc( HEAP_UNIT * sizeof ( UCHAR * ) ) ;
  1045. +       }
  1046. +
  1047. +
  1048. +public:
  1049. +       /**
  1050. +        * Constructor
  1051. +        */
  1052. +       MemoryAllocator( )
  1053. +       {
  1054. +               HEAP_UNIT = 1 << HEAP_BASE ;
  1055. +               HEAP_MASK = ( 1 << HEAP_BASE ) - 1 ;
  1056. +
  1057. +               data = ( UCHAR ** )malloc( sizeof( UCHAR * ) ) ;
  1058. +               data[ 0 ] = ( UCHAR * )malloc( HEAP_UNIT * N ) ;
  1059. +               datablocknum = 1 ;
  1060. +
  1061. +               stack = ( UCHAR *** )malloc( sizeof ( UCHAR ** ) ) ;
  1062. +               stack[ 0 ] = ( UCHAR ** )malloc( HEAP_UNIT * sizeof ( UCHAR * ) ) ;
  1063. +               stackblocknum = 1 ;
  1064. +               stacksize = HEAP_UNIT ;
  1065. +               available = HEAP_UNIT ;
  1066. +
  1067. +               for ( int i = 0 ; i < HEAP_UNIT ; i ++ )
  1068. +               {
  1069. +                       stack[ 0 ][ i ] = ( data[ 0 ] + i * N ) ;
  1070. +               }
  1071. +       }
  1072. +
  1073. +       /**
  1074. +        * Destructor
  1075. +        */
  1076. +       void destroy( )
  1077. +       {
  1078. +               int i ;
  1079. +               for ( i = 0 ; i < datablocknum ; i ++ )
  1080. +               {
  1081. +                       free( data[ i ] ) ;
  1082. +               }
  1083. +               for ( i = 0 ; i < stackblocknum ; i ++ )
  1084. +               {
  1085. +                       free( stack[ i ] ) ;
  1086. +               }
  1087. +               free( data ) ;
  1088. +               free( stack ) ;
  1089. +       }
  1090. +
  1091. +       /**
  1092. +        * Allocation method
  1093. +        */
  1094. +       UCHAR * allocate ( )
  1095. +       {
  1096. +               if ( available == 0 )
  1097. +               {
  1098. +                       allocateDataBlock ( ) ;
  1099. +               }
  1100. +
  1101. +               // printf("Allocating %d\n", header[ allocated ]) ;
  1102. +               available -- ;
  1103. +               return stack[ available >> HEAP_BASE ][ available & HEAP_MASK ] ;
  1104. +       }
  1105. +
  1106. +       /**
  1107. +        * De-allocation method
  1108. +        */
  1109. +       void deallocate ( UCHAR * obj )
  1110. +       {
  1111. +               if ( available == stacksize )
  1112. +               {
  1113. +                       allocateStackBlock ( ) ;
  1114. +               }
  1115. +
  1116. +               // printf("De-allocating %d\n", ( obj - data ) / N ) ;
  1117. +               stack[ available >> HEAP_BASE ][ available & HEAP_MASK ] = obj ;
  1118. +               available ++ ;
  1119. +               // printf("%d %d\n", allocated, header[ allocated ]) ;
  1120. +       }
  1121. +
  1122. +       /**
  1123. +        * Print information
  1124. +        */
  1125. +       void printInfo ( )
  1126. +       {
  1127. +               printf("Bytes: %d Used: %d Allocated: %d Maxfree: %d\n", getBytes(), getAllocated(), getAll(), stacksize ) ;
  1128. +       }
  1129. +
  1130. +       /**
  1131. +        * Query methods
  1132. +        */
  1133. +       int getAllocated( )
  1134. +       {
  1135. +               return HEAP_UNIT * datablocknum - available ;   
  1136. +       };
  1137. +
  1138. +       int getAll( )
  1139. +       {
  1140. +               return HEAP_UNIT * datablocknum ;
  1141. +       };
  1142. +
  1143. +       int getBytes( )
  1144. +       {
  1145. +               return N ;     
  1146. +       };
  1147. +};
  1148. +
  1149. +/**
  1150. + * Monotonic memory allocator - allows for allocation only
  1151. + *
  1152. + * Note: does not provide de-allocation method
  1153. + */
  1154. +template < int N >
  1155. +class MonotonicMemoryAllocator : public VirtualMemoryAllocator
  1156. +{
  1157. +private:
  1158. +
  1159. +       /// Constants
  1160. +       int HEAP_UNIT, HEAP_MASK ;
  1161. +
  1162. +       /// Data array
  1163. +       UCHAR ** data ;
  1164. +
  1165. +       /// Number of blocks
  1166. +       int blocknum ;
  1167. +
  1168. +       /// Total size of objects
  1169. +       int totalsize ;
  1170. +
  1171. +       /// Number of allocated objects
  1172. +       int allocated ;
  1173. +
  1174. +       /// Size of the first block
  1175. +       int firstblocksize ;
  1176. +
  1177. +       /**
  1178. +        * Allocate a block
  1179. +        */
  1180. +       void allocateBlock ( )
  1181. +       {
  1182. +               int oldsize = totalsize ;
  1183. +               totalsize += HEAP_UNIT ;
  1184. +               blocknum += 1 ;
  1185. +
  1186. +               // printf("Allocating... block size: %d %d\n", totalsize, totalsize * N ) ;
  1187. +               data = ( UCHAR ** )realloc( data, sizeof ( UCHAR * ) * blocknum ) ;
  1188. +               data[ blocknum - 1 ] = ( UCHAR * )malloc( HEAP_UNIT * N ) ;
  1189. +       }
  1190. +
  1191. +
  1192. +public:
  1193. +       /**
  1194. +        * Constructor
  1195. +        */
  1196. +       MonotonicMemoryAllocator( int length )
  1197. +       {
  1198. +               HEAP_UNIT = 1 << HEAP_BASE ;
  1199. +               HEAP_MASK = ( 1 << HEAP_BASE ) - 1 ;
  1200. +
  1201. +               firstblocksize = length ;
  1202. +               totalsize = length ;
  1203. +               blocknum = 1 ;
  1204. +               allocated = 0 ;
  1205. +               data = ( UCHAR ** )malloc( sizeof( UCHAR * ) ) ;
  1206. +               data[ 0 ] = ( UCHAR * )malloc( totalsize * N ) ;
  1207. +       }
  1208. +
  1209. +       /**
  1210. +        * Destructor
  1211. +        */
  1212. +       void destroy( )
  1213. +       {
  1214. +               for ( int i = 0 ; i < blocknum ; i ++ )
  1215. +               {
  1216. +                       free(data[ i ]) ;
  1217. +               }
  1218. +               free( data ) ;
  1219. +       }
  1220. +
  1221. +       /**
  1222. +        * Allocation method
  1223. +        */
  1224. +       UCHAR * allocate ( )
  1225. +       {
  1226. +               if ( allocated == totalsize )
  1227. +               {
  1228. +                       allocateBlock ( ) ;
  1229. +               }
  1230. +
  1231. +               // printf("Allocating %d\n", header[ allocated ]) ;
  1232. +               int nallocated = allocated ;
  1233. +               allocated ++ ;
  1234. +
  1235. +               if ( nallocated < firstblocksize )
  1236. +               {
  1237. +                       return ( data[ 0 ] + nallocated * N ) ;
  1238. +               }
  1239. +               else
  1240. +               {
  1241. +                       nallocated -= firstblocksize ;
  1242. +                       return ( data[ 1 + ( nallocated >> HEAP_BASE ) ] + ( nallocated & HEAP_MASK ) * N ) ;
  1243. +               }
  1244. +       }
  1245. +
  1246. +       /**
  1247. +        * De-allocation method
  1248. +        */
  1249. +       void deallocate ( UCHAR * obj )
  1250. +       {
  1251. +               printf("Attempt to deallocate from an allocation-only heap...Exit.\n") ;
  1252. +               exit( 0 ) ;
  1253. +       } ;
  1254. +
  1255. +       /**
  1256. +        * Print information
  1257. +        */
  1258. +       void printInfo ( )
  1259. +       {
  1260. +               printf("Bytes: %d Allocated: %d All: %d\n", N, allocated, totalsize ) ;
  1261. +       }
  1262. +
  1263. +       /**
  1264. +        * Query methods
  1265. +        */
  1266. +       int getAllocated( )
  1267. +       {
  1268. +               return allocated ;     
  1269. +       };
  1270. +
  1271. +       int getAll( )
  1272. +       {
  1273. +               return totalsize ;
  1274. +       };
  1275. +
  1276. +       int getBytes( )
  1277. +       {
  1278. +               return N ;     
  1279. +       };
  1280. +};
  1281. +
  1282. +/**
  1283. + * Serial memory allocator - allows for serial allocation and deallocation
  1284. + */
  1285. +template < int N >
  1286. +class SerialMemoryAllocator : public VirtualMemoryAllocator
  1287. +{
  1288. +private:
  1289. +
  1290. +       /// Constants
  1291. +       int HEAP_UNIT, HEAP_MASK ;
  1292. +
  1293. +       /// Data array
  1294. +       UCHAR ** data ;
  1295. +
  1296. +       /// Number of blocks
  1297. +       int blocknum ;
  1298. +
  1299. +       /// Total size of objects
  1300. +       int totalsize ;
  1301. +
  1302. +       /// Number of allocated objects
  1303. +       int allocated ;
  1304. +
  1305. +       /**
  1306. +        * Allocate a block
  1307. +        */
  1308. +       void allocateBlock ( )
  1309. +       {
  1310. +               int oldsize = totalsize ;
  1311. +               totalsize += HEAP_UNIT ;
  1312. +               blocknum += 1 ;
  1313. +
  1314. +               // printf("Allocating... block size: %d %d\n", totalsize, totalsize * N ) ;
  1315. +               data = ( UCHAR ** )realloc( data, sizeof ( UCHAR * ) * blocknum ) ;
  1316. +               data[ blocknum - 1 ] = ( UCHAR * )malloc( HEAP_UNIT * N ) ;
  1317. +       }
  1318. +
  1319. +
  1320. +public:
  1321. +       /**
  1322. +        * Constructor
  1323. +        */
  1324. +       SerialMemoryAllocator( )
  1325. +       {
  1326. +               HEAP_UNIT = 1 << HEAP_BASE ;
  1327. +               HEAP_MASK = ( 1 << HEAP_BASE ) - 1 ;
  1328. +
  1329. +               totalsize = HEAP_UNIT ;
  1330. +               blocknum = 1 ;
  1331. +               allocated = 0 ;
  1332. +               data = ( UCHAR ** )malloc( sizeof( UCHAR * ) ) ;
  1333. +               data[ 0 ] = ( UCHAR * )malloc( totalsize * N ) ;
  1334. +       }
  1335. +
  1336. +       /**
  1337. +        * Destructor
  1338. +        */
  1339. +       void destroy( )
  1340. +       {
  1341. +               for ( int i = 0 ; i < blocknum ; i ++ )
  1342. +               {
  1343. +                       free( data[ i ] ) ;
  1344. +               }
  1345. +               free( data ) ;
  1346. +       }
  1347. +
  1348. +       /**
  1349. +        * Allocation method
  1350. +        */
  1351. +       UCHAR * allocate ( )
  1352. +       {
  1353. +               if ( allocated == totalsize )
  1354. +               {
  1355. +                       allocateBlock ( ) ;
  1356. +               }
  1357. +
  1358. +               // printf("Allocating %d\n", header[ allocated ]) ;
  1359. +               int nallocated = allocated ;
  1360. +               allocated ++ ;
  1361. +               return ( data[ nallocated >> HEAP_BASE ] + ( nallocated & HEAP_MASK ) * N ) ;
  1362. +       }
  1363. +
  1364. +       /**
  1365. +        * Random-access de-allocation method: not implemented
  1366. +        */
  1367. +       void deallocate ( UCHAR * obj )
  1368. +       {
  1369. +               printf("Attempt to deallocate from an allocation-only heap...Exit.\n") ;
  1370. +               exit( 0 ) ;
  1371. +       } ;
  1372. +
  1373. +       /**
  1374. +        * Serial De-allocation method
  1375. +        */
  1376. +       void deallocateSerial ( int num )
  1377. +       {
  1378. +               allocated -= num ;
  1379. +       }
  1380. +
  1381. +       /**
  1382. +        * Get element
  1383. +        */
  1384. +       UCHAR * getAllocatedAt ( int index )
  1385. +       {
  1386. +               if ( index >= 0 )
  1387. +               {
  1388. +                       return ( data[ index >> HEAP_BASE ] + ( index & HEAP_MASK ) * N ) ;
  1389. +               }
  1390. +
  1391. +               return NULL ;
  1392. +       }
  1393. +
  1394. +       /**
  1395. +        * Print information
  1396. +        */
  1397. +       void printInfo ( )
  1398. +       {
  1399. +               printf("Bytes: %d Allocated: %d All: %d\n", N, allocated, totalsize ) ;
  1400. +       }
  1401. +
  1402. +       /**
  1403. +        * Query methods
  1404. +        */
  1405. +       int getAllocated( )
  1406. +       {
  1407. +               return allocated ;     
  1408. +       };
  1409. +
  1410. +       int getAll( )
  1411. +       {
  1412. +               return totalsize ;
  1413. +       };
  1414. +
  1415. +       int getBytes( )
  1416. +       {
  1417. +               return N ;     
  1418. +       };
  1419. +};
  1420. +
  1421. +
  1422. +
  1423. +#endif
  1424. diff --git a/intern/dualcon/intern/ModelReader.h b/intern/dualcon/intern/ModelReader.h
  1425. new file mode 100644
  1426. index 0000000..4948aa1
  1427. --- /dev/null
  1428. +++ b/intern/dualcon/intern/ModelReader.h
  1429. @@ -0,0 +1,42 @@
  1430. +#ifndef MODELREADER_H
  1431. +#define MODELREADER_H
  1432. +
  1433. +#include "GeoCommon.h"
  1434. +
  1435. +/*
  1436. + * Virtual class for input file readers
  1437. + *
  1438. + * @author Tao Ju
  1439. + */
  1440. +class ModelReader
  1441. +{
  1442. +public:
  1443. +       /// Constructor
  1444. +       ModelReader(){} ;
  1445. +
  1446. +       /// Get next triangle
  1447. +       virtual Triangle* getNextTriangle( ) = 0 ;
  1448. +       virtual int getNextTriangle( int t[3] ) = 0 ;
  1449. +
  1450. +       /// Get bounding box
  1451. +       virtual float getBoundingBox ( float origin[3] ) = 0 ;
  1452. +
  1453. +       /// Get number of triangles
  1454. +       virtual int getNumTriangles ( ) = 0 ;
  1455. +
  1456. +       /// Get storage size
  1457. +       virtual int getMemory ( ) = 0 ;
  1458. +
  1459. +       /// Reset file reading location
  1460. +       virtual void reset( ) = 0 ;
  1461. +
  1462. +       /// For explicit vertex models
  1463. +       virtual int getNumVertices( ) = 0 ;
  1464. +
  1465. +       virtual void getNextVertex( float v[3] ) = 0 ;
  1466. +
  1467. +       virtual void printInfo ( ) = 0 ;
  1468. +};
  1469. +
  1470. +
  1471. +#endif
  1472. \ No newline at end of file
  1473. diff --git a/intern/dualcon/intern/Projections.h b/intern/dualcon/intern/Projections.h
  1474. new file mode 100644
  1475. index 0000000..1a5b105
  1476. --- /dev/null
  1477. +++ b/intern/dualcon/intern/Projections.h
  1478. @@ -0,0 +1,827 @@
  1479. +#ifndef PROJECTIONS_H
  1480. +#define PROJECTIONS_H
  1481. +
  1482. +#include <stdio.h>
  1483. +#include <stdlib.h>
  1484. +
  1485. +#define CONTAINS_INDEX
  1486. +#define GRID_DIMENSION 20
  1487. +
  1488. +#define LONG int64_t
  1489. +#define UCHAR unsigned char
  1490. +
  1491. +/**
  1492. + * Structures and classes for computing projections of triangles
  1493. + * onto separating axes during scan conversion
  1494. + *
  1495. + * @author Tao Ju
  1496. + */
  1497. +
  1498. +
  1499. +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}} ;
  1500. +const int centmap[3][3][3][2] =
  1501. +{{{{0,0},{0,1},{1,1}},{{0,2},{0,3},{1,3}},{{2,2},{2,3},{3,3}}},
  1502. +{{{0,4},{0,5},{1,5}},{{0,6},{0,7},{1,7}},{{2,6},{2,7},{3,7}}},
  1503. +{{{4,4},{4,5},{5,5}},{{4,6},{4,7},{5,7}},{{6,6},{6,7},{7,7}}}} ;
  1504. +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}};
  1505. +const int facemap[6][4] = {
  1506. +       { 0,1,2,3 },
  1507. +       { 4,5,6,7 },
  1508. +       { 0,1,4,5 },
  1509. +       { 2,3,6,7 },
  1510. +       { 0,2,4,6 },
  1511. +       { 1,3,5,7 }} ;
  1512. +
  1513. +/**
  1514. + * Structure for the projections inheritable from parent
  1515. + */
  1516. +struct InheritableProjections
  1517. +{
  1518. +       /// Projections of triangle
  1519. +       LONG trigProj[13][2] ;
  1520. +
  1521. +       /// Projections of triangle vertices on primary axes
  1522. +       LONG trigVertProj[13][3] ;
  1523. +
  1524. +       /// Projections of triangle edges
  1525. +       LONG trigEdgeProj[13][3][2] ;
  1526. +
  1527. +       /// Normal of the triangle
  1528. +       double norm[3] ;
  1529. +       double normA, normB ;
  1530. +
  1531. +       /// End points along each axis
  1532. +       //int cubeEnds[13][2] ;
  1533. +
  1534. +       /// Error range on each axis
  1535. +       /// LONG errorProj[13];
  1536. +
  1537. +#ifdef CONTAINS_INDEX
  1538. +       /// Index of polygon
  1539. +       int index ;
  1540. +#endif
  1541. +};
  1542. +
  1543. +
  1544. +/**
  1545. + * Class for projections of cube / triangle vertices on the separating axes
  1546. + */
  1547. +class Projections
  1548. +{
  1549. +public:
  1550. +       /// Inheritable portion
  1551. +       InheritableProjections* inherit ;
  1552. +
  1553. +       /// Projections of the cube vertices
  1554. +       LONG cubeProj[13][6] ;
  1555. +
  1556. +public:
  1557. +
  1558. +       Projections( )
  1559. +       {
  1560. +       }
  1561. +
  1562. +       /**
  1563. +        * Construction
  1564. +        * from a cube (axes aligned) and triangle
  1565. +        */
  1566. +       Projections( LONG cube[2][3], LONG trig[3][3], LONG error, int triind )
  1567. +       {
  1568. +               int i, j ;
  1569. +               inherit = new InheritableProjections ;
  1570. +#ifdef CONTAINS_INDEX
  1571. +               inherit->index = triind ;
  1572. +#endif
  1573. +               /// Create axes
  1574. +               LONG axes[13][3] ;
  1575. +
  1576. +               // Cube faces
  1577. +               axes[0][0] = 1 ;
  1578. +               axes[0][1] = 0 ;
  1579. +               axes[0][2] = 0 ;
  1580. +
  1581. +               axes[1][0] = 0 ;
  1582. +               axes[1][1] = 1 ;
  1583. +               axes[1][2] = 0 ;
  1584. +
  1585. +               axes[2][0] = 0 ;
  1586. +               axes[2][1] = 0 ;
  1587. +               axes[2][2] = 1 ;
  1588. +
  1589. +               // Triangle face
  1590. +               LONG trigedge[3][3] ;
  1591. +               for ( i = 0 ; i < 3 ; i ++ )
  1592. +               {
  1593. +                       for ( j = 0 ; j < 3 ; j ++ )
  1594. +                       {
  1595. +                               trigedge[i][j] = trig[(i+1)%3][j] - trig[i][j] ;
  1596. +                       }
  1597. +               }
  1598. +               crossProduct( trigedge[0], trigedge[1], axes[3] ) ;
  1599. +
  1600. +               /// Normalize face normal and store
  1601. +               double dedge1[] = { (double) trig[1][0] - (double) trig[0][0],
  1602. +                                                       (double) trig[1][1] - (double) trig[0][1],
  1603. +                                                       (double) trig[1][2] - (double) trig[0][2] } ;
  1604. +               double dedge2[] = { (double) trig[2][0] - (double) trig[1][0],
  1605. +                                                       (double) trig[2][1] - (double) trig[1][1],
  1606. +                                                       (double) trig[2][2] - (double) trig[1][2] } ;
  1607. +               crossProduct( dedge1, dedge2, inherit->norm ) ;
  1608. +               normalize( inherit->norm ) ;
  1609. +//             inherit->normA = norm[ 0 ] ;
  1610. +//             inherit->normB = norm[ 2 ] > 0 ? norm[ 1 ] : 2 + norm[ 1 ] ;
  1611. +
  1612. +               // Face edges and triangle edges
  1613. +               int ct = 4 ;
  1614. +               for ( i = 0 ; i < 3 ; i ++ )
  1615. +                       for ( j = 0 ; j < 3 ; j ++ )
  1616. +                       {
  1617. +                               crossProduct( axes[j], trigedge[i], axes[ct] ) ;
  1618. +                               ct ++ ;
  1619. +                       }              
  1620. +
  1621. +               /// Generate projections
  1622. +               LONG cubeedge[3][3] ;
  1623. +               for ( i = 0 ; i < 3 ; i ++ )
  1624. +               {
  1625. +                       for ( j = 0 ; j < 3 ; j ++ )
  1626. +                       {
  1627. +                               cubeedge[i][j] = 0 ;
  1628. +                       }
  1629. +                       cubeedge[i][i] = cube[1][i] - cube[0][i] ;
  1630. +               }
  1631. +
  1632. +               for ( j = 0 ; j < 13 ; j ++ )
  1633. +               {
  1634. +                       // Origin
  1635. +                       cubeProj[j][0] = dotProduct( axes[j], cube[0] ) ;
  1636. +
  1637. +                       // 3 direction vectors
  1638. +                       for ( i = 1 ; i < 4 ; i ++ )
  1639. +                       {
  1640. +                               cubeProj[j][i] = dotProduct( axes[j], cubeedge[i-1] ) ;
  1641. +                       }
  1642. +
  1643. +                       // Offsets of 2 ends of cube projection
  1644. +                       LONG max = 0 ;
  1645. +                       LONG min = 0 ;
  1646. +                       for ( i = 1 ; i < 8 ; i ++ )
  1647. +                       {
  1648. +                               LONG proj = vertmap[i][0] * cubeProj[j][1] + vertmap[i][1] * cubeProj[j][2] + vertmap[i][2] * cubeProj[j][3] ;
  1649. +                               if ( proj > max )
  1650. +                               {
  1651. +                                       max = proj ;
  1652. +                               }
  1653. +                               if ( proj < min )
  1654. +                               {
  1655. +                                       min = proj ;
  1656. +                               }
  1657. +                       }
  1658. +                       cubeProj[j][4] = min ;
  1659. +                       cubeProj[j][5] = max ;
  1660. +
  1661. +               }
  1662. +
  1663. +               for ( j = 0 ; j < 13 ; j ++ )
  1664. +               {
  1665. +                       LONG vts[3] = { dotProduct( axes[j], trig[0] ),
  1666. +                                                       dotProduct( axes[j], trig[1] ),
  1667. +                                                       dotProduct( axes[j], trig[2] )  } ;
  1668. +
  1669. +                       // Vertex
  1670. +                       inherit->trigVertProj[j][0] = vts[0] ;
  1671. +                       inherit->trigVertProj[j][1] = vts[1] ;
  1672. +                       inherit->trigVertProj[j][2] = vts[2] ;
  1673. +
  1674. +                       // Edge
  1675. +                       for ( i = 0 ; i < 3 ; i ++ )
  1676. +                       {
  1677. +                               if ( vts[i] < vts[(i+1) % 3] )
  1678. +                               {
  1679. +                                       inherit->trigEdgeProj[j][i][0] = vts[i] ;
  1680. +                                       inherit->trigEdgeProj[j][i][1] = vts[(i+1) % 3] ;
  1681. +                               }
  1682. +                               else
  1683. +                               {
  1684. +                                       inherit->trigEdgeProj[j][i][1] = vts[i] ;
  1685. +                                       inherit->trigEdgeProj[j][i][0] = vts[(i+1) % 3] ;
  1686. +                               }
  1687. +                       }
  1688. +
  1689. +                       // Triangle
  1690. +                       inherit->trigProj[j][0] = vts[0] ;
  1691. +                       inherit->trigProj[j][1] = vts[0] ;
  1692. +                       for ( i = 1 ; i < 3 ; i ++ )
  1693. +                       {
  1694. +                               if ( vts[i] < inherit->trigProj[j][0] )
  1695. +                               {
  1696. +                                       inherit->trigProj[j][0] = vts[i] ;
  1697. +                               }
  1698. +                               if ( vts[i] > inherit->trigProj[j][1] )
  1699. +                               {
  1700. +                                       inherit->trigProj[j][1] = vts[i] ;
  1701. +                               }
  1702. +                       }
  1703. +               }
  1704. +
  1705. +       }
  1706. +
  1707. +       /**
  1708. +        * Construction
  1709. +        * from a parent Projections object and the index of the children
  1710. +        */
  1711. +       Projections ( Projections* parent )
  1712. +       {
  1713. +               // Copy inheritable projections
  1714. +               this->inherit = parent->inherit ;
  1715. +
  1716. +               // Shrink cube projections
  1717. +               for ( int i = 0 ; i < 13 ; i ++ )
  1718. +               {
  1719. +                       cubeProj[i][0] = parent->cubeProj[i][0] ;
  1720. +                       for ( int j = 1 ; j < 6 ; j ++ )
  1721. +                       {
  1722. +                               cubeProj[i][j] = parent->cubeProj[i][j] >> 1 ;
  1723. +                       }
  1724. +               }
  1725. +       };
  1726. +
  1727. +       Projections ( Projections* parent, int box[3], int depth )
  1728. +       {
  1729. +               int mask =  ( 1 << depth ) - 1 ;
  1730. +               int nbox[3] = { box[0] & mask, box[1] & mask, box[2] & mask } ;
  1731. +
  1732. +               // Copy inheritable projections
  1733. +               this->inherit = parent->inherit ;
  1734. +
  1735. +               // Shrink cube projections
  1736. +               for ( int i = 0 ; i < 13 ; i ++ )
  1737. +               {
  1738. +                       for ( int j = 1 ; j < 6 ; j ++ )
  1739. +                       {
  1740. +                               cubeProj[i][j] = parent->cubeProj[i][j] >> depth ;
  1741. +                       }
  1742. +
  1743. +                       cubeProj[i][0] = parent->cubeProj[i][0] + nbox[0] * cubeProj[i][1] + nbox[1] * cubeProj[i][2] + nbox[2] * cubeProj[i][3] ;
  1744. +               }
  1745. +       };
  1746. +
  1747. +       /**
  1748. +        * Testing intersection based on vertex/edge masks
  1749. +        */
  1750. +       int getIntersectionMasks( UCHAR cedgemask, UCHAR& edgemask )
  1751. +       {
  1752. +               int i, j ;
  1753. +               edgemask = cedgemask ;
  1754. +
  1755. +               // Pre-processing
  1756. +               /*
  1757. +               if ( cvertmask & 1 )
  1758. +               {
  1759. +                       edgemask |= 5 ;
  1760. +               }
  1761. +               if ( cvertmask & 2 )
  1762. +               {
  1763. +                       edgemask |= 3 ;
  1764. +               }
  1765. +               if ( cvertmask & 4 )
  1766. +               {
  1767. +                       edgemask |= 6 ;
  1768. +               }
  1769. +
  1770. +               */
  1771. +
  1772. +               // Test axes for edge intersection
  1773. +               UCHAR bit = 1 ;
  1774. +               for ( j = 0 ; j < 3 ; j ++ )
  1775. +               {
  1776. +                       if ( edgemask & bit )
  1777. +                       {
  1778. +                               for ( i = 0 ; i < 13 ; i ++ )
  1779. +                               {
  1780. +                                       LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
  1781. +                                       LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
  1782. +
  1783. +                                       if ( proj0 > inherit->trigEdgeProj[i][j][1] ||
  1784. +                                                proj1 < inherit->trigEdgeProj[i][j][0] )
  1785. +                                       {
  1786. +                                               edgemask &= ( ~ bit ) ;
  1787. +                                               break ;
  1788. +                                       }
  1789. +                               }
  1790. +                       }
  1791. +                       bit <<= 1 ;
  1792. +               }
  1793. +              
  1794. +               /*
  1795. +               if ( edgemask != 0 )
  1796. +               {
  1797. +                       printf("%d %d\n", cedgemask, edgemask) ;
  1798. +               }
  1799. +               */
  1800. +
  1801. +               // Test axes for triangle intersection
  1802. +               if ( edgemask )
  1803. +               {
  1804. +                       return 1 ;
  1805. +               }
  1806. +
  1807. +               for ( i = 3 ; i < 13 ; i ++ )
  1808. +               {
  1809. +                       LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
  1810. +                       LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
  1811. +
  1812. +                       if ( proj0 > inherit->trigProj[i][1] ||
  1813. +                                proj1 < inherit->trigProj[i][0] )
  1814. +                       {
  1815. +                               return 0 ;
  1816. +                       }
  1817. +               }
  1818. +              
  1819. +               return 1 ;
  1820. +       }
  1821. +
  1822. +       /**
  1823. +        * Retrieving children masks using PRIMARY AXES
  1824. +        */
  1825. +       UCHAR getChildrenMasks( UCHAR cvertmask, UCHAR vertmask[8] )
  1826. +       {
  1827. +               int i, j, k ;
  1828. +               int bmask[3][2] = {{0,0},{0,0},{0,0}} ;
  1829. +               int vmask[3][3][2] = {{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}}} ;
  1830. +               UCHAR boxmask = 0 ;
  1831. +               LONG len = cubeProj[0][1] >> 1 ;
  1832. +              
  1833. +               for ( i = 0 ; i < 3 ; i ++ )
  1834. +               {
  1835. +                       LONG mid = cubeProj[i][0] + len ;
  1836. +
  1837. +                       // Check bounding box
  1838. +                       if ( mid >= inherit->trigProj[i][0] )
  1839. +                       {
  1840. +                               bmask[i][0] = 1 ;
  1841. +                       }
  1842. +                       if ( mid <= inherit->trigProj[i][1] )
  1843. +                       {
  1844. +                               bmask[i][1] = 1 ;
  1845. +                       }
  1846. +
  1847. +                       // Check vertex mask
  1848. +                       if ( cvertmask )
  1849. +                       {
  1850. +                               for ( j = 0 ; j < 3 ; j ++ )
  1851. +                               {
  1852. +                                       if ( cvertmask & ( 1 << j ) )
  1853. +                                       {
  1854. +                                               // Only check if it's contained this node
  1855. +                                               if ( mid >= inherit->trigVertProj[i][j] )
  1856. +                                               {
  1857. +                                                       vmask[i][j][0] = 1 ;
  1858. +                                               }
  1859. +                                               if ( mid <= inherit->trigVertProj[i][j] )
  1860. +                                               {
  1861. +                                                       vmask[i][j][1] = 1 ;
  1862. +                                               }
  1863. +                                       }
  1864. +                               }
  1865. +                       }
  1866. +
  1867. +                       /*
  1868. +                       // Check edge mask
  1869. +                       if ( cedgemask )
  1870. +                       {
  1871. +                               for ( j = 0 ; j < 3 ; j ++ )
  1872. +                               {
  1873. +                                       if ( cedgemask & ( 1 << j ) )
  1874. +                                       {
  1875. +                                               // Only check if it's contained this node
  1876. +                                               if ( mid >= inherit->trigEdgeProj[i][j][0] )
  1877. +                                               {
  1878. +                                                       emask[i][j][0] = 1 ;
  1879. +                                               }
  1880. +                                               if ( mid <= inherit->trigEdgeProj[i][j][1] )
  1881. +                                               {
  1882. +                                                       emask[i][j][1] = 1 ;
  1883. +                                               }
  1884. +                                       }
  1885. +                               }
  1886. +                       }
  1887. +                       */
  1888. +
  1889. +               }
  1890. +
  1891. +               // Fill in masks
  1892. +               int ct = 0 ;
  1893. +               for ( i = 0 ; i < 2 ; i ++ )
  1894. +                       for ( j = 0 ; j < 2 ; j ++ )
  1895. +                               for ( k = 0 ; k < 2 ; k ++ )
  1896. +                               {
  1897. +                                       boxmask |= ( ( bmask[0][i] & bmask[1][j] & bmask[2][k] ) << ct ) ;
  1898. +                                       vertmask[ct] = (( vmask[0][0][i] & vmask[1][0][j] & vmask[2][0][k] ) |
  1899. +                                                                  (( vmask[0][1][i] & vmask[1][1][j] & vmask[2][1][k] ) << 1 ) |
  1900. +                                                                  (( vmask[0][2][i] & vmask[1][2][j] & vmask[2][2][k] ) << 2 ) ) ;
  1901. +                                       /*
  1902. +                                       edgemask[ct] = (( emask[0][0][i] & emask[1][0][j] & emask[2][0][k] ) |
  1903. +                                                                  (( emask[0][1][i] & emask[1][1][j] & emask[2][1][k] ) << 1 ) |
  1904. +                                                                  (( emask[0][2][i] & emask[1][2][j] & emask[2][2][k] ) << 2 ) ) ;
  1905. +                                       edgemask[ct] = cedgemask ;
  1906. +                                       */
  1907. +                                       ct ++ ;
  1908. +                               }
  1909. +
  1910. +               // Return bounding box masks
  1911. +               return boxmask ;
  1912. +       }
  1913. +
  1914. +       UCHAR getBoxMask( )
  1915. +       {
  1916. +               int i, j, k ;
  1917. +               int bmask[3][2] = {{0,0},{0,0},{0,0}} ;
  1918. +               UCHAR boxmask = 0 ;
  1919. +               LONG len = cubeProj[0][1] >> 1 ;
  1920. +              
  1921. +               for ( i = 0 ; i < 3 ; i ++ )
  1922. +               {
  1923. +                       LONG mid = cubeProj[i][0] + len ;
  1924. +
  1925. +                       // Check bounding box
  1926. +                       if ( mid >= inherit->trigProj[i][0] )
  1927. +                       {
  1928. +                               bmask[i][0] = 1 ;
  1929. +                       }
  1930. +                       if ( mid <= inherit->trigProj[i][1] )
  1931. +                       {
  1932. +                               bmask[i][1] = 1 ;
  1933. +                       }
  1934. +
  1935. +               }
  1936. +
  1937. +               // Fill in masks
  1938. +               int ct = 0 ;
  1939. +               for ( i = 0 ; i < 2 ; i ++ )
  1940. +                       for ( j = 0 ; j < 2 ; j ++ )
  1941. +                               for ( k = 0 ; k < 2 ; k ++ )
  1942. +                               {
  1943. +                                       boxmask |= ( ( bmask[0][i] & bmask[1][j] & bmask[2][k] ) << ct ) ;
  1944. +                                       ct ++ ;
  1945. +                               }
  1946. +
  1947. +               // Return bounding box masks
  1948. +               return boxmask ;
  1949. +       }
  1950. +
  1951. +
  1952. +       /**
  1953. +        * Get projections for sub-cubes (simple axes)
  1954. +        */
  1955. +       void getSubProjectionsSimple( Projections* p[8] )
  1956. +       {
  1957. +               // Process the axes cooresponding to the triangle's normal
  1958. +               int ind = 3 ;
  1959. +               LONG len = cubeProj[ 0 ][ 1 ] >> 1 ;
  1960. +               LONG trigproj[3] = { cubeProj[ ind ][ 1 ] >> 1, cubeProj[ ind ][ 2 ] >> 1, cubeProj[ ind ][ 3 ] >> 1 } ;
  1961. +
  1962. +               int ct = 0 ;
  1963. +               for ( int i = 0 ; i < 2 ; i ++ )
  1964. +                       for ( int j = 0 ; j < 2 ; j ++ )
  1965. +                               for ( int k = 0 ; k < 2 ; k ++ )
  1966. +                               {
  1967. +                                       p[ct] = new Projections( ) ;
  1968. +                                       p[ct]->inherit = inherit ;
  1969. +
  1970. +                                       p[ct]->cubeProj[ 0 ][ 0 ] = cubeProj[ 0 ][ 0 ] + i * len ;
  1971. +                                       p[ct]->cubeProj[ 1 ][ 0 ] = cubeProj[ 1 ][ 0 ] + j * len ;
  1972. +                                       p[ct]->cubeProj[ 2 ][ 0 ] = cubeProj[ 2 ][ 0 ] + k * len ;
  1973. +                                       p[ct]->cubeProj[ 0 ][ 1 ] = len ;
  1974. +
  1975. +                                       for ( int m = 1 ; m < 4 ; m ++ )
  1976. +                                       {
  1977. +                                               p[ct]->cubeProj[ ind ][ m ] = trigproj[ m - 1 ] ;
  1978. +                                       }
  1979. +                                       p[ct]->cubeProj[ ind ][ 0 ] = cubeProj[ ind ][0] + i * trigproj[0] + j * trigproj[1] + k * trigproj[2] ;
  1980. +
  1981. +                                       ct ++ ;
  1982. +                               }
  1983. +       }
  1984. +
  1985. +       /**
  1986. +        * Shifting a cube to a new origin
  1987. +        */
  1988. +       void shift ( int off[3] )
  1989. +       {
  1990. +               for ( int i = 0 ; i < 13 ; i ++ )
  1991. +               {
  1992. +                       cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
  1993. +               }
  1994. +       }
  1995. +
  1996. +       void shiftNoPrimary ( int off[3] )
  1997. +       {
  1998. +               for ( int i = 3 ; i < 13 ; i ++ )
  1999. +               {
  2000. +                       cubeProj[i][0] += off[0] * cubeProj[i][1] + off[1] * cubeProj[i][2] + off[2] * cubeProj[i][3] ;
  2001. +               }
  2002. +       }
  2003. +
  2004. +       /**
  2005. +        * Method to test intersection of the triangle and the cube
  2006. +        */
  2007. +       int isIntersecting ( )
  2008. +       {
  2009. +               for ( int i = 0 ; i < 13 ; i ++ )
  2010. +               {
  2011. +                       /*
  2012. +                       LONG proj0 = cubeProj[i][0] +
  2013. +                               vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
  2014. +                               vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
  2015. +                               vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
  2016. +                       LONG proj1 = cubeProj[i][0] +
  2017. +                               vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
  2018. +                               vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
  2019. +                               vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
  2020. +                       */
  2021. +
  2022. +                       LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
  2023. +                       LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
  2024. +
  2025. +                       if ( proj0 > inherit->trigProj[i][1] ||
  2026. +                                proj1 < inherit->trigProj[i][0] )
  2027. +                       {
  2028. +                               return 0 ;
  2029. +                       }
  2030. +               }
  2031. +              
  2032. +               return 1 ;
  2033. +       };
  2034. +
  2035. +       int isIntersectingNoPrimary ( )
  2036. +       {
  2037. +               for ( int i = 3 ; i < 13 ; i ++ )
  2038. +               {
  2039. +                       /*
  2040. +                       LONG proj0 = cubeProj[i][0] +
  2041. +                               vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
  2042. +                               vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
  2043. +                               vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
  2044. +                       LONG proj1 = cubeProj[i][0] +
  2045. +                               vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
  2046. +                               vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
  2047. +                               vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
  2048. +                       */
  2049. +
  2050. +                       LONG proj0 = cubeProj[i][0] + cubeProj[i][4] ;
  2051. +                       LONG proj1 = cubeProj[i][0] + cubeProj[i][5] ;
  2052. +
  2053. +                       if ( proj0 > inherit->trigProj[i][1] ||
  2054. +                                proj1 < inherit->trigProj[i][0] )
  2055. +                       {
  2056. +                               return 0 ;
  2057. +                       }
  2058. +               }
  2059. +              
  2060. +               return 1 ;
  2061. +       };     
  2062. +       
  2063. +       /**
  2064. +        * Method to test intersection of the triangle and one edge
  2065. +        */
  2066. +       int isIntersecting ( int edgeInd )
  2067. +       {
  2068. +               for ( int i = 0 ; i < 13 ; i ++ )
  2069. +               {
  2070. +                      
  2071. +                       LONG proj0 = cubeProj[i][0] +
  2072. +                               vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
  2073. +                               vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
  2074. +                               vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
  2075. +                       LONG proj1 = cubeProj[i][0] +
  2076. +                               vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
  2077. +                               vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
  2078. +                               vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
  2079. +
  2080. +
  2081. +                       if ( proj0 < proj1 )
  2082. +                       {
  2083. +                               if ( proj0 > inherit->trigProj[i][1] ||
  2084. +                                        proj1 < inherit->trigProj[i][0] )
  2085. +                               {
  2086. +                                       return 0 ;
  2087. +                               }
  2088. +                       }
  2089. +                       else
  2090. +                       {
  2091. +                               if ( proj1 > inherit->trigProj[i][1] ||
  2092. +                                        proj0 < inherit->trigProj[i][0] )
  2093. +                               {
  2094. +                                       return 0 ;
  2095. +                               }
  2096. +                       }
  2097. +               }
  2098. +              
  2099. +               // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] )  ;
  2100. +               return 1 ;
  2101. +       };
  2102. +
  2103. +       /**
  2104. +        * Method to test intersection of one triangle edge and one cube face
  2105. +        */
  2106. +       int isIntersecting ( int edgeInd, int faceInd )
  2107. +       {
  2108. +               for ( int i = 0 ; i < 13 ; i ++ )
  2109. +               {
  2110. +                       LONG trigproj0 = inherit->trigVertProj[i][edgeInd] ;
  2111. +                       LONG trigproj1 = inherit->trigVertProj[i][(edgeInd+1)%3] ;
  2112. +
  2113. +                       if ( trigproj0 < trigproj1 )
  2114. +                       {
  2115. +                               int t1 = 1 , t2 = 1 ;
  2116. +                               for ( int j = 0 ; j < 4 ; j ++ )
  2117. +                               {
  2118. +                                       LONG proj = cubeProj[i][0] +
  2119. +                                               vertmap[facemap[faceInd][j]][0] * cubeProj[i][1] +
  2120. +                                               vertmap[facemap[faceInd][j]][1] * cubeProj[i][2] +
  2121. +                                               vertmap[facemap[faceInd][j]][2] * cubeProj[i][3] ;
  2122. +                                       if ( proj >= trigproj0 )
  2123. +                                       {
  2124. +                                               t1 = 0 ;
  2125. +                                       }
  2126. +                                       if ( proj <= trigproj1 )
  2127. +                                       {
  2128. +                                               t2 = 0 ;
  2129. +                                       }
  2130. +                               }
  2131. +                               if ( t1 || t2 )
  2132. +                               {
  2133. +                                       return 0 ;
  2134. +                               }
  2135. +                       }
  2136. +                       else
  2137. +                       {
  2138. +                               int t1 = 1 , t2 = 1  ;
  2139. +                               for ( int j = 0 ; j < 4 ; j ++ )
  2140. +                               {
  2141. +                                       LONG proj = cubeProj[i][0] +
  2142. +                                               vertmap[facemap[faceInd][j]][0] * cubeProj[i][1] +
  2143. +                                               vertmap[facemap[faceInd][j]][1] * cubeProj[i][2] +
  2144. +                                               vertmap[facemap[faceInd][j]][2] * cubeProj[i][3] ;
  2145. +                                       if ( proj >= trigproj1 )
  2146. +                                       {
  2147. +                                               t1 = 0 ;
  2148. +                                       }
  2149. +                                       if ( proj <= trigproj0 )
  2150. +                                       {
  2151. +                                               t2 = 0 ;
  2152. +                                       }
  2153. +                               }
  2154. +                               if ( t1 || t2 )
  2155. +                               {
  2156. +                                       return 0 ;
  2157. +                               }
  2158. +                       }
  2159. +               }
  2160. +
  2161. +               return 1 ;
  2162. +       };
  2163. +
  2164. +
  2165. +       int isIntersectingPrimary ( int edgeInd )
  2166. +       {
  2167. +               for ( int i = 0 ; i < 13 ; i ++ )
  2168. +               {
  2169. +                      
  2170. +                       LONG proj0 = cubeProj[i][0] ;
  2171. +                       LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
  2172. +
  2173. +                       if ( proj0 < proj1 )
  2174. +                       {
  2175. +                               if ( proj0 > inherit->trigProj[i][1] ||
  2176. +                                        proj1 < inherit->trigProj[i][0] )
  2177. +                               {
  2178. +                                       return 0 ;
  2179. +                               }
  2180. +                       }
  2181. +                       else
  2182. +                       {
  2183. +                               if ( proj1 > inherit->trigProj[i][1] ||
  2184. +                                        proj0 < inherit->trigProj[i][0] )
  2185. +                               {
  2186. +                                       return 0 ;
  2187. +                               }
  2188. +                       }
  2189. +
  2190. +               }
  2191. +              
  2192. +               // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] )  ;
  2193. +               return 1 ;
  2194. +       };
  2195. +
  2196. +       double getIntersection ( int edgeInd )
  2197. +       {
  2198. +               int i = 3 ;
  2199. +
  2200. +               LONG proj0 = cubeProj[i][0] +
  2201. +                       vertmap[edgemap[edgeInd][0]][0] * cubeProj[i][1] +
  2202. +                       vertmap[edgemap[edgeInd][0]][1] * cubeProj[i][2] +
  2203. +                       vertmap[edgemap[edgeInd][0]][2] * cubeProj[i][3] ;
  2204. +               LONG proj1 = cubeProj[i][0] +
  2205. +                       vertmap[edgemap[edgeInd][1]][0] * cubeProj[i][1] +
  2206. +                       vertmap[edgemap[edgeInd][1]][1] * cubeProj[i][2] +
  2207. +                       vertmap[edgemap[edgeInd][1]][2] * cubeProj[i][3] ;
  2208. +               LONG proj2 = inherit->trigProj[i][1] ;
  2209. +
  2210. +               /*
  2211. +               if ( proj0 < proj1 )
  2212. +               {
  2213. +                       if ( proj2 < proj0 || proj2 > proj1 )
  2214. +                       {
  2215. +                               return -1 ;
  2216. +                       }
  2217. +               }
  2218. +               else
  2219. +               {
  2220. +                       if ( proj2 < proj1 || proj2 > proj0 )
  2221. +                       {
  2222. +                               return -1 ;
  2223. +                       }
  2224. +               }
  2225. +               */
  2226. +
  2227. +               double alpha = (double)( proj2 - proj0 ) / (double)( proj1 - proj0 ) ;
  2228. +               /*
  2229. +               if ( alpha < 0 )
  2230. +               {
  2231. +                       alpha = 0.5 ;
  2232. +               }
  2233. +               else if ( alpha > 1 )
  2234. +               {
  2235. +                       alpha = 0.5 ;
  2236. +               }
  2237. +               */
  2238. +
  2239. +               return alpha ;
  2240. +       };
  2241. +
  2242. +       float getIntersectionPrimary ( int edgeInd )
  2243. +       {
  2244. +               int i = 3 ;
  2245. +
  2246. +              
  2247. +               LONG proj0 = cubeProj[i][0] ;
  2248. +               LONG proj1 = cubeProj[i][0] + cubeProj[i][edgeInd + 1] ;
  2249. +               LONG proj2 = inherit->trigProj[i][1] ;
  2250. +
  2251. +               // double alpha = (double)( ( proj2 - proj0 ) * cubeProj[edgeInd][edgeInd + 1] ) / (double)( proj1 - proj0 ) ;
  2252. +               double alpha = (double)( ( proj2 - proj0 ) ) / (double)( proj1 - proj0 ) ;
  2253. +              
  2254. +               if ( alpha < 0 )
  2255. +               {
  2256. +                       alpha = 0.5 ;
  2257. +               }
  2258. +               else if ( alpha > 1 )
  2259. +               {
  2260. +                       alpha = 0.5 ;
  2261. +               }
  2262. +              
  2263. +
  2264. +               return (float)alpha ;
  2265. +       };
  2266. +
  2267. +       /**
  2268. +        * Method to perform cross-product
  2269. +        */
  2270. +       void crossProduct ( LONG a[3], LONG b[3], LONG res[3] )
  2271. +       {
  2272. +               res[0] = a[1] * b[2] - a[2] * b[1] ;
  2273. +               res[1] = a[2] * b[0] - a[0] * b[2] ;
  2274. +               res[2] = a[0] * b[1] - a[1] * b[0] ;
  2275. +       }
  2276. +       void crossProduct ( double a[3], double b[3], double res[3] )
  2277. +       {
  2278. +               res[0] = a[1] * b[2] - a[2] * b[1] ;
  2279. +               res[1] = a[2] * b[0] - a[0] * b[2] ;
  2280. +               res[2] = a[0] * b[1] - a[1] * b[0] ;
  2281. +       }
  2282. +
  2283. +       /**
  2284. +        * Method to perform dot product
  2285. +        */
  2286. +       LONG dotProduct ( LONG a[3], LONG b[3] )
  2287. +       {
  2288. +               return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ;
  2289. +       }
  2290. +
  2291. +       void normalize( double a[3] )
  2292. +       {
  2293. +               double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2] ;
  2294. +               if ( mag > 0 )
  2295. +               {
  2296. +                       mag = sqrt( mag ) ;
  2297. +                       a[0] /= mag ;
  2298. +                       a[1] /= mag ;
  2299. +                       a[2] /= mag ;
  2300. +               }
  2301. +       }
  2302. +
  2303. +};
  2304. +
  2305. +#endif
  2306. diff --git a/intern/dualcon/intern/Queue.h b/intern/dualcon/intern/Queue.h
  2307. new file mode 100644
  2308. index 0000000..084143a
  2309. --- /dev/null
  2310. +++ b/intern/dualcon/intern/Queue.h
  2311. @@ -0,0 +1,88 @@
  2312. +#ifndef QUEUE_H
  2313. +#define QUEUE_H
  2314. +
  2315. +struct gridQueueEle
  2316. +{
  2317. +       int x, y, z;
  2318. +       UCHAR dir ;
  2319. +       gridQueueEle* next ;
  2320. +};
  2321. +
  2322. +class GridQueue
  2323. +{
  2324. +       gridQueueEle* head ;
  2325. +       gridQueueEle* tail ;
  2326. +       int numEles ;
  2327. +
  2328. +public:
  2329. +
  2330. +       GridQueue( )
  2331. +       {
  2332. +               head = NULL ;
  2333. +               tail = NULL ;
  2334. +               numEles = 0 ;
  2335. +       }
  2336. +
  2337. +       gridQueueEle* getHead( )
  2338. +       {
  2339. +               return head ;
  2340. +       }
  2341. +
  2342. +       int getNumElements( )
  2343. +       {
  2344. +               return numEles ;
  2345. +       }
  2346. +
  2347. +
  2348. +       void pushQueue( int st[3], int dir )
  2349. +       {
  2350. +               gridQueueEle* ele = new gridQueueEle ;
  2351. +               ele->x = st[0] ;
  2352. +               ele->y = st[1] ;
  2353. +               ele->z = st[2] ;
  2354. +               ele->dir = (UCHAR) dir ;
  2355. +               ele->next = NULL ;
  2356. +               if ( head == NULL )
  2357. +               {
  2358. +                       head = ele ;
  2359. +               }
  2360. +               else
  2361. +               {
  2362. +                       tail->next = ele ;
  2363. +               }
  2364. +               tail = ele ;
  2365. +               numEles ++ ;
  2366. +       }
  2367. +
  2368. +       int popQueue( int st[3], int& dir )
  2369. +       {
  2370. +               if ( head == NULL )
  2371. +               {
  2372. +                       return 0 ;
  2373. +               }
  2374. +
  2375. +               st[0] = head->x ;
  2376. +               st[1] = head->y ;
  2377. +               st[2] = head->z ;
  2378. +               dir = (int) (head->dir) ;
  2379. +
  2380. +               gridQueueEle* temp = head ;
  2381. +               head = head->next ;
  2382. +               delete temp ;
  2383. +
  2384. +               if ( head == NULL )
  2385. +               {
  2386. +                       tail = NULL ;
  2387. +               }
  2388. +               numEles -- ;
  2389. +
  2390. +               return 1 ;
  2391. +       }
  2392. +
  2393. +};
  2394. +
  2395. +
  2396. +
  2397. +
  2398. +
  2399. +#endif
  2400. \ No newline at end of file
  2401. diff --git a/intern/dualcon/intern/cubes.h b/intern/dualcon/intern/cubes.h
  2402. new file mode 100644
  2403. index 0000000..cd24fed
  2404. --- /dev/null
  2405. +++ b/intern/dualcon/intern/cubes.h
  2406. @@ -0,0 +1,27 @@
  2407. +/* all code originally contributed by Tao Ju */
  2408. +/* modifications by Nicholas Bishop */
  2409. +
  2410. +#ifndef CUBES_H
  2411. +#define CUBES_H
  2412. +
  2413. +#include "marching_cubes_table.h"
  2414. +
  2415. +/* simple wrapper for auto-generated marching cubes data */
  2416. +class Cubes
  2417. +{
  2418. +public:
  2419. +       /// Get number of triangles
  2420. +       int getNumTriangle(int mask)
  2421. +       {
  2422. +               return marching_cubes_numtri[mask];
  2423. +       }
  2424. +
  2425. +       /// Get a triangle
  2426. +       void getTriangle(int mask, int index, int indices[3] )
  2427. +       {
  2428. +               for(int i = 0; i < 3; i++)
  2429. +                       indices[i] = marching_cubes_tris[mask][index][i];
  2430. +       }
  2431. +};
  2432. +
  2433. +#endif
  2434. diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp
  2435. new file mode 100644
  2436. index 0000000..d12fdee
  2437. --- /dev/null
  2438. +++ b/intern/dualcon/intern/dualcon_c_api.cpp
  2439. @@ -0,0 +1,202 @@
  2440. +#include <cassert>
  2441. +#include "dualcon.h"
  2442. +#include "ModelReader.h"
  2443. +#include "octree.h"
  2444. +
  2445. +#include <cstdio>
  2446. +
  2447. +void veccopy(float dst[3], const float src[3])
  2448. +{
  2449. +       dst[0] = src[0];
  2450. +       dst[1] = src[1];
  2451. +       dst[2] = src[2];
  2452. +}
  2453. +
  2454. +#define GET_FACE(_mesh, _n) \
  2455. +       (*(DualConFaces)(((char*)(_mesh)->faces) + ((_n) * (_mesh)->face_stride)))
  2456. +
  2457. +#define GET_CO(_mesh, _n) \
  2458. +       (*(DualConCo)(((char*)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
  2459. +
  2460. +void dualcon_mesh_add_co(DualConMesh *mesh, const float v[3])
  2461. +{
  2462. +       assert(mesh->curco < mesh->totco);
  2463. +
  2464. +       veccopy(GET_CO(mesh, mesh->curco), v);
  2465. +       mesh->curco++;
  2466. +}
  2467. +
  2468. +void dualcon_mesh_add_face(DualConMesh *mesh, int totndx, const int *ndx, int flip)
  2469. +{
  2470. +       int i;
  2471. +       
  2472. +       assert(mesh->curface < mesh->totface);
  2473. +
  2474. +       unsigned int *f = GET_FACE(mesh, mesh->curface);
  2475. +
  2476. +       f[3] = 0;
  2477. +       for(i = 0; i < totndx; i++)
  2478. +               f[i] = ndx[flip ? (totndx - i - 1) : i];
  2479. +       /* TODO: handle quad with last vert zero */
  2480. +
  2481. +       mesh->curface++;
  2482. +}
  2483. +
  2484. +void dualcon_mesh_add_polygon(DualConMesh *mesh, int totndx, const int *ndx, int flip)
  2485. +{
  2486. +       if(totndx <= 4) {
  2487. +               dualcon_mesh_add_face(mesh, totndx, ndx, flip);
  2488. +       }
  2489. +       else {
  2490. +               /* >4 sides, do a simple triangle fan for now */
  2491. +               for(int i = 1; i+1 < totndx; i++) {
  2492. +                       int v[3] = {ndx[0], ndx[i], ndx[i+1]};
  2493. +                       dualcon_mesh_add_face(mesh, 3, v, flip);
  2494. +               }
  2495. +       }
  2496. +}
  2497. +
  2498. +class DualConMeshReader : public ModelReader
  2499. +{
  2500. +private:
  2501. +       const DualConMesh *input_mesh;
  2502. +       int tottri, curface, offset;
  2503. +       float min[3], max[3], maxsize;
  2504. +       float scale;
  2505. +public:
  2506. +       DualConMeshReader(const DualConMesh *mesh, float _scale)
  2507. +       : input_mesh(mesh), scale(_scale)
  2508. +       {
  2509. +               reset();
  2510. +       }
  2511. +
  2512. +       void reset()
  2513. +       {
  2514. +               tottri = 0;
  2515. +               curface = 0;
  2516. +               offset = 0;
  2517. +               maxsize = 0;
  2518. +
  2519. +               /* initialize tottri */
  2520. +               for(int i = 0; i < input_mesh->totface; i++)
  2521. +                       tottri += GET_FACE(input_mesh, i)[3] ? 2 : 1;
  2522. +
  2523. +               veccopy(min, input_mesh->min);
  2524. +               veccopy(max, input_mesh->max);
  2525. +
  2526. +               /* initialize maxsize */
  2527. +               for(int i = 0; i < 3; i++) {
  2528. +                       float d = max[i] - min[i];
  2529. +                       if(d > maxsize)
  2530. +                               maxsize = d;
  2531. +               }
  2532. +
  2533. +               /* redo the bounds */
  2534. +               for(int i = 0; i < 3; i++)
  2535. +               {
  2536. +                       min[i] = (max[i] + min[i]) / 2 - maxsize / 2;
  2537. +                       max[i] = (max[i] + min[i]) / 2 + maxsize / 2;
  2538. +               }
  2539. +
  2540. +               for(int i = 0; i < 3; i++)
  2541. +                       min[i] -= maxsize * (1 / scale - 1) / 2;
  2542. +               maxsize *= 1 / scale;
  2543. +       }
  2544. +
  2545. +       Triangle* getNextTriangle()
  2546. +       {
  2547. +               if(curface == input_mesh->totface)
  2548. +                       return 0;
  2549. +
  2550. +               Triangle* t = new Triangle();
  2551. +              
  2552. +               unsigned int *f = GET_FACE(input_mesh, curface);
  2553. +               if(offset == 0) {
  2554. +                       veccopy(t->vt[0], GET_CO(input_mesh, f[0]));
  2555. +                       veccopy(t->vt[1], GET_CO(input_mesh, f[1]));
  2556. +                       veccopy(t->vt[2], GET_CO(input_mesh, f[2]));
  2557. +               }
  2558. +               else {
  2559. +                       veccopy(t->vt[0], GET_CO(input_mesh, f[2]));
  2560. +                       veccopy(t->vt[1], GET_CO(input_mesh, f[3]));
  2561. +                       veccopy(t->vt[2], GET_CO(input_mesh, f[0]));
  2562. +               }
  2563. +
  2564. +               if(offset == 0 && f[3])
  2565. +                       offset++;
  2566. +               else {
  2567. +                       offset = 0;
  2568. +                       curface++;
  2569. +               }
  2570. +
  2571. +               return t;
  2572. +       }
  2573. +
  2574. +       int getNextTriangle(int t[3])
  2575. +       {
  2576. +               if(curface == input_mesh->totface)
  2577. +                       return 0;
  2578. +              
  2579. +               unsigned int *f = GET_FACE(input_mesh, curface);
  2580. +               if(offset == 0) {
  2581. +                       t[0] = f[0];
  2582. +                       t[1] = f[1];
  2583. +                       t[2] = f[2];
  2584. +               }
  2585. +               else {
  2586. +                       t[0] = f[2];
  2587. +                       t[1] = f[3];
  2588. +                       t[2] = f[0];
  2589. +               }
  2590. +
  2591. +               if(offset == 0 && f[3])
  2592. +                       offset++;
  2593. +               else {
  2594. +                       offset = 0;
  2595. +                       curface++;
  2596. +               }
  2597. +
  2598. +               return 1;
  2599. +       }
  2600. +
  2601. +       int getNumTriangles()
  2602. +       {
  2603. +               return tottri;
  2604. +       }
  2605. +
  2606. +       int getNumVertices()
  2607. +       {
  2608. +               return input_mesh->totco;
  2609. +       }
  2610. +
  2611. +       float getBoundingBox(float origin[3])
  2612. +       {
  2613. +               veccopy(origin, min);
  2614. +               return maxsize ;
  2615. +       }
  2616. +
  2617. +       /* output */
  2618. +       void getNextVertex(float v[3])
  2619. +       {
  2620. +               /* TODO */
  2621. +               printf("BAD BAD BAD\n");
  2622. +       }
  2623. +
  2624. +       /* stubs */
  2625. +       void printInfo() {}
  2626. +       int getMemory() { return sizeof(DualConMeshReader); }
  2627. +};
  2628. +
  2629. +DualConMesh *dualcon(const DualConMesh *input_mesh,
  2630. +                    DualConCreateMesh create_mesh,
  2631. +                    DualConFlags flags,
  2632. +                    DualConMode mode,
  2633. +                    float threshold,
  2634. +                    float hermite_num,
  2635. +                    float scale,
  2636. +                    int depth)
  2637. +{
  2638. +       DualConMeshReader r(input_mesh, scale);
  2639. +       Octree o(&r, flags, mode, depth, threshold, hermite_num);
  2640. +       return o.scanConvert(create_mesh);
  2641. +}
  2642. diff --git a/intern/dualcon/intern/eigen.cpp b/intern/dualcon/intern/eigen.cpp
  2643. new file mode 100644
  2644. index 0000000..43388f9
  2645. --- /dev/null
  2646. +++ b/intern/dualcon/intern/eigen.cpp
  2647. @@ -0,0 +1,757 @@
  2648. +#include "eigen.h"
  2649. +
  2650. +#include <math.h>
  2651. +#include <stdio.h>
  2652. +#include <stdlib.h>
  2653. +#include <assert.h>
  2654. +#define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);a[k][l]=h+s*(g-h*tau);
  2655. +
  2656. +int method = 3;
  2657. +
  2658. +// for reducing two upper triangular systems of equations into 1
  2659. +void qr ( float *mat1, float *mat2, float *rvalue )
  2660. +{
  2661. +       int i, j;
  2662. +       float temp1 [ 8 ] [ 4 ];
  2663. +
  2664. +       for ( i = 0; i < 4; i++ )
  2665. +       {
  2666. +               for ( j = 0; j < i; j++ )
  2667. +               {
  2668. +                       temp1 [ i ] [ j ] = 0;
  2669. +                       temp1 [ i + 4 ] [ j ] = 0;
  2670. +               }
  2671. +               for ( j = i; j < 4; j++ )
  2672. +               {
  2673. +                       temp1 [ i ] [ j ] = mat1 [ ( 7 * i - i * i ) / 2 + j ];
  2674. +                       temp1 [ i + 4 ] [ j ] = mat2 [ ( 7 * i - i * i ) / 2 + j ];
  2675. +               }
  2676. +       }
  2677. +
  2678. +       qr ( temp1, 8, rvalue );
  2679. +}
  2680. +
  2681. +// WARNING: destroys eqs in the process
  2682. +void qr ( float eqs[][4], int num, float *rvalue )
  2683. +{
  2684. +       int i, j, k;
  2685. +
  2686. +       qr ( eqs, num, 0.000001f );
  2687. +       for ( i = 0; i < 10; i++ )
  2688. +       {
  2689. +               rvalue [ i ] = 0;
  2690. +       }
  2691. +
  2692. +       k = 0;
  2693. +       for ( i = 0; i < num && i < 4; i++ )
  2694. +       {
  2695. +               for ( j = i; j < 4; j++ )
  2696. +               {
  2697. +                       rvalue [ k++ ] = eqs [ i ] [ j ];
  2698. +               }
  2699. +       }
  2700. +}
  2701. +
  2702. +void qr ( float eqs[][4], int num, float tol )
  2703. +{
  2704. +       int i, j, k;
  2705. +       float a, b, mag, temp;
  2706. +
  2707. +       for ( i = 0; i < 4 && i < num; i++ )
  2708. +       {
  2709. +               for ( j = i + 1; j < num; j++ )
  2710. +               {
  2711. +                       a = eqs [ i ] [ i ];
  2712. +                       b = eqs [ j ] [ i ];
  2713. +
  2714. +                       if ( fabs ( a ) > 0.000001f || fabs ( b ) > 0.000001f )
  2715. +                       {
  2716. +                               mag = (float)sqrt ( a * a + b * b );
  2717. +                               a /= mag;
  2718. +                               b /= mag;
  2719. +
  2720. +                               for ( k = 0; k < 4; k++ )
  2721. +                               {
  2722. +                                       temp = a * eqs [ i ] [ k ] + b * eqs [ j ] [ k ];
  2723. +                                       eqs [ j ] [ k ] = b * eqs [ i ] [ k ] - a * eqs [ j ] [ k ];
  2724. +                                       eqs [ i ] [ k ] = temp;
  2725. +                               }
  2726. +                       }
  2727. +               }
  2728. +               for ( j = i - 1; j >= 0; j-- )
  2729. +               {
  2730. +                       if ( eqs [ j ] [ j ] < 0.000001f && eqs [ j ] [ j ] > -0.000001f )
  2731. +                       {
  2732. +                               a = eqs [ i ] [ i ];
  2733. +                               b = eqs [ j ] [ i ];
  2734. +
  2735. +                               if ( fabs ( a ) > 0.000001f || fabs ( b ) > 0.000001f )
  2736. +                               {
  2737. +                                       mag = (float)sqrt ( a * a + b * b );
  2738. +                                       a /= mag;
  2739. +                                       b /= mag;
  2740. +
  2741. +                                       for ( k = 0; k < 4; k++ )
  2742. +                                       {
  2743. +                                               temp = a * eqs [ i ] [ k ] + b * eqs [ j ] [ k ];
  2744. +                                               eqs [ j ] [ k ] = b * eqs [ i ] [ k ] - a * eqs [ j ] [ k ];
  2745. +                                               eqs [ i ] [ k ] = temp;
  2746. +                                       }
  2747. +                               }
  2748. +                       }
  2749. +               }
  2750. +       }
  2751. +
  2752. +}
  2753. +
  2754. +void jacobi ( float u[][3], float d[], float v[][3] )
  2755. +{
  2756. +       int j, iq, ip, i;
  2757. +       float tresh, theta, tau, t, sm, s, h, g, c, b [ 3 ], z [ 3 ];
  2758. +       float a [ 3 ] [ 3 ];
  2759. +
  2760. +       a [ 0 ] [ 0 ] = u [ 0 ] [ 0 ];
  2761. +       a [ 0 ] [ 1 ] = u [ 0 ] [ 1 ];
  2762. +       a [ 0 ] [ 2 ] = u [ 0 ] [ 2 ];
  2763. +       a [ 1 ] [ 0 ] = u [ 1 ] [ 0 ];
  2764. +       a [ 1 ] [ 1 ] = u [ 1 ] [ 1 ];
  2765. +       a [ 1 ] [ 2 ] = u [ 1 ] [ 2 ];
  2766. +       a [ 2 ] [ 0 ] = u [ 2 ] [ 0 ];
  2767. +       a [ 2 ] [ 1 ] = u [ 2 ] [ 1 ];
  2768. +       a [ 2 ] [ 2 ] = u [ 2 ] [ 2 ];
  2769. +
  2770. +       for ( ip = 0; ip < 3; ip++ )
  2771. +       {
  2772. +               for ( iq = 0; iq < 3; iq++ )
  2773. +               {
  2774. +                       v [ ip ] [ iq ] = 0.0f;
  2775. +               }
  2776. +               v [ ip ] [ ip ] = 1.0f;
  2777. +       }
  2778. +
  2779. +       for ( ip = 0; ip < 3; ip++ )
  2780. +       {
  2781. +               b [ ip ] = a [ ip ] [ ip ];
  2782. +               d [ ip ] = b [ ip ];
  2783. +               z [ ip ] = 0.0f;
  2784. +       }
  2785. +
  2786. +       for ( i = 1; i <= 50; i++ )
  2787. +       {
  2788. +               sm = 0.0f;
  2789. +               for ( ip = 0; ip < 2; ip++ )
  2790. +               {
  2791. +                       for ( iq = ip + 1; iq < 3; iq++ )
  2792. +                       {
  2793. +                               sm += (float)fabs ( a [ ip ] [ iq ] );
  2794. +                       }
  2795. +               }
  2796. +
  2797. +               if ( sm == 0.0f )
  2798. +               {
  2799. +                       // sort the stupid things and transpose
  2800. +                       a [ 0 ] [ 0 ] = v [ 0 ] [ 0 ];
  2801. +                       a [ 0 ] [ 1 ] = v [ 1 ] [ 0 ];
  2802. +                       a [ 0 ] [ 2 ] = v [ 2 ] [ 0 ];
  2803. +                       a [ 1 ] [ 0 ] = v [ 0 ] [ 1 ];
  2804. +                       a [ 1 ] [ 1 ] = v [ 1 ] [ 1 ];
  2805. +                       a [ 1 ] [ 2 ] = v [ 2 ] [ 1 ];
  2806. +                       a [ 2 ] [ 0 ] = v [ 0 ] [ 2 ];
  2807. +                       a [ 2 ] [ 1 ] = v [ 1 ] [ 2 ];
  2808. +                       a [ 2 ] [ 2 ] = v [ 2 ] [ 2 ];
  2809. +
  2810. +                       if ( fabs ( d [ 0 ] ) < fabs ( d [ 1 ] ) )
  2811. +                       {
  2812. +                               sm = d [ 0 ];
  2813. +                               d [ 0 ] = d [ 1 ];
  2814. +                               d [ 1 ] = sm;
  2815. +
  2816. +                               sm = a [ 0 ] [ 0 ];
  2817. +                               a [ 0 ] [ 0 ] = a [ 1 ] [ 0 ];
  2818. +                               a [ 1 ] [ 0 ] = sm;
  2819. +                               sm = a [ 0 ] [ 1 ];
  2820. +                               a [ 0 ] [ 1 ] = a [ 1 ] [ 1 ];
  2821. +                               a [ 1 ] [ 1 ] = sm;
  2822. +                               sm = a [ 0 ] [ 2 ];
  2823. +                               a [ 0 ] [ 2 ] = a [ 1 ] [ 2 ];
  2824. +                               a [ 1 ] [ 2 ] = sm;
  2825. +                       }
  2826. +                       if ( fabs ( d [ 1 ] ) < fabs ( d [ 2 ] ) )
  2827. +                       {
  2828. +                               sm = d [ 1 ];
  2829. +                               d [ 1 ] = d [ 2 ];
  2830. +                               d [ 2 ] = sm;
  2831. +
  2832. +                               sm = a [ 1 ] [ 0 ];
  2833. +                               a [ 1] [ 0 ] = a [ 2 ] [ 0 ];
  2834. +                               a [ 2 ] [ 0 ] = sm;
  2835. +                               sm = a [ 1 ] [ 1 ];
  2836. +                               a [ 1 ] [ 1 ] = a [ 2 ] [ 1 ];
  2837. +                               a [ 2 ] [ 1 ] = sm;
  2838. +                               sm = a [ 1 ] [ 2 ];
  2839. +                               a [ 1 ] [ 2 ] = a [ 2 ] [ 2 ];
  2840. +                               a [ 2 ] [ 2 ] = sm;
  2841. +                       }
  2842. +                       if ( fabs ( d [ 0 ] ) < fabs ( d [ 1 ] ) )
  2843. +                       {
  2844. +                               sm = d [ 0 ];
  2845. +                               d [ 0 ] = d [ 1 ];
  2846. +                               d [ 1 ] = sm;
  2847. +
  2848. +                               sm = a [ 0 ] [ 0 ];
  2849. +                               a [ 0 ] [ 0 ] = a [ 1 ] [ 0 ];
  2850. +                               a [ 1 ] [ 0 ] = sm;
  2851. +                               sm = a [ 0 ] [ 1 ];
  2852. +                               a [ 0 ] [ 1 ] = a [ 1 ] [ 1 ];
  2853. +                               a [ 1 ] [ 1 ] = sm;
  2854. +                               sm = a [ 0 ] [ 2 ];
  2855. +                               a [ 0 ] [ 2 ] = a [ 1 ] [ 2 ];
  2856. +                               a [ 1 ] [ 2 ] = sm;
  2857. +                       }
  2858. +
  2859. +                       v [ 0 ] [ 0 ] = a [ 0 ] [ 0 ];
  2860. +                       v [ 0 ] [ 1 ] = a [ 0 ] [ 1 ];
  2861. +                       v [ 0 ] [ 2 ] = a [ 0 ] [ 2 ];
  2862. +                       v [ 1 ] [ 0 ] = a [ 1 ] [ 0 ];
  2863. +                       v [ 1 ] [ 1 ] = a [ 1 ] [ 1 ];
  2864. +                       v [ 1 ] [ 2 ] = a [ 1 ] [ 2 ];
  2865. +                       v [ 2 ] [ 0 ] = a [ 2 ] [ 0 ];
  2866. +                       v [ 2 ] [ 1 ] = a [ 2 ] [ 1 ];
  2867. +                       v [ 2 ] [ 2 ] = a [ 2 ] [ 2 ];
  2868. +
  2869. +                       return;
  2870. +               }
  2871. +
  2872. +               if ( i < 4 )
  2873. +               {
  2874. +                       tresh = 0.2f * sm / 9;
  2875. +               }
  2876. +               else
  2877. +               {
  2878. +                       tresh = 0.0f;
  2879. +               }
  2880. +
  2881. +               for ( ip = 0; ip < 2; ip++ )
  2882. +               {
  2883. +                       for ( iq = ip + 1; iq < 3; iq++ )
  2884. +                       {
  2885. +                               g = 100.0f * (float)fabs ( a [ ip ] [ iq ] );
  2886. +                               if ( i > 4 && (float)( fabs ( d [ ip ] ) + g ) == (float)fabs ( d [ ip ] )
  2887. +                                       && (float)( fabs ( d [ iq ] ) + g ) == (float)fabs ( d [ iq ] ) )
  2888. +                               {
  2889. +                                       a [ ip ] [ iq ] = 0.0f;
  2890. +                               }
  2891. +                               else
  2892. +                               {
  2893. +                                       if ( fabs ( a [ ip ] [ iq ] ) > tresh )
  2894. +                                       {
  2895. +                                               h = d [ iq ] - d [ ip ];
  2896. +                                               if ( (float)( fabs ( h ) + g ) == (float)fabs ( h ) )
  2897. +                                               {
  2898. +                                                       t = ( a [ ip ] [ iq ] ) / h;
  2899. +                                               }
  2900. +                                               else
  2901. +                                               {
  2902. +                                                       theta = 0.5f * h / ( a [ ip ] [ iq ] );
  2903. +                                                       t = 1.0f / ( (float)fabs ( theta ) + (float)sqrt ( 1.0f + theta * theta ) );
  2904. +                                                       if ( theta < 0.0f )
  2905. +                                                       {
  2906. +                                                               t = -1.0f * t;
  2907. +                                                       }
  2908. +                                               }
  2909. +
  2910. +                                               c = 1.0f / (float)sqrt ( 1 + t * t );
  2911. +                                               s = t * c;
  2912. +                                               tau = s / ( 1.0f + c );
  2913. +                                               h = t * a [ ip ] [ iq ];
  2914. +                                               z [ ip ] -= h;
  2915. +                                               z [ iq ] += h;
  2916. +                                               d [ ip ] -= h;
  2917. +                                               d [ iq ] += h;
  2918. +                                               a [ ip ] [ iq ] = 0.0f;
  2919. +                                               for ( j = 0; j <= ip - 1; j++ )
  2920. +                                               {
  2921. +                                                       ROTATE ( a, j, ip, j, iq )
  2922. +                                               }
  2923. +                                               for ( j = ip + 1; j <= iq - 1; j++ )
  2924. +                                               {
  2925. +                                                       ROTATE ( a, ip, j, j, iq )
  2926. +                                               }
  2927. +                                               for ( j = iq + 1; j < 3; j++ )
  2928. +                                               {
  2929. +                                                       ROTATE ( a, ip, j, iq, j )
  2930. +                                               }
  2931. +                                               for ( j = 0; j < 3; j++ )
  2932. +                                               {
  2933. +                                                       ROTATE ( v, j, ip, j, iq )
  2934. +                                               }
  2935. +                                       }
  2936. +                               }
  2937. +                       }
  2938. +               }
  2939. +
  2940. +               for ( ip = 0; ip < 3; ip++ )
  2941. +               {
  2942. +                       b [ ip ] += z [ ip ];
  2943. +                       d [ ip ] = b [ ip ];
  2944. +                       z [ ip ] = 0.0f;
  2945. +               }
  2946. +       }
  2947. +       printf ( "too many iterations in jacobi\n" );
  2948. +       exit ( 1 );
  2949. +}
  2950. +
  2951. +int estimateRank ( float *a )
  2952. +{
  2953. +       float w [ 3 ];
  2954. +       float u [ 3 ] [ 3 ];
  2955. +       float mat [ 3 ] [ 3 ];
  2956. +       int i;
  2957. +
  2958. +       mat [ 0 ] [ 0 ] = a [ 0 ];
  2959. +       mat [ 0 ] [ 1 ] = a [ 1 ];
  2960. +       mat [ 0 ] [ 2 ] = a [ 2 ];
  2961. +       mat [ 1 ] [ 1 ] = a [ 3 ];
  2962. +       mat [ 1 ] [ 2 ] = a [ 4 ];
  2963. +       mat [ 2 ] [ 2 ] = a [ 5 ];
  2964. +       mat [ 1 ] [ 0 ] = a [ 1 ];
  2965. +       mat [ 2 ] [ 0 ] = a [ 2 ];
  2966. +       mat [ 2 ] [ 1 ] = a [ 4 ];
  2967. +
  2968. +       jacobi ( mat, w, u );
  2969. +
  2970. +       if ( w [ 0 ] == 0.0f )
  2971. +       {
  2972. +               return 0;
  2973. +       }
  2974. +       else
  2975. +       {
  2976. +               for ( i = 1; i < 3; i++ )
  2977. +               {
  2978. +                       if ( w [ i ] < 0.1f )
  2979. +                       {
  2980. +                               return i;
  2981. +                       }
  2982. +               }
  2983. +
  2984. +               return 3;
  2985. +       }
  2986. +
  2987. +}
  2988. +
  2989. +void matInverse ( float mat[][3], float midpoint[], float rvalue[][3], float w[], float u[][3] )
  2990. +{
  2991. +       // there is an implicit assumption that mat is symmetric and real
  2992. +       // U and V in the SVD will then be the same matrix whose rows are the eigenvectors of mat
  2993. +       // W will just be the eigenvalues of mat
  2994. +//     float w [ 3 ];
  2995. +//     float u [ 3 ] [ 3 ];
  2996. +       int i;
  2997. +
  2998. +       jacobi ( mat, w, u );
  2999. +
  3000. +       if ( w [ 0 ] == 0.0f )
  3001. +       {
  3002. +//             printf ( "error: largest eigenvalue is 0!\n" );
  3003. +       }
  3004. +       else
  3005. +       {
  3006. +               for ( i = 1; i < 3; i++ )
  3007. +               {
  3008. +                       if ( w [ i ] < 0.001f ) // / w [ 0 ] < TOLERANCE )
  3009. +                       {
  3010. +                                       w [ i ] = 0;
  3011. +                       }
  3012. +                       else
  3013. +                       {
  3014. +                               w [ i ] = 1.0f / w [ i ];
  3015. +                       }
  3016. +               }
  3017. +               w [ 0 ] = 1.0f / w [ 0 ];
  3018. +       }
  3019. +
  3020. +       rvalue [ 0 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 0 ] +
  3021. +                                       w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 0 ] +
  3022. +                                       w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 0 ];
  3023. +       rvalue [ 0 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 1 ] +
  3024. +                                       w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 1 ] +
  3025. +                                       w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 1 ];
  3026. +       rvalue [ 0 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 0 ] * u [ 0 ] [ 2 ] +
  3027. +                                       w [ 1 ] * u [ 1 ] [ 0 ] * u [ 1 ] [ 2 ] +
  3028. +                                       w [ 2 ] * u [ 2 ] [ 0 ] * u [ 2 ] [ 2 ];
  3029. +       rvalue [ 1 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 0 ] +
  3030. +                                       w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 0 ] +
  3031. +                                       w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 0 ];
  3032. +       rvalue [ 1 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 1 ] +
  3033. +                                       w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 1 ] +
  3034. +                                       w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 1 ];
  3035. +       rvalue [ 1 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 1 ] * u [ 0 ] [ 2 ] +
  3036. +                                       w [ 1 ] * u [ 1 ] [ 1 ] * u [ 1 ] [ 2 ] +
  3037. +                                       w [ 2 ] * u [ 2 ] [ 1 ] * u [ 2 ] [ 2 ];
  3038. +       rvalue [ 2 ] [ 0 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 0 ] +
  3039. +                                       w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 0 ] +
  3040. +                                       w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 0 ];
  3041. +       rvalue [ 2 ] [ 1 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 1 ] +
  3042. +                                       w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 1 ] +
  3043. +                                       w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 1 ];
  3044. +       rvalue [ 2 ] [ 2 ] = w [ 0 ] * u [ 0 ] [ 2 ] * u [ 0 ] [ 2 ] +
  3045. +                                       w [ 1 ] * u [ 1 ] [ 2 ] * u [ 1 ] [ 2 ] +
  3046. +                                       w [ 2 ] * u [ 2 ] [ 2 ] * u [ 2 ] [ 2 ];
  3047. +}
  3048. +
  3049. +float calcError ( float a[][3], float b[], float btb, float point[] )
  3050. +{
  3051. +       float rvalue = btb;
  3052. +
  3053. +       rvalue += -2.0f * ( point [ 0 ] * b [ 0 ] + point [ 1 ] * b [ 1 ] + point [ 2 ] * b [ 2 ] );
  3054. +       rvalue += point [ 0 ] * ( a [ 0 ] [ 0 ] * point [ 0 ] + a [ 0 ] [ 1 ] * point [ 1 ] + a [ 0 ] [ 2 ] * point [ 2 ] );
  3055. +       rvalue += point [ 1 ] * ( a [ 1 ] [ 0 ] * point [ 0 ] + a [ 1 ] [ 1 ] * point [ 1 ] + a [ 1 ] [ 2 ] * point [ 2 ] );
  3056. +       rvalue += point [ 2 ] * ( a [ 2 ] [ 0 ] * point [ 0 ] + a [ 2 ] [ 1 ] * point [ 1 ] + a [ 2 ] [ 2 ] * point [ 2 ] );
  3057. +
  3058. +       return rvalue;
  3059. +}
  3060. +
  3061. +float *calcNormal ( float halfA[], float norm[], float expectedNorm[] )
  3062. +{
  3063. +/*
  3064. +       float a [ 3 ] [ 3 ];
  3065. +       float w [ 3 ];
  3066. +       float u [ 3 ] [ 3 ];
  3067. +
  3068. +       a [ 0 ] [ 0 ] = halfA [ 0 ];
  3069. +       a [ 0 ] [ 1 ] = halfA [ 1 ];
  3070. +       a [ 0 ] [ 2 ] = halfA [ 2 ];
  3071. +       a [ 1 ] [ 1 ] = halfA [ 3 ];
  3072. +       a [ 1 ] [ 2 ] = halfA [ 4 ];
  3073. +       a [ 1 ] [ 0 ] = halfA [ 1 ];
  3074. +       a [ 2 ] [ 0 ] = halfA [ 2 ];
  3075. +       a [ 2 ] [ 1 ] = halfA [ 4 ];
  3076. +       a [ 2 ] [ 2 ] = halfA [ 5 ];
  3077. +
  3078. +       jacobi ( a, w, u );
  3079. +
  3080. +       if ( u [ 1 ] != 0 )
  3081. +       {
  3082. +               if ( w [ 1 ] / w [ 0 ] > 0.2f )
  3083. +               {
  3084. +                       // two dominant eigen values, just return the expectedNorm
  3085. +                       norm [ 0 ] = expectedNorm [ 0 ];
  3086. +                       norm [ 1 ] = expectedNorm [ 1 ];
  3087. +                       norm [ 2 ] = expectedNorm [ 2 ];
  3088. +                       return;
  3089. +               }
  3090. +       }
  3091. +
  3092. +       norm [ 0 ] = u [ 0 ] [ 0 ];
  3093. +       norm [ 1 ] = u [ 0 ] [ 1 ];
  3094. +       norm [ 2 ] = u [ 0 ] [ 2 ];
  3095. +*/
  3096. +       float dot = norm [ 0 ] * expectedNorm [ 0 ] + norm [ 1 ] * expectedNorm [ 1 ] +
  3097. +                               norm [ 2 ] * expectedNorm [ 2 ];
  3098. +
  3099. +       if ( dot < 0 )
  3100. +       {
  3101. +               norm [ 0 ] *= -1.0f;
  3102. +               norm [ 1 ] *= -1.0f;
  3103. +               norm [ 2 ] *= -1.0f;
  3104. +
  3105. +               dot *= -1.0f;
  3106. +       }
  3107. +
  3108. +       if ( dot < 0.707f )
  3109. +       {
  3110. +               return expectedNorm;
  3111. +       }
  3112. +       else
  3113. +       {
  3114. +               return norm;
  3115. +       }
  3116. +}
  3117. +
  3118. +void descent ( float A[][3], float B[], float guess[], BoundingBoxf *box )
  3119. +{
  3120. +       int i;
  3121. +       float r [ 3 ];
  3122. +       float delta, delta0;
  3123. +       int n = 10;
  3124. +       float alpha, div;
  3125. +       float newPoint [ 3 ];
  3126. +       float c;
  3127. +       float store [ 3 ];
  3128. +
  3129. +       store [ 0 ] = guess [ 0 ];
  3130. +       store [ 1 ] = guess [ 1 ];
  3131. +       store [ 2 ] = guess [ 2 ];
  3132. +
  3133. +       if ( method == 2 || method == 0 )
  3134. +       {
  3135. +
  3136. +       i = 0;
  3137. +       r [ 0 ] = B [ 0 ] - ( A [ 0 ] [ 0 ] * guess [ 0 ] + A [ 0 ] [ 1 ] * guess [ 1 ] + A [ 0 ] [ 2 ] * guess [ 2 ] );
  3138. +       r [ 1 ] = B [ 1 ] - ( A [