package electrosphere.renderer.meshgen; import java.nio.FloatBuffer; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.joml.Vector3f; import org.lwjgl.BufferUtils; import static org.lwjgl.opengl.GL30.glBindVertexArray; import electrosphere.client.terrain.cells.VoxelTextureAtlas; import electrosphere.engine.Globals; import electrosphere.entity.types.terrain.TerrainChunkData; import electrosphere.renderer.model.Material; import electrosphere.renderer.model.Mesh; import electrosphere.renderer.model.Model; import electrosphere.server.terrain.manager.ServerTerrainChunk; public class TerrainChunkModelGeneration { //http://paulbourke.net/geometry/polygonise/ public 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 public 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 }; /** * A single generated triangle */ static class Triangle { //the indices int[] indices = new int[3]; //array of size 3 /** * Creates a triangle object * @param index0 * @param index1 * @param index2 */ public Triangle(int index0, int index1, int index2){ indices[0] = index0; indices[1] = index1; indices[2] = index2; } } /** * The grid cell currently being looked at */ static class GridCell { Vector3f[] points = new Vector3f[8]; //array of size 8 double[] val = new double[8]; //array of size 8 int[] atlasValues = new int[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, int atl1, int atl2, int atl3, int atl4, int atl5, int atl6, int atl7, int atl8 ){ //triangle points points[0] = p1; points[1] = p2; points[2] = p3; points[3] = p4; points[4] = p5; points[5] = p6; points[6] = p7; points[7] = p8; //iso values val[0] = val1; val[1] = val2; val[2] = val3; val[3] = val4; val[4] = val5; val[5] = val6; val[6] = val7; val[7] = val8; //atlas values atlasValues[0] = atl1; atlasValues[1] = atl2; atlasValues[2] = atl3; atlasValues[3] = atl4; atlasValues[4] = atl5; atlasValues[5] = atl6; atlasValues[6] = atl7; atlasValues[7] = atl8; } } //location of the sampler index data in the shader public static final int SAMPLER_INDEX_ATTRIB_LOC = 5; //the ratio vectors of how much to pull from each texture public static final int SAMPLER_RATIO_ATTRIB_LOC = 6; protected static int polygonize( GridCell grid, double isolevel, List triangles, List samplerIndices, Map vertMap, List verts, List normals, List trianglesSharingVert ){ int i; int ntriang; int cubeIndex = 0; Vector3f[] vertList = new Vector3f[12]; int[] samplerIndex = new int[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]); } if(grid.val[0] > isolevel){ samplerIndex[0] = 0; } else { samplerIndex[0] = 1; } if(grid.val[1] > isolevel){ samplerIndex[1] = 1; } else { samplerIndex[1] = 2; } if(grid.val[2] > isolevel){ samplerIndex[2] = 2; } else { samplerIndex[2] = 3; } if(grid.val[3] > isolevel){ samplerIndex[3] = 3; } else { samplerIndex[3] = 0; } if(grid.val[4] > isolevel){ samplerIndex[4] = 4; } else { samplerIndex[4] = 5; } if(grid.val[5] > isolevel){ samplerIndex[5] = 5; } else { samplerIndex[5] = 6; } if(grid.val[6] > isolevel){ samplerIndex[6] = 6; } else { samplerIndex[6] = 7; } if(grid.val[7] > isolevel){ samplerIndex[7] = 7; } else { samplerIndex[7] = 4; } if(grid.val[0] > isolevel){ samplerIndex[8] = 0; } else { samplerIndex[8] = 4; } if(grid.val[1] > isolevel){ samplerIndex[9] = 1; } else { samplerIndex[9] = 5; } if(grid.val[2] > isolevel){ samplerIndex[10] = 2; } else { samplerIndex[10] = 6; } if(grid.val[3] > isolevel){ samplerIndex[11] = 3; } else { samplerIndex[11] = 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++; // //Sampler triangles // for(int j = 0; j < 3; j++){ //we add the triangle three times so all three vertices have the same values //that way they don't interpolate when you're in a middle point of the fragment //this could eventually potentially be optimized to send 1/3rd the data, but //the current approach is easier to reason about Vector3f samplerTriangle = new Vector3f( grid.atlasValues[samplerIndex[triTable[cubeIndex][i+0]]], grid.atlasValues[samplerIndex[triTable[cubeIndex][i+1]]], grid.atlasValues[samplerIndex[triTable[cubeIndex][i+2]]] ); samplerIndices.add(samplerTriangle); } // // 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[][][] terrainGrid, int[][][] textureGrid, int lod){ // 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 texture sampler values List samplerTriangles = new LinkedList(); //List of UVs List UVs = new LinkedList(); for(int x = 0; x < terrainGrid.length - 1; x++){ for(int y = 0; y < terrainGrid[0].length - 1; y++){ for(int z = 0; z < terrainGrid[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), terrainGrid[x+0][y+0][z+0], terrainGrid[x+0][y+0][z+1], terrainGrid[x+1][y+0][z+1], terrainGrid[x+1][y+0][z+0], terrainGrid[x+0][y+1][z+0], terrainGrid[x+0][y+1][z+1], terrainGrid[x+1][y+1][z+1], terrainGrid[x+1][y+1][z+0], textureGrid[x+0][y+0][z+0], textureGrid[x+0][y+0][z+1], textureGrid[x+1][y+0][z+1], textureGrid[x+1][y+0][z+0], textureGrid[x+0][y+1][z+0], textureGrid[x+0][y+1][z+1], textureGrid[x+1][y+1][z+1], textureGrid[x+1][y+1][z+0] ); //polygonize the current gridcell polygonize(currentCell, 0.01f, triangles, samplerTriangles, 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(); //List of texture sampler values List textureSamplers = new LinkedList(); //List of texture ratio values List textureRatioData = 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]); } float[] temp = new float[3]; int i = 0; for(Vector3f normal : normals){ Vector3f vert = verts.get(i); float absX = Math.abs(normal.x); float absY = Math.abs(normal.y); float absZ = Math.abs(normal.z); float uvX = vert.z * absX + vert.x * absY + vert.x * absZ; float uvY = vert.y * absX + vert.z * absY + vert.y * absZ; temp[0] = uvX; temp[1] = uvY; // if(absX >= absZ && absX >= absY){ // temp[0] = normal.z / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ)); // temp[1] = normal.y / 2.0f + 0.5f + vert.x * (absY / (absX + absY)) + vert.y * (absX / (absX + absY)); // } else if(absZ >= absX && absZ >= absY){ // temp[0] = normal.x / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ)); // temp[1] = normal.y / 2.0f + 0.5f + vert.z * (absY / (absZ + absY)) + vert.y * (absZ / (absZ + absY)); // } else if(absY >= absX && absY >= absZ){ // temp[0] = normal.x / 2.0f + 0.5f + vert.y * (absX / (absX + absY)) + vert.x * (absY / (absX + absY)); // temp[1] = normal.z / 2.0f + 0.5f + vert.y * (absZ / (absZ + absY)) + vert.z * (absY / (absZ + absY)); // } else { // temp[0] = vert.x / 1.5f + vert.z / 1.5f; // temp[1] = vert.y / 1.5f + vert.z / 1.5f; // } i++; UVs.add(temp[0]); UVs.add(temp[1]); } //flatten sampler indices for(Vector3f samplerVec : samplerTriangles){ textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.x)); textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.y)); textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.z)); } //set ratio dat for(Triangle triangle : triangles){ //first vertex textureRatioData.add(1.0f); textureRatioData.add(0.0f); textureRatioData.add(0.0f); //second vertex textureRatioData.add(0.0f); textureRatioData.add(1.0f); textureRatioData.add(0.0f); //third vertex textureRatioData.add(0.0f); textureRatioData.add(0.0f); textureRatioData.add(1.0f); } //List vertices, List normals, List faceElements, List uvs TerrainChunkData rVal = new TerrainChunkData(vertsFlat, normalsFlat, elementsFlat, UVs, textureSamplers, textureRatioData); return rVal; } /** * Generates a mesh based on a terrainchunkdata object * @param data The terrain chunk data object * @return The mesh */ protected static Mesh generateTerrainMesh(TerrainChunkData data){ Mesh mesh = new Mesh("terrainChunk"); // // VAO // mesh.generateVAO(); // // Buffer data to GPU // int elementCount = data.getFaceElements().size(); try { FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 3); FloatBuffer NormalArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 3); FloatBuffer TextureArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 2); for(int element : data.getFaceElements()){ //for each element, need to push vert, normal, etc //push current vertex VertexArrayBufferData.put(data.getVertices().get(element*3+0)); VertexArrayBufferData.put(data.getVertices().get(element*3+1)); VertexArrayBufferData.put(data.getVertices().get(element*3+2)); //push current normals NormalArrayBufferData.put(data.getNormals().get(element*3+0)); NormalArrayBufferData.put(data.getNormals().get(element*3+1)); NormalArrayBufferData.put(data.getNormals().get(element*3+2)); //push current uvs TextureArrayBufferData.put(data.getUVs().get(element*2+0)); TextureArrayBufferData.put(data.getUVs().get(element*2+1)); } //actually buffer vertices VertexArrayBufferData.flip(); mesh.bufferVertices(VertexArrayBufferData, 3); //actually buffer normals NormalArrayBufferData.flip(); mesh.bufferNormals(NormalArrayBufferData, 3); //actually buffer UVs TextureArrayBufferData.flip(); mesh.bufferTextureCoords(TextureArrayBufferData, 2); } catch (NullPointerException ex){ ex.printStackTrace(); } //alert mesh to use direct array access and set the number of elements in the direct arrays mesh.setUseElementArray(false); mesh.setDirectArraySize(elementCount); // // SAMPLER INDICES // try { int vertexCount = data.getTextureSamplers().size() / 3; FloatBuffer samplerBuffer = BufferUtils.createFloatBuffer(vertexCount * 3); for(float samplerVec : data.getTextureSamplers()){ samplerBuffer.put(samplerVec); } samplerBuffer.flip(); mesh.bufferCustomFloatAttribArray(samplerBuffer, 3, SAMPLER_INDEX_ATTRIB_LOC); } catch (NullPointerException ex){ ex.printStackTrace(); } // // SAMPLER RATIO DATA // try { int vertexCount = data.getTextureRatioVectors().size() / 3; FloatBuffer samplerBuffer = BufferUtils.createFloatBuffer(vertexCount * 3); for(float samplerVec : data.getTextureRatioVectors()){ samplerBuffer.put(samplerVec); } samplerBuffer.flip(); mesh.bufferCustomFloatAttribArray(samplerBuffer, 3, SAMPLER_RATIO_ATTRIB_LOC); } catch (NullPointerException ex){ ex.printStackTrace(); } //bounding sphere logic float halfChunk = ServerTerrainChunk.CHUNK_DIMENSION / 2.0f; mesh.updateBoundingSphere( halfChunk, halfChunk, halfChunk, (float)Math.sqrt(halfChunk * halfChunk + halfChunk * halfChunk + halfChunk * halfChunk) ); glBindVertexArray(0); return mesh; } /** * Generates a model based on a terrainchunkdata object * @param data The terrain chunk data object * @param atlas The atlas texture for the chunk * @return The model */ public static Model generateTerrainModel(TerrainChunkData data, VoxelTextureAtlas atlas){ Model rVal = new Model(); Mesh m = generateTerrainMesh(data); //construct the material for the chunk Material groundMat = new Material(); groundMat.setTexturePointer(atlas.getSpecular().getTexturePointer()); groundMat.setNormalTexturePointer(atlas.getNormal().getTexturePointer()); m.setMaterial(groundMat); //shader logic m.setShader(Globals.terrainShaderProgram); m.setParent(rVal); rVal.getMeshes().add(m); rVal.setBoundingSphere(m.getBoundingSphere()); return rVal; } //TODO: more optimal key creation private static String getVertKeyFromPoints(float x, float y, float z){ return x + "_" + y + "_" + z; } /** * Gets the already existing index of this point * @param vert the vertex's raw position * @param vertMap the map of key ->Vert index * @param verts * @return */ 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; } private static final int pickBlockIdForVertex(long blockIds, int vertIndex){ int bits = BLOCK_PICK_BITS_BY_VERT_INDEX[vertIndex]; int blockIndexA = bits >> 4; int blockIndexB = bits & 0xf; int blockIdA = (int)(blockIds >> 8 * blockIndexA) & 0xff; int blockIdB = (int)(blockIds >> 8 * blockIndexB) & 0xff; //assert (blockIdA == airBlockId) != (blockIdB == airBlockId); //return blockIdA - nonZeroAirBlockId + blockIdB; return blockIdA + blockIdB; } }