NOTE: If you’re looking for the older version please refer here.
This script takes point cloud data from the kinect, marches over the points using a marching cubes algorithm and renders a polygonal mesh. As far as I’m aware, it was the first live 3D (actual) rendering done on a kinect.
You’ll need…
- Open kinect.
- Toxiclibs, here.
Installation…
- I wrote an installation guide here, follow it to install open kinect.
- Download the latest toxiclibs library and unzip it.
- Move the unzipped toxiclibs folder into ~/Documents/Processing/libraries/
- Copy the code below and paste it in a new sketch in processing.
- Save the sketch as bubbleBoy.
- Restart processing so it knows to include the new library.
Code…
This is rather long. Basically, instead of including .java files in the sketch directory, I copied the contents into the sketch itself. Processing allows you to do this because it executes and compiles as Java anyway. All that’s needed is a minor tweak involving making marchingCubeTables a static method to allow for static fields. I also don’t include the processing.core files as you don’t need them.
NOTE: If you don’t feel like copying and pasting, I have a zip file with everything you’ll need at the bottom of this page. Just download, copy the toxiclibs library to your “libraries” folder in ~/Documents/Processing/ and copy the bubbleBoy2 directory to you “sketches” folder in ~/Documents/sketches .
import toxi.geom.Vec3D; import processing.opengl.*; //import rui.marchingCubes.*; // kinect import org.openkinect.*; import org.openkinect.processing.*; //import processing.core.PApplet; import java.lang.Math; import java.util.ArrayList; import toxi.geom.Vec3D; MarchingCubes mc; Vec3D rotationAxis; Boolean bUseFill; // kinect Kinect kinect; float a = 0; // Size of kinect image int w = 640; int h = 480; int kWidth = 640; int kHeight = 480; // depth mapping and tilt boolean depth = true; boolean rgb = false; boolean ir = false; float deg = 8; // Start at 15 degrees PImage depthImg; int minDepth = 40; int maxDepth = 860; // set initial record to false boolean record = false; int counter = 0; // print custom file boolean printFile = false; ArrayList points; PrintWriter output; // We'll use a lookup table so that we don't have to repeat the math over and over float[] depthLookUp = new float[2048]; void setup(){ size(1024, 600, OPENGL); Vec3D aabbMin = new Vec3D(-width/2, -height/2, -250); Vec3D aabbMax = new Vec3D(width/2, height/2, 250); Vec3D numPoints = new Vec3D(50,50,50); float isoLevel = 1; mc = new MarchingCubes(this, aabbMin, aabbMax, numPoints, isoLevel); rotationAxis = new Vec3D(); bUseFill = false; // kinect kinect = new Kinect(this); kinect.start(); kinect.enableDepth(true); kinect.tilt(deg); // We don't need the grayscale image in this example // so this makes it more efficient kinect.processDepthImage(false); // get depthImg to constrain depthImg = new PImage(kWidth, kHeight); // Lookup table for all possible depth values (0 - 2047) for (int i = 0; i < depthLookUp.length; i++) { depthLookUp[i] = rawDepthToMeters(i); } points = new ArrayList(); output = createWriter("points.txt"); } void draw(){ background(255); lights(); // kinect int[] depth = kinect.getRawDepth(); int skip = 50; //translate(width/750,height/750,-50); mc.reset(); // original for loop println("entering loop"); int nBalls = 0; for(int x=0; x<w; x+=skip) { for(int y=0; y<h; y+=skip) { int offset = x+y*w; int rawDepth = depth[offset]; if(rawDepth >= minDepth && rawDepth <= maxDepth) { PVector v = depthToWorld(x,y,rawDepth); Vec3D metaBallPos = new Vec3D(v.x * 500, v.y * 300, v.z*300); mc.addMetaBall(metaBallPos, 100, 1); nBalls++; } } } println("done with loop, " + nBalls + " balls"); // end original for loop mc.createMesh(); if(bUseFill){ fill(0,255,0); noStroke(); } else { noFill(); stroke(127); } pushMatrix(); translate(width/2, height/2, 0); rotateX(rotationAxis.x); rotateY(rotationAxis.y); mc.renderMesh(); popMatrix(); } PVector depthToWorld(int x, int y, int depthValue) { final double fx_d = 1.0 / 5.9421434211923247e+02; final double fy_d = 1.0 / 5.9104053696870778e+02; final double cx_d = 3.3930780975300314e+02; final double cy_d = 2.4273913761751615e+02; PVector result = new PVector(); double depth = depthLookUp[depthValue];//rawDepthToMeters(depthValue); result.x = (float)((x - cx_d) * depth * fx_d); result.y = (float)((y - cy_d) * depth * fy_d); result.z = (float)(depth); return result; } float rawDepthToMeters(int depthValue) { if (depthValue < 2047) { return (float)(1.0 / ((double)(depthValue) * -0.0030711016 + 3.3309495161)); } return 0.0f; } void keyPressed(){ if(key == CODED){ if(keyCode == LEFT) rotationAxis.y += 0.05; if(keyCode == RIGHT) rotationAxis.y -= 0.05; if(keyCode == UP) rotationAxis.x -= 0.05; if(keyCode == DOWN) rotationAxis.x += 0.05; } else { if(key == ' '){ bUseFill = !bUseFill; } if(key == 'r' || key == 'R'){ mc.reset(); rotationAxis.set(0,0,0); } } } void stop() { kinect.quit(); super.stop(); } // This is because we can't find fuck all for libraries, so we'll just drop java in here as it's converted at runtime... /** * * * simple class implementing the Marching Cubes algorithm to create 3d volumetric meshes. * based on the code and explanations by Paul Bourke that can be found here: * http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/ * * its dependent on Processing's PApplet and Karsten Schmidt's Vec3D class, * you can find processing here: www.processing.org * and you can find the Vec3D class here: code.google.com/p/toxiclibs * * @author ruimadeira * */ public class MarchingCubes { PApplet p5; public float voxelValues[][][]; protected Vec3D voxels[][][]; protected Vec3D numPoints, aabbMin, aabbMax; protected Vec3D cubeSize; protected Vec3D worldSize; protected float isoLevel; private Vec3D vertList[]; protected ArrayList<MCTriangle> triangles; /** * constructor: * you must define the world bounds, the number of points that will make the grid (in a Vec3D), * and the isoLevel. * @param _p5 * @param _aabbMin * @param _aabbMax * @param _numPoints * @param _isoLevel */ public MarchingCubes(PApplet _p5, Vec3D _aabbMin, Vec3D _aabbMax, Vec3D _numPoints, float _isoLevel){ p5 = _p5; aabbMin = new Vec3D(_aabbMin); aabbMax = new Vec3D(_aabbMax); worldSize = aabbMax.sub(aabbMin); numPoints = new Vec3D(_numPoints); cubeSize = new Vec3D(worldSize.x / (numPoints.x-1), worldSize.y / (numPoints.y-1), worldSize.z / (numPoints.z-1)); voxelValues = new float[(int)numPoints.x][(int)numPoints.y][(int)numPoints.z]; voxels = new Vec3D[(int)numPoints.x][(int)numPoints.y][(int)numPoints.z]; _internalReset(); isoLevel = _isoLevel; vertList = new Vec3D[12]; triangles = new ArrayList<MCTriangle>(); } /** * creates the mesh */ public void createMesh(){ triangles = new ArrayList<MCTriangle>(); for(int i=0; i<numPoints.x-1; i++){ for(int j=0; j<numPoints.y-1; j++){ for(int k=0; k<numPoints.z-1; k++){ polygonise(i, j, k); } } } } /** * returns an ArrayList of MCTriangles with all the triangles that make up the mesh * @return */ public ArrayList<MCTriangle> getMesh(){ return triangles; } /** * copies the mesh triangles into an array and returns * @return */ public MCTriangle[] getMeshToArray(){ MCTriangle _triArray[] = new MCTriangle[triangles.size()]; triangles.toArray(_triArray); return _triArray; } /** * default rendering, renders the mesh */ public void renderMesh(){ MCTriangle tri; p5.beginShape(PApplet.TRIANGLES); for(int i=0; i<triangles.size(); i++){ tri = triangles.get(i); p5.vertex(tri.a.x, tri.a.y, tri.a.z); p5.vertex(tri.b.x, tri.b.y, tri.b.z); p5.vertex(tri.c.x, tri.c.y, tri.c.z); } p5.endShape(); } /** * renders the iso grid. * its useful for debuging. */ public void renderGrid(){ p5.noFill(); p5.stroke(127); p5.beginShape(PApplet.LINES); for(int i=0; i<numPoints.x; i++){ for(int j=0; j<numPoints.y; j++){ for(int k=0; k<numPoints.z-1; k++){ p5.vertex(voxels[i][j][k].x, voxels[i][j][k].y, voxels[i][j][k].z); p5.vertex(voxels[i][j][k+1].x, voxels[i][j][k+1].y, voxels[i][j][k+1].z); } } } for(int i=0; i<numPoints.x; i++){ for(int j=0; j<numPoints.y-1; j++){ for(int k=0; k<numPoints.z; k++){ p5.vertex(voxels[i][j][k].x, voxels[i][j][k].y, voxels[i][j][k].z); p5.vertex(voxels[i][j+1][k].x, voxels[i][j+1][k].y, voxels[i][j+1][k].z); } } } for(int i=0; i<numPoints.x-1; i++){ for(int j=0; j<numPoints.y; j++){ for(int k=0; k<numPoints.z; k++){ p5.vertex(voxels[i][j][k].x, voxels[i][j][k].y, voxels[i][j][k].z); p5.vertex(voxels[i+1][j][k].x, voxels[i+1][j][k].y, voxels[i+1][j][k].z); } } } p5.endShape(); } /** * returns a tridimensional array of the values that each voxel has. * you can use this to define the value of each voxel * @return */ public float[][][] getValues(){ return voxelValues; } /** * return the voxel grid that makes up the iso space, in a three dimensional array. * @return */ public Vec3D[][][] getVoxels(){ return voxels; } /** * sets the iso value of a voxel * * @param posX * @param posY * @param posZ * @param value */ public void setValue(int indexX, int indexY, int indexZ, float value){ if(indexX > -1 && indexX < numPoints.x && indexY > -1 && indexY < numPoints.y && indexZ > -1 && indexZ < numPoints.z){ voxelValues[indexX][indexY][indexZ] = value; } } /** * gets the value of the specified voxel * @param posX * @param posY * @param posZ * @return */ public float getValue(int posX, int posY, int posZ){ if(posX > -1 && posX < numPoints.x && posY > -1 && posY < numPoints.y && posZ > -1 && posZ < numPoints.z){ return voxelValues[posX][posY][posZ]; } return 0; } /** * returns the a specific voxel of the iso space * @param posX * @param posY * @param posZ * @return */ public Vec3D getVoxel(int posX, int posY, int posZ){ if(posX > -1 && posX < numPoints.x && posY > -1 && posY < numPoints.y && posZ > -1 && posZ < numPoints.z){ return voxels[posX][posY][posZ]; } return new Vec3D(0,0,0); } /** * checks if the specified point is inside a voxel cube and returns the voxel. * returns a new Vec3D if point is outside the grid. * @param pos * @return */ public Vec3D getVoxelAtWorldCoord(Vec3D point){ for(int i=0; i<voxels.length-1; i++){ for(int j=0; j<voxels[i].length-1; j++){ for(int k=0; k<voxels[i][j].length-1; k++){ if(point.x >= voxels[i][j][k].x && point.y >= voxels[i][j][k].y && point.z >= voxels[i][j][k].z && point.x <= voxels[i+1][j+1][k+1].x && point.y <= voxels[i+1][j+1][k+1].y && point.z <= voxels[i+1][j+1][k+1].z){ return voxels[i][j][k]; } } } } return new Vec3D(); } /** * adds a metaball, with the specified radius, the grid points * inside the radius will be added the "metaValue" * @param pos * @param radius * @param metaValue */ public void addMetaBall(Vec3D pos, float radius, float metaValue){ float radiusSQ = radius*radius; float distSQ; for(int i=0; i<voxels.length; i++){ for(int j=0; j<voxels[i].length; j++){ for(int k=0; k<voxels[i][j].length; k++){ distSQ = voxels[i][j][k].distanceToSquared(pos); if(distSQ < radiusSQ){ voxelValues[i][j][k] += (1-distSQ / radiusSQ) * metaValue; } } } } } public void addMetaBox(Vec3D aabbMin, Vec3D aabbMax, float metaValue){ for(int i=0; i<voxels.length; i++){ for(int j=0; j<voxels[i].length; j++){ for(int k=0; k<voxels[i][j].length; k++){ if(voxels[i][j][k].x > aabbMin.x && voxels[i][j][k].y > aabbMin.y && voxels[i][j][k].z > aabbMin.z && voxels[i][j][k].x < aabbMax.x && voxels[i][j][k].y < aabbMax.y && voxels[i][j][k].z < aabbMax.z){ PApplet.println("added"); voxelValues[i][j][k] += metaValue; } } } } } /** * returns the maximum voxel value * @return */ public float getMax(){ float _max = voxelValues[0][0][0]; for(int i=0; i<voxels.length; i++){ for(int j=0; j<voxels[i].length; j++){ for(int k=1; k<voxels[i][j].length; k++){ if(_max < voxelValues[i][j][k])_max = voxelValues[i][j][k]; } } } return _max; } /** * returns the lowest voxel value * @return */ public float getMin(){ float _min = voxelValues[0][0][0]; for(int i=0; i<voxels.length; i++){ for(int j=0; j<voxels[i].length; j++){ for(int k=1; k<voxels[i][j].length; k++){ if(_min > voxelValues[i][j][k])_min = voxelValues[i][j][k]; } } } return _min; } /** * multiplies all grid values with _val * @param _val */ public void scale(float _val){ for(int i=0; i<voxels.length; i++){ for(int j=0; j<voxels[i].length; j++){ for(int k=0; k<voxels[i][j].length; k++){ voxelValues[i][j][k] *= _val; } } } } /** * sets all grid values with _val * @param _val */ public void set(float _val){ for(int i=0; i<voxels.length; i++){ for(int j=0; j<voxels[i].length; j++){ for(int k=0; k<voxels[i][j].length; k++){ voxelValues[i][j][k] = _val; } } } } /** * sets the grid point with specified index with the value * @param indexX * @param indexY * @param indexZ * @param val */ public void set(int indexX, int indexY, int indexZ, float val){ if(indexX >-1 && indexX < numPoints.x && indexY >-1 && indexY < numPoints.y && indexZ >-1 && indexZ < numPoints.z){ voxelValues[indexX][indexY][indexZ] = val; } } /** * normalizes the voxel values */ public void normalize(){ float maxVal = 0; for(int i=0; i<numPoints.x; i++){ for(int j=0; j<numPoints.y; j++){ for(int k=0; k<numPoints.z; k++){ if(voxelValues[i][j][k] > maxVal) maxVal = voxelValues[i][j][k]; } } } float invertMaxVal = 1.0f/maxVal; for(int i=0; i<numPoints.x; i++){ for(int j=0; j<numPoints.y; j++){ for(int k=0; k<numPoints.z; k++){ voxelValues[i][j][k] *= invertMaxVal; } } } } /** * resets the voxel values to zero */ public void reset(){ for(int i=0; i<numPoints.x; i++){ for(int j=0; j<numPoints.y; j++){ for(int k=0; k<numPoints.z; k++){ voxelValues[i][j][k] = 0; } } } } /** * redefines the minimum bounds of the iso space * @param _aabbMin */ public void setAABBMin(Vec3D _aabbMin){ aabbMin.set(_aabbMin); _internalReset(); } /** * returns the minimum bound of the iso space * @return */ public Vec3D getAABBMin(){ return aabbMin; } /** * redefines the maximum bound of the iso space * @param _aabbMax */ public void setAABBMax(Vec3D _aabbMax){ aabbMax.set(_aabbMax); _internalReset(); } /** * returns the maximum bound of the iso space * @return */ public Vec3D getAABBMax(){ return aabbMax; } /** * returns the number of triangles that make up the mesh * @return */ public int getNumTriangles(){ return triangles.size(); } /** * returns the iso level * @return */ public float getIsoLevel(){ return isoLevel; } /** * sets the iso level * @param _isoLevel */ public void setIsoLevel(float _isoLevel){ isoLevel = _isoLevel; } /** * returns the number of vertexes that make up the iso space * in a Vec3D: the x value represents the number of elements along the X axis, * the y value the number of elements along the Y axis and the z value the number * of elements along the Z axis * @return */ public Vec3D getNumVoxels(){ return numPoints; } /** * redefines the number of voxels that make up the grid * @param _numPoints */ public void setNumVoxels(Vec3D _numPoints){ numPoints.set(_numPoints.x, _numPoints.y, _numPoints.z); voxels = new Vec3D[(int)numPoints.x][(int)numPoints.y][(int)numPoints.z]; voxelValues = new float[(int)numPoints.x][(int)numPoints.y][(int)numPoints.z]; _internalReset(); } /** * returns the size of a single cube of the iso space * @return */ public Vec3D getCubeSize(){ return cubeSize; } /** * returns the total size of the iso space * @return */ public Vec3D getWorldSize(){ return worldSize; } //Internals protected void _internalReset(){ for(int i=0; i<numPoints.x; i++){ for(int j=0; j<numPoints.y; j++){ for(int k=0; k<numPoints.z; k++){ voxels[i][j][k] = new Vec3D(cubeSize.x * i, cubeSize.y * j, cubeSize.z * k); voxels[i][j][k].x += aabbMin.x; voxels[i][j][k].y += aabbMin.y; voxels[i][j][k].z += aabbMin.z; voxelValues[i][j][k] = 0; } } } } protected void polygonise(int i, int j, int k){ int cubeIndex = 0; if (voxelValues[i][j][k] < isoLevel) cubeIndex |= 1; if (voxelValues[i+1][j][k] < isoLevel) cubeIndex |= 2; if (voxelValues[i+1][j+1][k] < isoLevel) cubeIndex |= 4; if (voxelValues[i][j+1][k] < isoLevel) cubeIndex |= 8; if (voxelValues[i][j][k+1] < isoLevel) cubeIndex |= 16; if (voxelValues[i+1][j][k+1] < isoLevel) cubeIndex |= 32; if (voxelValues[i+1][j+1][k+1] < isoLevel) cubeIndex |= 64; if (voxelValues[i][j+1][k+1] < isoLevel) cubeIndex |= 128; /* Cube is entirely in/out of the surface */ if (MarchingCubesTables.edgeTable[cubeIndex] == 0){ return; } /* Find the vertices where the surface intersects the cube */ if ((MarchingCubesTables.edgeTable[cubeIndex] & 1) > 0){ vertList[0] = vertexInterp(isoLevel, voxels[i][j][k], voxels[i+1][j][k], voxelValues[i][j][k] ,voxelValues[i+1][j][k]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 2) > 0){ vertList[1] = vertexInterp(isoLevel, voxels[i+1][j][k], voxels[i+1][j+1][k], voxelValues[i+1][j][k], voxelValues[i+1][j+1][k]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 4) > 0){ vertList[2] = vertexInterp(isoLevel, voxels[i+1][j+1][k], voxels[i][j+1][k], voxelValues[i+1][j+1][k], voxelValues[i][j+1][k]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 8 ) > 0){ vertList[3] = vertexInterp(isoLevel, voxels[i][j+1][k], voxels[i][j][k], voxelValues[i][j+1][k], voxelValues[i][j][k]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 16) > 0){ vertList[4] = vertexInterp(isoLevel, voxels[i][j][k+1], voxels[i+1][j][k+1], voxelValues[i][j][k+1], voxelValues[i+1][j][k+1]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 32) > 0){ vertList[5] = vertexInterp(isoLevel, voxels[i+1][j][k+1], voxels[i+1][j+1][k+1], voxelValues[i+1][j][k+1], voxelValues[i+1][j+1][k+1]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 64) > 0){ vertList[6] = vertexInterp(isoLevel, voxels[i+1][j+1][k+1], voxels[i][j+1][k+1], voxelValues[i+1][j+1][k+1], voxelValues[i][j+1][k+1]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 128) > 0){ vertList[7] = vertexInterp(isoLevel, voxels[i][j+1][k+1], voxels[i][j][k+1], voxelValues[i][j+1][k+1], voxelValues[i][j][k+1]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 256) > 0){ vertList[8] = vertexInterp(isoLevel, voxels[i][j][k], voxels[i][j][k+1], voxelValues[i][j][k], voxelValues[i][j][k+1]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 512) > 0){ vertList[9] = vertexInterp(isoLevel, voxels[i+1][j][k], voxels[i+1][j][k+1], voxelValues[i+1][j][k], voxelValues[i+1][j][k+1]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 1024) > 0){ vertList[10] = vertexInterp(isoLevel, voxels[i+1][j+1][k], voxels[i+1][j+1][k+1], voxelValues[i+1][j+1][k], voxelValues[i+1][j+1][k+1]); } if ((MarchingCubesTables.edgeTable[cubeIndex] & 2048) > 0){ vertList[11] = vertexInterp(isoLevel, voxels[i][j+1][k], voxels[i][j+1][k+1], voxelValues[i][j+1][k], voxelValues[i][j+1][k+1]); } Vec3D vecA; Vec3D vecB; Vec3D normalVec = new Vec3D(); for(i=0; MarchingCubesTables.triTable[cubeIndex][i] != -1; i+=3){ vecA = vertList[MarchingCubesTables.triTable[cubeIndex][i+1]].sub(vertList[MarchingCubesTables.triTable[cubeIndex][i]]); vecB = vertList[MarchingCubesTables.triTable[cubeIndex][i+2]].sub(vertList[MarchingCubesTables.triTable[cubeIndex][i+1]]); normalVec = vecA.cross(vecB); Vec3D triA = new Vec3D(vertList[MarchingCubesTables.triTable[cubeIndex][i]].x, vertList[MarchingCubesTables.triTable[cubeIndex][i]].y, vertList[MarchingCubesTables.triTable[cubeIndex][i]].z); Vec3D triB = new Vec3D(vertList[MarchingCubesTables.triTable[cubeIndex][i+1]].x, vertList[MarchingCubesTables.triTable[cubeIndex][i+1]].y, vertList[MarchingCubesTables.triTable[cubeIndex][i+1]].z); Vec3D triC = new Vec3D(vertList[MarchingCubesTables.triTable[cubeIndex][i+2]].x, vertList[MarchingCubesTables.triTable[cubeIndex][i+2]].y, vertList[MarchingCubesTables.triTable[cubeIndex][i+2]].z); triangles.add(new MCTriangle(triA, triB, triC, normalVec)); } } protected Vec3D vertexInterp(float _isoLevel, Vec3D vertice, Vec3D vertice2, float valP1, float valP2){ float mu; Vec3D p = new Vec3D(); if (Math.abs(isoLevel-valP1) < 0.00001) return(vertice); if (Math.abs(isoLevel-valP2) < 0.00001) return(vertice2); if (Math.abs(valP1-valP2) < 0.00001) return(vertice); mu = (isoLevel - valP1) / (valP2 - valP1); p.x = vertice.x + mu * (vertice2.x - vertice.x); p.y = vertice.y + mu * (vertice2.y - vertice.y); p.z = vertice.z + mu * (vertice2.z - vertice.z); return p; } } /** * * tables, dont mess with these :) * @author ruimadeira * */ public static final class MarchingCubesTables { public static final int edgeTable[] = { 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 }; public static final int triTable[][] = { {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1}, {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}, {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}, {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1}, {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1}, {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1}, {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}, {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1}, {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1}, {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1}, {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}, {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1}, {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1}, {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1}, {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1}, {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1}, {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1}, {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1}, {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1}, {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}, {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1}, {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1}, {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}, {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1}, {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1}, {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1}, {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1}, {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1}, {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1}, {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}, {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1}, {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1}, {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1}, {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1}, {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1}, {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1}, {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1}, {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1}, {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1}, {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1}, {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1}, {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1}, {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1}, {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1}, {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1}, {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1}, {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1}, {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1}, {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1}, {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1}, {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1}, {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}, {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}, {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}, {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1}, {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}, {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1}, {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1}, {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1}, {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1}, {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1}, {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1}, {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1}, {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1}, {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1}, {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1}, {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1}, {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1}, {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1}, {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1}, {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1}, {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1}, {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1}, {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1}, {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}, {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1}, {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1}, {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1}, {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1}, {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1}, {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1}, {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1}, {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1}, {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1}, {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1}, {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1}, {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1}, {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1}, {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1}, {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1}, {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1}, {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1}, {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1}, {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1}, {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1}, {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1}, {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1}, {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1}, {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1}, {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1}, {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1}, {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1}, {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1}, {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1}, {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1}, {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1}, {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1}, {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1}, {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1}, {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1}, {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} }; } import toxi.geom.Vec3D; /** * simple container for triangle vertices and normal * @author ruimadeira * */ public class MCTriangle { public Vec3D a, b, c, normal; MCTriangle(){ } MCTriangle(Vec3D _a, Vec3D _b, Vec3D _c){ a = new Vec3D(_a); b = new Vec3D(_b); c = new Vec3D(_c); normal = new Vec3D(); } MCTriangle(Vec3D _a, Vec3D _b, Vec3D _c, Vec3D _norm){ a = new Vec3D(_a); b = new Vec3D(_b); c = new Vec3D(_c); normal = new Vec3D(_norm); } }
Phew! I know, it’s a lot of code, but look how much you have to play with now!
Nice!
What do I add to the code to make this alien green like your screengrab?!
Hi blobbyboy,
Just hit the spacebar after you load the script and it’s running. It’s preprogrammed to turn green, but try playing with it and come up with you’re own color.
Mike
Haha!! nice job!!!
how can i increase the depth range?
i have tried here, but it doesnt feel like its only that:
float rawDepthToMeters(int depthValue) {
if (depthValue < 8047) {
return (float)(1.0 / ((double)(depthValue) * -0.0030711016 + 3.3309495161));
}
thanks for sharing 🙂
does this run on windows too
I would also like to know how to increase the depth. Please get back to us. Thanks for sharing!
bubbleBoy2 Error
No library found for toxi.geom
What’s up with that?
How would you go by positioning the bubble on x,y,z axis?
How could you make multiples of the same bubble?