package electrosphere.render; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.joml.Matrix4f; import org.joml.Vector3f; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL33; import org.lwjgl.opengl.GL44; import org.lwjgl.opengl.GL45; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; import electrosphere.FluidSim; public class Mesh { public static int vaoPtr; static int vertBufferPtr; static int normBufferPtr; static int faceBufferPtr; static int shaderProgram; public static int elementCount = 0; static Matrix4f viewMatrix = new Matrix4f(); static Matrix4f projectionMatrix = new Matrix4f(); static Matrix4f model = new Matrix4f().identity(); static MemoryStack stack = MemoryStack.create(4 * 1000 * 1000); public static void meshInitially(FluidSim sim){ //create and bind vao vaoPtr = GL44.glGenVertexArrays(); GL44.glBindVertexArray(vaoPtr); //generate verts TerrainChunkData data = generateTerrainChunkData(sim.getData()); // //Buffer data to GPU // vertBufferPtr = GL44.glGenBuffers(); GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, vertBufferPtr); try { int vertexCount = data.vertices.size(); FloatBuffer vertData = BufferUtils.createFloatBuffer(vertexCount); for(float vertValue : data.vertices){ vertData.put(vertValue); } vertData.flip(); GL44.glBufferData(GL44.GL_ARRAY_BUFFER,vertData,GL44.GL_STATIC_DRAW); GL44.glVertexAttribPointer(0, 3, GL44.GL_FLOAT, false, 0, 0); GL44.glEnableVertexAttribArray(0); // MemoryUtil.memFree(vertData); } catch (NullPointerException ex){ ex.printStackTrace(); } // // FACES // faceBufferPtr = GL44.glGenBuffers(); GL44.glBindBuffer(GL44.GL_ELEMENT_ARRAY_BUFFER, faceBufferPtr); elementCount = data.elements.size(); try { IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(elementCount); for(int element : data.elements){ elementArrayBufferData.put(element); } elementArrayBufferData.flip(); GL44.glBufferData(GL45.GL_ELEMENT_ARRAY_BUFFER,elementArrayBufferData,GL44.GL_STATIC_DRAW); // MemoryUtil.memFree(elementArrayBufferData); } catch (NullPointerException ex){ ex.printStackTrace(); } // // NORMALS // normBufferPtr = GL44.glGenBuffers(); GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, normBufferPtr); try { int normalCount = data.normals.size() / 3; FloatBuffer NormalArrayBufferData; if(normalCount > 0){ NormalArrayBufferData = BufferUtils.createFloatBuffer(normalCount * 3); float[] temp = new float[3]; for(float normalValue : data.normals){ NormalArrayBufferData.put(normalValue); } NormalArrayBufferData.flip(); GL44.glBufferData(GL44.GL_ARRAY_BUFFER,NormalArrayBufferData,GL44.GL_STATIC_DRAW); GL44.glVertexAttribPointer(1, 3, GL44.GL_FLOAT, false, 0, 0); GL44.glEnableVertexAttribArray(1); MemoryUtil.memFree(NormalArrayBufferData); } } catch (NullPointerException ex){ ex.printStackTrace(); } String vsSrc = ""; ClassLoader classloader = Thread.currentThread().getContextClassLoader(); try (BufferedReader is = new BufferedReader(new InputStreamReader(classloader.getResourceAsStream("shader.vs")))){ String temp; while((temp = is.readLine())!=null){ vsSrc = vsSrc + temp + "\n"; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } String fsSrc = ""; try (BufferedReader is = new BufferedReader(new InputStreamReader(classloader.getResourceAsStream("shader.fs")))){ String temp; while((temp = is.readLine())!=null){ fsSrc = fsSrc + temp + "\n"; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // //Create shader // int vertexShader = GL45.glCreateShader(GL45.GL_VERTEX_SHADER); GL45.glShaderSource(vertexShader, vsSrc); //Compiles the source for the vertex shader object GL45.glCompileShader(vertexShader); //The following tests if the vertex shader compiles successfully int success; success = GL45.glGetShaderi(vertexShader, GL45.GL_COMPILE_STATUS); if (success != GL45.GL_TRUE) { System.err.println("Vertex Shader failed to compile!"); System.err.println("Source is: "); System.err.println(GL45.glGetShaderSource(vertexShader)); System.err.println(GL45.glGetShaderInfoLog(vertexShader)); } //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader int fragmentShader = GL45.glCreateShader(GL45.GL_FRAGMENT_SHADER); //This points the opengl shadder object to its proper source GL45.glShaderSource(fragmentShader, fsSrc); //This compiles the shader object GL45.glCompileShader(fragmentShader); //This tests for the success of the compile attempt success = GL45.glGetShaderi(fragmentShader, GL45.GL_COMPILE_STATUS); if (success != GL45.GL_TRUE) { System.err.println("Fragment Shader failed to compile!"); System.err.println("Source is: "); System.err.println(GL45.glGetShaderSource(fragmentShader)); System.err.println(GL45.glGetShaderInfoLog(fragmentShader)); } //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram shaderProgram = GL45.glCreateProgram(); //This attaches the vertex and fragment shaders to the program GL45.glAttachShader(shaderProgram, vertexShader); GL45.glAttachShader(shaderProgram, fragmentShader); //This links the program to the GPU (I think its to the GPU anyway) GL45.glLinkProgram(shaderProgram); //Tests for the success of the shader program creation success = GL45.glGetProgrami(shaderProgram, GL45.GL_LINK_STATUS); if (success != GL45.GL_TRUE) { throw new RuntimeException(GL45.glGetProgramInfoLog(shaderProgram)); } //Deletes the individual shader objects to free up memory GL45.glDeleteShader(vertexShader); GL45.glDeleteShader(fragmentShader); //bind shader GL45.glUseProgram(shaderProgram); viewMatrix = new Matrix4f(); viewMatrix.setLookAt(new Vector3f(-8,20,0), new Vector3f(8,8,8), new Vector3f(0,1,0)); projectionMatrix = new Matrix4f(); projectionMatrix.setPerspective(90,1920.0f/1080.0f,0.0001f,1000f); model = new Matrix4f().identity(); GL45.glUniformMatrix4fv(GL45.glGetUniformLocation(shaderProgram, "view"), false, viewMatrix.get(new float[16])); GL45.glUniformMatrix4fv(GL45.glGetUniformLocation(shaderProgram, "projection"), false, projectionMatrix.get(new float[16])); GL45.glUniformMatrix4fv(GL45.glGetUniformLocation(shaderProgram, "model"), false, model.get(new float[16])); } public static void remesh(FluidSim sim){ //generate verts TerrainChunkData data = generateTerrainChunkData(sim.getData()); try(MemoryStack stackLocal = stack.push()){ // //Buffer data to GPU // GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, vertBufferPtr); try { int vertexCount = data.vertices.size(); FloatBuffer vertData = stackLocal.mallocFloat(vertexCount); for(float vertValue : data.vertices){ vertData.put(vertValue); } vertData.flip(); GL44.glBufferData(GL44.GL_ARRAY_BUFFER,vertData,GL44.GL_STATIC_DRAW); GL44.glVertexAttribPointer(0, 3, GL44.GL_FLOAT, false, 0, 0); GL44.glEnableVertexAttribArray(0); } catch (NullPointerException ex){ ex.printStackTrace(); } // // FACES // GL44.glBindBuffer(GL44.GL_ELEMENT_ARRAY_BUFFER, faceBufferPtr); elementCount = data.elements.size(); try { IntBuffer elementArrayBufferData = stackLocal.mallocInt(elementCount); for(int element : data.elements){ elementArrayBufferData.put(element); } elementArrayBufferData.flip(); GL44.glBufferData(GL45.GL_ELEMENT_ARRAY_BUFFER,elementArrayBufferData,GL44.GL_STATIC_DRAW); } catch (NullPointerException ex){ ex.printStackTrace(); } // // NORMALS // GL44.glBindBuffer(GL44.GL_ARRAY_BUFFER, normBufferPtr); try { int normalCount = data.normals.size() / 3; FloatBuffer NormalArrayBufferData; if(normalCount > 0){ NormalArrayBufferData = stackLocal.mallocFloat(normalCount * 3); for(float normalValue : data.normals){ NormalArrayBufferData.put(normalValue); } NormalArrayBufferData.flip(); GL44.glBufferData(GL44.GL_ARRAY_BUFFER,NormalArrayBufferData,GL44.GL_STATIC_DRAW); GL44.glVertexAttribPointer(1, 3, GL44.GL_FLOAT, false, 0, 0); GL44.glEnableVertexAttribArray(1); } } catch (NullPointerException ex){ ex.printStackTrace(); } } } static float angle = 0; public static void draw(){ GL45.glUseProgram(shaderProgram); GL45.glBindFramebuffer(GL45.GL_FRAMEBUFFER, 0); GL44.glBindVertexArray(vaoPtr); // angle = angle + 0.01f; // viewMatrix.identity().setLookAt( // new Vector3f( // 10 * (float)Math.cos(angle), // 10, // 10 * (float)Math.sin(angle)), // new Vector3f(8,8,8), // new Vector3f(0,1,0)); GL45.glUniformMatrix4fv(GL45.glGetUniformLocation(shaderProgram, "view"), false, viewMatrix.get(new float[16])); GL45.glUniformMatrix4fv(GL45.glGetUniformLocation(shaderProgram, "projection"), false, projectionMatrix.get(new float[16])); GL45.glUniformMatrix4fv(GL45.glGetUniformLocation(shaderProgram, "model"), false, model.get(new float[16])); GL44.glDrawElements(GL44.GL_TRIANGLES, Mesh.elementCount, GL44.GL_UNSIGNED_INT, 0); } //http://paulbourke.net/geometry/polygonise/ static 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 }; //256 by 16 static 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} }; private static final byte[] BLOCK_PICK_BITS_BY_VERT_INDEX = new byte[]{ (byte)0x67, (byte)0x26, (byte)0x23, (byte)0x37, (byte)0x45, (byte)0x04, (byte)0x01, (byte)0x15, (byte)0x57, (byte)0x46, (byte)0x02, (byte)0x13 }; static class Triangle { int[] indices = new int[3]; //array of size 3 public Triangle(int index0, int index1, int index2){ indices[0] = index0; indices[1] = index1; indices[2] = index2; } } static class GridCell { Vector3f[] points = new Vector3f[8]; //array of size 8 double[] val = new double[8]; //array of size 8 public void setValues( Vector3f p1, Vector3f p2, Vector3f p3, Vector3f p4, Vector3f p5, Vector3f p6, Vector3f p7, Vector3f p8, double val1, double val2, double val3, double val4, double val5, double val6, double val7, double val8 ){ points[0] = p1; points[1] = p2; points[2] = p3; points[3] = p4; points[4] = p5; points[5] = p6; points[6] = p7; points[7] = p8; val[0] = val1; val[1] = val2; val[2] = val3; val[3] = val4; val[4] = val5; val[5] = val6; val[6] = val7; val[7] = val8; } } protected static int polygonize( GridCell grid, double isolevel, List triangles, Map vertMap, List verts, List normals, List trianglesSharingVert ){ int i; int ntriang; int cubeIndex = 0; Vector3f[] vertList = new Vector3f[12]; //get lookup key (index) for edge table //edge table tells us which vertices are inside of the surface 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) return(0); //instead of having all intersections be perfectly at the midpoint, //for each edge this code calculates where along the edge to place the vertex //this should dramatically smooth the surface if ((edgeTable[cubeIndex] & 1) > 0) vertList[0] = VertexInterp(isolevel,grid.points[0],grid.points[1],grid.val[0],grid.val[1]); if ((edgeTable[cubeIndex] & 2) > 0) vertList[1] = VertexInterp(isolevel,grid.points[1],grid.points[2],grid.val[1],grid.val[2]); if ((edgeTable[cubeIndex] & 4) > 0) vertList[2] = VertexInterp(isolevel,grid.points[2],grid.points[3],grid.val[2],grid.val[3]); if ((edgeTable[cubeIndex] & 8) > 0) vertList[3] = VertexInterp(isolevel,grid.points[3],grid.points[0],grid.val[3],grid.val[0]); if ((edgeTable[cubeIndex] & 16) > 0) vertList[4] = VertexInterp(isolevel,grid.points[4],grid.points[5],grid.val[4],grid.val[5]); if ((edgeTable[cubeIndex] & 32) > 0) vertList[5] = VertexInterp(isolevel,grid.points[5],grid.points[6],grid.val[5],grid.val[6]); if ((edgeTable[cubeIndex] & 64) > 0) vertList[6] = VertexInterp(isolevel,grid.points[6],grid.points[7],grid.val[6],grid.val[7]); if ((edgeTable[cubeIndex] & 128) > 0) vertList[7] = VertexInterp(isolevel,grid.points[7],grid.points[4],grid.val[7],grid.val[4]); if ((edgeTable[cubeIndex] & 256) > 0) vertList[8] = VertexInterp(isolevel,grid.points[0],grid.points[4],grid.val[0],grid.val[4]); if ((edgeTable[cubeIndex] & 512) > 0) vertList[9] = VertexInterp(isolevel,grid.points[1],grid.points[5],grid.val[1],grid.val[5]); if ((edgeTable[cubeIndex] & 1024) > 0) vertList[10] = VertexInterp(isolevel,grid.points[2],grid.points[6],grid.val[2],grid.val[6]); if ((edgeTable[cubeIndex] & 2048) > 0) vertList[11] = VertexInterp(isolevel,grid.points[3],grid.points[7],grid.val[3],grid.val[7]); //Create the triangle ntriang = 0; for (i=0; triTable[cubeIndex][i]!=-1; i+=3) { // // Triangles calculation // //get indices Vector3f vert0 = vertList[triTable[cubeIndex][i+0]]; Vector3f vert1 = vertList[triTable[cubeIndex][i+1]]; Vector3f vert2 = vertList[triTable[cubeIndex][i+2]]; int index0 = getVertIndex(vert0,vertMap,verts); int index1 = getVertIndex(vert1,vertMap,verts); int index2 = getVertIndex(vert2,vertMap,verts); //add 0's to normals until it matches vert count while(trianglesSharingVert.size() < verts.size()){ trianglesSharingVert.add(0); normals.add(new Vector3f()); } //add new triangle Triangle newTriangle = new Triangle(index0,index1,index2); triangles.add(newTriangle); ntriang++; // // Normals calculation // //calculate normal for new triangle Vector3f u = verts.get(index1).sub(verts.get(index0), new Vector3f()); Vector3f v = verts.get(index2).sub(verts.get(index1), new Vector3f()); Vector3f n = new Vector3f(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x).normalize(); //for each vertex, average the new normal with the normals that are already there int trianglesSharingIndex0 = trianglesSharingVert.get(index0); //calculate proportion of each normal float oldProportion = trianglesSharingIndex0 / (float)(trianglesSharingIndex0 + 1); float newProportion = 1.0f / (float)(trianglesSharingIndex0 + 1); //increment number of triangles sharing vert trianglesSharingVert.set(index0, trianglesSharingIndex0 + 1); Vector3f currentNormal = normals.get(index0); currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion); normals.get(index0).set(currentNormal); int trianglesSharingIndex1 = trianglesSharingVert.get(index1); //calculate proportion of each normal oldProportion = trianglesSharingIndex1 / (float)(trianglesSharingIndex1 + 1); newProportion = 1.0f / (float)(trianglesSharingIndex1 + 1); //increment number of triangles sharing vert trianglesSharingVert.set(index1, trianglesSharingIndex1 + 1); currentNormal = normals.get(index1); currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion); normals.get(index1).set(currentNormal); int trianglesSharingIndex2 = trianglesSharingVert.get(index2); //calculate proportion of each normal oldProportion = trianglesSharingIndex2 / (float)(trianglesSharingIndex2 + 1); newProportion = 1.0f / (float)(trianglesSharingIndex2 + 1); //increment number of triangles sharing vert trianglesSharingVert.set(index2, trianglesSharingIndex2 + 1); currentNormal = normals.get(index2); currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion); normals.get(index2).set(currentNormal); } return(ntriang); } //interpolates the location that the edge gets cut based on the magnitudes of the scalars of the vertices at either end of the edge static Vector3f VertexInterp(double isolevel, Vector3f p1, Vector3f p2, double valp1, double valp2){ double mu; float x, y, z; if (Math.abs(isolevel-valp1) < 0.00001) return(p1); if (Math.abs(isolevel-valp2) < 0.00001) return(p2); if (Math.abs(valp1-valp2) < 0.00001) return(p1); mu = (isolevel - valp1) / (valp2 - valp1); x = (float)(p1.x + mu * (p2.x - p1.x)); y = (float)(p1.y + mu * (p2.y - p1.y)); z = (float)(p1.z + mu * (p2.z - p1.z)); return new Vector3f(x,y,z); } public static TerrainChunkData generateTerrainChunkData(float[][][] data){ // 5 6 // +-------------+ +-----5-------+ ^ Y // / | / | / | /| | _ // / | / | 4 9 6 10 | /\ Z // 4 +-----+-------+ 7 | +-----+7------+ | | / // | 1 +-------+-----+ 2 | +-----1-+-----+ | / // | / | / 8 0 11 2 | / // | / | / | / | / |/ // 0 +-------------+ 3 +------3------+ +---------------> X //the current grid cell GridCell currentCell = new GridCell(); //the list of all triangles List triangles = new LinkedList(); //the map of vertex to index Map vertMap = new HashMap(); //the list of all verts List verts = new LinkedList(); //the list of all normals List normals = new LinkedList(); //the list of number of triangles that share a vert List trianglesSharingVert = new LinkedList(); //List of elements in order List faceElements = new LinkedList(); for(int x = 0; x < data.length - 1; x++){ for(int y = 0; y < data[0].length - 1; y++){ for(int z = 0; z < data[0][0].length - 1; z++){ //push the current cell's values into the gridcell currentCell.setValues( new Vector3f(x+0,y+0,z+0), new Vector3f(x+0,y+0,z+1), new Vector3f(x+1,y+0,z+1), new Vector3f(x+1,y+0,z+0), new Vector3f(x+0,y+1,z+0), new Vector3f(x+0,y+1,z+1), new Vector3f(x+1,y+1,z+1), new Vector3f(x+1,y+1,z+0), data[x+0][y+0][z+0], data[x+0][y+0][z+1], data[x+1][y+0][z+1], data[x+1][y+0][z+0], data[x+0][y+1][z+0], data[x+0][y+1][z+1], data[x+1][y+1][z+1], data[x+1][y+1][z+0] ); //polygonize the current gridcell polygonize(currentCell, 0.01, triangles, vertMap, verts, normals, trianglesSharingVert); } } } //all verts in order, flattened as an array of floats instead of vecs List vertsFlat = new LinkedList(); //all normals in order, flattened as an array of floats instead of vecs List normalsFlat = new LinkedList(); //all elements of faces in order List elementsFlat = new LinkedList(); //flatten verts + normals for(Vector3f vert : verts){ vertsFlat.add(vert.x); vertsFlat.add(vert.y); vertsFlat.add(vert.z); } for(Vector3f normal : normals){ normalsFlat.add(normal.x); normalsFlat.add(normal.y); normalsFlat.add(normal.z); } for(Triangle triangle : triangles){ elementsFlat.add(triangle.indices[0]); elementsFlat.add(triangle.indices[1]); elementsFlat.add(triangle.indices[2]); } //List vertices, List normals, List faceElements, List uvs TerrainChunkData rVal = new TerrainChunkData(vertsFlat, normalsFlat, elementsFlat); return rVal; } static class TerrainChunkData { List vertices; List normals; List elements; TerrainChunkData(List vertices, List normals, List elements){ this.vertices = vertices; this.normals = normals; this.elements = elements; } } //TODO: more optimal key creation private static String getVertKeyFromPoints(float x, float y, float z){ return x + "_" + y + "_" + z; } private static int getVertIndex(Vector3f vert, Map vertMap, List verts){ int rVal = -1; String vertKey = getVertKeyFromPoints(vert.x,vert.y,vert.z); if(vertMap.containsKey(vertKey)){ return vertMap.get(vertKey); } else { rVal = verts.size(); verts.add(vert); vertMap.put(vertKey,rVal); return rVal; } } private static Vector3f averageNormals(Vector3f normal0, float proportion0, Vector3f normal1, float proportion1){ Vector3f rVal = new Vector3f(normal0); rVal = rVal.mul(proportion0).add(new Vector3f(normal1).mul(proportion1)); return rVal; } }