commit aa18145fcacd2037f8b6e76ad728a14682a14cde Author: josua Date: Wed Aug 21 14:04:31 2019 +1000 Initial Commit diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..cfd3392 --- /dev/null +++ b/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/.project b/.project new file mode 100644 index 0000000..b64f5ea --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + ShooterGame + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..3a21537 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/src/shootergame/Main.java b/src/shootergame/Main.java new file mode 100644 index 0000000..9457f28 --- /dev/null +++ b/src/shootergame/Main.java @@ -0,0 +1,29 @@ +package shootergame; + +import mainloop.manager.MainloopManager; +import shootergame.display.DisplayWindow; +import shootergame.init.Textures; +import shootergame.mainloop.MainloopEventHandler; + +public class Main +{ + public static MainloopManager mainloop; + public static DisplayWindow window; + + public static void main(String[] args) + { + // Create the mainloop + mainloop = new MainloopManager(MainloopEventHandler.MAINLOOP_EVENT_HANDLER); + mainloop.register(MainloopEventHandler.MAINLOOP_EVENT_HANDLER); + + // Create the display + window = new DisplayWindow("ShooterGame"); + window.init(); + + // Initialize the textures + Textures.initTextures(window); + + // Start the mainloop + mainloop.start(); + } +} diff --git a/src/shootergame/display/DisplayRender.java b/src/shootergame/display/DisplayRender.java new file mode 100644 index 0000000..f4a43f2 --- /dev/null +++ b/src/shootergame/display/DisplayRender.java @@ -0,0 +1,35 @@ +package shootergame.display; + +import static org.lwjgl.opengl.GL11.*; + +import org.lwjgl.opengl.GL; + +import shootergame.init.Textures; +import shootergame.init.Tiles; +import shootergame.util.gl.GlHelpers; +import shootergame.util.math.vec.Vec2i; + +public class DisplayRender +{ + public static void render(int w, int h) + { + // Setup GL and clear the colour + GL.createCapabilities(); + glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, w, h); + + // Enable some stuff + GlHelpers.enableTexture2d(); + + // Set the colour to white + GlHelpers.color4(1, 1, 1, 1); + + // Bind the texmap + Textures.texmap.bindTexture(); + + Tiles.GRASS.render(new Vec2i(0, 0)); + + // Unbind the texmap + Textures.texmap.unbindTexture(); + } +} diff --git a/src/shootergame/display/DisplayWindow.java b/src/shootergame/display/DisplayWindow.java new file mode 100644 index 0000000..0ef8770 --- /dev/null +++ b/src/shootergame/display/DisplayWindow.java @@ -0,0 +1,129 @@ +package shootergame.display; + +import java.nio.IntBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.GL11; + +import mainloop.task.IMainloopTask; +import shootergame.Main; +import shootergame.input.CursorEnterCallback; +import shootergame.input.CursorPosCallback; +import shootergame.input.KeyCallback; +import shootergame.input.KeyCharCallback; +import shootergame.input.MouseButtonCallback; +import shootergame.mainloop.MainloopEventHandler; +import shootergame.util.gl.GlHelpers; + +public class DisplayWindow implements IMainloopTask +{ + private String name; + private long window; + private int width; + private int height; + + public int getWidth() { + return this.width; + } + + public int getHeight() { + return this.height; + } + + public DisplayWindow(String name) + { + this.name = name; + } + + public void init() + { + // Initialize GLFW + if(!GLFW.glfwInit()) + throw new RuntimeException("Failed to initialize GLFW"); + + // Get the monitor size + IntBuffer w = BufferUtils.createIntBuffer(1); + IntBuffer h = BufferUtils.createIntBuffer(1); + long monitor = GLFW.glfwGetPrimaryMonitor(); + GLFW.glfwGetMonitorPhysicalSize(monitor, w, h); + this.width = w.get()*4; + this.height = h.get()*4; + + // Set the window hint + GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE); + + // Create the window + this.window = GLFW.glfwCreateWindow(this.width, this.height, this.name, 0, 0); + + // Has the window been created + if(this.window == 0) { + System.err.println("Failed to create the window"); + } + + // Set the key handlers + GLFW.glfwSetKeyCallback(this.window, new KeyCallback()); + GLFW.glfwSetCursorPosCallback(this.window, new CursorPosCallback()); + GLFW.glfwSetCharCallback(this.window, new KeyCharCallback()); + GLFW.glfwSetCursorEnterCallback(this.window, new CursorEnterCallback()); + GLFW.glfwSetMouseButtonCallback(this.window, new MouseButtonCallback()); + + // Show the window + GLFW.glfwShowWindow(this.window); + + // Register the display event loop + Main.mainloop.register(this); + } + + public void render() + { + // Make the context current + this.makeContextCurrent(); + + // Set the framebuffer size + int w[] = {0}; + int h[] = {0}; + GLFW.glfwGetFramebufferSize(this.window, w, h); + + // Render everything + DisplayRender.render(w[0], h[0]); + + // Check if the matrix count is ok + GlHelpers.checkMatrixCount(); + + // Swap the framebuffers and poll events + this.swapBuffers(); + this.pollEvents(); + } + + public void swapBuffers() { + GLFW.glfwSwapBuffers(this.window); + } + + public void pollEvents() { + GLFW.glfwPollEvents(); + } + + public void makeContextCurrent() { + GLFW.glfwMakeContextCurrent(this.window); + } + + public boolean shouldClose() { + return GLFW.glfwWindowShouldClose(this.window); + } + + @Override + public boolean MainLoopDelay(long millis) { + return millis > MainloopEventHandler.MAINLOOP_EVENT_HANDLER.mspf; + } + + @Override + public boolean MainLoopRepeat() { + return true; + } + + @Override + public void MainLoopUpdate() { + this.render(); + } +} diff --git a/src/shootergame/init/Textures.java b/src/shootergame/init/Textures.java new file mode 100644 index 0000000..cdeda90 --- /dev/null +++ b/src/shootergame/init/Textures.java @@ -0,0 +1,29 @@ +package shootergame.init; + +import java.util.ArrayList; + +import org.lwjgl.opengl.GL; + +import shootergame.display.DisplayWindow; +import shootergame.util.gl.texture.TextureMap; +import shootergame.util.gl.texture.TextureReference; +import shootergame.util.gl.texture.TextureReferenceAnimation; + +public class Textures +{ + public static void initTextures(DisplayWindow window) + { + // Make the context current + window.makeContextCurrent(); + GL.createCapabilities(); + + // Initiaize all the textures + texmap.init(); + } + + public static final ArrayList animations = new ArrayList(); + + public static final TextureMap texmap = new TextureMap("/home/josua/eclipse-workspace/ShooterGame/src/shootergame/resources/texmap.png"); + + public static final TextureReference TILE_GRASS = texmap.getTextureReference(0, 0, 16, 16); +} diff --git a/src/shootergame/init/Tiles.java b/src/shootergame/init/Tiles.java new file mode 100644 index 0000000..885c823 --- /dev/null +++ b/src/shootergame/init/Tiles.java @@ -0,0 +1,9 @@ +package shootergame.init; + +import shootergame.tiles.Tile; +import shootergame.tiles.TileGrass; + +public class Tiles +{ + public static final Tile GRASS = new TileGrass("grass"); +} diff --git a/src/shootergame/input/CursorEnterCallback.java b/src/shootergame/input/CursorEnterCallback.java new file mode 100644 index 0000000..e8449b3 --- /dev/null +++ b/src/shootergame/input/CursorEnterCallback.java @@ -0,0 +1,14 @@ +package shootergame.input; + +import org.lwjgl.glfw.GLFWCursorEnterCallbackI; + +public class CursorEnterCallback implements GLFWCursorEnterCallbackI +{ + + @Override + public void invoke(long arg0, boolean arg1) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/shootergame/input/CursorPosCallback.java b/src/shootergame/input/CursorPosCallback.java new file mode 100644 index 0000000..d7e7840 --- /dev/null +++ b/src/shootergame/input/CursorPosCallback.java @@ -0,0 +1,14 @@ +package shootergame.input; + +import org.lwjgl.glfw.GLFWCursorPosCallbackI; + +public class CursorPosCallback implements GLFWCursorPosCallbackI +{ + + @Override + public void invoke(long arg0, double arg1, double arg2) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/shootergame/input/KeyCallback.java b/src/shootergame/input/KeyCallback.java new file mode 100644 index 0000000..2a864f1 --- /dev/null +++ b/src/shootergame/input/KeyCallback.java @@ -0,0 +1,14 @@ +package shootergame.input; + +import org.lwjgl.glfw.GLFWKeyCallbackI; + +public class KeyCallback implements GLFWKeyCallbackI +{ + + @Override + public void invoke(long arg0, int arg1, int arg2, int arg3, int arg4) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/shootergame/input/KeyCharCallback.java b/src/shootergame/input/KeyCharCallback.java new file mode 100644 index 0000000..a4b7f9a --- /dev/null +++ b/src/shootergame/input/KeyCharCallback.java @@ -0,0 +1,14 @@ +package shootergame.input; + +import org.lwjgl.glfw.GLFWCharCallbackI; + +public class KeyCharCallback implements GLFWCharCallbackI +{ + + @Override + public void invoke(long arg0, int arg1) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/shootergame/input/MouseButtonCallback.java b/src/shootergame/input/MouseButtonCallback.java new file mode 100644 index 0000000..0b237e0 --- /dev/null +++ b/src/shootergame/input/MouseButtonCallback.java @@ -0,0 +1,14 @@ +package shootergame.input; + +import org.lwjgl.glfw.GLFWMouseButtonCallbackI; + +public class MouseButtonCallback implements GLFWMouseButtonCallbackI +{ + + @Override + public void invoke(long arg0, int arg1, int arg2, int arg3) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/shootergame/mainloop/MainloopEventHandler.java b/src/shootergame/mainloop/MainloopEventHandler.java new file mode 100644 index 0000000..7d5ace8 --- /dev/null +++ b/src/shootergame/mainloop/MainloopEventHandler.java @@ -0,0 +1,51 @@ +package shootergame.mainloop; + +import mainloop.event.IMainloopEvent; +import mainloop.task.IMainloopTask; +import shootergame.Main; + +public class MainloopEventHandler implements IMainloopEvent, IMainloopTask +{ + public static final MainloopEventHandler MAINLOOP_EVENT_HANDLER = new MainloopEventHandler(); + + public long mspf = 1000/60; + + @Override + public void onClose() { + System.out.println("Mainloop closed normally"); + } + + @Override + public void onEarly() { + mspf -= 1; + if(mspf < 1) mspf = 1; + } + + @Override + public void onLate() { + mspf += 1; + } + + @Override + public void onStart() { + System.out.println("Mainloop started"); + } + + @Override + public boolean MainLoopDelay(long millis) { + return millis > 1; + } + + @Override + public boolean MainLoopRepeat() { + return true; + } + + @Override + public void MainLoopUpdate() + { + // Stop the mainloop if the window should close + if(Main.window.shouldClose()) Main.mainloop.stop(); + } + +} diff --git a/src/shootergame/resources/texmap.png b/src/shootergame/resources/texmap.png new file mode 100644 index 0000000..d6973fa Binary files /dev/null and b/src/shootergame/resources/texmap.png differ diff --git a/src/shootergame/tiles/Tile.java b/src/shootergame/tiles/Tile.java new file mode 100644 index 0000000..9816529 --- /dev/null +++ b/src/shootergame/tiles/Tile.java @@ -0,0 +1,19 @@ +package shootergame.tiles; + +import shootergame.util.math.vec.Vec2i; + +public class Tile +{ + private String id; + + public Tile(String id) { + this.id = id; + } + + public String getID() { + return this.id; + } + + public void render(Vec2i pos) { + } +} diff --git a/src/shootergame/tiles/TileFlat.java b/src/shootergame/tiles/TileFlat.java new file mode 100644 index 0000000..0427ace --- /dev/null +++ b/src/shootergame/tiles/TileFlat.java @@ -0,0 +1,30 @@ +package shootergame.tiles; + +import shootergame.util.gl.GlHelpers; +import shootergame.util.gl.texture.TextureReference; +import shootergame.util.math.vec.Vec2i; + +public class TileFlat extends Tile +{ + private TextureReference tex; + + public TileFlat(String id, TextureReference tex) { + super(id); + this.tex = tex; + } + + @Override + public void render(Vec2i pos) + { + // Call super + super.render(pos); + + // Render the tile + GlHelpers.begin(); + tex.texCoord(0, 0); GlHelpers.vertex2(pos.x+0, pos.y+0); + tex.texCoord(1, 0); GlHelpers.vertex2(pos.x+1, pos.y+0); + tex.texCoord(1, 1); GlHelpers.vertex2(pos.x+1, pos.y+1); + tex.texCoord(0, 1); GlHelpers.vertex2(pos.x+0, pos.y+1); + GlHelpers.end(); + } +} diff --git a/src/shootergame/tiles/TileGrass.java b/src/shootergame/tiles/TileGrass.java new file mode 100644 index 0000000..00b9798 --- /dev/null +++ b/src/shootergame/tiles/TileGrass.java @@ -0,0 +1,12 @@ +package shootergame.tiles; + +import shootergame.init.Textures; + +public class TileGrass extends TileFlat +{ + + public TileGrass(String id) { + super(id, Textures.TILE_GRASS); + } + +} diff --git a/src/shootergame/util/gl/GlHelpers.java b/src/shootergame/util/gl/GlHelpers.java new file mode 100644 index 0000000..565d477 --- /dev/null +++ b/src/shootergame/util/gl/GlHelpers.java @@ -0,0 +1,108 @@ +package shootergame.util.gl; + +import static org.lwjgl.opengl.GL11.*; + +import shootergame.Main; +import shootergame.display.DisplayRender; + +public class GlHelpers +{ + private static int MATRIX_COUNT = 0; + + public static void checkMatrixCount() { + if(MATRIX_COUNT != 0) { + MATRIX_COUNT = 0; + System.err.println("Matrix count is unbalanced!"); + } + } + + public static void begin() { + glBegin(GL_QUADS); + } + + public static void end() { + glEnd(); + } + + public static void vertex3(float x, float y, float z) { + glVertex3f(x, y, z); + } + + public static void vertex2(float x, float y) { + glVertex2f(x/Main.window.getWidth()*100, y/Main.window.getHeight()*100); + } + + public static void color3(float r, float g, float b) { + glColor3f(r, g, b); + } + + public static void color4(float r, float g, float b, float a) { + glColor4f(r, g, b, a); + } + + public static void rotate(float a, float x, float y, float z) { + glRotatef(a, x, y, z); + } + + public static void translate(float x, float y, float z) { + glTranslatef(x, y, z); + } + + public static void disableCullFace() { + glDisable(GL_CULL_FACE); + } + + public static void enableCullFace() { + glEnable(GL_CULL_FACE); + } + + public static void disableDepthTest() { + glDisable(GL_DEPTH_TEST); + } + + public static void enableDepthTest() { + glEnable(GL_DEPTH_TEST); + } + + public static void disableTexture2d() { + glDisable(GL_TEXTURE_2D); + } + + public static void enableTexture2d() { + glEnable(GL_TEXTURE_2D); + } + + public static void disableAlpha() { + glDisable(GL_ALPHA); + } + + public static void enableAlpha() { + glEnable(GL_ALPHA); + } + + public static void disableBlend() { + glDisable(GL_BLEND); + } + + public static void enableBlend() { + glEnable(GL_BLEND); + } + + public static void popMatrix() { + glPopMatrix(); + MATRIX_COUNT += 1; + } + + public static void pushMatrix() { + glPushMatrix(); + MATRIX_COUNT -= 1; + } + + public static void translate(double x, double y, double z) { + translate((float)x, (float)y, (float)z); + } + + public static void rotate(double a, float x, float y, float z) { + rotate((float)a, x, y, z); + } +} diff --git a/src/shootergame/util/gl/texture/Texture.java b/src/shootergame/util/gl/texture/Texture.java new file mode 100644 index 0000000..0abc8ac --- /dev/null +++ b/src/shootergame/util/gl/texture/Texture.java @@ -0,0 +1,49 @@ +package shootergame.util.gl.texture; + +import java.nio.ByteBuffer; + +import org.lwjgl.stb.STBImage; + +public class Texture +{ + private ByteBuffer texture; + private int width; + private int height; + private int channels; + + public Texture(String path) + { + // Get the width, height, and channels + int width[] = {0}; + int height[] = {0}; + int channels[] = {0}; + + // Load the specified texture + this.texture = STBImage.stbi_load(path, width, height, channels, STBImage.STBI_rgb_alpha); + this.width = width[0]; + this.height = height[0]; + this.channels = channels[0]; + + System.out.println("w:"+this.width+" h:"+this.height+" c:"+this.channels+"\npath: "+path); + } + + public int getWidth() { + return this.width; + } + + public int getHeight() { + return this.height; + } + + public int getChannels() { + return this.channels; + } + + public ByteBuffer getByteBuffer() { + return this.texture; + } + + public void free() { + //STBImage.stbi_image_free(this.texture); + } +} diff --git a/src/shootergame/util/gl/texture/TextureMap.java b/src/shootergame/util/gl/texture/TextureMap.java new file mode 100644 index 0000000..de5ba0c --- /dev/null +++ b/src/shootergame/util/gl/texture/TextureMap.java @@ -0,0 +1,64 @@ +package shootergame.util.gl.texture; + +import static org.lwjgl.opengl.GL11.*; + +public class TextureMap +{ + private int texture_gl; + private String path; + private int max_x; + private int max_y; + + public TextureMap(String path) { + this.path = path; + } + + public void init() + { + // Generate and bind the texture map + this.texture_gl = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, this.texture_gl); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // Load the texture into opengl + Texture texture = new Texture(path); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + texture.getWidth(), texture.getHeight(), + 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.getByteBuffer()); + + // Store the width and height variables + this.max_x = texture.getWidth(); + this.max_y = texture.getHeight(); + + System.out.println("texmap: "+texture_gl); + + // Free the texture + //texture.free(); + } + + public TextureReference getTextureReference(int start_x, int start_y, int end_x, int end_y) { + return new TextureReference(start_x, start_y, end_x, end_y) + { + + @Override + public int getMaxX() { + return max_x; + } + + @Override + public int getMaxY() { + return max_y; + } + + }; + } + + public void bindTexture() { + glBindTexture(GL_TEXTURE_2D, texture_gl); + } + + public void unbindTexture() { + glBindTexture(GL_TEXTURE_2D, 0); + } +} diff --git a/src/shootergame/util/gl/texture/TextureReference.java b/src/shootergame/util/gl/texture/TextureReference.java new file mode 100644 index 0000000..84d22b8 --- /dev/null +++ b/src/shootergame/util/gl/texture/TextureReference.java @@ -0,0 +1,38 @@ +package shootergame.util.gl.texture; + +import static org.lwjgl.opengl.GL11.*; + +import shootergame.util.math.MathHelpers; + +public abstract class TextureReference +{ + private int start_x; + private int start_y; + private int end_x; + private int end_y; + + TextureReference() { + } + + public TextureReference(int start_x, int end_x, int start_y, int end_y) + { + // Save all the specified values + this.start_x = start_x; + this.start_y = start_y; + this.end_x = end_x; + this.end_y = end_y; + } + + public void texCoord(float x, float y) + { + // Create texture coordinates + float cx = (float) ( MathHelpers.map(x, 0, 1, start_x, end_x) / (double) this.getMaxX() ); + float cy = (float) ( MathHelpers.map(y, 0, 1, start_y, end_y) / (double) this.getMaxY() ); + + // Send the coordinates from the texture map to opengl + glTexCoord2f(cx, cy); + } + + public abstract int getMaxX(); + public abstract int getMaxY(); +} diff --git a/src/shootergame/util/gl/texture/TextureReferenceAnimation.java b/src/shootergame/util/gl/texture/TextureReferenceAnimation.java new file mode 100644 index 0000000..9a3b0dc --- /dev/null +++ b/src/shootergame/util/gl/texture/TextureReferenceAnimation.java @@ -0,0 +1,25 @@ +package shootergame.util.gl.texture; + +public abstract class TextureReferenceAnimation extends TextureReference +{ + private TextureReference[] references; + private int upto = 0; + + public TextureReferenceAnimation(TextureReference[] references) + { + this.references = references; + } + + @Override + public void texCoord(float x, float y) { + references[upto].texCoord(x, y); + } + + public void tick() + { + // Cycle through all the textures + upto += 1; + upto %= references.length; + } + +} diff --git a/src/shootergame/util/math/MathHelpers.java b/src/shootergame/util/math/MathHelpers.java new file mode 100644 index 0000000..b6a9ca9 --- /dev/null +++ b/src/shootergame/util/math/MathHelpers.java @@ -0,0 +1,37 @@ +package shootergame.util.math; + +import shootergame.util.math.vec.Vec2d; + +public class MathHelpers +{ + public static double squared(double x) { + return x*x; + } + + public static double pow(int c, double x) + { + double res = 1; + + for(int i=0;i +{ + public T getEmpty(Vec2i pos); +} diff --git a/src/shootergame/util/math/map/Map2D.java b/src/shootergame/util/math/map/Map2D.java new file mode 100644 index 0000000..e66018c --- /dev/null +++ b/src/shootergame/util/math/map/Map2D.java @@ -0,0 +1,88 @@ +package shootergame.util.math.map; + +import java.util.ArrayList; +import java.util.Iterator; + +import shootergame.util.math.vec.Vec2i; + +public class Map2D implements Iterable> +{ + private ArrayList> elements; + private IMap2D map2d_i; + + public Map2D(IMap2D map2d_i) + { + // Store some values + this.map2d_i = map2d_i; + this.elements = new ArrayList>(); + } + + public void set(Vec2i pos, T o) + { + // Loop over the elements + for(Map2DElement e : this.elements) + { + // Set the object if these positions are the same + if(e.pos.equal(pos)) { + e.o = o; + return; + } + } + + // Create an element and add it + Map2DElement e = new Map2DElement(pos, o); + this.elements.add(e); + } + + public T get(Vec2i pos) + { + // Loop over the elements + for(Map2DElement e : this.elements) + { + // Send back the object if these positions are the same + if(e.pos.equal(pos)) { + //System.out.println(1); + return e.o; + } + } + + // Send back an empty (unloaded) chunk + return this.map2d_i.getEmpty(pos); + } + + public void remove(Vec2i pos) + { + // Loop over the elements + for(int i=0;i e = this.elements.get(i); + + // Delete the item if the position is the same + if(e.pos.equal(pos)) { + this.elements.remove(e); + } + } + } + + @Override + public Iterator> iterator() { + return new Iterator>() + { + private int i = 0; + + @Override + public boolean hasNext() { + return i < elements.size(); + } + + @Override + public Map2DElement next() { + Map2DElement o = elements.get(i); + i++; + return o; + } + + }; + } +} diff --git a/src/shootergame/util/math/map/Map2DElement.java b/src/shootergame/util/math/map/Map2DElement.java new file mode 100644 index 0000000..593d620 --- /dev/null +++ b/src/shootergame/util/math/map/Map2DElement.java @@ -0,0 +1,16 @@ +package shootergame.util.math.map; + +import shootergame.util.math.vec.Vec2i; + +public class Map2DElement +{ + public Vec2i pos; + public T o; + + public Map2DElement(Vec2i pos, T o) + { + // Store the specified values + this.pos = pos; + this.o = o; + } +} \ No newline at end of file diff --git a/src/shootergame/util/math/random/OpenSimplexNoise.java b/src/shootergame/util/math/random/OpenSimplexNoise.java new file mode 100644 index 0000000..75f9221 --- /dev/null +++ b/src/shootergame/util/math/random/OpenSimplexNoise.java @@ -0,0 +1,2139 @@ +package shootergame.util.math.random; + +/* + * OpenSimplex Noise in Java. + * by Kurt Spencer + * + * v1.1 (October 5, 2014) + * - Added 2D and 4D implementations. + * - Proper gradient sets for all dimensions, from a + * dimensionally-generalizable scheme with an actual + * rhyme and reason behind it. + * - Removed default permutation array in favor of + * default seed. + * - Changed seed-based constructor to be independent + * of any particular randomization library, so results + * will be the same when ported to other languages. + */ + +public class OpenSimplexNoise { + + private static final double STRETCH_CONSTANT_2D = -0.211324865405187; //(1/Math.sqrt(2+1)-1)/2; + private static final double SQUISH_CONSTANT_2D = 0.366025403784439; //(Math.sqrt(2+1)-1)/2; + private static final double STRETCH_CONSTANT_3D = -1.0 / 6; //(1/Math.sqrt(3+1)-1)/3; + private static final double SQUISH_CONSTANT_3D = 1.0 / 3; //(Math.sqrt(3+1)-1)/3; + private static final double STRETCH_CONSTANT_4D = -0.138196601125011; //(1/Math.sqrt(4+1)-1)/4; + private static final double SQUISH_CONSTANT_4D = 0.309016994374947; //(Math.sqrt(4+1)-1)/4; + + private static final double NORM_CONSTANT_2D = 47; + private static final double NORM_CONSTANT_3D = 103; + private static final double NORM_CONSTANT_4D = 30; + + private static final long DEFAULT_SEED = 0; + + private short[] perm; + private short[] permGradIndex3D; + + public OpenSimplexNoise() { + this(DEFAULT_SEED); + } + + public OpenSimplexNoise(short[] perm) { + this.perm = perm; + permGradIndex3D = new short[256]; + + for (int i = 0; i < 256; i++) { + //Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array. + permGradIndex3D[i] = (short)((perm[i] % (gradients3D.length / 3)) * 3); + } + } + + //Initializes the class using a permutation array generated from a 64-bit seed. + //Generates a proper permutation (i.e. doesn't merely perform N successive pair swaps on a base array) + //Uses a simple 64-bit LCG. + public OpenSimplexNoise(long seed) { + perm = new short[256]; + permGradIndex3D = new short[256]; + short[] source = new short[256]; + for (short i = 0; i < 256; i++) + source[i] = i; + seed = seed * 6364136223846793005l + 1442695040888963407l; + seed = seed * 6364136223846793005l + 1442695040888963407l; + seed = seed * 6364136223846793005l + 1442695040888963407l; + for (int i = 255; i >= 0; i--) { + seed = seed * 6364136223846793005l + 1442695040888963407l; + int r = (int)((seed + 31) % (i + 1)); + if (r < 0) + r += (i + 1); + perm[i] = source[r]; + permGradIndex3D[i] = (short)((perm[i] % (gradients3D.length / 3)) * 3); + source[r] = source[i]; + } + } + + //2D OpenSimplex Noise. + public double eval(double x, double y) { + + //Place input coordinates onto grid. + double stretchOffset = (x + y) * STRETCH_CONSTANT_2D; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + + //Floor to get grid coordinates of rhombus (stretched square) super-cell origin. + int xsb = fastFloor(xs); + int ysb = fastFloor(ys); + + //Skew out to get actual coordinates of rhombus origin. We'll need these later. + double squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + + //Compute grid coordinates relative to rhombus origin. + double xins = xs - xsb; + double yins = ys - ysb; + + //Sum those together to get a value that determines which region we're in. + double inSum = xins + yins; + + //Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + + //We'll be defining these inside the next block and using them afterwards. + double dx_ext, dy_ext; + int xsv_ext, ysv_ext; + + double value = 0; + + //Contribution (1,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_2D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_2D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, dx1, dy1); + } + + //Contribution (0,1) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_2D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_2D; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, dx2, dy2); + } + + if (inSum <= 1) { //We're inside the triangle (2-Simplex) at (0,0) + double zins = 1 - inSum; + if (zins > xins || zins > yins) { //(0,0) is one of the closest two triangular vertices + if (xins > yins) { + xsv_ext = xsb + 1; + ysv_ext = ysb - 1; + dx_ext = dx0 - 1; + dy_ext = dy0 + 1; + } else { + xsv_ext = xsb - 1; + ysv_ext = ysb + 1; + dx_ext = dx0 + 1; + dy_ext = dy0 - 1; + } + } else { //(1,0) and (0,1) are the closest two vertices. + xsv_ext = xsb + 1; + ysv_ext = ysb + 1; + dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; + dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; + } + } else { //We're inside the triangle (2-Simplex) at (1,1) + double zins = 2 - inSum; + if (zins < xins || zins < yins) { //(0,0) is one of the closest two triangular vertices + if (xins > yins) { + xsv_ext = xsb + 2; + ysv_ext = ysb + 0; + dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D; + dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D; + } else { + xsv_ext = xsb + 0; + ysv_ext = ysb + 2; + dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D; + dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D; + } + } else { //(1,0) and (0,1) are the closest two vertices. + dx_ext = dx0; + dy_ext = dy0; + xsv_ext = xsb; + ysv_ext = ysb; + } + xsb += 1; + ysb += 1; + dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; + dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; + } + + //Contribution (0,0) or (1,1) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb, ysb, dx0, dy0); + } + + //Extra Vertex + double attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext; + if (attn_ext > 0) { + attn_ext *= attn_ext; + value += attn_ext * attn_ext * extrapolate(xsv_ext, ysv_ext, dx_ext, dy_ext); + } + + return value / NORM_CONSTANT_2D; + } + + //3D OpenSimplex Noise. + public double eval(double x, double y, double z) { + + //Place input coordinates on simplectic honeycomb. + double stretchOffset = (x + y + z) * STRETCH_CONSTANT_3D; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + double zs = z + stretchOffset; + + //Floor to get simplectic honeycomb coordinates of rhombohedron (stretched cube) super-cell origin. + int xsb = fastFloor(xs); + int ysb = fastFloor(ys); + int zsb = fastFloor(zs); + + //Skew out to get actual coordinates of rhombohedron origin. We'll need these later. + double squishOffset = (xsb + ysb + zsb) * SQUISH_CONSTANT_3D; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + double zb = zsb + squishOffset; + + //Compute simplectic honeycomb coordinates relative to rhombohedral origin. + double xins = xs - xsb; + double yins = ys - ysb; + double zins = zs - zsb; + + //Sum those together to get a value that determines which region we're in. + double inSum = xins + yins + zins; + + //Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + double dz0 = z - zb; + + //We'll be defining these inside the next block and using them afterwards. + double dx_ext0, dy_ext0, dz_ext0; + double dx_ext1, dy_ext1, dz_ext1; + int xsv_ext0, ysv_ext0, zsv_ext0; + int xsv_ext1, ysv_ext1, zsv_ext1; + + double value = 0; + if (inSum <= 1) { //We're inside the tetrahedron (3-Simplex) at (0,0,0) + + //Determine which two of (0,0,1), (0,1,0), (1,0,0) are closest. + byte aPoint = 0x01; + double aScore = xins; + byte bPoint = 0x02; + double bScore = yins; + if (aScore >= bScore && zins > bScore) { + bScore = zins; + bPoint = 0x04; + } else if (aScore < bScore && zins > aScore) { + aScore = zins; + aPoint = 0x04; + } + + //Now we determine the two lattice points not part of the tetrahedron that may contribute. + //This depends on the closest two tetrahedral vertices, including (0,0,0) + double wins = 1 - inSum; + if (wins > aScore || wins > bScore) { //(0,0,0) is one of the closest two tetrahedral vertices. + byte c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. + + if ((c & 0x01) == 0) { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1; + dx_ext1 = dx0; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0; + if ((c & 0x01) == 0) { + ysv_ext1 -= 1; + dy_ext1 += 1; + } else { + ysv_ext0 -= 1; + dy_ext0 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0; + dz_ext1 = dz0 + 1; + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1; + } + } else { //(0,0,0) is not one of the closest two tetrahedral vertices. + byte c = (byte)(aPoint | bPoint); //Our two extra vertices are determined by the closest two. + + if ((c & 0x01) == 0) { + xsv_ext0 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_3D; + dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; + dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysb; + ysv_ext1 = ysb - 1; + dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; + } + } + + //Contribution (0,0,0) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, dx0, dy0, dz0); + } + + //Contribution (1,0,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; + double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); + } + + //Contribution (0,1,0) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; + double dz2 = dz1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); + } + + //Contribution (0,0,1) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); + } + } else if (inSum >= 2) { //We're inside the tetrahedron (3-Simplex) at (1,1,1) + + //Determine which two tetrahedral vertices are the closest, out of (1,1,0), (1,0,1), (0,1,1) but not (1,1,1). + byte aPoint = 0x06; + double aScore = xins; + byte bPoint = 0x05; + double bScore = yins; + if (aScore <= bScore && zins < bScore) { + bScore = zins; + bPoint = 0x03; + } else if (aScore > bScore && zins < aScore) { + aScore = zins; + aPoint = 0x03; + } + + //Now we determine the two lattice points not part of the tetrahedron that may contribute. + //This depends on the closest two tetrahedral vertices, including (1,1,1) + double wins = 3 - inSum; + if (wins < aScore || wins < bScore) { //(1,1,1) is one of the closest two tetrahedral vertices. + byte c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. + + if ((c & 0x01) != 0) { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_3D; + dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; + } else { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_3D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; + if ((c & 0x01) != 0) { + ysv_ext1 += 1; + dy_ext1 -= 1; + } else { + ysv_ext0 += 1; + dy_ext0 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_3D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsb + 1; + zsv_ext1 = zsb + 2; + dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 - 3 * SQUISH_CONSTANT_3D; + } else { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_3D; + } + } else { //(1,1,1) is not one of the closest two tetrahedral vertices. + byte c = (byte)(aPoint & bPoint); //Our two extra vertices are determined by the closest two. + + if ((c & 0x01) != 0) { + xsv_ext0 = xsb + 1; + xsv_ext1 = xsb + 2; + dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; + dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; + } else { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx0 - SQUISH_CONSTANT_3D; + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysb + 1; + ysv_ext1 = ysb + 2; + dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; + } else { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy0 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsb + 1; + zsv_ext1 = zsb + 2; + dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; + } else { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz0 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; + } + } + + //Contribution (1,1,0) + double dx3 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; + double dy3 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; + double dz3 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx3, dy3, dz3); + } + + //Contribution (1,0,1) + double dx2 = dx3; + double dy2 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; + double dz2 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx2, dy2, dz2); + } + + //Contribution (0,1,1) + double dx1 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; + double dy1 = dy3; + double dz1 = dz2; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx1, dy1, dz1); + } + + //Contribution (1,1,1) + dx0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; + dy0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; + dz0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, dx0, dy0, dz0); + } + } else { //We're inside the octahedron (Rectified 3-Simplex) in between. + double aScore; + byte aPoint; + boolean aIsFurtherSide; + double bScore; + byte bPoint; + boolean bIsFurtherSide; + + //Decide between point (0,0,1) and (1,1,0) as closest + double p1 = xins + yins; + if (p1 > 1) { + aScore = p1 - 1; + aPoint = 0x03; + aIsFurtherSide = true; + } else { + aScore = 1 - p1; + aPoint = 0x04; + aIsFurtherSide = false; + } + + //Decide between point (0,1,0) and (1,0,1) as closest + double p2 = xins + zins; + if (p2 > 1) { + bScore = p2 - 1; + bPoint = 0x05; + bIsFurtherSide = true; + } else { + bScore = 1 - p2; + bPoint = 0x02; + bIsFurtherSide = false; + } + + //The closest out of the two (1,0,0) and (0,1,1) will replace the furthest out of the two decided above, if closer. + double p3 = yins + zins; + if (p3 > 1) { + double score = p3 - 1; + if (aScore <= bScore && aScore < score) { + aScore = score; + aPoint = 0x06; + aIsFurtherSide = true; + } else if (aScore > bScore && bScore < score) { + bScore = score; + bPoint = 0x06; + bIsFurtherSide = true; + } + } else { + double score = 1 - p3; + if (aScore <= bScore && aScore < score) { + aScore = score; + aPoint = 0x01; + aIsFurtherSide = false; + } else if (aScore > bScore && bScore < score) { + bScore = score; + bPoint = 0x01; + bIsFurtherSide = false; + } + } + + //Where each of the two closest points are determines how the extra two vertices are calculated. + if (aIsFurtherSide == bIsFurtherSide) { + if (aIsFurtherSide) { //Both closest points on (1,1,1) side + + //One of the two extra points is (1,1,1) + dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; + dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; + dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb + 1; + + //Other extra point is based on the shared axis. + byte c = (byte)(aPoint & bPoint); + if ((c & 0x01) != 0) { + dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; + xsv_ext1 = xsb + 2; + ysv_ext1 = ysb; + zsv_ext1 = zsb; + } else if ((c & 0x02) != 0) { + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; + xsv_ext1 = xsb; + ysv_ext1 = ysb + 2; + zsv_ext1 = zsb; + } else { + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; + xsv_ext1 = xsb; + ysv_ext1 = ysb; + zsv_ext1 = zsb + 2; + } + } else {//Both closest points on (0,0,0) side + + //One of the two extra points is (0,0,0) + dx_ext0 = dx0; + dy_ext0 = dy0; + dz_ext0 = dz0; + xsv_ext0 = xsb; + ysv_ext0 = ysb; + zsv_ext0 = zsb; + + //Other extra point is based on the omitted axis. + byte c = (byte)(aPoint | bPoint); + if ((c & 0x01) == 0) { + dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; + xsv_ext1 = xsb - 1; + ysv_ext1 = ysb + 1; + zsv_ext1 = zsb + 1; + } else if ((c & 0x02) == 0) { + dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; + xsv_ext1 = xsb + 1; + ysv_ext1 = ysb - 1; + zsv_ext1 = zsb + 1; + } else { + dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; + xsv_ext1 = xsb + 1; + ysv_ext1 = ysb + 1; + zsv_ext1 = zsb - 1; + } + } + } else { //One point on (0,0,0) side, one point on (1,1,1) side + byte c1, c2; + if (aIsFurtherSide) { + c1 = aPoint; + c2 = bPoint; + } else { + c1 = bPoint; + c2 = aPoint; + } + + //One contribution is a permutation of (1,1,-1) + if ((c1 & 0x01) == 0) { + dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_3D; + dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; + dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; + xsv_ext0 = xsb - 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb + 1; + } else if ((c1 & 0x02) == 0) { + dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; + dy_ext0 = dy0 + 1 - SQUISH_CONSTANT_3D; + dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb - 1; + zsv_ext0 = zsb + 1; + } else { + dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; + dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; + dz_ext0 = dz0 + 1 - SQUISH_CONSTANT_3D; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb - 1; + } + + //One contribution is a permutation of (0,0,2) + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; + xsv_ext1 = xsb; + ysv_ext1 = ysb; + zsv_ext1 = zsb; + if ((c2 & 0x01) != 0) { + dx_ext1 -= 2; + xsv_ext1 += 2; + } else if ((c2 & 0x02) != 0) { + dy_ext1 -= 2; + ysv_ext1 += 2; + } else { + dz_ext1 -= 2; + zsv_ext1 += 2; + } + } + + //Contribution (1,0,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; + double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); + } + + //Contribution (0,1,0) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; + double dz2 = dz1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); + } + + //Contribution (0,0,1) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); + } + + //Contribution (1,1,0) + double dx4 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; + double dy4 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; + double dz4 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx4, dy4, dz4); + } + + //Contribution (1,0,1) + double dx5 = dx4; + double dy5 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; + double dz5 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5; + if (attn5 > 0) { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx5, dy5, dz5); + } + + //Contribution (0,1,1) + double dx6 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; + double dy6 = dy4; + double dz6 = dz5; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6; + if (attn6 > 0) { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx6, dy6, dz6); + } + } + + //First extra vertex + double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0; + if (attn_ext0 > 0) + { + attn_ext0 *= attn_ext0; + value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, dx_ext0, dy_ext0, dz_ext0); + } + + //Second extra vertex + double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1; + if (attn_ext1 > 0) + { + attn_ext1 *= attn_ext1; + value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, dx_ext1, dy_ext1, dz_ext1); + } + + return value / NORM_CONSTANT_3D; + } + + //4D OpenSimplex Noise. + public double eval(double x, double y, double z, double w) { + + //Place input coordinates on simplectic honeycomb. + double stretchOffset = (x + y + z + w) * STRETCH_CONSTANT_4D; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + double zs = z + stretchOffset; + double ws = w + stretchOffset; + + //Floor to get simplectic honeycomb coordinates of rhombo-hypercube super-cell origin. + int xsb = fastFloor(xs); + int ysb = fastFloor(ys); + int zsb = fastFloor(zs); + int wsb = fastFloor(ws); + + //Skew out to get actual coordinates of stretched rhombo-hypercube origin. We'll need these later. + double squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_CONSTANT_4D; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + double zb = zsb + squishOffset; + double wb = wsb + squishOffset; + + //Compute simplectic honeycomb coordinates relative to rhombo-hypercube origin. + double xins = xs - xsb; + double yins = ys - ysb; + double zins = zs - zsb; + double wins = ws - wsb; + + //Sum those together to get a value that determines which region we're in. + double inSum = xins + yins + zins + wins; + + //Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + double dz0 = z - zb; + double dw0 = w - wb; + + //We'll be defining these inside the next block and using them afterwards. + double dx_ext0, dy_ext0, dz_ext0, dw_ext0; + double dx_ext1, dy_ext1, dz_ext1, dw_ext1; + double dx_ext2, dy_ext2, dz_ext2, dw_ext2; + int xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0; + int xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1; + int xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2; + + double value = 0; + if (inSum <= 1) { //We're inside the pentachoron (4-Simplex) at (0,0,0,0) + + //Determine which two of (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0) are closest. + byte aPoint = 0x01; + double aScore = xins; + byte bPoint = 0x02; + double bScore = yins; + if (aScore >= bScore && zins > bScore) { + bScore = zins; + bPoint = 0x04; + } else if (aScore < bScore && zins > aScore) { + aScore = zins; + aPoint = 0x04; + } + if (aScore >= bScore && wins > bScore) { + bScore = wins; + bPoint = 0x08; + } else if (aScore < bScore && wins > aScore) { + aScore = wins; + aPoint = 0x08; + } + + //Now we determine the three lattice points not part of the pentachoron that may contribute. + //This depends on the closest two pentachoron vertices, including (0,0,0,0) + double uins = 1 - inSum; + if (uins > aScore || uins > bScore) { //(0,0,0,0) is one of the closest two pentachoron vertices. + byte c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. + if ((c & 0x01) == 0) { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx0 + 1; + dx_ext1 = dx_ext2 = dx0; + } else { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy_ext1 = dy_ext2 = dy0; + if ((c & 0x01) == 0x01) { + ysv_ext0 -= 1; + dy_ext0 += 1; + } else { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz_ext1 = dz_ext2 = dz0; + if ((c & 0x03) != 0) { + if ((c & 0x03) == 0x03) { + zsv_ext0 -= 1; + dz_ext0 += 1; + } else { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } else { + zsv_ext2 -= 1; + dz_ext2 += 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1; + } + + if ((c & 0x08) == 0) { + wsv_ext0 = wsv_ext1 = wsb; + wsv_ext2 = wsb - 1; + dw_ext0 = dw_ext1 = dw0; + dw_ext2 = dw0 + 1; + } else { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; + dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1; + } + } else { //(0,0,0,0) is not one of the closest two pentachoron vertices. + byte c = (byte)(aPoint | bPoint); //Our three extra vertices are determined by the closest two. + + if ((c & 0x01) == 0) { + xsv_ext0 = xsv_ext2 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_4D; + dx_ext2 = dx0 - SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + dx_ext1 = dx_ext2 = dx0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy_ext2 = dy0 - SQUISH_CONSTANT_4D; + if ((c & 0x01) == 0x01) { + ysv_ext1 -= 1; + dy_ext1 += 1; + } else { + ysv_ext2 -= 1; + dy_ext2 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy_ext2 = dy0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz_ext2 = dz0 - SQUISH_CONSTANT_4D; + if ((c & 0x03) == 0x03) { + zsv_ext1 -= 1; + dz_ext1 += 1; + } else { + zsv_ext2 -= 1; + dz_ext2 += 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz_ext2 = dz0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) == 0) { + wsv_ext0 = wsv_ext1 = wsb; + wsv_ext2 = wsb - 1; + dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - SQUISH_CONSTANT_4D; + dw_ext2 = dw0 + 1 - SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; + dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw_ext2 = dw0 - 1 - SQUISH_CONSTANT_4D; + } + } + + //Contribution (0,0,0,0) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 0, dx0, dy0, dz0, dw0); + } + + //Contribution (1,0,0,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; + double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; + double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); + } + + //Contribution (0,1,0,0) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; + double dz2 = dz1; + double dw2 = dw1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); + } + + //Contribution (0,0,1,0) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; + double dw3 = dw1; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); + } + + //Contribution (0,0,0,1) + double dx4 = dx2; + double dy4 = dy1; + double dz4 = dz1; + double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); + } + } else if (inSum >= 3) { //We're inside the pentachoron (4-Simplex) at (1,1,1,1) + //Determine which two of (1,1,1,0), (1,1,0,1), (1,0,1,1), (0,1,1,1) are closest. + byte aPoint = 0x0E; + double aScore = xins; + byte bPoint = 0x0D; + double bScore = yins; + if (aScore <= bScore && zins < bScore) { + bScore = zins; + bPoint = 0x0B; + } else if (aScore > bScore && zins < aScore) { + aScore = zins; + aPoint = 0x0B; + } + if (aScore <= bScore && wins < bScore) { + bScore = wins; + bPoint = 0x07; + } else if (aScore > bScore && wins < aScore) { + aScore = wins; + aPoint = 0x07; + } + + //Now we determine the three lattice points not part of the pentachoron that may contribute. + //This depends on the closest two pentachoron vertices, including (0,0,0,0) + double uins = 4 - inSum; + if (uins < aScore || uins < bScore) { //(1,1,1,1) is one of the closest two pentachoron vertices. + byte c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. + + if ((c & 0x01) != 0) { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx0 - 2 - 4 * SQUISH_CONSTANT_4D; + dx_ext1 = dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; + if ((c & 0x01) != 0) { + ysv_ext1 += 1; + dy_ext1 -= 1; + } else { + ysv_ext0 += 1; + dy_ext0 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; + if ((c & 0x03) != 0x03) { + if ((c & 0x03) == 0) { + zsv_ext0 += 1; + dz_ext0 -= 1; + } else { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } else { + zsv_ext2 += 1; + dz_ext2 -= 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) != 0) { + wsv_ext0 = wsv_ext1 = wsb + 1; + wsv_ext2 = wsb + 2; + dw_ext0 = dw_ext1 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 2 - 4 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; + dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * SQUISH_CONSTANT_4D; + } + } else { //(1,1,1,1) is not one of the closest two pentachoron vertices. + byte c = (byte)(aPoint & bPoint); //Our three extra vertices are determined by the closest two. + + if ((c & 0x01) != 0) { + xsv_ext0 = xsv_ext2 = xsb + 1; + xsv_ext1 = xsb + 2; + dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; + dx_ext2 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; + dx_ext1 = dx_ext2 = dx0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy_ext2 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c & 0x01) != 0) { + ysv_ext2 += 1; + dy_ext2 -= 1; + } else { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy_ext2 = dy0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz_ext2 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c & 0x03) != 0) { + zsv_ext2 += 1; + dz_ext2 -= 1; + } else { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz_ext2 = dz0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) != 0) { + wsv_ext0 = wsv_ext1 = wsb + 1; + wsv_ext2 = wsb + 2; + dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; + dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw_ext2 = dw0 - 3 * SQUISH_CONSTANT_4D; + } + } + + //Contribution (1,1,1,0) + double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); + } + + //Contribution (1,1,0,1) + double dx3 = dx4; + double dy3 = dy4; + double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; + double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); + } + + //Contribution (1,0,1,1) + double dx2 = dx4; + double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; + double dz2 = dz4; + double dw2 = dw3; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); + } + + //Contribution (0,1,1,1) + double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; + double dz1 = dz4; + double dy1 = dy4; + double dw1 = dw3; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); + } + + //Contribution (1,1,1,1) + dx0 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; + dy0 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; + dz0 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; + dw0 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 1, dx0, dy0, dz0, dw0); + } + } else if (inSum <= 2) { //We're inside the first dispentachoron (Rectified 4-Simplex) + double aScore; + byte aPoint; + boolean aIsBiggerSide = true; + double bScore; + byte bPoint; + boolean bIsBiggerSide = true; + + //Decide between (1,1,0,0) and (0,0,1,1) + if (xins + yins > zins + wins) { + aScore = xins + yins; + aPoint = 0x03; + } else { + aScore = zins + wins; + aPoint = 0x0C; + } + + //Decide between (1,0,1,0) and (0,1,0,1) + if (xins + zins > yins + wins) { + bScore = xins + zins; + bPoint = 0x05; + } else { + bScore = yins + wins; + bPoint = 0x0A; + } + + //Closer between (1,0,0,1) and (0,1,1,0) will replace the further of a and b, if closer. + if (xins + wins > yins + zins) { + double score = xins + wins; + if (aScore >= bScore && score > bScore) { + bScore = score; + bPoint = 0x09; + } else if (aScore < bScore && score > aScore) { + aScore = score; + aPoint = 0x09; + } + } else { + double score = yins + zins; + if (aScore >= bScore && score > bScore) { + bScore = score; + bPoint = 0x06; + } else if (aScore < bScore && score > aScore) { + aScore = score; + aPoint = 0x06; + } + } + + //Decide if (1,0,0,0) is closer. + double p1 = 2 - inSum + xins; + if (aScore >= bScore && p1 > bScore) { + bScore = p1; + bPoint = 0x01; + bIsBiggerSide = false; + } else if (aScore < bScore && p1 > aScore) { + aScore = p1; + aPoint = 0x01; + aIsBiggerSide = false; + } + + //Decide if (0,1,0,0) is closer. + double p2 = 2 - inSum + yins; + if (aScore >= bScore && p2 > bScore) { + bScore = p2; + bPoint = 0x02; + bIsBiggerSide = false; + } else if (aScore < bScore && p2 > aScore) { + aScore = p2; + aPoint = 0x02; + aIsBiggerSide = false; + } + + //Decide if (0,0,1,0) is closer. + double p3 = 2 - inSum + zins; + if (aScore >= bScore && p3 > bScore) { + bScore = p3; + bPoint = 0x04; + bIsBiggerSide = false; + } else if (aScore < bScore && p3 > aScore) { + aScore = p3; + aPoint = 0x04; + aIsBiggerSide = false; + } + + //Decide if (0,0,0,1) is closer. + double p4 = 2 - inSum + wins; + if (aScore >= bScore && p4 > bScore) { + bScore = p4; + bPoint = 0x08; + bIsBiggerSide = false; + } else if (aScore < bScore && p4 > aScore) { + aScore = p4; + aPoint = 0x08; + aIsBiggerSide = false; + } + + //Where each of the two closest points are determines how the extra three vertices are calculated. + if (aIsBiggerSide == bIsBiggerSide) { + if (aIsBiggerSide) { //Both closest points on the bigger side + byte c1 = (byte)(aPoint | bPoint); + byte c2 = (byte)(aPoint & bPoint); + if ((c1 & 0x01) == 0) { + xsv_ext0 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 3 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 + 1 - 2 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x02) == 0) { + ysv_ext0 = ysb; + ysv_ext1 = ysb - 1; + dy_ext0 = dy0 - 3 * SQUISH_CONSTANT_4D; + dy_ext1 = dy0 + 1 - 2 * SQUISH_CONSTANT_4D; + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + dy_ext1 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x04) == 0) { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0 - 3 * SQUISH_CONSTANT_4D; + dz_ext1 = dz0 + 1 - 2 * SQUISH_CONSTANT_4D; + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + dz_ext1 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x08) == 0) { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - 3 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 + 1 - 2 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + } + + //One combination is a permutation of (0,0,0,2) based on c2 + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; + if ((c2 & 0x01) != 0) { + xsv_ext2 += 2; + dx_ext2 -= 2; + } else if ((c2 & 0x02) != 0) { + ysv_ext2 += 2; + dy_ext2 -= 2; + } else if ((c2 & 0x04) != 0) { + zsv_ext2 += 2; + dz_ext2 -= 2; + } else { + wsv_ext2 += 2; + dw_ext2 -= 2; + } + + } else { //Both closest points on the smaller side + //One of the two extra points is (0,0,0,0) + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0; + dy_ext2 = dy0; + dz_ext2 = dz0; + dw_ext2 = dw0; + + //Other two points are based on the omitted axes. + byte c = (byte)(aPoint | bPoint); + + if ((c & 0x01) == 0) { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; + if ((c & 0x01) == 0x01) + { + ysv_ext0 -= 1; + dy_ext0 += 1; + } else { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; + if ((c & 0x03) == 0x03) + { + zsv_ext0 -= 1; + dz_ext0 += 1; + } else { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) == 0) + { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - SQUISH_CONSTANT_4D; + dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; + } + + } + } else { //One point on each "side" + byte c1, c2; + if (aIsBiggerSide) { + c1 = aPoint; + c2 = bPoint; + } else { + c1 = bPoint; + c2 = aPoint; + } + + //Two contributions are the bigger-sided point with each 0 replaced with -1. + if ((c1 & 0x01) == 0) { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; + if ((c1 & 0x01) == 0x01) { + ysv_ext0 -= 1; + dy_ext0 += 1; + } else { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x04) == 0) { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; + if ((c1 & 0x03) == 0x03) { + zsv_ext0 -= 1; + dz_ext0 += 1; + } else { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x08) == 0) { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - SQUISH_CONSTANT_4D; + dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; + } + + //One contribution is a permutation of (0,0,0,2) based on the smaller-sided point + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; + if ((c2 & 0x01) != 0) { + xsv_ext2 += 2; + dx_ext2 -= 2; + } else if ((c2 & 0x02) != 0) { + ysv_ext2 += 2; + dy_ext2 -= 2; + } else if ((c2 & 0x04) != 0) { + zsv_ext2 += 2; + dz_ext2 -= 2; + } else { + wsv_ext2 += 2; + dw_ext2 -= 2; + } + } + + //Contribution (1,0,0,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; + double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; + double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); + } + + //Contribution (0,1,0,0) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; + double dz2 = dz1; + double dw2 = dw1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); + } + + //Contribution (0,0,1,0) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; + double dw3 = dw1; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); + } + + //Contribution (0,0,0,1) + double dx4 = dx2; + double dy4 = dy1; + double dz4 = dz1; + double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); + } + + //Contribution (1,1,0,0) + double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; + if (attn5 > 0) { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); + } + + //Contribution (1,0,1,0) + double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; + if (attn6 > 0) { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); + } + + //Contribution (1,0,0,1) + double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; + if (attn7 > 0) { + attn7 *= attn7; + value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); + } + + //Contribution (0,1,1,0) + double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; + if (attn8 > 0) { + attn8 *= attn8; + value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); + } + + //Contribution (0,1,0,1) + double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; + if (attn9 > 0) { + attn9 *= attn9; + value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); + } + + //Contribution (0,0,1,1) + double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; + if (attn10 > 0) { + attn10 *= attn10; + value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); + } + } else { //We're inside the second dispentachoron (Rectified 4-Simplex) + double aScore; + byte aPoint; + boolean aIsBiggerSide = true; + double bScore; + byte bPoint; + boolean bIsBiggerSide = true; + + //Decide between (0,0,1,1) and (1,1,0,0) + if (xins + yins < zins + wins) { + aScore = xins + yins; + aPoint = 0x0C; + } else { + aScore = zins + wins; + aPoint = 0x03; + } + + //Decide between (0,1,0,1) and (1,0,1,0) + if (xins + zins < yins + wins) { + bScore = xins + zins; + bPoint = 0x0A; + } else { + bScore = yins + wins; + bPoint = 0x05; + } + + //Closer between (0,1,1,0) and (1,0,0,1) will replace the further of a and b, if closer. + if (xins + wins < yins + zins) { + double score = xins + wins; + if (aScore <= bScore && score < bScore) { + bScore = score; + bPoint = 0x06; + } else if (aScore > bScore && score < aScore) { + aScore = score; + aPoint = 0x06; + } + } else { + double score = yins + zins; + if (aScore <= bScore && score < bScore) { + bScore = score; + bPoint = 0x09; + } else if (aScore > bScore && score < aScore) { + aScore = score; + aPoint = 0x09; + } + } + + //Decide if (0,1,1,1) is closer. + double p1 = 3 - inSum + xins; + if (aScore <= bScore && p1 < bScore) { + bScore = p1; + bPoint = 0x0E; + bIsBiggerSide = false; + } else if (aScore > bScore && p1 < aScore) { + aScore = p1; + aPoint = 0x0E; + aIsBiggerSide = false; + } + + //Decide if (1,0,1,1) is closer. + double p2 = 3 - inSum + yins; + if (aScore <= bScore && p2 < bScore) { + bScore = p2; + bPoint = 0x0D; + bIsBiggerSide = false; + } else if (aScore > bScore && p2 < aScore) { + aScore = p2; + aPoint = 0x0D; + aIsBiggerSide = false; + } + + //Decide if (1,1,0,1) is closer. + double p3 = 3 - inSum + zins; + if (aScore <= bScore && p3 < bScore) { + bScore = p3; + bPoint = 0x0B; + bIsBiggerSide = false; + } else if (aScore > bScore && p3 < aScore) { + aScore = p3; + aPoint = 0x0B; + aIsBiggerSide = false; + } + + //Decide if (1,1,1,0) is closer. + double p4 = 3 - inSum + wins; + if (aScore <= bScore && p4 < bScore) { + bScore = p4; + bPoint = 0x07; + bIsBiggerSide = false; + } else if (aScore > bScore && p4 < aScore) { + aScore = p4; + aPoint = 0x07; + aIsBiggerSide = false; + } + + //Where each of the two closest points are determines how the extra three vertices are calculated. + if (aIsBiggerSide == bIsBiggerSide) { + if (aIsBiggerSide) { //Both closest points on the bigger side + byte c1 = (byte)(aPoint & bPoint); + byte c2 = (byte)(aPoint | bPoint); + + //Two contributions are permutations of (0,0,0,1) and (0,0,0,2) based on c1 + xsv_ext0 = xsv_ext1 = xsb; + ysv_ext0 = ysv_ext1 = ysb; + zsv_ext0 = zsv_ext1 = zsb; + wsv_ext0 = wsv_ext1 = wsb; + dx_ext0 = dx0 - SQUISH_CONSTANT_4D; + dy_ext0 = dy0 - SQUISH_CONSTANT_4D; + dz_ext0 = dz0 - SQUISH_CONSTANT_4D; + dw_ext0 = dw0 - SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 2 * SQUISH_CONSTANT_4D; + if ((c1 & 0x01) != 0) { + xsv_ext0 += 1; + dx_ext0 -= 1; + xsv_ext1 += 2; + dx_ext1 -= 2; + } else if ((c1 & 0x02) != 0) { + ysv_ext0 += 1; + dy_ext0 -= 1; + ysv_ext1 += 2; + dy_ext1 -= 2; + } else if ((c1 & 0x04) != 0) { + zsv_ext0 += 1; + dz_ext0 -= 1; + zsv_ext1 += 2; + dz_ext1 -= 2; + } else { + wsv_ext0 += 1; + dw_ext0 -= 1; + wsv_ext1 += 2; + dw_ext1 -= 2; + } + + //One contribution is a permutation of (1,1,1,-1) based on c2 + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + if ((c2 & 0x01) == 0) { + xsv_ext2 -= 2; + dx_ext2 += 2; + } else if ((c2 & 0x02) == 0) { + ysv_ext2 -= 2; + dy_ext2 += 2; + } else if ((c2 & 0x04) == 0) { + zsv_ext2 -= 2; + dz_ext2 += 2; + } else { + wsv_ext2 -= 2; + dw_ext2 += 2; + } + } else { //Both closest points on the smaller side + //One of the two extra points is (1,1,1,1) + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; + + //Other two points are based on the shared axes. + byte c = (byte)(aPoint & bPoint); + + if ((c & 0x01) != 0) { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c & 0x01) == 0) + { + ysv_ext0 += 1; + dy_ext0 -= 1; + } else { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c & 0x03) == 0) + { + zsv_ext0 += 1; + dz_ext0 -= 1; + } else { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) != 0) + { + wsv_ext0 = wsb + 1; + wsv_ext1 = wsb + 2; + dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb; + dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; + } + } + } else { //One point on each "side" + byte c1, c2; + if (aIsBiggerSide) { + c1 = aPoint; + c2 = bPoint; + } else { + c1 = bPoint; + c2 = aPoint; + } + + //Two contributions are the bigger-sided point with each 1 replaced with 2. + if ((c1 & 0x01) != 0) { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c1 & 0x01) == 0) { + ysv_ext0 += 1; + dy_ext0 -= 1; + } else { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x04) != 0) { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c1 & 0x03) == 0) { + zsv_ext0 += 1; + dz_ext0 -= 1; + } else { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x08) != 0) { + wsv_ext0 = wsb + 1; + wsv_ext1 = wsb + 2; + dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb; + dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; + } + + //One contribution is a permutation of (1,1,1,-1) based on the smaller-sided point + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + if ((c2 & 0x01) == 0) { + xsv_ext2 -= 2; + dx_ext2 += 2; + } else if ((c2 & 0x02) == 0) { + ysv_ext2 -= 2; + dy_ext2 += 2; + } else if ((c2 & 0x04) == 0) { + zsv_ext2 -= 2; + dz_ext2 += 2; + } else { + wsv_ext2 -= 2; + dw_ext2 += 2; + } + } + + //Contribution (1,1,1,0) + double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); + } + + //Contribution (1,1,0,1) + double dx3 = dx4; + double dy3 = dy4; + double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; + double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); + } + + //Contribution (1,0,1,1) + double dx2 = dx4; + double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; + double dz2 = dz4; + double dw2 = dw3; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); + } + + //Contribution (0,1,1,1) + double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; + double dz1 = dz4; + double dy1 = dy4; + double dw1 = dw3; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); + } + + //Contribution (1,1,0,0) + double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; + if (attn5 > 0) { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); + } + + //Contribution (1,0,1,0) + double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; + if (attn6 > 0) { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); + } + + //Contribution (1,0,0,1) + double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; + if (attn7 > 0) { + attn7 *= attn7; + value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); + } + + //Contribution (0,1,1,0) + double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; + if (attn8 > 0) { + attn8 *= attn8; + value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); + } + + //Contribution (0,1,0,1) + double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; + if (attn9 > 0) { + attn9 *= attn9; + value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); + } + + //Contribution (0,0,1,1) + double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; + if (attn10 > 0) { + attn10 *= attn10; + value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); + } + } + + //First extra vertex + double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0; + if (attn_ext0 > 0) + { + attn_ext0 *= attn_ext0; + value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0, dx_ext0, dy_ext0, dz_ext0, dw_ext0); + } + + //Second extra vertex + double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1; + if (attn_ext1 > 0) + { + attn_ext1 *= attn_ext1; + value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1, dx_ext1, dy_ext1, dz_ext1, dw_ext1); + } + + //Third extra vertex + double attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2; + if (attn_ext2 > 0) + { + attn_ext2 *= attn_ext2; + value += attn_ext2 * attn_ext2 * extrapolate(xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2, dx_ext2, dy_ext2, dz_ext2, dw_ext2); + } + + return value / NORM_CONSTANT_4D; + } + + private double extrapolate(int xsb, int ysb, double dx, double dy) + { + int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E; + return gradients2D[index] * dx + + gradients2D[index + 1] * dy; + } + + private double extrapolate(int xsb, int ysb, int zsb, double dx, double dy, double dz) + { + int index = permGradIndex3D[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF]; + return gradients3D[index] * dx + + gradients3D[index + 1] * dy + + gradients3D[index + 2] * dz; + } + + private double extrapolate(int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw) + { + int index = perm[(perm[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF] + wsb) & 0xFF] & 0xFC; + return gradients4D[index] * dx + + gradients4D[index + 1] * dy + + gradients4D[index + 2] * dz + + gradients4D[index + 3] * dw; + } + + private static int fastFloor(double x) { + int xi = (int)x; + return x < xi ? xi - 1 : xi; + } + + //Gradients for 2D. They approximate the directions to the + //vertices of an octagon from the center. + private static byte[] gradients2D = new byte[] { + 5, 2, 2, 5, + -5, 2, -2, 5, + 5, -2, 2, -5, + -5, -2, -2, -5, + }; + + //Gradients for 3D. They approximate the directions to the + //vertices of a rhombicuboctahedron from the center, skewed so + //that the triangular and square facets can be inscribed inside + //circles of the same radius. + private static byte[] gradients3D = new byte[] { + -11, 4, 4, -4, 11, 4, -4, 4, 11, + 11, 4, 4, 4, 11, 4, 4, 4, 11, + -11, -4, 4, -4, -11, 4, -4, -4, 11, + 11, -4, 4, 4, -11, 4, 4, -4, 11, + -11, 4, -4, -4, 11, -4, -4, 4, -11, + 11, 4, -4, 4, 11, -4, 4, 4, -11, + -11, -4, -4, -4, -11, -4, -4, -4, -11, + 11, -4, -4, 4, -11, -4, 4, -4, -11, + }; + + //Gradients for 4D. They approximate the directions to the + //vertices of a disprismatotesseractihexadecachoron from the center, + //skewed so that the tetrahedral and cubic facets can be inscribed inside + //spheres of the same radius. + private static byte[] gradients4D = new byte[] { + 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, + -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, + 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, + -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, + 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, + -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, + 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, + -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, + 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, + -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, + 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, + -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, + 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, + -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, + 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, + -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, + }; +} \ No newline at end of file diff --git a/src/shootergame/util/math/random/RandomHelpers.java b/src/shootergame/util/math/random/RandomHelpers.java new file mode 100644 index 0000000..6e3ede6 --- /dev/null +++ b/src/shootergame/util/math/random/RandomHelpers.java @@ -0,0 +1,14 @@ +package shootergame.util.math.random; + +import java.util.Random; + +public class RandomHelpers +{ + public static int randrange(Random rand, int min, int max) { + return randrange(rand, max - min) + min; + } + + public static int randrange(Random rand, int max) { + return (int)(rand.nextDouble() * max); + } +} diff --git a/src/shootergame/util/math/range/Range2i.java b/src/shootergame/util/math/range/Range2i.java new file mode 100644 index 0000000..a3412c1 --- /dev/null +++ b/src/shootergame/util/math/range/Range2i.java @@ -0,0 +1,13 @@ +package shootergame.util.math.range; + +public class Range2i +{ + public int mx; + public int my; + + public Range2i(int mx, int my) + { + this.mx = mx; + this.my = my; + } +} diff --git a/src/shootergame/util/math/range/Range3i.java b/src/shootergame/util/math/range/Range3i.java new file mode 100644 index 0000000..7e85358 --- /dev/null +++ b/src/shootergame/util/math/range/Range3i.java @@ -0,0 +1,15 @@ +package shootergame.util.math.range; + +public class Range3i +{ + public int mx; + public int my; + public int mz; + + public Range3i(int mx, int my, int mz) + { + this.mx = mx; + this.my = my; + this.mz = mz; + } +} diff --git a/src/shootergame/util/math/vec/Vec2d.java b/src/shootergame/util/math/vec/Vec2d.java new file mode 100644 index 0000000..f87e7da --- /dev/null +++ b/src/shootergame/util/math/vec/Vec2d.java @@ -0,0 +1,27 @@ +package shootergame.util.math.vec; + +import shootergame.util.math.MathHelpers; + +public class Vec2d +{ + public double x; + public double y; + + public Vec2d(double x, double y) + { + this.x = x; + this.y = y; + } + + public double distance(Vec2d other) { + return MathHelpers.distance2d(x, y, other.x, other.y); + } + + public static double distance(Vec2d v1, Vec2d v2) { + return v1.distance(v2); + } + + public boolean equal(Vec2d other) { + return x == other.x && y == other.y; + } +} diff --git a/src/shootergame/util/math/vec/Vec2i.java b/src/shootergame/util/math/vec/Vec2i.java new file mode 100644 index 0000000..beac2a2 --- /dev/null +++ b/src/shootergame/util/math/vec/Vec2i.java @@ -0,0 +1,50 @@ +package shootergame.util.math.vec; + +import shootergame.util.math.MathHelpers; +import shootergame.util.math.range.Range2i; + +public class Vec2i +{ + public int x; + public int y; + + public Vec2i(int x, int y) + { + this.x = x; + this.y = y; + } + + public double distance(Vec2i other) { + return MathHelpers.distance2d(x, y, other.x, other.y); + } + + public static double distance(Vec2i v1, Vec2i v2) { + return v1.distance(v2); + } + + public int getId(Range2i range) + { + int id = 0; + int m = 1; + + id += x; + m = range.mx; + id += y*m; + + return id; + } + + public static Vec2i fromId(Range2i range, int id) + { + int x = id % range.mx; + id -= x; + id /= range.mx; + int y = id % range.my; + + return new Vec2i(x, y); + } + + public boolean equal(Vec2i other) { + return x == other.x && y == other.y; + } +} diff --git a/src/shootergame/util/math/vec/Vec3d.java b/src/shootergame/util/math/vec/Vec3d.java new file mode 100644 index 0000000..42bb4f9 --- /dev/null +++ b/src/shootergame/util/math/vec/Vec3d.java @@ -0,0 +1,29 @@ +package shootergame.util.math.vec; + +import shootergame.util.math.MathHelpers; + +public class Vec3d +{ + public double x; + public double y; + public double z; + + public Vec3d(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public double distance(Vec3d other) { + return MathHelpers.distance3d(x, y, z, other.x, other.y, other.z); + } + + public static double distance(Vec3d v1, Vec3d v2) { + return v1.distance(v2); + } + + public boolean equal(Vec3d other) { + return x == other.x && y == other.y && z == other.z; + } +} diff --git a/src/shootergame/util/math/vec/Vec3i.java b/src/shootergame/util/math/vec/Vec3i.java new file mode 100644 index 0000000..4c99fbf --- /dev/null +++ b/src/shootergame/util/math/vec/Vec3i.java @@ -0,0 +1,57 @@ +package shootergame.util.math.vec; + +import shootergame.util.math.MathHelpers; +import shootergame.util.math.range.Range3i; + +public class Vec3i +{ + public int x; + public int y; + public int z; + + public Vec3i(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public double distance(Vec3i other) { + return MathHelpers.distance3d(x, y, z, other.x, other.y, other.z); + } + + public static double distance(Vec3i v1, Vec3i v2) { + return v1.distance(v2); + } + + public int getId(Range3i range) + { + int id = 0; + int m = 1; + + id += x; + m = range.mx; + id += y*m; + m *= range.my; + id += z*m; + + return id; + } + + public static Vec3i fromId(Range3i range, int id) + { + int x = id % range.mx; + id -= x; + id /= range.mx; + int y = id % range.my; + id -= y; + id /= range.my; + int z = id % range.mz; + + return new Vec3i(x, y, z); + } + + public boolean equal(Vec3i other) { + return x == other.x && y == other.y && z == other.z; + } +}