UnityMol  0.9.6-875
UnityMol viewer / In developement
MarchingCubes.cs
Go to the documentation of this file.
1 using UnityEngine;
2 using System.Collections;
3 using System.Collections.Generic;
4 
5 public class MarchingCubes {
6  //Function delegates, makes using functions pointers easier
7  delegate void MODE_FUNC(Vector3 pos, float[] cube, List<Vector3> vertList, List<int> indexList);
8  //Function poiter to what mode to use, cubes or tetrahedrons
9  static MODE_FUNC Mode_Func = MarchCube;
10  private static EdgeGrid edgeGrid;
11  public static VertexTree vertexTree;
12  //Set the mode to use
13  //Cubes is faster and creates less verts, tetrahedrons is slower and creates more verts but better represents the mesh surface
14 
15  static int[,] m_sampler = new int[,] {
16  {1,-1,0}, {1,-1,1}, {0,-1,1}, {-1,-1,1}, {-1,-1,0}, {-1,-1,-1}, {0,-1,-1}, {1,-1,-1}, {0,-1,0},
17  {1,0,0}, {1,0,1}, {0,0,1}, {-1,0,1}, {-1,0,0}, {-1,0,-1}, {0,0,-1}, {1,0,-1}, {0,0,0},
18  {1,1,0}, {1,1,1}, {0,1,1}, {-1,1,1}, {-1,1,0}, {-1,1,-1}, {0,1,-1}, {1,1,-1}, {0,1,0}
19  };
20 
21  static public void SetModeToCubes() { Mode_Func = MarchCube; }
22  static public void SetModeToTetrahedrons() { Mode_Func = MarchCubeTetrahedron; }
23 
24  static public void SetTarget(float tar) { target = tar; }
25  static public void SetWindingOrder(int v0, int v1, int v2) { windingOrder = new int[]{ v0, v1, v2 }; }
26 
27 
28  //static public Mesh CreateMesh(float[,,] voxels, int xStart, int xEnd,
29  static public MeshData CreateMesh(float[,,] voxels, int xStart, int xEnd,
30  int yStart, int yEnd,
31  int zStart, int zEnd) {
32  List<Vector3> verts = new List<Vector3>();
33  List<int> index = new List<int>();
34 
35  float[] cube = new float[8];
36  int vXDim = voxels.GetLength(0);
37  int vYDim = voxels.GetLength(1);
38  int vZDim = voxels.GetLength(2);
39 
40  Vector3 lowerBound = Vector3.zero;
41  Vector3 upperBound = new Vector3(vXDim, vYDim, vZDim);
42 
43  //Debug.Log("MarchingCubes::CreateMesh() > Creating the vertex tree: " + Time.time.ToString());
44  vertexTree = new VertexTree(lowerBound, upperBound);
45 
46  // Gaps otherwise
47  if(xStart > 0)
48  xStart--;
49  if(yStart > 0)
50  yStart--;
51  if(zStart > 0)
52  zStart--;
53 
54  for(int x = xStart; x < xEnd-1; x++) {
55  for(int y = yStart; y < yEnd-1; y++) {
56  for(int z = zStart; z < zEnd-1; z++) {
57  //Get the values in the 8 neighbours which make up a cube
58  FillCube(x,y,z,voxels,cube);
59  //Perform algorithm
60  Mode_Func(new Vector3(x,y,z), cube, verts, index);
61  }
62  }
63  }
64  //Debug.Log("MarchingCubes::CreateMesh() > End of vertex tree creation: " + Time.realtimeSinceStartup.ToString());
65 
66  // Mesh mesh = new Mesh();
67  MeshData mData = new MeshData();
68  // mData = GenerateMesh.AutoWeld(index.ToArray(), verts.ToArray());
69 
70  mData.triangles = index.ToArray();
71  mData.vertices = verts.ToArray();
72 
73  /*
74  if(mData.vertices.Length > 65000) {
75  //If you get this error its means that the voxels array contaions to much information and
76  //a mesh larger than 65000 verts is need to represent it. You can fix this by using a smaller arrays of voxel,
77  //make less 'noisey' data, or manually split up the mesh into sub meshes.
78  Debug.Log("MarchingCubes::CreateMesh - Number of mesh verts greater than 65000. Cannot create mesh");
79  Debug.Log(mData.vertices.Length.ToString());
80  return null;
81  }
82  */
83 
84 
85  /*
86  Debug.Log("MarchingCubes::CreateMesh() > Number of vertices and triangles created:");
87  Debug.Log(mData.vertices.Length.ToString());
88  Debug.Log( (mData.triangles.Length / 3).ToString());
89  */
90 
91  /*
92  mesh.Clear();
93  mesh.vertices = mData.vertices;
94  mesh.triangles = mData.triangles;
95 
96  return mesh;
97  */
98  return mData;
99  }
100 
101  /*
102  private static Vector3 TriLinearInterpNormal(Vector3 pos, Vector3[,,] m_normals) {
103  int x = (int)pos.x;
104  int y = (int)pos.y;
105  int z = (int)pos.z;
106 
107  float fx = pos.x-x;
108  float fy = pos.y-y;
109  float fz = pos.z-z;
110 
111  Vector3 x0 = m_normals[x,y,z] * (1.0f-fx) + m_normals[x+1,y,z] * fx;
112  Vector3 x1 = m_normals[x,y,z+1] * (1.0f-fx) + m_normals[x+1,y,z+1] * fx;
113 
114  Vector3 x2 = m_normals[x,y+1,z] * (1.0f-fx) + m_normals[x+1,y+1,z] * fx;
115  Vector3 x3 = m_normals[x,y+1,z+1] * (1.0f-fx) + m_normals[x+1,y+1,z+1] * fx;
116 
117  Vector3 z0 = x0 * (1.0f-fz) + x1 * fz;
118  Vector3 z1 = x2 * (1.0f-fz) + x3 * fz;
119 
120  return z0 * (1.0f - fy) + z1 * fy;
121  }
122  */
123 
124  static void FillCube(int x, int y, int z, float[,,] voxels, float[] cube) {
125  for(int i = 0; i < 8; i++)
126  cube[i] = voxels[x + vertexOffset[i,0], y + vertexOffset[i,1], z + vertexOffset[i,2]];
127  }
128 
129  // GetOffset finds the approximate point of intersection of the surface
130  // between two points with the values v1 and v2
131  static float GetOffset(float v1, float v2) {
132  float delta = v2 - v1;
133  return (delta == 0.0f) ? 0.5f : (target - v1)/delta;
134  }
135 
136  public static float[,,] SmoothVoxels(float[,,] m_voxels) {
137  //float startTime = Time.realtimeSinceStartup;
138 
139  // This averages a voxel with all its neighbours. It is an optional step
140  // but I think it looks nicer. You might want to do a fancier smoothing step
141  // like a gaussian blur
142 
143  int w = m_voxels.GetLength(0);
144  int h = m_voxels.GetLength(1);
145  int l = m_voxels.GetLength(2);
146 
147  float[,,] smoothedVoxels = new float[w,h,l];
148 
149  for(int x = 1; x < w-1; x++) {
150  for(int y = 1; y < h-1; y++) {
151  for(int z = 1; z < l-1; z++) {
152  float ht = 0.0f;
153 
154  for(int i = 0; i < 27; i++)
155  ht += m_voxels[x + m_sampler[i,0], y + m_sampler[i,1], z + m_sampler[i,2]];
156 
157  smoothedVoxels[x,y,z] = ht/27.0f;
158  }
159  }
160  }
161  return smoothedVoxels;
162  //Debug.Log("Smooth voxels time = " + (Time.realtimeSinceStartup-startTime).ToString() );
163  }
164 /*
165  public static Vector3[,,] CalculateNormals(float[,,] m_voxels) {
166  //float startTime = Time.realtimeSinceStartup;
167 
168  //This calculates the normal of each voxel. If you have a 3d array of data
169  //the normal is the derivitive of the x, y and z axis.
170  //Normally you need to flip the normal (*-1) but it is not needed in this case.
171  //If you dont call this function the normals that Unity generates for a mesh are used.
172  Vector3[,,] m_normals;
173 
174  int w = m_voxels.GetLength(0);
175  int h = m_voxels.GetLength(1);
176  int l = m_voxels.GetLength(2);
177 
178  m_normals = new Vector3[w,h,l];
179 
180  for(int x = 2; x < w-2; x++) {
181  for(int y = 2; y < h-2; y++) {
182  for(int z = 2; z < l-2; z++) {
183  float dx = m_voxels[x+1,y,z] - m_voxels[x-1,y,z];
184  float dy = m_voxels[x,y+1,z] - m_voxels[x,y-1,z];
185  float dz = m_voxels[x,y,z+1] - m_voxels[x,y,z-1];
186 
187  m_normals[x,y,z] = Vector3.Normalize(new Vector3(dx,dy,dz));
188  }
189  }
190  }
191  return m_normals;
192  }
193 */
194 
195  //MarchCube performs the Marching Cubes algorithm on a single cube
196  static void MarchCube(Vector3 pos, float[] cube, List<Vector3> vertList, List<int> indexList) {
197  int i, j, vert, idx;
198  int flagIndex = 0;
199  float offset = 0.0f;
200 
201  Vector3[] edgeVertex = new Vector3[12];
202 
203  //Find which vertices are inside of the surface and which are outside
204  for(i = 0; i < 8; i++) if(cube[i] <= target) flagIndex |= 1<<i;
205 
206  //Find which edges are intersected by the surface
207  int edgeFlags = cubeEdgeFlags[flagIndex];
208 
209  //If the cube is entirely inside or outside of the surface, then there will be no intersections
210  if(edgeFlags == 0) return;
211 
212  //Find the point of intersection of the surface with each edge
213  for(i = 0; i < 12; i++) {
214  //if there is an intersection on this edge
215  if((edgeFlags & (1<<i)) != 0) {
216  offset = GetOffset(cube[edgeConnection[i,0]], cube[edgeConnection[i,1]]);
217 
218  edgeVertex[i].x = pos.x + (vertexOffset[edgeConnection[i,0],0] + offset * edgeDirection[i,0]);
219  edgeVertex[i].y = pos.y + (vertexOffset[edgeConnection[i,0],1] + offset * edgeDirection[i,1]);
220  edgeVertex[i].z = pos.z + (vertexOffset[edgeConnection[i,0],2] + offset * edgeDirection[i,2]);
221  }
222  }
223 
224  //Save the triangles that were found. There can be up to five per cubes
225  for(i = 0; i < 5; i++) {
226  if(triangleConnectionTable[flagIndex,3*i] < 0) break;
227  idx = vertList.Count;
228  int usualIndex = idx;
229  for(j = 0; j < 3; j++) {
230  vert = triangleConnectionTable[flagIndex,3*i+j]; // index of the vertex in internal cube coordinates
231  //int usualIndex = idx+windingOrder[j]; // index of the vertex in the vertexList, in the usual implementation
232  int cullingIndex = 0;
233  cullingIndex = vertexTree.AddVertex(edgeVertex[vert], usualIndex);
234 
235  if(usualIndex == cullingIndex) { // The vertex was NOT already in the tree
236  indexList.Add(usualIndex);
237  vertList.Add(edgeVertex[vert]);
238  usualIndex++;
239  } else { // The vertex was already in the tree, its index is cullingIndex
240  indexList.Add(cullingIndex);
241  }
242  }
243  }
244  }
245 
246  //MarchTetrahedron performs the Marching Tetrahedrons algorithm on a single tetrahedron
247  static void MarchTetrahedron(Vector3[] tetrahedronPosition, float[] tetrahedronValue, List<Vector3> vertList, List<int> indexList) {
248  int i, j, vert, vert0, vert1, idx;
249  int flagIndex = 0, edgeFlags;
250  float offset, invOffset;
251 
252  Vector3[] edgeVertex = new Vector3[6];
253 
254  //Find which vertices are inside of the surface and which are outside
255  for(i = 0; i < 4; i++) if(tetrahedronValue[i] <= target) flagIndex |= 1<<i;
256 
257  //Find which edges are intersected by the surface
258  edgeFlags = tetrahedronEdgeFlags[flagIndex];
259 
260  //If the tetrahedron is entirely inside or outside of the surface, then there will be no intersections
261  if(edgeFlags == 0) return;
262 
263  //Find the point of intersection of the surface with each edge
264  for(i = 0; i < 6; i++) {
265  //if there is an intersection on this edge
266  if((edgeFlags & (1<<i)) != 0) {
267  vert0 = tetrahedronEdgeConnection[i,0];
268  vert1 = tetrahedronEdgeConnection[i,1];
269  offset = GetOffset(tetrahedronValue[vert0], tetrahedronValue[vert1]);
270  invOffset = 1.0f - offset;
271 
272  edgeVertex[i].x = invOffset*tetrahedronPosition[vert0].x + offset*tetrahedronPosition[vert1].x;
273  edgeVertex[i].y = invOffset*tetrahedronPosition[vert0].y + offset*tetrahedronPosition[vert1].y;
274  edgeVertex[i].z = invOffset*tetrahedronPosition[vert0].z + offset*tetrahedronPosition[vert1].z;
275  }
276  }
277 
278  //Save the triangles that were found. There can be up to 2 per tetrahedron
279  for(i = 0; i < 2; i++) {
280  if(tetrahedronTriangles[flagIndex,3*i] < 0) break;
281  idx = vertList.Count;
282 
283  for(j = 0; j < 3; j++) {
284  vert = tetrahedronTriangles[flagIndex,3*i+j];
285  indexList.Add(idx+windingOrder[j]);
286  vertList.Add(edgeVertex[vert]);
287  }
288  }
289  }
290 
291  //MarchCubeTetrahedron performs the Marching Tetrahedrons algorithm on a single cube
292  static void MarchCubeTetrahedron(Vector3 pos, float[] cube, List<Vector3> vertList, List<int> indexList) {
293  int i, j, vertexInACube;
294  Vector3[] cubePosition = new Vector3[8];
295  Vector3[] tetrahedronPosition = new Vector3[4];
296  float[] tetrahedronValue = new float[4];
297 
298  //Make a local copy of the cube's corner positions
299  for(i = 0; i < 8; i++) cubePosition[i] = new Vector3( pos.x + vertexOffset[i,0], pos.y + vertexOffset[i,1], pos.z + vertexOffset[i,2]);
300 
301  for(i = 0; i < 6; i++) {
302  for(j = 0; j < 4; j++) {
303  vertexInACube = tetrahedronsInACube[i,j];
304  tetrahedronPosition[j] = cubePosition[vertexInACube];
305  tetrahedronValue[j] = cube[vertexInACube];
306  }
307  MarchTetrahedron(tetrahedronPosition, tetrahedronValue, vertList, indexList);
308  }
309  }
310 
311  //Target is the value that represents the surface of mesh
312  //For example a range of -1 to 1, 0 would be the mid point were we want the surface to cut through
313  //The target value does not have to be the mid point it can be any value with in the range
314  static float target = 0.5f;
315 
316  //Winding order of triangles use 2,1,0 or 0,1,2
317  static int[] windingOrder = new int[] { 0, 1, 2 };
318 
319  // vertexOffset lists the positions, relative to vertex0, of each of the 8 vertices of a cube
320  // vertexOffset[8][3]
321 
322  static int[,] vertexOffset = new int[,] {
323  {0, 0, 0},{1, 0, 0},{1, 1, 0},{0, 1, 0},
324  {0, 0, 1},{1, 0, 1},{1, 1, 1},{0, 1, 1}
325  };
326 
327  // edgeConnection lists the index of the endpoint vertices for each of the 12 edges of the cube
328  // edgeConnection[12][2]
329 
330  static int[,] edgeConnection = new int[,] {
331  {0,1}, {1,2}, {2,3}, {3,0},
332  {4,5}, {5,6}, {6,7}, {7,4},
333  {0,4}, {1,5}, {2,6}, {3,7}
334  };
335 
336  // edgeDirection lists the direction vector (vertex1-vertex0) for each edge in the cube
337  // edgeDirection[12][3]
338 
339  static float[,] edgeDirection = new float[,] {
340  {1.0f, 0.0f, 0.0f},{0.0f, 1.0f, 0.0f},{-1.0f, 0.0f, 0.0f},{0.0f, -1.0f, 0.0f},
341  {1.0f, 0.0f, 0.0f},{0.0f, 1.0f, 0.0f},{-1.0f, 0.0f, 0.0f},{0.0f, -1.0f, 0.0f},
342  {0.0f, 0.0f, 1.0f},{0.0f, 0.0f, 1.0f},{ 0.0f, 0.0f, 1.0f},{0.0f, 0.0f, 1.0f}
343  };
344 
345  // tetrahedronEdgeConnection lists the index of the endpoint vertices for each of the 6 edges of the tetrahedron
346  // tetrahedronEdgeConnection[6][2]
347 
348  static int[,] tetrahedronEdgeConnection = new int[,] {
349  {0,1}, {1,2}, {2,0}, {0,3}, {1,3}, {2,3}
350  };
351 
352  // tetrahedronEdgeConnection lists the index of verticies from a cube
353  // that made up each of the six tetrahedrons within the cube
354  // tetrahedronsInACube[6][4]
355 
356  static int[,] tetrahedronsInACube = new int[,] {
357  {0,5,1,6},
358  {0,1,2,6},
359  {0,2,3,6},
360  {0,3,7,6},
361  {0,7,4,6},
362  {0,4,5,6}
363  };
364 
365  // For any edge, if one vertex is inside of the surface and the other is outside of the surface
366  // then the edge intersects the surface
367  // For each of the 4 vertices of the tetrahedron can be two possible states : either inside or outside of the surface
368  // For any tetrahedron the are 2^4=16 possible sets of vertex states
369  // This table lists the edges intersected by the surface for all 16 possible vertex states
370  // There are 6 edges. For each entry in the table, if edge #n is intersected, then bit #n is set to 1
371  // tetrahedronEdgeFlags[16]
372 
373  static int[] tetrahedronEdgeFlags = new int[] {
374  0x00, 0x0d, 0x13, 0x1e, 0x26, 0x2b, 0x35, 0x38, 0x38, 0x35, 0x2b, 0x26, 0x1e, 0x13, 0x0d, 0x00
375  };
376 
377 
378  // For each of the possible vertex states listed in tetrahedronEdgeFlags there is a specific triangulation
379  // of the edge intersection points. tetrahedronTriangles lists all of them in the form of
380  // 0-2 edge triples with the list terminated by the invalid value -1.
381  // tetrahedronTriangles[16][7]
382 
383  static int[,] tetrahedronTriangles = new int[,] {
384  {-1, -1, -1, -1, -1, -1, -1},
385  { 0, 3, 2, -1, -1, -1, -1},
386  { 0, 1, 4, -1, -1, -1, -1},
387  { 1, 4, 2, 2, 4, 3, -1},
388 
389  { 1, 2, 5, -1, -1, -1, -1},
390  { 0, 3, 5, 0, 5, 1, -1},
391  { 0, 2, 5, 0, 5, 4, -1},
392  { 5, 4, 3, -1, -1, -1, -1},
393 
394  { 3, 4, 5, -1, -1, -1, -1},
395  { 4, 5, 0, 5, 2, 0, -1},
396  { 1, 5, 0, 5, 3, 0, -1},
397  { 5, 2, 1, -1, -1, -1, -1},
398 
399  { 3, 4, 2, 2, 4, 1, -1},
400  { 4, 1, 0, -1, -1, -1, -1},
401  { 2, 3, 0, -1, -1, -1, -1},
402  {-1, -1, -1, -1, -1, -1, -1}
403  };
404 
405  // For any edge, if one vertex is inside of the surface and the other is outside of the surface
406  // then the edge intersects the surface
407  // For each of the 8 vertices of the cube can be two possible states : either inside or outside of the surface
408  // For any cube the are 2^8=256 possible sets of vertex states
409  // This table lists the edges intersected by the surface for all 256 possible vertex states
410  // There are 12 edges. For each entry in the table, if edge #n is intersected, then bit #n is set to 1
411  // cubeEdgeFlags[256]
412 
413  static int[] cubeEdgeFlags = new int[] {
414  0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
415  0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
416  0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
417  0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
418  0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
419  0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
420  0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
421  0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
422  0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
423  0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
424  0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
425  0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460,
426  0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
427  0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230,
428  0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190,
429  0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000
430  };
431 
432  // For each of the possible vertex states listed in cubeEdgeFlags there is a specific triangulation
433  // of the edge intersection points. triangleConnectionTable lists all of them in the form of
434  // 0-5 edge triples with the list terminated by the invalid value -1.
435  // For example: triangleConnectionTable[3] list the 2 triangles formed when corner[0]
436  // and corner[1] are inside of the surface, but the rest of the cube is not.
437  // triangleConnectionTable[256][16]
438 
439  static int[,] triangleConnectionTable = new int[,] {
440  {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
441  {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
442  {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
443  {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
444  {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
445  {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
446  {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
447  {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
448  {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
449  {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
450  {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
451  {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
452  {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
453  {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
454  {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
455  {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
456  {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
457  {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
458  {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
459  {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
460  {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
461  {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
462  {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
463  {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
464  {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
465  {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
466  {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
467  {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
468  {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
469  {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
470  {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
471  {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
472  {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
473  {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
474  {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
475  {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
476  {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
477  {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
478  {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
479  {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
480  {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
481  {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
482  {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
483  {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
484  {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
485  {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
486  {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
487  {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
488  {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
489  {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
490  {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
491  {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
492  {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
493  {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
494  {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
495  {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
496  {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
497  {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
498  {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
499  {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
500  {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
501  {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
502  {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
503  {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
504  {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
505  {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
506  {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
507  {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
508  {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
509  {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
510  {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
511  {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
512  {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
513  {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
514  {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
515  {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
516  {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
517  {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
518  {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
519  {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
520  {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
521  {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
522  {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
523  {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
524  {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
525  {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
526  {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
527  {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
528  {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
529  {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
530  {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
531  {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
532  {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
533  {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
534  {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
535  {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
536  {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
537  {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
538  {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
539  {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
540  {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
541  {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
542  {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
543  {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
544  {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
545  {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
546  {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
547  {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
548  {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
549  {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
550  {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
551  {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
552  {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
553  {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
554  {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
555  {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
556  {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
557  {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
558  {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
559  {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
560  {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
561  {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
562  {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
563  {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
564  {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
565  {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
566  {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
567  {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
568  {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
569  {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
570  {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
571  {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
572  {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
573  {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
574  {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
575  {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
576  {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
577  {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
578  {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
579  {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
580  {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
581  {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
582  {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
583  {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
584  {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
585  {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
586  {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
587  {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
588  {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
589  {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
590  {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
591  {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
592  {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
593  {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
594  {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
595  {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
596  {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
597  {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
598  {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
599  {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
600  {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
601  {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
602  {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
603  {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
604  {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
605  {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
606  {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
607  {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
608  {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
609  {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
610  {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
611  {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
612  {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
613  {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
614  {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
615  {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
616  {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
617  {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
618  {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
619  {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
620  {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
621  {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
622  {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
623  {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
624  {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
625  {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
626  {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
627  {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
628  {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
629  {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
630  {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
631  {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
632  {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
633  {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
634  {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
635  {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
636  {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
637  {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
638  {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
639  {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
640  {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
641  {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
642  {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
643  {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
644  {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
645  {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
646  {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
647  {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
648  {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
649  {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
650  {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
651  {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
652  {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
653  {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
654  {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
655  {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
656  {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
657  {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
658  {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
659  {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
660  {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
661  {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
662  {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
663  {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
664  {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
665  {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
666  {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
667  {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
668  {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
669  {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
670  {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
671  {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
672  {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
673  {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
674  {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
675  {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
676  {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
677  {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
678  {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
679  {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
680  {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
681  {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
682  {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
683  {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
684  {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
685  {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
686  {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
687  {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
688  {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
689  {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
690  {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
691  {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
692  {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
693  {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
694  {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
695  {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
696  };
697 }
static int[,] m_sampler
static float GetOffset(float v1, float v2)
static void SetModeToCubes()
static void MarchTetrahedron(Vector3[] tetrahedronPosition, float[] tetrahedronValue, List< Vector3 > vertList, List< int > indexList)
static float[,,] SmoothVoxels(float[,,] m_voxels)
static void SetWindingOrder(int v0, int v1, int v2)
static MODE_FUNC Mode_Func
Definition: MarchingCubes.cs:9
static int[,] tetrahedronTriangles
int AddVertex(Vector3 v, int ind)
Definition: VertexTree.cs:111
static int[] tetrahedronEdgeFlags
delegate void MODE_FUNC(Vector3 pos, float[] cube, List< Vector3 > vertList, List< int > indexList)
static int[] windingOrder
static void FillCube(int x, int y, int z, float[,,] voxels, float[] cube)
static int[] cubeEdgeFlags
static MeshData CreateMesh(float[,,] voxels, int xStart, int xEnd, int yStart, int yEnd, int zStart, int zEnd)
int[] triangles
Definition: MeshData.cs:5
Vector3[] vertices
Definition: MeshData.cs:6
static int[,] vertexOffset
static float target
static void MarchCube(Vector3 pos, float[] cube, List< Vector3 > vertList, List< int > indexList)
static void SetTarget(float tar)
static float[,] edgeDirection
static void SetModeToTetrahedrons()
static EdgeGrid edgeGrid
static VertexTree vertexTree
static int[,] tetrahedronsInACube
static int[,] edgeConnection
static void MarchCubeTetrahedron(Vector3 pos, float[] cube, List< Vector3 > vertList, List< int > indexList)
static int[,] tetrahedronEdgeConnection
static int[,] triangleConnectionTable