package net.nicoptere.marchingcubes { /** * @author nicoptere * http://en.nicoptere.net/ */ import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.geom.Point; public class MarchingCubes { public var _dataset:Dataset; static private var _instance:MarchingCubes; public function MarchingCubes( dataset:Dataset ) { _dataset = dataset; _instance = this; } /** * performs the marching cubes algorithm on a given dataset * @return an array of 3D triangles */ public function compute():Array { var data:Array = dataset.data;// .concat(); var isolevel:Number = dataset.isoLevel; var i:int; var j:int; var k:int; var l:int; var c:int = 0; var n:int; var ntri:int; var X:int = _dataset.x; var Y:int = _dataset.y; var Z:int = _dataset.z; var renderable:Array = []; var grid:GridCell = new GridCell(); for (i = 0; i < X; i++) { for (j = 0; j < Y; j++) { for (k = 0; k < Z; k++) { grid.p[0].x = i; grid.p[0].y = j; grid.p[0].z = k; grid.val[0] = data[i][j][k]; grid.p[1].x = i+1; grid.p[1].y = j; grid.p[1].z = k; grid.val[1] = data[i + 1][j][k]; grid.p[2].x = i+1; grid.p[2].y = j+1; grid.p[2].z = k; grid.val[2] = data[i + 1][j + 1][k]; grid.p[3].x = i; grid.p[3].y = j+1; grid.p[3].z = k; grid.val[3] = data[i][j + 1][k]; grid.p[4].x = i; grid.p[4].y = j; grid.p[4].z = k+1; grid.val[4] = data[i][j][k + 1]; grid.p[5].x = i+1; grid.p[5].y = j; grid.p[5].z = k+1; grid.val[5] = data[i + 1][j][k + 1]; grid.p[6].x = i+1; grid.p[6].y = j+1; grid.p[6].z = k+1; grid.val[6] = data[i + 1][j + 1][k + 1]; grid.p[7].x = i; grid.p[7].y = j+1; grid.p[7].z = k+1; grid.val[7] = data[i][j+1][k+1]; polygonise(grid, isolevel, renderable); } } } return renderable; } //static version of the compute method static public function compute():Array { return _instance.compute(); } /** * assigns the dataset */ public function set dataset( data:Dataset ):void { _dataset = data; } /** * returns the dataset */ public function get dataset():Dataset { return _dataset; } /* Given a grid cell and an isolevel, calculate the triangular facets required to represent the isosurface through the cell. Return the triangular faces, the array "renderable" will be loaded up with the vertices at most 5 triangules. 0 will be returned if the grid cell is either totally above of totally below the isolevel. */ /** * Given a grid cell and an isolevel, calculate the triangular faces required to represent the isosurface through the cell. * @param grid a GridCell instance * @param isolevel the isosurface threshold * @param renderable the array of Triangle that compose the final mesh and will be incremented with at most 5 faces */ public function polygonise( grid:GridCell, isolevel:Number, renderable:Array ):void { var i:int; var p0:Vector3D; var p1:Vector3D; var p2:Vector3D; var cubeindex:int; var vertlist:Array = new Array( 12 ); /* Determine the index into the edge table which tells us which vertices are inside of the surface */ cubeindex = 0; if (grid.val[0] < isolevel) cubeindex |= 1; if (grid.val[1] < isolevel) cubeindex |= 2; if (grid.val[2] < isolevel) cubeindex |= 4; if (grid.val[3] < isolevel) cubeindex |= 8; if (grid.val[4] < isolevel) cubeindex |= 16; if (grid.val[5] < isolevel) cubeindex |= 32; if (grid.val[6] < isolevel) cubeindex |= 64; if (grid.val[7] < isolevel) cubeindex |= 128; // Cube is entirely in/out of the surface if (edgeTable[cubeindex] == 0) { /* //interseting thing to push further:fill teh cubes that are inside the matter */ /* i = grid.val.length; while ( i-- ) { //is outside the shape if ( grid.val[i] >= isolevel ) return; } //is inside the 'matter'. should render a portion of cube ... */ return; } // Find the vertices where the surface intersects the cube if (edgeTable[cubeindex] & 1) { vertlist[0] = VertexInterp(isolevel, grid.p[0], grid.p[1], grid.val[0], grid.val[1]); } if (edgeTable[cubeindex] & 2) { vertlist[1] = VertexInterp(isolevel, grid.p[1], grid.p[2], grid.val[1], grid.val[2]); } if (edgeTable[cubeindex] & 4) { vertlist[2] = VertexInterp(isolevel, grid.p[2], grid.p[3], grid.val[2], grid.val[3]); } if (edgeTable[cubeindex] & 8) { vertlist[3] = VertexInterp(isolevel, grid.p[3], grid.p[0], grid.val[3], grid.val[0]); } if (edgeTable[cubeindex] & 16) { vertlist[4] = VertexInterp(isolevel, grid.p[4], grid.p[5], grid.val[4], grid.val[5]); } if (edgeTable[cubeindex] & 32) { vertlist[5] = VertexInterp(isolevel, grid.p[5], grid.p[6], grid.val[5], grid.val[6]); } if (edgeTable[cubeindex] & 64) { vertlist[6] = VertexInterp(isolevel, grid.p[6], grid.p[7], grid.val[6], grid.val[7]); } if (edgeTable[cubeindex] & 128) { vertlist[7] = VertexInterp(isolevel, grid.p[7], grid.p[4], grid.val[7], grid.val[4]); } if (edgeTable[cubeindex] & 256) { vertlist[8] = VertexInterp(isolevel, grid.p[0], grid.p[4], grid.val[0], grid.val[4]); } if (edgeTable[cubeindex] & 512) { vertlist[9] = VertexInterp(isolevel, grid.p[1], grid.p[5], grid.val[1], grid.val[5]); } if (edgeTable[cubeindex] & 1024) { vertlist[10] = VertexInterp(isolevel, grid.p[2], grid.p[6], grid.val[2], grid.val[6]); } if (edgeTable[cubeindex] & 2048) { vertlist[11] = VertexInterp(isolevel, grid.p[3], grid.p[7], grid.val[3], grid.val[7]); } // Creates the triangles for (i = 0; i < triTable[cubeindex].length; i += 3 ) { if ( vertlist[ triTable[ cubeindex ][ i ] ] != undefined ) { p0 = vertlist[triTable[cubeindex][ i ]] ; p1 = vertlist[triTable[cubeindex][ i + 1 ]]; p2 = vertlist[triTable[cubeindex][ i + 2 ]]; renderable.push( new Triangle( p0, p1, p2 ) ); } } } /* Linearly interpolate the position where an isosurface cuts an edge between two vertices, each with their own scalar value */ public function VertexInterp(isolevel:Number,p1:Vector3D,p2:Vector3D,valp1:Number,valp2:Number):Vector3D { //point is close enough from the corners and is returned as such if (Math.abs(isolevel - valp1) < Number.MIN_VALUE) return(p1); if (Math.abs(isolevel - valp2) < Number.MIN_VALUE) return(p2); if (Math.abs(valp1 - valp2) < Number.MIN_VALUE) return(p1); var mu:Number = (isolevel - valp1) / (valp2 - valp1); var p:Vector3D = new Vector3D(); p.x = p1.x + mu * (p2.x - p1.x); p.y = p1.y + mu * (p2.y - p1.y); p.z = p1.z + mu * (p2.z - p1.z); return p; } //edge list to collecdt the corresponding triangle configuration from the triTable private const edgeTable:Array = [ 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ]; //compact version of the lookup table private const triTable:Array = [ [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 8, 3, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 9, 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 8, 3, 1, 8, 1, 9,-1,-1,-1,-1,-1,-1,-1], [10, 1, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 8, 3, 0, 1, 2,10,-1,-1,-1,-1,-1,-1,-1], [ 9, 0, 2, 9, 2,10,-1,-1,-1,-1,-1,-1,-1], [ 3, 2, 8, 2,10, 8, 8,10, 9,-1,-1,-1,-1], [11, 2, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [11, 2, 0,11, 0, 8,-1,-1,-1,-1,-1,-1,-1], [11, 2, 3, 0, 1, 9,-1,-1,-1,-1,-1,-1,-1], [ 2, 1,11, 1, 9,11,11, 9, 8,-1,-1,-1,-1], [10, 1, 3,10, 3,11,-1,-1,-1,-1,-1,-1,-1], [ 1, 0,10, 0, 8,10,10, 8,11,-1,-1,-1,-1], [ 0, 3, 9, 3,11, 9, 9,11,10,-1,-1,-1,-1], [ 8,10, 9, 8,11,10,-1,-1,-1,-1,-1,-1,-1], [ 8, 4, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 3, 0, 4, 3, 4, 7,-1,-1,-1,-1,-1,-1,-1], [ 1, 9, 0, 8, 4, 7,-1,-1,-1,-1,-1,-1,-1], [ 9, 4, 1, 4, 7, 1, 1, 7, 3,-1,-1,-1,-1], [10, 1, 2, 8, 4, 7,-1,-1,-1,-1,-1,-1,-1], [ 2,10, 1, 0, 4, 7, 0, 7, 3,-1,-1,-1,-1], [ 4, 7, 8, 0, 2,10, 0,10, 9,-1,-1,-1,-1], [ 2, 7, 3, 2, 9, 7, 7, 9, 4, 2,10, 9,-1], [ 2, 3,11, 7, 8, 4,-1,-1,-1,-1,-1,-1,-1], [ 7,11, 4,11, 2, 4, 4, 2, 0,-1,-1,-1,-1], [ 3,11, 2, 4, 7, 8, 9, 0, 1,-1,-1,-1,-1], [ 2, 7,11, 2, 1, 7, 1, 4, 7, 1, 9, 4,-1], [ 8, 4, 7,11,10, 1,11, 1, 3,-1,-1,-1,-1], [11, 4, 7, 1, 4,11, 1,11,10, 1, 0, 4,-1], [ 3, 8, 0, 7,11, 4,11, 9, 4,11,10, 9,-1], [ 7,11, 4, 4,11, 9,11,10, 9,-1,-1,-1,-1], [ 9, 5, 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 3, 0, 8, 4, 9, 5,-1,-1,-1,-1,-1,-1,-1], [ 5, 4, 0, 5, 0, 1,-1,-1,-1,-1,-1,-1,-1], [ 4, 8, 5, 8, 3, 5, 5, 3, 1,-1,-1,-1,-1], [ 2,10, 1, 9, 5, 4,-1,-1,-1,-1,-1,-1,-1], [ 0, 8, 3, 5, 4, 9,10, 1, 2,-1,-1,-1,-1], [10, 5, 2, 5, 4, 2, 2, 4, 0,-1,-1,-1,-1], [ 3, 4, 8, 3, 2, 4, 2, 5, 4, 2,10, 5,-1], [11, 2, 3, 9, 5, 4,-1,-1,-1,-1,-1,-1,-1], [ 9, 5, 4, 8,11, 2, 8, 2, 0,-1,-1,-1,-1], [ 3,11, 2, 1, 5, 4, 1, 4, 0,-1,-1,-1,-1], [ 8, 5, 4, 2, 5, 8, 2, 8,11, 2, 1, 5,-1], [ 5, 4, 9, 1, 3,11, 1,11,10,-1,-1,-1,-1], [ 0, 9, 1, 4, 8, 5, 8,10, 5, 8,11,10,-1], [ 3, 4, 0, 3,10, 4, 4,10, 5, 3,11,10,-1], [ 4, 8, 5, 5, 8,10, 8,11,10,-1,-1,-1,-1], [ 9, 5, 7, 9, 7, 8,-1,-1,-1,-1,-1,-1,-1], [ 0, 9, 3, 9, 5, 3, 3, 5, 7,-1,-1,-1,-1], [ 8, 0, 7, 0, 1, 7, 7, 1, 5,-1,-1,-1,-1], [ 1, 7, 3, 1, 5, 7,-1,-1,-1,-1,-1,-1,-1], [ 1, 2,10, 5, 7, 8, 5, 8, 9,-1,-1,-1,-1], [ 9, 1, 0,10, 5, 2, 5, 3, 2, 5, 7, 3,-1], [ 5, 2,10, 8, 2, 5, 8, 5, 7, 8, 0, 2,-1], [10, 5, 2, 2, 5, 3, 5, 7, 3,-1,-1,-1,-1], [11, 2, 3, 8, 9, 5, 8, 5, 7,-1,-1,-1,-1], [ 9, 2, 0, 9, 7, 2, 2, 7,11, 9, 5, 7,-1], [ 0, 3, 8, 2, 1,11, 1, 7,11, 1, 5, 7,-1], [ 2, 1,11,11, 1, 7, 1, 5, 7,-1,-1,-1,-1], [ 3, 9, 1, 3, 8, 9, 7,11,10, 7,10, 5,-1], [ 9, 1, 0,10, 7,11,10, 5, 7,-1,-1,-1,-1], [ 3, 8, 0, 7,10, 5, 7,11,10,-1,-1,-1,-1], [11, 5, 7,11,10, 5,-1,-1,-1,-1,-1,-1,-1], [10, 6, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 8, 3, 0,10, 6, 5,-1,-1,-1,-1,-1,-1,-1], [ 0, 1, 9, 5,10, 6,-1,-1,-1,-1,-1,-1,-1], [10, 6, 5, 9, 8, 3, 9, 3, 1,-1,-1,-1,-1], [ 1, 2, 6, 1, 6, 5,-1,-1,-1,-1,-1,-1,-1], [ 0, 8, 3, 2, 6, 5, 2, 5, 1,-1,-1,-1,-1], [ 5, 9, 6, 9, 0, 6, 6, 0, 2,-1,-1,-1,-1], [ 9, 6, 5, 3, 6, 9, 3, 9, 8, 3, 2, 6,-1], [ 3,11, 2,10, 6, 5,-1,-1,-1,-1,-1,-1,-1], [ 6, 5,10, 2, 0, 8, 2, 8,11,-1,-1,-1,-1], [ 1, 9, 0, 6, 5,10,11, 2, 3,-1,-1,-1,-1], [ 1,10, 2, 5, 9, 6, 9,11, 6, 9, 8,11,-1], [11, 6, 3, 6, 5, 3, 3, 5, 1,-1,-1,-1,-1], [ 0, 5, 1, 0,11, 5, 5,11, 6, 0, 8,11,-1], [ 0, 5, 9, 0, 3, 5, 3, 6, 5, 3,11, 6,-1], [ 5, 9, 6, 6, 9,11, 9, 8,11,-1,-1,-1,-1], [10, 6, 5, 4, 7, 8,-1,-1,-1,-1,-1,-1,-1], [ 5,10, 6, 7, 3, 0, 7, 0, 4,-1,-1,-1,-1], [ 5,10, 6, 0, 1, 9, 8, 4, 7,-1,-1,-1,-1], [ 4, 5, 9, 6, 7,10, 7, 1,10, 7, 3, 1,-1], [ 7, 8, 4, 5, 1, 2, 5, 2, 6,-1,-1,-1,-1], [ 4, 1, 0, 4, 5, 1, 6, 7, 3, 6, 3, 2,-1], [ 9, 4, 5, 8, 0, 7, 0, 6, 7, 0, 2, 6,-1], [ 4, 5, 9, 6, 3, 2, 6, 7, 3,-1,-1,-1,-1], [ 7, 8, 4, 2, 3,11,10, 6, 5,-1,-1,-1,-1], [11, 6, 7,10, 2, 5, 2, 4, 5, 2, 0, 4,-1], [11, 6, 7, 8, 0, 3, 1,10, 2, 9, 4, 5,-1], [ 6, 7,11, 1,10, 2, 9, 4, 5,-1,-1,-1,-1], [ 6, 7,11, 4, 5, 8, 5, 3, 8, 5, 1, 3,-1], [ 6, 7,11, 4, 1, 0, 4, 5, 1,-1,-1,-1,-1], [ 4, 5, 9, 3, 8, 0,11, 6, 7,-1,-1,-1,-1], [ 9, 4, 5, 7,11, 6,-1,-1,-1,-1,-1,-1,-1], [10, 6, 4,10, 4, 9,-1,-1,-1,-1,-1,-1,-1], [ 8, 3, 0, 9,10, 6, 9, 6, 4,-1,-1,-1,-1], [ 1,10, 0,10, 6, 0, 0, 6, 4,-1,-1,-1,-1], [ 8, 6, 4, 8, 1, 6, 6, 1,10, 8, 3, 1,-1], [ 9, 1, 4, 1, 2, 4, 4, 2, 6,-1,-1,-1,-1], [ 1, 0, 9, 3, 2, 8, 2, 4, 8, 2, 6, 4,-1], [ 2, 4, 0, 2, 6, 4,-1,-1,-1,-1,-1,-1,-1], [ 3, 2, 8, 8, 2, 4, 2, 6, 4,-1,-1,-1,-1], [ 2, 3,11, 6, 4, 9, 6, 9,10,-1,-1,-1,-1], [ 0,10, 2, 0, 9,10, 4, 8,11, 4,11, 6,-1], [10, 2, 1,11, 6, 3, 6, 0, 3, 6, 4, 0,-1], [10, 2, 1,11, 4, 8,11, 6, 4,-1,-1,-1,-1], [ 1, 4, 9,11, 4, 1,11, 1, 3,11, 6, 4,-1], [ 0, 9, 1, 4,11, 6, 4, 8,11,-1,-1,-1,-1], [11, 6, 3, 3, 6, 0, 6, 4, 0,-1,-1,-1,-1], [ 8, 6, 4, 8,11, 6,-1,-1,-1,-1,-1,-1,-1], [ 6, 7,10, 7, 8,10,10, 8, 9,-1,-1,-1,-1], [ 9, 3, 0, 6, 3, 9, 6, 9,10, 6, 7, 3,-1], [ 6, 1,10, 6, 7, 1, 7, 0, 1, 7, 8, 0,-1], [ 6, 7,10,10, 7, 1, 7, 3, 1,-1,-1,-1,-1], [ 7, 2, 6, 7, 9, 2, 2, 9, 1, 7, 8, 9,-1], [ 1, 0, 9, 3, 6, 7, 3, 2, 6,-1,-1,-1,-1], [ 8, 0, 7, 7, 0, 6, 0, 2, 6,-1,-1,-1,-1], [ 2, 7, 3, 2, 6, 7,-1,-1,-1,-1,-1,-1,-1], [ 7,11, 6, 3, 8, 2, 8,10, 2, 8, 9,10,-1], [11, 6, 7,10, 0, 9,10, 2, 0,-1,-1,-1,-1], [ 2, 1,10, 7,11, 6, 8, 0, 3,-1,-1,-1,-1], [ 1,10, 2, 6, 7,11,-1,-1,-1,-1,-1,-1,-1], [ 7,11, 6, 3, 9, 1, 3, 8, 9,-1,-1,-1,-1], [ 9, 1, 0,11, 6, 7,-1,-1,-1,-1,-1,-1,-1], [ 0, 3, 8,11, 6, 7,-1,-1,-1,-1,-1,-1,-1], [11, 6, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [11, 7, 6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 0, 8, 3,11, 7, 6,-1,-1,-1,-1,-1,-1,-1], [ 9, 0, 1,11, 7, 6,-1,-1,-1,-1,-1,-1,-1], [ 7, 6,11, 3, 1, 9, 3, 9, 8,-1,-1,-1,-1], [ 1, 2,10, 6,11, 7,-1,-1,-1,-1,-1,-1,-1], [ 2,10, 1, 7, 6,11, 8, 3, 0,-1,-1,-1,-1], [11, 7, 6,10, 9, 0,10, 0, 2,-1,-1,-1,-1], [ 7, 6,11, 3, 2, 8, 8, 2,10, 8,10, 9,-1], [ 2, 3, 7, 2, 7, 6,-1,-1,-1,-1,-1,-1,-1], [ 8, 7, 0, 7, 6, 0, 0, 6, 2,-1,-1,-1,-1], [ 1, 9, 0, 3, 7, 6, 3, 6, 2,-1,-1,-1,-1], [ 7, 6, 2, 7, 2, 9, 2, 1, 9, 7, 9, 8,-1], [ 6,10, 7,10, 1, 7, 7, 1, 3,-1,-1,-1,-1], [ 6,10, 1, 6, 1, 7, 7, 1, 0, 7, 0, 8,-1], [ 9, 0, 3, 6, 9, 3, 6,10, 9, 6, 3, 7,-1], [ 6,10, 7, 7,10, 8,10, 9, 8,-1,-1,-1,-1], [ 8, 4, 6, 8, 6,11,-1,-1,-1,-1,-1,-1,-1], [11, 3, 6, 3, 0, 6, 6, 0, 4,-1,-1,-1,-1], [ 0, 1, 9, 4, 6,11, 4,11, 8,-1,-1,-1,-1], [ 1, 9, 4,11, 1, 4,11, 3, 1,11, 4, 6,-1], [10, 1, 2,11, 8, 4,11, 4, 6,-1,-1,-1,-1], [10, 1, 2,11, 3, 6, 6, 3, 0, 6, 0, 4,-1], [ 0, 2,10, 0,10, 9, 4,11, 8, 4, 6,11,-1], [ 2,11, 3, 6, 9, 4, 6,10, 9,-1,-1,-1,-1], [ 3, 8, 2, 8, 4, 2, 2, 4, 6,-1,-1,-1,-1], [ 2, 0, 4, 2, 4, 6,-1,-1,-1,-1,-1,-1,-1], [ 1, 9, 0, 3, 8, 2, 2, 8, 4, 2, 4, 6,-1], [ 9, 4, 1, 1, 4, 2, 4, 6, 2,-1,-1,-1,-1], [ 8, 4, 6, 8, 6, 1, 6,10, 1, 8, 1, 3,-1], [ 1, 0,10,10, 0, 6, 0, 4, 6,-1,-1,-1,-1], [ 8, 0, 3, 9, 6,10, 9, 4, 6,-1,-1,-1,-1], [10, 4, 6,10, 9, 4,-1,-1,-1,-1,-1,-1,-1], [ 9, 5, 4, 7, 6,11,-1,-1,-1,-1,-1,-1,-1], [ 4, 9, 5, 3, 0, 8,11, 7, 6,-1,-1,-1,-1], [ 6,11, 7, 4, 0, 1, 4, 1, 5,-1,-1,-1,-1], [ 6,11, 7, 4, 8, 5, 5, 8, 3, 5, 3, 1,-1], [ 6,11, 7, 1, 2,10, 9, 5, 4,-1,-1,-1,-1], [11, 7, 6, 8, 3, 0, 1, 2,10, 9, 5, 4,-1], [11, 7, 6,10, 5, 2, 2, 5, 4, 2, 4, 0,-1], [ 7, 4, 8, 2,11, 3,10, 5, 6,-1,-1,-1,-1], [ 4, 9, 5, 6, 2, 3, 6, 3, 7,-1,-1,-1,-1], [ 9, 5, 4, 8, 7, 0, 0, 7, 6, 0, 6, 2,-1], [ 4, 0, 1, 4, 1, 5, 6, 3, 7, 6, 2, 3,-1], [ 7, 4, 8, 5, 2, 1, 5, 6, 2,-1,-1,-1,-1], [ 4, 9, 5, 6,10, 7, 7,10, 1, 7, 1, 3,-1], [ 5, 6,10, 0, 9, 1, 8, 7, 4,-1,-1,-1,-1], [ 5, 6,10, 7, 0, 3, 7, 4, 0,-1,-1,-1,-1], [10, 5, 6, 4, 8, 7,-1,-1,-1,-1,-1,-1,-1], [ 5, 6, 9, 6,11, 9, 9,11, 8,-1,-1,-1,-1], [ 0, 9, 5, 0, 5, 3, 3, 5, 6, 3, 6,11,-1], [ 0, 1, 5, 0, 5,11, 5, 6,11, 0,11, 8,-1], [11, 3, 6, 6, 3, 5, 3, 1, 5,-1,-1,-1,-1], [ 1, 2,10, 5, 6, 9, 9, 6,11, 9,11, 8,-1], [ 1, 0, 9, 6,10, 5,11, 3, 2,-1,-1,-1,-1], [ 6,10, 5, 2, 8, 0, 2,11, 8,-1,-1,-1,-1], [ 3, 2,11,10, 5, 6,-1,-1,-1,-1,-1,-1,-1], [ 9, 5, 6, 3, 9, 6, 3, 8, 9, 3, 6, 2,-1], [ 5, 6, 9, 9, 6, 0, 6, 2, 0,-1,-1,-1,-1], [ 0, 3, 8, 2, 5, 6, 2, 1, 5,-1,-1,-1,-1], [ 1, 6, 2, 1, 5, 6,-1,-1,-1,-1,-1,-1,-1], [10, 5, 6, 9, 3, 8, 9, 1, 3,-1,-1,-1,-1], [ 0, 9, 1, 5, 6,10,-1,-1,-1,-1,-1,-1,-1], [ 8, 0, 3,10, 5, 6,-1,-1,-1,-1,-1,-1,-1], [10, 5, 6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [11, 7, 5,11, 5,10,-1,-1,-1,-1,-1,-1,-1], [ 3, 0, 8, 7, 5,10, 7,10,11,-1,-1,-1,-1], [ 9, 0, 1,10,11, 7,10, 7, 5,-1,-1,-1,-1], [ 3, 1, 9, 3, 9, 8, 7,10,11, 7, 5,10,-1], [ 2,11, 1,11, 7, 1, 1, 7, 5,-1,-1,-1,-1], [ 0, 8, 3, 2,11, 1, 1,11, 7, 1, 7, 5,-1], [ 9, 0, 2, 9, 2, 7, 2,11, 7, 9, 7, 5,-1], [11, 3, 2, 8, 5, 9, 8, 7, 5,-1,-1,-1,-1], [10, 2, 5, 2, 3, 5, 5, 3, 7,-1,-1,-1,-1], [ 5,10, 2, 8, 5, 2, 8, 7, 5, 8, 2, 0,-1], [ 9, 0, 1,10, 2, 5, 5, 2, 3, 5, 3, 7,-1], [ 1,10, 2, 5, 8, 7, 5, 9, 8,-1,-1,-1,-1], [ 1, 3, 7, 1, 7, 5,-1,-1,-1,-1,-1,-1,-1], [ 8, 7, 0, 0, 7, 1, 7, 5, 1,-1,-1,-1,-1], [ 0, 3, 9, 9, 3, 5, 3, 7, 5,-1,-1,-1,-1], [ 9, 7, 5, 9, 8, 7,-1,-1,-1,-1,-1,-1,-1], [ 4, 5, 8, 5,10, 8, 8,10,11,-1,-1,-1,-1], [ 3, 0, 4, 3, 4,10, 4, 5,10, 3,10,11,-1], [ 0, 1, 9, 4, 5, 8, 8, 5,10, 8,10,11,-1], [ 5, 9, 4, 1,11, 3, 1,10,11,-1,-1,-1,-1], [ 8, 4, 5, 2, 8, 5, 2,11, 8, 2, 5, 1,-1], [ 3, 2,11, 1, 4, 5, 1, 0, 4,-1,-1,-1,-1], [ 9, 4, 5, 8, 2,11, 8, 0, 2,-1,-1,-1,-1], [11, 3, 2, 9, 4, 5,-1,-1,-1,-1,-1,-1,-1], [ 3, 8, 4, 3, 4, 2, 2, 4, 5, 2, 5,10,-1], [10, 2, 5, 5, 2, 4, 2, 0, 4,-1,-1,-1,-1], [ 0, 3, 8, 5, 9, 4,10, 2, 1,-1,-1,-1,-1], [ 2, 1,10, 9, 4, 5,-1,-1,-1,-1,-1,-1,-1], [ 4, 5, 8, 8, 5, 3, 5, 1, 3,-1,-1,-1,-1], [ 5, 0, 4, 5, 1, 0,-1,-1,-1,-1,-1,-1,-1], [ 3, 8, 0, 4, 5, 9,-1,-1,-1,-1,-1,-1,-1], [ 9, 4, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 7, 4,11, 4, 9,11,11, 9,10,-1,-1,-1,-1], [ 3, 0, 8, 7, 4,11,11, 4, 9,11, 9,10,-1], [11, 7, 4, 1,11, 4, 1,10,11, 1, 4, 0,-1], [ 8, 7, 4,11, 1,10,11, 3, 1,-1,-1,-1,-1], [ 2,11, 7, 2, 7, 1, 1, 7, 4, 1, 4, 9,-1], [ 3, 2,11, 4, 8, 7, 9, 1, 0,-1,-1,-1,-1], [ 7, 4,11,11, 4, 2, 4, 0, 2,-1,-1,-1,-1], [ 2,11, 3, 7, 4, 8,-1,-1,-1,-1,-1,-1,-1], [ 2, 3, 7, 2, 7, 9, 7, 4, 9, 2, 9,10,-1], [ 4, 8, 7, 0,10, 2, 0, 9,10,-1,-1,-1,-1], [ 2, 1,10, 0, 7, 4, 0, 3, 7,-1,-1,-1,-1], [10, 2, 1, 8, 7, 4,-1,-1,-1,-1,-1,-1,-1], [ 9, 1, 4, 4, 1, 7, 1, 3, 7,-1,-1,-1,-1], [ 1, 0, 9, 8, 7, 4,-1,-1,-1,-1,-1,-1,-1], [ 3, 4, 0, 3, 7, 4,-1,-1,-1,-1,-1,-1,-1], [ 8, 7, 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 8, 9,10, 8,10,11,-1,-1,-1,-1,-1,-1,-1], [ 0, 9, 3, 3, 9,11, 9,10,11,-1,-1,-1,-1], [ 1,10, 0, 0,10, 8,10,11, 8,-1,-1,-1,-1], [10, 3, 1,10,11, 3,-1,-1,-1,-1,-1,-1,-1], [ 2,11, 1, 1,11, 9,11, 8, 9,-1,-1,-1,-1], [11, 3, 2, 0, 9, 1,-1,-1,-1,-1,-1,-1,-1], [11, 0, 2,11, 8, 0,-1,-1,-1,-1,-1,-1,-1], [11, 3, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 3, 8, 2, 2, 8,10, 8, 9,10,-1,-1,-1,-1], [ 9, 2, 0, 9,10, 2,-1,-1,-1,-1,-1,-1,-1], [ 8, 0, 3, 1,10, 2,-1,-1,-1,-1,-1,-1,-1], [10, 2, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 8, 1, 3, 8, 9, 1,-1,-1,-1,-1,-1,-1,-1], [ 9, 1, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [ 8, 0, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] ]; } }