diff options
author | Tyler Murphy <tylerm@tylerm.dev> | 2023-04-17 12:12:01 -0400 |
---|---|---|
committer | Tyler Murphy <tylerm@tylerm.dev> | 2023-04-17 12:12:01 -0400 |
commit | 180aad05decc7eefa87e4e45d6747c48f40e5361 (patch) | |
tree | 51545197f7c94b4022acab880772c9f4fc65db0e /src/main | |
download | minecraftjava-main.tar.gz minecraftjava-main.tar.bz2 minecraftjava-main.zip |
Diffstat (limited to 'src/main')
71 files changed, 7069 insertions, 0 deletions
diff --git a/src/main/java/net/tylermurphy/Minecraft/Audio/Sound.java b/src/main/java/net/tylermurphy/Minecraft/Audio/Sound.java new file mode 100755 index 0000000..58852da --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Audio/Sound.java @@ -0,0 +1,82 @@ +package net.tylermurphy.Minecraft.Audio;
+
+import org.lwjgl.openal.AL10;
+import org.lwjgl.system.*;
+
+import net.tylermurphy.Minecraft.Util.Constants;
+
+import java.nio.*;
+
+import static org.lwjgl.openal.AL10.*;
+import static org.lwjgl.stb.STBVorbis.*;
+import static org.lwjgl.system.MemoryStack.*;
+import static org.lwjgl.system.libc.LibCStdlib.*;
+
+public class Sound {
+
+ int bufferId;
+ int sourceId;
+
+ protected Sound(String fileName) {
+ ShortBuffer rawAudioBuffer;
+
+ int channels;
+ int sampleRate;
+
+ try (MemoryStack stack = stackPush()) {
+ IntBuffer channelsBuffer = stack.mallocInt(1);
+ IntBuffer sampleRateBuffer = stack.mallocInt(1);
+ rawAudioBuffer = stb_vorbis_decode_filename(Constants.OGG_LOCATION + fileName +".ogg", channelsBuffer, sampleRateBuffer);
+ channels = channelsBuffer.get(0);
+ sampleRate = sampleRateBuffer.get(0);
+ }
+
+ int format = -1;
+ if (channels == 1) {
+ format = AL_FORMAT_MONO16;
+ } else if (channels == 2) {
+ format = AL_FORMAT_STEREO16;
+ }
+
+ bufferId = alGenBuffers();
+ alBufferData(bufferId, format, rawAudioBuffer, sampleRate);
+ free(rawAudioBuffer);
+ sourceId = alGenSources();
+ alSourcei(sourceId, AL_BUFFER, bufferId);
+ }
+
+ public void play() {
+ stop();
+ alSourcePlay(sourceId);
+ }
+
+ public boolean isPlaying() {
+ return AL10.alGetSourcei(sourceId, AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING;
+ }
+
+ public void stop() {
+ alSourceStop(sourceId);
+ }
+
+ public void pause() {
+ alSourcePause(sourceId);
+ }
+
+ public void resume() {
+ alSourcePlay(sourceId);
+ }
+
+ public void setPosition(int x,int y,int z) {
+ AL10.alSource3f(sourceId, AL10.AL_POSITION, x, y, z);
+ }
+
+ public void setLooping(boolean loop) {
+ AL10.alSourcei(sourceId, AL10.AL_LOOPING, loop ? 1 : 0);
+ }
+
+ protected void cleanUp() {
+ alDeleteSources(sourceId);
+ alDeleteBuffers(bufferId);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Audio/SoundManager.java b/src/main/java/net/tylermurphy/Minecraft/Audio/SoundManager.java new file mode 100755 index 0000000..10b7d6d --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Audio/SoundManager.java @@ -0,0 +1,45 @@ +package net.tylermurphy.Minecraft.Audio;
+
+import java.util.ArrayList;
+
+import java.util.List;
+
+import org.lwjgl.openal.*;
+
+public class SoundManager {
+
+ private static long device;
+ private static long context;
+ private static List<Sound> sounds;
+
+ public static void init() {
+ String defaultDeviceName = ALC10.alcGetString(0, ALC10.ALC_DEFAULT_DEVICE_SPECIFIER);
+ device = ALC10.alcOpenDevice(defaultDeviceName);
+ int[] attributes = {0};
+ context = ALC10.alcCreateContext(device, attributes);
+ ALC10.alcMakeContextCurrent(context);
+ ALCCapabilities alcCapabilities = ALC.createCapabilities(device);
+ AL.createCapabilities(alcCapabilities);
+ sounds = new ArrayList<>();
+ AL11.alDistanceModel(AL11.AL_LINEAR_DISTANCE_CLAMPED);
+ }
+
+ public static Sound loadSound(String fileName) {
+ Sound sound = new Sound(fileName);
+ sounds.add(sound);
+ return sound;
+ }
+
+ public static void cleanUp() {
+ for(Sound sound : sounds) {
+ sound.cleanUp();
+ }
+ ALC10.alcDestroyContext(context);
+ ALC10.alcCloseDevice(device);
+ }
+
+ public static void setListenerData(float x, float y, float z) {
+ AL10.alListener3f(AL10.AL_POSITION, x, y, z);
+ AL10.alListener3f(AL10.AL_VELOCITY, 0, 0, 0);
+ }
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Chunk/Chunk.java b/src/main/java/net/tylermurphy/Minecraft/Chunk/Chunk.java new file mode 100755 index 0000000..f9979e6 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Chunk/Chunk.java @@ -0,0 +1,111 @@ +package net.tylermurphy.Minecraft.Chunk;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import net.tylermurphy.Minecraft.Gen.WorldGenerator;
+import net.tylermurphy.Minecraft.Scene.Objects.Renderable;
+import net.tylermurphy.Minecraft.Scene.World;
+
+public class Chunk {
+
+ private static final ExecutorService threadpool = Executors.newCachedThreadPool();
+
+ public final int gridX;
+ public final int gridZ;
+ public final int chunk_seed;
+
+ public byte[][][] cubes;
+
+ private Renderable chunkRenderable, transparentRenderable;
+
+ private ChunkMesh chunkMesh, transparentChunkMesh;
+
+ private final boolean generate;
+ private boolean initialized = false;
+ private boolean updating = true;
+ private boolean scheduled = false;
+ private int pendingUpdates = 0;
+
+ public Chunk(int gridX, int gridZ, boolean generate) {
+ this.gridX = gridX;
+ this.gridZ = gridZ;
+ this.generate = generate;
+ this.chunk_seed = gridX * World.seed ^ gridZ;
+ cubes = new byte[16][256][16];
+ }
+
+ public boolean isSafe() {
+ return initialized;
+ }
+
+ public Renderable renderable() {
+ return chunkRenderable;
+ }
+
+ public void deleteRenderable(){
+ this.chunkRenderable = null;
+ }
+
+ public Renderable transparentRenderable(){
+ return transparentRenderable;
+ }
+
+ public void deleteTransparentRenderable(){
+ this.transparentRenderable = null;
+ }
+
+ public void scheduleFutureMeshUpdate(){
+ this.scheduled = true;
+ }
+
+ public boolean isScheduled(){
+ return scheduled;
+ }
+
+ public void updateMesh() {
+ if(!initialized || updating){
+ pendingUpdates++;
+ return;
+ }
+ chunkMesh = new ChunkMesh();
+ transparentChunkMesh = new ChunkMesh();
+ updating = true;
+ scheduled = false;
+ pendingUpdates--;
+ threadpool.submit(() -> {
+ chunkMesh.update(this, false);
+ transparentChunkMesh.update(this, true);
+ });
+ }
+
+ public boolean loadMesh() {
+ if(!initialized || !updating) return false;
+ if(chunkMesh.completed && transparentChunkMesh.completed) {
+ if(chunkRenderable != null && chunkRenderable.getMesh() != null)
+ chunkRenderable.getMesh().delete();
+ chunkRenderable = chunkMesh.createChunkMesh();
+ chunkMesh = null;
+ if(transparentRenderable != null && transparentRenderable.getMesh() != null)
+ transparentRenderable.getMesh().delete();
+ transparentRenderable = transparentChunkMesh.createChunkMesh();
+ transparentChunkMesh = null;
+ updating = false;
+ if(pendingUpdates > 0) updateMesh();
+ return true;
+ }
+ return false;
+ }
+
+ public void initialize() {
+ chunkMesh = new ChunkMesh();
+ transparentChunkMesh = new ChunkMesh();
+ threadpool.submit(() -> {
+ if(generate) WorldGenerator.generate(this);
+ chunkMesh.update(this, false);
+ transparentChunkMesh.update(this, true);
+ initialized = true;
+ });
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Chunk/ChunkMesh.java b/src/main/java/net/tylermurphy/Minecraft/Chunk/ChunkMesh.java new file mode 100755 index 0000000..093243a --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Chunk/ChunkMesh.java @@ -0,0 +1,214 @@ +package net.tylermurphy.Minecraft.Chunk;
+
+import static net.tylermurphy.Minecraft.Chunk.Cube.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.tylermurphy.Minecraft.Scene.Objects.Transform;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.joml.Vector2f;
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.Render.Data.Mesh;
+import net.tylermurphy.Minecraft.Scene.World;
+import net.tylermurphy.Minecraft.Scene.Objects.Renderable;
+
+public class ChunkMesh {
+
+ private List<Vertex> verticies;
+ private List<Vertex> tranaparentVerticies;
+ private List<Float> positionsList;
+ private List<Float> normalsList;
+ private List<Float> tcsList;
+ private List<Float> lightingList;
+ private List<Float> layerList;
+
+ public float[] positions, tcs, normals, lighting, layers;
+
+ private Chunk chunk;
+
+ private boolean transparent;
+
+ public boolean completed = false;
+
+ public void update(Chunk chunk, boolean transparent) {
+
+ this.chunk = chunk;
+ this.transparent = transparent;
+ this.completed = false;
+
+ verticies = new ArrayList<>();
+ tranaparentVerticies = new ArrayList<>();
+ positionsList = new ArrayList<>();
+ normalsList = new ArrayList<>();
+ tcsList = new ArrayList<>();
+ lightingList = new ArrayList<>();
+ layerList = new ArrayList<>();
+
+ buildMesh();
+ populateLists();
+
+ this.completed = true;
+ }
+
+ private void buildMesh() {
+ for(int x=0;x<16;x++) {
+ for(int y=0; y<256; y++) {
+ for(int z=0; z<16; z++) {
+
+ if(chunk.cubes[x][y][z] == AIR) continue;
+
+ if(getBlock(chunk.cubes[x][y][z]).transparent != transparent) continue;
+
+ boolean px = true, nx = true, py = true, ny = true, pz = true, nz = true;
+
+ if(x<15) px = chunk.cubes[x + 1][y][z] != AIR && transparentCheck(x + 1, y, z, x, y, z);
+ else px = getCube(chunk.gridX + 1, chunk.gridZ, 0, y, z) != AIR && transparentCheck(getCube(chunk.gridX + 1, chunk.gridZ, 0, y, z), x, y, z);
+ if(x>0) nx = chunk.cubes[x - 1][y][z] != AIR && transparentCheck(x - 1, y, z, x, y, z);
+ else nx = getCube(chunk.gridX - 1, chunk.gridZ, 15, y, z) != AIR && transparentCheck(getCube(chunk.gridX - 1, chunk.gridZ, 15, y, z), x, y, z);
+ if(y<255) py = chunk.cubes[x][y + 1][z] != AIR && transparentCheck(x, y + 1, z, x, y, z);
+ if(y>0) ny = chunk.cubes[x][y - 1][z] != AIR && transparentCheck(x, y - 1, z, x, y, z);
+ if(z<15) pz = chunk.cubes[x][y][z + 1] != AIR && transparentCheck(x, y, z + 1, x, y, z);
+ else pz = getCube(chunk.gridX, chunk.gridZ + 1, x, y, 0) != AIR && transparentCheck(getCube(chunk.gridX, chunk.gridZ + 1, x, y, 0), x, y, z);
+ if(z>0) nz = chunk.cubes[x][y][z - 1] != AIR && transparentCheck(x, y, z - 1, x, y, z);
+ else nz = getCube(chunk.gridX, chunk.gridZ - 1, x, y, 15) != AIR && transparentCheck(getCube(chunk.gridX, chunk.gridZ - 1, x, y, 15), x, y, z);
+
+ JSONObject positions = getBlock(chunk.cubes[x][y][z]).positions;
+ if(chunk.cubes[x][y][z]==17 && ( y==255 || chunk.cubes[x][y+1][z] != 17 )) {
+
+ if(y<255) {
+ byte xp,xn,zp,zn;
+
+ if(x<15) xp = chunk.cubes[x+1][y+1][z];
+ else xp = getCube(chunk.gridX+1,chunk.gridZ,0,y+1,z);
+ if(x<0) xn = chunk.cubes[x-1][y+1][z];
+ else xn = getCube(chunk.gridX-1,chunk.gridZ,15,y+1,z);
+ if(z<15) zp = chunk.cubes[x][y+1][z+1];
+ else zp = getCube(chunk.gridX,chunk.gridZ+1,x,y+1,0);
+ if(z<0) zn = chunk.cubes[x][y+1][z-1];
+ else zn = getCube(chunk.gridX,chunk.gridZ-1,x,y+1,15);
+
+ if(xp != 17 && xn != 17 && zp != 17 && zn != 17) {
+ positions = models.get("water");
+ py = false;
+ }
+ } else {
+ positions = models.get("water");
+ py = false;
+ }
+
+ }
+
+ if(getBlock(chunk.cubes[x][y][z]).transparent && chunk.cubes[x][y][z] != 17 && (y == 0 || chunk.cubes[x][y-1][z] == 17)) {
+ ny = false;
+ }
+
+ JSONArray PX_POS = positions.getJSONArray("PX_POS");
+ JSONArray NX_POS = positions.getJSONArray("NX_POS");
+ JSONArray PY_POS = positions.getJSONArray("PY_POS");
+ JSONArray NY_POS = positions.getJSONArray("NY_POS");
+ JSONArray PZ_POS = positions.getJSONArray("PZ_POS");
+ JSONArray NZ_POS = positions.getJSONArray("NZ_POS");
+
+ if(!px) { for(int i=0;i<6;i++) { verticies.add(new Vertex(new Vector3f((float) PX_POS.getJSONArray(i).getDouble(0) + x, (float) PX_POS.getJSONArray(i).getDouble(1) + y, (float) PX_POS.getJSONArray(i).getDouble(2) + z), TEXTURE_CORDS[i], NORMALS[i], getBlock(chunk.cubes[x][y][z]).tex_px, .9f)); } }
+ if(!nx) { for(int i=0;i<6;i++) { verticies.add(new Vertex(new Vector3f((float) NX_POS.getJSONArray(i).getDouble(0) + x, (float) NX_POS.getJSONArray(i).getDouble(1) + y, (float) NX_POS.getJSONArray(i).getDouble(2) + z), TEXTURE_CORDS[i], NORMALS[i], getBlock(chunk.cubes[x][y][z]).tex_nx, .9f)); } }
+ if(!py) { for(int i=0;i<6;i++) { verticies.add(new Vertex(new Vector3f((float) PY_POS.getJSONArray(i).getDouble(0) + x, (float) PY_POS.getJSONArray(i).getDouble(1) + y, (float) PY_POS.getJSONArray(i).getDouble(2) + z), TEXTURE_CORDS[i], NORMALS[i], getBlock(chunk.cubes[x][y][z]).tex_py, 1f)); } }
+ if(!ny) { for(int i=0;i<6;i++) { verticies.add(new Vertex(new Vector3f((float) NY_POS.getJSONArray(i).getDouble(0) + x, (float) NY_POS.getJSONArray(i).getDouble(1) + y, (float) NY_POS.getJSONArray(i).getDouble(2) + z), TEXTURE_CORDS[i], NORMALS[i], getBlock(chunk.cubes[x][y][z]).tex_ny, 1f)); } }
+ if(!pz) { for(int i=0;i<6;i++) { verticies.add(new Vertex(new Vector3f((float) PZ_POS.getJSONArray(i).getDouble(0) + x, (float) PZ_POS.getJSONArray(i).getDouble(1) + y, (float) PZ_POS.getJSONArray(i).getDouble(2) + z), TEXTURE_CORDS[i], NORMALS[i], getBlock(chunk.cubes[x][y][z]).tex_pz, .8f)); } }
+ if(!nz) { for(int i=0;i<6;i++) { verticies.add(new Vertex(new Vector3f((float) NZ_POS.getJSONArray(i).getDouble(0) + x, (float) NZ_POS.getJSONArray(i).getDouble(1) + y, (float) NZ_POS.getJSONArray(i).getDouble(2) + z), TEXTURE_CORDS[i], NORMALS[i], getBlock(chunk.cubes[x][y][z]).tex_nz, .8f)); } }
+ }
+ }
+ }
+ }
+
+ private byte getCube(int gx, int gz, int x, int y, int z) {
+ Chunk c = World.getChunk(gx,gz);
+ if(c == null) return 0;
+ return c.cubes[x][y][z];
+ }
+
+ private boolean transparentCheck(int x1,int y1,int z1,int x2,int y2,int z2) {
+ return transparentCheck(chunk.cubes[x1][y1][z1], x2, y2, z2);
+ }
+
+ private boolean transparentCheck(byte block,int x2,int y2,int z2) {
+ if(getBlock(block).alwaysRenderNeighbors || getBlock(chunk.cubes[x2][y2][z2]).alwaysRenderNeighbors)
+ return false;
+ else if(!getBlock(block).transparent && !getBlock(chunk.cubes[x2][y2][z2]).transparent && block == chunk.cubes[x2][y2][z2])
+ return true;
+ else return getBlock(block).transparent == getBlock(chunk.cubes[x2][y2][z2]).transparent || !getBlock(block).transparent;
+ }
+
+ static class Vertex{
+ Vector3f positions;
+ Vector2f uvs;
+ Vector3f normals;
+ float light;
+ float layer;
+ Vertex(Vector3f positions, Vector2f uvs, Vector3f normals, float layer, float light){
+ this.positions = positions;
+ this.uvs = uvs;
+ this.normals = normals;
+ this.layer = layer;
+ this.light = light;
+ }
+ }
+
+ private void populateLists() {
+ for(Vertex vertex : verticies) {
+ positionsList.add(vertex.positions.x);
+ positionsList.add(vertex.positions.y);
+ positionsList.add(vertex.positions.z);
+ tcsList.add(vertex.uvs.x);
+ tcsList.add(vertex.uvs.y);
+ normalsList.add(vertex.normals.x);
+ normalsList.add(vertex.normals.y);
+ normalsList.add(vertex.normals.z);
+ lightingList.add(vertex.light);
+ layerList.add(vertex.layer);
+ }
+
+ positions = new float[positionsList.size()];
+ tcs = new float[tcsList.size()];
+ normals = new float[normalsList.size()];
+ lighting = new float[lightingList.size()];
+ layers = new float[layerList.size()];
+
+ for(int i=0;i<positions.length;i++) positions[i] = positionsList.get(i);
+ for(int i=0;i<normals.length;i++) normals[i] = normalsList.get(i);
+ for(int i=0;i<tcs.length;i++) tcs[i] = tcsList.get(i);
+ for(int i=0;i<lighting.length;i++) lighting[i] = lightingList.get(i);
+ for(int i=0;i<layers.length;i++) layers[i] = layerList.get(i);
+
+ verticies.clear();
+ tranaparentVerticies.clear();
+ positionsList.clear();
+ normalsList.clear();
+ tcsList.clear();
+ lightingList.clear();
+ layerList.clear();
+ }
+
+ public Renderable createChunkMesh() {
+ Mesh mesh = new Mesh(positions.length)
+ .store(positions, 3)
+ .store(tcs, 2)
+ .store(lighting, 1)
+ .store(layers, 1)
+ .finish();
+ Transform transform = new Transform().setPosition(new Vector3f(chunk.gridX*16,9,chunk.gridZ*16));
+ Renderable renderable = new Renderable(mesh, transform, TEXTURE);
+ this.positions = null;
+ this.tcs = null;
+ this.normals = null;
+ this.lighting = null;
+ this.layers = null;
+ this.chunk = null;
+ this.completed = false;
+ return renderable;
+
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Chunk/Cube.java b/src/main/java/net/tylermurphy/Minecraft/Chunk/Cube.java new file mode 100755 index 0000000..1b59393 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Chunk/Cube.java @@ -0,0 +1,156 @@ +package net.tylermurphy.Minecraft.Chunk;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.stream.Stream;
+
+import net.tylermurphy.Minecraft.Render.Data.Texture;
+import org.joml.Vector2f;
+import org.joml.Vector3f;
+
+import org.json.JSONObject;
+
+public class Cube{
+
+ public static final byte NULL = -2;
+ public static final byte AIR = -1;
+ public static int TEXTURE;
+
+ public int tex_px, tex_nx, tex_py, tex_ny, tex_pz, tex_nz;
+ public boolean transparent;
+ public boolean alwaysRenderNeighbors;
+ public boolean placeable;
+ public String name;
+ public long tick_update_delay;
+ public JSONObject positions;
+
+ public static HashMap<String,JSONObject> models = new HashMap<>();
+
+ public static HashMap<Integer, Texture> textures = new HashMap<>();
+ public static HashMap<String, Integer> texturePairings = new HashMap<>();
+
+ public static HashMap<Integer,Cube> blocks = new HashMap<>();
+ public static HashMap<String,Integer> blockPairings = new HashMap<>();
+
+ public static Cube getBlock(byte b){
+ return blocks.get((int) b);
+ }
+
+ public static Cube getBlock(String s){
+ return blocks.get(blockPairings.get(s));
+ }
+
+ private static JSONObject loadJsonFile(File file){
+ StringBuilder contentBuilder = new StringBuilder();
+ try (Stream<String> stream = Files.lines( Paths.get(file.getPath()), StandardCharsets.UTF_8)){
+ stream.forEach(s -> contentBuilder.append(s).append("\n"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return new JSONObject(contentBuilder.toString());
+ }
+
+ private static void loadModels(){
+ models = new HashMap<>();
+ File dir = new File("assets/models");
+ File[] directoryListing = dir.listFiles();
+ assert directoryListing != null;
+ for(File file : directoryListing){
+ JSONObject json = loadJsonFile(file);
+ models.put(file.getName().replaceFirst("[.][^.]+$", ""), json);
+ }
+ }
+
+ private static void loadTextures(){
+ textures = new HashMap<>();
+ texturePairings = new HashMap<>();
+ File dir = new File("assets/textures/blocks");
+ File[] directoryListing = dir.listFiles();
+ int i = 0;
+ assert directoryListing != null;
+ for(File file : directoryListing){
+ String name = file.getName().replaceFirst("[.][^.]+$", "");
+ textures.put(i, Texture.loadRawTextureData("blocks/"+name));
+ texturePairings.put(name, i);
+ i++;
+ }
+ TEXTURE = Texture.loadTexture2DArray(textures);
+ }
+
+ private static void loadBlocks(){
+ blocks = new HashMap<>();
+ blockPairings = new HashMap<>();
+ File file = new File("assets/blocks/blocks.json");
+ JSONObject json = loadJsonFile(file);
+ for(String key : json.keySet()){
+ String name = json.getString(key);
+ int id = Integer.parseInt(key);
+ blockPairings.put(name, id);
+ File block_file = new File("assets/blocks/" + name + ".json");
+ JSONObject block = loadJsonFile(block_file);
+ blocks.put(id, createCube(name, block));
+ }
+ }
+
+ private static Cube createCube(String name, JSONObject json){
+ Cube cube = new Cube();
+ cube.positions = models.get(json.getString("model"));
+ cube.transparent = json.getBoolean("transparent");
+ cube.alwaysRenderNeighbors = json.getBoolean("renderNeighbors");
+ cube.placeable = json.getBoolean("placeable");
+ cube.name = name;
+ cube.tick_update_delay = 20;
+ JSONObject textureList = json.getJSONObject("textures");
+ if(json.getString("texture").equals("all")){
+ cube.tex_px = texturePairings.get(textureList.getString("face"));
+ cube.tex_nx = texturePairings.get(textureList.getString("face"));
+ cube.tex_py = texturePairings.get(textureList.getString("face"));
+ cube.tex_ny = texturePairings.get(textureList.getString("face"));
+ cube.tex_pz = texturePairings.get(textureList.getString("face"));
+ cube.tex_nz = texturePairings.get(textureList.getString("face"));
+ } else if(json.getString("texture").equals("side")){
+ cube.tex_px = texturePairings.get(textureList.getString("side"));
+ cube.tex_nx = texturePairings.get(textureList.getString("side"));
+ cube.tex_py = texturePairings.get(textureList.getString("top"));
+ cube.tex_ny = texturePairings.get(textureList.getString("bottom"));
+ cube.tex_pz = texturePairings.get(textureList.getString("side"));
+ cube.tex_nz = texturePairings.get(textureList.getString("side"));
+ }
+ return cube;
+ }
+
+ public static void init() {
+
+ loadModels();
+ loadTextures();
+ loadBlocks();
+
+ }
+
+ public static Vector3f[] NORMALS = {
+
+ new Vector3f(0.f, 0.f, 0.f),
+ new Vector3f(0.f, 0.f, 0.f),
+ new Vector3f(0.f, 0.f, 0.f),
+ new Vector3f(0.f, 0.f, 0.f),
+ new Vector3f(0.f, 0.f, 0.f),
+ new Vector3f(0.f, 0.f, 0.f)
+
+ };
+
+ public static Vector2f[] TEXTURE_CORDS = {
+
+ new Vector2f(0.f, 0.f),
+ new Vector2f(0.f, 1.f),
+ new Vector2f(1.f, 1.f),
+ new Vector2f(1.f, 1.f),
+ new Vector2f(1.f, 0.f),
+ new Vector2f(0.f, 0.f)
+
+ };
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Chunk/Generator.java b/src/main/java/net/tylermurphy/Minecraft/Chunk/Generator.java new file mode 100755 index 0000000..395923e --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Chunk/Generator.java @@ -0,0 +1,35 @@ +package net.tylermurphy.Minecraft.Chunk;
+
+import net.tylermurphy.Minecraft.Scene.World;
+
+public class Generator {
+
+ private static void generateLandscape(Chunk c) {
+ for(int x=0;x<16;x++) {
+ for(int z=0;z<16;z++) {
+
+ int biome = (int) (PerlinNoise.getNoise(World.seed, c.gridX*16+x, c.gridZ*16+z, PerlinNoise.NoiseType.Cellular)*3)+3;
+ biome = Math.max(1, Math.min(6, biome));
+
+ int height1 = (int) (PerlinNoise.getNoise(World.seed, c.gridX*16+x, c.gridZ*16+z, PerlinNoise.NoiseType.PerlinFractal)*biome)+biome;
+ int height2 = (int) (PerlinNoise.getNoise(World.seed+1, c.gridX*16+x, c.gridZ*16+z, PerlinNoise.NoiseType.Perlin)*biome)+biome;
+ int height3 = (int) (PerlinNoise.getNoise(World.seed+2, c.gridX*16+x, c.gridZ*16+z, PerlinNoise.NoiseType.Simplex)*biome)+biome;
+
+ int top = 90 + height1 + height2 - height3;
+
+ for(int y=0;y<256;y++) {
+ if(y<top) {
+ c.cubes[x][y][z] = (byte)(biome);
+ } else {
+ c.cubes[x][y][z] = -1;
+ }
+ }
+ }
+ }
+ }
+
+ public static void generate(Chunk c) {
+ generateLandscape(c);
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Chunk/PerlinNoise.java b/src/main/java/net/tylermurphy/Minecraft/Chunk/PerlinNoise.java new file mode 100755 index 0000000..02c209d --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Chunk/PerlinNoise.java @@ -0,0 +1,2147 @@ +package net.tylermurphy.Minecraft.Chunk;
+
+import org.joml.Vector2f;
+import org.joml.Vector3f;
+
+public class PerlinNoise {
+
+ public enum NoiseType {Value, ValueFractal, Perlin, PerlinFractal, Simplex, SimplexFractal, Cellular, WhiteNoise, Cubic, CubicFractal}
+ public enum Interp {Linear, Hermite, Quintic}
+ public enum FractalType {FBM, Billow, RigidMulti}
+ public enum CellularDistanceFunction {Euclidean, Manhattan, Natural}
+ public enum CellularReturnType {CellValue, NoiseLookup, Distance, Distance2, Distance2Add, Distance2Sub, Distance2Mul, Distance2Div}
+
+ private int m_seed = 1337;
+ private float m_frequency = (float) 0.01;
+ private Interp m_interp = Interp.Quintic;
+ private NoiseType m_noiseType = NoiseType.Simplex;
+
+ private int m_octaves = 3;
+ private float m_lacunarity = (float) 2.0;
+ private float m_gain = (float) 0.5;
+ private FractalType m_fractalType = FractalType.FBM;
+
+ private float m_fractalBounding;
+
+ private CellularDistanceFunction m_cellularDistanceFunction = CellularDistanceFunction.Euclidean;
+ private CellularReturnType m_cellularReturnType = CellularReturnType.CellValue;
+ private PerlinNoise m_cellularNoiseLookup = null;
+
+ private float m_gradientPerturbAmp = (float) (1.0 / 0.45);
+
+ public static double getNoise(int seed, int x, int y, int z) {
+ PerlinNoise noise = new PerlinNoise(seed);
+ noise.m_noiseType = NoiseType.Perlin;
+ noise.m_fractalType = FractalType.FBM;
+ return noise.GetNoise(x,y,z);
+ }
+
+ public static double getNoise(int seed, int x, int z,NoiseType noiseType) {
+ PerlinNoise noise = new PerlinNoise(seed);
+ noise.m_noiseType = noiseType;
+ noise.m_fractalType = FractalType.FBM;
+ return noise.GetNoise(x,z);
+ }
+
+ public static double getNoise(int seed, int x, int z) {
+ PerlinNoise noise = new PerlinNoise(seed);
+ noise.m_noiseType = NoiseType.Perlin;
+ noise.m_fractalType = FractalType.FBM;
+ return noise.GetNoise(x,z);
+ }
+
+ public PerlinNoise() {
+ this(1337);
+ }
+
+ public PerlinNoise(int seed) {
+ m_seed = seed;
+ CalculateFractalBounding();
+ }
+
+ public static float GetDecimalType() {
+ return 0;
+ }
+
+ public int GetSeed() {
+ return m_seed;
+ }
+
+ public void SetSeed(int seed) {
+ m_seed = seed;
+ }
+
+ public void SetFrequency(float frequency) {
+ m_frequency = frequency;
+ }
+
+ public void SetInterp(Interp interp) {
+ m_interp = interp;
+ }
+
+ public void SetNoiseType(NoiseType noiseType) {
+ m_noiseType = noiseType;
+ }
+
+ public void SetFractalOctaves(int octaves) {
+ m_octaves = octaves;
+ CalculateFractalBounding();
+ }
+
+ public void SetFractalLacunarity(float lacunarity) {
+ m_lacunarity = lacunarity;
+ }
+
+ public void SetFractalGain(float gain) {
+ m_gain = gain;
+ CalculateFractalBounding();
+ }
+
+ public void SetFractalType(FractalType fractalType) {
+ m_fractalType = fractalType;
+ }
+
+ public void SetCellularDistanceFunction(CellularDistanceFunction cellularDistanceFunction) {
+ m_cellularDistanceFunction = cellularDistanceFunction;
+ }
+
+ public void SetCellularReturnType(CellularReturnType cellularReturnType) {
+ m_cellularReturnType = cellularReturnType;
+ }
+
+ public void SetCellularNoiseLookup(PerlinNoise noise) {
+ m_cellularNoiseLookup = noise;
+ }
+
+ public void SetGradientPerturbAmp(float gradientPerturbAmp) {
+ m_gradientPerturbAmp = gradientPerturbAmp / (float) 0.45;
+ }
+
+ private static class Float2 {
+ public final float x, y;
+
+ public Float2(float x, float y) {
+ this.x = x;
+ this.y = y;
+ }
+ }
+
+ private static class Float3 {
+ public final float x, y, z;
+
+ public Float3(float x, float y, float z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+ }
+
+ private static final Float2[] GRAD_2D = {
+ new Float2(-1, -1), new Float2(1, -1), new Float2(-1, 1), new Float2(1, 1),
+ new Float2(0, -1), new Float2(-1, 0), new Float2(0, 1), new Float2(1, 0),
+ };
+
+ private static final Float3[] GRAD_3D = {
+ new Float3(1, 1, 0), new Float3(-1, 1, 0), new Float3(1, -1, 0), new Float3(-1, -1, 0),
+ new Float3(1, 0, 1), new Float3(-1, 0, 1), new Float3(1, 0, -1), new Float3(-1, 0, -1),
+ new Float3(0, 1, 1), new Float3(0, -1, 1), new Float3(0, 1, -1), new Float3(0, -1, -1),
+ new Float3(1, 1, 0), new Float3(0, -1, 1), new Float3(-1, 1, 0), new Float3(0, -1, -1),
+ };
+
+ private static final Float2[] CELL_2D =
+ {
+ new Float2(-0.4313539279f, 0.1281943404f), new Float2(-0.1733316799f, 0.415278375f), new Float2(-0.2821957395f, -0.3505218461f), new Float2(-0.2806473808f, 0.3517627718f), new Float2(0.3125508975f, -0.3237467165f), new Float2(0.3383018443f, -0.2967353402f), new Float2(-0.4393982022f, -0.09710417025f), new Float2(-0.4460443703f, -0.05953502905f),
+ new Float2(-0.302223039f, 0.3334085102f), new Float2(-0.212681052f, -0.3965687458f), new Float2(-0.2991156529f, 0.3361990872f), new Float2(0.2293323691f, 0.3871778202f), new Float2(0.4475439151f, -0.04695150755f), new Float2(0.1777518f, 0.41340573f), new Float2(0.1688522499f, -0.4171197882f), new Float2(-0.0976597166f, 0.4392750616f),
+ new Float2(0.08450188373f, 0.4419948321f), new Float2(-0.4098760448f, -0.1857461384f), new Float2(0.3476585782f, -0.2857157906f), new Float2(-0.3350670039f, -0.30038326f), new Float2(0.2298190031f, -0.3868891648f), new Float2(-0.01069924099f, 0.449872789f), new Float2(-0.4460141246f, -0.05976119672f), new Float2(0.3650293864f, 0.2631606867f),
+ new Float2(-0.349479423f, 0.2834856838f), new Float2(-0.4122720642f, 0.1803655873f), new Float2(-0.267327811f, 0.3619887311f), new Float2(0.322124041f, -0.3142230135f), new Float2(0.2880445931f, -0.3457315612f), new Float2(0.3892170926f, -0.2258540565f), new Float2(0.4492085018f, -0.02667811596f), new Float2(-0.4497724772f, 0.01430799601f),
+ new Float2(0.1278175387f, -0.4314657307f), new Float2(-0.03572100503f, 0.4485799926f), new Float2(-0.4297407068f, -0.1335025276f), new Float2(-0.3217817723f, 0.3145735065f), new Float2(-0.3057158873f, 0.3302087162f), new Float2(-0.414503978f, 0.1751754899f), new Float2(-0.3738139881f, 0.2505256519f), new Float2(0.2236891408f, -0.3904653228f),
+ new Float2(0.002967775577f, -0.4499902136f), new Float2(0.1747128327f, -0.4146991995f), new Float2(-0.4423772489f, -0.08247647938f), new Float2(-0.2763960987f, -0.355112935f), new Float2(-0.4019385906f, -0.2023496216f), new Float2(0.3871414161f, -0.2293938184f), new Float2(-0.430008727f, 0.1326367019f), new Float2(-0.03037574274f, -0.4489736231f),
+ new Float2(-0.3486181573f, 0.2845441624f), new Float2(0.04553517144f, -0.4476902368f), new Float2(-0.0375802926f, 0.4484280562f), new Float2(0.3266408905f, 0.3095250049f), new Float2(0.06540017593f, -0.4452222108f), new Float2(0.03409025829f, 0.448706869f), new Float2(-0.4449193635f, 0.06742966669f), new Float2(-0.4255936157f, -0.1461850686f),
+ new Float2(0.449917292f, 0.008627302568f), new Float2(0.05242606404f, 0.4469356864f), new Float2(-0.4495305179f, -0.02055026661f), new Float2(-0.1204775703f, 0.4335725488f), new Float2(-0.341986385f, -0.2924813028f), new Float2(0.3865320182f, 0.2304191809f), new Float2(0.04506097811f, -0.447738214f), new Float2(-0.06283465979f, 0.4455915232f),
+ new Float2(0.3932600341f, -0.2187385324f), new Float2(0.4472261803f, -0.04988730975f), new Float2(0.3753571011f, -0.2482076684f), new Float2(-0.273662295f, 0.357223947f), new Float2(0.1700461538f, 0.4166344988f), new Float2(0.4102692229f, 0.1848760794f), new Float2(0.323227187f, -0.3130881435f), new Float2(-0.2882310238f, -0.3455761521f),
+ new Float2(0.2050972664f, 0.4005435199f), new Float2(0.4414085979f, -0.08751256895f), new Float2(-0.1684700334f, 0.4172743077f), new Float2(-0.003978032396f, 0.4499824166f), new Float2(-0.2055133639f, 0.4003301853f), new Float2(-0.006095674897f, -0.4499587123f), new Float2(-0.1196228124f, -0.4338091548f), new Float2(0.3901528491f, -0.2242337048f),
+ new Float2(0.01723531752f, 0.4496698165f), new Float2(-0.3015070339f, 0.3340561458f), new Float2(-0.01514262423f, -0.4497451511f), new Float2(-0.4142574071f, -0.1757577897f), new Float2(-0.1916377265f, -0.4071547394f), new Float2(0.3749248747f, 0.2488600778f), new Float2(-0.2237774255f, 0.3904147331f), new Float2(-0.4166343106f, -0.1700466149f),
+ new Float2(0.3619171625f, 0.267424695f), new Float2(0.1891126846f, -0.4083336779f), new Float2(-0.3127425077f, 0.323561623f), new Float2(-0.3281807787f, 0.307891826f), new Float2(-0.2294806661f, 0.3870899429f), new Float2(-0.3445266136f, 0.2894847362f), new Float2(-0.4167095422f, -0.1698621719f), new Float2(-0.257890321f, -0.3687717212f),
+ new Float2(-0.3612037825f, 0.2683874578f), new Float2(0.2267996491f, 0.3886668486f), new Float2(0.207157062f, 0.3994821043f), new Float2(0.08355176718f, -0.4421754202f), new Float2(-0.4312233307f, 0.1286329626f), new Float2(0.3257055497f, 0.3105090899f), new Float2(0.177701095f, -0.4134275279f), new Float2(-0.445182522f, 0.06566979625f),
+ new Float2(0.3955143435f, 0.2146355146f), new Float2(-0.4264613988f, 0.1436338239f), new Float2(-0.3793799665f, -0.2420141339f), new Float2(0.04617599081f, -0.4476245948f), new Float2(-0.371405428f, -0.2540826796f), new Float2(0.2563570295f, -0.3698392535f), new Float2(0.03476646309f, 0.4486549822f), new Float2(-0.3065454405f, 0.3294387544f),
+ new Float2(-0.2256979823f, 0.3893076172f), new Float2(0.4116448463f, -0.1817925206f), new Float2(-0.2907745828f, -0.3434387019f), new Float2(0.2842278468f, -0.348876097f), new Float2(0.3114589359f, -0.3247973695f), new Float2(0.4464155859f, -0.0566844308f), new Float2(-0.3037334033f, -0.3320331606f), new Float2(0.4079607166f, 0.1899159123f),
+ new Float2(-0.3486948919f, -0.2844501228f), new Float2(0.3264821436f, 0.3096924441f), new Float2(0.3211142406f, 0.3152548881f), new Float2(0.01183382662f, 0.4498443737f), new Float2(0.4333844092f, 0.1211526057f), new Float2(0.3118668416f, 0.324405723f), new Float2(-0.272753471f, 0.3579183483f), new Float2(-0.422228622f, -0.1556373694f),
+ new Float2(-0.1009700099f, -0.4385260051f), new Float2(-0.2741171231f, -0.3568750521f), new Float2(-0.1465125133f, 0.4254810025f), new Float2(0.2302279044f, -0.3866459777f), new Float2(-0.3699435608f, 0.2562064828f), new Float2(0.105700352f, -0.4374099171f), new Float2(-0.2646713633f, 0.3639355292f), new Float2(0.3521828122f, 0.2801200935f),
+ new Float2(-0.1864187807f, -0.4095705534f), new Float2(0.1994492955f, -0.4033856449f), new Float2(0.3937065066f, 0.2179339044f), new Float2(-0.3226158377f, 0.3137180602f), new Float2(0.3796235338f, 0.2416318948f), new Float2(0.1482921929f, 0.4248640083f), new Float2(-0.407400394f, 0.1911149365f), new Float2(0.4212853031f, 0.1581729856f),
+ new Float2(-0.2621297173f, 0.3657704353f), new Float2(-0.2536986953f, -0.3716678248f), new Float2(-0.2100236383f, 0.3979825013f), new Float2(0.3624152444f, 0.2667493029f), new Float2(-0.3645038479f, -0.2638881295f), new Float2(0.2318486784f, 0.3856762766f), new Float2(-0.3260457004f, 0.3101519002f), new Float2(-0.2130045332f, -0.3963950918f),
+ new Float2(0.3814998766f, -0.2386584257f), new Float2(-0.342977305f, 0.2913186713f), new Float2(-0.4355865605f, 0.1129794154f), new Float2(-0.2104679605f, 0.3977477059f), new Float2(0.3348364681f, -0.3006402163f), new Float2(0.3430468811f, 0.2912367377f), new Float2(-0.2291836801f, -0.3872658529f), new Float2(0.2547707298f, -0.3709337882f),
+ new Float2(0.4236174945f, -0.151816397f), new Float2(-0.15387742f, 0.4228731957f), new Float2(-0.4407449312f, 0.09079595574f), new Float2(-0.06805276192f, -0.444824484f), new Float2(0.4453517192f, -0.06451237284f), new Float2(0.2562464609f, -0.3699158705f), new Float2(0.3278198355f, -0.3082761026f), new Float2(-0.4122774207f, -0.1803533432f),
+ new Float2(0.3354090914f, -0.3000012356f), new Float2(0.446632869f, -0.05494615882f), new Float2(-0.1608953296f, 0.4202531296f), new Float2(-0.09463954939f, 0.4399356268f), new Float2(-0.02637688324f, -0.4492262904f), new Float2(0.447102804f, -0.05098119915f), new Float2(-0.4365670908f, 0.1091291678f), new Float2(-0.3959858651f, 0.2137643437f),
+ new Float2(-0.4240048207f, -0.1507312575f), new Float2(-0.3882794568f, 0.2274622243f), new Float2(-0.4283652566f, -0.1378521198f), new Float2(0.3303888091f, 0.305521251f), new Float2(0.3321434919f, -0.3036127481f), new Float2(-0.413021046f, -0.1786438231f), new Float2(0.08403060337f, -0.4420846725f), new Float2(-0.3822882919f, 0.2373934748f),
+ new Float2(-0.3712395594f, -0.2543249683f), new Float2(0.4472363971f, -0.04979563372f), new Float2(-0.4466591209f, 0.05473234629f), new Float2(0.0486272539f, -0.4473649407f), new Float2(-0.4203101295f, -0.1607463688f), new Float2(0.2205360833f, 0.39225481f), new Float2(-0.3624900666f, 0.2666476169f), new Float2(-0.4036086833f, -0.1989975647f),
+ new Float2(0.2152727807f, 0.3951678503f), new Float2(-0.4359392962f, -0.1116106179f), new Float2(0.4178354266f, 0.1670735057f), new Float2(0.2007630161f, 0.4027334247f), new Float2(-0.07278067175f, -0.4440754146f), new Float2(0.3644748615f, -0.2639281632f), new Float2(-0.4317451775f, 0.126870413f), new Float2(-0.297436456f, 0.3376855855f),
+ new Float2(-0.2998672222f, 0.3355289094f), new Float2(-0.2673674124f, 0.3619594822f), new Float2(0.2808423357f, 0.3516071423f), new Float2(0.3498946567f, 0.2829730186f), new Float2(-0.2229685561f, 0.390877248f), new Float2(0.3305823267f, 0.3053118493f), new Float2(-0.2436681211f, -0.3783197679f), new Float2(-0.03402776529f, 0.4487116125f),
+ new Float2(-0.319358823f, 0.3170330301f), new Float2(0.4454633477f, -0.06373700535f), new Float2(0.4483504221f, 0.03849544189f), new Float2(-0.4427358436f, -0.08052932871f), new Float2(0.05452298565f, 0.4466847255f), new Float2(-0.2812560807f, 0.3512762688f), new Float2(0.1266696921f, 0.4318041097f), new Float2(-0.3735981243f, 0.2508474468f),
+ new Float2(0.2959708351f, -0.3389708908f), new Float2(-0.3714377181f, 0.254035473f), new Float2(-0.404467102f, -0.1972469604f), new Float2(0.1636165687f, -0.419201167f), new Float2(0.3289185495f, -0.3071035458f), new Float2(-0.2494824991f, -0.3745109914f), new Float2(0.03283133272f, 0.4488007393f), new Float2(-0.166306057f, -0.4181414777f),
+ new Float2(-0.106833179f, 0.4371346153f), new Float2(0.06440260376f, -0.4453676062f), new Float2(-0.4483230967f, 0.03881238203f), new Float2(-0.421377757f, -0.1579265206f), new Float2(0.05097920662f, -0.4471030312f), new Float2(0.2050584153f, -0.4005634111f), new Float2(0.4178098529f, -0.167137449f), new Float2(-0.3565189504f, -0.2745801121f),
+ new Float2(0.4478398129f, 0.04403977727f), new Float2(-0.3399999602f, -0.2947881053f), new Float2(0.3767121994f, 0.2461461331f), new Float2(-0.3138934434f, 0.3224451987f), new Float2(-0.1462001792f, -0.4255884251f), new Float2(0.3970290489f, -0.2118205239f), new Float2(0.4459149305f, -0.06049689889f), new Float2(-0.4104889426f, -0.1843877112f),
+ new Float2(0.1475103971f, -0.4251360756f), new Float2(0.09258030352f, 0.4403735771f), new Float2(-0.1589664637f, -0.4209865359f), new Float2(0.2482445008f, 0.3753327428f), new Float2(0.4383624232f, -0.1016778537f), new Float2(0.06242802956f, 0.4456486745f), new Float2(0.2846591015f, -0.3485243118f), new Float2(-0.344202744f, -0.2898697484f),
+ new Float2(0.1198188883f, -0.4337550392f), new Float2(-0.243590703f, 0.3783696201f), new Float2(0.2958191174f, -0.3391033025f), new Float2(-0.1164007991f, 0.4346847754f), new Float2(0.1274037151f, -0.4315881062f), new Float2(0.368047306f, 0.2589231171f), new Float2(0.2451436949f, 0.3773652989f), new Float2(-0.4314509715f, 0.12786735f),
+ };
+
+ private static final Float3[] CELL_3D =
+ {
+ new Float3(0.1453787434f, -0.4149781685f, -0.0956981749f), new Float3(-0.01242829687f, -0.1457918398f, -0.4255470325f), new Float3(0.2877979582f, -0.02606483451f, -0.3449535616f), new Float3(-0.07732986802f, 0.2377094325f, 0.3741848704f), new Float3(0.1107205875f, -0.3552302079f, -0.2530858567f), new Float3(0.2755209141f, 0.2640521179f, -0.238463215f), new Float3(0.294168941f, 0.1526064594f, 0.3044271714f), new Float3(0.4000921098f, -0.2034056362f, 0.03244149937f),
+ new Float3(-0.1697304074f, 0.3970864695f, -0.1265461359f), new Float3(-0.1483224484f, -0.3859694688f, 0.1775613147f), new Float3(0.2623596946f, -0.2354852944f, 0.2796677792f), new Float3(-0.2709003183f, 0.3505271138f, -0.07901746678f), new Float3(-0.03516550699f, 0.3885234328f, 0.2243054374f), new Float3(-0.1267712655f, 0.1920044036f, 0.3867342179f), new Float3(0.02952021915f, 0.4409685861f, 0.08470692262f), new Float3(-0.2806854217f, -0.266996757f, 0.2289725438f),
+ new Float3(-0.171159547f, 0.2141185563f, 0.3568720405f), new Float3(0.2113227183f, 0.3902405947f, -0.07453178509f), new Float3(-0.1024352839f, 0.2128044156f, -0.3830421561f), new Float3(-0.3304249877f, -0.1566986703f, 0.2622305365f), new Float3(0.2091111325f, 0.3133278055f, -0.2461670583f), new Float3(0.344678154f, -0.1944240454f, -0.2142341261f), new Float3(0.1984478035f, -0.3214342325f, -0.2445373252f), new Float3(-0.2929008603f, 0.2262915116f, 0.2559320961f),
+ new Float3(-0.1617332831f, 0.006314769776f, -0.4198838754f), new Float3(-0.3582060271f, -0.148303178f, -0.2284613961f), new Float3(-0.1852067326f, -0.3454119342f, -0.2211087107f), new Float3(0.3046301062f, 0.1026310383f, 0.314908508f), new Float3(-0.03816768434f, -0.2551766358f, -0.3686842991f), new Float3(-0.4084952196f, 0.1805950793f, 0.05492788837f), new Float3(-0.02687443361f, -0.2749741471f, 0.3551999201f), new Float3(-0.03801098351f, 0.3277859044f, 0.3059600725f),
+ new Float3(0.2371120802f, 0.2900386767f, -0.2493099024f), new Float3(0.4447660503f, 0.03946930643f, 0.05590469027f), new Float3(0.01985147278f, -0.01503183293f, -0.4493105419f), new Float3(0.4274339143f, 0.03345994256f, -0.1366772882f), new Float3(-0.2072988631f, 0.2871414597f, -0.2776273824f), new Float3(-0.3791240978f, 0.1281177671f, 0.2057929936f), new Float3(-0.2098721267f, -0.1007087278f, -0.3851122467f), new Float3(0.01582798878f, 0.4263894424f, 0.1429738373f),
+ new Float3(-0.1888129464f, -0.3160996813f, -0.2587096108f), new Float3(0.1612988974f, -0.1974805082f, -0.3707885038f), new Float3(-0.08974491322f, 0.229148752f, -0.3767448739f), new Float3(0.07041229526f, 0.4150230285f, -0.1590534329f), new Float3(-0.1082925611f, -0.1586061639f, 0.4069604477f), new Float3(0.2474100658f, -0.3309414609f, 0.1782302128f), new Float3(-0.1068836661f, -0.2701644537f, -0.3436379634f), new Float3(0.2396452163f, 0.06803600538f, -0.3747549496f),
+ new Float3(-0.3063886072f, 0.2597428179f, 0.2028785103f), new Float3(0.1593342891f, -0.3114350249f, -0.2830561951f), new Float3(0.2709690528f, 0.1412648683f, -0.3303331794f), new Float3(-0.1519780427f, 0.3623355133f, 0.2193527988f), new Float3(0.1699773681f, 0.3456012883f, 0.2327390037f), new Float3(-0.1986155616f, 0.3836276443f, -0.1260225743f), new Float3(-0.1887482106f, -0.2050154888f, -0.353330953f), new Float3(0.2659103394f, 0.3015631259f, -0.2021172246f),
+ new Float3(-0.08838976154f, -0.4288819642f, -0.1036702021f), new Float3(-0.04201869311f, 0.3099592485f, 0.3235115047f), new Float3(-0.3230334656f, 0.201549922f, -0.2398478873f), new Float3(0.2612720941f, 0.2759854499f, -0.2409749453f), new Float3(0.385713046f, 0.2193460345f, 0.07491837764f), new Float3(0.07654967953f, 0.3721732183f, 0.241095919f), new Float3(0.4317038818f, -0.02577753072f, 0.1243675091f), new Float3(-0.2890436293f, -0.3418179959f, -0.04598084447f),
+ new Float3(-0.2201947582f, 0.383023377f, -0.08548310451f), new Float3(0.4161322773f, -0.1669634289f, -0.03817251927f), new Float3(0.2204718095f, 0.02654238946f, -0.391391981f), new Float3(-0.1040307469f, 0.3890079625f, -0.2008741118f), new Float3(-0.1432122615f, 0.371614387f, -0.2095065525f), new Float3(0.3978380468f, -0.06206669342f, 0.2009293758f), new Float3(-0.2599274663f, 0.2616724959f, -0.2578084893f), new Float3(0.4032618332f, -0.1124593585f, 0.1650235939f),
+ new Float3(-0.08953470255f, -0.3048244735f, 0.3186935478f), new Float3(0.118937202f, -0.2875221847f, 0.325092195f), new Float3(0.02167047076f, -0.03284630549f, -0.4482761547f), new Float3(-0.3411343612f, 0.2500031105f, 0.1537068389f), new Float3(0.3162964612f, 0.3082064153f, -0.08640228117f), new Float3(0.2355138889f, -0.3439334267f, -0.1695376245f), new Float3(-0.02874541518f, -0.3955933019f, 0.2125550295f), new Float3(-0.2461455173f, 0.02020282325f, -0.3761704803f),
+ new Float3(0.04208029445f, -0.4470439576f, 0.02968078139f), new Float3(0.2727458746f, 0.2288471896f, -0.2752065618f), new Float3(-0.1347522818f, -0.02720848277f, -0.4284874806f), new Float3(0.3829624424f, 0.1231931484f, -0.2016512234f), new Float3(-0.3547613644f, 0.1271702173f, 0.2459107769f), new Float3(0.2305790207f, 0.3063895591f, 0.2354968222f), new Float3(-0.08323845599f, -0.1922245118f, 0.3982726409f), new Float3(0.2993663085f, -0.2619918095f, -0.2103333191f),
+ new Float3(-0.2154865723f, 0.2706747713f, 0.287751117f), new Float3(0.01683355354f, -0.2680655787f, -0.3610505186f), new Float3(0.05240429123f, 0.4335128183f, -0.1087217856f), new Float3(0.00940104872f, -0.4472890582f, 0.04841609928f), new Float3(0.3465688735f, 0.01141914583f, -0.2868093776f), new Float3(-0.3706867948f, -0.2551104378f, 0.003156692623f), new Float3(0.2741169781f, 0.2139972417f, -0.2855959784f), new Float3(0.06413433865f, 0.1708718512f, 0.4113266307f),
+ new Float3(-0.388187972f, -0.03973280434f, -0.2241236325f), new Float3(0.06419469312f, -0.2803682491f, 0.3460819069f), new Float3(-0.1986120739f, -0.3391173584f, 0.2192091725f), new Float3(-0.203203009f, -0.3871641506f, 0.1063600375f), new Float3(-0.1389736354f, -0.2775901578f, -0.3257760473f), new Float3(-0.06555641638f, 0.342253257f, -0.2847192729f), new Float3(-0.2529246486f, -0.2904227915f, 0.2327739768f), new Float3(0.1444476522f, 0.1069184044f, 0.4125570634f),
+ new Float3(-0.3643780054f, -0.2447099973f, -0.09922543227f), new Float3(0.4286142488f, -0.1358496089f, -0.01829506817f), new Float3(0.165872923f, -0.3136808464f, -0.2767498872f), new Float3(0.2219610524f, -0.3658139958f, 0.1393320198f), new Float3(0.04322940318f, -0.3832730794f, 0.2318037215f), new Float3(-0.08481269795f, -0.4404869674f, -0.03574965489f), new Float3(0.1822082075f, -0.3953259299f, 0.1140946023f), new Float3(-0.3269323334f, 0.3036542563f, 0.05838957105f),
+ new Float3(-0.4080485344f, 0.04227858267f, -0.184956522f), new Float3(0.2676025294f, -0.01299671652f, 0.36155217f), new Float3(0.3024892441f, -0.1009990293f, -0.3174892964f), new Float3(0.1448494052f, 0.425921681f, -0.0104580805f), new Float3(0.4198402157f, 0.08062320474f, 0.1404780841f), new Float3(-0.3008872161f, -0.333040905f, -0.03241355801f), new Float3(0.3639310428f, -0.1291284382f, -0.2310412139f), new Float3(0.3295806598f, 0.0184175994f, -0.3058388149f),
+ new Float3(0.2776259487f, -0.2974929052f, -0.1921504723f), new Float3(0.4149000507f, -0.144793182f, -0.09691688386f), new Float3(0.145016715f, -0.0398992945f, 0.4241205002f), new Float3(0.09299023471f, -0.299732164f, -0.3225111565f), new Float3(0.1028907093f, -0.361266869f, 0.247789732f), new Float3(0.2683057049f, -0.07076041213f, -0.3542668666f), new Float3(-0.4227307273f, -0.07933161816f, -0.1323073187f), new Float3(-0.1781224702f, 0.1806857196f, -0.3716517945f),
+ new Float3(0.4390788626f, -0.02841848598f, -0.09435116353f), new Float3(0.2972583585f, 0.2382799621f, -0.2394997452f), new Float3(-0.1707002821f, 0.2215845691f, 0.3525077196f), new Float3(0.3806686614f, 0.1471852559f, -0.1895464869f), new Float3(-0.1751445661f, -0.274887877f, 0.3102596268f), new Float3(-0.2227237566f, -0.2316778837f, 0.3149912482f), new Float3(0.1369633021f, 0.1341343041f, -0.4071228836f), new Float3(-0.3529503428f, -0.2472893463f, -0.129514612f),
+ new Float3(-0.2590744185f, -0.2985577559f, -0.2150435121f), new Float3(-0.3784019401f, 0.2199816631f, -0.1044989934f), new Float3(-0.05635805671f, 0.1485737441f, 0.4210102279f), new Float3(0.3251428613f, 0.09666046873f, -0.2957006485f), new Float3(-0.4190995804f, 0.1406751354f, -0.08405978803f), new Float3(-0.3253150961f, -0.3080335042f, -0.04225456877f), new Float3(0.2857945863f, -0.05796152095f, 0.3427271751f), new Float3(-0.2733604046f, 0.1973770973f, -0.2980207554f),
+ new Float3(0.219003657f, 0.2410037886f, -0.3105713639f), new Float3(0.3182767252f, -0.271342949f, 0.1660509868f), new Float3(-0.03222023115f, -0.3331161506f, -0.300824678f), new Float3(-0.3087780231f, 0.1992794134f, -0.2596995338f), new Float3(-0.06487611647f, -0.4311322747f, 0.1114273361f), new Float3(0.3921171432f, -0.06294284106f, -0.2116183942f), new Float3(-0.1606404506f, -0.358928121f, -0.2187812825f), new Float3(-0.03767771199f, -0.2290351443f, 0.3855169162f),
+ new Float3(0.1394866832f, -0.3602213994f, 0.2308332918f), new Float3(-0.4345093872f, 0.005751117145f, 0.1169124335f), new Float3(-0.1044637494f, 0.4168128432f, -0.1336202785f), new Float3(0.2658727501f, 0.2551943237f, 0.2582393035f), new Float3(0.2051461999f, 0.1975390727f, 0.3484154868f), new Float3(-0.266085566f, 0.23483312f, 0.2766800993f), new Float3(0.07849405464f, -0.3300346342f, -0.2956616708f), new Float3(-0.2160686338f, 0.05376451292f, -0.3910546287f),
+ new Float3(-0.185779186f, 0.2148499206f, 0.3490352499f), new Float3(0.02492421743f, -0.3229954284f, -0.3123343347f), new Float3(-0.120167831f, 0.4017266681f, 0.1633259825f), new Float3(-0.02160084693f, -0.06885389554f, 0.4441762538f), new Float3(0.2597670064f, 0.3096300784f, 0.1978643903f), new Float3(-0.1611553854f, -0.09823036005f, 0.4085091653f), new Float3(-0.3278896792f, 0.1461670309f, 0.2713366126f), new Float3(0.2822734956f, 0.03754421121f, -0.3484423997f),
+ new Float3(0.03169341113f, 0.347405252f, -0.2842624114f), new Float3(0.2202613604f, -0.3460788041f, -0.1849713341f), new Float3(0.2933396046f, 0.3031973659f, 0.1565989581f), new Float3(-0.3194922995f, 0.2453752201f, -0.200538455f), new Float3(-0.3441586045f, -0.1698856132f, -0.2349334659f), new Float3(0.2703645948f, -0.3574277231f, 0.04060059933f), new Float3(0.2298568861f, 0.3744156221f, 0.0973588921f), new Float3(0.09326603877f, -0.3170108894f, 0.3054595587f),
+ new Float3(-0.1116165319f, -0.2985018719f, 0.3177080142f), new Float3(0.2172907365f, -0.3460005203f, -0.1885958001f), new Float3(0.1991339479f, 0.3820341668f, -0.1299829458f), new Float3(-0.0541918155f, -0.2103145071f, 0.39412061f), new Float3(0.08871336998f, 0.2012117383f, 0.3926114802f), new Float3(0.2787673278f, 0.3505404674f, 0.04370535101f), new Float3(-0.322166438f, 0.3067213525f, 0.06804996813f), new Float3(-0.4277366384f, 0.132066775f, 0.04582286686f),
+ new Float3(0.240131882f, -0.1612516055f, 0.344723946f), new Float3(0.1448607981f, -0.2387819045f, 0.3528435224f), new Float3(-0.3837065682f, -0.2206398454f, 0.08116235683f), new Float3(-0.4382627882f, -0.09082753406f, -0.04664855374f), new Float3(-0.37728353f, 0.05445141085f, 0.2391488697f), new Float3(0.1259579313f, 0.348394558f, 0.2554522098f), new Float3(-0.1406285511f, -0.270877371f, -0.3306796947f), new Float3(-0.1580694418f, 0.4162931958f, -0.06491553533f),
+ new Float3(0.2477612106f, -0.2927867412f, -0.2353514536f), new Float3(0.2916132853f, 0.3312535401f, 0.08793624968f), new Float3(0.07365265219f, -0.1666159848f, 0.411478311f), new Float3(-0.26126526f, -0.2422237692f, 0.2748965434f), new Float3(-0.3721862032f, 0.252790166f, 0.008634938242f), new Float3(-0.3691191571f, -0.255281188f, 0.03290232422f), new Float3(0.2278441737f, -0.3358364886f, 0.1944244981f), new Float3(0.363398169f, -0.2310190248f, 0.1306597909f),
+ new Float3(-0.304231482f, -0.2698452035f, 0.1926830856f), new Float3(-0.3199312232f, 0.316332536f, -0.008816977938f), new Float3(0.2874852279f, 0.1642275508f, -0.304764754f), new Float3(-0.1451096801f, 0.3277541114f, -0.2720669462f), new Float3(0.3220090754f, 0.0511344108f, 0.3101538769f), new Float3(-0.1247400865f, -0.04333605335f, -0.4301882115f), new Float3(-0.2829555867f, -0.3056190617f, -0.1703910946f), new Float3(0.1069384374f, 0.3491024667f, -0.2630430352f),
+ new Float3(-0.1420661144f, -0.3055376754f, -0.2982682484f), new Float3(-0.250548338f, 0.3156466809f, -0.2002316239f), new Float3(0.3265787872f, 0.1871229129f, 0.2466400438f), new Float3(0.07646097258f, -0.3026690852f, 0.324106687f), new Float3(0.3451771584f, 0.2757120714f, -0.0856480183f), new Float3(0.298137964f, 0.2852657134f, 0.179547284f), new Float3(0.2812250376f, 0.3466716415f, 0.05684409612f), new Float3(0.4390345476f, -0.09790429955f, -0.01278335452f),
+ new Float3(0.2148373234f, 0.1850172527f, 0.3494474791f), new Float3(0.2595421179f, -0.07946825393f, 0.3589187731f), new Float3(0.3182823114f, -0.307355516f, -0.08203022006f), new Float3(-0.4089859285f, -0.04647718411f, 0.1818526372f), new Float3(-0.2826749061f, 0.07417482322f, 0.3421885344f), new Float3(0.3483864637f, 0.225442246f, -0.1740766085f), new Float3(-0.3226415069f, -0.1420585388f, -0.2796816575f), new Float3(0.4330734858f, -0.118868561f, -0.02859407492f),
+ new Float3(-0.08717822568f, -0.3909896417f, -0.2050050172f), new Float3(-0.2149678299f, 0.3939973956f, -0.03247898316f), new Float3(-0.2687330705f, 0.322686276f, -0.1617284888f), new Float3(0.2105665099f, -0.1961317136f, -0.3459683451f), new Float3(0.4361845915f, -0.1105517485f, 0.004616608544f), new Float3(0.05333333359f, -0.313639498f, -0.3182543336f), new Float3(-0.05986216652f, 0.1361029153f, -0.4247264031f), new Float3(0.3664988455f, 0.2550543014f, -0.05590974511f),
+ new Float3(-0.2341015558f, -0.182405731f, 0.3382670703f), new Float3(-0.04730947785f, -0.4222150243f, -0.1483114513f), new Float3(-0.2391566239f, -0.2577696514f, -0.2808182972f), new Float3(-0.1242081035f, 0.4256953395f, -0.07652336246f), new Float3(0.2614832715f, -0.3650179274f, 0.02980623099f), new Float3(-0.2728794681f, -0.3499628774f, 0.07458404908f), new Float3(0.007892900508f, -0.1672771315f, 0.4176793787f), new Float3(-0.01730330376f, 0.2978486637f, -0.3368779738f),
+ new Float3(0.2054835762f, -0.3252600376f, -0.2334146693f), new Float3(-0.3231994983f, 0.1564282844f, -0.2712420987f), new Float3(-0.2669545963f, 0.2599343665f, -0.2523278991f), new Float3(-0.05554372779f, 0.3170813944f, -0.3144428146f), new Float3(-0.2083935713f, -0.310922837f, -0.2497981362f), new Float3(0.06989323478f, -0.3156141536f, 0.3130537363f), new Float3(0.3847566193f, -0.1605309138f, -0.1693876312f), new Float3(-0.3026215288f, -0.3001537679f, -0.1443188342f),
+ new Float3(0.3450735512f, 0.08611519592f, 0.2756962409f), new Float3(0.1814473292f, -0.2788782453f, -0.3029914042f), new Float3(-0.03855010448f, 0.09795110726f, 0.4375151083f), new Float3(0.3533670318f, 0.2665752752f, 0.08105160988f), new Float3(-0.007945601311f, 0.140359426f, -0.4274764309f), new Float3(0.4063099273f, -0.1491768253f, -0.1231199324f), new Float3(-0.2016773589f, 0.008816271194f, -0.4021797064f), new Float3(-0.07527055435f, -0.425643481f, -0.1251477955f),
+ };
+
+
+ private static int FastFloor(float f) {
+ return (f >= 0 ? (int) f : (int) f - 1);
+ }
+
+
+ private static int FastRound(float f) {
+ return (f >= 0) ? (int) (f + (float) 0.5) : (int) (f - (float) 0.5);
+ }
+
+
+ private static float Lerp(float a, float b, float t) {
+ return a + t * (b - a);
+ }
+
+
+ private static float InterpHermiteFunc(float t) {
+ return t * t * (3 - 2 * t);
+ }
+
+
+ private static float InterpQuinticFunc(float t) {
+ return t * t * t * (t * (t * 6 - 15) + 10);
+ }
+
+
+ private static float CubicLerp(float a, float b, float c, float d, float t) {
+ float p = (d - c) - (a - b);
+ return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b;
+ }
+
+ private void CalculateFractalBounding() {
+ float amp = m_gain;
+ float ampFractal = 1;
+ for (int i = 1; i < m_octaves; i++) {
+ ampFractal += amp;
+ amp *= m_gain;
+ }
+ m_fractalBounding = 1 / ampFractal;
+ }
+
+ // Hashing
+ private final static int X_PRIME = 1619;
+ private final static int Y_PRIME = 31337;
+ private final static int Z_PRIME = 6971;
+ private final static int W_PRIME = 1013;
+
+ private static int Hash2D(int seed, int x, int y) {
+ int hash = seed;
+ hash ^= X_PRIME * x;
+ hash ^= Y_PRIME * y;
+
+ hash = hash * hash * hash * 60493;
+ hash = (hash >> 13) ^ hash;
+
+ return hash;
+ }
+
+ private static int Hash3D(int seed, int x, int y, int z) {
+ int hash = seed;
+ hash ^= X_PRIME * x;
+ hash ^= Y_PRIME * y;
+ hash ^= Z_PRIME * z;
+
+ hash = hash * hash * hash * 60493;
+ hash = (hash >> 13) ^ hash;
+
+ return hash;
+ }
+
+ private static float ValCoord2D(int seed, int x, int y) {
+ int n = seed;
+ n ^= X_PRIME * x;
+ n ^= Y_PRIME * y;
+
+ return (n * n * n * 60493) / (float) 2147483648.0;
+ }
+
+ private static float ValCoord3D(int seed, int x, int y, int z) {
+ int n = seed;
+ n ^= X_PRIME * x;
+ n ^= Y_PRIME * y;
+ n ^= Z_PRIME * z;
+
+ return (n * n * n * 60493) / (float) 2147483648.0;
+ }
+
+ private static float ValCoord4D(int seed, int x, int y, int z, int w) {
+ int n = seed;
+ n ^= X_PRIME * x;
+ n ^= Y_PRIME * y;
+ n ^= Z_PRIME * z;
+ n ^= W_PRIME * w;
+
+ return (n * n * n * 60493) / (float) 2147483648.0;
+ }
+
+ private static float GradCoord2D(int seed, int x, int y, float xd, float yd) {
+ int hash = seed;
+ hash ^= X_PRIME * x;
+ hash ^= Y_PRIME * y;
+
+ hash = hash * hash * hash * 60493;
+ hash = (hash >> 13) ^ hash;
+
+ Float2 g = GRAD_2D[hash & 7];
+
+ return xd * g.x + yd * g.y;
+ }
+
+ private static float GradCoord3D(int seed, int x, int y, int z, float xd, float yd, float zd) {
+ int hash = seed;
+ hash ^= X_PRIME * x;
+ hash ^= Y_PRIME * y;
+ hash ^= Z_PRIME * z;
+
+ hash = hash * hash * hash * 60493;
+ hash = (hash >> 13) ^ hash;
+
+ Float3 g = GRAD_3D[hash & 15];
+
+ return xd * g.x + yd * g.y + zd * g.z;
+ }
+
+ private static float GradCoord4D(int seed, int x, int y, int z, int w, float xd, float yd, float zd, float wd) {
+ int hash = seed;
+ hash ^= X_PRIME * x;
+ hash ^= Y_PRIME * y;
+ hash ^= Z_PRIME * z;
+ hash ^= W_PRIME * w;
+
+ hash = hash * hash * hash * 60493;
+ hash = (hash >> 13) ^ hash;
+
+ hash &= 31;
+ float a = yd, b = zd, c = wd; // X,Y,Z
+ switch (hash >> 3) { // OR, DEPENDING ON HIGH ORDER 2 BITS:
+ case 1:
+ a = wd;
+ b = xd;
+ c = yd;
+ break; // W,X,Y
+ case 2:
+ a = zd;
+ b = wd;
+ c = xd;
+ break; // Z,W,X
+ case 3:
+ a = yd;
+ b = zd;
+ c = wd;
+ break; // Y,Z,W
+ }
+ return ((hash & 4) == 0 ? -a : a) + ((hash & 2) == 0 ? -b : b) + ((hash & 1) == 0 ? -c : c);
+ }
+
+ public float GetNoise(float x, float y, float z) {
+ x *= m_frequency;
+ y *= m_frequency;
+ z *= m_frequency;
+
+ switch (m_noiseType) {
+ case Value:
+ return SingleValue(m_seed, x, y, z);
+ case ValueFractal:
+ switch (m_fractalType) {
+ case FBM:
+ return SingleValueFractalFBM(x, y, z);
+ case Billow:
+ return SingleValueFractalBillow(x, y, z);
+ case RigidMulti:
+ return SingleValueFractalRigidMulti(x, y, z);
+ default:
+ return 0;
+ }
+ case Perlin:
+ return SinglePerlin(m_seed, x, y, z);
+ case PerlinFractal:
+ switch (m_fractalType) {
+ case FBM:
+ return SinglePerlinFractalFBM(x, y, z);
+ case Billow:
+ return SinglePerlinFractalBillow(x, y, z);
+ case RigidMulti:
+ return SinglePerlinFractalRigidMulti(x, y, z);
+ default:
+ return 0;
+ }
+ case Simplex:
+ return SingleSimplex(m_seed, x, y, z);
+ case SimplexFractal:
+ switch (m_fractalType) {
+ case FBM:
+ return SingleSimplexFractalFBM(x, y, z);
+ case Billow:
+ return SingleSimplexFractalBillow(x, y, z);
+ case RigidMulti:
+ return SingleSimplexFractalRigidMulti(x, y, z);
+ default:
+ return 0;
+ }
+ case Cellular:
+ switch (m_cellularReturnType) {
+ case CellValue:
+ case NoiseLookup:
+ case Distance:
+ return SingleCellular(x, y, z);
+ default:
+ return SingleCellular2Edge(x, y, z);
+ }
+ case WhiteNoise:
+ return GetWhiteNoise(x, y, z);
+ case Cubic:
+ return SingleCubic(m_seed, x, y, z);
+ case CubicFractal:
+ switch (m_fractalType) {
+ case FBM:
+ return SingleCubicFractalFBM(x, y, z);
+ case Billow:
+ return SingleCubicFractalBillow(x, y, z);
+ case RigidMulti:
+ return SingleCubicFractalRigidMulti(x, y, z);
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+ }
+
+ public float GetNoise(float x, float y) {
+ x *= m_frequency;
+ y *= m_frequency;
+
+ switch (m_noiseType) {
+ case Value:
+ return SingleValue(m_seed, x, y);
+ case ValueFractal:
+ switch (m_fractalType) {
+ case FBM:
+ return SingleValueFractalFBM(x, y);
+ case Billow:
+ return SingleValueFractalBillow(x, y);
+ case RigidMulti:
+ return SingleValueFractalRigidMulti(x, y);
+ default:
+ return 0;
+ }
+ case Perlin:
+ return SinglePerlin(m_seed, x, y);
+ case PerlinFractal:
+ switch (m_fractalType) {
+ case FBM:
+ return SinglePerlinFractalFBM(x, y);
+ case Billow:
+ return SinglePerlinFractalBillow(x, y);
+ case RigidMulti:
+ return SinglePerlinFractalRigidMulti(x, y);
+ default:
+ return 0;
+ }
+ case Simplex:
+ return SingleSimplex(m_seed, x, y);
+ case SimplexFractal:
+ switch (m_fractalType) {
+ case FBM:
+ return SingleSimplexFractalFBM(x, y);
+ case Billow:
+ return SingleSimplexFractalBillow(x, y);
+ case RigidMulti:
+ return SingleSimplexFractalRigidMulti(x, y);
+ default:
+ return 0;
+ }
+ case Cellular:
+ switch (m_cellularReturnType) {
+ case CellValue:
+ case NoiseLookup:
+ case Distance:
+ return SingleCellular(x, y);
+ default:
+ return SingleCellular2Edge(x, y);
+ }
+ case WhiteNoise:
+ return GetWhiteNoise(x, y);
+ case Cubic:
+ return SingleCubic(m_seed, x, y);
+ case CubicFractal:
+ switch (m_fractalType) {
+ case FBM:
+ return SingleCubicFractalFBM(x, y);
+ case Billow:
+ return SingleCubicFractalBillow(x, y);
+ case RigidMulti:
+ return SingleCubicFractalRigidMulti(x, y);
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+ }
+
+ // White Noise
+
+ private int FloatCast2Int(float f) {
+ int i = Float.floatToRawIntBits(f);
+
+ return i ^ (i >> 16);
+ }
+
+ public float GetWhiteNoise(float x, float y, float z, float w) {
+ int xi = FloatCast2Int(x);
+ int yi = FloatCast2Int(y);
+ int zi = FloatCast2Int(z);
+ int wi = FloatCast2Int(w);
+
+ return ValCoord4D(m_seed, xi, yi, zi, wi);
+ }
+
+ public float GetWhiteNoise(float x, float y, float z) {
+ int xi = FloatCast2Int(x);
+ int yi = FloatCast2Int(y);
+ int zi = FloatCast2Int(z);
+
+ return ValCoord3D(m_seed, xi, yi, zi);
+ }
+
+ public float GetWhiteNoise(float x, float y) {
+ int xi = FloatCast2Int(x);
+ int yi = FloatCast2Int(y);
+
+ return ValCoord2D(m_seed, xi, yi);
+ }
+
+ public float GetWhiteNoiseInt(int x, int y, int z, int w) {
+ return ValCoord4D(m_seed, x, y, z, w);
+ }
+
+ public float GetWhiteNoiseInt(int x, int y, int z) {
+ return ValCoord3D(m_seed, x, y, z);
+ }
+
+ public float GetWhiteNoiseInt(int x, int y) {
+ return ValCoord2D(m_seed, x, y);
+ }
+
+ // Value Noise
+ public float GetValueFractal(float x, float y, float z) {
+ x *= m_frequency;
+ y *= m_frequency;
+ z *= m_frequency;
+
+ switch (m_fractalType) {
+ case FBM:
+ return SingleValueFractalFBM(x, y, z);
+ case Billow:
+ return SingleValueFractalBillow(x, y, z);
+ case RigidMulti:
+ return SingleValueFractalRigidMulti(x, y, z);
+ default:
+ return 0;
+ }
+ }
+
+ private float SingleValueFractalFBM(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = SingleValue(seed, x, y, z);
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += SingleValue(++seed, x, y, z) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleValueFractalBillow(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = Math.abs(SingleValue(seed, x, y, z)) * 2 - 1;
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += (Math.abs(SingleValue(++seed, x, y, z)) * 2 - 1) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleValueFractalRigidMulti(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = 1 - Math.abs(SingleValue(seed, x, y, z));
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum -= (1 - Math.abs(SingleValue(++seed, x, y, z))) * amp;
+ }
+
+ return sum;
+ }
+
+ public float GetValue(float x, float y, float z) {
+ return SingleValue(m_seed, x * m_frequency, y * m_frequency, z * m_frequency);
+ }
+
+ private float SingleValue(int seed, float x, float y, float z) {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+ int z0 = FastFloor(z);
+ int x1 = x0 + 1;
+ int y1 = y0 + 1;
+ int z1 = z0 + 1;
+
+ float xs, ys, zs;
+ switch (m_interp) {
+ default:
+ case Linear:
+ xs = x - x0;
+ ys = y - y0;
+ zs = z - z0;
+ break;
+ case Hermite:
+ xs = InterpHermiteFunc(x - x0);
+ ys = InterpHermiteFunc(y - y0);
+ zs = InterpHermiteFunc(z - z0);
+ break;
+ case Quintic:
+ xs = InterpQuinticFunc(x - x0);
+ ys = InterpQuinticFunc(y - y0);
+ zs = InterpQuinticFunc(z - z0);
+ break;
+ }
+
+ float xf00 = Lerp(ValCoord3D(seed, x0, y0, z0), ValCoord3D(seed, x1, y0, z0), xs);
+ float xf10 = Lerp(ValCoord3D(seed, x0, y1, z0), ValCoord3D(seed, x1, y1, z0), xs);
+ float xf01 = Lerp(ValCoord3D(seed, x0, y0, z1), ValCoord3D(seed, x1, y0, z1), xs);
+ float xf11 = Lerp(ValCoord3D(seed, x0, y1, z1), ValCoord3D(seed, x1, y1, z1), xs);
+
+ float yf0 = Lerp(xf00, xf10, ys);
+ float yf1 = Lerp(xf01, xf11, ys);
+
+ return Lerp(yf0, yf1, zs);
+ }
+
+ public float GetValueFractal(float x, float y) {
+ x *= m_frequency;
+ y *= m_frequency;
+
+ switch (m_fractalType) {
+ case FBM:
+ return SingleValueFractalFBM(x, y);
+ case Billow:
+ return SingleValueFractalBillow(x, y);
+ case RigidMulti:
+ return SingleValueFractalRigidMulti(x, y);
+ default:
+ return 0;
+ }
+ }
+
+ private float SingleValueFractalFBM(float x, float y) {
+ int seed = m_seed;
+ float sum = SingleValue(seed, x, y);
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += SingleValue(++seed, x, y) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleValueFractalBillow(float x, float y) {
+ int seed = m_seed;
+ float sum = Math.abs(SingleValue(seed, x, y)) * 2 - 1;
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ amp *= m_gain;
+ sum += (Math.abs(SingleValue(++seed, x, y)) * 2 - 1) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleValueFractalRigidMulti(float x, float y) {
+ int seed = m_seed;
+ float sum = 1 - Math.abs(SingleValue(seed, x, y));
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum -= (1 - Math.abs(SingleValue(++seed, x, y))) * amp;
+ }
+
+ return sum;
+ }
+
+ public float GetValue(float x, float y) {
+ return SingleValue(m_seed, x * m_frequency, y * m_frequency);
+ }
+
+ private float SingleValue(int seed, float x, float y) {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+ int x1 = x0 + 1;
+ int y1 = y0 + 1;
+
+ float xs, ys;
+ switch (m_interp) {
+ default:
+ case Linear:
+ xs = x - x0;
+ ys = y - y0;
+ break;
+ case Hermite:
+ xs = InterpHermiteFunc(x - x0);
+ ys = InterpHermiteFunc(y - y0);
+ break;
+ case Quintic:
+ xs = InterpQuinticFunc(x - x0);
+ ys = InterpQuinticFunc(y - y0);
+ break;
+ }
+
+ float xf0 = Lerp(ValCoord2D(seed, x0, y0), ValCoord2D(seed, x1, y0), xs);
+ float xf1 = Lerp(ValCoord2D(seed, x0, y1), ValCoord2D(seed, x1, y1), xs);
+
+ return Lerp(xf0, xf1, ys);
+ }
+
+ // Gradient Noise
+ public float GetPerlinFractal(float x, float y, float z) {
+ x *= m_frequency;
+ y *= m_frequency;
+ z *= m_frequency;
+
+ switch (m_fractalType) {
+ case FBM:
+ return SinglePerlinFractalFBM(x, y, z);
+ case Billow:
+ return SinglePerlinFractalBillow(x, y, z);
+ case RigidMulti:
+ return SinglePerlinFractalRigidMulti(x, y, z);
+ default:
+ return 0;
+ }
+ }
+
+ private float SinglePerlinFractalFBM(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = SinglePerlin(seed, x, y, z);
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += SinglePerlin(++seed, x, y, z) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SinglePerlinFractalBillow(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = Math.abs(SinglePerlin(seed, x, y, z)) * 2 - 1;
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += (Math.abs(SinglePerlin(++seed, x, y, z)) * 2 - 1) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SinglePerlinFractalRigidMulti(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = 1 - Math.abs(SinglePerlin(seed, x, y, z));
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum -= (1 - Math.abs(SinglePerlin(++seed, x, y, z))) * amp;
+ }
+
+ return sum;
+ }
+
+ public float GetPerlin(float x, float y, float z) {
+ return SinglePerlin(m_seed, x * m_frequency, y * m_frequency, z * m_frequency);
+ }
+
+ private float SinglePerlin(int seed, float x, float y, float z) {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+ int z0 = FastFloor(z);
+ int x1 = x0 + 1;
+ int y1 = y0 + 1;
+ int z1 = z0 + 1;
+
+ float xs, ys, zs;
+ switch (m_interp) {
+ default:
+ case Linear:
+ xs = x - x0;
+ ys = y - y0;
+ zs = z - z0;
+ break;
+ case Hermite:
+ xs = InterpHermiteFunc(x - x0);
+ ys = InterpHermiteFunc(y - y0);
+ zs = InterpHermiteFunc(z - z0);
+ break;
+ case Quintic:
+ xs = InterpQuinticFunc(x - x0);
+ ys = InterpQuinticFunc(y - y0);
+ zs = InterpQuinticFunc(z - z0);
+ break;
+ }
+
+ float xd0 = x - x0;
+ float yd0 = y - y0;
+ float zd0 = z - z0;
+ float xd1 = xd0 - 1;
+ float yd1 = yd0 - 1;
+ float zd1 = zd0 - 1;
+
+ float xf00 = Lerp(GradCoord3D(seed, x0, y0, z0, xd0, yd0, zd0), GradCoord3D(seed, x1, y0, z0, xd1, yd0, zd0), xs);
+ float xf10 = Lerp(GradCoord3D(seed, x0, y1, z0, xd0, yd1, zd0), GradCoord3D(seed, x1, y1, z0, xd1, yd1, zd0), xs);
+ float xf01 = Lerp(GradCoord3D(seed, x0, y0, z1, xd0, yd0, zd1), GradCoord3D(seed, x1, y0, z1, xd1, yd0, zd1), xs);
+ float xf11 = Lerp(GradCoord3D(seed, x0, y1, z1, xd0, yd1, zd1), GradCoord3D(seed, x1, y1, z1, xd1, yd1, zd1), xs);
+
+ float yf0 = Lerp(xf00, xf10, ys);
+ float yf1 = Lerp(xf01, xf11, ys);
+
+ return Lerp(yf0, yf1, zs);
+ }
+
+ public float GetPerlinFractal(float x, float y) {
+ x *= m_frequency;
+ y *= m_frequency;
+
+ switch (m_fractalType) {
+ case FBM:
+ return SinglePerlinFractalFBM(x, y);
+ case Billow:
+ return SinglePerlinFractalBillow(x, y);
+ case RigidMulti:
+ return SinglePerlinFractalRigidMulti(x, y);
+ default:
+ return 0;
+ }
+ }
+
+ private float SinglePerlinFractalFBM(float x, float y) {
+ int seed = m_seed;
+ float sum = SinglePerlin(seed, x, y);
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += SinglePerlin(++seed, x, y) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SinglePerlinFractalBillow(float x, float y) {
+ int seed = m_seed;
+ float sum = Math.abs(SinglePerlin(seed, x, y)) * 2 - 1;
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += (Math.abs(SinglePerlin(++seed, x, y)) * 2 - 1) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SinglePerlinFractalRigidMulti(float x, float y) {
+ int seed = m_seed;
+ float sum = 1 - Math.abs(SinglePerlin(seed, x, y));
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum -= (1 - Math.abs(SinglePerlin(++seed, x, y))) * amp;
+ }
+
+ return sum;
+ }
+
+ public float GetPerlin(float x, float y) {
+ return SinglePerlin(m_seed, x * m_frequency, y * m_frequency);
+ }
+
+ private float SinglePerlin(int seed, float x, float y) {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+ int x1 = x0 + 1;
+ int y1 = y0 + 1;
+
+ float xs, ys;
+ switch (m_interp) {
+ default:
+ case Linear:
+ xs = x - x0;
+ ys = y - y0;
+ break;
+ case Hermite:
+ xs = InterpHermiteFunc(x - x0);
+ ys = InterpHermiteFunc(y - y0);
+ break;
+ case Quintic:
+ xs = InterpQuinticFunc(x - x0);
+ ys = InterpQuinticFunc(y - y0);
+ break;
+ }
+
+ float xd0 = x - x0;
+ float yd0 = y - y0;
+ float xd1 = xd0 - 1;
+ float yd1 = yd0 - 1;
+
+ float xf0 = Lerp(GradCoord2D(seed, x0, y0, xd0, yd0), GradCoord2D(seed, x1, y0, xd1, yd0), xs);
+ float xf1 = Lerp(GradCoord2D(seed, x0, y1, xd0, yd1), GradCoord2D(seed, x1, y1, xd1, yd1), xs);
+
+ return Lerp(xf0, xf1, ys);
+ }
+
+ // Simplex Noise
+ public float GetSimplexFractal(float x, float y, float z) {
+ x *= m_frequency;
+ y *= m_frequency;
+ z *= m_frequency;
+
+ switch (m_fractalType) {
+ case FBM:
+ return SingleSimplexFractalFBM(x, y, z);
+ case Billow:
+ return SingleSimplexFractalBillow(x, y, z);
+ case RigidMulti:
+ return SingleSimplexFractalRigidMulti(x, y, z);
+ default:
+ return 0;
+ }
+ }
+
+ private float SingleSimplexFractalFBM(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = SingleSimplex(seed, x, y, z);
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += SingleSimplex(++seed, x, y, z) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleSimplexFractalBillow(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = Math.abs(SingleSimplex(seed, x, y, z)) * 2 - 1;
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += (Math.abs(SingleSimplex(++seed, x, y, z)) * 2 - 1) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleSimplexFractalRigidMulti(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = 1 - Math.abs(SingleSimplex(seed, x, y, z));
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum -= (1 - Math.abs(SingleSimplex(++seed, x, y, z))) * amp;
+ }
+
+ return sum;
+ }
+
+ public float GetSimplex(float x, float y, float z) {
+ return SingleSimplex(m_seed, x * m_frequency, y * m_frequency, z * m_frequency);
+ }
+
+ private final static float F3 = (float) (1.0 / 3.0);
+ private final static float G3 = (float) (1.0 / 6.0);
+ private final static float G33 = G3 * 3 - 1;
+
+ private float SingleSimplex(int seed, float x, float y, float z) {
+ float t = (x + y + z) * F3;
+ int i = FastFloor(x + t);
+ int j = FastFloor(y + t);
+ int k = FastFloor(z + t);
+
+ t = (i + j + k) * G3;
+ float x0 = x - (i - t);
+ float y0 = y - (j - t);
+ float z0 = z - (k - t);
+
+ int i1, j1, k1;
+ int i2, j2, k2;
+
+ if (x0 >= y0) {
+ if (y0 >= z0) {
+ i1 = 1;
+ j1 = 0;
+ k1 = 0;
+ i2 = 1;
+ j2 = 1;
+ k2 = 0;
+ } else if (x0 >= z0) {
+ i1 = 1;
+ j1 = 0;
+ k1 = 0;
+ i2 = 1;
+ j2 = 0;
+ k2 = 1;
+ } else // x0 < z0
+ {
+ i1 = 0;
+ j1 = 0;
+ k1 = 1;
+ i2 = 1;
+ j2 = 0;
+ k2 = 1;
+ }
+ } else // x0 < y0
+ {
+ if (y0 < z0) {
+ i1 = 0;
+ j1 = 0;
+ k1 = 1;
+ i2 = 0;
+ j2 = 1;
+ k2 = 1;
+ } else if (x0 < z0) {
+ i1 = 0;
+ j1 = 1;
+ k1 = 0;
+ i2 = 0;
+ j2 = 1;
+ k2 = 1;
+ } else // x0 >= z0
+ {
+ i1 = 0;
+ j1 = 1;
+ k1 = 0;
+ i2 = 1;
+ j2 = 1;
+ k2 = 0;
+ }
+ }
+
+ float x1 = x0 - i1 + G3;
+ float y1 = y0 - j1 + G3;
+ float z1 = z0 - k1 + G3;
+ float x2 = x0 - i2 + F3;
+ float y2 = y0 - j2 + F3;
+ float z2 = z0 - k2 + F3;
+ float x3 = x0 + G33;
+ float y3 = y0 + G33;
+ float z3 = z0 + G33;
+
+ float n0, n1, n2, n3;
+
+ t = (float) 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
+ if (t < 0) n0 = 0;
+ else {
+ t *= t;
+ n0 = t * t * GradCoord3D(seed, i, j, k, x0, y0, z0);
+ }
+
+ t = (float) 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
+ if (t < 0) n1 = 0;
+ else {
+ t *= t;
+ n1 = t * t * GradCoord3D(seed, i + i1, j + j1, k + k1, x1, y1, z1);
+ }
+
+ t = (float) 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
+ if (t < 0) n2 = 0;
+ else {
+ t *= t;
+ n2 = t * t * GradCoord3D(seed, i + i2, j + j2, k + k2, x2, y2, z2);
+ }
+
+ t = (float) 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
+ if (t < 0) n3 = 0;
+ else {
+ t *= t;
+ n3 = t * t * GradCoord3D(seed, i + 1, j + 1, k + 1, x3, y3, z3);
+ }
+
+ return 32 * (n0 + n1 + n2 + n3);
+ }
+
+ public float GetSimplexFractal(float x, float y) {
+ x *= m_frequency;
+ y *= m_frequency;
+
+ switch (m_fractalType) {
+ case FBM:
+ return SingleSimplexFractalFBM(x, y);
+ case Billow:
+ return SingleSimplexFractalBillow(x, y);
+ case RigidMulti:
+ return SingleSimplexFractalRigidMulti(x, y);
+ default:
+ return 0;
+ }
+ }
+
+ private float SingleSimplexFractalFBM(float x, float y) {
+ int seed = m_seed;
+ float sum = SingleSimplex(seed, x, y);
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += SingleSimplex(++seed, x, y) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleSimplexFractalBillow(float x, float y) {
+ int seed = m_seed;
+ float sum = Math.abs(SingleSimplex(seed, x, y)) * 2 - 1;
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += (Math.abs(SingleSimplex(++seed, x, y)) * 2 - 1) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleSimplexFractalRigidMulti(float x, float y) {
+ int seed = m_seed;
+ float sum = 1 - Math.abs(SingleSimplex(seed, x, y));
+ float amp = 1;
+
+ for (int i = 1; i < m_octaves; i++) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum -= (1 - Math.abs(SingleSimplex(++seed, x, y))) * amp;
+ }
+
+ return sum;
+ }
+
+ public float GetSimplex(float x, float y) {
+ return SingleSimplex(m_seed, x * m_frequency, y * m_frequency);
+ }
+
+ private final static float F2 = (float) (1.0 / 2.0);
+ private final static float G2 = (float) (1.0 / 4.0);
+
+ private float SingleSimplex(int seed, float x, float y) {
+ float t = (x + y) * F2;
+ int i = FastFloor(x + t);
+ int j = FastFloor(y + t);
+
+ t = (i + j) * G2;
+ float X0 = i - t;
+ float Y0 = j - t;
+
+ float x0 = x - X0;
+ float y0 = y - Y0;
+
+ int i1, j1;
+ if (x0 > y0) {
+ i1 = 1;
+ j1 = 0;
+ } else {
+ i1 = 0;
+ j1 = 1;
+ }
+
+ float x1 = x0 - i1 + G2;
+ float y1 = y0 - j1 + G2;
+ float x2 = x0 - 1 + F2;
+ float y2 = y0 - 1 + F2;
+
+ float n0, n1, n2;
+
+ t = (float) 0.5 - x0 * x0 - y0 * y0;
+ if (t < 0) n0 = 0;
+ else {
+ t *= t;
+ n0 = t * t * GradCoord2D(seed, i, j, x0, y0);
+ }
+
+ t = (float) 0.5 - x1 * x1 - y1 * y1;
+ if (t < 0) n1 = 0;
+ else {
+ t *= t;
+ n1 = t * t * GradCoord2D(seed, i + i1, j + j1, x1, y1);
+ }
+
+ t = (float) 0.5 - x2 * x2 - y2 * y2;
+ if (t < 0) n2 = 0;
+ else {
+ t *= t;
+ n2 = t * t * GradCoord2D(seed, i + 1, j + 1, x2, y2);
+ }
+
+ return 50 * (n0 + n1 + n2);
+ }
+
+ public float GetSimplex(float x, float y, float z, float w) {
+ return SingleSimplex(m_seed, x * m_frequency, y * m_frequency, z * m_frequency, w * m_frequency);
+ }
+
+ private static final byte[] SIMPLEX_4D =
+ {
+ 0, 1, 2, 3, 0, 1, 3, 2, 0, 0, 0, 0, 0, 2, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0,
+ 0, 2, 1, 3, 0, 0, 0, 0, 0, 3, 1, 2, 0, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 2, 0, 3, 0, 0, 0, 0, 1, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 1, 2, 3, 1, 0,
+ 1, 0, 2, 3, 1, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 1, 0, 0, 0, 0, 2, 1, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 2, 3, 0, 2, 1, 0, 0, 0, 0, 3, 1, 2, 0,
+ 2, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 2, 0, 0, 0, 0, 3, 2, 0, 1, 3, 2, 1, 0
+ };
+
+ private final static float F4 = (float) ((2.23606797 - 1.0) / 4.0);
+ private final static float G4 = (float) ((5.0 - 2.23606797) / 20.0);
+
+ private float SingleSimplex(int seed, float x, float y, float z, float w) {
+ float n0, n1, n2, n3, n4;
+ float t = (x + y + z + w) * F4;
+ int i = FastFloor(x + t);
+ int j = FastFloor(y + t);
+ int k = FastFloor(z + t);
+ int l = FastFloor(w + t);
+ t = (i + j + k + l) * G4;
+ float X0 = i - t;
+ float Y0 = j - t;
+ float Z0 = k - t;
+ float W0 = l - t;
+ float x0 = x - X0;
+ float y0 = y - Y0;
+ float z0 = z - Z0;
+ float w0 = w - W0;
+
+ int c = (x0 > y0) ? 32 : 0;
+ c += (x0 > z0) ? 16 : 0;
+ c += (y0 > z0) ? 8 : 0;
+ c += (x0 > w0) ? 4 : 0;
+ c += (y0 > w0) ? 2 : 0;
+ c += (z0 > w0) ? 1 : 0;
+ c <<= 2;
+
+ int i1 = SIMPLEX_4D[c] >= 3 ? 1 : 0;
+ int i2 = SIMPLEX_4D[c] >= 2 ? 1 : 0;
+ int i3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0;
+ int j1 = SIMPLEX_4D[c] >= 3 ? 1 : 0;
+ int j2 = SIMPLEX_4D[c] >= 2 ? 1 : 0;
+ int j3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0;
+ int k1 = SIMPLEX_4D[c] >= 3 ? 1 : 0;
+ int k2 = SIMPLEX_4D[c] >= 2 ? 1 : 0;
+ int k3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0;
+ int l1 = SIMPLEX_4D[c] >= 3 ? 1 : 0;
+ int l2 = SIMPLEX_4D[c] >= 2 ? 1 : 0;
+ int l3 = SIMPLEX_4D[c] >= 1 ? 1 : 0;
+
+ float x1 = x0 - i1 + G4;
+ float y1 = y0 - j1 + G4;
+ float z1 = z0 - k1 + G4;
+ float w1 = w0 - l1 + G4;
+ float x2 = x0 - i2 + 2 * G4;
+ float y2 = y0 - j2 + 2 * G4;
+ float z2 = z0 - k2 + 2 * G4;
+ float w2 = w0 - l2 + 2 * G4;
+ float x3 = x0 - i3 + 3 * G4;
+ float y3 = y0 - j3 + 3 * G4;
+ float z3 = z0 - k3 + 3 * G4;
+ float w3 = w0 - l3 + 3 * G4;
+ float x4 = x0 - 1 + 4 * G4;
+ float y4 = y0 - 1 + 4 * G4;
+ float z4 = z0 - 1 + 4 * G4;
+ float w4 = w0 - 1 + 4 * G4;
+
+ t = (float) 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
+ if (t < 0) n0 = 0;
+ else {
+ t *= t;
+ n0 = t * t * GradCoord4D(seed, i, j, k, l, x0, y0, z0, w0);
+ }
+ t = (float) 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
+ if (t < 0) n1 = 0;
+ else {
+ t *= t;
+ n1 = t * t * GradCoord4D(seed, i + i1, j + j1, k + k1, l + l1, x1, y1, z1, w1);
+ }
+ t = (float) 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
+ if (t < 0) n2 = 0;
+ else {
+ t *= t;
+ n2 = t * t * GradCoord4D(seed, i + i2, j + j2, k + k2, l + l2, x2, y2, z2, w2);
+ }
+ t = (float) 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
+ if (t < 0) n3 = 0;
+ else {
+ t *= t;
+ n3 = t * t * GradCoord4D(seed, i + i3, j + j3, k + k3, l + l3, x3, y3, z3, w3);
+ }
+ t = (float) 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
+ if (t < 0) n4 = 0;
+ else {
+ t *= t;
+ n4 = t * t * GradCoord4D(seed, i + 1, j + 1, k + 1, l + 1, x4, y4, z4, w4);
+ }
+
+ return 27 * (n0 + n1 + n2 + n3 + n4);
+ }
+
+ // Cubic Noise
+ public float GetCubicFractal(float x, float y, float z) {
+ x *= m_frequency;
+ y *= m_frequency;
+ z *= m_frequency;
+
+ switch (m_fractalType) {
+ case FBM:
+ return SingleCubicFractalFBM(x, y, z);
+ case Billow:
+ return SingleCubicFractalBillow(x, y, z);
+ case RigidMulti:
+ return SingleCubicFractalRigidMulti(x, y, z);
+ default:
+ return 0;
+ }
+ }
+
+ private float SingleCubicFractalFBM(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = SingleCubic(seed, x, y, z);
+ float amp = 1;
+ int i = 0;
+
+ while (++i < m_octaves) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += SingleCubic(++seed, x, y, z) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleCubicFractalBillow(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = Math.abs(SingleCubic(seed, x, y, z)) * 2 - 1;
+ float amp = 1;
+ int i = 0;
+
+ while (++i < m_octaves) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += (Math.abs(SingleCubic(++seed, x, y, z)) * 2 - 1) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleCubicFractalRigidMulti(float x, float y, float z) {
+ int seed = m_seed;
+ float sum = 1 - Math.abs(SingleCubic(seed, x, y, z));
+ float amp = 1;
+ int i = 0;
+
+ while (++i < m_octaves) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+ z *= m_lacunarity;
+
+ amp *= m_gain;
+ sum -= (1 - Math.abs(SingleCubic(++seed, x, y, z))) * amp;
+ }
+
+ return sum;
+ }
+
+ public float GetCubic(float x, float y, float z) {
+ return SingleCubic(m_seed, x * m_frequency, y * m_frequency, z * m_frequency);
+ }
+
+ private final static float CUBIC_3D_BOUNDING = 1 / (float) (1.5 * 1.5 * 1.5);
+
+ private float SingleCubic(int seed, float x, float y, float z) {
+ int x1 = FastFloor(x);
+ int y1 = FastFloor(y);
+ int z1 = FastFloor(z);
+
+ int x0 = x1 - 1;
+ int y0 = y1 - 1;
+ int z0 = z1 - 1;
+ int x2 = x1 + 1;
+ int y2 = y1 + 1;
+ int z2 = z1 + 1;
+ int x3 = x1 + 2;
+ int y3 = y1 + 2;
+ int z3 = z1 + 2;
+
+ float xs = x - (float) x1;
+ float ys = y - (float) y1;
+ float zs = z - (float) z1;
+
+ return CubicLerp(
+ CubicLerp(
+ CubicLerp(ValCoord3D(seed, x0, y0, z0), ValCoord3D(seed, x1, y0, z0), ValCoord3D(seed, x2, y0, z0), ValCoord3D(seed, x3, y0, z0), xs),
+ CubicLerp(ValCoord3D(seed, x0, y1, z0), ValCoord3D(seed, x1, y1, z0), ValCoord3D(seed, x2, y1, z0), ValCoord3D(seed, x3, y1, z0), xs),
+ CubicLerp(ValCoord3D(seed, x0, y2, z0), ValCoord3D(seed, x1, y2, z0), ValCoord3D(seed, x2, y2, z0), ValCoord3D(seed, x3, y2, z0), xs),
+ CubicLerp(ValCoord3D(seed, x0, y3, z0), ValCoord3D(seed, x1, y3, z0), ValCoord3D(seed, x2, y3, z0), ValCoord3D(seed, x3, y3, z0), xs),
+ ys),
+ CubicLerp(
+ CubicLerp(ValCoord3D(seed, x0, y0, z1), ValCoord3D(seed, x1, y0, z1), ValCoord3D(seed, x2, y0, z1), ValCoord3D(seed, x3, y0, z1), xs),
+ CubicLerp(ValCoord3D(seed, x0, y1, z1), ValCoord3D(seed, x1, y1, z1), ValCoord3D(seed, x2, y1, z1), ValCoord3D(seed, x3, y1, z1), xs),
+ CubicLerp(ValCoord3D(seed, x0, y2, z1), ValCoord3D(seed, x1, y2, z1), ValCoord3D(seed, x2, y2, z1), ValCoord3D(seed, x3, y2, z1), xs),
+ CubicLerp(ValCoord3D(seed, x0, y3, z1), ValCoord3D(seed, x1, y3, z1), ValCoord3D(seed, x2, y3, z1), ValCoord3D(seed, x3, y3, z1), xs),
+ ys),
+ CubicLerp(
+ CubicLerp(ValCoord3D(seed, x0, y0, z2), ValCoord3D(seed, x1, y0, z2), ValCoord3D(seed, x2, y0, z2), ValCoord3D(seed, x3, y0, z2), xs),
+ CubicLerp(ValCoord3D(seed, x0, y1, z2), ValCoord3D(seed, x1, y1, z2), ValCoord3D(seed, x2, y1, z2), ValCoord3D(seed, x3, y1, z2), xs),
+ CubicLerp(ValCoord3D(seed, x0, y2, z2), ValCoord3D(seed, x1, y2, z2), ValCoord3D(seed, x2, y2, z2), ValCoord3D(seed, x3, y2, z2), xs),
+ CubicLerp(ValCoord3D(seed, x0, y3, z2), ValCoord3D(seed, x1, y3, z2), ValCoord3D(seed, x2, y3, z2), ValCoord3D(seed, x3, y3, z2), xs),
+ ys),
+ CubicLerp(
+ CubicLerp(ValCoord3D(seed, x0, y0, z3), ValCoord3D(seed, x1, y0, z3), ValCoord3D(seed, x2, y0, z3), ValCoord3D(seed, x3, y0, z3), xs),
+ CubicLerp(ValCoord3D(seed, x0, y1, z3), ValCoord3D(seed, x1, y1, z3), ValCoord3D(seed, x2, y1, z3), ValCoord3D(seed, x3, y1, z3), xs),
+ CubicLerp(ValCoord3D(seed, x0, y2, z3), ValCoord3D(seed, x1, y2, z3), ValCoord3D(seed, x2, y2, z3), ValCoord3D(seed, x3, y2, z3), xs),
+ CubicLerp(ValCoord3D(seed, x0, y3, z3), ValCoord3D(seed, x1, y3, z3), ValCoord3D(seed, x2, y3, z3), ValCoord3D(seed, x3, y3, z3), xs),
+ ys),
+ zs) * CUBIC_3D_BOUNDING;
+ }
+
+
+ public float GetCubicFractal(float x, float y) {
+ x *= m_frequency;
+ y *= m_frequency;
+
+ switch (m_fractalType) {
+ case FBM:
+ return SingleCubicFractalFBM(x, y);
+ case Billow:
+ return SingleCubicFractalBillow(x, y);
+ case RigidMulti:
+ return SingleCubicFractalRigidMulti(x, y);
+ default:
+ return 0;
+ }
+ }
+
+ private float SingleCubicFractalFBM(float x, float y) {
+ int seed = m_seed;
+ float sum = SingleCubic(seed, x, y);
+ float amp = 1;
+ int i = 0;
+
+ while (++i < m_octaves) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += SingleCubic(++seed, x, y) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleCubicFractalBillow(float x, float y) {
+ int seed = m_seed;
+ float sum = Math.abs(SingleCubic(seed, x, y)) * 2 - 1;
+ float amp = 1;
+ int i = 0;
+
+ while (++i < m_octaves) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum += (Math.abs(SingleCubic(++seed, x, y)) * 2 - 1) * amp;
+ }
+
+ return sum * m_fractalBounding;
+ }
+
+ private float SingleCubicFractalRigidMulti(float x, float y) {
+ int seed = m_seed;
+ float sum = 1 - Math.abs(SingleCubic(seed, x, y));
+ float amp = 1;
+ int i = 0;
+
+ while (++i < m_octaves) {
+ x *= m_lacunarity;
+ y *= m_lacunarity;
+
+ amp *= m_gain;
+ sum -= (1 - Math.abs(SingleCubic(++seed, x, y))) * amp;
+ }
+
+ return sum;
+ }
+
+ public float GetCubic(float x, float y) {
+ x *= m_frequency;
+ y *= m_frequency;
+
+ return SingleCubic(0, x, y);
+ }
+
+ private final static float CUBIC_2D_BOUNDING = 1 / (float) (1.5 * 1.5);
+
+ private float SingleCubic(int seed, float x, float y) {
+ int x1 = FastFloor(x);
+ int y1 = FastFloor(y);
+
+ int x0 = x1 - 1;
+ int y0 = y1 - 1;
+ int x2 = x1 + 1;
+ int y2 = y1 + 1;
+ int x3 = x1 + 2;
+ int y3 = y1 + 2;
+
+ float xs = x - (float) x1;
+ float ys = y - (float) y1;
+
+ return CubicLerp(
+ CubicLerp(ValCoord2D(seed, x0, y0), ValCoord2D(seed, x1, y0), ValCoord2D(seed, x2, y0), ValCoord2D(seed, x3, y0),
+ xs),
+ CubicLerp(ValCoord2D(seed, x0, y1), ValCoord2D(seed, x1, y1), ValCoord2D(seed, x2, y1), ValCoord2D(seed, x3, y1),
+ xs),
+ CubicLerp(ValCoord2D(seed, x0, y2), ValCoord2D(seed, x1, y2), ValCoord2D(seed, x2, y2), ValCoord2D(seed, x3, y2),
+ xs),
+ CubicLerp(ValCoord2D(seed, x0, y3), ValCoord2D(seed, x1, y3), ValCoord2D(seed, x2, y3), ValCoord2D(seed, x3, y3),
+ xs),
+ ys) * CUBIC_2D_BOUNDING;
+ }
+
+ // Cellular Noise
+ public float GetCellular(float x, float y, float z) {
+ x *= m_frequency;
+ y *= m_frequency;
+ z *= m_frequency;
+
+ switch (m_cellularReturnType) {
+ case CellValue:
+ case NoiseLookup:
+ case Distance:
+ return SingleCellular(x, y, z);
+ default:
+ return SingleCellular2Edge(x, y, z);
+ }
+ }
+
+ private float SingleCellular(float x, float y, float z) {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+ int zr = FastRound(z);
+
+ float distance = 999999;
+ int xc = 0, yc = 0, zc = 0;
+
+ switch (m_cellularDistanceFunction) {
+ case Euclidean:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ for (int zi = zr - 1; zi <= zr + 1; zi++) {
+ Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+ float vecZ = zi - z + vec.z;
+
+ float newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ zc = zi;
+ }
+ }
+ }
+ }
+ break;
+ case Manhattan:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ for (int zi = zr - 1; zi <= zr + 1; zi++) {
+ Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+ float vecZ = zi - z + vec.z;
+
+ float newDistance = Math.abs(vecX) + Math.abs(vecY) + Math.abs(vecZ);
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ zc = zi;
+ }
+ }
+ }
+ }
+ break;
+ case Natural:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ for (int zi = zr - 1; zi <= zr + 1; zi++) {
+ Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+ float vecZ = zi - z + vec.z;
+
+ float newDistance = (Math.abs(vecX) + Math.abs(vecY) + Math.abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ);
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ zc = zi;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ switch (m_cellularReturnType) {
+ case CellValue:
+ return ValCoord3D(0, xc, yc, zc);
+
+ case NoiseLookup:
+ Float3 vec = CELL_3D[Hash3D(m_seed, xc, yc, zc) & 255];
+ return m_cellularNoiseLookup.GetNoise(xc + vec.x, yc + vec.y, zc + vec.z);
+
+ case Distance:
+ return distance - 1;
+ default:
+ return 0;
+ }
+ }
+
+ private float SingleCellular2Edge(float x, float y, float z) {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+ int zr = FastRound(z);
+
+ float distance = 999999;
+ float distance2 = 999999;
+
+ switch (m_cellularDistanceFunction) {
+ case Euclidean:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ for (int zi = zr - 1; zi <= zr + 1; zi++) {
+ Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+ float vecZ = zi - z + vec.z;
+
+ float newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;
+
+ distance2 = Math.max(Math.min(distance2, newDistance), distance);
+ distance = Math.min(distance, newDistance);
+ }
+ }
+ }
+ break;
+ case Manhattan:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ for (int zi = zr - 1; zi <= zr + 1; zi++) {
+ Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+ float vecZ = zi - z + vec.z;
+
+ float newDistance = Math.abs(vecX) + Math.abs(vecY) + Math.abs(vecZ);
+
+ distance2 = Math.max(Math.min(distance2, newDistance), distance);
+ distance = Math.min(distance, newDistance);
+ }
+ }
+ }
+ break;
+ case Natural:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ for (int zi = zr - 1; zi <= zr + 1; zi++) {
+ Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+ float vecZ = zi - z + vec.z;
+
+ float newDistance = (Math.abs(vecX) + Math.abs(vecY) + Math.abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ);
+
+ distance2 = Math.max(Math.min(distance2, newDistance), distance);
+ distance = Math.min(distance, newDistance);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (m_cellularReturnType) {
+ case Distance2:
+ return distance2 - 1;
+ case Distance2Add:
+ return distance2 + distance - 1;
+ case Distance2Sub:
+ return distance2 - distance - 1;
+ case Distance2Mul:
+ return distance2 * distance - 1;
+ case Distance2Div:
+ return distance / distance2 - 1;
+ default:
+ return 0;
+ }
+ }
+
+ public float GetCellular(float x, float y) {
+ x *= m_frequency;
+ y *= m_frequency;
+
+ switch (m_cellularReturnType) {
+ case CellValue:
+ case NoiseLookup:
+ case Distance:
+ return SingleCellular(x, y);
+ default:
+ return SingleCellular2Edge(x, y);
+ }
+ }
+
+ private float SingleCellular(float x, float y) {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+
+ float distance = 999999;
+ int xc = 0, yc = 0;
+
+ switch (m_cellularDistanceFunction) {
+ default:
+ case Euclidean:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = vecX * vecX + vecY * vecY;
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ }
+ }
+ }
+ break;
+ case Manhattan:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = (Math.abs(vecX) + Math.abs(vecY));
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ }
+ }
+ }
+ break;
+ case Natural:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = (Math.abs(vecX) + Math.abs(vecY)) + (vecX * vecX + vecY * vecY);
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ }
+ }
+ }
+ break;
+ }
+
+ switch (m_cellularReturnType) {
+ case CellValue:
+ return ValCoord2D(0, xc, yc);
+
+ case NoiseLookup:
+ Float2 vec = CELL_2D[Hash2D(m_seed, xc, yc) & 255];
+ return m_cellularNoiseLookup.GetNoise(xc + vec.x, yc + vec.y);
+
+ case Distance:
+ return distance - 1;
+ default:
+ return 0;
+ }
+ }
+
+ private float SingleCellular2Edge(float x, float y) {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+
+ float distance = 999999;
+ float distance2 = 999999;
+
+ switch (m_cellularDistanceFunction) {
+ default:
+ case Euclidean:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = vecX * vecX + vecY * vecY;
+
+ distance2 = Math.max(Math.min(distance2, newDistance), distance);
+ distance = Math.min(distance, newDistance);
+ }
+ }
+ break;
+ case Manhattan:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = Math.abs(vecX) + Math.abs(vecY);
+
+ distance2 = Math.max(Math.min(distance2, newDistance), distance);
+ distance = Math.min(distance, newDistance);
+ }
+ }
+ break;
+ case Natural:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = (Math.abs(vecX) + Math.abs(vecY)) + (vecX * vecX + vecY * vecY);
+
+ distance2 = Math.max(Math.min(distance2, newDistance), distance);
+ distance = Math.min(distance, newDistance);
+ }
+ }
+ break;
+ }
+
+ switch (m_cellularReturnType) {
+ case Distance2:
+ return distance2 - 1;
+ case Distance2Add:
+ return distance2 + distance - 1;
+ case Distance2Sub:
+ return distance2 - distance - 1;
+ case Distance2Mul:
+ return distance2 * distance - 1;
+ case Distance2Div:
+ return distance / distance2 - 1;
+ default:
+ return 0;
+ }
+ }
+
+ public void GradientPerturb(Vector3f v3) {
+ SingleGradientPerturb(m_seed, m_gradientPerturbAmp, m_frequency, v3);
+ }
+
+ public void GradientPerturbFractal(Vector3f v3) {
+ int seed = m_seed;
+ float amp = m_gradientPerturbAmp * m_fractalBounding;
+ float freq = m_frequency;
+
+ SingleGradientPerturb(seed, amp, m_frequency, v3);
+
+ for (int i = 1; i < m_octaves; i++) {
+ freq *= m_lacunarity;
+ amp *= m_gain;
+ SingleGradientPerturb(++seed, amp, freq, v3);
+ }
+ }
+
+ private void SingleGradientPerturb(int seed, float perturbAmp, float frequency, Vector3f v3) {
+ float xf = v3.x * frequency;
+ float yf = v3.y * frequency;
+ float zf = v3.z * frequency;
+
+ int x0 = FastFloor(xf);
+ int y0 = FastFloor(yf);
+ int z0 = FastFloor(zf);
+ int x1 = x0 + 1;
+ int y1 = y0 + 1;
+ int z1 = z0 + 1;
+
+ float xs, ys, zs;
+ switch (m_interp) {
+ default:
+ case Linear:
+ xs = xf - x0;
+ ys = yf - y0;
+ zs = zf - z0;
+ break;
+ case Hermite:
+ xs = InterpHermiteFunc(xf - x0);
+ ys = InterpHermiteFunc(yf - y0);
+ zs = InterpHermiteFunc(zf - z0);
+ break;
+ case Quintic:
+ xs = InterpQuinticFunc(xf - x0);
+ ys = InterpQuinticFunc(yf - y0);
+ zs = InterpQuinticFunc(zf - z0);
+ break;
+ }
+
+ Float3 vec0 = CELL_3D[Hash3D(seed, x0, y0, z0) & 255];
+ Float3 vec1 = CELL_3D[Hash3D(seed, x1, y0, z0) & 255];
+
+ float lx0x = Lerp(vec0.x, vec1.x, xs);
+ float ly0x = Lerp(vec0.y, vec1.y, xs);
+ float lz0x = Lerp(vec0.z, vec1.z, xs);
+
+ vec0 = CELL_3D[Hash3D(seed, x0, y1, z0) & 255];
+ vec1 = CELL_3D[Hash3D(seed, x1, y1, z0) & 255];
+
+ float lx1x = Lerp(vec0.x, vec1.x, xs);
+ float ly1x = Lerp(vec0.y, vec1.y, xs);
+ float lz1x = Lerp(vec0.z, vec1.z, xs);
+
+ float lx0y = Lerp(lx0x, lx1x, ys);
+ float ly0y = Lerp(ly0x, ly1x, ys);
+ float lz0y = Lerp(lz0x, lz1x, ys);
+
+ vec0 = CELL_3D[Hash3D(seed, x0, y0, z1) & 255];
+ vec1 = CELL_3D[Hash3D(seed, x1, y0, z1) & 255];
+
+ lx0x = Lerp(vec0.x, vec1.x, xs);
+ ly0x = Lerp(vec0.y, vec1.y, xs);
+ lz0x = Lerp(vec0.z, vec1.z, xs);
+
+ vec0 = CELL_3D[Hash3D(seed, x0, y1, z1) & 255];
+ vec1 = CELL_3D[Hash3D(seed, x1, y1, z1) & 255];
+
+ lx1x = Lerp(vec0.x, vec1.x, xs);
+ ly1x = Lerp(vec0.y, vec1.y, xs);
+ lz1x = Lerp(vec0.z, vec1.z, xs);
+
+ v3.x += Lerp(lx0y, Lerp(lx0x, lx1x, ys), zs) * perturbAmp;
+ v3.y += Lerp(ly0y, Lerp(ly0x, ly1x, ys), zs) * perturbAmp;
+ v3.z += Lerp(lz0y, Lerp(lz0x, lz1x, ys), zs) * perturbAmp;
+ }
+
+ public void GradientPerturb(Vector2f v2) {
+ SingleGradientPerturb(m_seed, m_gradientPerturbAmp, m_frequency, v2);
+ }
+
+ public void GradientPerturbFractal(Vector2f v2) {
+ int seed = m_seed;
+ float amp = m_gradientPerturbAmp * m_fractalBounding;
+ float freq = m_frequency;
+
+ SingleGradientPerturb(seed, amp, m_frequency, v2);
+
+ for (int i = 1; i < m_octaves; i++) {
+ freq *= m_lacunarity;
+ amp *= m_gain;
+ SingleGradientPerturb(++seed, amp, freq, v2);
+ }
+ }
+
+ private void SingleGradientPerturb(int seed, float perturbAmp, float frequency, Vector2f v2) {
+ float xf = v2.x * frequency;
+ float yf = v2.y * frequency;
+
+ int x0 = FastFloor(xf);
+ int y0 = FastFloor(yf);
+ int x1 = x0 + 1;
+ int y1 = y0 + 1;
+
+ float xs, ys;
+ switch (m_interp) {
+ default:
+ case Linear:
+ xs = xf - x0;
+ ys = yf - y0;
+ break;
+ case Hermite:
+ xs = InterpHermiteFunc(xf - x0);
+ ys = InterpHermiteFunc(yf - y0);
+ break;
+ case Quintic:
+ xs = InterpQuinticFunc(xf - x0);
+ ys = InterpQuinticFunc(yf - y0);
+ break;
+ }
+
+ Float2 vec0 = CELL_2D[Hash2D(seed, x0, y0) & 255];
+ Float2 vec1 = CELL_2D[Hash2D(seed, x1, y0) & 255];
+
+ float lx0x = Lerp(vec0.x, vec1.x, xs);
+ float ly0x = Lerp(vec0.y, vec1.y, xs);
+
+ vec0 = CELL_2D[Hash2D(seed, x0, y1) & 255];
+ vec1 = CELL_2D[Hash2D(seed, x1, y1) & 255];
+
+ float lx1x = Lerp(vec0.x, vec1.x, xs);
+ float ly1x = Lerp(vec0.y, vec1.y, xs);
+
+ v2.x += Lerp(lx0x, lx1x, ys) * perturbAmp;
+ v2.y += Lerp(ly0x, ly1x, ys) * perturbAmp;
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Command/CommandHandler.java b/src/main/java/net/tylermurphy/Minecraft/Command/CommandHandler.java new file mode 100755 index 0000000..c289604 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Command/CommandHandler.java @@ -0,0 +1,37 @@ +package net.tylermurphy.Minecraft.Command;
+
+import net.tylermurphy.Minecraft.Command.Commands.Teleport;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+
+public class CommandHandler {
+
+ public final static Map<String, ICommand> REGISTER = new HashMap<>();
+
+ public static void registerCommands() {
+ register(new Teleport());
+ }
+
+ private static void register(ICommand command) {
+ if (!REGISTER.containsKey(command.getInvoke())) {
+ REGISTER.put(command.getInvoke().toLowerCase(), command);
+ }
+ }
+
+ public static void handleCommand(String text) {
+ final String[] split = text.replaceFirst(
+ "(?i)" + Pattern.quote("/"), "").split("\\s+");
+ final String invoke = split[0].toLowerCase();
+ if(REGISTER.containsKey(invoke)) {
+ ICommand command = REGISTER.get(invoke);
+ final List<String> args = Arrays.asList(split).subList(1, split.length);
+ command.invoke(args);
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Command/Commands/Teleport.java b/src/main/java/net/tylermurphy/Minecraft/Command/Commands/Teleport.java new file mode 100755 index 0000000..a48955c --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Command/Commands/Teleport.java @@ -0,0 +1,30 @@ +package net.tylermurphy.Minecraft.Command.Commands;
+
+import java.util.List;
+
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.Command.ICommand;
+import net.tylermurphy.Minecraft.Scene.World;
+
+public class Teleport implements ICommand {
+
+ public void invoke(List<String> args) {
+ if(args.size() < 3) return;
+ float x,y,z;
+ try {
+ x = Float.parseFloat(args.get(0));
+ y = Float.parseFloat(args.get(1));
+ z = Float.parseFloat(args.get(2));
+ } catch (Exception e) {
+ return;
+ }
+
+ World.player.getTransform().setGlobalPosition(new Vector3f(x,y,z));
+ }
+
+ public String getInvoke() {
+ return "tp";
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Command/ICommand.java b/src/main/java/net/tylermurphy/Minecraft/Command/ICommand.java new file mode 100755 index 0000000..c3b85d3 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Command/ICommand.java @@ -0,0 +1,11 @@ +package net.tylermurphy.Minecraft.Command;
+
+import java.util.List;
+
+public interface ICommand {
+
+ public void invoke(List<String> args);
+
+ public String getInvoke();
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Gen/WorldGenerator.java b/src/main/java/net/tylermurphy/Minecraft/Gen/WorldGenerator.java new file mode 100755 index 0000000..b912ccd --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Gen/WorldGenerator.java @@ -0,0 +1,112 @@ +package net.tylermurphy.Minecraft.Gen;
+
+import net.tylermurphy.Minecraft.Chunk.Chunk;
+import net.tylermurphy.Minecraft.Chunk.PerlinNoise;
+import net.tylermurphy.Minecraft.Scene.World;
+
+public class WorldGenerator {
+
+ private static int OCTAVES = 2;
+ private static int AMPLITUDE = 10;
+ private static int ROUGHNESS = 3;
+
+ public static int generateHeight(int x, int z) {
+ float total = 0;
+ float d = (float) Math.pow(2, OCTAVES-1);
+ for(int i=0;i<OCTAVES;i++){
+ float freq = (float) (Math.pow(2, i) / d);
+ float amp = (float) Math.pow(ROUGHNESS, i) * AMPLITUDE;
+ total += getInterpolatedNoise((x)*freq, (z)*freq) * amp;
+ }
+ return (int) total+100;
+ }
+
+ private static float interpolate(float a, float b, float blend){
+ double theta = blend * Math.PI;
+ float f = (float)(1f - Math.cos(theta)) * 0.5f;
+ return a * (1f - f) + b * f;
+ }
+
+ private static float getInterpolatedNoise(float x, float z){
+ int intX = (int) x;
+ int intZ = (int) z;
+ float fracX = x - intX;
+ float fracZ = z - intZ;
+
+ float v1 = (float) PerlinNoise.getNoise(World.seed, intX, intZ);
+ float v2 = (float) PerlinNoise.getNoise(World.seed, intX + 1, intZ);
+ float v3 = (float) PerlinNoise.getNoise(World.seed, intX, intZ + 1);
+ float v4 = (float) PerlinNoise.getNoise(World.seed, intX + 1, intZ + 1);
+ float i1 = interpolate(v1, v2, fracX);
+ float i2 = interpolate(v3, v4, fracX);
+ return interpolate(i1, i2, fracZ);
+ }
+
+ private static void generateLandscape(Chunk c) {
+ for(int x=0;x<16;x++) {
+ for(int z=0;z<16;z++) {
+ int top = generateHeight(c.gridX*16+x, c.gridZ*16+z);
+ for(int y=0;y<256;y++) {
+ if(top<=95) {
+ if(y < top) c.cubes[x][y][z] = 14;
+ else if(y == top) c.cubes[x][y][z] = 13;
+ else if(y <= 90) c.cubes[x][y][z] = 17;
+ else c.cubes[x][y][z] = -1;
+ } else {
+ if(y < top - 90) c.cubes[x][y][z] = 2;
+ else if(y < top) c.cubes[x][y][z] = 1;
+ else if(y == top) c.cubes[x][y][z] = 0;
+ else c.cubes[x][y][z] = -1;
+ }
+ }
+ }
+ }
+ }
+
+ private static void generateNature(Chunk c) {
+ for(int x=0;x<16;x++) {
+ for(int z=0;z<16;z++) {
+ int top = generateHeight(c.gridX*16+x, c.gridZ*16+z);
+ double n1 = PerlinNoise.getNoise(c.chunk_seed, x*2+z, z/2-x,PerlinNoise.NoiseType.WhiteNoise);
+ double n2 = PerlinNoise.getNoise(c.chunk_seed, z*5-z*2, x/4+6-x*5,PerlinNoise.NoiseType.WhiteNoise);
+ double n3 = PerlinNoise.getNoise(c.chunk_seed, x/5+17, z/14,PerlinNoise.NoiseType.WhiteNoise);
+ double n4 = PerlinNoise.getNoise(c.chunk_seed, z+5, (int)Math.pow(x,2),PerlinNoise.NoiseType.WhiteNoise);
+ if(top<=95) {
+ if(n1*n2/n3*n4>2 && top > 90) {
+ c.cubes[x][top+1][z] = 15;
+ c.cubes[x][top+2][z] = 15;
+ c.cubes[x][top+3][z] = 15;
+ }
+ } else {
+ if(n1*n2/n4*n3>2 && top > 90) {
+ if(x < 1 || x > 14 || z < 1 || z > 14) continue;
+ c.cubes[x][top+1][z] = 10;
+ c.cubes[x][top+2][z] = 10;
+ c.cubes[x][top+3][z] = 10;
+
+ c.cubes[x-1][top+3][z] = 12;
+ c.cubes[x-1][top+3][z+1] = 12;
+ c.cubes[x][top+3][z+1] = 12;
+ c.cubes[x+1][top+3][z+1] = 12;
+ c.cubes[x+1][top+3][z] = 12;
+ c.cubes[x+1][top+3][z-1] = 12;
+ c.cubes[x][top+3][z-1] = 12;
+ c.cubes[x-1][top+3][z-1] = 12;
+
+ c.cubes[x+1][top+4][z] = 12;
+ c.cubes[x-1][top+4][z] = 12;
+ c.cubes[x][top+4][z+1] = 12;
+ c.cubes[x][top+4][z-1] = 12;
+ c.cubes[x][top+4][z] = 12;
+ }
+ }
+ }
+ }
+ }
+
+ public static void generate(Chunk c) {
+ generateLandscape(c);
+ generateNature(c);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Input/CommandInput.java b/src/main/java/net/tylermurphy/Minecraft/Input/CommandInput.java new file mode 100755 index 0000000..85540ab --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Input/CommandInput.java @@ -0,0 +1,57 @@ +package net.tylermurphy.Minecraft.Input;
+
+import org.lwjgl.glfw.GLFW;
+
+import net.tylermurphy.Minecraft.Command.CommandHandler;
+import net.tylermurphy.Minecraft.Scene.World;
+
+import static net.tylermurphy.Minecraft.UI.UIMaster.*;
+
+public class CommandInput extends IInput {
+
+ public void keyPressed(int keyCode) {
+ switch(keyCode) {
+ case GLFW.GLFW_KEY_ESCAPE:
+ Input.setEnabled("CommandInput", false);
+ Input.setEnabled("GameInput", true);
+ bindUI(3);
+ setEnabled(false);
+ getText("commandBar").setText("");
+ World.player.isPaused = false;
+ break;
+ case GLFW.GLFW_KEY_BACKSPACE:
+ bindUI(3);
+ String currentText = getText("commandBar").getTextString();
+ if(currentText.length() > 0)
+ getText("commandBar").setText(currentText.substring(0,currentText.length()-1));
+ break;
+ case GLFW.GLFW_KEY_ENTER:
+ bindUI(3);
+ setEnabled(false);
+
+ String command = getText("commandBar").getTextString();
+ CommandHandler.handleCommand(command);
+
+ Input.setEnabled("CommandInput", false);
+ Input.setEnabled("GameInput", true);
+ getText("commandBar").setText("");
+ World.player.isPaused = false;
+ break;
+ }
+ }
+
+ public void keyRelesed(int keyCode) {}
+
+ public void mousePressed(int mouseButton) {}
+
+ public void mouseRelesed(int mouseButton) {}
+
+ public void charAction(char c) {
+ bindUI(3);
+ String currentText = getText("commandBar").getTextString();
+
+ currentText += c;
+ getText("commandBar").setText(currentText);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Input/CoreInput.java b/src/main/java/net/tylermurphy/Minecraft/Input/CoreInput.java new file mode 100755 index 0000000..2732805 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Input/CoreInput.java @@ -0,0 +1,25 @@ +package net.tylermurphy.Minecraft.Input;
+
+import org.lwjgl.glfw.GLFW;
+
+import net.tylermurphy.Minecraft.Render.Data.Display;
+
+public class CoreInput extends IInput {
+
+ public void keyPressed(int keyCode) {
+ switch(keyCode) {
+ case GLFW.GLFW_KEY_F11:
+ Display.setFullScreen(!Display.fullscreen);
+ break;
+ }
+ }
+
+ public void keyRelesed(int keyCode) {}
+
+ public void mousePressed(int mouseButton) {}
+
+ public void mouseRelesed(int mouseButton) {}
+
+ public void charAction(char c) {}
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Input/GameInput.java b/src/main/java/net/tylermurphy/Minecraft/Input/GameInput.java new file mode 100755 index 0000000..5da40a6 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Input/GameInput.java @@ -0,0 +1,85 @@ +package net.tylermurphy.Minecraft.Input;
+
+import static net.tylermurphy.Minecraft.UI.UIMaster.*;
+
+import net.tylermurphy.Minecraft.Scene.Objects.WorldOrigin;
+import org.lwjgl.glfw.GLFW;
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.Chunk.Cube;
+import net.tylermurphy.Minecraft.Scene.World;
+import net.tylermurphy.Minecraft.Util.Flags;
+import net.tylermurphy.Minecraft.Util.MousePicker;
+
+public class GameInput extends IInput {
+
+ byte blockId = 1;
+
+ public void keyPressed(int keyCode) {
+ switch(keyCode) {
+ case GLFW.GLFW_KEY_ESCAPE:
+ Flags.actionForceClose = true; break;
+ case GLFW.GLFW_KEY_F3:
+ bindUI(1);
+ setEnabled(!isEnabled());
+ break;
+ case GLFW.GLFW_KEY_EQUAL:
+ do {
+ blockId++;
+ if (blockId > (byte) (Cube.blocks.size() - 1)) blockId = 0;
+ } while (!Cube.getBlock(blockId).placeable);
+ bindUI(1);
+ getText("block").setText("Block Selected: minecraft:"+Cube.getBlock(blockId).name);
+ break;
+ case GLFW.GLFW_KEY_MINUS:
+ do {
+ blockId--;
+ if (blockId < 0) blockId = (byte) (Cube.blocks.size() - 1);
+ } while (!Cube.getBlock(blockId).placeable);
+ bindUI(1);
+ getText("block").setText("Block Selected: minecraft:"+Cube.getBlock(blockId).name);
+ break;
+ case GLFW.GLFW_KEY_F2:
+ World.player.isFlying = !World.player.isFlying;
+ break;
+ case GLFW.GLFW_KEY_K:
+ if(World.player.isDead) {
+ World.player.isDead = false;
+ World.player.health = 20;
+ World.world_origin = new WorldOrigin(0,0);
+ World.player.getTransform().setPosition(new Vector3f(0, World.getHighestBlock(0, 0)+1,0));
+ bindUI(0);
+ getText("dead").setEnabled(false);
+ getImage("crosshair").setEnabled(true);
+ }
+ break;
+ case GLFW.GLFW_KEY_SLASH:
+ this.enabled = false;
+ Input.setEnabled("CommandInput", true);
+ bindUI(3);
+ setEnabled(true);
+ World.player.isPaused = true;
+ break;
+ }
+ }
+
+ public void keyRelesed(int keyCode) {}
+
+ public void mousePressed(int mouseButton) {
+ switch(mouseButton) {
+ case GLFW.GLFW_MOUSE_BUTTON_1:
+ if(MousePicker.breakPos!=null)
+ World.setBlock((int)MousePicker.breakPos.x,(int)MousePicker.breakPos.y,(int)MousePicker.breakPos.z, Cube.AIR);
+ break;
+ case GLFW.GLFW_MOUSE_BUTTON_2:
+ if(MousePicker.placePos!=null && !World.player.collides(MousePicker.placePos.x,MousePicker.placePos.y,MousePicker.placePos.z))
+ World.setBlock((int)MousePicker.placePos.x,(int)MousePicker.placePos.y,(int)MousePicker.placePos.z, blockId);
+ break;
+ }
+ }
+
+ public void mouseRelesed(int mouseButton) {}
+
+ public void charAction(char c) {}
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Input/IInput.java b/src/main/java/net/tylermurphy/Minecraft/Input/IInput.java new file mode 100755 index 0000000..0eb48e7 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Input/IInput.java @@ -0,0 +1,12 @@ +package net.tylermurphy.Minecraft.Input;
+
+public abstract class IInput {
+
+ public boolean enabled = true;
+
+ public abstract void keyPressed(int keyCode);
+ public abstract void keyRelesed(int keyCode);
+ public abstract void mousePressed(int mouseButton);
+ public abstract void mouseRelesed(int mouseButton);
+ public abstract void charAction(char c);
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Input/Input.java b/src/main/java/net/tylermurphy/Minecraft/Input/Input.java new file mode 100755 index 0000000..86deb12 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Input/Input.java @@ -0,0 +1,154 @@ +package net.tylermurphy.Minecraft.Input;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lwjgl.glfw.GLFW;
+import org.lwjgl.glfw.GLFWCursorPosCallback;
+import org.lwjgl.glfw.GLFWKeyCallback;
+import org.lwjgl.glfw.GLFWMouseButtonCallback;
+
+import org.lwjgl.glfw.GLFWCharCallback;
+
+public class Input {
+
+ private static List<IInput> inputs = new ArrayList<IInput>();
+
+ private static boolean[] keys = new boolean[GLFW.GLFW_KEY_LAST];
+ private static boolean[] mouseButtons = new boolean[GLFW.GLFW_MOUSE_BUTTON_LAST];
+ private static double mouseX, mouseY;
+ private static double mouseX_last, mouseY_last;
+
+ private static GLFWKeyCallback keyboard;
+ private static GLFWCursorPosCallback mouseMove;
+ private static GLFWMouseButtonCallback mouseButton;
+ private static GLFWCharCallback character;
+
+ public static void init() {
+
+ keyboard = new GLFWKeyCallback() {
+ public void invoke(long window, int key, int scancode, int action, int mods) {
+ switch(action) {
+ case GLFW.GLFW_PRESS:
+ keys[key] = true;
+ for(IInput input : inputs) {
+ if(!input.enabled) continue;
+ input.keyPressed(key);
+ }
+ break;
+ case GLFW.GLFW_RELEASE:
+ keys[key] = false;
+ for(IInput input : inputs) {
+ if(!input.enabled) continue;
+ input.keyRelesed(key);
+ }
+ break;
+ }
+
+ }
+ };
+
+ mouseMove = new GLFWCursorPosCallback() {
+ public void invoke(long window, double xPos, double yPos) {
+ mouseX = xPos; mouseY = yPos;
+ }
+ };
+
+ mouseButton = new GLFWMouseButtonCallback() {
+ public void invoke(long window, int button, int action, int mods) {
+ switch(action) {
+ case GLFW.GLFW_PRESS:
+ mouseButtons[button] = true;
+ for(IInput input : inputs) {
+ if(!input.enabled) continue;
+ input.mousePressed(button);
+ }
+ break;
+ case GLFW.GLFW_RELEASE:
+ mouseButtons[button] = false;
+ for(IInput input : inputs) {
+ if(!input.enabled) continue;
+ input.mouseRelesed(button);
+ }
+ break;
+ }
+ }
+ };
+
+ character = new GLFWCharCallback() {
+ public void invoke(long window, int key) {
+ for(IInput input : inputs) {
+ if(!input.enabled) continue;
+ input.charAction((char)key);
+ }
+ }
+ };
+ }
+
+ public static void addInput(IInput input) {
+ inputs.add(input);
+ }
+
+ public static void destroy() {
+ keyboard.free();
+ mouseMove.free();
+ mouseButton.free();
+ character.free();
+ }
+
+ public static boolean isKeyDown(int key) {
+ return keys[key];
+ }
+
+ public static boolean isButtonDown(int button) {
+ return mouseButtons[button];
+ }
+
+ public static double getMouseX() {
+ return mouseX;
+ }
+
+ public static double getMouseY() {
+ return mouseY;
+ }
+
+ public static double getMouseDX() {
+ double d = -(mouseX_last - mouseX);
+ mouseX_last = mouseX;
+ return d;
+ }
+
+ public static double getMouseDY() {
+ double d = mouseY_last - mouseY;
+ mouseY_last = mouseY;
+ return d;
+ }
+
+ public static GLFWKeyCallback getKeyboardCallback() {
+ return keyboard;
+ }
+
+ public static GLFWCursorPosCallback getMouseMoveCallback() {
+ return mouseMove;
+ }
+
+ public static GLFWMouseButtonCallback getMouseButtonCallback() {
+ return mouseButton;
+ }
+
+ public static GLFWCharCallback getCharCallback() {
+ return character;
+ }
+
+ public static void setEnabled(String className, boolean enabled) {
+ for(IInput input : inputs) {
+ String fullName = input.getClass().getTypeName();
+ fullName = fullName.substring(fullName.lastIndexOf(".")+1,fullName.length());
+ if(className.equals(fullName)) {
+ input.enabled = enabled;
+ }
+ }
+ }
+
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Main.java b/src/main/java/net/tylermurphy/Minecraft/Main.java new file mode 100755 index 0000000..ea10bd9 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Main.java @@ -0,0 +1,95 @@ +package net.tylermurphy.Minecraft;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.tylermurphy.Minecraft.Audio.SoundManager;
+import net.tylermurphy.Minecraft.Chunk.Cube;
+import net.tylermurphy.Minecraft.Command.CommandHandler;
+import net.tylermurphy.Minecraft.Input.*;
+import net.tylermurphy.Minecraft.Render.MainRenderer;
+import net.tylermurphy.Minecraft.Render.Data.Texture;
+import net.tylermurphy.Minecraft.Scripts.*;
+import net.tylermurphy.Minecraft.Render.Data.Display;
+import net.tylermurphy.Minecraft.Util.Flags;
+
+public class Main {
+
+ private static long currentTime = System.nanoTime();
+ private static long nanoSeconendsPassed;
+ private static int tps,ticks;
+
+ public static String currentWorld = "test";
+
+ private static final List<Script> scripts = new ArrayList<>();
+
+ public static void main(String[] args) {
+
+ Display.create(1280, 720, "Minecraft", Texture.loadRawTextureData("gui/icon"));
+
+ Input.addInput(new GameInput());
+ Input.addInput(new CoreInput());
+ Input.addInput(new CommandInput());
+ Input.setEnabled("CommandInput", false);
+
+ SoundManager.init();
+
+ scripts.add(new GameScript());
+ scripts.add(new PlayerScript());
+ scripts.add(new UIScript());
+
+ CommandHandler.registerCommands();
+
+ for(Script script : scripts) script.Init();
+
+ MainRenderer renderer = new MainRenderer();
+
+ Cube.init();
+
+ while(Display.closed() && !Flags.actionForceClose) {
+
+ long lastTime = currentTime;
+ currentTime = System.nanoTime();
+ nanoSeconendsPassed += currentTime - lastTime;
+
+ Display.update();
+
+ for(Script script : scripts) script.Update();
+
+ if(nanoSeconendsPassed >= 50000000) {
+ tps = Math.round((50000000f/nanoSeconendsPassed)*20);
+ for(Script script : scripts) script.Tick();
+ nanoSeconendsPassed -= 50000000;
+ if(nanoSeconendsPassed >= 5000000000L)
+ nanoSeconendsPassed = 0;
+ ticks++;
+ }
+ renderer.update();
+ Display.swapBuffers();
+
+ }
+
+ for(Script script : scripts) script.End();
+
+ renderer.update();
+ Display.swapBuffers();
+ renderer.close();
+
+ for(Script script : scripts) script.Stop();
+
+ SoundManager.cleanUp();
+ Display.close();
+
+ System.exit(0);
+
+ }
+
+ public static int getTPS() {
+ return tps;
+ }
+
+ public static int getTicks() {
+ return ticks;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/ChunkRenderer.java b/src/main/java/net/tylermurphy/Minecraft/Render/ChunkRenderer.java new file mode 100755 index 0000000..29e079b --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/ChunkRenderer.java @@ -0,0 +1,99 @@ +package net.tylermurphy.Minecraft.Render;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+import org.joml.Matrix4f;
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.Chunk.Chunk;
+import net.tylermurphy.Minecraft.Render.Shaders.ChunkShader;
+import net.tylermurphy.Minecraft.Render.Util.FrustumCuller;
+import net.tylermurphy.Minecraft.Scene.World;
+import net.tylermurphy.Minecraft.Scene.Objects.Renderable;
+import net.tylermurphy.Minecraft.Util.Constants;
+import net.tylermurphy.Minecraft.Util.Maths;
+
+public class ChunkRenderer {
+
+ private final ChunkShader shader;
+
+ public ChunkRenderer(Matrix4f projectionMatrix) {
+ this.shader = new ChunkShader();
+ shader.start();
+ shader.loadProjectionMatrix(projectionMatrix);
+ shader.connectTextureUnits();
+ shader.stop();
+ }
+
+ public void render(Matrix4f projectionMatrix) {
+ FrustumCuller frustum = FrustumCuller.getFrustum(Maths.createViewMatrix(World.camera),projectionMatrix);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glCullFace(GL11.GL_BACK);
+ GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+ GL11.glClearColor(Constants.RED, Constants.GREEN, Constants.BLUE, 1);
+ shader.start();
+ if(World.player.isDead)
+ shader.loadTint(new Vector3f(100,0,0));
+ else
+ shader.loadTint(new Vector3f(0,0,0));
+ shader.loadViewMatrix(World.camera);
+ shader.loadPlayerPosition(World.player.getTransform().getPosition());
+ shader.loadRenderDistance(World.renderDistance);
+ shader.loadSkyColor(new Vector3f(Constants.RED,Constants.GREEN,Constants.BLUE));
+ attemptFrameChunkMeshLoad();
+ boolean loadedMesh = false;
+ for (Chunk chunk : World.getChunks()) {
+ if(chunk==null) continue;
+ if(!frustum.cubeInFrustum( chunk.gridX*16 - World.world_origin.x(), 0, chunk.gridZ*16 - World.world_origin.z(), chunk.gridX*16 + 16 - World.world_origin.x() , 256, chunk.gridZ*16 + 16 - World.world_origin.z() )) {
+ continue;
+ }
+ if(!loadedMesh) loadedMesh = chunk.loadMesh();
+ if(chunk.renderable() != null)
+ renderChunkMesh(chunk.renderable());
+ if(chunk.transparentRenderable() != null)
+ renderChunkMesh(chunk.transparentRenderable());
+ GL20.glDisableVertexAttribArray(0);
+ GL20.glDisableVertexAttribArray(1);
+ GL20.glDisableVertexAttribArray(2);
+ GL20.glDisableVertexAttribArray(3);
+ GL30.glBindVertexArray(0);
+ }
+ GL11.glDisable(GL11.GL_CULL_FACE);
+ shader.stop();
+ }
+
+ private void attemptFrameChunkMeshLoad(){
+
+ }
+
+ private void renderChunkMesh(Renderable renderable) {
+ GL30.glBindVertexArray(renderable.getMesh().getID());
+ GL20.glEnableVertexAttribArray(0);
+ GL20.glEnableVertexAttribArray(1);
+ GL20.glEnableVertexAttribArray(2);
+ GL20.glEnableVertexAttribArray(3);
+ GL13.glActiveTexture(GL13.GL_TEXTURE0);
+ GL11.glBindTexture(GL30.GL_TEXTURE_2D_ARRAY, renderable.getTexture());
+ prepareInstance(renderable);
+ GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, renderable.getMesh().getVertexCount());
+ }
+
+ private void prepareInstance(Renderable renderable) {
+ Matrix4f transformationMatrix = Maths.createTransformationMatrix(
+ new Vector3f(
+ renderable.getTransform().getPosition().x - World.world_origin.x(),
+ renderable.getTransform().getPosition().y,
+ renderable.getTransform().getPosition().z - World.world_origin.z()
+ ),
+ renderable.getTransform().getRotation().x,renderable.getTransform().getRotation().y, renderable.getTransform().getRotation().z, renderable.getTransform().getScale());
+ shader.loadTransformationMatrix(transformationMatrix);
+ }
+
+ public void cleanUp() {
+ shader.cleanUp();
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Data/Display.java b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Display.java new file mode 100755 index 0000000..f866e97 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Display.java @@ -0,0 +1,175 @@ +package net.tylermurphy.Minecraft.Render.Data;
+
+import java.nio.DoubleBuffer;
+import java.nio.IntBuffer;
+
+import org.joml.Vector2f;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.glfw.GLFW;
+import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
+import org.lwjgl.glfw.GLFWImage;
+import org.lwjgl.glfw.GLFWVidMode;
+import org.lwjgl.opengl.GL;
+import org.lwjgl.opengl.GL11;
+
+import net.tylermurphy.Minecraft.Input.Input;
+
+public class Display {
+
+ private static long monitor;
+ private static long window;
+
+ private static int width,height;
+
+ private static double previousTime = GLFW.glfwGetTime();
+ private static double passedTime = 0;
+
+ private static boolean contextReady = false;
+
+ public static boolean wasResized = false;
+
+ public static boolean fullscreen = false;
+ private static int backup_xpos,backup_ypos,backup_xsize,backup_ysize;
+
+ public static void create(int width, int height, String title, Texture icon) {
+
+ Display.width = width;
+ Display.height = height;
+
+ if(!GLFW.glfwInit()) {
+ System.err.println("Error: Coudnt init GLFW");
+ System.exit(-1);
+ }
+
+ Input.init();
+
+ GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
+
+ monitor = GLFW.glfwGetPrimaryMonitor();
+ window = GLFW.glfwCreateWindow(width, height, title, 0, 0);
+
+ GLFW.glfwSetKeyCallback(window, Input.getKeyboardCallback());
+ GLFW.glfwSetCursorPosCallback(window, Input.getMouseMoveCallback());
+ GLFW.glfwSetMouseButtonCallback(window, Input.getMouseButtonCallback());
+ GLFW.glfwSetCharCallback(window, Input.getCharCallback());
+
+ GLFWFramebufferSizeCallback framebufferCallback = new GLFWFramebufferSizeCallback() {
+ public void invoke(long window, int width, int height) {
+ if(contextReady) {
+ Display.width = width;
+ Display.height = height;
+ Display.wasResized = true;
+ GL11.glViewport(0, 0, width, height);
+ }
+ }
+ };
+
+ GLFW.glfwSetFramebufferSizeCallback(window, framebufferCallback);
+
+ if(window==0) {
+ System.err.println("Error: Coudnt create window");
+ System.exit(-1);
+ }
+
+ if(icon != null) {
+ GLFWImage image = GLFWImage.malloc(); GLFWImage.Buffer imagebf = GLFWImage.malloc(1);
+ image.set(icon.getWidth(), icon.getHeight(), icon.getImage());
+ imagebf.put(0, image);
+ GLFW.glfwSetWindowIcon(window, imagebf);
+ }
+
+ GLFWVidMode videoMode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
+ assert videoMode != null;
+ GLFW.glfwSetWindowPos(window, (videoMode.width() - width) / 2, (videoMode.height() - height) / 2);
+ GLFW.glfwMakeContextCurrent(window);
+ GLFW.glfwSwapInterval(0);
+ GLFW.glfwShowWindow(window);
+
+ GL.createCapabilities();
+ grabCursor();
+
+ contextReady = true;
+
+ }
+
+ public static boolean closed() {
+ return !GLFW.glfwWindowShouldClose(window);
+ }
+
+ public static void update() {
+ double currentTime = GLFW.glfwGetTime();
+ passedTime = currentTime - previousTime;
+ previousTime = currentTime;
+ GLFW.glfwPollEvents();
+ }
+
+ public static void swapBuffers() {
+ GLFW.glfwSwapBuffers(window);
+ }
+
+ public static void close() {
+ Input.destroy();
+ GLFW.glfwDestroyWindow(window);
+ GLFW.glfwTerminate();
+ GL.destroy();
+ }
+
+ public static int getWidth() {
+ return width;
+ }
+
+ public static int getHeight() {
+ return height;
+ }
+
+ public static float getFrameTimeSeconds() {
+ return (float) passedTime;
+ }
+
+ public static void grabCursor() {
+ GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
+ }
+
+ public static void releaseCursor() {
+ GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL);
+ }
+
+ public static Vector2f getCursorPos() {
+ DoubleBuffer xpos = BufferUtils.createDoubleBuffer(1);
+ DoubleBuffer ypos = BufferUtils.createDoubleBuffer(1);
+ GLFW.glfwGetCursorPos(window, xpos, ypos);
+ return new Vector2f((float)xpos.get(),(float)ypos.get());
+ }
+
+ public static void setFullScreen(boolean fullscreen) {
+
+ if(Display.fullscreen == fullscreen)
+ return;
+
+ Display.fullscreen = fullscreen;
+
+ if(fullscreen) {
+
+ IntBuffer xpos = BufferUtils.createIntBuffer(1);
+ IntBuffer ypos = BufferUtils.createIntBuffer(1);
+ GLFW.glfwGetWindowPos(window, xpos, ypos);
+
+ IntBuffer xsize = BufferUtils.createIntBuffer(1);
+ IntBuffer ysize = BufferUtils.createIntBuffer(1);
+ GLFW.glfwGetWindowSize(window, xsize, ysize);
+
+ backup_xpos = xpos.get();
+ backup_ypos = ypos.get();
+ backup_xsize = xsize.get();
+ backup_ysize = ysize.get();
+
+ GLFWVidMode mode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
+
+ assert mode != null;
+ GLFW.glfwSetWindowMonitor(window, monitor, backup_xpos, backup_ypos, mode.width(), mode.height(), 0);
+ } else {
+ GLFW.glfwSetWindowMonitor(window, 0, backup_xpos, backup_ypos, backup_xsize, backup_ysize, 0);
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Data/Mesh.java b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Mesh.java new file mode 100755 index 0000000..093a58e --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Mesh.java @@ -0,0 +1,82 @@ +package net.tylermurphy.Minecraft.Render.Data;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL15;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+
+import java.io.Serializable;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Mesh implements Serializable {
+
+ private static final long serialVersionUID = -8137846451745511907L;
+
+ public static List<Integer> vaos = new ArrayList<>();
+ public static List<Integer> vbos = new ArrayList<>();
+
+ private final int id;
+ private final int vertexCount;
+ private int counter = 0;
+
+ public Mesh(int vertexCount){
+ this.id = GL30.glGenVertexArrays();
+ vaos.add(id);
+ this.vertexCount = vertexCount;
+ GL30.glBindVertexArray(id);
+ }
+
+ public Mesh store(float[] data, int coordinateSize){
+ int id = GL15.glGenBuffers();
+ vbos.add(id);
+ GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, id);
+ FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
+ buffer.put(data);
+ buffer.flip();
+ GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
+ GL20.glVertexAttribPointer(counter,coordinateSize, GL11.GL_FLOAT,false,0,0);
+ GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
+ counter++;
+ return this;
+ }
+
+ public Mesh finish(){
+ GL30.glBindVertexArray(0);
+ return this;
+ }
+
+ public void delete(){
+ IntBuffer amount = BufferUtils.createIntBuffer(1);
+ GL20.glGetIntegerv(GL20.GL_MAX_VERTEX_ATTRIBS, amount);
+ GL30.glBindVertexArray(id);
+ for (int i=0; i < amount.get(0); i++) {
+ IntBuffer vbo = BufferUtils.createIntBuffer(1);
+ GL20.glGetVertexAttribiv(i, GL20.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, vbo);
+ if(vbo.get(0) > 0) {
+ GL15.glDeleteBuffers(vbo.get(0));
+ }
+ }
+ GL30.glDeleteVertexArrays(id);
+ }
+
+ public int getID() {
+ return id;
+ }
+ public int getVertexCount() {
+ return vertexCount;
+ }
+
+ public static void cleanUp() {
+ for(int vao:vaos){
+ GL30.glDeleteVertexArrays(vao);
+ }
+ for(int vbo:vbos){
+ GL30.glDeleteBuffers(vbo);
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Data/Texture.java b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Texture.java new file mode 100755 index 0000000..edfce82 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Texture.java @@ -0,0 +1,113 @@ +package net.tylermurphy.Minecraft.Render.Data;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.lwjgl.opengl.GL30.*;
+
+import org.lwjgl.opengl.EXTTextureFilterAnisotropic;
+import org.lwjgl.opengl.GL;
+import org.lwjgl.stb.STBImage;
+import org.lwjgl.system.MemoryStack;
+
+import net.tylermurphy.Minecraft.Util.Constants;
+
+public class Texture {
+
+ public ByteBuffer getImage() {
+ return image;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ private ByteBuffer image;
+ private int width, height;
+
+ private static List<Integer> ids = new ArrayList<Integer>();
+
+ Texture(int width, int heigh, ByteBuffer image) {
+ this.image = image;
+ this.height = heigh;
+ this.width = width;
+ }
+
+ public static Texture loadRawTextureData(String fileName) {
+ ByteBuffer image;
+ int width, height;
+ try (MemoryStack stack = MemoryStack.stackPush()) {
+ IntBuffer comp = stack.mallocInt(1);
+ IntBuffer w = stack.mallocInt(1);
+ IntBuffer h = stack.mallocInt(1);
+ image = STBImage.stbi_load(Constants.PNG_LOCATION + fileName + ".png", w, h, comp, 4);
+ if (image == null) {
+ System.err.println("Couldn't load " + Constants.PNG_LOCATION + fileName + ".png");
+ }
+ width = w.get();
+ height = h.get();
+ return new Texture(width, height, image);
+ }
+ }
+
+ private static int loadImage(String fileName) {
+ int id = glGenTextures();
+ Texture image = loadRawTextureData(fileName);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, id);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.getImage());
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -1);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ ids.add(id);
+ return id;
+ }
+
+ public static int loadTexture(String fileName) {
+ return loadImage(fileName);
+ }
+
+ public static int loadFontAtlas(String fileName) {
+ return loadImage(fileName);
+ }
+
+ public static int loadTexture2DArray(HashMap<Integer, Texture> textures){
+ int id = glGenTextures();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, id);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ if (GL.getCapabilities().GL_EXT_texture_filter_anisotropic) {
+ float maxAnisotropy = glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
+ glTexParameterf(GL_TEXTURE_2D_ARRAY, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
+ }
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, textures.get(0).width, textures.get(0).height, textures.values().size(), 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer) null);
+ for(Map.Entry<Integer, Texture> entry : textures.entrySet()){
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, entry.getKey(), entry.getValue().width, entry.getValue().height, 1, GL_RGBA, GL_UNSIGNED_BYTE, entry.getValue().getImage());
+ }
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
+ ids.add(id);
+ return id;
+ }
+
+ public static void cleanUp(){
+ for(int id:ids){
+ glDeleteTextures(id);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, id);
+ }
+ }
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/FontRenderer.java b/src/main/java/net/tylermurphy/Minecraft/Render/FontRenderer.java new file mode 100755 index 0000000..ed17824 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/FontRenderer.java @@ -0,0 +1,101 @@ +package net.tylermurphy.Minecraft.Render;
+
+import java.util.List;
+
+import java.util.Map;
+
+import net.tylermurphy.Minecraft.Render.Data.Mesh;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+import org.joml.Matrix4f;
+import org.joml.Vector2f;
+import org.joml.Vector4f;
+
+import net.tylermurphy.Minecraft.Render.Shaders.FontShader;
+import net.tylermurphy.Minecraft.Render.Shaders.QuadShader;
+import net.tylermurphy.Minecraft.UI.UIFont;
+import net.tylermurphy.Minecraft.UI.UIText;
+import net.tylermurphy.Minecraft.Util.Maths;
+
+public class FontRenderer {
+
+ private final Mesh quad;
+ private final FontShader fontShader;
+ private final QuadShader quadShader;
+
+ public FontRenderer() {
+ float[] positions = {-1, 1, -1, -1, 1, 1, 1, -1};
+ quad = new Mesh(positions.length/2).store(positions, 2).finish();
+ fontShader = new FontShader();
+ quadShader = new QuadShader();
+ }
+
+ public void render(Map<UIFont, List<UIText>> texts){
+ for(UIFont font : texts.keySet()){
+ for(UIText text : texts.get(font)){
+ renderQuad(text);
+ }
+ }
+ prepare();
+ for(UIFont font : texts.keySet()){
+ GL13.glActiveTexture(GL13.GL_TEXTURE0);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, font.getTextureAtlas());
+ for(UIText text : texts.get(font)){
+ renderText(text);
+ }
+ }
+ endRendering();
+ }
+
+ public void cleanUp(){
+ fontShader.cleanUp();
+ quadShader.cleanUp();
+ }
+
+ private void prepare(){
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+ fontShader.start();
+ }
+
+ private void renderText(UIText text){
+ GL30.glBindVertexArray(text.getMesh());
+ GL20.glEnableVertexAttribArray(0);
+ GL20.glEnableVertexAttribArray(1);
+ fontShader.loadColor(text.getColour());
+ fontShader.loadTranslation(text.getConvertedPosition());
+ GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, text.getVertexCount());
+ GL20.glDisableVertexAttribArray(0);
+ GL20.glDisableVertexAttribArray(1);
+ GL30.glBindVertexArray(0);
+ }
+
+ private void renderQuad(UIText text) {
+ quadShader.start();
+ GL30.glBindVertexArray(quad.getID());
+ GL20.glEnableVertexAttribArray(0);
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+ Matrix4f matrix = Maths.createTransformationMatrix(new Vector2f(text.getStretchBackdrop() ? -1 : text.getConvertedPosition().x*2-1,(1-text.getConvertedPosition().y-.0125f*text.getFontSize()-.0025f)*2-1), new Vector2f(text.getStretchBackdrop() ? 2 : (float) text.getMaxX()*2,.025f*text.getFontSize()));
+ quadShader.loadTransformation(matrix);
+ quadShader.loadColor(new Vector4f(150/255f,150/255f,150/255f,.5f));
+ GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, quad.getVertexCount());
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ GL20.glDisableVertexAttribArray(0);
+ GL30.glBindVertexArray(0);
+ quadShader.stop();
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ }
+
+ private void endRendering(){
+ fontShader.stop();
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/GuiRenderer.java b/src/main/java/net/tylermurphy/Minecraft/Render/GuiRenderer.java new file mode 100755 index 0000000..b7ae6f2 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/GuiRenderer.java @@ -0,0 +1,57 @@ +package net.tylermurphy.Minecraft.Render;
+
+import java.util.List;
+
+
+import net.tylermurphy.Minecraft.Render.Data.Mesh;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+import org.joml.Matrix4f;
+import org.joml.Vector2f;
+
+import net.tylermurphy.Minecraft.Render.Shaders.GuiShader;
+import net.tylermurphy.Minecraft.UI.UIComponent;
+import net.tylermurphy.Minecraft.UI.UIImage;
+import net.tylermurphy.Minecraft.Util.Maths;
+
+
+public class GuiRenderer {
+
+ private final Mesh quad;
+ private GuiShader shader;
+
+ public GuiRenderer(){
+ float[] positions = {-1, 1, -1, -1, 1, 1, 1, -1};
+ quad = new Mesh(positions.length/2).store(positions, 2).finish();
+ shader = new GuiShader();
+ }
+
+ public void render(List<UIComponent> components){
+ shader.start();
+ GL30.glBindVertexArray(quad.getID());
+ GL20.glEnableVertexAttribArray(0);
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+ for(UIComponent cp : components) {
+ if(!(cp instanceof UIImage)) continue;
+ UIImage gui = (UIImage)cp;
+ GL13.glActiveTexture(GL13.GL_TEXTURE0);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, gui.getTexture());
+ Matrix4f matrix = Maths.createTransformationMatrix(new Vector2f(gui.getConvertedPosition().x*2-1,(1-gui.getConvertedPosition().y)*2-1), gui.getConvertedSize());
+ shader.loadTransformation(matrix);
+ GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, quad.getVertexCount());
+ }
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ GL11.glDisable(GL11.GL_BLEND);
+ GL20.glDisableVertexAttribArray(0);
+ GL30.glBindVertexArray(0);
+ shader.stop();
+ }
+
+ public void cleanUp(){
+ shader.cleanUp();
+ }
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/MainRenderer.java b/src/main/java/net/tylermurphy/Minecraft/Render/MainRenderer.java new file mode 100755 index 0000000..28ec88f --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/MainRenderer.java @@ -0,0 +1,73 @@ +package net.tylermurphy.Minecraft.Render;
+
+import net.tylermurphy.Minecraft.Render.Data.Mesh;
+import org.joml.Matrix4f;
+
+import net.tylermurphy.Minecraft.Audio.SoundManager;
+import net.tylermurphy.Minecraft.Render.Data.Texture;
+import net.tylermurphy.Minecraft.Scene.World;
+import net.tylermurphy.Minecraft.UI.UIMaster;
+import net.tylermurphy.Minecraft.Util.Constants;
+import net.tylermurphy.Minecraft.Render.Data.Display;
+import net.tylermurphy.Minecraft.Util.MousePicker;
+import org.joml.Vector3f;
+
+public class MainRenderer {
+
+ private final GuiRenderer guiRenderer;
+ private final FontRenderer fontRenderer;
+ private final ChunkRenderer chunkRenderer;
+
+ private Matrix4f projectionMatrix;
+
+ public MainRenderer() {
+ guiRenderer = new GuiRenderer();
+ fontRenderer = new FontRenderer();
+ createProjectionMatrix();
+ MousePicker.init(projectionMatrix);
+ chunkRenderer = new ChunkRenderer(projectionMatrix);
+ }
+
+ public void update() {
+ if(Display.wasResized) {
+ Display.wasResized = false;
+ createProjectionMatrix();
+ }
+ chunkRenderer.render(projectionMatrix);
+ if(!World.player.isDead) {
+ World.player.move();
+ World.player.getTransform().setRotation(new Vector3f(
+ World.camera.getPitch(),
+ -World.camera.getYaw(),
+ World.camera.getRoll()
+ ));
+ World.camera.move();
+ }
+ UIMaster.renderUI(guiRenderer, fontRenderer);
+ MousePicker.update();
+ SoundManager.setListenerData(World.player.getTransform().getPosition().x, World.player.getTransform().getPosition().y , World.player.getTransform().getPosition().z);
+ }
+
+ public void close() {
+ guiRenderer.cleanUp();
+ chunkRenderer.cleanUp();
+ Mesh.cleanUp();
+ Texture.cleanUp();
+ }
+
+ private void createProjectionMatrix(){
+ float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
+ float y_scale = (float) ((1f / Math.tan(Math.toRadians(Constants.FOV / 2f))));
+ float x_scale = y_scale / aspectRatio;
+ float frustum_length = Constants.FAR_DISTANCE - Constants.NEAR_DISTANCE;
+
+ projectionMatrix = new Matrix4f()
+ .m00(x_scale)
+ .m11(y_scale)
+ .m22( -((Constants.FAR_DISTANCE + Constants.NEAR_DISTANCE) / frustum_length) )
+ .m23(-1)
+ .m32( -((2 * Constants.NEAR_DISTANCE * Constants.FAR_DISTANCE) / frustum_length) )
+ .m33(0);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/ChunkShader.java b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/ChunkShader.java new file mode 100755 index 0000000..f998e7a --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/ChunkShader.java @@ -0,0 +1,81 @@ +package net.tylermurphy.Minecraft.Render.Shaders;
+
+import org.joml.Matrix4f;
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.Render.Util.ShaderProgram;
+import net.tylermurphy.Minecraft.Scene.Camera;
+import net.tylermurphy.Minecraft.Util.Maths;
+
+public class ChunkShader extends ShaderProgram{
+
+ private static final String VERTEX_FILE = "Chunk_VS.glsl";
+ private static final String FRAGMENT_FILE = "Chunk_FS.glsl";
+
+ private int location_transformationMatrix;
+ private int location_projectionMatrix;
+ private int location_viewMatrix;
+ private int location_modelTexture;
+ private int location_tint;
+ private int location_playerPosition;
+ private int location_renderDistance;
+ private int location_skyColor;
+
+ public ChunkShader() {
+ super(VERTEX_FILE, FRAGMENT_FILE);
+ }
+
+ @Override
+ public void bindAttributes() {
+ super.bindAttribute(0, "position");
+ super.bindAttribute(1, "textureCoordinates");
+ super.bindAttribute(2, "baseLightingValue");
+ super.bindAttribute(3, "layer");
+ }
+
+ @Override
+ public void getAllUniformLocations() {
+ location_transformationMatrix = super.getUniformLocation("transformationMatrix");
+ location_projectionMatrix = super.getUniformLocation("projectionMatrix");
+ location_viewMatrix = super.getUniformLocation("viewMatrix");
+ location_modelTexture = super.getUniformLocation("modelTexture");
+ location_tint = super.getUniformLocation("tint");
+ location_playerPosition = super.getUniformLocation("playerPosition");
+ location_renderDistance = super.getUniformLocation("renderDistance");
+ location_skyColor = super.getUniformLocation("skyColor");
+ }
+
+ public void connectTextureUnits() {
+ super.loadInt(location_modelTexture, 0);
+ }
+
+ public void loadTint(Vector3f tint) {
+ super.loadVector(location_tint, tint);
+ }
+
+ public void loadTransformationMatrix(Matrix4f matrix){
+ super.loadMatrix(location_transformationMatrix, matrix);
+ }
+
+ public void loadViewMatrix(Camera camera){
+ Matrix4f viewMatrix = Maths.createViewMatrix(camera);
+ super.loadMatrix(location_viewMatrix, viewMatrix);
+ }
+
+ public void loadProjectionMatrix(Matrix4f projection){
+ super.loadMatrix(location_projectionMatrix, projection);
+ }
+
+ public void loadPlayerPosition(Vector3f position) {
+ super.loadVector(location_playerPosition, position);
+ }
+
+ public void loadRenderDistance(int distance) {
+ super.loadInt(location_renderDistance, distance);
+ }
+
+ public void loadSkyColor(Vector3f color) {
+ super.loadVector(location_skyColor, color);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/FontShader.java b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/FontShader.java new file mode 100755 index 0000000..0615b13 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/FontShader.java @@ -0,0 +1,40 @@ +package net.tylermurphy.Minecraft.Render.Shaders;
+
+import org.joml.Vector2f;
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.Render.Util.ShaderProgram;
+
+public class FontShader extends ShaderProgram{
+
+ private static final String VERTEX_FILE ="Font_VS.glsl";
+ private static final String FRAGMENT_FILE = "Font_FS.glsl";
+
+ private int location_color;
+ private int location_translation;
+
+ public FontShader() {
+ super(VERTEX_FILE, FRAGMENT_FILE);
+ }
+
+ @Override
+ protected void getAllUniformLocations() {
+ location_color = super.getUniformLocation("color");
+ location_translation = super.getUniformLocation("translation");
+ }
+
+ @Override
+ protected void bindAttributes() {
+ super.bindAttribute(0, "position");
+ super.bindAttribute(1, "textureCoords");
+ }
+
+ public void loadColor(Vector3f colour){
+ super.loadVector(location_color, colour);
+ }
+
+ public void loadTranslation(Vector2f vector2f){
+ super.load2DVector(location_translation, vector2f);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/GuiShader.java b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/GuiShader.java new file mode 100755 index 0000000..cf10ff3 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/GuiShader.java @@ -0,0 +1,33 @@ +package net.tylermurphy.Minecraft.Render.Shaders;
+
+import org.joml.Matrix4f;
+
+import net.tylermurphy.Minecraft.Render.Util.ShaderProgram;
+
+public class GuiShader extends ShaderProgram{
+
+ private static final String VERTEX_FILE = "Gui_VS.glsl";
+ private static final String FRAGMENT_FILE = "Gui_FS.glsl";
+
+ private int location_transformationMatrix;
+
+ public GuiShader() {
+ super(VERTEX_FILE, FRAGMENT_FILE);
+ }
+
+ public void loadTransformation(Matrix4f matrix){
+ super.loadMatrix(location_transformationMatrix, matrix);
+ }
+
+ protected void getAllUniformLocations() {
+ location_transformationMatrix = super.getUniformLocation("transformationMatrix");
+ }
+
+ protected void bindAttributes() {
+ super.bindAttribute(0, "position");
+ }
+
+
+
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/QuadShader.java b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/QuadShader.java new file mode 100755 index 0000000..0424cc3 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/QuadShader.java @@ -0,0 +1,37 @@ +package net.tylermurphy.Minecraft.Render.Shaders;
+
+import org.joml.Matrix4f;
+import org.joml.Vector4f;
+
+import net.tylermurphy.Minecraft.Render.Util.ShaderProgram;
+
+public class QuadShader extends ShaderProgram{
+
+ private static final String VERTEX_FILE = "Quad_VS.glsl";
+ private static final String FRAGMENT_FILE = "Quad_FS.glsl";
+
+ private int location_transformationMatrix;
+ private int location_color;
+
+ public QuadShader() {
+ super(VERTEX_FILE, FRAGMENT_FILE);
+ }
+
+ public void loadTransformation(Matrix4f matrix){
+ super.loadMatrix(location_transformationMatrix, matrix);
+ }
+
+ protected void getAllUniformLocations() {
+ location_transformationMatrix = super.getUniformLocation("transformationMatrix");
+ location_color = super.getUniformLocation("color");
+ }
+
+ protected void bindAttributes() {
+ super.bindAttribute(0, "position");
+ }
+
+ public void loadColor(Vector4f color) {
+ super.loadVector(location_color, color);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Util/FrustumCuller.java b/src/main/java/net/tylermurphy/Minecraft/Render/Util/FrustumCuller.java new file mode 100755 index 0000000..41472c4 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Util/FrustumCuller.java @@ -0,0 +1,172 @@ +package net.tylermurphy.Minecraft.Render.Util;
+
+import java.nio.FloatBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.joml.Matrix4f;
+
+import net.tylermurphy.Minecraft.Render.Util.FrustumCuller;
+
+public class FrustumCuller {
+ public float[][] m_Frustum = new float[6][4];
+ public static final int RIGHT = 0;
+ public static final int LEFT = 1;
+ public static final int BOTTOM = 2;
+ public static final int TOP = 3;
+ public static final int BACK = 4;
+ public static final int FRONT = 5;
+ public static final int A = 0;
+ public static final int B = 1;
+ public static final int C = 2;
+ public static final int D = 3;
+ private static FrustumCuller frustum = new FrustumCuller();
+
+ private static FloatBuffer modlBuffer = BufferUtils.createFloatBuffer(16);
+ private static FloatBuffer projBuffer = BufferUtils.createFloatBuffer(16);
+
+ float[] proj = new float[16];
+ float[] modl = new float[16];
+ float[] clip = new float[16];
+
+ public static FrustumCuller getFrustum(Matrix4f viewMatrix, Matrix4f projectionMatrix) {
+ frustum.calculateFrustum(viewMatrix, projectionMatrix);
+ return frustum;
+ }
+
+ private void normalizePlane(float[][] frustum, int side) {
+ float magnitude = (float) Math.sqrt(frustum[side][0] * frustum[side][0] + frustum[side][1] * frustum[side][1] + frustum[side][2] * frustum[side][2]);
+
+ frustum[side][0] /= magnitude;
+ frustum[side][1] /= magnitude;
+ frustum[side][2] /= magnitude;
+ frustum[side][3] /= magnitude;
+ }
+
+ private void calculateFrustum(Matrix4f viewMatrix, Matrix4f projectionMatrix) {
+
+ modlBuffer.rewind();
+ viewMatrix.get(modlBuffer);
+ projBuffer.rewind();
+ projectionMatrix.get(projBuffer);
+
+ for(int i = 0; i < 16; i ++) {
+ modl[i] = modlBuffer.get(i);
+ proj[i] = projBuffer.get(i);
+ }
+
+ this.clip[0] = (this.modl[0] * this.proj[0] + this.modl[1] * this.proj[4] + this.modl[2] * this.proj[8] + this.modl[3] * this.proj[12]);
+ this.clip[1] = (this.modl[0] * this.proj[1] + this.modl[1] * this.proj[5] + this.modl[2] * this.proj[9] + this.modl[3] * this.proj[13]);
+ this.clip[2] = (this.modl[0] * this.proj[2] + this.modl[1] * this.proj[6] + this.modl[2] * this.proj[10] + this.modl[3] * this.proj[14]);
+ this.clip[3] = (this.modl[0] * this.proj[3] + this.modl[1] * this.proj[7] + this.modl[2] * this.proj[11] + this.modl[3] * this.proj[15]);
+
+ this.clip[4] = (this.modl[4] * this.proj[0] + this.modl[5] * this.proj[4] + this.modl[6] * this.proj[8] + this.modl[7] * this.proj[12]);
+ this.clip[5] = (this.modl[4] * this.proj[1] + this.modl[5] * this.proj[5] + this.modl[6] * this.proj[9] + this.modl[7] * this.proj[13]);
+ this.clip[6] = (this.modl[4] * this.proj[2] + this.modl[5] * this.proj[6] + this.modl[6] * this.proj[10] + this.modl[7] * this.proj[14]);
+ this.clip[7] = (this.modl[4] * this.proj[3] + this.modl[5] * this.proj[7] + this.modl[6] * this.proj[11] + this.modl[7] * this.proj[15]);
+
+ this.clip[8] = (this.modl[8] * this.proj[0] + this.modl[9] * this.proj[4] + this.modl[10] * this.proj[8] + this.modl[11] * this.proj[12]);
+ this.clip[9] = (this.modl[8] * this.proj[1] + this.modl[9] * this.proj[5] + this.modl[10] * this.proj[9] + this.modl[11] * this.proj[13]);
+ this.clip[10] = (this.modl[8] * this.proj[2] + this.modl[9] * this.proj[6] + this.modl[10] * this.proj[10] + this.modl[11] * this.proj[14]);
+ this.clip[11] = (this.modl[8] * this.proj[3] + this.modl[9] * this.proj[7] + this.modl[10] * this.proj[11] + this.modl[11] * this.proj[15]);
+
+ this.clip[12] = (this.modl[12] * this.proj[0] + this.modl[13] * this.proj[4] + this.modl[14] * this.proj[8] + this.modl[15] * this.proj[12]);
+ this.clip[13] = (this.modl[12] * this.proj[1] + this.modl[13] * this.proj[5] + this.modl[14] * this.proj[9] + this.modl[15] * this.proj[13]);
+ this.clip[14] = (this.modl[12] * this.proj[2] + this.modl[13] * this.proj[6] + this.modl[14] * this.proj[10] + this.modl[15] * this.proj[14]);
+ this.clip[15] = (this.modl[12] * this.proj[3] + this.modl[13] * this.proj[7] + this.modl[14] * this.proj[11] + this.modl[15] * this.proj[15]);
+
+ this.m_Frustum[0][0] = (this.clip[3] - this.clip[0]);
+ this.m_Frustum[0][1] = (this.clip[7] - this.clip[4]);
+ this.m_Frustum[0][2] = (this.clip[11] - this.clip[8]);
+ this.m_Frustum[0][3] = (this.clip[15] - this.clip[12]);
+
+ normalizePlane(this.m_Frustum, 0);
+
+ this.m_Frustum[1][0] = (this.clip[3] + this.clip[0]);
+ this.m_Frustum[1][1] = (this.clip[7] + this.clip[4]);
+ this.m_Frustum[1][2] = (this.clip[11] + this.clip[8]);
+ this.m_Frustum[1][3] = (this.clip[15] + this.clip[12]);
+
+ normalizePlane(this.m_Frustum, 1);
+
+ this.m_Frustum[2][0] = (this.clip[3] + this.clip[1]);
+ this.m_Frustum[2][1] = (this.clip[7] + this.clip[5]);
+ this.m_Frustum[2][2] = (this.clip[11] + this.clip[9]);
+ this.m_Frustum[2][3] = (this.clip[15] + this.clip[13]);
+
+ normalizePlane(this.m_Frustum, 2);
+
+ this.m_Frustum[3][0] = (this.clip[3] - this.clip[1]);
+ this.m_Frustum[3][1] = (this.clip[7] - this.clip[5]);
+ this.m_Frustum[3][2] = (this.clip[11] - this.clip[9]);
+ this.m_Frustum[3][3] = (this.clip[15] - this.clip[13]);
+
+ normalizePlane(this.m_Frustum, 3);
+
+ this.m_Frustum[4][0] = (this.clip[3] - this.clip[2]);
+ this.m_Frustum[4][1] = (this.clip[7] - this.clip[6]);
+ this.m_Frustum[4][2] = (this.clip[11] - this.clip[10]);
+ this.m_Frustum[4][3] = (this.clip[15] - this.clip[14]);
+
+ normalizePlane(this.m_Frustum, 4);
+
+ this.m_Frustum[5][0] = (this.clip[3] + this.clip[2]);
+ this.m_Frustum[5][1] = (this.clip[7] + this.clip[6]);
+ this.m_Frustum[5][2] = (this.clip[11] + this.clip[10]);
+ this.m_Frustum[5][3] = (this.clip[15] + this.clip[14]);
+
+ normalizePlane(this.m_Frustum, 5);
+ }
+
+ public boolean pointInFrustum(float x, float y, float z) {
+ for (int i = 0; i < 6; i++) {
+ if (this.m_Frustum[i][0] * x + this.m_Frustum[i][1] * y + this.m_Frustum[i][2] * z + this.m_Frustum[i][3] <= 0.0F) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public boolean sphereInFrustum(float x, float y, float z, float radius) {
+ for (int i = 0; i < 6; i++) {
+ if (this.m_Frustum[i][0] * x + this.m_Frustum[i][1] * y + this.m_Frustum[i][2] * z + this.m_Frustum[i][3] <= -radius) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public boolean cubeFullyInFrustum(float x1, float y1, float z1, float x2, float y2, float z2) {
+ for (int i = 0; i < 6; i++) {
+ if (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F)
+ return false;
+ if (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F)
+ return false;
+ if (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F)
+ return false;
+ if (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F)
+ return false;
+ if (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F)
+ return false;
+ if (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F)
+ return false;
+ if (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F)
+ return false;
+ if (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F)
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean cubeInFrustum(float x1, float y1, float z1, float x2, float y2, float z2) {
+ return true;
+// for (int i = 0; i < 6; i++) {
+// if ((this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F)) {
+// return false;
+// }
+// }
+// return true;
+ }
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Util/ShaderProgram.java b/src/main/java/net/tylermurphy/Minecraft/Render/Util/ShaderProgram.java new file mode 100755 index 0000000..ce5bae6 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Util/ShaderProgram.java @@ -0,0 +1,126 @@ +package net.tylermurphy.Minecraft.Render.Util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.FloatBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL20;
+import org.joml.Matrix4f;
+import org.joml.Vector2f;
+import org.joml.Vector3f;
+import org.joml.Vector4f;
+
+import net.tylermurphy.Minecraft.Util.Constants;
+
+public abstract class ShaderProgram {
+
+ private int programID;
+ private int vertexShaderID;
+ private int fragmentShaderID;
+
+ private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
+
+ public ShaderProgram(String vertexFile,String fragmentFile){
+ vertexShaderID = loadShader(vertexFile,GL20.GL_VERTEX_SHADER);
+ fragmentShaderID = loadShader(fragmentFile,GL20.GL_FRAGMENT_SHADER);
+ programID = GL20.glCreateProgram();
+ GL20.glAttachShader(programID, vertexShaderID);
+ GL20.glAttachShader(programID, fragmentShaderID);
+ bindAttributes();
+ GL20.glLinkProgram(programID);
+ GL20.glValidateProgram(programID);
+ getAllUniformLocations();
+ }
+
+ protected abstract void getAllUniformLocations();
+
+ protected int getUniformLocation(String uniformName){
+ return GL20.glGetUniformLocation(programID,uniformName);
+ }
+
+ public void start(){
+ GL20.glUseProgram(programID);
+ }
+
+ public void stop(){
+ GL20.glUseProgram(0);
+ }
+
+ public void cleanUp(){
+ stop();
+ GL20.glDetachShader(programID, vertexShaderID);
+ GL20.glDetachShader(programID, fragmentShaderID);
+ GL20.glDeleteShader(vertexShaderID);
+ GL20.glDeleteShader(fragmentShaderID);
+ GL20.glDeleteProgram(programID);
+ }
+
+ protected abstract void bindAttributes();
+
+ protected void bindAttribute(int attribute, String variableName){
+ GL20.glBindAttribLocation(programID, attribute, variableName);
+ }
+
+ protected void loadFloat(int location, float value){
+ GL20.glUniform1f(location, value);
+ }
+
+ protected void loadInt(int location, int value){
+ GL20.glUniform1i(location, value);
+ }
+
+ protected void loadVector(int location, Vector3f vector){
+ GL20.glUniform3f(location,vector.x,vector.y,vector.z);
+ }
+
+ protected void loadVector(int location, Vector4f vector){
+ GL20.glUniform4f(location,vector.x,vector.y,vector.z, vector.w);
+ }
+
+ protected void load2DVector(int location, Vector2f vector){
+ GL20.glUniform2f(location,vector.x,vector.y);
+ }
+
+ protected void loadBoolean(int location, boolean value){
+ float toLoad = 0;
+ if(value){
+ toLoad = 1;
+ }
+ GL20.glUniform1f(location, toLoad);
+ }
+
+ protected void loadMatrix(int location, Matrix4f matrix){
+ matrix.get(matrixBuffer);
+ GL20.glUniformMatrix4fv(location, false, matrixBuffer);
+ }
+
+ private static int loadShader(String file, int type){
+ StringBuilder shaderSource = new StringBuilder();
+ try{
+ FileReader fr = new FileReader(new File(Constants.SHADER_LOCATION + file));
+ BufferedReader reader = new BufferedReader(fr);
+ String line;
+ while((line = reader.readLine())!=null){
+ shaderSource.append(line).append("//\n");
+ }
+ reader.close();
+ }catch(IOException e){
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ int shaderID = GL20.glCreateShader(type);
+ GL20.glShaderSource(shaderID, shaderSource);
+ GL20.glCompileShader(shaderID);
+ if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS )== GL11.GL_FALSE){
+ System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
+ System.err.println("Could not compile shader!");
+ System.exit(-1);
+ }
+ return shaderID;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scene/Camera.java b/src/main/java/net/tylermurphy/Minecraft/Scene/Camera.java new file mode 100755 index 0000000..9752998 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scene/Camera.java @@ -0,0 +1,74 @@ +package net.tylermurphy.Minecraft.Scene;
+
+import java.io.Serializable;
+
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.Input.Input;
+import net.tylermurphy.Minecraft.Render.Data.Display;
+
+public class Camera implements Serializable {
+
+ private static final long serialVersionUID = -2612670500762524881L;
+
+ protected Vector3f position = new Vector3f(0, 0, 0);
+ protected float pitch = 0;
+ protected float yaw = 0;
+ protected float roll = 0;
+
+ public void move(){
+ if(!World.player.isPaused) {
+ calculatePitch();
+ calculateYaw();
+ }
+ calculateCameraPosition();
+
+ yaw%=360;
+ }
+
+ public void invertPitch(){
+ this.pitch = -pitch;
+ }
+
+ public Vector3f getPosition() {
+ return position;
+ }
+
+ public float getPitch() {
+ return pitch;
+ }
+
+ public float getYaw() {
+ return yaw;
+ }
+
+ public float getRoll() {
+ return roll;
+ }
+
+ public void calculateCameraPosition(){
+ position.x = World.player.getTransform().getPosition().x;
+ position.z = World.player.getTransform().getPosition().z;
+ position.y = World.player.getTransform().getPosition().y + 10;
+ }
+
+ protected void calculatePitch(){
+ if(Display.closed()) {
+ float pitchChange = (float) (Input.getMouseDY() * 0.3f);
+ pitch -= pitchChange;
+ if(pitch < -90){
+ pitch = -90;
+ }else if(pitch > 90){
+ pitch = 90;
+ }
+ }
+ }
+
+ protected void calculateYaw(){
+ if(Display.closed()) {
+ float angleChange = (float) (Input.getMouseDX() * 0.4f);
+ yaw += angleChange;
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Entity.java b/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Entity.java new file mode 100755 index 0000000..b2e69f4 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Entity.java @@ -0,0 +1,105 @@ +package net.tylermurphy.Minecraft.Scene.Objects;
+
+import java.io.Serializable;
+
+import net.tylermurphy.Minecraft.Scene.World;
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.Chunk.Cube;
+
+public class Entity extends Renderable implements Serializable{
+
+ private static final long serialVersionUID = -1273546184611580473L;
+
+ protected static final float RUN_SPEED = 4;
+ protected static final float JUMP_POWER = 6;
+ protected static final float GRAVITY = -15;
+
+ protected float currentForwardSpeed = 0;
+ protected float currentSideSpeed = 0;
+ protected float upwardsSpeed = 0;
+
+ public boolean isInAir = true;
+ public boolean isFlying = false;
+ public boolean isSwimming = false;
+ public boolean isBobbing = false;
+ public boolean isFalling = false;
+ public boolean wasFalling = false;
+ public boolean isDead = false;
+
+ public Entity(Transform transform) {
+ super(null,transform,0);
+ }
+
+ public boolean willCollide(float dx, float dy, float dz) {
+ float px = getTransform().getPosition().x;
+ float py = getTransform().getPosition().y;
+ float pz = getTransform().getPosition().z;
+ if(getTransform().getPosition().x<0)
+ px--;
+ if(getTransform().getPosition().z<0)
+ pz--;
+ int[] nbc = {
+ (int) (px+dx+.25f),
+ (int) (py+dy),
+ (int) (pz+dz+.25f),
+ (int) (px+dx+.75f),
+ (int) (py+dy+1.9f),
+ (int) (pz+dz+.75f)
+ };
+
+ for(int x = nbc[0]; x<=nbc[3]; x++) {
+ for(int y = nbc[1]; y<=nbc[4]; y++) {
+ for(int z = nbc[2]; z<=nbc[5]; z++) {
+ byte block_head = World.getBlock(x,y,z);
+ byte block_current_feet = World.getBlock(x,(int)(py),z);
+ byte block_current_upper = World.getBlock(x,(int)(py+1f),z);
+ byte block_current_lower = World.getBlock(x,(int)(py+.75f),z);
+ if(block_current_feet == 17 ) {
+ isSwimming = true;
+ isBobbing = false;
+ }
+ if(block_current_feet == 17 && block_current_lower == 17 && block_current_upper == Cube.AIR){
+ isSwimming = false;
+ isBobbing = true;
+ }
+ if(block_current_feet != 17) {
+ isSwimming = false;
+ isBobbing = false;
+ }
+ if(dy != 0) {
+ if(block_head != Cube.AIR && block_head != 17) {
+ isInAir = !(y <= getTransform().getGlobalPosition().y);
+ return false;
+ } else isInAir = true;
+ }else {
+ if(block_head != Cube.AIR && block_head != 17) return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean collides(float x, float y, float z) {
+ float px = getTransform().getPosition().x;
+ float py = getTransform().getPosition().y;
+ float pz = getTransform().getPosition().z;
+ if(getTransform().getPosition().x<0)
+ px--;
+ if(getTransform().getPosition().z<0)
+ pz--;
+ int[] nbc = {
+ (int) (px+.25f),
+ (int) (py),
+ (int) (pz+.25f),
+ (int) (px+.75f),
+ (int) (py+1.9f),
+ (int) (pz+.75f)
+ };
+ return x >= nbc[0] && x <= nbc[3] &&
+ y >= nbc[1] && y <= nbc[4] &&
+ z >= nbc[2] && z <= nbc[5];
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Renderable.java b/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Renderable.java new file mode 100755 index 0000000..476e2c6 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Renderable.java @@ -0,0 +1,46 @@ +package net.tylermurphy.Minecraft.Scene.Objects;
+
+import java.io.Serializable;
+
+import net.tylermurphy.Minecraft.Render.Data.Mesh;
+
+public class Renderable implements Serializable {
+
+ private static final long serialVersionUID = -5017401455504595815L;
+
+ public Renderable(Mesh mesh, Transform transform, int texture) {
+ this.mesh = mesh;
+ this.transform = transform;
+ this.texture = texture;
+ }
+
+ private Transform transform;
+ private Mesh mesh;
+ private int texture;
+
+ public Mesh getMesh() {
+ return mesh;
+ }
+
+ public void setMesh(Mesh mesh) {
+ this.mesh = mesh;
+ }
+
+ public int getTexture(){
+ return texture;
+ }
+
+ public void setTexture(int texture){
+ this.texture = texture;
+ }
+
+ public Transform getTransform(){
+ if(transform == null) this.transform = new Transform();
+ return transform;
+ }
+
+ public void setTransform(Transform transform){
+ this.transform = transform;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Transform.java b/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Transform.java new file mode 100755 index 0000000..2da820f --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/Transform.java @@ -0,0 +1,59 @@ +package net.tylermurphy.Minecraft.Scene.Objects;
+
+import net.tylermurphy.Minecraft.Scene.World;
+import org.joml.Vector3f;
+
+public class Transform {
+
+ private Vector3f position = new Vector3f(0f, 0f, 0f);
+ private Vector3f rotation = new Vector3f(0f, 0f, 0f);
+ private float scale = 1.0f;
+
+ public Transform setPosition(Vector3f position){
+ this.position = position;
+ return this;
+ }
+
+ public Transform setGlobalPosition(Vector3f position) {
+ this.position = new Vector3f(
+ position.x - World.world_origin.x(),
+ position.y,
+ position.z - World.world_origin.z()
+ );
+ return this;
+ }
+
+ public Transform increasePosition(float dx, float dy, float dz) {
+ this.position.x += dx;
+ this.position.y += dy;
+ this.position.z += dz;
+ return this;
+ }
+
+ public Transform setRotation(Vector3f rotation){
+ this.rotation = rotation;
+ return this;
+ }
+
+ public Transform setScale(float scale){
+ this.scale = scale;
+ return this;
+ }
+
+ public Vector3f getPosition(){
+ return position;
+ }
+
+ public Vector3f getGlobalPosition() {
+ return new Vector3f(position.x+ World.world_origin.x(),position.y,position.z+ World.world_origin.z());
+ }
+
+ public Vector3f getRotation(){
+ return rotation;
+ }
+
+ public float getScale(){
+ return scale;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/WorldOrigin.java b/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/WorldOrigin.java new file mode 100755 index 0000000..a5fa73e --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scene/Objects/WorldOrigin.java @@ -0,0 +1,47 @@ +package net.tylermurphy.Minecraft.Scene.Objects;
+
+import net.tylermurphy.Minecraft.Scene.World;
+import org.joml.Vector3f;
+
+public class WorldOrigin {
+
+ private int x;
+ private int z;
+
+ public WorldOrigin(int x, int z){
+ this.x = x;
+ this.z = z;
+ }
+
+ public int x(){
+ return x;
+ }
+
+ public int z(){
+ return z;
+ }
+
+ public void recalculateOrigin(){
+ Vector3f position = World.player.getTransform().getPosition();
+ if((int)position.x>=256) {
+ int changes = (int) (position.x / 256);
+ x += 256*changes;
+ World.player.getTransform().setPosition(new Vector3f(position.x - 256*changes ,position.y,position.z));
+ } else if((int)position.x<=-256) {
+ int changes = (int) (position.x / 256);
+ x += 256*changes;
+ World.player.getTransform().setPosition(new Vector3f(position.x - 256*changes ,position.y,position.z));
+ }
+
+ if((int)position.z>=256) {
+ int changes = (int) (position.z / 256);
+ z += 256*changes;
+ World.player.getTransform().setPosition(new Vector3f(position.x,position.y,position.z - 256*changes));
+ } else if((int)position.z<=-256) {
+ int changes = (int) (position.z / 256);
+ z += 256*changes;
+ World.player.getTransform().setPosition(new Vector3f(position.x,position.y,position.z - 256*changes));
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scene/Player.java b/src/main/java/net/tylermurphy/Minecraft/Scene/Player.java new file mode 100755 index 0000000..69e741a --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scene/Player.java @@ -0,0 +1,100 @@ +package net.tylermurphy.Minecraft.Scene;
+
+import java.io.Serializable;
+
+import net.tylermurphy.Minecraft.Scene.Objects.Transform;
+import org.lwjgl.glfw.GLFW;
+
+import net.tylermurphy.Minecraft.Input.Input;
+import net.tylermurphy.Minecraft.Scene.Objects.Entity;
+import net.tylermurphy.Minecraft.Render.Data.Display;
+
+public class Player extends Entity implements Serializable {
+
+ private static final long serialVersionUID = 5135364541978251987L;
+
+ public int health = 20;
+
+ public boolean isPaused;
+
+ public Player(Transform transform) {
+ super(transform);
+ }
+
+ public void move() {
+ if(!isPaused)
+ checkInputs();
+ else {
+ this.currentForwardSpeed = 0;
+ this.currentSideSpeed = 0;
+ }
+ float distance = (float) (currentForwardSpeed * Display.getFrameTimeSeconds() * (isFlying == true ? 2 : 1) * ((isSwimming || isBobbing) && !isFlying ? .25 : 1) );
+ float dx = (float) (distance * Math.sin(Math.toRadians(getTransform().getRotation().y)));
+ float dz = (float) (distance * Math.cos(Math.toRadians(getTransform().getRotation().y)));
+ float distance2 = (float) (currentSideSpeed * Display.getFrameTimeSeconds() * (isFlying == true ? 2 : 1) * ((isSwimming || isBobbing) && !isFlying ? .25 : 1) );
+ dx += (float) (distance2 * Math.sin(Math.toRadians(90-getTransform().getRotation().y)));
+ dz += (float) (distance2 * Math.cos(Math.toRadians(90+getTransform().getRotation().y)));
+ if(isInAir && !(isFlying || isSwimming)) upwardsSpeed += GRAVITY * Display.getFrameTimeSeconds();
+ upwardsSpeed *= (isSwimming && !isFlying ? .5 : 1);
+ upwardsSpeed *= (isBobbing) ? -1 : 1;
+ float dy = (float) (upwardsSpeed * Display.getFrameTimeSeconds());
+
+ if(willCollide(dx, 0, 0))
+ getTransform().increasePosition(dx, 0, 0);
+
+ if(willCollide(0, dy, 0)) {
+ getTransform().increasePosition(0, dy, 0);
+ }
+
+ if(willCollide(0, 0, dz))
+ getTransform().increasePosition(0, 0, dz);
+
+ if(getTransform().getPosition().y < 0) {
+ getTransform().increasePosition(0, 256, 0);
+ }
+ }
+
+ private void checkInputs() {
+ int keys_pressed = 0;
+
+ if(Input.isKeyDown(GLFW.GLFW_KEY_W)) {
+ this.currentForwardSpeed = -RUN_SPEED; keys_pressed++;
+ }else if(Input.isKeyDown(GLFW.GLFW_KEY_S)) {
+ this.currentForwardSpeed = RUN_SPEED; keys_pressed++;
+ }else {
+ this.currentForwardSpeed = 0;
+ }
+
+ if(Input.isKeyDown(GLFW.GLFW_KEY_A)) {
+ this.currentSideSpeed = -RUN_SPEED; keys_pressed++;
+ }else if(Input.isKeyDown(GLFW.GLFW_KEY_D)) {
+ this.currentSideSpeed = RUN_SPEED; keys_pressed++;
+ }else {
+ this.currentSideSpeed = 0;
+ }
+
+ if(keys_pressed == 2) {
+ this.currentForwardSpeed /=1.25;
+ this.currentSideSpeed /=1.25;
+ }
+
+ if(Input.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL)) {
+ this.currentForwardSpeed *= 1.5;
+ this.currentSideSpeed *= 1.5;
+ }
+
+ if(Input.isKeyDown(GLFW.GLFW_KEY_SPACE)) {
+ if(!isInAir && !(isFlying || isSwimming)) {
+ this.upwardsSpeed = JUMP_POWER;
+ isInAir = true;
+ }else if(isFlying || isSwimming) {
+ this.upwardsSpeed = JUMP_POWER;
+ }
+ } else if(Input.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT) && isFlying || isSwimming && !isFlying) {
+ this.upwardsSpeed = -JUMP_POWER;
+ } else if(isFlying) {
+ this.upwardsSpeed = 0;
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scene/World.java b/src/main/java/net/tylermurphy/Minecraft/Scene/World.java new file mode 100755 index 0000000..d54ed92 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scene/World.java @@ -0,0 +1,89 @@ +package net.tylermurphy.Minecraft.Scene;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.stream.Collectors;
+
+import net.tylermurphy.Minecraft.Chunk.Cube;
+import net.tylermurphy.Minecraft.Scene.Objects.WorldOrigin;
+
+import net.tylermurphy.Minecraft.Chunk.Chunk;
+import net.tylermurphy.Minecraft.Tick.BlockUpdate;
+
+public class World {
+
+ private static final HashMap<String,Chunk> chunks = new HashMap<>();
+
+ public static Camera camera;
+ public static Player player;
+ public static int seed;
+ public static int renderDistance;
+
+ public static WorldOrigin world_origin;
+
+ public static byte getBlock(int x, int y, int z) {
+ if(y<0 || y> 255) return Cube.AIR;
+ int cx = (int)Math.floor(x/16.0) + world_origin.x()/16;
+ int cz = (int)Math.floor(z/16.0) + world_origin.z()/16;
+ Chunk chunk = getChunk(cx, cz);
+ if(chunk==null) return Cube.NULL;
+ int rx = x-16*(int)Math.floor(x/16.0);
+ int rz = z-16*(int)Math.floor(z/16.0);
+ return chunk.cubes[rx][y][rz];
+ }
+
+ public static int getHighestBlock(int fx, int fz) {
+ for(int y=255;y>=0;y--) {
+ if(getBlock(fx,y,fz) != -1) return y;
+ }
+ return 255;
+ }
+
+ public static void setBlock(int x, int y, int z, byte id) {
+ if(y<0 || y> 255) return;
+ int cx = (int)Math.floor(x/16.0) + world_origin.x()/16;
+ int cz = (int)Math.floor(z/16.0) + world_origin.z()/16;
+ Chunk chunk = getChunk(cx, cz);
+ if(chunk==null) return;
+ int rx = x-16*(int)Math.floor(x/16.0);
+ int rz = z-16*(int)Math.floor(z/16.0);
+ BlockUpdate.createBlockUpdate(x, y, z, chunk.cubes[rx][y][rz], id);
+ chunk.scheduleFutureMeshUpdate();
+ chunk.cubes[rx][y][rz] = id;
+ if(id != -1 && y > 0 && chunk.cubes[rx][y - 1][rz] == 0)
+ chunk.cubes[rx][y -1][rz] = 1;
+ int ox = (rx%16) == 0 ? -1 : (rx%16) == 15 ? 1 : 0;
+ int oz = (rz%16) == 0 ? -1 : (rz%16) == 15 ? 1 : 0;
+ Chunk coc = null,coz = null;
+ if(ox != 0) coc = getChunk(chunk.gridX + ox, chunk.gridZ);
+ if(oz != 0) coz = getChunk(chunk.gridX, chunk.gridZ + oz);
+ if(coc != null) {
+ coc.scheduleFutureMeshUpdate();
+ }
+ if(coz != null) {
+ coz.scheduleFutureMeshUpdate();
+ }
+ }
+
+ public static Chunk getChunk(int x, int z){
+ Chunk c = chunks.get(x+":"+z);
+ return c == null ? null : c.isSafe() ? c : null;
+ }
+
+ public static Chunk getChunkUnsafe(int x, int z){
+ return chunks.get(x+":"+z);
+ }
+
+ public static void addChunk(Chunk c){
+ chunks.put(c.gridX+":"+c.gridZ, c);
+ }
+
+ public static void removeChunk(int x, int z){
+ chunks.remove(x+":"+z);
+ }
+
+ public static Collection<Chunk> getChunks(){
+ return chunks.values().stream().filter(Chunk::isSafe).collect(Collectors.toList());
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Scripts/GameScript.java b/src/main/java/net/tylermurphy/Minecraft/Scripts/GameScript.java new file mode 100755 index 0000000..f73ef9d --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scripts/GameScript.java @@ -0,0 +1,99 @@ +package net.tylermurphy.Minecraft.Scripts;
+
+import java.util.Random;
+
+import net.tylermurphy.Minecraft.Audio.Sound;
+import net.tylermurphy.Minecraft.Audio.SoundManager;
+import net.tylermurphy.Minecraft.Chunk.Chunk;
+import net.tylermurphy.Minecraft.Scene.Camera;
+import net.tylermurphy.Minecraft.Scene.Objects.Transform;
+import net.tylermurphy.Minecraft.Scene.Objects.WorldOrigin;
+import net.tylermurphy.Minecraft.Scene.Player;
+import net.tylermurphy.Minecraft.Scene.World;
+import net.tylermurphy.Minecraft.Tick.TickManager;
+import net.tylermurphy.Minecraft.Util.ChunkLoader;
+import net.tylermurphy.Minecraft.Util.Constants;
+import net.tylermurphy.Minecraft.Util.Data;
+import net.tylermurphy.Minecraft.Util.ResourceManager;
+import org.joml.Vector3f;
+
+public class GameScript extends Script {
+
+ Sound sound;
+ String[] music = {"calm1","calm2","calm3","hal1","hal2","hal3","hal4","nuance1","nuance2","piano1","piano2","piano3"};
+
+ public void Init() {
+ createScene();
+ loadNextSound();
+ }
+
+ public void Update() {
+ ChunkLoader.run();
+ }
+
+ public void Tick() {
+ if(!sound.isPlaying()) loadNextSound();
+ for(Chunk c: World.getChunks()) {
+ if(c==null) continue;
+ if(c.isScheduled())
+ c.updateMesh();
+ }
+ TickManager.doTick();
+ }
+
+ public void loadNextSound() {
+ Random random = new Random();
+ int i = random.nextInt(music.length);
+ sound = SoundManager.loadSound(music[i]);
+ sound.setLooping(false);
+ sound.play();
+ }
+
+ public void Stop() {
+ sound.stop();
+
+ ChunkLoader.save();
+
+ ResourceManager.saveObject("playerdata/", "temp.player", World.player);
+ ResourceManager.saveObject("playerdata/", "temp.camera", World.camera);
+ Data worldData = new Data();
+ worldData.INTS.put("SEED", World.seed);
+ worldData.INTS.put("OriginX", World.world_origin.x());
+ worldData.INTS.put("OriginZ", World.world_origin.z());
+ ResourceManager.saveObject("", "world.dat", worldData);
+ }
+
+ private static void createScene() {
+
+ Camera camera = (Camera) ResourceManager.loadObject("playerdata/", "temp.camera");
+ if(camera!=null) {
+ World.camera = camera;
+ } else{
+ World.camera = new Camera();
+ }
+
+ Data worldData = (Data) ResourceManager.loadObject("", "world.dat");
+ if(worldData == null) {
+ World.seed = new Random().nextInt(1000000000);
+ World.world_origin = new WorldOrigin(0,0);
+ } else {
+ World.seed = worldData.INTS.get("SEED");
+ int wx = worldData.INTS.get("OriginX");
+ int wz = worldData.INTS.get("OriginZ");
+ World.world_origin = new WorldOrigin(wx,wz);
+ }
+ World.renderDistance = Constants.RENDER_DISTANCE;
+ Player player = (Player) ResourceManager.loadObject("playerdata/", "temp.player");
+ if(player!=null) {
+ World.player = player;
+ } else{
+ World.player = new Player(
+ new Transform()
+ .setPosition(new Vector3f(0, 160, 0))
+ .setScale(.6f)
+ );
+ }
+
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Scripts/PlayerScript.java b/src/main/java/net/tylermurphy/Minecraft/Scripts/PlayerScript.java new file mode 100755 index 0000000..eb64b14 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scripts/PlayerScript.java @@ -0,0 +1,44 @@ +package net.tylermurphy.Minecraft.Scripts;
+
+import static net.tylermurphy.Minecraft.UI.UIMaster.bindUI;
+import static net.tylermurphy.Minecraft.UI.UIMaster.getImage;
+import static net.tylermurphy.Minecraft.UI.UIMaster.getText;
+import static net.tylermurphy.Minecraft.UI.UIMaster.setEnabled;
+
+import net.tylermurphy.Minecraft.Main;
+import net.tylermurphy.Minecraft.Scene.World;
+
+public class PlayerScript extends Script {
+
+ int last_height = 0;
+
+ public void Update() {
+ World.player.isFalling = World.player.isInAir && !World.player.isFlying && !World.player.isSwimming;
+ if(World.player.isSwimming || World.player.isFlying) last_height = (int) World.player.getTransform().getGlobalPosition().y;
+
+ if(World.player.isFalling) {
+ if(!World.player.wasFalling)
+ last_height = (int) World.player.getTransform().getGlobalPosition().y;
+ World.player.wasFalling = true;
+ } else if(World.player.wasFalling) {
+ int current_height = (int) World.player.getTransform().getGlobalPosition().y;
+ float height_fell = last_height - current_height;
+ if(height_fell > 3)
+ World.player.health -= height_fell - 3;
+ World.player.health = Math.max(World.player.health,0);
+ World.player.wasFalling = false;
+ }
+
+ if(World.player.health <= 0) {
+ World.player.isDead = true;
+ bindUI(1);
+ setEnabled(false);
+ bindUI(0);
+ getText("dead").setEnabled(true);
+ getImage("crosshair").setEnabled(false);
+ }
+ World.world_origin.recalculateOrigin();
+ if(!World.player.isDead && Main.getTicks() % 80 == 0 && World.player.health < 20) World.player.health++;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scripts/Script.java b/src/main/java/net/tylermurphy/Minecraft/Scripts/Script.java new file mode 100755 index 0000000..0ff5c8d --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scripts/Script.java @@ -0,0 +1,11 @@ +package net.tylermurphy.Minecraft.Scripts;
+
+public class Script {
+
+ public void Init() {}
+ public void Update() {}
+ public void Tick() {}
+ public void End() {}
+ public void Stop() {}
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Scripts/UIScript.java b/src/main/java/net/tylermurphy/Minecraft/Scripts/UIScript.java new file mode 100755 index 0000000..2f7da5f --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Scripts/UIScript.java @@ -0,0 +1,62 @@ +package net.tylermurphy.Minecraft.Scripts;
+
+import static net.tylermurphy.Minecraft.UI.UIMaster.bindUI;
+import static net.tylermurphy.Minecraft.UI.UIMaster.getImage;
+import static net.tylermurphy.Minecraft.UI.UIMaster.getText;
+import static net.tylermurphy.Minecraft.UI.UIMaster.setEnabled;
+
+import net.tylermurphy.Minecraft.Main;
+import net.tylermurphy.Minecraft.Scene.World;
+import net.tylermurphy.Minecraft.UI.UIImage;
+import net.tylermurphy.Minecraft.UI.UIFactory.*;
+import net.tylermurphy.Minecraft.Render.Data.Display;
+
+public class UIScript extends Script {
+
+ public void Init() {
+ UIStore.InitalizeStoreData();
+ CoreUI.initCoreUI();
+ F3UI.initF3UI();
+ SavingUI.initSavingUI();
+ CommandUI.initCommandUI();
+ }
+
+ public void Update() {
+ bindUI(0);
+ for(int i=1;i<=10;i++) {
+ UIImage heart = getImage("heart" + i);
+ if(World.player.health >= i*2) {
+ heart.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ } else if(World.player.health >= i*2-1) {
+ heart.setTexture(UIStore.TEXTURES.get("heart_half_texture"));
+ } else {
+ heart.setTexture(UIStore.TEXTURES.get("heart_empty_texture"));
+ }
+ }
+ }
+
+ public void Tick() {
+ String position = "Position: "+(int)(World.player.getTransform().getGlobalPosition().x())+","+(int) World.player.getTransform().getGlobalPosition().y()+","+(int)(World.player.getTransform().getGlobalPosition().z());
+ String rotation = "Rotation: "+(int) World.player.getTransform().getRotation().x+","+(int) World.player.getTransform().getRotation().y+","+(int) World.player.getTransform().getRotation().z;
+ bindUI(1);
+ getText("position").setText(position);
+ getText("rotation").setText(rotation);
+ getText("freemem").setText("Free memory (bytes): " + Runtime.getRuntime().freeMemory());
+ if(Main.getTicks() % 20 == 0) {
+ getText("fps").setText("FPS: " + (int)(1/Display.getFrameTimeSeconds()));
+ getText("tps").setText("TPS: " + Main.getTPS());
+ }
+ }
+
+ public void End() {
+ bindUI(0);
+ setEnabled(false);
+ bindUI(1);
+ setEnabled(false);
+ bindUI(2);
+ setEnabled(true);
+ bindUI(3);
+ setEnabled(false);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Tick/BlockUpdate.java b/src/main/java/net/tylermurphy/Minecraft/Tick/BlockUpdate.java new file mode 100755 index 0000000..6c5fef1 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Tick/BlockUpdate.java @@ -0,0 +1,53 @@ +package net.tylermurphy.Minecraft.Tick;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.tylermurphy.Minecraft.Chunk.Cube;
+import net.tylermurphy.Minecraft.Scene.World;
+
+public class BlockUpdate {
+
+ public int x,y,z;
+ public byte old_block_id;
+ public byte new_block_id;
+ private long delay_of_update, creation_of_update;
+
+ private static List<BlockUpdate> current_block_updates = new ArrayList<BlockUpdate>();
+ private static List<BlockUpdate> waiting_block_updates = new ArrayList<BlockUpdate>();
+
+ public static void createBlockUpdate(int x, int y, int z, byte old_block_id, byte new_block_id) {
+ BlockUpdate update = new BlockUpdate();
+ update.x = x;
+ update.y = y;
+ update.z = z;
+ update.old_block_id = old_block_id;
+ update.new_block_id = new_block_id;
+ if(new_block_id != -1)
+ update.delay_of_update = Cube.getBlock(new_block_id).tick_update_delay*1000000;
+ else
+ update.delay_of_update = Cube.getBlock("water").tick_update_delay*1000000;
+ update.creation_of_update = System.nanoTime();
+ waiting_block_updates.add(update);
+ }
+
+ public static List<BlockUpdate> loadBirthedUpdates() {
+ int j = waiting_block_updates.size();
+ for(int i = 0; i < j; i++) {
+ BlockUpdate update = waiting_block_updates.get(i);
+ if(World.getBlock(update.x, update.y, update.z) != update.new_block_id) continue;
+ if(System.nanoTime() - update.creation_of_update >= update.delay_of_update) {
+ waiting_block_updates.remove(i);
+ j--;
+ i--;
+ current_block_updates.add(update);
+ }
+ }
+ return current_block_updates;
+ }
+
+ public static void purgeUpdates() {
+ current_block_updates.clear();
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Tick/GameTicks/GrassTick.java b/src/main/java/net/tylermurphy/Minecraft/Tick/GameTicks/GrassTick.java new file mode 100755 index 0000000..f7201f1 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Tick/GameTicks/GrassTick.java @@ -0,0 +1,50 @@ +package net.tylermurphy.Minecraft.Tick.GameTicks;
+
+import net.tylermurphy.Minecraft.Scene.World;
+import net.tylermurphy.Minecraft.Tick.BlockUpdate;
+
+public class GrassTick {
+
+ private static boolean foundGrass(int x, int y, int z)
+ {
+ for(int a = x-1; a<x+2; a++) {
+ for(int b = y-1; b<y+2; b++) {
+ for(int c = z-1; c<z+2; c++) {
+ if(x == a && c == z) continue;
+ if(World.getBlock(a, b, c) == 0) return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static void searchForDirt(int x, int y, int z)
+ {
+ for(int a = x-1; a<x+2; a++)
+ for(int b = y-1; b<y+2; b++)
+ for(int c = z-1; c<z+2; c++) {
+ if(x == a && c == z)
+ continue;
+ if(World.getBlock(a, b, c) == 1 && World.getBlock(a, b+1, c) == -1) {
+ BlockUpdate.createBlockUpdate(a, b, c, (byte)1, (byte)1);
+ }
+ }
+ }
+
+ public static void doGrassTick(BlockUpdate update) {
+ if(update.new_block_id == 1) {
+ int rand = (int)(Math.random()*100);
+ if(rand>95) {
+ if(World.getBlock(update.x,update.y+1,update.z) == -1 && foundGrass(update.x,update.y,update.z)) {
+ World.setBlock(update.x,update.y,update.z, (byte)0);
+ }
+ } else {
+ BlockUpdate.createBlockUpdate(update.x,update.y,update.z, (byte)1, (byte)1);
+ }
+ }
+ if(update.new_block_id == 0) {
+ searchForDirt(update.x,update.y,update.z);
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Tick/GameTicks/WaterTick.java b/src/main/java/net/tylermurphy/Minecraft/Tick/GameTicks/WaterTick.java new file mode 100755 index 0000000..01b008c --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Tick/GameTicks/WaterTick.java @@ -0,0 +1,45 @@ +package net.tylermurphy.Minecraft.Tick.GameTicks;
+
+import net.tylermurphy.Minecraft.Scene.World;
+import net.tylermurphy.Minecraft.Tick.BlockUpdate;
+
+public class WaterTick {
+
+ public static void doWaterTick(BlockUpdate update) {
+ if(update.new_block_id == 17) {
+ if(World.getBlock(update.x, update.y-1, update.z) == -1) {
+ World.setBlock(update.x, update.y-1, update.z, (byte)17);
+ }
+ if(World.getBlock(update.x-1, update.y, update.z) == -1) {
+ World.setBlock(update.x-1, update.y, update.z, (byte)17);
+ }
+ if(World.getBlock(update.x+1, update.y, update.z) == -1) {
+ World.setBlock(update.x+1, update.y, update.z, (byte)17);
+ }
+ if(World.getBlock(update.x, update.y, update.z-1) == -1) {
+ World.setBlock(update.x, update.y, update.z-1, (byte)17);
+ }
+ if(World.getBlock(update.x, update.y, update.z+1) == -1) {
+ World.setBlock(update.x, update.y, update.z+1, (byte)17);
+ }
+ }
+ if(update.new_block_id == -1) {
+ if(World.getBlock(update.x, update.y+1, update.z) == 17) {
+ World.setBlock(update.x, update.y+1, update.z, (byte)17);
+ }
+ if(World.getBlock(update.x-1, update.y, update.z) == 17) {
+ World.setBlock(update.x-1, update.y, update.z, (byte)17);
+ }
+ if(World.getBlock(update.x+1, update.y, update.z) == 17) {
+ World.setBlock(update.x+1, update.y, update.z, (byte)17);
+ }
+ if(World.getBlock(update.x, update.y, update.z-1) == 17) {
+ World.setBlock(update.x, update.y, update.z-1, (byte)17);
+ }
+ if(World.getBlock(update.x, update.y, update.z+1) == 17) {
+ World.setBlock(update.x, update.y, update.z+1, (byte)17);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Tick/TickManager.java b/src/main/java/net/tylermurphy/Minecraft/Tick/TickManager.java new file mode 100755 index 0000000..c705d37 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Tick/TickManager.java @@ -0,0 +1,24 @@ +package net.tylermurphy.Minecraft.Tick;
+
+import java.util.List;
+
+import net.tylermurphy.Minecraft.Tick.GameTicks.GrassTick;
+import net.tylermurphy.Minecraft.Tick.GameTicks.WaterTick;
+
+
+public class TickManager {
+
+ public static void doTick() {
+ List<BlockUpdate> block_updates = BlockUpdate.loadBirthedUpdates();
+ for(BlockUpdate update : block_updates) {
+ if(update.new_block_id == 17 || update.new_block_id == -1) {
+ WaterTick.doWaterTick(update);
+ }
+ if(update.new_block_id == 0 || update.new_block_id == 1) {
+ GrassTick.doGrassTick(update);
+ }
+ }
+ BlockUpdate.purgeUpdates();
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/Text/Character.java b/src/main/java/net/tylermurphy/Minecraft/UI/Text/Character.java new file mode 100755 index 0000000..d7d78cf --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/Text/Character.java @@ -0,0 +1,72 @@ +package net.tylermurphy.Minecraft.UI.Text;
+
+
+public class Character {
+
+ private int id;
+ private double xTextureCoord;
+ private double yTextureCoord;
+ private double xMaxTextureCoord;
+ private double yMaxTextureCoord;
+ private double xOffset;
+ private double yOffset;
+ private double sizeX;
+ private double sizeY;
+ private double xAdvance;
+
+
+ protected Character(int id, double xTextureCoord, double yTextureCoord, double xTexSize, double yTexSize,
+ double xOffset, double yOffset, double sizeX, double sizeY, double xAdvance) {
+ this.id = id;
+ this.xTextureCoord = xTextureCoord;
+ this.yTextureCoord = yTextureCoord;
+ this.xOffset = xOffset;
+ this.yOffset = yOffset;
+ this.sizeX = sizeX;
+ this.sizeY = sizeY;
+ this.xMaxTextureCoord = xTexSize + xTextureCoord;
+ this.yMaxTextureCoord = yTexSize + yTextureCoord;
+ this.xAdvance = xAdvance;
+ }
+
+ protected int getId() {
+ return id;
+ }
+
+ protected double getxTextureCoord() {
+ return xTextureCoord;
+ }
+
+ protected double getyTextureCoord() {
+ return yTextureCoord;
+ }
+
+ protected double getXMaxTextureCoord() {
+ return xMaxTextureCoord;
+ }
+
+ protected double getYMaxTextureCoord() {
+ return yMaxTextureCoord;
+ }
+
+ protected double getxOffset() {
+ return xOffset;
+ }
+
+ protected double getyOffset() {
+ return yOffset;
+ }
+
+ protected double getSizeX() {
+ return sizeX;
+ }
+
+ protected double getSizeY() {
+ return sizeY;
+ }
+
+ protected double getxAdvance() {
+ return xAdvance;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/Text/Line.java b/src/main/java/net/tylermurphy/Minecraft/UI/Text/Line.java new file mode 100755 index 0000000..ec80db5 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/Text/Line.java @@ -0,0 +1,44 @@ +package net.tylermurphy.Minecraft.UI.Text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Line {
+
+ private double maxLength;
+ private double spaceSize;
+
+ private List<Word> words = new ArrayList<Word>();
+ private double currentLineLength = 0;
+
+
+ protected Line(double spaceWidth, double fontSize, double maxLength) {
+ this.spaceSize = spaceWidth * fontSize;
+ this.maxLength = maxLength;
+ }
+
+ protected boolean attemptToAddWord(Word word) {
+ double additionalLength = word.getWordWidth();
+ additionalLength += !words.isEmpty() ? spaceSize : 0;
+ if (currentLineLength + additionalLength <= maxLength) {
+ words.add(word);
+ currentLineLength += additionalLength;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected double getMaxLength() {
+ return maxLength;
+ }
+
+ protected double getLineLength() {
+ return currentLineLength;
+ }
+
+ protected List<Word> getWords() {
+ return words;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/Text/MetaFile.java b/src/main/java/net/tylermurphy/Minecraft/UI/Text/MetaFile.java new file mode 100755 index 0000000..1d22499 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/Text/MetaFile.java @@ -0,0 +1,157 @@ +package net.tylermurphy.Minecraft.UI.Text;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.tylermurphy.Minecraft.Util.Constants;
+import net.tylermurphy.Minecraft.Render.Data.Display;
+
+public class MetaFile {
+
+ private static final int PAD_TOP = 0;
+ private static final int PAD_LEFT = 1;
+ private static final int PAD_BOTTOM = 2;
+ private static final int PAD_RIGHT = 3;
+
+ private static final int DESIRED_PADDING = 8;
+
+ private static final String SPLITTER = " ";
+ private static final String NUMBER_SEPARATOR = ",";
+
+ private double aspectRatio;
+
+ private double verticalPerPixelSize;
+ private double horizontalPerPixelSize;
+ private double spaceWidth;
+ private int[] padding;
+ private int paddingWidth;
+ private int paddingHeight;
+
+ private Map<Integer, Character> metaData = new HashMap<Integer, Character>();
+
+ private BufferedReader reader;
+ private Map<String, String> values = new HashMap<String, String>();
+
+ protected MetaFile(String file) {
+ this.aspectRatio = (double) Display.getWidth() / (double) Display.getHeight();
+ openFile(file);
+ loadPaddingData();
+ loadLineSizes();
+ int imageWidth = getValueOfVariable("scaleW");
+ loadCharacterData(imageWidth);
+ close();
+ }
+
+ protected double getSpaceWidth() {
+ return spaceWidth;
+ }
+
+ protected Character getCharacter(int ascii) {
+ return metaData.get(ascii);
+ }
+
+ private boolean processNextLine() {
+ values.clear();
+ String line = null;
+ try {
+ line = reader.readLine();
+ } catch (IOException e1) {
+ }
+ if (line == null) {
+ return false;
+ }
+ for (String part : line.split(SPLITTER)) {
+ String[] valuePairs = part.split("=");
+ if (valuePairs.length == 2) {
+ values.put(valuePairs[0], valuePairs[1]);
+ }
+ }
+ return true;
+ }
+
+ private int getValueOfVariable(String variable) {
+ int i = 0;
+ try {
+ i = Integer.parseInt(values.get(variable));
+ }catch(Exception e) {
+ e.printStackTrace();
+ }
+ return i;
+ }
+
+ private int[] getValuesOfVariable(String variable) {
+ String[] numbers = values.get(variable).split(NUMBER_SEPARATOR);
+ int[] actualValues = new int[numbers.length];
+ for (int i = 0; i < actualValues.length; i++) {
+ actualValues[i] = Integer.parseInt(numbers[i]);
+ }
+ return actualValues;
+ }
+
+ private void close() {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void openFile(String file) {
+ try {
+ FileReader isr = new FileReader(new File(Constants.FNT_LOCATION + file + ".fnt"));
+ reader = new BufferedReader(isr);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.err.println("Couldn't read font meta file!");
+ }
+ }
+
+ private void loadPaddingData() {
+ processNextLine();
+ this.padding = getValuesOfVariable("padding");
+ this.paddingWidth = padding[PAD_LEFT] + padding[PAD_RIGHT];
+ this.paddingHeight = padding[PAD_TOP] + padding[PAD_BOTTOM];
+ }
+
+ private void loadLineSizes() {
+ processNextLine();
+ int lineHeightPixels = getValueOfVariable("lineHeight") - paddingHeight;
+ verticalPerPixelSize = TextMeshCreator.LINE_HEIGHT / (double) lineHeightPixels;
+ horizontalPerPixelSize = verticalPerPixelSize / aspectRatio;
+ }
+
+ private void loadCharacterData(int imageWidth) {
+ processNextLine();
+ processNextLine();
+ while (processNextLine()) {
+ Character c = loadCharacter(imageWidth);
+ if (c != null) {
+ metaData.put(c.getId(), c);
+ }
+ }
+ }
+
+ private Character loadCharacter(int imageSize) {
+ int id = getValueOfVariable("id");
+ if (id == TextMeshCreator.SPACE_ASCII) {
+ this.spaceWidth = (getValueOfVariable("xadvance") - paddingWidth) * horizontalPerPixelSize;
+ return null;
+ }
+ double xTex = ((double) getValueOfVariable("x") + (padding[PAD_LEFT] - DESIRED_PADDING)) / imageSize;
+ double yTex = ((double) getValueOfVariable("y") + (padding[PAD_TOP] - DESIRED_PADDING)) / imageSize;
+ int width = getValueOfVariable("width") - (paddingWidth - (2 * DESIRED_PADDING));
+ int height = getValueOfVariable("height") - ((paddingHeight) - (2 * DESIRED_PADDING));
+ double quadWidth = width * horizontalPerPixelSize;
+ double quadHeight = height * verticalPerPixelSize;
+ double xTexSize = (double) width / imageSize;
+ double yTexSize = (double) height / imageSize;
+ double xOff = (getValueOfVariable("xoffset") + padding[PAD_LEFT] - DESIRED_PADDING) * horizontalPerPixelSize;
+ double yOff = (getValueOfVariable("yoffset") + (padding[PAD_TOP] - DESIRED_PADDING)) * verticalPerPixelSize;
+ double xAdvance = (getValueOfVariable("xadvance") - paddingWidth) * horizontalPerPixelSize;
+ return new Character(id, xTex, yTex, xTexSize, yTexSize, xOff, yOff, quadWidth, quadHeight, xAdvance);
+ }
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMaster.java b/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMaster.java new file mode 100755 index 0000000..2616722 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMaster.java @@ -0,0 +1,63 @@ +package net.tylermurphy.Minecraft.UI.Text;
+
+import java.util.ArrayList;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.tylermurphy.Minecraft.Render.FontRenderer;
+import net.tylermurphy.Minecraft.UI.UIComponent;
+import net.tylermurphy.Minecraft.UI.UIFont;
+import net.tylermurphy.Minecraft.UI.UIText;
+
+public class TextMaster {
+
+ private static Map<UIFont, List<UIText>> texts = new HashMap<UIFont, List<UIText>>();
+
+ private static void proccessText(UIText text) {
+ UIFont fontType = text.getFont();
+ List<UIText> batch = texts.get(fontType);
+ if (batch != null) {
+ batch.add(text);
+ } else {
+ List<UIText> newBatch = new ArrayList<net.tylermurphy.Minecraft.UI.UIText>();
+ newBatch.add(text);
+ texts.put(fontType, newBatch);
+ }
+ }
+
+ public static void render(List<UIComponent> components,FontRenderer fontrenderer){
+ for(UIComponent component : components) {
+ UIText text;
+ if(component instanceof UIText) {
+ text = (UIText)component;
+ } else {
+ continue;
+ }
+ loadText(text);
+ proccessText(text);
+ }
+ fontrenderer.render(TextMaster.texts);
+ TextMaster.texts.clear();
+ }
+
+ public static void loadText(UIText text){
+ UIFont font = text.getFont();
+ List<UIText> textBatch = texts.get(font);
+ if(textBatch == null){
+ textBatch = new ArrayList<UIText>();
+ texts.put(font, textBatch);
+ }
+ textBatch.add(text);
+ }
+
+ public static void removeText(UIText text){
+ List<UIText> textBatch = texts.get(text.getFont());
+ textBatch.remove(text);
+ if(textBatch.isEmpty()){
+ texts.remove(text.getFont());
+ }
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMeshCreator.java b/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMeshCreator.java new file mode 100755 index 0000000..bd84abb --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMeshCreator.java @@ -0,0 +1,140 @@ +package net.tylermurphy.Minecraft.UI.Text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.tylermurphy.Minecraft.UI.UIText;
+
+public class TextMeshCreator {
+
+ protected static final double LINE_HEIGHT = 0.03f;
+ protected static final int SPACE_ASCII = 32;
+
+ private MetaFile metaData;
+
+ public TextMeshCreator(String metaFile) {
+ metaData = new MetaFile(metaFile);
+ }
+
+ public TextMeshData createTextMesh(UIText text) {
+ List<Line> lines = createStructure(text);
+ TextMeshData data = createQuadVertices(text, lines);
+ return data;
+ }
+
+ private List<Line> createStructure(UIText text) {
+ char[] chars = text.getTextString().toCharArray();
+ List<Line> lines = new ArrayList<Line>();
+ Line currentLine = new Line(metaData.getSpaceWidth(), text.getFontSize(), text.getMaxLineSize());
+ Word currentWord = new Word(text.getFontSize());
+ for (char c : chars) {
+ int ascii = (int) c;
+ if (ascii == SPACE_ASCII) {
+ boolean added = currentLine.attemptToAddWord(currentWord);
+ if (!added) {
+ lines.add(currentLine);
+ currentLine = new Line(metaData.getSpaceWidth(), text.getFontSize(), text.getMaxLineSize());
+ currentLine.attemptToAddWord(currentWord);
+ }
+ currentWord = new Word(text.getFontSize());
+ continue;
+ }
+ Character character = metaData.getCharacter(ascii);
+ currentWord.addCharacter(character);
+ }
+ completeStructure(lines, currentLine, currentWord, text);
+ return lines;
+ }
+
+ private void completeStructure(List<Line> lines, Line currentLine, Word currentWord, UIText text) {
+ boolean added = currentLine.attemptToAddWord(currentWord);
+ if (!added) {
+ lines.add(currentLine);
+ currentLine = new Line(metaData.getSpaceWidth(), text.getFontSize(), text.getMaxLineSize());
+ currentLine.attemptToAddWord(currentWord);
+ }
+ lines.add(currentLine);
+ }
+
+ private TextMeshData createQuadVertices(UIText text, List<Line> lines) {
+ text.setNumberOfLines(lines.size());
+ double curserX = 0f;
+ double curserY = 0f;
+ double maxX = 0;
+ List<Float> vertices = new ArrayList<Float>();
+ List<Float> textureCoords = new ArrayList<Float>();
+ for (Line line : lines) {
+ if (text.isCentered()) {
+ curserX = (line.getMaxLength() - line.getLineLength()) / 2;
+ }
+ for (Word word : line.getWords()) {
+ for (Character letter : word.getCharacters()) {
+ double newMaxX = addVerticesForCharacter(curserX, curserY, letter, text.getFontSize(), vertices);
+ maxX = Math.max(newMaxX, maxX);
+ addTexCoords(textureCoords, letter.getxTextureCoord(), letter.getyTextureCoord(),
+ letter.getXMaxTextureCoord(), letter.getYMaxTextureCoord());
+ curserX += letter.getxAdvance() * text.getFontSize();
+ }
+ curserX += metaData.getSpaceWidth() * text.getFontSize();
+ }
+ curserX = 0;
+ curserY += LINE_HEIGHT * text.getFontSize();
+ }
+ text.setMaxX(maxX);
+ return new TextMeshData(listToArray(vertices), listToArray(textureCoords));
+ }
+
+ private double addVerticesForCharacter(double curserX, double curserY, Character character, double fontSize,
+ List<Float> vertices) {
+ double x = curserX + (character.getxOffset() * fontSize);
+ double y = curserY + (character.getyOffset() * fontSize);
+ double maxX = x + (character.getSizeX() * fontSize);
+ double maxY = y + (character.getSizeY() * fontSize);
+ double properX = (2 * x) - 1;
+ double properY = (-2 * y) + 1;
+ double properMaxX = (2 * maxX) - 1;
+ double properMaxY = (-2 * maxY) + 1;
+ addVertices(vertices, properX, properY, properMaxX, properMaxY);
+ return maxX;
+ }
+
+ private static void addVertices(List<Float> vertices, double x, double y, double maxX, double maxY) {
+ vertices.add((float) x);
+ vertices.add((float) y);
+ vertices.add((float) x);
+ vertices.add((float) maxY);
+ vertices.add((float) maxX);
+ vertices.add((float) maxY);
+ vertices.add((float) maxX);
+ vertices.add((float) maxY);
+ vertices.add((float) maxX);
+ vertices.add((float) y);
+ vertices.add((float) x);
+ vertices.add((float) y);
+ }
+
+ private static void addTexCoords(List<Float> texCoords, double x, double y, double maxX, double maxY) {
+ texCoords.add((float) x);
+ texCoords.add((float) y);
+ texCoords.add((float) x);
+ texCoords.add((float) maxY);
+ texCoords.add((float) maxX);
+ texCoords.add((float) maxY);
+ texCoords.add((float) maxX);
+ texCoords.add((float) maxY);
+ texCoords.add((float) maxX);
+ texCoords.add((float) y);
+ texCoords.add((float) x);
+ texCoords.add((float) y);
+ }
+
+
+ private static float[] listToArray(List<Float> listOfFloats) {
+ float[] array = new float[listOfFloats.size()];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = listOfFloats.get(i);
+ }
+ return array;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMeshData.java b/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMeshData.java new file mode 100755 index 0000000..2226e93 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/Text/TextMeshData.java @@ -0,0 +1,25 @@ +package net.tylermurphy.Minecraft.UI.Text;
+
+public class TextMeshData {
+
+ private float[] vertexPositions;
+ private float[] textureCoords;
+
+ protected TextMeshData(float[] vertexPositions, float[] textureCoords){
+ this.vertexPositions = vertexPositions;
+ this.textureCoords = textureCoords;
+ }
+
+ public float[] getVertexPositions() {
+ return vertexPositions;
+ }
+
+ public float[] getTextureCoords() {
+ return textureCoords;
+ }
+
+ public int getVertexCount() {
+ return vertexPositions.length/2;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/Text/Word.java b/src/main/java/net/tylermurphy/Minecraft/UI/Text/Word.java new file mode 100755 index 0000000..9256619 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/Text/Word.java @@ -0,0 +1,29 @@ +package net.tylermurphy.Minecraft.UI.Text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Word {
+
+ private List<Character> characters = new ArrayList<Character>();
+ private double width = 0;
+ private double fontSize;
+
+ protected Word(double fontSize){
+ this.fontSize = fontSize;
+ }
+
+ protected void addCharacter(Character character){
+ characters.add(character);
+ width += character.getxAdvance() * fontSize;
+ }
+
+ protected List<Character> getCharacters(){
+ return characters;
+ }
+
+ protected double getWordWidth(){
+ return width;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UI.java b/src/main/java/net/tylermurphy/Minecraft/UI/UI.java new file mode 100755 index 0000000..1f1f1e0 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UI.java @@ -0,0 +1,38 @@ +package net.tylermurphy.Minecraft.UI;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class UI {
+
+ public boolean enabled = true;
+
+ protected List<UIComponent> children = new ArrayList<UIComponent>();
+
+ protected UIComponent findKey(String key) {
+ for(UIComponent component : children) {
+ UIComponent c = component.findKey(key);
+ if(c!=null) return c;
+ }
+ return null;
+ }
+
+ protected UIText findText(String key) {
+ return (UIText) findKey(key);
+ }
+
+ protected UIImage findImage(String key) {
+ return (UIImage) findKey(key);
+ }
+
+ protected void add(UIComponent component) {
+ children.add(component);
+ };
+
+ protected void prepare() {
+ if(!enabled) return;
+ for(UIComponent component : children)
+ component.prepare(null);
+ }
+
+ }
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIComponent.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIComponent.java new file mode 100755 index 0000000..ffe39eb --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIComponent.java @@ -0,0 +1,104 @@ +package net.tylermurphy.Minecraft.UI;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.joml.Matrix4f;
+import org.joml.Vector2f;
+import org.joml.Vector4f;
+
+import net.tylermurphy.Minecraft.Render.Data.Display;
+import net.tylermurphy.Minecraft.Util.Maths;
+
+public abstract class UIComponent {
+
+ private List<UIComponent> children = new ArrayList<UIComponent>();
+
+ private Vector4f size = new Vector4f(0,100,0,100);
+ private Vector4f position = new Vector4f(0,0,0,0);
+
+ protected boolean enabled = true;
+
+ private String key;
+
+ private int zIndex = 1;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public int getZIndex() {
+ return zIndex;
+ }
+
+ public void setZIndex(int zIndex) {
+ this.zIndex = zIndex;
+ }
+
+ public UIComponent findKey(String key) {
+ if(this.key != null && this.key.equals(key)) return this;
+ for(UIComponent component : children) {
+ UIComponent c = component.findKey(key);
+ if(c!=null) return c;
+ }
+ return null;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ };
+
+ public void add(UIComponent component) {
+ children.add(component);
+ };
+
+ protected List<UIComponent> getComponents() {
+ return children;
+ };
+
+ public void prepare(UIComponent parent) {
+ if(this.enabled) UIMaster.componentBatch.add(this);
+ for(UIComponent component : children) {
+ component.prepare(component);
+ }
+ }
+
+ public void setSize(float xScale, float xOffset, float yScale, float yOffset) {
+ this.size = new Vector4f(xScale,xOffset,yScale,yOffset);
+ }
+
+ public Vector4f getSize() {
+ return size;
+ }
+
+ public void setPosition(float xScale, float xOffset, float yScale, float yOffset) {
+ this.position = new Vector4f(xScale,xOffset,yScale,yOffset);
+ }
+
+ public Vector4f getPosition() {
+ return position;
+ }
+
+ public Vector2f getConvertedSize() {
+ return new Vector2f(
+ size.x + size.y/Display.getWidth(),
+ size.z + size.w/Display.getHeight()
+ );
+ }
+
+ public Vector2f getConvertedPosition() {
+ return new Vector2f(
+ (position.x + position.y/Display.getWidth()),
+ (position.w/Display.getHeight() + position.z)
+ );
+ }
+
+ public Matrix4f getMatrix() {
+ return Maths.createTransformationMatrix(new Vector2f(getConvertedPosition().x*2-1,getConvertedPosition().y*2-1), getConvertedSize());
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/CommandUI.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/CommandUI.java new file mode 100755 index 0000000..259958a --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/CommandUI.java @@ -0,0 +1,23 @@ +package net.tylermurphy.Minecraft.UI.UIFactory;
+
+import static net.tylermurphy.Minecraft.UI.UIMaster.*;
+
+import net.tylermurphy.Minecraft.UI.UIText;
+
+public class CommandUI {
+
+ public static void initCommandUI() {
+
+
+ createUI(3);
+ setEnabled(false);
+
+ UIText commandBar = new UIText("/",1,UIStore.FONTS.get("yugothic"),1000,false);
+ commandBar.setPosition(0, 0, 1-.1f, 0);
+ commandBar.setKey("commandBar");
+ commandBar.setStretchBackdrop(true);
+
+ add(commandBar);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/CoreUI.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/CoreUI.java new file mode 100755 index 0000000..ec9ff74 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/CoreUI.java @@ -0,0 +1,76 @@ +package net.tylermurphy.Minecraft.UI.UIFactory;
+
+import static net.tylermurphy.Minecraft.UI.UIMaster.add;
+import static net.tylermurphy.Minecraft.UI.UIMaster.createUI;
+
+import net.tylermurphy.Minecraft.UI.UIImage;
+import net.tylermurphy.Minecraft.UI.UIText;
+
+public class CoreUI {
+
+ public static void initCoreUI() {
+
+ createUI(0);
+ UIImage image = new UIImage();
+ image.setTexture(UIStore.TEXTURES.get("crosshair"));
+ image.setPosition(.5f, -15f, .5f, -15f);
+ image.setSize(0, 30, 0, 30);
+ image.setKey("crosshair");
+ UIImage heart1 = new UIImage();
+ heart1.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart1.setPosition(0, 20, 1f, -20);
+ heart1.setSize(0, 20, 0, 20);
+ heart1.setKey("heart1");
+ UIImage heart2 = new UIImage();
+ heart2.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart2.setPosition(0, 50, 1f, -20);
+ heart2.setSize(0, 20, 0, 20);
+ heart2.setKey("heart2");
+ UIImage heart3 = new UIImage();
+ heart3.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart3.setPosition(0, 80, 1f, -20);
+ heart3.setSize(0, 20, 0, 20);
+ heart3.setKey("heart3");
+ UIImage heart4 = new UIImage();
+ heart4.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart4.setPosition(0, 110, 1f, -20);
+ heart4.setSize(0, 20, 0, 20);
+ heart4.setKey("heart4");
+ UIImage heart5 = new UIImage();
+ heart5.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart5.setPosition(0, 140, 1f, -20);
+ heart5.setSize(0, 20, 0, 20);
+ heart5.setKey("heart5");
+ UIImage heart6 = new UIImage();
+ heart6.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart6.setPosition(0, 170, 1f, -20);
+ heart6.setSize(0, 20, 0, 20);
+ heart6.setKey("heart6");
+ UIImage heart7 = new UIImage();
+ heart7.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart7.setPosition(0, 200, 1f, -20);
+ heart7.setSize(0, 20, 0, 20);
+ heart7.setKey("heart7");
+ UIImage heart8 = new UIImage();
+ heart8.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart8.setPosition(0, 230, 1f, -20);
+ heart8.setSize(0, 20, 0, 20);
+ heart8.setKey("heart8");
+ UIImage heart9 = new UIImage();
+ heart9.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart9.setPosition(0, 260, 1f, -20);
+ heart9.setSize(0, 20, 0, 20);
+ heart9.setKey("heart9");
+ UIImage heart10 = new UIImage();
+ heart10.setTexture(UIStore.TEXTURES.get("heart_full_texture"));
+ heart10.setPosition(0, 290, 1f, -20);
+ heart10.setSize(0, 20, 0, 20);
+ heart10.setKey("heart10");
+ UIText dead = new UIText("You have died, press k to respawn.",1,UIStore.FONTS.get("yugothic"),1000,false);
+ dead.setPosition(0.4f, 0, .5f, -20);
+ dead.setKey("dead");
+ dead.setEnabled(false);
+ add(image,heart1,heart2,heart3,heart4,heart5,heart6,heart7,heart8,heart9,heart10,dead);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/F3UI.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/F3UI.java new file mode 100755 index 0000000..3ec7d84 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/F3UI.java @@ -0,0 +1,53 @@ +package net.tylermurphy.Minecraft.UI.UIFactory;
+
+import static net.tylermurphy.Minecraft.UI.UIMaster.add;
+import static net.tylermurphy.Minecraft.UI.UIMaster.createUI;
+import static net.tylermurphy.Minecraft.UI.UIMaster.setEnabled;
+
+import net.tylermurphy.Minecraft.Render.Data.Texture;
+import net.tylermurphy.Minecraft.UI.UIFont;
+import net.tylermurphy.Minecraft.UI.UIText;
+
+public class F3UI {
+
+ public static void initF3UI() {
+
+ createUI(1);
+ setEnabled(false);
+
+ String maxMem = "Max memory (bytes): " + Runtime.getRuntime().maxMemory();
+ String freeMem = "Free memory (bytes): " + Runtime.getRuntime().freeMemory();
+ String allocMem = "Allocated memory (bytes): " + Runtime.getRuntime().totalMemory();
+ String cores = "Available processors (cores): "+ Runtime.getRuntime().availableProcessors();
+
+ UIText maxMemText = new UIText(maxMem,1,UIStore.FONTS.get("yugothic"),1000,false);
+ maxMemText.setPosition(0, 0, .125f, 0);
+ UIText freeMemText = new UIText(freeMem,1,UIStore.FONTS.get("yugothic"),1000,false);
+ freeMemText.setPosition(0, 0, .15f, 0);
+ freeMemText.setKey("freemem");
+ UIText allocMemText = new UIText(allocMem,1,UIStore.FONTS.get("yugothic"),1000,false);
+ allocMemText.setPosition(0, 0, .175f, 0);
+ UIText coresText = new UIText(cores,1,UIStore.FONTS.get("yugothic"),1000,false);
+ coresText.setPosition(0, 0, .2f, .2f);
+
+ UIText position = new UIText("",1,UIStore.FONTS.get("yugothic"),1000,false);
+ position.setPosition(0, 0, 0, 0);
+ position.setKey("position");
+ UIText rotation = new UIText("",1,UIStore.FONTS.get("yugothic"),1000,false);
+ rotation.setPosition(0, 0, .025f, 0);
+ rotation.setKey("rotation");
+ UIText fps = new UIText("",1,UIStore.FONTS.get("yugothic"),1000,false);
+ fps.setPosition(0, 0, .05f, 0);
+ fps.setKey("fps");
+ UIText tps = new UIText("",1,UIStore.FONTS.get("yugothic"),1000,false);
+ tps.setPosition(0, 0, 0.075f, 0);
+ tps.setKey("tps");
+
+ UIText block = new UIText("Block Selected: minecraft:dirt",1,UIStore.FONTS.get("yugothic"),1000,false);
+ block.setPosition(0, 0, .25f, 0);
+ block.setKey("block");
+
+ add(maxMemText,freeMemText,allocMemText,coresText,position,rotation,fps,block,tps);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/SavingUI.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/SavingUI.java new file mode 100755 index 0000000..7826e4a --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/SavingUI.java @@ -0,0 +1,17 @@ +package net.tylermurphy.Minecraft.UI.UIFactory;
+
+import static net.tylermurphy.Minecraft.UI.UIMaster.*;
+
+import net.tylermurphy.Minecraft.UI.UIText;
+
+public class SavingUI {
+
+ public static void initSavingUI() {
+ createUI(2);
+ UIText saving = new UIText("Saving...",1,UIStore.FONTS.get("yugothic"),1000,false);
+ saving.setPosition(0.5f, -50, 0.5f, -20);
+ add(saving);
+ setEnabled(false);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/UIStore.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/UIStore.java new file mode 100755 index 0000000..b4c7c8a --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIFactory/UIStore.java @@ -0,0 +1,24 @@ +package net.tylermurphy.Minecraft.UI.UIFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.tylermurphy.Minecraft.Render.Data.Texture;
+import net.tylermurphy.Minecraft.UI.UIFont;
+
+public class UIStore {
+
+ public static Map<String,Integer> TEXTURES = new HashMap<String,Integer>();
+ public static Map<String,UIFont> FONTS = new HashMap<String,UIFont>();
+
+ public static void InitalizeStoreData() {
+
+ FONTS.put("yugothic", new UIFont(Texture.loadFontAtlas("font/yugothic"),"yugothic"));
+ TEXTURES.put("heart_full_texture",Texture.loadTexture("gui/heart_full"));
+ TEXTURES.put("heart_half_texture",Texture.loadTexture("gui/heart_half"));
+ TEXTURES.put("heart_empty_texture",Texture.loadTexture("gui/heart_empty"));
+ TEXTURES.put("crosshair",Texture.loadTexture("gui/crosshair"));
+
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIFont.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIFont.java new file mode 100755 index 0000000..6f93b37 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIFont.java @@ -0,0 +1,31 @@ +package net.tylermurphy.Minecraft.UI;
+
+import net.tylermurphy.Minecraft.Render.Data.Texture;
+import net.tylermurphy.Minecraft.UI.Text.TextMeshCreator;
+import net.tylermurphy.Minecraft.UI.Text.TextMeshData;
+
+public class UIFont {
+
+ private int textureAtlas;
+ private TextMeshCreator loader;
+
+
+ public UIFont(int textureAtlas, String fontFile) {
+ this.textureAtlas = textureAtlas;
+ this.loader = new TextMeshCreator(fontFile);
+ }
+
+ public UIFont(String font) {
+ this.textureAtlas = Texture.loadFontAtlas(font);
+ this.loader = new TextMeshCreator(font);
+ }
+
+ public int getTextureAtlas() {
+ return textureAtlas;
+ }
+
+ public TextMeshData loadText(UIText text) {
+ return loader.createTextMesh(text);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIImage.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIImage.java new file mode 100755 index 0000000..7e772ab --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIImage.java @@ -0,0 +1,30 @@ +package net.tylermurphy.Minecraft.UI;
+
+import org.joml.Vector2f;
+
+import net.tylermurphy.Minecraft.Render.Data.Display;
+
+public class UIImage extends UIComponent {
+
+ private int texture;
+
+ public void setTexture(int texture) {
+ this.texture = texture;
+ }
+
+ public int getTexture() {
+ return texture;
+ }
+
+ public boolean clicked() {
+ Vector2f pos = Display.getCursorPos();
+ float x1 = super.getConvertedPosition().x*Display.getWidth();
+ float y1 = super.getConvertedPosition().y*Display.getHeight();
+ float x2 = super.getConvertedPosition().x*Display.getWidth()+super.getConvertedSize().x*Display.getWidth();
+ float y2 = super.getConvertedPosition().y*Display.getHeight()+super.getConvertedSize().y*Display.getHeight();
+ if(pos.x >= x1 && pos.x <= x2 && pos.y >= y1 && pos.y <= y2)
+ return true;
+ return false;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UILayerQuickSort.java b/src/main/java/net/tylermurphy/Minecraft/UI/UILayerQuickSort.java new file mode 100755 index 0000000..6355347 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UILayerQuickSort.java @@ -0,0 +1,38 @@ +package net.tylermurphy.Minecraft.UI;
+
+import java.util.List;
+
+public class UILayerQuickSort {
+
+ public static void quickSort(List<UIComponent> arr, int start, int end){
+
+ int partition = partition(UIMaster.componentBatch, start, end);
+
+ if(partition-1>start) {
+ quickSort(UIMaster.componentBatch, start, partition - 1);
+ }
+ if(partition+1<end) {
+ quickSort(UIMaster.componentBatch, partition + 1, end);
+ }
+ }
+
+ public static int partition(List<UIComponent> arr, int start, int end){
+
+ UIComponent pivot = arr.get(end);
+
+ for(int i=start; i<end; i++){
+ if(arr.get(i).getZIndex()<pivot.getZIndex()){
+ UIComponent temp= arr.get(start);
+ arr.set(start, arr.get(i));
+ arr.set(i, temp);
+ start++;
+ }
+ }
+
+ UIComponent temp = arr.get(start);
+ arr.set(start, pivot);
+ arr.set(end, temp);
+
+ return start;
+ }
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIMaster.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIMaster.java new file mode 100755 index 0000000..8709aab --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIMaster.java @@ -0,0 +1,65 @@ +package net.tylermurphy.Minecraft.UI;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.tylermurphy.Minecraft.Render.FontRenderer;
+import net.tylermurphy.Minecraft.Render.GuiRenderer;
+import net.tylermurphy.Minecraft.UI.Text.TextMaster;
+
+public class UIMaster {
+
+ private static List<UI> uis = new ArrayList<UI>();
+ private static int bindedID = 0;
+ protected static List<UIComponent> componentBatch = new ArrayList<UIComponent>();
+
+ public static void createUI(int id) {
+ uis.add(id,new UI());
+ bindedID = id;
+ }
+
+ private static UI getUI() {
+ return uis.get(bindedID);
+ }
+
+ public static void add(UIComponent... components) {
+ for(UIComponent component : components) {
+ getUI().add(component);
+ }
+ }
+
+ public static UIImage getImage(String key) {
+ return (UIImage) getUI().findKey(key);
+ }
+
+ public static UIText getText(String key) {
+ return (UIText) getUI().findKey(key);
+ }
+
+ public static void bindUI(int id) {
+ bindedID = id;
+ }
+
+ public static void setEnabled(boolean value) {
+ getUI().enabled = value;
+ }
+
+ public static boolean isEnabled() {
+ return getUI().enabled;
+ }
+
+ public static void renderUI(GuiRenderer renderer, FontRenderer fontrenderer) {
+ for(UI ui : uis) {
+ if(!ui.enabled) continue;
+ ui.prepare();
+ }
+ try{
+ UILayerQuickSort.quickSort(componentBatch, 0, componentBatch.size()-1);
+ } catch (Exception ignore) {}
+ renderer.render(componentBatch);
+ TextMaster.render(componentBatch,fontrenderer);
+ componentBatch.clear();
+ }
+
+}
+
diff --git a/src/main/java/net/tylermurphy/Minecraft/UI/UIText.java b/src/main/java/net/tylermurphy/Minecraft/UI/UIText.java new file mode 100755 index 0000000..fa2e0bc --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/UI/UIText.java @@ -0,0 +1,110 @@ +package net.tylermurphy.Minecraft.UI;
+
+import net.tylermurphy.Minecraft.Render.Data.Mesh;
+import org.joml.Vector3f;
+
+import net.tylermurphy.Minecraft.UI.Text.TextMaster;
+import net.tylermurphy.Minecraft.UI.Text.TextMeshData;
+
+public class UIText extends UIComponent{
+
+ private String textString;
+ private final float fontSize;
+
+ private final Vector3f colour = new Vector3f(255f, 255f, 255f);
+
+ private final float lineMaxSize;
+ private int numberOfLines;
+ private double maxX;
+
+ private final UIFont font;
+
+ private final boolean centerText;
+ private boolean stretchBackdrop = false;
+
+ private Mesh mesh;
+
+ public UIText(String text, float fontSize, UIFont font, float maxLineLength ,boolean centered) {
+ this.textString = text;
+ this.fontSize = fontSize;
+ this.font = font;
+ this.lineMaxSize = maxLineLength;
+ this.centerText = centered;
+ TextMeshData data = font.loadText(this);
+ this.mesh = new Mesh(data.getVertexPositions().length).store(data.getVertexPositions(), 2).store(data.getTextureCoords(), 2).finish();
+ TextMaster.loadText(this);
+ }
+
+ public void remove() {
+ TextMaster.removeText(this);
+ }
+
+ public UIFont getFont() {
+ return font;
+ }
+
+ public void setColour(float r, float g, float b) {
+ colour.set(r, g, b);
+ }
+
+ public Vector3f getColour() {
+ return colour;
+ }
+
+ public int getNumberOfLines() {
+ return numberOfLines;
+ }
+
+ public int getMesh() {
+ return mesh.getID();
+ }
+
+ public int getVertexCount() {
+ return mesh.getVertexCount();
+ }
+
+ public float getFontSize() {
+ return fontSize;
+ }
+
+ public void setNumberOfLines(int number) {
+ this.numberOfLines = number;
+ }
+
+ public boolean isCentered() {
+ return centerText;
+ }
+
+ public float getMaxLineSize() {
+ return lineMaxSize;
+ }
+
+ public String getTextString() {
+ return textString;
+ }
+
+ public void setText(String textString) {
+ this.textString = textString;
+
+ mesh.delete();
+ TextMeshData data = font.loadText(this);
+ this.mesh = new Mesh(data.getVertexPositions().length).store(data.getVertexPositions(), 2).store(data.getTextureCoords(), 2).finish();
+ }
+
+ public void setMaxX(double maxX) {
+ this.maxX = maxX;
+ }
+
+ public double getMaxX() {
+ return maxX;
+ }
+
+ public void setStretchBackdrop(boolean stretchBackdrop) {
+ this.stretchBackdrop = stretchBackdrop;
+ }
+
+ public boolean getStretchBackdrop() {
+ return this.stretchBackdrop;
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Util/ChunkLoader.java b/src/main/java/net/tylermurphy/Minecraft/Util/ChunkLoader.java new file mode 100755 index 0000000..2e81fc9 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Util/ChunkLoader.java @@ -0,0 +1,112 @@ +package net.tylermurphy.Minecraft.Util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.tylermurphy.Minecraft.Chunk.Chunk;
+import net.tylermurphy.Minecraft.Scene.World;
+import org.joml.Vector2i;
+
+public class ChunkLoader {
+
+ private static final ArrayList<Vector2i> keys_to_be_removed = new ArrayList<>();
+
+ private static final HashMap<String, Data> loaded_regions = new HashMap<>();
+
+ public static void run() {
+ try {
+ int cx,cz;
+ cx = (int) ((World.player.getTransform().getGlobalPosition().x)/16);
+ cz = (int) ((World.player.getTransform().getGlobalPosition().z)/16);
+ keys_to_be_removed.clear();
+ for(Chunk c : World.getChunks()) {
+ if(c.gridX < cx-World.renderDistance || c.gridX > cx+World.renderDistance || c.gridZ < cz-World.renderDistance || c.gridZ > cz+World.renderDistance) {
+
+ int x = c.gridX; int z = c.gridZ;
+ int regionX = x > 0 ? x / 16 : (x - 16) / 16;
+ int regionZ = z > 0 ? z / 16 : (z - 16) / 16;
+ Data region = loaded_regions.get(getRegionKey(regionX,regionZ));
+ byte[] data = ResourceManager.flattenArray(c.cubes);
+ region.BYTE_ARRAYS.put(getChunkKey(x,z), data);
+ loaded_regions.put(getRegionKey(regionX,regionZ), region);
+
+ if(c.renderable() != null)
+ c.renderable().getMesh().delete();
+ c.deleteRenderable();
+ if(c.transparentRenderable() != null)
+ c.transparentRenderable().getMesh().delete();
+ c.deleteTransparentRenderable();
+ c.cubes = null;
+ keys_to_be_removed.add(new Vector2i(c.gridX, c.gridZ));
+ }
+ }
+ for(Vector2i pos : keys_to_be_removed) {
+ World.removeChunk(pos.x, pos.y);
+ }
+ for(int x=cx-World.renderDistance; x<cx+World.renderDistance;x++) {
+ for(int z=cz-World.renderDistance; z<cz+World.renderDistance;z++) {
+ if(World.getChunkUnsafe(x, z) != null) continue;
+
+ Chunk chunk = loadChunk(x, z);
+ chunk.initialize();
+ World.addChunk(chunk);
+ update(x+1,z);
+ update(x-1,z);
+ update(x,z+1);
+ update(x,z-1);
+ }
+ }
+ }catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void save() {
+ for(Chunk c : World.getChunks()) {
+ int x = c.gridX; int z = c.gridZ;
+ int regionX = x > 0 ? x / 16 : (x - 16) / 16;
+ int regionZ = z > 0 ? z / 16 : (z - 16) / 16;
+ Data region = loaded_regions.get(getRegionKey(regionX,regionZ));
+ byte[] data = ResourceManager.flattenArray(c.cubes);
+ region.BYTE_ARRAYS.put(getChunkKey(x,z), data);
+ loaded_regions.put(getRegionKey(regionX,regionZ), region);
+ }
+ for(Map.Entry<String, Data> entry : loaded_regions.entrySet()) {
+ ResourceManager.saveObject("region/", entry.getKey(), entry.getValue());
+ }
+ }
+
+ private static void update(int x, int z) {
+ Chunk c = World.getChunkUnsafe(x, z);
+ if(c != null) c.updateMesh();
+ }
+
+ private static Chunk loadChunk(int gridX, int gridZ) {
+ int regionX = gridX > 0 ? gridX / 16 : (gridX - 16) / 16;
+ int regionZ = gridZ > 0 ? gridZ / 16 : (gridZ - 16) / 16;
+ Data region;
+ if(!loaded_regions.containsKey(getRegionKey(regionX,regionZ))) {
+ Object reg = ResourceManager.loadObject("region/", getRegionKey(regionX,regionZ));
+ if(reg == null) region = new Data();
+ else region = (Data)reg;
+ loaded_regions.put(getRegionKey(regionX,regionZ), region);
+ } else region = loaded_regions.get(getRegionKey(regionX,regionZ));
+ if(region.BYTE_ARRAYS.containsKey(getChunkKey(gridX,gridZ))) {
+ byte[] data = region.BYTE_ARRAYS.get(getChunkKey(gridX,gridZ));
+ Chunk chunk = new Chunk(gridX,gridZ,true);
+ chunk.cubes = ResourceManager.expandArray(data);
+ return chunk;
+ } else {
+ return new Chunk(gridX,gridZ,true);
+ }
+ }
+
+ public static String getRegionKey(int regionX, int regionZ) {
+ return regionX+"x"+regionZ+"z.region";
+ }
+
+ public static String getChunkKey(int gridX, int gridZ) {
+ return gridX+"x"+gridZ+"z";
+ }
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Util/Constants.java b/src/main/java/net/tylermurphy/Minecraft/Util/Constants.java new file mode 100755 index 0000000..d657e83 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Util/Constants.java @@ -0,0 +1,21 @@ +package net.tylermurphy.Minecraft.Util;
+
+public class Constants {
+
+ public static final String SHADER_LOCATION = "assets/shaders/";
+ public static final String PNG_LOCATION = "assets/textures/";
+ public static final String FNT_LOCATION = "assets/font/";
+ public static final String OGG_LOCATION = "assets/sounds/";
+ public static final String SAVES_LOCATION = "saves";
+
+ public static final float NEAR_DISTANCE = 0.1f;
+ public static final float FAR_DISTANCE = 1000;
+ public static final float FOV = 70;
+
+ public static final float RED = 0.78125f;
+ public static final float GREEN = 0.8984375f;
+ public static final float BLUE = 0.8984375f;
+
+ public static final int RENDER_DISTANCE = 24;
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Util/Data.java b/src/main/java/net/tylermurphy/Minecraft/Util/Data.java new file mode 100755 index 0000000..7c4213d --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Util/Data.java @@ -0,0 +1,16 @@ +package net.tylermurphy.Minecraft.Util;
+
+import java.io.Serializable;
+import java.util.HashMap;
+
+public class Data implements Serializable {
+
+ private static final long serialVersionUID = 6866388687418069074L;
+
+ public final HashMap<String,byte[]> BYTE_ARRAYS = new HashMap<>();
+
+ public final HashMap<String,Float> FLOATS = new HashMap<>();
+ public final HashMap<String,Integer> INTS = new HashMap<>();
+ public final HashMap<String,Boolean> BOOLEANS = new HashMap<>();
+
+}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Util/Flags.java b/src/main/java/net/tylermurphy/Minecraft/Util/Flags.java new file mode 100755 index 0000000..8282ad9 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Util/Flags.java @@ -0,0 +1,7 @@ +package net.tylermurphy.Minecraft.Util;
+
+public class Flags {
+
+ public static boolean actionForceClose = false;
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Util/Maths.java b/src/main/java/net/tylermurphy/Minecraft/Util/Maths.java new file mode 100755 index 0000000..89343e1 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Util/Maths.java @@ -0,0 +1,66 @@ +package net.tylermurphy.Minecraft.Util;
+
+import org.joml.Vector2f;
+import org.joml.Vector3f;
+import org.joml.Matrix4f;
+
+import net.tylermurphy.Minecraft.Scene.Camera;
+
+public class Maths {
+
+ public static Matrix4f createTransformationMatrix(Vector2f translation, Vector2f scale) {
+ Matrix4f matrix = new Matrix4f();
+ matrix.identity();
+ matrix.translate(translation.x, translation.y, 0);
+ matrix.scale(new Vector3f(scale.x, scale.y, 1f));
+ return matrix;
+ }
+
+ public static Matrix4f createTransformationMatrix(Vector3f translation, float rx, float ry, float rz, float scale) {
+ Matrix4f matrix = new Matrix4f();
+ matrix.identity();
+ matrix.translate(translation);
+ matrix.rotate((float) Math.toRadians(rx), new Vector3f(1,0,0));
+ matrix.rotate((float) Math.toRadians(ry), new Vector3f(0,1,0));
+ matrix.rotate((float) Math.toRadians(rz), new Vector3f(0,0,1));
+ matrix.scale(scale);
+ return matrix;
+ }
+
+ public static Matrix4f createViewMatrix(Camera camera) {
+ Matrix4f viewMatrix = new Matrix4f();
+ viewMatrix.identity();
+ viewMatrix.rotate((float) Math.toRadians(camera.getPitch()), new Vector3f(1, 0, 0));
+ viewMatrix.rotate((float) Math.toRadians(camera.getYaw()), new Vector3f(0, 1, 0));
+ Vector3f cameraPos = camera.getPosition();
+ Vector3f negativeCameraPos = new Vector3f(-cameraPos.x,-cameraPos.y,-cameraPos.z);
+ viewMatrix.translate(negativeCameraPos);
+ return viewMatrix;
+ }
+
+ public static float barryCentric(Vector3f p1, Vector3f p2, Vector3f p3, Vector2f pos) {
+ float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
+ float l1 = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z)) / det;
+ float l2 = ((p3.z - p1.z) * (pos.x - p3.x) + (p1.x - p3.x) * (pos.y - p3.z)) / det;
+ float l3 = 1.0f - l1 - l2;
+ return l1 * p1.y + l2 * p2.y + l3 * p3.y;
+ }
+
+ public static float getDistance(float x1, float z1, float x2, float z2) {
+ float x = (x2-x1) * (x2-x1);
+ float z = (z2-z1) * (z2-z1);
+ float answer = (float) Math.sqrt(x + z);
+ System.out.println(answer);
+ return answer;
+ }
+
+ public static float getDistance(Vector3f vec1, Vector3f vec2) {
+ float x = (vec1.x-vec2.x) * (vec1.x-vec2.x);
+ float z = (vec1.z-vec2.z) * (vec1.z-vec2.z);
+ float answer = (float) Math.sqrt(x + z);
+ return answer;
+ }
+
+
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Util/MousePicker.java b/src/main/java/net/tylermurphy/Minecraft/Util/MousePicker.java new file mode 100755 index 0000000..d35a1d1 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Util/MousePicker.java @@ -0,0 +1,73 @@ +package net.tylermurphy.Minecraft.Util;
+
+import net.tylermurphy.Minecraft.Render.Data.Display;
+import org.joml.Matrix4f;
+import org.joml.Vector2f;
+import org.joml.Vector3f;
+import org.joml.Vector4f;
+
+import net.tylermurphy.Minecraft.Chunk.Cube;
+import net.tylermurphy.Minecraft.Scene.World;
+
+public class MousePicker {
+
+ public static Vector3f breakPos = new Vector3f();
+ public static Vector3f placePos = new Vector3f();
+
+ private static Matrix4f projectionMatrix;
+ private static Matrix4f viewMatrix;
+
+ public static void init(Matrix4f projection) {
+ projectionMatrix = projection;
+ }
+
+ public static void update() {
+ viewMatrix = Maths.createViewMatrix(World.camera);
+ Vector3f currentRay = calculateMouseRay();
+ breakPos = search(currentRay, World.player.getTransform().getPosition(), 0);
+ if(breakPos == null) placePos = null;
+ }
+
+ private static Vector3f calculateMouseRay() {
+ float mouseX = (float) Display.getWidth()/2;
+ float mouseY = (float) Display.getHeight()/2;
+ Vector2f normalizedCoords = getNormalisedDeviceCoordinates(mouseX, mouseY);
+ Vector4f clipCoords = new Vector4f(normalizedCoords.x, normalizedCoords.y, -1.0f, 1.0f);
+ Vector4f eyeCoords = toEyeCoords(clipCoords);
+ return toWorldCoords(eyeCoords);
+ }
+
+ private static Vector3f toWorldCoords(Vector4f eyeCoords) {
+ Matrix4f invertedView = viewMatrix;
+ Vector4f rayWorld = invertedView.invert().transform(eyeCoords);;
+ Vector3f mouseRay = new Vector3f(rayWorld.x, rayWorld.y, rayWorld.z);
+ mouseRay.normalize();
+ return mouseRay;
+ }
+
+ private static Vector4f toEyeCoords(Vector4f clipCoords) {
+ Matrix4f invertedProjection = projectionMatrix;
+ Vector4f eyeCoords = invertedProjection.invert().transform(clipCoords);
+ return new Vector4f(eyeCoords.x, eyeCoords.y, -1f, 0f);
+ }
+
+ private static Vector2f getNormalisedDeviceCoordinates(float mouseX, float mouseY) {
+ float x = (2.0f * mouseX) / Display.getWidth() - 1f;
+ float y = (2.0f * mouseY) / Display.getHeight() - 1f;
+ return new Vector2f(x, y);
+ }
+
+ private static Vector3f search(Vector3f ray, Vector3f position, int recursionCount) {
+ Vector3f ppos = World.player.getTransform().getPosition();
+ if(Math.abs(position.x-ppos.x) > 4 || Math.abs(position.y-ppos.y) > 4 || Math.abs(position.z-ppos.z) > 4 ) return null;
+ if(recursionCount > 200) return null;
+ int intX = Math.round(position.x);
+ int intY = Math.round(position.y+1);
+ int intZ = Math.round(position.z);
+ if(World.getBlock(intX, intY, intZ) != Cube.AIR && World.getBlock(intX, intY, intZ) != 17)
+ return new Vector3f(intX,intY,intZ);
+ placePos = new Vector3f(intX,intY,intZ);
+ return search(ray,new Vector3f(position.x+ray.x/4,position.y+ray.y/4,position.z+ray.z/4), recursionCount++);
+ }
+
+}
diff --git a/src/main/java/net/tylermurphy/Minecraft/Util/ResourceManager.java b/src/main/java/net/tylermurphy/Minecraft/Util/ResourceManager.java new file mode 100755 index 0000000..fc6f96f --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Util/ResourceManager.java @@ -0,0 +1,130 @@ +package net.tylermurphy.Minecraft.Util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+import net.tylermurphy.Minecraft.Main;
+
+public class ResourceManager {
+
+ static String saveName;
+
+ protected static void init(String saveName) {
+ ResourceManager.saveName = saveName;
+ }
+
+ private static byte[] compress(byte[] data){
+ ByteArrayOutputStream baos = null;
+ Deflater dfl = new Deflater();
+ dfl.setLevel(Deflater.BEST_COMPRESSION);
+ dfl.setInput(data);
+ dfl.finish();
+ baos = new ByteArrayOutputStream();
+ byte[] tmp = new byte[4*1024];
+ try {
+ while(!dfl.finished()) {
+ int size = dfl.deflate(tmp);
+ baos.write(tmp, 0, size);
+ }
+ } catch(Exception e) {
+
+ } finally {
+ try {
+ if(baos != null) baos.close();
+ } catch(Exception e) {}
+ }
+ return baos.toByteArray();
+ }
+
+ protected static byte[] decompress(byte[] data){
+ ByteArrayOutputStream baos = null;
+ Inflater ifl = new Inflater();
+ ifl.setInput(data);
+ baos = new ByteArrayOutputStream();
+ byte[] tmp = new byte[4*1024];
+ try {
+ while(!ifl.finished()) {
+ int size = ifl.inflate(tmp);
+ baos.write(tmp, 0, size);
+ }
+ } catch(Exception e) {
+
+ } finally {
+ try {
+ if(baos != null) baos.close();
+ } catch(Exception e) {}
+ }
+ return baos.toByteArray();
+ }
+
+ public static byte[][][] expandArray(byte[] data) {
+ byte[] result = decompress(data);
+ byte[][][] cubes = new byte[16][256][16];
+ for (int x = 0 ; x != 16 ; x++) {
+ for (int y = 0 ; y != 256 ; y++) {
+ for (int z = 0 ; z != 16 ; z++) {
+ cubes[x][y][z] = result[256 * 16 * x + 16 * y + z];
+ }
+ }
+ }
+ return cubes;
+ }
+
+ public static byte[] flattenArray(byte[][][] cubes) {
+ byte[] data = new byte[16*256*16];
+ for (int x = 0 ; x != 16 ; x++) {
+ for (int y = 0 ; y != 256 ; y++) {
+ for (int z = 0 ; z != 16 ; z++) {
+ data[256 * 16 * x + 16 * y + z] = cubes[x][y][z];
+ }
+ }
+ }
+ byte[] result = compress(data);
+ return result;
+ }
+
+ public static Object loadObject(String pass_path, String fileName) {
+ String path = Constants.SAVES_LOCATION+"/"+Main.currentWorld+"/"+pass_path+"/";
+ ObjectInputStream is = null;
+ try {
+ is = new ObjectInputStream(new FileInputStream(new File(path+fileName)));
+ Object object = is.readObject();
+ is.close();
+ return object;
+ } catch(Exception e) {
+ } finally {
+ try {
+ if(is!=null) is.close();
+ } catch(Exception e) {
+ }
+ }
+ return null;
+ }
+
+ public static void saveObject(String pass_path, String fileName, Object o) {
+ String path = Constants.SAVES_LOCATION+"/"+Main.currentWorld+"/"+pass_path+"/";
+ ObjectOutputStream os = null;
+ try {
+ File folder = new File(path);
+ folder.mkdirs();
+ File file = new File(path+fileName);
+ if(!file.exists()) file.createNewFile();
+ os = new ObjectOutputStream(new FileOutputStream(file));
+ os.writeObject(o);
+ os.close();
+ } catch(Exception e) {
+
+ } finally {
+ try {
+ if(os!=null) os.close();
+ } catch(Exception e) {}
+ }
+ }
+
+}
|