├── src
├── structure_house.txt
├── de
│ └── meinkraft
│ │ ├── .gitignore
│ │ ├── lib
│ │ ├── InputController.java
│ │ ├── Time.java
│ │ ├── Main.java
│ │ ├── Utils.java
│ │ ├── Vector2.java
│ │ ├── Transform.java
│ │ ├── Vector4.java
│ │ ├── Vector3.java
│ │ ├── Display.java
│ │ ├── VAO.java
│ │ ├── Input.java
│ │ ├── Camera.java
│ │ ├── Shader.java
│ │ ├── Texture.java
│ │ └── Matrix4.java
│ │ ├── ChunkState.java
│ │ ├── EntityPlayer.java
│ │ ├── Player.java
│ │ ├── BlockAO.java
│ │ ├── BlockAir.java
│ │ ├── BlockDirt.java
│ │ ├── BlockRose.java
│ │ ├── Blockcheck.java
│ │ ├── BlockGrass.java
│ │ ├── BlockStone.java
│ │ ├── BlockTallGrass.java
│ │ ├── BlockWoodenPlanks.java
│ │ ├── WorldGenerator.java
│ │ ├── Entity.java
│ │ ├── BlockTypeAir.java
│ │ ├── Material.java
│ │ ├── StructureLoader.java
│ │ ├── gui
│ │ ├── GUIFontCharacter.java
│ │ ├── GUI.java
│ │ ├── GUILabel.java
│ │ ├── GUIObject.java
│ │ └── GUIFont.java
│ │ ├── WorldGeneratorFlat.java
│ │ ├── BlockType.java
│ │ ├── World.java
│ │ ├── OpenSimplexNoise.java
│ │ ├── Block.java
│ │ ├── BlockTypePlant.java
│ │ ├── WorldGeneratorNormal.java
│ │ ├── BlockTypeCube.java
│ │ ├── Chunk.java
│ │ ├── Meinkraft.java
│ │ ├── ChunkLoader.java
│ │ ├── ChunkManager.java
│ │ └── OpenSimplexNoiseOctave.java
├── bs.fs
├── gui.fs
├── bs.vs
├── gui.vs
├── shader.fs
├── font.vs
├── font.fs
└── shader.vs
├── .gitignore
└── .project
/src/structure_house.txt:
--------------------------------------------------------------------------------
1 | 0,0,0:6
--------------------------------------------------------------------------------
/src/de/meinkraft/.gitignore:
--------------------------------------------------------------------------------
1 | /ChunkLoaderCM.java
2 |
--------------------------------------------------------------------------------
/src/bs.fs:
--------------------------------------------------------------------------------
1 | #version 110
2 |
3 | void main() {
4 | gl_FragColor = vec4(1);
5 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /libs/
3 | /native/
4 | /docs/
5 | .classpath
6 | *.log
7 | *.png
8 | *.fnt
9 | *.db
--------------------------------------------------------------------------------
/src/gui.fs:
--------------------------------------------------------------------------------
1 | #version 110
2 |
3 | varying vec4 color;
4 |
5 | void main() {
6 | gl_FragColor = color;
7 | }
--------------------------------------------------------------------------------
/src/bs.vs:
--------------------------------------------------------------------------------
1 | #version 110
2 |
3 | uniform mat4 p;
4 | uniform mat4 v;
5 | uniform mat4 m;
6 |
7 | void main() {
8 | gl_Position = p * v * m * gl_Vertex;
9 | }
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/InputController.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | public interface InputController {
4 |
5 | public void input();
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/de/meinkraft/ChunkState.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public enum ChunkState {
4 |
5 | UNLOADED,
6 | LOADING,
7 | LOADED;
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/de/meinkraft/EntityPlayer.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class EntityPlayer extends Entity {
4 |
5 | public EntityPlayer() {
6 |
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/de/meinkraft/Player.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import de.meinkraft.lib.Vector3;
4 |
5 | public class Player {
6 |
7 | // temp
8 | public Vector3 dir;
9 | public Vector3 pos;
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/gui.vs:
--------------------------------------------------------------------------------
1 | #version 110
2 |
3 | uniform mat4 p;
4 | uniform mat4 v;
5 | uniform mat4 m;
6 |
7 | varying vec4 color;
8 |
9 | void main() {
10 | gl_Position = p * v * m * gl_Vertex;
11 | color = gl_Color;
12 | }
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockAO.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class BlockAO {
4 |
5 | public boolean nT, nB, eT, eB, sT, sB, wT, wB;
6 | public boolean cXYZ, c_XYZ, cX_YZ, cXY_Z, c_X_YZ, cX_Y_Z, c_XY_Z, c_X_Y_Z;
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockAir.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class BlockAir extends Block {
4 |
5 | public BlockAir(int id, Material material, BlockType type) {
6 | super(id, material, type);
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockDirt.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class BlockDirt extends Block {
4 |
5 | public BlockDirt(int id, Material material, BlockType type, int... textures) {
6 | super(id, material, type, textures);
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockRose.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class BlockRose extends Block {
4 |
5 | public BlockRose(int id, Material material, BlockType type, int... textures) {
6 | super(id, material, type, textures);
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/de/meinkraft/Blockcheck.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class Blockcheck {
4 |
5 | public boolean north, east, south, west, top, bottom;
6 |
7 | public boolean all() {
8 | return north && east && south && west && top && bottom;
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockGrass.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class BlockGrass extends Block {
4 |
5 | public BlockGrass(int id, Material material, BlockType type, int... textures) {
6 | super(id, material, type, textures);
7 | // TODO Auto-generated constructor stub
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockStone.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class BlockStone extends Block {
4 |
5 | public BlockStone(int id, Material material, BlockType type, int... textures) {
6 | super(id, material, type, textures);
7 | // TODO Auto-generated constructor stub
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockTallGrass.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class BlockTallGrass extends Block {
4 |
5 | public BlockTallGrass(int id, Material material, BlockType type, int... textures) {
6 | super(id, material, type, textures);
7 | // TODO Auto-generated constructor stub
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockWoodenPlanks.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class BlockWoodenPlanks extends Block {
4 |
5 | public BlockWoodenPlanks(int id, Material material, BlockType type, int... textures) {
6 | super(id, material, type, textures);
7 | // TODO Auto-generated constructor stub
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/de/meinkraft/WorldGenerator.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.util.Random;
4 |
5 | public abstract class WorldGenerator {
6 |
7 | private final Random random = new Random(2015);
8 |
9 | public abstract void generate(Chunk chunk);
10 |
11 | public Random getRandom() {
12 | return random;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/shader.fs:
--------------------------------------------------------------------------------
1 | #version 150
2 |
3 | in vec3 texCoord;
4 | in float ao;
5 | in float fogFactor;
6 |
7 | uniform sampler2DArray texture0;
8 |
9 | out vec4 color;
10 |
11 | void main() {
12 | color = texture(texture0, texCoord);
13 |
14 | if(color.a == 0)
15 | discard;
16 |
17 | color *= ao / 3.0;
18 | color = mix(vec4(1), color, fogFactor);
19 | }
--------------------------------------------------------------------------------
/src/de/meinkraft/Entity.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import de.meinkraft.lib.Vector3;
4 |
5 | public abstract class Entity {
6 |
7 | private Vector3 pos;
8 |
9 | public Entity() {
10 | pos = new Vector3();
11 | }
12 |
13 | public Vector3 getPos() {
14 | return pos;
15 | }
16 |
17 | public void setPos(Vector3 pos) {
18 | this.pos = pos;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/font.vs:
--------------------------------------------------------------------------------
1 | #version 330
2 |
3 | uniform mat4 p;
4 | uniform mat4 v;
5 | uniform mat4 m;
6 |
7 | layout(location = 0) in vec2 position;
8 | layout(location = 1) in vec2 texCoord;
9 | layout(location = 2) in vec3 color;
10 |
11 | out vec3 pass_color;
12 | out vec2 pass_texCoord;
13 |
14 | void main() {
15 | gl_Position = p * v * m * vec4(position, 0.0, 1.0);
16 | pass_color = color;
17 | pass_texCoord = texCoord;
18 | }
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Meinkraft
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/font.fs:
--------------------------------------------------------------------------------
1 | #version 330
2 |
3 | uniform sampler2D atlas;
4 | uniform float size;
5 |
6 | in vec3 pass_color;
7 | in vec2 pass_texCoord;
8 |
9 | out vec4 outColor;
10 |
11 | void main() {
12 | float smoothing = 1.0 / (16.0 * size);
13 | float distance = 1.0 - texture(atlas, pass_texCoord).a;
14 | float alpha = 1.0 - smoothstep(0.5 - smoothing, 0.5 + smoothing, distance);
15 |
16 | //if(alpha <= 0.0)
17 | // discard;
18 |
19 | outColor = vec4(1.0, 1.0, 0, alpha);
20 | }
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockTypeAir.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.nio.FloatBuffer;
4 |
5 | public class BlockTypeAir extends BlockType {
6 |
7 | public BlockTypeAir(boolean solid, boolean both) {
8 | super(solid, both);
9 | }
10 |
11 | @Override
12 | public int getVerticesCount(Blockcheck check) {
13 | return 0;
14 | }
15 |
16 | @Override
17 | public void addVertices(float x, float y, float z, FloatBuffer buffer, Blockcheck check, BlockAO ao, int... textures) {
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Time.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import static org.lwjgl.glfw.GLFW.glfwGetTime;
4 |
5 | public class Time {
6 |
7 | private static float delta = 0;
8 | private static double lastTime = 0;
9 |
10 | public static void update() {
11 | delta = (float) (glfwGetTime() - lastTime);
12 | lastTime = glfwGetTime();
13 | }
14 |
15 | public static float getDelta() {
16 | return delta;
17 | }
18 |
19 | public static double getTime() {
20 | return glfwGetTime();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/de/meinkraft/Material.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class Material {
4 |
5 | public static final Material AIR = new Material();
6 | public static final Material STONE = new Material().setOpaque(true);
7 | public static final Material GROUND = new Material().setOpaque(true);
8 | public static final Material PLANT = new Material().setOpaque(false);
9 |
10 | private boolean opaque;
11 |
12 | public Material() {
13 |
14 | }
15 |
16 | public boolean isOpaque() {
17 | return opaque;
18 | }
19 |
20 | public Material setOpaque(boolean opaque) {
21 | this.opaque = opaque;
22 | return this;
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/de/meinkraft/StructureLoader.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.InputStreamReader;
7 |
8 | public class StructureLoader {
9 |
10 | public static void loadStructure(World world, int x, int y, int z, InputStream path) throws IOException {
11 | BufferedReader br = new BufferedReader(new InputStreamReader(path));
12 |
13 | String line;
14 | while((line = br.readLine()) != null) {
15 | String xyz = line.split(":")[0];
16 | world.setBlockAt(x + Integer.parseInt(xyz.split(",")[0]), y + Integer.parseInt(xyz.split(",")[1]), z + Integer.parseInt(xyz.split(",")[2]), Block.getBlockById(Integer.parseInt(line.split(":")[1])));
17 | }
18 | br.close();
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/de/meinkraft/gui/GUIFontCharacter.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.gui;
2 |
3 | public class GUIFontCharacter {
4 |
5 | private final int x, y, w, h, xoff, yoff, xadv;
6 |
7 | public GUIFontCharacter(int x, int y, int w, int h, int xoff, int yoff, int xadv) {
8 | this.x = x;
9 | this.y = y;
10 | this.w = w;
11 | this.h = h;
12 | this.xoff = xoff;
13 | this.yoff = yoff;
14 | this.xadv = xadv;
15 | }
16 |
17 | public int getX() {
18 | return x;
19 | }
20 |
21 | public int getY() {
22 | return y;
23 | }
24 |
25 | public int getW() {
26 | return w;
27 | }
28 |
29 | public int getH() {
30 | return h;
31 | }
32 |
33 | public int getXoff() {
34 | return xoff;
35 | }
36 |
37 | public int getYoff() {
38 | return yoff;
39 | }
40 |
41 | public int getXadv() {
42 | return xadv;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/de/meinkraft/gui/GUI.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.gui;
2 |
3 | import java.io.IOException;
4 |
5 | import de.meinkraft.lib.Display;
6 | import de.meinkraft.lib.Matrix4;
7 | import de.meinkraft.lib.Shader;
8 | import de.meinkraft.lib.Transform;
9 |
10 | public class GUI {
11 |
12 | public static final Matrix4 ORTHO = new Matrix4().initOrthographic(0, Display.getWidth(), 0, Display.getHeight(), -1, 1);
13 | public static Shader SHADER;
14 | static {
15 | try {
16 | SHADER = Shader.loadShader("/gui.vs", "/gui.fs", null);
17 | SHADER.addUniform("p");
18 | SHADER.addUniform("v");
19 | SHADER.addUniform("m");
20 |
21 | SHADER.bind();
22 | SHADER.setUniform("p", ORTHO);
23 | SHADER.setUniform("v", new Transform().getTransformationMatrix());
24 | SHADER.setUniform("m", new Transform().getTransformationMatrix());
25 |
26 | Shader.unbind();
27 | } catch (IOException e) {
28 | e.printStackTrace();
29 | }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/de/meinkraft/WorldGeneratorFlat.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class WorldGeneratorFlat extends WorldGenerator {
4 |
5 | @Override
6 | public void generate(Chunk chunk) {
7 | for(int x = 0; x < Chunk.SIZE_X; x++)
8 | for(int y = 0; y < Chunk.SIZE_Y; y++)
9 | for(int z = 0; z < Chunk.SIZE_Z; z++) {
10 | if(y > 63) {
11 | if(y == 64) {
12 | if(getRandom().nextInt(5) == 0)
13 | chunk.setBlockAt(x, y, z, Block.TALL_GRASS);
14 | else if(getRandom().nextInt(50) == 0)
15 | chunk.setBlockAt(x, y, z, Block.ROSE);
16 | else
17 | chunk.setBlockAt(x, y, z, Block.AIR);
18 | } else
19 | chunk.setBlockAt(x, y, z, Block.AIR);
20 | }
21 | else {
22 | if(y == 63)
23 | chunk.setBlockAt(x, y, z, Block.GRASS);
24 | else if(y >= 60)
25 | chunk.setBlockAt(x, y, z, Block.DIRT);
26 | else
27 | chunk.setBlockAt(x, y, z, Block.STONE);
28 | }
29 | }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/shader.vs:
--------------------------------------------------------------------------------
1 | #version 150
2 | #extension GL_ARB_explicit_attrib_location: enable
3 |
4 | layout(location = 0) in vec3 inPosition;
5 | layout(location = 1) in vec3 inTexCoord;
6 | layout(location = 2) in float inAO;
7 |
8 | uniform mat4 p;
9 | uniform mat4 v;
10 | uniform mat4 m;
11 |
12 | uniform bool enableFog;
13 |
14 | const float fogDensity = 0.04;
15 | const float fogStart = 60;
16 |
17 | out vec3 position;
18 | out vec3 texCoord;
19 | out float ao;
20 | out float fogFactor;
21 |
22 | void main() {
23 | gl_Position = p * v * m * vec4(inPosition, 1);
24 | position = inPosition;
25 | texCoord = inTexCoord;
26 | ao = inAO;
27 |
28 | float fogFragCoord = length(v * m * vec4(inPosition, 1));
29 | if(!enableFog || fogFragCoord < fogStart)
30 | fogFragCoord = 0;
31 | else
32 | fogFragCoord = fogFragCoord - fogStart;
33 |
34 | fogFactor = exp(-fogDensity * fogDensity * fogFragCoord * fogFragCoord * 1.442695);
35 | fogFactor = clamp(fogFactor, 0.0, 1.0);
36 | }
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockType.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.nio.FloatBuffer;
4 |
5 | public abstract class BlockType {
6 |
7 | public static final BlockType AIR = new BlockTypeAir(false, false);
8 | public static final BlockType CUBE = new BlockTypeCube(true, false);
9 | public static final BlockType PLANT = new BlockTypePlant(false, true);
10 |
11 | private final boolean solid, doubleSided;
12 |
13 | public BlockType(boolean solid, boolean doubleSided) {
14 | this.solid = solid;
15 | this.doubleSided = doubleSided;
16 | }
17 |
18 | public abstract int getVerticesCount(Blockcheck check);
19 | public abstract void addVertices(float x, float y, float z, FloatBuffer buffer, Blockcheck check, BlockAO ao, int...textures);
20 |
21 | public float getAO(boolean side1, boolean side2, boolean corner) {
22 | if(side1 && side2)
23 | return 0;
24 |
25 | return 3 - (side1 ? 1 : 0 + (side2 ? 1 : 0) + (corner ? 1 : 0));
26 | }
27 |
28 | public boolean isSolid() {
29 | return solid;
30 | }
31 |
32 | public boolean isDoubleSided() {
33 | return doubleSided;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Main.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import static org.lwjgl.glfw.GLFW.glfwPollEvents;
4 | import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
5 | import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
6 | import static org.lwjgl.opengl.GL11.*;
7 |
8 | import org.lwjgl.openal.AL;
9 | import org.lwjgl.openal.ALContext;
10 |
11 | import de.meinkraft.Meinkraft;
12 |
13 | public class Main {
14 |
15 | public static void main(String[] args) {
16 | Display.create(1280, 720, "Meinkraft");
17 | ALContext alc = ALContext.create();
18 | // alDistanceModel
19 |
20 | glEnable(GL_DEPTH_TEST);
21 | glEnable(GL_CULL_FACE);
22 | // glEnable(GL_BLEND);
23 | // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
24 |
25 | glClearColor(1, 1, 1, 1);
26 |
27 | Meinkraft mk = new Meinkraft();
28 |
29 | while(glfwWindowShouldClose(Display.getWindow()) == 0) {
30 | Time.update();
31 |
32 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
33 |
34 | mk.input();
35 | Input.update();
36 | glfwPollEvents();
37 | mk.update();
38 | mk.render();
39 |
40 | glfwSwapBuffers(Display.getWindow());
41 | }
42 |
43 | Input.destroy();
44 | Display.destory();
45 | AL.destroy(alc);
46 |
47 | System.exit(0);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Utils.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.InputStreamReader;
7 | import java.nio.FloatBuffer;
8 | import java.nio.IntBuffer;
9 |
10 | import org.lwjgl.BufferUtils;
11 |
12 | public class Utils {
13 |
14 | public static String readFileToString(String path) throws IOException {
15 | BufferedReader bR = new BufferedReader(new InputStreamReader(getResourceAsStream(path)));
16 | StringBuilder sB = new StringBuilder();
17 | String line;
18 |
19 | while((line = bR.readLine()) != null)
20 | sB.append(line).append("\n");
21 |
22 | bR.close();
23 |
24 | return sB.toString();
25 | }
26 |
27 | public static InputStream getResourceAsStream(String path) {
28 | return Class.class.getResourceAsStream(path);
29 | }
30 |
31 | public static FloatBuffer createFlippedFloatBuffer(float[] data) {
32 | FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
33 | buffer.put(data);
34 | buffer.flip();
35 |
36 | return buffer;
37 | }
38 |
39 | public static IntBuffer createFlippedIntBuffer(int[] data) {
40 | IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
41 | buffer.put(data);
42 | buffer.flip();
43 |
44 | return buffer;
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Vector2.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | public class Vector2 {
4 |
5 | private float x, y;
6 |
7 | public Vector2() {
8 | this(0);
9 | }
10 |
11 | public Vector2(float v) {
12 | this(v, v);
13 | }
14 |
15 | public Vector2(float x, float y) {
16 | this.x = x;
17 | this.y = y;
18 | }
19 |
20 | public float angle(Vector2 v) {
21 | return (float) Math.toDegrees(Math.acos(dot(v) / (length() * v.length())));
22 | }
23 |
24 | public float dot(Vector2 v) {
25 | return x * v.getX() + y * v.getY();
26 | }
27 |
28 | public float length() {
29 | return (float) Math.sqrt(x * x + y * y);
30 | }
31 |
32 | public Vector2 negate() {
33 | return mul(-1);
34 | }
35 |
36 | public Vector2 normalised() {
37 | return new Vector2(x / length(), y / length());
38 | }
39 |
40 | public Vector2 add(Vector2 v) {
41 | return new Vector2(x + v.getX(), y + v.getY());
42 | }
43 |
44 | public Vector2 mul(float v) {
45 | return new Vector2(x * v, y * v);
46 | }
47 |
48 | public float getX() {
49 | return x;
50 | }
51 |
52 | public void setX(float x) {
53 | this.x = x;
54 | }
55 |
56 | public float getY() {
57 | return y;
58 | }
59 |
60 | public void setY(float y) {
61 | this.y = y;
62 | }
63 |
64 | @Override
65 | public String toString() {
66 | return "vec2(" + x + ", " + y + ")";
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/de/meinkraft/World.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import de.meinkraft.lib.Time;
4 |
5 | public class World {
6 |
7 | private final ChunkManager chunkManager;
8 | private final Player player;
9 |
10 | private String name;
11 | private WorldGenerator worldGenerator;
12 |
13 | public World(String name, WorldGenerator worldGenerator) {
14 | this.name = name;
15 | this.worldGenerator = worldGenerator;
16 |
17 | chunkManager = new ChunkManager(this);
18 | player = new Player();
19 | }
20 |
21 | public void update() {
22 | chunkManager.update();
23 | }
24 |
25 | public void render() {
26 | chunkManager.render();
27 | }
28 |
29 | public Block getBlockAt(int x, int y, int z) {
30 | return chunkManager.getBlockAt(x, y, z);
31 | }
32 |
33 | public void setBlockAt(int x, int y, int z, Block block) {
34 | chunkManager.setBlockAt(x, y, z, block);
35 | }
36 |
37 | public ChunkManager getChunkManager() {
38 | return chunkManager;
39 | }
40 |
41 | public Player getPlayer() {
42 | return player;
43 | }
44 |
45 | public String getName() {
46 | return name;
47 | }
48 |
49 | public void setName(String name) {
50 | this.name = name;
51 | }
52 |
53 | public WorldGenerator getWorldGenerator() {
54 | return worldGenerator;
55 | }
56 |
57 | public void setWorldGenerator(WorldGenerator worldGenerator) {
58 | this.worldGenerator = worldGenerator;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/de/meinkraft/OpenSimplexNoise.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.util.Random;
4 |
5 | public class OpenSimplexNoise {
6 |
7 | private OpenSimplexNoiseOctave[] o;
8 | private double[] f;
9 | private double[] a;
10 |
11 | private double persistance;
12 |
13 | public OpenSimplexNoise(int largestFeature, double persistance, long seed) {
14 | this.persistance = persistance;
15 |
16 | int numberOfOctaves = (int) Math.ceil(Math.log10(largestFeature) / Math.log10(2));
17 |
18 | o = new OpenSimplexNoiseOctave[numberOfOctaves];
19 | f = new double[numberOfOctaves];
20 | a = new double[numberOfOctaves];
21 |
22 | Random r = new Random(seed);
23 |
24 | for(int i = 0; i < numberOfOctaves; i++) {
25 | o[i] = new OpenSimplexNoiseOctave(r.nextInt());
26 |
27 | f[i] = Math.pow(2, i);
28 | a[i] = Math.pow(persistance, o.length - i);
29 | }
30 | }
31 |
32 | public double getNoise(int x, int y) {
33 | double result = 0;
34 |
35 | for(int i = 0; i < o.length; i++)
36 | result += o[i].eval(x / f[i], y / f[i]) * a[i];
37 |
38 | return result;
39 | }
40 |
41 | public double getNoise(double x, double y, double z) {
42 | double result = 0;
43 |
44 | for(int i = 0; i < o.length; i++) {
45 | double f = Math.pow(2, i);
46 | double a = Math.pow(persistance, o.length - i);
47 | result += o[i].eval(x / f, y / f, z / f) * a;
48 | }
49 |
50 | return result;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Transform.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | public class Transform {
4 |
5 | private Vector3 translation;
6 | private Vector3 rotation;
7 | private Vector3 scale;
8 |
9 | public Transform() {
10 | this(new Vector3());
11 | }
12 |
13 | public Transform(Transform transform) {
14 | this(transform.getTranslation(), transform.getRotation(), transform.getScale());
15 | }
16 |
17 | public Transform(Vector3 translation) {
18 | this(translation, new Vector3());
19 | }
20 |
21 | public Transform(Vector3 translation, Vector3 rotation) {
22 | this(translation, rotation, new Vector3(1));
23 | }
24 |
25 | public Transform(Vector3 translation, Vector3 rotation, Vector3 scale) {
26 | this.translation = translation;
27 | this.rotation = rotation;
28 | this.scale = scale;
29 | }
30 |
31 | public Matrix4 getTransformationMatrix() {
32 | Matrix4 t = new Matrix4().initTranslation(translation);
33 | Matrix4 r = new Matrix4().initRotation(rotation, Matrix4.XYZ);
34 | Matrix4 s = new Matrix4().initScale(scale);
35 |
36 | return t.mul(r.mul(s));
37 | }
38 |
39 | public Vector3 getTranslation() {
40 | return translation;
41 | }
42 |
43 | public void setTranslation(Vector3 translation) {
44 | this.translation = translation;
45 | }
46 |
47 | public Vector3 getRotation() {
48 | return rotation;
49 | }
50 |
51 | public void setRotation(Vector3 rotation) {
52 | this.rotation = rotation;
53 | }
54 |
55 | public Vector3 getScale() {
56 | return scale;
57 | }
58 |
59 | public void setScale(Vector3 scale) {
60 | this.scale = scale;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/de/meinkraft/gui/GUILabel.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.gui;
2 |
3 | import static org.lwjgl.opengl.GL11.GL_QUADS;
4 | import static org.lwjgl.opengl.GL11.glBegin;
5 | import static org.lwjgl.opengl.GL11.glColor4f;
6 | import static org.lwjgl.opengl.GL11.glEnd;
7 | import static org.lwjgl.opengl.GL11.glVertex2f;
8 | import de.meinkraft.lib.Display;
9 | import de.meinkraft.lib.Vector3;
10 |
11 | public class GUILabel extends GUIObject {
12 |
13 | public static GUIFont font;
14 |
15 | public GUILabel(float x, float y, int width, int height) {
16 | super(x, y, width, height);
17 |
18 | font = new GUIFont("font", 20);
19 | font.setColor(new Vector3(1,0,0));
20 | }
21 |
22 | @Override
23 | public void draw() {
24 | int displayW = Display.getWidth();
25 | int displayH = Display.getHeight();
26 |
27 | float x = getX() * displayW;
28 | if(getOrientationX() == 1)
29 | x -= getWidth() / 2.0f;
30 | else if(getOrientationX() == 2)
31 | x -= - getWidth();
32 |
33 | float y = getY() * displayH;
34 | if(getOrientationY() == 1)
35 | y -= getHeight() / 2.0f;
36 | else if(getOrientationY() == 2)
37 | y -= getHeight();
38 |
39 | GUI.SHADER.bind();
40 | glBegin(GL_QUADS);
41 | {
42 | glColor4f(0, 0, 1, 1);
43 |
44 | glVertex2f(x, y);
45 | glVertex2f(x + getWidth(), y);
46 | glVertex2f(x + getWidth(), y + getHeight());
47 | glVertex2f(x, y + getHeight());
48 | }
49 | glEnd();
50 |
51 | font.drawString("Text", (int) (getX() * displayW), (int) (getY() * displayH));
52 | }
53 |
54 | public void setFont(GUIFont font) {
55 | GUILabel.font = font;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Vector4.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | public class Vector4 {
4 |
5 | private float x, y, z, w;
6 |
7 | public Vector4() {
8 | this(0);
9 | }
10 |
11 | public Vector4(float v) {
12 | this(v, v, v, v);
13 | }
14 |
15 | public Vector4(float x, float y, float z, float w) {
16 | this.x = x;
17 | this.y = y;
18 | this.z = z;
19 | this.w = w;
20 | }
21 |
22 | public float dot(Vector4 v) {
23 | return x * v.getX() + y * v.getY() + z * v.getZ() + w * v.getW();
24 | }
25 |
26 | public float length() {
27 | return (float) Math.sqrt(x * x + y * y + z * z + w * w);
28 | }
29 |
30 | public Vector4 negate() {
31 | return mul(-1);
32 | }
33 |
34 | public Vector4 normalised() {
35 | return new Vector4(x / length(), y / length(), z / length(), w / length());
36 | }
37 |
38 | public Vector4 add(Vector4 v) {
39 | return new Vector4(x + v.getX(), y + v.getY(), z + v.getZ(), w + v.getW());
40 | }
41 |
42 | public Vector4 mul(float v) {
43 | return new Vector4(x * v, y * v, z * v, w * v);
44 | }
45 |
46 | public float getX() {
47 | return x;
48 | }
49 |
50 | public void setX(float x) {
51 | this.x = x;
52 | }
53 |
54 | public float getY() {
55 | return y;
56 | }
57 |
58 | public void setY(float y) {
59 | this.y = y;
60 | }
61 |
62 | public float getZ() {
63 | return z;
64 | }
65 |
66 | public void setZ(float z) {
67 | this.z = z;
68 | }
69 |
70 | public float getW() {
71 | return w;
72 | }
73 |
74 | public void setW(float w) {
75 | this.w = w;
76 | }
77 |
78 | @Override
79 | public String toString() {
80 | return "vec4(" + x + ", " + y + ", " + z + ", " + w + ")";
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Vector3.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | public class Vector3 {
4 |
5 | private float x, y, z;
6 |
7 | public Vector3() {
8 | this(0);
9 | }
10 |
11 | public Vector3(float v) {
12 | this(v, v, v);
13 | }
14 |
15 | public Vector3(float x, float y, float z) {
16 | this.x = x;
17 | this.y = y;
18 | this.z = z;
19 | }
20 |
21 | public float angle(Vector3 v) {
22 | return (float) Math.toDegrees(Math.acos(dot(v) / (length() * v.length())));
23 | }
24 |
25 | public Vector3 cross(Vector3 v) {
26 | return new Vector3(y * v.getZ() - z * v.getY(), z * v.getX() - x * v.getZ(), x * v.getY() - y * v.getX());
27 | }
28 |
29 | public float dot(Vector3 v) {
30 | return x * v.getX() + y * v.getY() + z * v.getZ();
31 | }
32 |
33 | public float length() {
34 | return (float) Math.sqrt(x * x + y * y + z * z);
35 | }
36 |
37 | public Vector3 negate() {
38 | return mul(-1);
39 | }
40 |
41 | public Vector3 normalised() {
42 | return new Vector3(x / length(), y / length(), z / length());
43 | }
44 |
45 | public Vector3 add(Vector3 v) {
46 | return new Vector3(x + v.getX(), y + v.getY(), z + v.getZ());
47 | }
48 |
49 | public Vector3 mul(float v) {
50 | return new Vector3(x * v, y * v, z * v);
51 | }
52 |
53 | public float getX() {
54 | return x;
55 | }
56 |
57 | public void setX(float x) {
58 | this.x = x;
59 | }
60 |
61 | public float getY() {
62 | return y;
63 | }
64 |
65 | public void setY(float y) {
66 | this.y = y;
67 | }
68 |
69 | public float getZ() {
70 | return z;
71 | }
72 |
73 | public void setZ(float z) {
74 | this.z = z;
75 | }
76 |
77 | @Override
78 | public String toString() {
79 | return "vec3(" + x + ", " + y + ", " + z + ")";
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/de/meinkraft/Block.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.lang.reflect.Field;
4 |
5 | public abstract class Block {
6 |
7 | public static final Block AIR = new BlockAir(0, Material.AIR, BlockType.AIR);
8 | public static final Block STONE = new BlockStone(1, Material.GROUND, BlockType.CUBE, 1,1,1,1,1,1);
9 | public static final Block DIRT = new BlockDirt(2, Material.GROUND, BlockType.CUBE, 2,2,2,2,2,2);
10 | public static final Block GRASS = new BlockGrass(3, Material.GROUND, BlockType.CUBE, 3,3,3,3,0,2);
11 | public static final Block ROSE = new BlockRose(4, Material.PLANT, BlockType.PLANT, 12);
12 | public static final Block TALL_GRASS = new BlockTallGrass(5, Material.PLANT, BlockType.PLANT, 39);
13 | public static final Block WOODEN_PLANKS = new BlockWoodenPlanks(6, Material.GROUND, BlockType.CUBE, 4,4,4,4,4,4);
14 |
15 | private final int id;
16 | private final Material material;
17 | private final BlockType type;
18 | private final int[] textures;
19 |
20 | public Block(int id, Material material, BlockType type, int... textures) {
21 | this.id = id;
22 | this.material = material;
23 | this.type = type;
24 | this.textures = textures;
25 | }
26 |
27 | // public abstract ItemStack getItemDrop();
28 | // public abstract float[]? getVertices();
29 |
30 | public static Block getBlockById(int id) {
31 | for(Field field : Block.class.getDeclaredFields()) {
32 | if(field.getType().getSimpleName().equals("Block")) {
33 | try {
34 | Block block = (Block) field.get(field.getName());
35 |
36 | if(block.id == id)
37 | return block;
38 | } catch (IllegalArgumentException e) {
39 | e.printStackTrace();
40 | } catch (IllegalAccessException e) {
41 | e.printStackTrace();
42 | }
43 | }
44 | }
45 |
46 | return null;
47 | }
48 |
49 | public int getId() {
50 | return id;
51 | }
52 |
53 | public Material getMaterial() {
54 | return material;
55 | }
56 |
57 | public BlockType getType() {
58 | return type;
59 | }
60 |
61 | public int[] getTextures() {
62 | return textures;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockTypePlant.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.nio.FloatBuffer;
4 |
5 | import org.lwjgl.opengl.OpenGLException;
6 |
7 | public class BlockTypePlant extends BlockType {
8 |
9 | public BlockTypePlant(boolean solid, boolean both) {
10 | super(solid, both);
11 | }
12 |
13 | @Override
14 | public int getVerticesCount(Blockcheck check) {
15 | if(check.all())
16 | return 0;
17 | else
18 | return 16;
19 | }
20 |
21 | @Override
22 | public void addVertices(float x, float y, float z, FloatBuffer buffer, Blockcheck check, BlockAO ao, int... textures) {
23 | if(textures.length != 1)
24 | throw new OpenGLException(getClass().getSimpleName() + " must have 1 texture");
25 |
26 | if(!check.all()) {
27 | buffer.put(new float[] {
28 | x + 0, y + 0, z + 0, 0, 1, textures[0], getAO(false, false, false),
29 | x + 1, y + 0, z + 1, 1, 1, textures[0], getAO(false, false, false),
30 | x + 1, y + 1.4142f, z + 1, 1, 0, textures[0], getAO(false, false, false),
31 | x + 0, y + 1.4142f, z + 0, 0, 0, textures[0], getAO(false, false, false),
32 |
33 | x + 1, y + 0, z + 1, 1, 1, textures[0], getAO(false, false, false),
34 | x + 0, y + 0, z + 0, 0, 1, textures[0], getAO(false, false, false),
35 | x + 0, y + 1.4142f, z + 0, 0, 0, textures[0], getAO(false, false, false),
36 | x + 1, y + 1.4142f, z + 1, 1, 0, textures[0], getAO(false, false, false),
37 |
38 | x + 0, y + 0, z + 1, 0, 1, textures[0], getAO(false, false, false),
39 | x + 1, y + 0, z + 0, 1, 1, textures[0], getAO(false, false, false),
40 | x + 1, y + 1.4142f, z + 0, 1, 0, textures[0], getAO(false, false, false),
41 | x + 0, y + 1.4142f, z + 1, 0, 0, textures[0], getAO(false, false, false),
42 |
43 | x + 1, y + 0, z + 0, 1, 1, textures[0], getAO(false, false, false),
44 | x + 0, y + 0, z + 1, 0, 1, textures[0], getAO(false, false, false),
45 | x + 0, y + 1.4142f, z + 1, 0, 0, textures[0], getAO(false, false, false),
46 | x + 1, y + 1.4142f, z + 0, 1, 0, textures[0], getAO(false, false, false)
47 | });
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/de/meinkraft/gui/GUIObject.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.gui;
2 |
3 | public abstract class GUIObject {
4 |
5 | /*
6 | * first 4 bits hold the orientation (where should the position set to? (relative to the object)) 0000xxxx
7 | * last 4 bits hold the alignment (where should the position align to?) xxxx0000
8 | */
9 | private byte orientation;
10 |
11 | private float x, y;
12 | private int width, height;
13 |
14 | public GUIObject(float x, float y, int width, int height) {
15 | this.x = x;
16 | this.y = y;
17 | this.width = width;
18 | this.height = height;
19 | }
20 |
21 | protected void draw() {
22 |
23 | }
24 |
25 | public void setOrientationX(int x) {
26 | if(x < 0) x = 0; else if(x > 2) x = 2;
27 |
28 | orientation = (byte) ((orientation & 252) | (x & 3));
29 | }
30 |
31 | public int getOrientationX() {
32 | return (orientation & 3) >> 0;
33 | }
34 |
35 | public void setOrientationY(int y) {
36 | if(y < 0) y = 0; else if(y > 2) y = 2;
37 |
38 | orientation = (byte) (orientation & 243 | (y & 3) << 2);
39 | }
40 |
41 | public int getOrientationY() {
42 | return (orientation & 12) >> 2;
43 | }
44 |
45 | public void setAlignmentX(int x) {
46 | if(x < 0) x = 0; else if(x > 2) x = 2;
47 |
48 | orientation = (byte) (orientation & 207 | (x & 3) << 4);
49 | }
50 |
51 | public int getAlignmentX() {
52 | return (orientation & 48) >> 4;
53 | }
54 |
55 | public void setAlignmentY(int y) {
56 | if(y < 0) y = 0; else if(y > 2) y = 2;
57 |
58 | orientation = (byte) (orientation & 63 | (y & 3) << 6);
59 | }
60 |
61 | public int getAlignmentY() {
62 | return (orientation & 192) >> 6;
63 | }
64 |
65 | public byte getOrientation() {
66 | return orientation;
67 | }
68 |
69 | public float getX() {
70 | return x;
71 | }
72 |
73 | public void setX(float x) {
74 | this.x = x;
75 | }
76 |
77 | public float getY() {
78 | return y;
79 | }
80 |
81 | public void setY(float y) {
82 | this.y = y;
83 | }
84 |
85 | public int getWidth() {
86 | return width;
87 | }
88 |
89 | public void setWidth(int width) {
90 | this.width = width;
91 | }
92 |
93 | public int getHeight() {
94 | return height;
95 | }
96 |
97 | public void setHeight(int height) {
98 | this.height = height;
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/de/meinkraft/WorldGeneratorNormal.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | public class WorldGeneratorNormal extends WorldGenerator {
4 |
5 | private OpenSimplexNoise osn0, osn1, osn2;
6 |
7 | public WorldGeneratorNormal() {
8 | osn0 = new OpenSimplexNoise(64, 0.1, 315123531234l);
9 | osn1 = new OpenSimplexNoise(30, 0.2, 315123531234l);
10 | osn2 = new OpenSimplexNoise(30, 0.2, 837538751238l);
11 | }
12 |
13 | @Override
14 | public void generate(Chunk chunk) {
15 | for(int x = 0; x < Chunk.SIZE_X; x++)
16 | for(int z = 0; z < Chunk.SIZE_Z; z++) {
17 | double v = osn0.getNoise((chunk.getX() * Chunk.SIZE_X + x), (chunk.getZ() * Chunk.SIZE_Z + z)) * 0.5 + 0.5;
18 | int h = (int) (Chunk.SIZE_Y * v);
19 |
20 | for(int y = 0; y < Chunk.SIZE_Y; y++) {
21 | if(y < h - 3)
22 | chunk.setBlockAt(x, y, z, Block.STONE);
23 | else if(y < h)
24 | chunk.setBlockAt(x, y, z, Block.DIRT);
25 | else if(y == h)
26 | chunk.setBlockAt(x, y, z, Block.GRASS);
27 | else
28 | chunk.setBlockAt(x, y, z, Block.AIR);
29 | }
30 | }
31 |
32 | for(int x = 0; x < Chunk.SIZE_X; x++)
33 | for(int z = 0; z < Chunk.SIZE_Z; z++) {
34 | for(int y = 0; y < Chunk.SIZE_Y; y++) {
35 | double v = osn1.getNoise((chunk.getX() * Chunk.SIZE_X + x), y / 1.5, (chunk.getZ() * Chunk.SIZE_Z + z)) * 0.5 + 0.5;
36 | double v2 = osn2.getNoise((chunk.getX() * Chunk.SIZE_X + x), y / 1.5, (chunk.getZ() * Chunk.SIZE_Z + z)) * 0.5 + 0.5;
37 |
38 | if(v > MIN && v < MAX && v2 > MIN && v2 < MAX)
39 | chunk.setBlockAt(x, y, z, Block.AIR);
40 | // else
41 | // chunk.setBlockAt(x, y, z, Block.AIR);
42 |
43 | // if(v > 0.50 && v < 0.51 && v2 > 0.50 && v2 < 0.51)
44 | // chunk.setBlockAt(x, y, z, Block.STONE);
45 | // else
46 | // chunk.setBlockAt(x, y, z, Block.AIR);
47 | }
48 | }
49 | }
50 |
51 | private final static double MIN = 0.52, MAX = 0.56;
52 |
53 | // @Override
54 | // public void generate(Chunk chunk) {
55 | // for(int x = 0; x < Chunk.SIZE_X; x++)
56 | // for(int z = 0; z < Chunk.SIZE_Z; z++) {
57 | // double v = osn.getNoise((chunk.getX() * Chunk.SIZE_X + x), (chunk.getZ() * Chunk.SIZE_Z + z)) * 0.5 + 0.5;
58 | // int h = (int) (Chunk.SIZE_Y * v);
59 | //
60 | // for(int y = 0; y < Chunk.SIZE_Y; y++) {
61 | // if(y < h - 3)
62 | // chunk.setBlockAt(x, y, z, Block.STONE);
63 | // else if(y < h)
64 | // chunk.setBlockAt(x, y, z, Block.DIRT);
65 | // else if(y == h)
66 | // chunk.setBlockAt(x, y, z, Block.GRASS);
67 | // else
68 | // chunk.setBlockAt(x, y, z, Block.AIR);
69 | // }
70 | // }
71 | // }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Display.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
4 | import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
5 | import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
6 | import static org.lwjgl.glfw.GLFW.glfwInit;
7 | import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
8 | import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback;
9 | import static org.lwjgl.glfw.GLFW.glfwSetWindowSizeCallback;
10 | import static org.lwjgl.glfw.GLFW.glfwSetWindowTitle;
11 | import static org.lwjgl.glfw.GLFW.glfwSwapInterval;
12 | import static org.lwjgl.glfw.GLFW.glfwTerminate;
13 | import static org.lwjgl.glfw.GLFW.glfwWindowHint;
14 |
15 | import org.lwjgl.glfw.Callbacks;
16 | import org.lwjgl.glfw.GLFWErrorCallback;
17 | import org.lwjgl.glfw.GLFWWindowSizeCallback;
18 | import org.lwjgl.opengl.GLContext;
19 |
20 | public class Display {
21 |
22 | private static int WIDTH, HEIGHT;
23 | private static long WINDOW;
24 |
25 | private static GLFWErrorCallback errorCallback;
26 | private static GLFWWindowSizeCallback windowSizeCallback;
27 |
28 | private static boolean resized;
29 |
30 | public static void create(int w, int h, String t) {
31 | WIDTH = w;
32 | HEIGHT = h;
33 |
34 | glfwSetErrorCallback(errorCallback = Callbacks.errorCallbackPrint(System.err));
35 |
36 | if(glfwInit() == 0)
37 | throw new RuntimeException("Unable to initialize GLFW");
38 |
39 | glfwWindowHint(GLFW_RESIZABLE, 1);
40 |
41 | WINDOW = glfwCreateWindow(w, h, t, 0, 0);
42 |
43 | glfwMakeContextCurrent(WINDOW);
44 | GLContext.createFromCurrent();
45 |
46 | glfwSwapInterval(1);
47 | setupCallbacks();
48 | }
49 |
50 | public static void destory() {
51 | glfwDestroyWindow(WINDOW);
52 | windowSizeCallback.release();
53 | glfwTerminate();
54 | errorCallback.release();
55 | }
56 |
57 | private static void setupCallbacks() {
58 | glfwSetWindowSizeCallback(Display.WINDOW, windowSizeCallback = new GLFWWindowSizeCallback() {
59 |
60 | @Override
61 | public void invoke(long window, int width, int height) {
62 | WIDTH = width;
63 | HEIGHT = height;
64 |
65 | resized = true;
66 | }
67 |
68 | });
69 | }
70 |
71 | public static int getWidth() {
72 | return WIDTH;
73 | }
74 |
75 | public static int getHeight() {
76 | return HEIGHT;
77 | }
78 |
79 | public static long getWindow() {
80 | return WINDOW;
81 | }
82 |
83 | public static boolean wasResized() {
84 | if(resized) {
85 | resized = false;
86 | return true;
87 | } else
88 | return false;
89 | }
90 |
91 | public static void setTitle(String title) {
92 | glfwSetWindowTitle(WINDOW, title);
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/VAO.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import static org.lwjgl.opengl.GL11.glDrawElements;
4 | import static org.lwjgl.opengl.GL11.GL_FLOAT;
5 | import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT;
6 | import static org.lwjgl.opengl.GL15.glBindBuffer;
7 | import static org.lwjgl.opengl.GL15.glBufferData;
8 | import static org.lwjgl.opengl.GL15.glBufferSubData;
9 | import static org.lwjgl.opengl.GL15.glGenBuffers;
10 | import static org.lwjgl.opengl.GL15.glDeleteBuffers;
11 | import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
12 | import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
13 | import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER;
14 | import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
15 | import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
16 | import static org.lwjgl.opengl.GL30.glBindVertexArray;
17 | import static org.lwjgl.opengl.GL30.glDeleteVertexArrays;
18 | import static org.lwjgl.opengl.GL30.glGenVertexArrays;
19 |
20 | import java.nio.FloatBuffer;
21 | import java.nio.IntBuffer;
22 |
23 | public class VAO {
24 |
25 | private final int mode;
26 | private final int vaoID;
27 | private final int vboID;
28 | private final int iboID;
29 |
30 | public VAO(int mode) {
31 | this.mode = mode;
32 | this.vaoID = glGenVertexArrays();
33 | this.vboID = glGenBuffers();
34 | this.iboID = glGenBuffers();
35 | }
36 |
37 | /**
38 | * @param values - "SIZE STRIDE OFFSET"
39 | */
40 | public void initVAO(String...attributes) {
41 | glBindVertexArray(vaoID);
42 | glBindBuffer(GL_ARRAY_BUFFER, vboID);
43 |
44 | for(int i = 0; i < attributes.length; i++) {
45 | String[] values = attributes[i].split(" ");
46 |
47 | glEnableVertexAttribArray(i);
48 | glVertexAttribPointer(i, Integer.valueOf(values[0]), GL_FLOAT, false, 4 * Integer.valueOf(values[1]), 4 * Integer.valueOf(values[2]));
49 | }
50 |
51 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
52 | glBindVertexArray(0);
53 | }
54 |
55 | public void initVBO(FloatBuffer buffer) {
56 | glBindBuffer(GL_ARRAY_BUFFER, vboID);
57 | glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
58 | glBindBuffer(GL_ARRAY_BUFFER, 0);
59 | }
60 |
61 | public void updateVBO(FloatBuffer buffer, long offset) {
62 | glBindBuffer(GL_ARRAY_BUFFER, vboID);
63 | glBufferSubData(GL_ARRAY_BUFFER, 4 * offset, buffer);
64 | glBindBuffer(GL_ARRAY_BUFFER, 0);
65 | }
66 |
67 | public void initIBO(IntBuffer buffer) {
68 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
69 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
70 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
71 | }
72 |
73 | public void render(int indices_count, int indices_offset) {
74 | glBindVertexArray(vaoID);
75 | glDrawElements(mode, indices_count, GL_UNSIGNED_INT, 4 * indices_offset);
76 | glBindVertexArray(0);
77 | }
78 |
79 | public void delete() {
80 | glDeleteBuffers(vboID);
81 | glDeleteBuffers(iboID);
82 | glDeleteVertexArrays(vaoID);
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/de/meinkraft/BlockTypeCube.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.nio.FloatBuffer;
4 |
5 | import org.lwjgl.opengl.OpenGLException;
6 |
7 | public class BlockTypeCube extends BlockType {
8 |
9 | public BlockTypeCube(boolean solid, boolean both) {
10 | super(solid, both);
11 | }
12 |
13 | @Override
14 | public int getVerticesCount(Blockcheck check) {
15 | int count = 0;
16 |
17 | if(!check.north)
18 | count += 4;
19 |
20 | if(!check.east)
21 | count += 4;
22 |
23 | if(!check.south)
24 | count += 4;
25 |
26 | if(!check.west)
27 | count += 4;
28 |
29 | if(!check.top)
30 | count += 4;
31 |
32 | if(!check.bottom)
33 | count += 4;
34 |
35 | return count;
36 | }
37 |
38 | @Override
39 | public void addVertices(float x, float y, float z, FloatBuffer buffer, Blockcheck check, BlockAO ao, int...textures) {
40 | if(textures.length != 6)
41 | throw new OpenGLException(getClass().getSimpleName() + " must have 6 textures");
42 |
43 | if(!check.north)
44 | buffer.put(new float[] {
45 | x + 0, y + 0, z + 0, 1, 1, textures[0], getAO(ao.nB, ao.wB, ao.c_X_Y_Z),
46 | x + 0, y + 1, z + 0, 1, 0, textures[0], getAO(ao.nT, ao.wT, ao.c_XY_Z),
47 | x + 1, y + 1, z + 0, 0, 0, textures[0], getAO(ao.nT, ao.eT, ao.cXY_Z),
48 | x + 1, y + 0, z + 0, 0, 1, textures[0], getAO(ao.nB, ao.eB, ao.cX_Y_Z)
49 | });
50 |
51 | if(!check.east)
52 | buffer.put(new float[] {
53 | x + 1, y + 0, z + 1, 0, 1, textures[1], getAO(ao.eB, ao.sB, ao.cX_YZ),
54 | x + 1, y + 0, z + 0, 1, 1, textures[1], getAO(ao.eB, ao.nB, ao.cX_Y_Z),
55 | x + 1, y + 1, z + 0, 1, 0, textures[1], getAO(ao.eT, ao.nT, ao.cXY_Z),
56 | x + 1, y + 1, z + 1, 0, 0, textures[1], getAO(ao.eT, ao.sT, ao.cXYZ)
57 | });
58 |
59 | if(!check.south)
60 | buffer.put(new float[] {
61 | x + 0, y + 0, z + 1, 0, 1, textures[2], getAO(ao.sB, ao.wB, ao.c_X_YZ),
62 | x + 1, y + 0, z + 1, 1, 1, textures[2], getAO(ao.sB, ao.eB, ao.cX_YZ),
63 | x + 1, y + 1, z + 1, 1, 0, textures[2], getAO(ao.sT, ao.eT, ao.cXYZ),
64 | x + 0, y + 1, z + 1, 0, 0, textures[2], getAO(ao.sT, ao.wT, ao.c_XYZ)
65 | });
66 |
67 | if(!check.west)
68 | buffer.put(new float[] {
69 | x + 0, y + 0, z + 0, 0, 1, textures[3], getAO(ao.wB, ao.nB, ao.c_X_Y_Z),
70 | x + 0, y + 0, z + 1, 1, 1, textures[3], getAO(ao.wB, ao.sB, ao.c_X_YZ),
71 | x + 0, y + 1, z + 1, 1, 0, textures[3], getAO(ao.wT, ao.sT, ao.c_XYZ),
72 | x + 0, y + 1, z + 0, 0, 0, textures[3], getAO(ao.wT, ao.nT, ao.c_XY_Z)
73 | });
74 |
75 | if(!check.top)
76 | buffer.put(new float[] {
77 | x + 0, y + 1, z + 1, 0, 1, textures[4], getAO(ao.wT, ao.sT, ao.c_XYZ),
78 | x + 1, y + 1, z + 1, 1, 1, textures[4], getAO(ao.sT, ao.eT, ao.cXYZ),
79 | x + 1, y + 1, z + 0, 1, 0, textures[4], getAO(ao.eT, ao.nT, ao.cXY_Z),
80 | x + 0, y + 1, z + 0, 0, 0, textures[4], getAO(ao.nT, ao.wT, ao.c_XY_Z)
81 | });
82 |
83 | if(!check.bottom)
84 | buffer.put(new float[] {
85 | x + 0, y + 0, z + 1, 0, 1, textures[5], getAO(ao.sB, ao.wB, ao.c_X_YZ),
86 | x + 0, y + 0, z + 0, 0, 0, textures[5], getAO(ao.wB, ao.nB, ao.c_X_Y_Z),
87 | x + 1, y + 0, z + 0, 1, 0, textures[5], getAO(ao.nB, ao.eB, ao.cX_Y_Z),
88 | x + 1, y + 0, z + 1, 1, 1, textures[5], getAO(ao.eB, ao.sB, ao.cX_YZ)
89 | });
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/de/meinkraft/Chunk.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
4 |
5 | import java.nio.FloatBuffer;
6 | import java.nio.IntBuffer;
7 |
8 | import de.meinkraft.lib.VAO;
9 |
10 | public class Chunk {
11 |
12 | public static final int SIZE_X = 16, SIZE_Y = 128, SIZE_Z = 16;
13 |
14 | private final Block[][][] blocks;
15 | private final short[][][] lights;
16 |
17 | private VAO vao;
18 | public FloatBuffer vertices;
19 | public IntBuffer indices;
20 | private int solidBlocks;
21 |
22 | private boolean doLoad;
23 |
24 | private final int x, z;
25 | private ChunkState state;
26 |
27 | public Chunk(int x, int z) {
28 | this.x = x;
29 | this.z = z;
30 | this.state = ChunkState.UNLOADED;
31 |
32 | blocks = new Block[SIZE_X][SIZE_Y][SIZE_Z];
33 | lights = new short[SIZE_X][SIZE_Y][SIZE_Z];
34 | }
35 |
36 | public void update() {
37 | if(doLoad)
38 | load();
39 | }
40 |
41 | public void render() {
42 | if(isLoaded())
43 | vao.render(solidBlocks, 0);
44 | }
45 |
46 | public void load() {
47 | if(vao == null)
48 | vao = new VAO(GL_TRIANGLES);
49 |
50 | vao.initVBO(vertices);
51 | vao.initIBO(indices);
52 | vao.initVAO("3 7 0", "3 7 3", "1 7 6");
53 |
54 | solidBlocks = indices.limit();
55 | doLoad = false;
56 | state = ChunkState.LOADED;
57 | }
58 |
59 | public void unload() {
60 | if(isLoaded())
61 | vao.delete();
62 |
63 | vao = null;
64 | vertices = null;
65 | indices = null;
66 | state = ChunkState.UNLOADED;
67 | }
68 |
69 | public void deleteBlocks() {
70 | for(int x = 0; x < Chunk.SIZE_X; x++)
71 | for(int y = 0; y < Chunk.SIZE_Y; y++)
72 | for(int z = 0; z < Chunk.SIZE_Z; z++) {
73 | blocks[x][y][z] = null;
74 | }
75 | }
76 |
77 | public boolean isGenerated() {
78 | return blocks[SIZE_X - 1][SIZE_Y - 1][SIZE_Z - 1] != null;
79 | }
80 |
81 | public boolean isLoaded() {
82 | return vao != null;
83 | }
84 |
85 | public int getSkyLight(int x, int y, int z) {
86 | return lights[x][y][z] >> 12;
87 | }
88 |
89 | public void setSkyLight(int x, int y, int z, int value) {
90 | if(value < 0) value = 0; else if(value > 15) value = 15;
91 |
92 | lights[x][y][z] = (short) (lights[x][y][z] & 0x0FFF | value << 12);
93 | }
94 |
95 | public int getVoxelLightR(int x, int y, int z) {
96 | return lights[x][y][z] & 0x0F00 >> 8;
97 | }
98 |
99 | public int getVoxelLightG(int x, int y, int z) {
100 | return lights[x][y][z] & 0x00F0 >> 4;
101 | }
102 |
103 | public int getVoxelLightB(int x, int y, int z) {
104 | return lights[x][y][z] & 0x000F >> 0;
105 | }
106 |
107 | public void setVoxelLight(int x, int y, int z, int r, int g, int b) {
108 | if(r < 0) r = 0; else if(r > 15) r = 15;
109 | if(g < 0) g = 0; else if(g > 15) g = 15;
110 | if(b < 0) b = 0; else if(b > 15) b = 15;
111 |
112 | lights[x][y][z] = (short) (lights[x][y][z] & 0xF000 | r << 8 | g << 4 | b << 0);
113 | }
114 |
115 | public Block getBlockAt(int x, int y, int z) {
116 | if(isGenerated() && x >= 0 && x < SIZE_X && y >= 0 && y < SIZE_Y && z >= 0 && z < SIZE_Z)
117 | return blocks[x][y][z];
118 |
119 | return Block.AIR; // temp
120 | }
121 |
122 | public void setBlockAt(int x, int y, int z, Block block) {
123 | if(x >= 0 && x < SIZE_X && y >= 0 && y < SIZE_Y && z >= 0 && z < SIZE_Z)
124 | blocks[x][y][z] = block;
125 | }
126 |
127 | public void doLoad() {
128 | doLoad = true;
129 | }
130 |
131 | public ChunkState getState() {
132 | return state;
133 | }
134 |
135 | public void setState(ChunkState state) {
136 | this.state = state;
137 | }
138 |
139 | public int getX() {
140 | return x;
141 | }
142 |
143 | public int getZ() {
144 | return z;
145 | }
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Input.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import static org.lwjgl.glfw.GLFW.GLFW_CURSOR;
4 | import static org.lwjgl.glfw.GLFW.GLFW_PRESS;
5 | import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
6 | import static org.lwjgl.glfw.GLFW.glfwGetClipboardString;
7 | import static org.lwjgl.glfw.GLFW.glfwGetCursorPos;
8 | import static org.lwjgl.glfw.GLFW.glfwGetInputMode;
9 | import static org.lwjgl.glfw.GLFW.glfwGetKey;
10 | import static org.lwjgl.glfw.GLFW.glfwGetMouseButton;
11 | import static org.lwjgl.glfw.GLFW.glfwSetClipboardString;
12 | import static org.lwjgl.glfw.GLFW.glfwSetCursorPos;
13 | import static org.lwjgl.glfw.GLFW.glfwSetInputMode;
14 | import static org.lwjgl.glfw.GLFW.glfwSetScrollCallback;
15 |
16 | import java.nio.DoubleBuffer;
17 |
18 | import org.lwjgl.BufferUtils;
19 | import org.lwjgl.glfw.GLFWScrollCallback;
20 |
21 | public class Input {
22 |
23 | private static final boolean[] KEY_BUTTONS = new boolean[349];
24 | private static final boolean[] MOUSE_BUTTONS = new boolean[8];
25 |
26 | private static GLFWScrollCallback scrollCallback;
27 | static {
28 | glfwSetScrollCallback(Display.getWindow(), scrollCallback = new GLFWScrollCallback() {
29 |
30 | @Override
31 | public void invoke(long window, double xoffset, double yoffset) {
32 | mouseWheel = (int) yoffset;
33 | scrolled = true;
34 | }
35 |
36 | });
37 | }
38 | private static int mouseWheel;
39 | private static boolean scrolled;
40 |
41 | private static int lastMouseX = (int) getMousePos().getX();
42 | private static int lastMouseY = (int) getMousePos().getY();
43 |
44 | private static int mouseDX;
45 | private static int mouseDY;
46 |
47 | public static void update() {
48 | for(int i = 0; i < KEY_BUTTONS.length; i++)
49 | KEY_BUTTONS[i] = getKey(i);
50 |
51 | for(int i = 0; i < MOUSE_BUTTONS.length; i++)
52 | MOUSE_BUTTONS[i] = getMouse(i);
53 |
54 | int mouseX = (int) getMousePos().getX();
55 | int mouseY = (int) getMousePos().getY();
56 |
57 | mouseDX = mouseX - lastMouseX;
58 | mouseDY = mouseY - lastMouseY;
59 |
60 | lastMouseX = mouseX;
61 | lastMouseY = mouseY;
62 |
63 | scrolled = false;
64 | }
65 |
66 | public static void destroy() {
67 | if(scrollCallback != null)
68 | scrollCallback.release();
69 | }
70 |
71 | public static boolean getKey(int key) {
72 | return glfwGetKey(Display.getWindow(), key) == GLFW_PRESS;
73 | }
74 |
75 | public static boolean getKeyDown(int key) {
76 | return !KEY_BUTTONS[key] && glfwGetKey(Display.getWindow(), key) == GLFW_PRESS;
77 | }
78 |
79 | public static boolean getKeyUp(int key) {
80 | return KEY_BUTTONS[key] && glfwGetKey(Display.getWindow(), key) == GLFW_RELEASE;
81 | }
82 |
83 | public static boolean getMouse(int mouse) {
84 | return glfwGetMouseButton(Display.getWindow(), mouse) == GLFW_PRESS;
85 | }
86 |
87 | public static boolean getMouseDown(int mouse) {
88 | return !MOUSE_BUTTONS[mouse] && glfwGetMouseButton(Display.getWindow(), mouse) == GLFW_PRESS;
89 | }
90 |
91 | public static boolean getMouseUp(int mouse) {
92 | return MOUSE_BUTTONS[mouse] && glfwGetMouseButton(Display.getWindow(), mouse) == GLFW_RELEASE;
93 | }
94 |
95 | public static int getMouseDX() {
96 | return mouseDX;
97 | }
98 |
99 | public static int getMouseDY() {
100 | return mouseDY;
101 | }
102 |
103 | public static int getMouseWheel() {
104 | return scrolled ? mouseWheel : 0;
105 | }
106 |
107 | public static int getCursorMode() {
108 | return glfwGetInputMode(Display.getWindow(), GLFW_CURSOR);
109 | }
110 |
111 | public static void setCursorMode(int mode) {
112 | glfwSetInputMode(Display.getWindow(), GLFW_CURSOR, mode);
113 | }
114 |
115 | public static Vector2 getMousePos() {
116 | DoubleBuffer x = BufferUtils.createDoubleBuffer(1), y = BufferUtils.createDoubleBuffer(1);
117 |
118 | glfwGetCursorPos(Display.getWindow(), x, y);
119 |
120 | return new Vector2((float) x.get(), (float) y.get());
121 | }
122 |
123 | public static void setMousePos(int x, int y) {
124 | glfwSetCursorPos(Display.getWindow(), x, y);
125 | }
126 |
127 | public static String getClipboard() {
128 | return glfwGetClipboardString(Display.getWindow());
129 | }
130 |
131 | public static void setClipboard(String str) {
132 | glfwSetClipboardString(Display.getWindow(), str);
133 | }
134 |
135 | }
136 |
--------------------------------------------------------------------------------
/src/de/meinkraft/Meinkraft.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_F;
4 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_P;
5 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_R;
6 | import static org.lwjgl.opengl.GL11.*;
7 | import static org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE;
8 |
9 | import java.io.IOException;
10 | import java.util.Locale;
11 |
12 | import de.meinkraft.gui.GUI;
13 | import de.meinkraft.gui.GUIFont;
14 | import de.meinkraft.gui.GUILabel;
15 | import de.meinkraft.lib.Camera;
16 | import de.meinkraft.lib.Display;
17 | import de.meinkraft.lib.Input;
18 | import de.meinkraft.lib.Matrix4;
19 | import de.meinkraft.lib.Shader;
20 | import de.meinkraft.lib.Texture;
21 | import de.meinkraft.lib.Time;
22 | import de.meinkraft.lib.Transform;
23 | import de.meinkraft.lib.Utils;
24 |
25 | public class Meinkraft {
26 |
27 | private Camera camera;
28 | private int textures;
29 | private Shader shader;
30 |
31 | private GUILabel guiText;
32 |
33 | private boolean fog;
34 |
35 | private World world;
36 |
37 | public Meinkraft() {
38 | camera = new Camera(new Matrix4().initPerspective(70f, (float) Display.getWidth() / (float) Display.getHeight(), 0.01f, 1000f));
39 |
40 | try {
41 | textures = Texture.loadTexture2DArray(Utils.getResourceAsStream("/terrain.png"), 64, 64, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE);
42 | } catch (IOException e1) {
43 | e1.printStackTrace();
44 | }
45 | try {
46 | shader = Shader.loadShader("/shader.vs", "/shader.fs", null);
47 | shader.addUniform("p");
48 | shader.addUniform("v");
49 | shader.addUniform("m");
50 | shader.addUniform("enableFog");
51 |
52 | shader.bind();
53 | shader.setUniform("p", camera.getProjectionMatrix());
54 | shader.setUniform("m", new Transform().getTransformationMatrix());
55 | shader.setUniform("enableFog", 0);
56 |
57 | Shader.unbind();
58 | } catch (IOException e) {
59 | e.printStackTrace();
60 | }
61 |
62 | guiText = new GUILabel(0.5f, 0.05f, 200, 50);
63 | guiText.setOrientationX(1);
64 | guiText.setOrientationY(0);
65 |
66 | world = new World("World", new WorldGeneratorFlat());
67 | }
68 |
69 | public void input() {
70 | camera.input();
71 |
72 | if(Input.getKeyDown(GLFW_KEY_F)) {
73 | shader.bind();
74 | shader.setUniform("enableFog", fog ? 0 : 1);
75 | fog = !fog;
76 | Shader.unbind();
77 | }
78 |
79 | if(Input.getKeyDown(GLFW_KEY_P)) {
80 | try {
81 | StructureLoader.loadStructure(world, (int) Math.floor(-camera.getTransform().getTranslation().getX()), 64, (int) Math.floor(-camera.getTransform().getTranslation().getZ()), Utils.getResourceAsStream("/structure_house.txt"));
82 | } catch (IOException e) {
83 | // TODO Auto-generated catch block
84 | e.printStackTrace();
85 | }
86 | }
87 |
88 | // for debug
89 | if(Input.getKeyDown(GLFW_KEY_R)) {
90 | world.setWorldGenerator(new WorldGeneratorNormal());
91 | world.getChunkManager().regenerate();
92 | }
93 | }
94 |
95 | public void update() {
96 | // temp
97 | world.getPlayer().pos = camera.getTransform().getTranslation().negate();
98 | world.getPlayer().dir = camera.getDirection().negate();
99 | world.update();
100 |
101 | Display.setTitle("FPS " + String.format(Locale.ENGLISH, "%.2f", 1.0f / Time.getDelta()) + " cx:" + world.getChunkManager().getPlayerChunkPositionX() + " cz:" + world.getChunkManager().getPlayerChunkPositionZ());
102 | if(Display.wasResized()) {
103 | camera.getProjectionMatrix().initPerspective(70f, (float) Display.getWidth() / (float) Display.getHeight(), 0.01f, 1000f);
104 | GUI.ORTHO.initOrthographic(0, Display.getWidth(), 0, Display.getHeight(), -1, 1);
105 |
106 | shader.bind();
107 | shader.setUniform("p", camera.getProjectionMatrix());
108 |
109 | GUI.SHADER.bind();
110 | GUI.SHADER.setUniform("p", GUI.ORTHO);
111 | GUIFont.SHADER.bind();
112 | GUIFont.SHADER.setUniform("p", GUI.ORTHO);
113 | Shader.unbind();
114 |
115 | glViewport(0, 0, Display.getWidth(), Display.getHeight());
116 | }
117 | }
118 |
119 | public void render() {
120 | shader.bind();
121 | shader.setUniform("v", camera.getViewMatrix());
122 | Texture.bindTexture2DArray(textures);
123 | world.render();
124 |
125 | glCullFace(GL_FRONT);
126 | guiText.draw();
127 | GUILabel.font.drawString("BlA", 0, 0);
128 | glCullFace(GL_BACK);
129 |
130 | Shader.unbind();
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/src/de/meinkraft/gui/GUIFont.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.gui;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStreamReader;
6 |
7 | import de.meinkraft.lib.Shader;
8 | import de.meinkraft.lib.Texture;
9 | import de.meinkraft.lib.Transform;
10 | import de.meinkraft.lib.Utils;
11 | import de.meinkraft.lib.Vector3;
12 | import static org.lwjgl.opengl.GL11.*;
13 | import static org.lwjgl.opengl.GL12.*;
14 | import static org.lwjgl.opengl.GL20.*;
15 |
16 | public class GUIFont {
17 |
18 | public static Shader SHADER;
19 | static {
20 | try {
21 | SHADER = Shader.loadShader("/font.vs", "/font.fs", null);
22 | SHADER.addUniform("p");
23 | SHADER.addUniform("v");
24 | SHADER.addUniform("m");
25 | SHADER.addUniform("size");
26 |
27 | SHADER.bind();
28 | SHADER.setUniform("p", GUI.ORTHO);
29 | SHADER.setUniform("v", new Transform().getTransformationMatrix());
30 | SHADER.setUniform("m", new Transform().getTransformationMatrix());
31 | SHADER.setUniform("size", 1.0f);
32 | Shader.unbind();
33 | } catch (IOException e) {
34 | e.printStackTrace();
35 | }
36 | }
37 |
38 | private GUIFontCharacter[] chars;
39 | private int atlas;
40 | private int fontsize;
41 | private Vector3 color;
42 |
43 | public GUIFont(String name, int size) {
44 | chars = new GUIFontCharacter[256];
45 |
46 | BufferedReader bR = new BufferedReader(new InputStreamReader(Utils.getResourceAsStream("/" + name + ".fnt")));
47 | String line;
48 | try {
49 | while((line = bR.readLine()) != null) {
50 | line = line.replaceAll("\\s+", " ");
51 |
52 | if(line.startsWith("char ")) {
53 | String[] meta = line.split(" ");
54 | chars[Integer.parseInt(meta[1].split("=")[1])] = new GUIFontCharacter(Integer.parseInt(meta[2].split("=")[1]), Integer.parseInt(meta[3].split("=")[1]), Integer.parseInt(meta[4].split("=")[1]), Integer.parseInt(meta[5].split("=")[1]), Integer.parseInt(meta[6].split("=")[1]), Integer.parseInt(meta[7].split("=")[1]), Integer.parseInt(meta[8].split("=")[1]));
55 | } else if(line.startsWith("info "))
56 | fontsize = Integer.parseInt(line.substring(line.indexOf("size=")).split(" ")[0].split("=")[1]);
57 | }
58 | } catch (IOException e) {
59 | e.printStackTrace();
60 | }
61 |
62 | try {
63 | atlas = Texture.loadTexture2D(Utils.getResourceAsStream("/" + name + ".png"), GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_CLAMP_TO_EDGE);
64 | } catch (IOException e) {
65 | e.printStackTrace();
66 | }
67 |
68 | setSize(size);
69 | color = new Vector3();
70 | }
71 |
72 | public void drawString(String text, int x, int y) {
73 | int adv = 0;
74 |
75 | // glEnable(GL_BLEND);
76 | // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
77 |
78 | SHADER.bind();
79 | Texture.bindTexture2D(atlas);
80 | glBegin(GL_QUADS);
81 | {
82 | glVertexAttrib3f(2, color.getX(), color.getY(), color.getZ());
83 |
84 | for(char c : text.toCharArray()) {
85 | GUIFontCharacter gfc = chars[(int) c];
86 |
87 | glVertexAttrib2f(1, gfc.getX() / 512.0f, gfc.getY() / 512.0f);
88 | glVertex2f(adv + gfc.getXoff() + x, gfc.getYoff() + y - 8);
89 |
90 | glVertexAttrib2f(1, (gfc.getX() + gfc.getW()) / 512.0f, gfc.getY() / 512.0f);
91 | glVertex2f(adv + gfc.getXoff() + x + gfc.getW(), gfc.getYoff() + y - 8);
92 |
93 | glVertexAttrib2f(1, (gfc.getX() + gfc.getW()) / 512.0f, (gfc.getY() + gfc.getH()) / 512.0f);
94 | glVertex2f(adv + gfc.getXoff() + x + gfc.getW(), gfc.getYoff() + y + gfc.getH() - 8);
95 |
96 | glVertexAttrib2f(1, gfc.getX() / 512.0f, (gfc.getY() + gfc.getH()) / 512.0f);
97 | glVertex2f(adv + gfc.getXoff() + x, gfc.getYoff() + y + gfc.getH() - 8);
98 |
99 | adv += gfc.getXadv() - 16; // padding left & right
100 | }
101 | }
102 | glEnd();
103 | }
104 |
105 | public int getWidth(String text) {
106 | int width = 0;
107 |
108 | for(char c : text.toCharArray()) {
109 | GUIFontCharacter gfc = chars[(int) c];
110 |
111 | width += gfc.getW() + gfc.getXoff();
112 | }
113 |
114 | return width;
115 | }
116 |
117 | public void setSize(int size) {
118 | SHADER.bind();
119 | SHADER.setUniform("m", new Transform(new Vector3(), new Vector3(), new Vector3((float) size / fontsize)).getTransformationMatrix());
120 |
121 | float fs = (float) size / fontsize;
122 |
123 | if(fs < 1)
124 | fs = 0.8f;
125 |
126 | SHADER.setUniform("size", fs);
127 | Shader.unbind();
128 | }
129 |
130 | public void setColor(Vector3 color) {
131 | this.color = color;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Camera.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import static org.lwjgl.glfw.GLFW.GLFW_CURSOR_DISABLED;
4 | import static org.lwjgl.glfw.GLFW.GLFW_CURSOR_NORMAL;
5 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_A;
6 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_D;
7 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_E;
8 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE;
9 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT;
10 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_Q;
11 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_S;
12 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_W;
13 | import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_1;
14 |
15 | public class Camera implements InputController {
16 |
17 | public static final float MOV_SPEED = 5;
18 | public static final float ROT_SPEED = 0.1f;
19 |
20 | private boolean lockMov, lockRot;
21 |
22 | private Matrix4 projection;
23 | private Transform transform;
24 |
25 | public Camera(Matrix4 projection) {
26 | this.projection = projection;
27 | this.transform = new Transform();
28 | }
29 |
30 | @Override
31 | public void input() {
32 | if(Input.getCursorMode() == GLFW_CURSOR_DISABLED) {
33 | if(Input.getKeyDown(GLFW_KEY_ESCAPE)) {
34 | Input.setCursorMode(GLFW_CURSOR_NORMAL);
35 | Input.setMousePos(Display.getWidth() / 2, Display.getHeight() / 2);
36 | } else {
37 | if(!lockMov) {
38 | Vector3 forward = getDirection();
39 | Vector3 sideward = new Vector3(getViewMatrix().get(0, 0), getViewMatrix().get(0, 1), getViewMatrix().get(0, 2));
40 |
41 | float MOV_SPEED = Camera.MOV_SPEED;
42 | if(Input.getKey(GLFW_KEY_LEFT_SHIFT))
43 | MOV_SPEED *= 15;
44 |
45 | if(Input.getKey(GLFW_KEY_W))
46 | transform.setTranslation(transform.getTranslation().add(forward.mul(MOV_SPEED * Time.getDelta())));
47 |
48 | if(Input.getKey(GLFW_KEY_S))
49 | transform.setTranslation(transform.getTranslation().add(forward.mul(-MOV_SPEED * Time.getDelta())));
50 |
51 | if(Input.getKey(GLFW_KEY_A))
52 | transform.setTranslation(transform.getTranslation().add(sideward.mul(MOV_SPEED * Time.getDelta())));
53 |
54 | if(Input.getKey(GLFW_KEY_D))
55 | transform.setTranslation(transform.getTranslation().add(sideward.mul(-MOV_SPEED * Time.getDelta())));
56 |
57 | if(Input.getKey(GLFW_KEY_Q))
58 | transform.setTranslation(transform.getTranslation().add(new Vector3(0, -MOV_SPEED, 0).mul(Time.getDelta())));
59 |
60 | if(Input.getKey(GLFW_KEY_E))
61 | transform.setTranslation(transform.getTranslation().add(new Vector3(0, MOV_SPEED, 0).mul(Time.getDelta())));
62 | }
63 |
64 | if(!lockRot) {
65 | int x = Input.getMouseDX();
66 | int y = Input.getMouseDY();
67 |
68 | if(x != 0)
69 | transform.getRotation().setY(transform.getRotation().getY() + (float) x * ROT_SPEED);
70 |
71 | if(y != 0)
72 | transform.getRotation().setX(transform.getRotation().getX() + (float) y * ROT_SPEED);
73 | }
74 | }
75 | } else if(Input.getCursorMode() == GLFW_CURSOR_NORMAL) {
76 | if(Input.getMouseDown(GLFW_MOUSE_BUTTON_1))
77 | Input.setCursorMode(GLFW_CURSOR_DISABLED);
78 | }
79 | }
80 |
81 | public void update() {
82 | // // AUDIO
83 | // alListener(AL_POSITION, transform.getTranslation().negate().asFloatBuffer());
84 | // alListener(AL_VELOCITY, new Vector3().asFloatBuffer());
85 | //
86 | // Vector3 at = getViewMatrix().zVector3().negate();
87 | // Vector3 up = getViewMatrix().yVector3();
88 | // FloatBuffer buffer = BufferUtils.createFloatBuffer(6).put(new float[] {at.getX(), at.getY(), at.getZ(), up.getX(), up.getY(), up.getZ()});
89 | // buffer.flip();
90 | //
91 | // alListenerfv(AL_ORIENTATION, buffer);
92 | }
93 |
94 | public Matrix4 getViewMatrix() {
95 | Matrix4 t = new Matrix4().initTranslation(transform.getTranslation());
96 | Matrix4 r = new Matrix4().initRotation(transform.getRotation(), Matrix4.YXZ);
97 |
98 | return r.mul(t);
99 | }
100 |
101 | public Vector3 getDirection() {
102 | return new Vector3(getViewMatrix().get(2, 0), getViewMatrix().get(2, 1), getViewMatrix().get(2, 2));
103 | }
104 |
105 | public void lockMovement(boolean lock) {
106 | lockMov = lock;
107 | }
108 |
109 | public void lockRotation(boolean lock) {
110 | lockRot = lock;
111 | }
112 |
113 | public Matrix4 getProjectionMatrix() {
114 | return projection;
115 | }
116 |
117 | public void setProjectionMatrix(Matrix4 projection) {
118 | this.projection = projection;
119 | }
120 |
121 | public Transform getTransform() {
122 | return transform;
123 | }
124 |
125 | public void setTransform(Transform transform) {
126 | this.transform = transform;
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Shader.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
4 | import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER;
5 | import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
6 | import static org.lwjgl.opengl.GL20.GL_VALIDATE_STATUS;
7 | import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER;
8 | import static org.lwjgl.opengl.GL20.glAttachShader;
9 | import static org.lwjgl.opengl.GL20.glBindAttribLocation;
10 | import static org.lwjgl.opengl.GL20.glCompileShader;
11 | import static org.lwjgl.opengl.GL20.glCreateProgram;
12 | import static org.lwjgl.opengl.GL20.glCreateShader;
13 | import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
14 | import static org.lwjgl.opengl.GL20.glGetProgrami;
15 | import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
16 | import static org.lwjgl.opengl.GL20.glGetShaderi;
17 | import static org.lwjgl.opengl.GL20.glGetUniformLocation;
18 | import static org.lwjgl.opengl.GL20.glLinkProgram;
19 | import static org.lwjgl.opengl.GL20.glShaderSource;
20 | import static org.lwjgl.opengl.GL20.glUniform1i;
21 | import static org.lwjgl.opengl.GL20.glUniform1f;
22 | import static org.lwjgl.opengl.GL20.glUniform2f;
23 | import static org.lwjgl.opengl.GL20.glUniform3f;
24 | import static org.lwjgl.opengl.GL20.glUniform4f;
25 | import static org.lwjgl.opengl.GL20.glUniformMatrix4fv;
26 | import static org.lwjgl.opengl.GL20.glUseProgram;
27 | import static org.lwjgl.opengl.GL20.glValidateProgram;
28 |
29 | import org.lwjgl.BufferUtils;
30 | import org.lwjgl.opengl.OpenGLException;
31 |
32 | import java.io.IOException;
33 | import java.nio.FloatBuffer;
34 | import java.util.HashMap;
35 |
36 | public class Shader {
37 |
38 | private HashMap uniforms;
39 |
40 | private int id;
41 |
42 | public Shader(int id) {
43 | this.id = id;
44 |
45 | uniforms = new HashMap();
46 | }
47 |
48 | public void bind() {
49 | glUseProgram(id);
50 | }
51 |
52 | public void bindAttribute(int index, String attribute) {
53 | glBindAttribLocation(id, index, attribute);
54 | }
55 |
56 | public void addUniform(String uniform) {
57 | int uniformLoc = glGetUniformLocation(id, uniform);
58 |
59 | if(uniformLoc == -1)
60 | throw new OpenGLException("Shader: could not find uniform " + uniform);
61 |
62 | uniforms.put(uniform, uniformLoc);
63 | }
64 |
65 | public void setUniform(String uniform, int v) {
66 | glUniform1i(uniforms.get(uniform), v);
67 | }
68 |
69 | public void setUniform(String uniform, float v) {
70 | glUniform1f(uniforms.get(uniform), v);
71 | }
72 |
73 | public void setUniform(String uniform, Vector2 v) {
74 | glUniform2f(uniforms.get(uniform), v.getX(), v.getY());
75 | }
76 |
77 | public void setUniform(String uniform, Vector3 v) {
78 | glUniform3f(uniforms.get(uniform), v.getX(), v.getY(), v.getZ());
79 | }
80 |
81 | public void setUniform(String uniform, Vector4 v) {
82 | glUniform4f(uniforms.get(uniform), v.getX(), v.getY(), v.getZ(), v.getW());
83 | }
84 |
85 | public void setUniform(String uniform, Matrix4 v) {
86 | FloatBuffer buffer = BufferUtils.createFloatBuffer(4 * 4);
87 |
88 | for(int x = 0; x < 4; x++)
89 | for(int y = 0; y < 4; y++)
90 | buffer.put(v.get(x, y));
91 |
92 | buffer.flip();
93 |
94 | glUniformMatrix4fv(uniforms.get(uniform), true, buffer);
95 | }
96 |
97 | public int getId() {
98 | return id;
99 | }
100 |
101 | public static void unbind() {
102 | glUseProgram(0);
103 | }
104 |
105 | public static Shader loadShader(String vs, String fs, String[] attributes) throws IOException {
106 | int id = glCreateProgram();
107 |
108 | if(id == 0)
109 | throw new OpenGLException("Could not find a valid memory location for shader program");
110 |
111 | // vertex shader
112 | int vsId = glCreateShader(GL_VERTEX_SHADER);
113 |
114 | if(vsId == 0)
115 | throw new OpenGLException("Could not find a valid memory location for shader type");
116 |
117 | glShaderSource(vsId, Utils.readFileToString(vs));
118 | glCompileShader(vsId);
119 |
120 | if(glGetShaderi(vsId, GL_COMPILE_STATUS) == 0)
121 | throw new OpenGLException(glGetShaderInfoLog(vsId, 1024));
122 |
123 | glAttachShader(id, vsId);
124 |
125 | // fragment shader
126 | int fsId = glCreateShader(GL_FRAGMENT_SHADER);
127 |
128 | if(fsId == 0)
129 | throw new OpenGLException("Could not find a valid memory location for shader type");
130 |
131 | glShaderSource(fsId, Utils.readFileToString(fs));
132 | glCompileShader(fsId);
133 |
134 | if(glGetShaderi(fsId, GL_COMPILE_STATUS) == 0)
135 | throw new OpenGLException(glGetShaderInfoLog(fsId, 1024));
136 |
137 | glAttachShader(id, fsId);
138 |
139 | Shader shader = new Shader(id);
140 | if(attributes != null) {
141 | for(int i = 0; i < attributes.length; i++)
142 | shader.bindAttribute(i, attributes[i]);
143 | }
144 |
145 | glLinkProgram(id);
146 |
147 | if(glGetProgrami(id, GL_LINK_STATUS) == 0)
148 | throw new OpenGLException(glGetProgramInfoLog(id, 1024));
149 |
150 | glValidateProgram(id);
151 |
152 | if(glGetProgrami(id, GL_VALIDATE_STATUS) == 0)
153 | throw new OpenGLException(glGetProgramInfoLog(id, 1024));
154 |
155 | return shader;
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/src/de/meinkraft/ChunkLoader.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.util.ArrayDeque;
4 |
5 | import org.lwjgl.BufferUtils;
6 |
7 | public class ChunkLoader extends Thread {
8 |
9 | private ArrayDeque queue, queue2;
10 |
11 | private final ChunkManager chunkManager;
12 |
13 | public ChunkLoader(ChunkManager chunkManager) {
14 | this.chunkManager = chunkManager;
15 |
16 | queue = new ArrayDeque();
17 | queue2 = new ArrayDeque();
18 | start();
19 | }
20 |
21 | public synchronized void addChunk(Chunk chunk) {
22 | if(queue.contains(chunk))
23 | return;
24 |
25 | chunk.setState(ChunkState.LOADING);
26 | queue.add(chunk);
27 | notify();
28 | }
29 |
30 | @Override
31 | public void run() {
32 | while(isAlive()) {
33 | if(!queue.isEmpty()) {
34 | Chunk chunk = queue.peek();
35 |
36 | if(!chunkManager.isChunkInRange(chunk.getX(), chunk.getZ())) {
37 | if(chunkManager.hasChunkNeighboursLoading(chunk))
38 | continue;
39 |
40 | chunk.setState(ChunkState.UNLOADED);
41 | queue.remove();
42 | } else {
43 | // System.out.println(chunk.getX() + "," + chunk.getZ() + " generating");
44 | chunkManager.getWorld().getWorldGenerator().generate(chunk);
45 |
46 | if(!queue2.contains(chunk))
47 | queue2.add(queue.poll());
48 | }
49 | }
50 |
51 | if(!queue2.isEmpty()) {
52 | Chunk chunk = queue2.peek();
53 |
54 | if(!chunkManager.isChunkInRange(chunk.getX(), chunk.getZ())) {
55 | if(chunkManager.hasChunkNeighboursLoading(chunk))
56 | continue;
57 |
58 | chunk.setState(ChunkState.UNLOADED);
59 | queue2.remove();
60 | continue;
61 | }
62 |
63 | // if(chunk.isGenerated()) {
64 | if(!chunkManager.isChunkSurrounded(chunk))
65 | continue;
66 |
67 | System.out.println(chunk.getX() + "," + chunk.getZ() + " loading");
68 | int vcount = 0;
69 | for(int x = 0; x < Chunk.SIZE_X; x++)
70 | for(int y = 0; y < Chunk.SIZE_Y; y++)
71 | for(int z = 0; z < Chunk.SIZE_Z; z++) {
72 | Blockcheck bc = new Blockcheck();
73 |
74 | int wx = chunk.getX() * Chunk.SIZE_X + x;
75 | int wz = chunk.getZ() * Chunk.SIZE_Z + z;
76 |
77 | if(chunkManager.getBlockAt(wx + 1, y, wz).getType().isSolid() && chunkManager.getBlockAt(wx + 1, y, wz).getMaterial().isOpaque())
78 | bc.east = true;
79 |
80 | if(chunkManager.getBlockAt(wx - 1, y, wz).getType().isSolid() && chunkManager.getBlockAt(wx - 1, y, wz).getMaterial().isOpaque())
81 | bc.west = true;
82 |
83 | if(chunkManager.getBlockAt(wx, y + 1, wz).getType().isSolid() && chunkManager.getBlockAt(wx, y + 1, wz).getMaterial().isOpaque())
84 | bc.top = true;
85 |
86 | if(chunkManager.getBlockAt(wx, y - 1, wz).getType().isSolid() && chunkManager.getBlockAt(wx, y - 1, wz).getMaterial().isOpaque())
87 | bc.bottom = true;
88 |
89 | if(chunkManager.getBlockAt(wx, y, wz + 1).getType().isSolid() && chunkManager.getBlockAt(wx, y, wz + 1).getMaterial().isOpaque())
90 | bc.south = true;
91 |
92 | if(chunkManager.getBlockAt(wx, y, wz - 1).getType().isSolid() && chunkManager.getBlockAt(wx, y, wz - 1).getMaterial().isOpaque())
93 | bc.north = true;
94 |
95 | vcount += chunk.getBlockAt(x, y, z).getType().getVerticesCount(bc);
96 | }
97 |
98 | chunk.vertices = BufferUtils.createFloatBuffer(vcount * 7);
99 | for(int x = 0; x < Chunk.SIZE_X; x++)
100 | for(int y = 0; y < Chunk.SIZE_Y; y++)
101 | for(int z = 0; z < Chunk.SIZE_Z; z++) {
102 | Blockcheck bc = new Blockcheck();
103 | BlockAO ao = new BlockAO();
104 |
105 | int wx = chunk.getX() * Chunk.SIZE_X + x;
106 | int wz = chunk.getZ() * Chunk.SIZE_Z + z;
107 |
108 | if(chunkManager.getBlockAt(wx + 1, y, wz).getType().isSolid() && chunkManager.getBlockAt(wx + 1, y, wz).getMaterial().isOpaque())
109 | bc.east = true;
110 |
111 | if(chunkManager.getBlockAt(wx - 1, y, wz).getType().isSolid() && chunkManager.getBlockAt(wx - 1, y, wz).getMaterial().isOpaque())
112 | bc.west = true;
113 |
114 | if(chunkManager.getBlockAt(wx, y + 1, wz).getType().isSolid() && chunkManager.getBlockAt(wx, y + 1, wz).getMaterial().isOpaque())
115 | bc.top = true;
116 |
117 | if(chunkManager.getBlockAt(wx, y - 1, wz).getType().isSolid() && chunkManager.getBlockAt(wx, y - 1, wz).getMaterial().isOpaque())
118 | bc.bottom = true;
119 |
120 | if(chunkManager.getBlockAt(wx, y, wz + 1).getType().isSolid() && chunkManager.getBlockAt(wx, y, wz + 1).getMaterial().isOpaque())
121 | bc.south = true;
122 |
123 | if(chunkManager.getBlockAt(wx, y, wz - 1).getType().isSolid() && chunkManager.getBlockAt(wx, y, wz - 1).getMaterial().isOpaque())
124 | bc.north = true;
125 |
126 | if(!bc.all()) {
127 | if(chunkManager.getBlockAt(wx + 1, y + 1, wz).getType().isSolid() && chunkManager.getBlockAt(wx + 1, y + 1, wz).getMaterial().isOpaque())
128 | ao.eT = true;
129 | if(chunkManager.getBlockAt(wx + 1, y - 1, wz).getType().isSolid() && chunkManager.getBlockAt(wx + 1, y - 1, wz).getMaterial().isOpaque())
130 | ao.eB = true;
131 | if(chunkManager.getBlockAt(wx - 1, y + 1, wz).getType().isSolid() && chunkManager.getBlockAt(wx - 1, y + 1, wz).getMaterial().isOpaque())
132 | ao.wT = true;
133 | if(chunkManager.getBlockAt(wx - 1, y - 1, wz).getType().isSolid() && chunkManager.getBlockAt(wx - 1, y - 1, wz).getMaterial().isOpaque())
134 | ao.wB = true;
135 | if(chunkManager.getBlockAt(wx, y + 1, wz + 1).getType().isSolid() && chunkManager.getBlockAt(wx, y + 1, wz + 1).getMaterial().isOpaque())
136 | ao.sT = true;
137 | if(chunkManager.getBlockAt(wx, y - 1, wz + 1).getType().isSolid() && chunkManager.getBlockAt(wx, y - 1, wz + 1).getMaterial().isOpaque())
138 | ao.sB = true;
139 | if(chunkManager.getBlockAt(wx, y + 1, wz - 1).getType().isSolid() && chunkManager.getBlockAt(wx, y + 1, wz - 1).getMaterial().isOpaque())
140 | ao.nT = true;
141 | if(chunkManager.getBlockAt(wx, y - 1, wz - 1).getType().isSolid() && chunkManager.getBlockAt(wx, y - 1, wz - 1).getMaterial().isOpaque())
142 | ao.nB = true;
143 |
144 | if(chunkManager.getBlockAt(wx + 1, y + 1, wz + 1).getType().isSolid() && chunkManager.getBlockAt(wx + 1, y + 1, wz + 1).getMaterial().isOpaque())
145 | ao.cXYZ = true;
146 | if(chunkManager.getBlockAt(wx - 1, y + 1, wz + 1).getType().isSolid() && chunkManager.getBlockAt(wx - 1, y + 1, wz + 1).getMaterial().isOpaque())
147 | ao.c_XYZ = true;
148 | if(chunkManager.getBlockAt(wx + 1, y - 1, wz + 1).getType().isSolid() && chunkManager.getBlockAt(wx + 1, y - 1, wz + 1).getMaterial().isOpaque())
149 | ao.cX_YZ = true;
150 | if(chunkManager.getBlockAt(wx + 1, y + 1, wz - 1).getType().isSolid() && chunkManager.getBlockAt(wx + 1, y + 1, wz - 1).getMaterial().isOpaque())
151 | ao.cXY_Z = true;
152 | if(chunkManager.getBlockAt(wx - 1, y - 1, wz + 1).getType().isSolid() && chunkManager.getBlockAt(wx - 1, y - 1, wz + 1).getMaterial().isOpaque())
153 | ao.c_X_YZ = true;
154 | if(chunkManager.getBlockAt(wx + 1, y - 1, wz - 1).getType().isSolid() && chunkManager.getBlockAt(wx + 1, y - 1, wz - 1).getMaterial().isOpaque())
155 | ao.cX_Y_Z = true;
156 | if(chunkManager.getBlockAt(wx - 1, y + 1, wz - 1).getType().isSolid() && chunkManager.getBlockAt(wx - 1, y + 1, wz - 1).getMaterial().isOpaque())
157 | ao.c_XY_Z = true;
158 | if(chunkManager.getBlockAt(wx - 1, y - 1, wz - 1).getType().isSolid() && chunkManager.getBlockAt(wx - 1, y - 1, wz - 1).getMaterial().isOpaque())
159 | ao.c_X_Y_Z = true;
160 | }
161 |
162 | chunk.getBlockAt(x, y, z).getType().addVertices(wx, y, wz, chunk.vertices, bc, ao, chunk.getBlockAt(x, y, z).getTextures());
163 | }
164 | chunk.vertices.flip();
165 |
166 | chunk.indices = BufferUtils.createIntBuffer(chunk.vertices.limit() / 4 * 6);
167 | for(int i = 0, j = 0; i < chunk.indices.limit(); i += 6, j += 4) {
168 | chunk.indices.put(j + 0);
169 | chunk.indices.put(j + 1);
170 | chunk.indices.put(j + 2);
171 | chunk.indices.put(j + 0);
172 | chunk.indices.put(j + 2);
173 | chunk.indices.put(j + 3);
174 | }
175 | chunk.indices.flip();
176 | chunk.doLoad();
177 |
178 | queue2.remove();
179 | // }
180 |
181 | continue;
182 | }
183 |
184 | synchronized (this) {
185 | try {
186 | System.out.println("waiting");
187 | wait();
188 | } catch (InterruptedException e) {
189 | e.printStackTrace();
190 | return;
191 | }
192 | }
193 | }
194 | }
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Texture.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | import static org.lwjgl.opengl.GL13.GL_MAX_TEXTURE_UNITS;
4 | import static org.lwjgl.opengl.GL11.GL_LINEAR_MIPMAP_LINEAR;
5 | import static org.lwjgl.opengl.GL11.GL_LINEAR_MIPMAP_NEAREST;
6 | import static org.lwjgl.opengl.GL11.GL_NEAREST_MIPMAP_LINEAR;
7 | import static org.lwjgl.opengl.GL11.GL_NEAREST_MIPMAP_NEAREST;
8 | import static org.lwjgl.opengl.GL11.GL_RGBA;
9 | import static org.lwjgl.opengl.GL11.GL_RGBA8;
10 | import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
11 | import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
12 | import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
13 | import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_S;
14 | import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_T;
15 | import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
16 | import static org.lwjgl.opengl.GL11.glGenTextures;
17 | import static org.lwjgl.opengl.GL11.glTexImage2D;
18 | import static org.lwjgl.opengl.GL11.glTexParameteri;
19 | import static org.lwjgl.opengl.GL30.GL_TEXTURE_2D_ARRAY;
20 | import static org.lwjgl.opengl.GL30.glGenerateMipmap;
21 | import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D;
22 | import static org.lwjgl.opengl.GL12.GL_TEXTURE_WRAP_R;
23 | import static org.lwjgl.opengl.GL12.glTexImage3D;
24 | import static org.lwjgl.opengl.GL12.glTexSubImage3D;
25 | import static org.lwjgl.opengl.GL11.glBindTexture;
26 | import static org.lwjgl.opengl.GL13.glActiveTexture;
27 |
28 | import java.awt.image.BufferedImage;
29 | import java.io.IOException;
30 | import java.io.InputStream;
31 | import java.nio.ByteBuffer;
32 |
33 | import javax.imageio.ImageIO;
34 |
35 | import org.lwjgl.BufferUtils;
36 | import org.lwjgl.opengl.OpenGLException;
37 |
38 | public class Texture {
39 |
40 | private static int imageWidth;
41 | private static int imageHeight;
42 |
43 | // TEXTURE_2D
44 | public static void bindTexture2D(int id) {
45 | glBindTexture(GL_TEXTURE_2D, id);
46 | }
47 |
48 | public static void bindTexture2D(int id, int unit) {
49 | if(unit >= 0 && unit <= GL_MAX_TEXTURE_UNITS) {
50 | glActiveTexture(unit);
51 | glBindTexture(GL_TEXTURE_2D, id);
52 | } else
53 | throw new OpenGLException("Texture unit " + unit + " is not valid");
54 | }
55 |
56 | public static void unbindTexture2D() {
57 | glBindTexture(GL_TEXTURE_2D, 0);
58 | }
59 |
60 | public static int loadTexture2D(InputStream iS, int magFilter, int minFilter, int wrapMode) throws IOException {
61 | ByteBuffer data = getImageData(iS);
62 |
63 | int id = glGenTextures();
64 |
65 | glBindTexture(GL_TEXTURE_2D, id);
66 |
67 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
68 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
69 |
70 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
71 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
72 |
73 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
74 |
75 | if(minFilter == GL_NEAREST_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_LINEAR_MIPMAP_LINEAR)
76 | glGenerateMipmap(GL_TEXTURE_2D);
77 |
78 | glBindTexture(GL_TEXTURE_2D, 0);
79 |
80 | return id;
81 | }
82 |
83 | // TEXTURE_2D_ARRAY
84 | public static void bindTexture2DArray(int id) {
85 | glBindTexture(GL_TEXTURE_2D_ARRAY, id);
86 | }
87 |
88 | public static void bindTexture2DArray(int id, int unit) {
89 | if(unit >= 0 && unit <= GL_MAX_TEXTURE_UNITS) {
90 | glActiveTexture(unit);
91 | glBindTexture(GL_TEXTURE_2D_ARRAY, id);
92 | } else
93 | throw new OpenGLException("Texture unit " + unit + " is not valid");
94 | }
95 |
96 | public static void unbindTexture2DArray() {
97 | glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
98 | }
99 |
100 | public static int loadTexture2DArray(InputStream iS, int width, int height, int magFilter, int minFilter, int wrapMode) throws IOException {
101 | int id = glGenTextures();
102 |
103 | glBindTexture(GL_TEXTURE_2D_ARRAY, id);
104 |
105 | glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, magFilter);
106 | glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, minFilter);
107 |
108 | glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, wrapMode);
109 | glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, wrapMode);
110 |
111 | ByteBuffer[] data = getImageDataArray(iS, width, height);
112 |
113 | int depth = (imageWidth / width) * (imageHeight / height);
114 |
115 | glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, width, height, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer) null);
116 |
117 | for(int i = 0; i < data.length; i++)
118 | glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, data[i]);
119 |
120 | if(minFilter == GL_NEAREST_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_LINEAR_MIPMAP_LINEAR)
121 | glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
122 |
123 | glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
124 |
125 | return id;
126 | }
127 |
128 | // TEXTURE_3D
129 | public static void bindTexture3D(int id) {
130 | glBindTexture(GL_TEXTURE_3D, id);
131 | }
132 |
133 | public static void bindTexture3D(int id, int unit) {
134 | if(unit >= 0 && unit <= GL_MAX_TEXTURE_UNITS) {
135 | glActiveTexture(unit);
136 | glBindTexture(GL_TEXTURE_3D, id);
137 | } else
138 | throw new OpenGLException("Texture unit " + unit + " is not valid");
139 | }
140 |
141 | public static void unbindTexture3D() {
142 | glBindTexture(GL_TEXTURE_3D, 0);
143 | }
144 |
145 | public static int loadTexture3D(InputStream iS, int width, int height, int magFilter, int minFilter, int wrapMode) throws IOException {
146 | int id = glGenTextures();
147 |
148 | glBindTexture(GL_TEXTURE_3D, id);
149 |
150 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, magFilter);
151 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, minFilter);
152 |
153 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrapMode);
154 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrapMode);
155 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrapMode);
156 |
157 | ByteBuffer[] data = getImageDataArray(iS, width, height);
158 |
159 | int depth = (imageWidth / width) * (imageHeight / height);
160 |
161 | glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, width, height, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer) null);
162 |
163 | for(int i = 0; i < data.length; i++)
164 | glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, data[i]);
165 |
166 | if(minFilter == GL_NEAREST_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_LINEAR_MIPMAP_LINEAR)
167 | glGenerateMipmap(GL_TEXTURE_3D);
168 |
169 | glBindTexture(GL_TEXTURE_3D, 0);
170 |
171 | return id;
172 | }
173 |
174 | private static ByteBuffer getImageData(InputStream iS) throws IOException {
175 | BufferedImage image = ImageIO.read(iS);
176 |
177 | imageWidth = image.getWidth();
178 | imageHeight = image.getHeight();
179 |
180 | int[] pixels = image.getRGB(0, 0, imageWidth, imageHeight, null, 0, imageWidth);
181 | ByteBuffer buffer = BufferUtils.createByteBuffer(imageWidth * imageHeight * 4);
182 |
183 | for(int y = 0; y < imageHeight; y++) {
184 | for(int x = 0; x < imageWidth; x++) {
185 | int pixel = pixels[y * imageWidth + x];
186 |
187 | buffer.put((byte) ((pixel >> 16) & 0xFF));
188 | buffer.put((byte) ((pixel >> 8) & 0xFF));
189 | buffer.put((byte) (pixel & 0xFF));
190 | buffer.put((byte) ((pixel >> 24) & 0xFF));
191 | }
192 | }
193 |
194 | buffer.flip();
195 |
196 | return buffer;
197 | }
198 |
199 | private static ByteBuffer[] getImageDataArray(InputStream iS, int singleW, int singleH) throws IOException {
200 | BufferedImage image = ImageIO.read(iS);
201 |
202 | imageWidth = image.getWidth();
203 | imageHeight = image.getHeight();
204 |
205 | int[] pixels = image.getRGB(0, 0, imageWidth, imageHeight, null, 0, imageWidth);
206 |
207 | int layerX = imageWidth / singleW;
208 | int layerY = imageHeight / singleH;
209 | int depth = layerX * layerY;
210 | ByteBuffer[] buffers = new ByteBuffer[depth];
211 |
212 | int index = 0;
213 | for(int ly = 0; ly < layerY; ly++) {
214 | for(int lx = 0; lx < layerX; lx++) {
215 | buffers[index] = BufferUtils.createByteBuffer(singleW * singleH * 4);
216 |
217 | for(int y = 0; y < singleH; y++) {
218 | for(int x = 0; x < singleW; x++) {
219 | int pixel = pixels[(ly * singleH + y) * imageWidth + lx * singleW + x];
220 |
221 | buffers[index].put((byte) ((pixel >> 16) & 0xFF));
222 | buffers[index].put((byte) ((pixel >> 8) & 0xFF));
223 | buffers[index].put((byte) (pixel & 0xFF));
224 | buffers[index].put((byte) ((pixel >> 24) & 0xFF));
225 | }
226 | }
227 |
228 | buffers[index].flip();
229 | index++;
230 | }
231 | }
232 |
233 | return buffers;
234 | }
235 |
236 | }
237 |
--------------------------------------------------------------------------------
/src/de/meinkraft/ChunkManager.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | import java.util.ArrayDeque;
4 | import static org.lwjgl.opengl.GL11.*;
5 |
6 | public class ChunkManager {
7 |
8 | // the radius in which chunks get generated
9 | public static final byte RADIUS = 4;
10 |
11 | private Chunk[][] chunks;
12 |
13 | private final World world;
14 | private final ChunkLoader chunkLoader;
15 | private final ArrayDeque queue;
16 |
17 | public ChunkManager(World world) {
18 | this.world = world;
19 | chunkLoader = new ChunkLoader(this);
20 | queue = new ArrayDeque();
21 |
22 | chunks = new Chunk[2 * RADIUS + 1][2 * RADIUS + 1];
23 | }
24 |
25 | public void update() {
26 | int px = getPlayerChunkPositionX();
27 | int pz = getPlayerChunkPositionZ();
28 |
29 | for(int x = 0; x < chunks.length; x++)
30 | for(int z = 0; z < chunks.length; z++) {
31 | Chunk chunk = chunks[x][z];
32 |
33 | if(chunk == null) {
34 | cs:for(int lx = -RADIUS; lx <= RADIUS; lx++)
35 | for(int lz = -RADIUS; lz <= RADIUS; lz++) {
36 | if(getChunkAt(px + lx, pz + lz) == null) {
37 | chunks[x][z] = new Chunk(px + lx, pz + lz);
38 | chunkLoader.addChunk(chunks[x][z]);
39 | break cs;
40 | }
41 | }
42 | } else {
43 | if(isChunkInRange(chunk.getX(), chunk.getZ()))
44 | chunk.update();
45 | else {
46 | if(chunk.getState() == ChunkState.LOADING || hasChunkNeighboursLoading(chunk)) {
47 | if(!queue.contains(chunk))
48 | queue.add(chunk);
49 | } else {
50 | System.out.println("FIRST_HAS_NEIGHBOURS_LOADING: " + hasChunkNeighboursLoading(chunk) + " " + chunk.getX() + "," + chunk.getZ());
51 | chunk.unload();
52 | }
53 |
54 | chunks[x][z] = null;
55 |
56 | if(z > 0)
57 | z--;
58 | else {
59 | if(x > 0) {
60 | x--;
61 | z = chunks.length - 1;
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 | if(!queue.isEmpty()) {
69 | Chunk chunk = queue.poll();
70 |
71 | if(chunk.getState() != ChunkState.LOADING && !hasChunkNeighboursLoading(chunk)) {
72 | System.out.println("SECOND_HAS_NEIGHBOURS_LOADING: " + hasChunkNeighboursLoading(chunk) + " " + chunk.getX() + "," + chunk.getZ());
73 | chunk.unload();
74 | }
75 | else
76 | queue.add(chunk);
77 | }
78 | }
79 |
80 | public void render() {
81 | for(int x = 0; x < chunks.length; x++)
82 | for(int z = 0; z < chunks.length; z++) {
83 | Chunk chunk = chunks[x][z];
84 |
85 | if(chunk == null || !chunk.isLoaded())
86 | continue;
87 |
88 | // Vector3 playerPos = new Vector3(world.getPlayer().pos.getX(), world.getPlayer().pos.getY(), world.getPlayer().pos.getZ());
89 | // Vector3 chunkDir1 = new Vector3(chunk.getX() * Chunk.SIZE_X, 0, chunk.getZ() * Chunk.SIZE_Z).add(playerPos.negate()).normalised();
90 | // Vector3 chunkDir2 = new Vector3(chunk.getX() * Chunk.SIZE_X + 16, 0, chunk.getZ() * Chunk.SIZE_Z).add(playerPos.negate()).normalised();
91 | // Vector3 chunkDir3 = new Vector3(chunk.getX() * Chunk.SIZE_X + 16, 0, chunk.getZ() * Chunk.SIZE_Z + 16).add(playerPos.negate()).normalised();
92 | // Vector3 chunkDir4 = new Vector3(chunk.getX() * Chunk.SIZE_X, 0, chunk.getZ() * Chunk.SIZE_Z + 16).add(playerPos.negate()).normalised();
93 | //
94 | // if(chunkDir1.dot(world.getPlayer().dir) > 0 && chunkDir2.dot(world.getPlayer().dir) > 0 && chunkDir3.dot(world.getPlayer().dir) > 0 && chunkDir4.dot(world.getPlayer().dir) > 0) {
95 | chunk.render();
96 | // count++;
97 | // }
98 | }
99 |
100 | // debug
101 | glBegin(GL_LINE_STRIP);
102 | {
103 | for(int x = 0; x < chunks.length; x++)
104 | for(int z = 0; z < chunks.length; z++) {
105 | Chunk chunk = chunks[x][z];
106 |
107 | if(chunk == null)
108 | continue;
109 |
110 | if(chunk.isGenerated()) {
111 | glVertex3f(chunk.getX() * Chunk.SIZE_X, 65, chunk.getZ() * Chunk.SIZE_Z);
112 | glVertex3f(chunk.getX() * Chunk.SIZE_X + Chunk.SIZE_X, 65, chunk.getZ() * Chunk.SIZE_Z);
113 | glVertex3f(chunk.getX() * Chunk.SIZE_X + Chunk.SIZE_X, 65, chunk.getZ() * Chunk.SIZE_Z + Chunk.SIZE_Z);
114 | glVertex3f(chunk.getX() * Chunk.SIZE_X, 65, chunk.getZ() * Chunk.SIZE_Z + Chunk.SIZE_Z);
115 | }
116 | }
117 | }
118 | glEnd();
119 | }
120 |
121 | public void regenerate() {
122 | for(int xx = 0; xx < chunks.length; xx++)
123 | for(int zz = 0; zz < chunks.length; zz++) {
124 | if(chunks[xx][zz] == null)
125 | continue;
126 |
127 | chunks[xx][zz].deleteBlocks();
128 | chunkLoader.addChunk(chunks[xx][zz]);
129 | }
130 | }
131 |
132 | public int getPlayerChunkPositionX() {
133 | return (int) Math.floor(world.getPlayer().pos.getX() / Chunk.SIZE_X);
134 | }
135 |
136 | public int getPlayerChunkPositionZ() {
137 | return (int) Math.floor(world.getPlayer().pos.getZ() / Chunk.SIZE_Z);
138 | }
139 |
140 | // public boolean allChunksGenerated() {
141 | // for(int x = 0; x < chunks.length; x++)
142 | // for(int z = 0; z < chunks.length; z++) {
143 | // if(chunks[x][z] == null || !chunks[x][z].isGenerated())
144 | // return false;
145 | // }
146 | //
147 | // return true;
148 | // }
149 |
150 | public boolean isChunkInRange(int x, int z) {
151 | if(Math.abs((int) Math.floor(world.getPlayer().pos.getX() / Chunk.SIZE_X) - x) > RADIUS || Math.abs((int) Math.floor(world.getPlayer().pos.getZ() / Chunk.SIZE_Z) - z) > RADIUS)
152 | return false;
153 | else
154 | return true;
155 | }
156 |
157 | /**
158 | *
159 | * @param chunk
160 | * @return Returns true if the chunk is surrounded by generated chunks
161 | */
162 | public boolean isChunkSurrounded(Chunk chunk) {
163 | if(isChunkInRange(chunk.getX() - 1, chunk.getZ())) {
164 | if(getChunkAt(chunk.getX() - 1, chunk.getZ()) == null || !getChunkAt(chunk.getX() - 1, chunk.getZ()).isGenerated())
165 | return false;
166 | }
167 |
168 | if(isChunkInRange(chunk.getX() + 1, chunk.getZ())) {
169 | if(getChunkAt(chunk.getX() + 1, chunk.getZ()) == null || !getChunkAt(chunk.getX() + 1, chunk.getZ()).isGenerated())
170 | return false;
171 | }
172 |
173 | if(isChunkInRange(chunk.getX(), chunk.getZ() - 1)) {
174 | if(getChunkAt(chunk.getX(), chunk.getZ() - 1) == null || !getChunkAt(chunk.getX(), chunk.getZ() - 1).isGenerated())
175 | return false;
176 | }
177 |
178 | if(isChunkInRange(chunk.getX(), chunk.getZ() + 1)) {
179 | if(getChunkAt(chunk.getX(), chunk.getZ() + 1) == null || !getChunkAt(chunk.getX(), chunk.getZ() + 1).isGenerated())
180 | return false;
181 | }
182 |
183 | return true;
184 | }
185 |
186 | /**
187 | *
188 | * @param chunk
189 | * @return Returns true if the chunk has a neighbour, which is in a loading state
190 | */
191 | public boolean hasChunkNeighboursLoading(Chunk chunk) {
192 | if(getChunkAt(chunk.getX() - 1, chunk.getZ()) != null && !getChunkAt(chunk.getX() - 1, chunk.getZ()).isGenerated())
193 | return true;
194 |
195 | if(getChunkAt(chunk.getX() + 1, chunk.getZ()) != null && !getChunkAt(chunk.getX() + 1, chunk.getZ()).isGenerated())
196 | return true;
197 |
198 | if(getChunkAt(chunk.getX(), chunk.getZ() - 1) != null && !getChunkAt(chunk.getX(), chunk.getZ() - 1).isGenerated())
199 | return true;
200 |
201 | if(getChunkAt(chunk.getX(), chunk.getZ() + 1) != null && !getChunkAt(chunk.getX(), chunk.getZ() + 1).isGenerated())
202 | return true;
203 |
204 | return false;
205 | }
206 |
207 | public Chunk getChunkAt(int x, int z) {
208 | for(int xx = 0; xx < chunks.length; xx++)
209 | for(int zz = 0; zz < chunks.length; zz++) {
210 | if(chunks[xx][zz] == null)
211 | continue;
212 |
213 | if(chunks[xx][zz].getX() == x && chunks[xx][zz].getZ() == z)
214 | return chunks[xx][zz];
215 | }
216 |
217 | if(!queue.isEmpty()) {
218 | Object[] chunks = queue.toArray();
219 | for(Object obj : chunks) {
220 | if(obj instanceof Chunk) {
221 | Chunk chunk = (Chunk) obj;
222 |
223 | if(chunk.getX() == x && chunk.getZ() == z)
224 | return chunk;
225 | }
226 | }
227 | }
228 |
229 | return null;
230 | }
231 |
232 | public Block getBlockAt(int x, int y, int z) {
233 | int chunkX = (int) Math.floor((float) x / Chunk.SIZE_X);
234 | int chunkZ = (int) Math.floor((float) z / Chunk.SIZE_Z);
235 |
236 | for(int xx = 0; xx < chunks.length; xx++)
237 | for(int zz = 0; zz < chunks.length; zz++) {
238 | if(chunks[xx][zz] == null)
239 | continue;
240 |
241 | if(chunks[xx][zz].getX() == chunkX && chunks[xx][zz].getZ() == chunkZ)
242 | return chunks[xx][zz].getBlockAt(x - chunkX * Chunk.SIZE_X, y, z - chunkZ * Chunk.SIZE_Z);
243 | }
244 |
245 | if(!queue.isEmpty()) {
246 | Object[] chunks = queue.toArray();
247 | for(Object obj : chunks) {
248 | if(obj instanceof Chunk) {
249 | Chunk chunk = (Chunk) obj;
250 |
251 | if(chunk.getX() == chunkX && chunk.getZ() == chunkZ)
252 | return chunk.getBlockAt(x - chunkX * Chunk.SIZE_X, y, z - chunkZ * Chunk.SIZE_Z);
253 | }
254 | }
255 | }
256 |
257 | return Block.AIR;
258 | }
259 |
260 | public void setBlockAt(int x, int y, int z, Block block) {
261 | int chunkX = (int) Math.floor((float) x / Chunk.SIZE_X);
262 | int chunkZ = (int) Math.floor((float) z / Chunk.SIZE_Z);
263 |
264 | for(int xx = 0; xx < chunks.length; xx++)
265 | for(int zz = 0; zz < chunks.length; zz++) {
266 | if(chunks[xx][zz] == null)
267 | continue;
268 |
269 | if(chunks[xx][zz].getX() == chunkX && chunks[xx][zz].getZ() == chunkZ) {
270 | chunks[xx][zz].setBlockAt(x - chunkX * Chunk.SIZE_X, y, z - chunkZ * Chunk.SIZE_Z, block);
271 |
272 | chunkLoader.addChunk(chunks[xx][zz]);
273 | }
274 | }
275 | }
276 |
277 | public World getWorld() {
278 | return world;
279 | }
280 |
281 | public Chunk[][] getChunks() {
282 | return chunks;
283 | }
284 |
285 | }
286 |
--------------------------------------------------------------------------------
/src/de/meinkraft/lib/Matrix4.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft.lib;
2 |
3 | public class Matrix4 {
4 |
5 | public static final int XYZ = 0;
6 | public static final int ZXY = 1;
7 | public static final int YZX = 2;
8 | public static final int ZYX = 3;
9 | public static final int YXZ = 4;
10 | public static final int XZY = 5;
11 |
12 | private float[][] m;
13 |
14 | public Matrix4() {
15 | m = new float[4][4];
16 | }
17 |
18 | public Matrix4 loadIdentity() {
19 | m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
20 | m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0;
21 | m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0;
22 | m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
23 |
24 | return this;
25 | }
26 |
27 | public Matrix4 initTranslation(Vector3 v) {
28 | return initTranslation(v.getX(), v.getY(), v.getZ());
29 | }
30 |
31 | public Matrix4 initTranslation(float x, float y, float z) {
32 | m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = x;
33 | m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = y;
34 | m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = z;
35 | m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
36 |
37 | return this;
38 | }
39 |
40 | public Matrix4 initRotation(Vector3 v, int order) {
41 | return initRotation(v.getX(), v.getY(), v.getZ(), order);
42 | }
43 |
44 | public Matrix4 initRotation(float x, float y, float z, int order) {
45 | Matrix4 rx = new Matrix4();
46 | Matrix4 ry = new Matrix4();
47 | Matrix4 rz = new Matrix4();
48 |
49 | x = (float) Math.toRadians(x);
50 | y = (float) Math.toRadians(y);
51 | z = (float) Math.toRadians(z);
52 |
53 | rx.m[0][0] = 1; rx.m[0][1] = 0; rx.m[0][2] = 0; rx.m[0][3] = 0;
54 | rx.m[1][0] = 0; rx.m[1][1] = (float) Math.cos(x); rx.m[1][2] = (float) -Math.sin(x); rx.m[1][3] = 0;
55 | rx.m[2][0] = 0; rx.m[2][1] = (float) Math.sin(x); rx.m[2][2] = (float) Math.cos(x); rx.m[2][3] = 0;
56 | rx.m[3][0] = 0; rx.m[3][1] = 0; rx.m[3][2] = 0; rx.m[3][3] = 1;
57 |
58 | ry.m[0][0] = (float) Math.cos(y); ry.m[0][1] = 0; ry.m[0][2] = (float) Math.sin(y); ry.m[0][3] = 0;
59 | ry.m[1][0] = 0; ry.m[1][1] = 1; ry.m[1][2] = 0; ry.m[1][3] = 0;
60 | ry.m[2][0] = (float) -Math.sin(y); ry.m[2][1] = 0; ry.m[2][2] = (float) Math.cos(y); ry.m[2][3] = 0;
61 | ry.m[3][0] = 0; ry.m[3][1] = 0; ry.m[3][2] = 0; ry.m[3][3] = 1;
62 |
63 | rz.m[0][0] = (float) Math.cos(z); rz.m[0][1] = (float) -Math.sin(z); rz.m[0][2] = 0; rz.m[0][3] = 0;
64 | rz.m[1][0] = (float) Math.sin(z); rz.m[1][1] = (float) Math.cos(z); rz.m[1][2] = 0; rz.m[1][3] = 0;
65 | rz.m[2][0] = 0; rz.m[2][1] = 0; rz.m[2][2] = 1; rz.m[2][3] = 0;
66 | rz.m[3][0] = 0; rz.m[3][1] = 0; rz.m[3][2] = 0; rz.m[3][3] = 1;
67 |
68 | switch(order) {
69 | case XYZ:
70 | m = rz.mul(ry.mul(rx)).getM();
71 | break;
72 | case ZXY:
73 | m = ry.mul(rx.mul(rz)).getM();
74 | break;
75 | case YZX:
76 | m = rx.mul(rz.mul(ry)).getM();
77 | break;
78 | case ZYX:
79 | m = rx.mul(ry.mul(rz)).getM();
80 | break;
81 | case YXZ:
82 | m = rz.mul(rx.mul(ry)).getM();
83 | break;
84 | case XZY:
85 | m = ry.mul(rz.mul(rx)).getM();
86 | break;
87 | }
88 |
89 | return this;
90 | }
91 |
92 | public Matrix4 initScale(Vector3 v) {
93 | return initScale(v.getX(), v.getY(), v.getZ());
94 | }
95 |
96 | public Matrix4 initScale(float x, float y, float z) {
97 | m[0][0] = x; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
98 | m[1][0] = 0; m[1][1] = y; m[1][2] = 0; m[1][3] = 0;
99 | m[2][0] = 0; m[2][1] = 0; m[2][2] = z; m[2][3] = 0;
100 | m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
101 |
102 | return this;
103 | }
104 |
105 | public Matrix4 initPerspective(float fov, float aspectRatio, float zNear, float zFar) {
106 | float t = (float) (zNear * Math.tan(Math.PI / 180.0f * (fov / 2)));
107 | float b = -t;
108 | float r = t * aspectRatio;
109 | float l = -r;
110 |
111 | m[0][0] = (2 * zNear) / (r - l); m[0][1] = 0; m[0][2] = (r + l) / (r - l); m[0][3] = 0;
112 | m[1][0] = 0; m[1][1] = (2 * zNear) / (t - b); m[1][2] = (t + b) / (t - b); m[1][3] = 0;
113 | m[2][0] = 0; m[2][1] = 0; m[2][2] = -(zFar + zNear) / (zFar - zNear); m[2][3] = (-2 * zFar * zNear) / (zFar - zNear);
114 | m[3][0] = 0; m[3][1] = 0; m[3][2] = -1; m[3][3] = 0;
115 |
116 | return this;
117 | }
118 |
119 | public Matrix4 initOrthographic(float left, float right, float top, float bottom, float zNear, float zFar) {
120 | m[0][0] = 2.0f / (right - left); m[0][1] = 0; m[0][2] = 0; m[0][3] = -(right + left) / (right - left);
121 | m[1][0] = 0; m[1][1] = 2.0f / (top - bottom); m[1][2] = 0; m[1][3] = -(top + bottom) / (top - bottom);
122 | m[2][0] = 0; m[2][1] = 0; m[2][2] = -2.0f / (zFar - zNear); m[2][3] = -(zFar + zNear) / (zFar - zNear);
123 | m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
124 |
125 | return this;
126 | }
127 |
128 | public Vector3 transform(Vector4 v) {
129 | return new Vector3(m[0][0] * v.getX() + m[1][0] * v.getY() + m[2][0] * v.getZ() + m[3][0] * v.getW(),
130 | m[0][1] * v.getX() + m[1][1] * v.getY() + m[2][1] * v.getZ() + m[3][1] * v.getW(),
131 | m[0][2] * v.getX() + m[1][2] * v.getY() + m[2][2] * v.getZ() + m[3][2] * v.getW());
132 | }
133 |
134 | public Matrix4 transpose() {
135 | try {
136 | Matrix4 mat = (Matrix4) this.clone();
137 |
138 | for(int x = 0; x < 4; x++) {
139 | for(int y = 0; y < 4; y++) {
140 | m[x][y] = mat.m[y][x];
141 | }
142 | }
143 |
144 | return this;
145 | } catch (CloneNotSupportedException e) {
146 | e.printStackTrace();
147 | }
148 |
149 | return null;
150 | }
151 |
152 | /**
153 | * A new matrix will be returned
154 | * @return Returns the inverse of this matrix
155 | */
156 | public Matrix4 inverse() {
157 | Matrix4 matrix = new Matrix4();
158 |
159 | matrix.m[0][0] = m[1][1] * m[2][2] * m[3][3] + m[1][2] * m[2][3] * m[3][1] + m[1][3] * m[2][1] * m[3][2] - m[1][1] * m[2][3] * m[3][2] - m[1][2] * m[2][1] * m[3][3] - m[1][3] * m[2][2] * m[3][1];
160 | matrix.m[0][1] = m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3] + m[0][3] * m[2][2] * m[3][1] - m[0][1] * m[2][2] * m[3][3] - m[0][2] * m[2][3] * m[3][1] - m[0][3] * m[2][1] * m[3][2];
161 | matrix.m[0][2] = m[0][1] * m[1][2] * m[3][3] + m[0][2] * m[1][3] * m[3][1] + m[0][3] * m[1][1] * m[3][2] - m[0][1] * m[1][3] * m[3][2] - m[0][2] * m[1][1] * m[3][3] - m[0][3] * m[1][2] * m[3][1];
162 | matrix.m[0][3] = m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3] + m[0][3] * m[1][2] * m[2][1] - m[0][1] * m[1][2] * m[2][3] - m[0][2] * m[1][3] * m[2][1] - m[0][3] * m[1][1] * m[2][2];
163 | matrix.m[1][0] = m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3] + m[1][3] * m[2][2] * m[3][0] - m[1][0] * m[2][2] * m[3][3] - m[1][2] * m[2][3] * m[3][0] - m[1][3] * m[2][0] * m[3][2];
164 | matrix.m[1][1] = m[0][0] * m[2][2] * m[3][3] + m[0][2] * m[2][3] * m[3][0] + m[0][3] * m[2][0] * m[3][2] - m[0][0] * m[2][3] * m[3][2] - m[0][2] * m[2][0] * m[3][3] - m[0][3] * m[2][2] * m[3][0];
165 | matrix.m[1][2] = m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3] + m[0][3] * m[1][3] * m[3][0] - m[0][0] * m[1][2] * m[3][3] - m[0][2] * m[1][3] * m[3][0] - m[0][3] * m[1][0] * m[3][2];
166 | matrix.m[1][3] = m[0][0] * m[1][2] * m[2][3] + m[0][2] * m[1][3] * m[2][0] + m[0][3] * m[1][0] * m[2][2] - m[0][0] * m[1][3] * m[2][2] - m[0][2] * m[1][0] * m[2][3] - m[0][3] * m[1][2] * m[2][0];
167 | matrix.m[2][0] = m[1][0] * m[2][1] * m[3][3] + m[1][1] * m[2][3] * m[3][0] + m[1][3] * m[2][0] * m[3][1] - m[1][0] * m[2][3] * m[3][1] - m[1][1] * m[2][0] * m[3][3] - m[1][3] * m[2][1] * m[3][0];
168 | matrix.m[2][1] = m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] + m[0][3] * m[2][1] * m[3][0] - m[0][0] * m[2][1] * m[3][3] - m[0][1] * m[2][3] * m[3][0] - m[0][3] * m[2][0] * m[3][1];
169 | matrix.m[2][2] = m[0][0] * m[1][1] * m[3][3] + m[0][1] * m[1][3] * m[3][0] + m[0][3] * m[1][0] * m[3][1] - m[0][0] * m[1][3] * m[3][1] - m[0][1] * m[1][0] * m[3][3] - m[0][3] * m[1][1] * m[3][0];
170 | matrix.m[2][3] = m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3] + m[0][3] * m[1][1] * m[2][0] - m[0][0] * m[1][1] * m[2][3] - m[0][1] * m[1][3] * m[2][0] - m[0][3] * m[1][0] * m[2][1];
171 | matrix.m[3][0] = m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2] + m[1][2] * m[2][1] * m[3][0] - m[1][0] * m[2][1] * m[3][2] - m[1][1] * m[2][2] * m[3][0] - m[1][2] * m[2][0] * m[3][1];
172 | matrix.m[3][1] = m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0] + m[0][2] * m[2][0] * m[3][1] - m[0][0] * m[2][2] * m[3][1] - m[0][1] * m[2][0] * m[3][2] - m[0][2] * m[2][1] * m[3][0];
173 | matrix.m[3][2] = m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2] + m[0][2] * m[1][1] * m[3][0] - m[0][0] * m[1][1] * m[3][2] - m[0][1] * m[1][2] * m[3][0] - m[0][2] * m[1][0] * m[3][1];
174 | matrix.m[3][3] = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0] + m[0][2] * m[1][0] * m[2][1] - m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] - m[0][2] * m[1][1] * m[2][0];
175 |
176 | return matrix;
177 | }
178 |
179 | public Matrix4 mul(Matrix4 v) {
180 | Matrix4 r = new Matrix4();
181 |
182 | for(int x = 0; x < 4; x++) {
183 | for(int y = 0; y < 4; y++) {
184 | r.set(x, y, m[x][0] * v.get(0, y) +
185 | m[x][1] * v.get(1, y) +
186 | m[x][2] * v.get(2, y) +
187 | m[x][3] * v.get(3, y));
188 | }
189 | }
190 |
191 | return r;
192 | }
193 |
194 | public float get(int x, int y) {
195 | return m[x][y];
196 | }
197 |
198 | public void set(int x, int y, float v) {
199 | m[x][y] = v;
200 | }
201 |
202 | public float[][] getM() {
203 | return m;
204 | }
205 |
206 | public void setM(float[][] m) {
207 | this.m = m;
208 | }
209 |
210 | @Override
211 | public String toString() {
212 | StringBuilder sb = new StringBuilder();
213 |
214 | int c = 0;
215 | for(int x = 0; x < 4; x++) {
216 | for(int y = 0; y < 4; y++) {
217 | if(c > 3) {
218 | sb.append("\n");
219 | c = 0;
220 | }
221 |
222 | sb.append(m[x][y] + " | ");
223 | c++;
224 | }
225 | }
226 |
227 | return sb.toString();
228 | }
229 |
230 | }
231 |
--------------------------------------------------------------------------------
/src/de/meinkraft/OpenSimplexNoiseOctave.java:
--------------------------------------------------------------------------------
1 | package de.meinkraft;
2 |
3 | /*
4 | * OpenSimplex Noise in Java.
5 | * by Kurt Spencer
6 | *
7 | * v1.1 (October 5, 2014)
8 | * - Added 2D and 4D implementations.
9 | * - Proper gradient sets for all dimensions, from a
10 | * dimensionally-generalizable scheme with an actual
11 | * rhyme and reason behind it.
12 | * - Removed default permutation array in favor of
13 | * default seed.
14 | * - Changed seed-based constructor to be independent
15 | * of any particular randomization library, so results
16 | * will be the same when ported to other languages.
17 | */
18 |
19 | public class OpenSimplexNoiseOctave {
20 |
21 | private static final double STRETCH_CONSTANT_2D = -0.211324865405187; //(1/Math.sqrt(2+1)-1)/2;
22 | private static final double SQUISH_CONSTANT_2D = 0.366025403784439; //(Math.sqrt(2+1)-1)/2;
23 | private static final double STRETCH_CONSTANT_3D = -1.0 / 6; //(1/Math.sqrt(3+1)-1)/3;
24 | private static final double SQUISH_CONSTANT_3D = 1.0 / 3; //(Math.sqrt(3+1)-1)/3;
25 | private static final double STRETCH_CONSTANT_4D = -0.138196601125011; //(1/Math.sqrt(4+1)-1)/4;
26 | private static final double SQUISH_CONSTANT_4D = 0.309016994374947; //(Math.sqrt(4+1)-1)/4;
27 |
28 | private static final double NORM_CONSTANT_2D = 47;
29 | private static final double NORM_CONSTANT_3D = 103;
30 | private static final double NORM_CONSTANT_4D = 30;
31 |
32 | private static final long DEFAULT_SEED = 0;
33 |
34 | private short[] perm;
35 | private short[] permGradIndex3D;
36 |
37 | public OpenSimplexNoiseOctave() {
38 | this(DEFAULT_SEED);
39 | }
40 |
41 | public OpenSimplexNoiseOctave(short[] perm) {
42 | this.perm = perm;
43 | permGradIndex3D = new short[256];
44 |
45 | for (int i = 0; i < 256; i++) {
46 | //Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array.
47 | permGradIndex3D[i] = (short)((perm[i] % (gradients3D.length / 3)) * 3);
48 | }
49 | }
50 |
51 | //Initializes the class using a permutation array generated from a 64-bit seed.
52 | //Generates a proper permutation (i.e. doesn't merely perform N successive pair swaps on a base array)
53 | //Uses a simple 64-bit LCG.
54 | public OpenSimplexNoiseOctave(long seed) {
55 | perm = new short[256];
56 | permGradIndex3D = new short[256];
57 | short[] source = new short[256];
58 | for (short i = 0; i < 256; i++)
59 | source[i] = i;
60 | seed = seed * 6364136223846793005l + 1442695040888963407l;
61 | seed = seed * 6364136223846793005l + 1442695040888963407l;
62 | seed = seed * 6364136223846793005l + 1442695040888963407l;
63 | for (int i = 255; i >= 0; i--) {
64 | seed = seed * 6364136223846793005l + 1442695040888963407l;
65 | int r = (int)((seed + 31) % (i + 1));
66 | if (r < 0)
67 | r += (i + 1);
68 | perm[i] = source[r];
69 | permGradIndex3D[i] = (short)((perm[i] % (gradients3D.length / 3)) * 3);
70 | source[r] = source[i];
71 | }
72 | }
73 |
74 | //2D OpenSimplex Noise.
75 | public double eval(double x, double y) {
76 |
77 | //Place input coordinates onto grid.
78 | double stretchOffset = (x + y) * STRETCH_CONSTANT_2D;
79 | double xs = x + stretchOffset;
80 | double ys = y + stretchOffset;
81 |
82 | //Floor to get grid coordinates of rhombus (stretched square) super-cell origin.
83 | int xsb = fastFloor(xs);
84 | int ysb = fastFloor(ys);
85 |
86 | //Skew out to get actual coordinates of rhombus origin. We'll need these later.
87 | double squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D;
88 | double xb = xsb + squishOffset;
89 | double yb = ysb + squishOffset;
90 |
91 | //Compute grid coordinates relative to rhombus origin.
92 | double xins = xs - xsb;
93 | double yins = ys - ysb;
94 |
95 | //Sum those together to get a value that determines which region we're in.
96 | double inSum = xins + yins;
97 |
98 | //Positions relative to origin point.
99 | double dx0 = x - xb;
100 | double dy0 = y - yb;
101 |
102 | //We'll be defining these inside the next block and using them afterwards.
103 | double dx_ext, dy_ext;
104 | int xsv_ext, ysv_ext;
105 |
106 | double value = 0;
107 |
108 | //Contribution (1,0)
109 | double dx1 = dx0 - 1 - SQUISH_CONSTANT_2D;
110 | double dy1 = dy0 - 0 - SQUISH_CONSTANT_2D;
111 | double attn1 = 2 - dx1 * dx1 - dy1 * dy1;
112 | if (attn1 > 0) {
113 | attn1 *= attn1;
114 | value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, dx1, dy1);
115 | }
116 |
117 | //Contribution (0,1)
118 | double dx2 = dx0 - 0 - SQUISH_CONSTANT_2D;
119 | double dy2 = dy0 - 1 - SQUISH_CONSTANT_2D;
120 | double attn2 = 2 - dx2 * dx2 - dy2 * dy2;
121 | if (attn2 > 0) {
122 | attn2 *= attn2;
123 | value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, dx2, dy2);
124 | }
125 |
126 | if (inSum <= 1) { //We're inside the triangle (2-Simplex) at (0,0)
127 | double zins = 1 - inSum;
128 | if (zins > xins || zins > yins) { //(0,0) is one of the closest two triangular vertices
129 | if (xins > yins) {
130 | xsv_ext = xsb + 1;
131 | ysv_ext = ysb - 1;
132 | dx_ext = dx0 - 1;
133 | dy_ext = dy0 + 1;
134 | } else {
135 | xsv_ext = xsb - 1;
136 | ysv_ext = ysb + 1;
137 | dx_ext = dx0 + 1;
138 | dy_ext = dy0 - 1;
139 | }
140 | } else { //(1,0) and (0,1) are the closest two vertices.
141 | xsv_ext = xsb + 1;
142 | ysv_ext = ysb + 1;
143 | dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D;
144 | dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D;
145 | }
146 | } else { //We're inside the triangle (2-Simplex) at (1,1)
147 | double zins = 2 - inSum;
148 | if (zins < xins || zins < yins) { //(0,0) is one of the closest two triangular vertices
149 | if (xins > yins) {
150 | xsv_ext = xsb + 2;
151 | ysv_ext = ysb + 0;
152 | dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D;
153 | dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D;
154 | } else {
155 | xsv_ext = xsb + 0;
156 | ysv_ext = ysb + 2;
157 | dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D;
158 | dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D;
159 | }
160 | } else { //(1,0) and (0,1) are the closest two vertices.
161 | dx_ext = dx0;
162 | dy_ext = dy0;
163 | xsv_ext = xsb;
164 | ysv_ext = ysb;
165 | }
166 | xsb += 1;
167 | ysb += 1;
168 | dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D;
169 | dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D;
170 | }
171 |
172 | //Contribution (0,0) or (1,1)
173 | double attn0 = 2 - dx0 * dx0 - dy0 * dy0;
174 | if (attn0 > 0) {
175 | attn0 *= attn0;
176 | value += attn0 * attn0 * extrapolate(xsb, ysb, dx0, dy0);
177 | }
178 |
179 | //Extra Vertex
180 | double attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext;
181 | if (attn_ext > 0) {
182 | attn_ext *= attn_ext;
183 | value += attn_ext * attn_ext * extrapolate(xsv_ext, ysv_ext, dx_ext, dy_ext);
184 | }
185 |
186 | return value / NORM_CONSTANT_2D;
187 | }
188 |
189 | //3D OpenSimplex Noise.
190 | public double eval(double x, double y, double z) {
191 |
192 | //Place input coordinates on simplectic honeycomb.
193 | double stretchOffset = (x + y + z) * STRETCH_CONSTANT_3D;
194 | double xs = x + stretchOffset;
195 | double ys = y + stretchOffset;
196 | double zs = z + stretchOffset;
197 |
198 | //Floor to get simplectic honeycomb coordinates of rhombohedron (stretched cube) super-cell origin.
199 | int xsb = fastFloor(xs);
200 | int ysb = fastFloor(ys);
201 | int zsb = fastFloor(zs);
202 |
203 | //Skew out to get actual coordinates of rhombohedron origin. We'll need these later.
204 | double squishOffset = (xsb + ysb + zsb) * SQUISH_CONSTANT_3D;
205 | double xb = xsb + squishOffset;
206 | double yb = ysb + squishOffset;
207 | double zb = zsb + squishOffset;
208 |
209 | //Compute simplectic honeycomb coordinates relative to rhombohedral origin.
210 | double xins = xs - xsb;
211 | double yins = ys - ysb;
212 | double zins = zs - zsb;
213 |
214 | //Sum those together to get a value that determines which region we're in.
215 | double inSum = xins + yins + zins;
216 |
217 | //Positions relative to origin point.
218 | double dx0 = x - xb;
219 | double dy0 = y - yb;
220 | double dz0 = z - zb;
221 |
222 | //We'll be defining these inside the next block and using them afterwards.
223 | double dx_ext0, dy_ext0, dz_ext0;
224 | double dx_ext1, dy_ext1, dz_ext1;
225 | int xsv_ext0, ysv_ext0, zsv_ext0;
226 | int xsv_ext1, ysv_ext1, zsv_ext1;
227 |
228 | double value = 0;
229 | if (inSum <= 1) { //We're inside the tetrahedron (3-Simplex) at (0,0,0)
230 |
231 | //Determine which two of (0,0,1), (0,1,0), (1,0,0) are closest.
232 | byte aPoint = 0x01;
233 | double aScore = xins;
234 | byte bPoint = 0x02;
235 | double bScore = yins;
236 | if (aScore >= bScore && zins > bScore) {
237 | bScore = zins;
238 | bPoint = 0x04;
239 | } else if (aScore < bScore && zins > aScore) {
240 | aScore = zins;
241 | aPoint = 0x04;
242 | }
243 |
244 | //Now we determine the two lattice points not part of the tetrahedron that may contribute.
245 | //This depends on the closest two tetrahedral vertices, including (0,0,0)
246 | double wins = 1 - inSum;
247 | if (wins > aScore || wins > bScore) { //(0,0,0) is one of the closest two tetrahedral vertices.
248 | byte c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b.
249 |
250 | if ((c & 0x01) == 0) {
251 | xsv_ext0 = xsb - 1;
252 | xsv_ext1 = xsb;
253 | dx_ext0 = dx0 + 1;
254 | dx_ext1 = dx0;
255 | } else {
256 | xsv_ext0 = xsv_ext1 = xsb + 1;
257 | dx_ext0 = dx_ext1 = dx0 - 1;
258 | }
259 |
260 | if ((c & 0x02) == 0) {
261 | ysv_ext0 = ysv_ext1 = ysb;
262 | dy_ext0 = dy_ext1 = dy0;
263 | if ((c & 0x01) == 0) {
264 | ysv_ext1 -= 1;
265 | dy_ext1 += 1;
266 | } else {
267 | ysv_ext0 -= 1;
268 | dy_ext0 += 1;
269 | }
270 | } else {
271 | ysv_ext0 = ysv_ext1 = ysb + 1;
272 | dy_ext0 = dy_ext1 = dy0 - 1;
273 | }
274 |
275 | if ((c & 0x04) == 0) {
276 | zsv_ext0 = zsb;
277 | zsv_ext1 = zsb - 1;
278 | dz_ext0 = dz0;
279 | dz_ext1 = dz0 + 1;
280 | } else {
281 | zsv_ext0 = zsv_ext1 = zsb + 1;
282 | dz_ext0 = dz_ext1 = dz0 - 1;
283 | }
284 | } else { //(0,0,0) is not one of the closest two tetrahedral vertices.
285 | byte c = (byte)(aPoint | bPoint); //Our two extra vertices are determined by the closest two.
286 |
287 | if ((c & 0x01) == 0) {
288 | xsv_ext0 = xsb;
289 | xsv_ext1 = xsb - 1;
290 | dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_3D;
291 | dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D;
292 | } else {
293 | xsv_ext0 = xsv_ext1 = xsb + 1;
294 | dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D;
295 | dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D;
296 | }
297 |
298 | if ((c & 0x02) == 0) {
299 | ysv_ext0 = ysb;
300 | ysv_ext1 = ysb - 1;
301 | dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_3D;
302 | dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D;
303 | } else {
304 | ysv_ext0 = ysv_ext1 = ysb + 1;
305 | dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D;
306 | dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D;
307 | }
308 |
309 | if ((c & 0x04) == 0) {
310 | zsv_ext0 = zsb;
311 | zsv_ext1 = zsb - 1;
312 | dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_3D;
313 | dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D;
314 | } else {
315 | zsv_ext0 = zsv_ext1 = zsb + 1;
316 | dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D;
317 | dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D;
318 | }
319 | }
320 |
321 | //Contribution (0,0,0)
322 | double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0;
323 | if (attn0 > 0) {
324 | attn0 *= attn0;
325 | value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, dx0, dy0, dz0);
326 | }
327 |
328 | //Contribution (1,0,0)
329 | double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D;
330 | double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D;
331 | double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D;
332 | double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1;
333 | if (attn1 > 0) {
334 | attn1 *= attn1;
335 | value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1);
336 | }
337 |
338 | //Contribution (0,1,0)
339 | double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D;
340 | double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D;
341 | double dz2 = dz1;
342 | double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2;
343 | if (attn2 > 0) {
344 | attn2 *= attn2;
345 | value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2);
346 | }
347 |
348 | //Contribution (0,0,1)
349 | double dx3 = dx2;
350 | double dy3 = dy1;
351 | double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D;
352 | double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3;
353 | if (attn3 > 0) {
354 | attn3 *= attn3;
355 | value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3);
356 | }
357 | } else if (inSum >= 2) { //We're inside the tetrahedron (3-Simplex) at (1,1,1)
358 |
359 | //Determine which two tetrahedral vertices are the closest, out of (1,1,0), (1,0,1), (0,1,1) but not (1,1,1).
360 | byte aPoint = 0x06;
361 | double aScore = xins;
362 | byte bPoint = 0x05;
363 | double bScore = yins;
364 | if (aScore <= bScore && zins < bScore) {
365 | bScore = zins;
366 | bPoint = 0x03;
367 | } else if (aScore > bScore && zins < aScore) {
368 | aScore = zins;
369 | aPoint = 0x03;
370 | }
371 |
372 | //Now we determine the two lattice points not part of the tetrahedron that may contribute.
373 | //This depends on the closest two tetrahedral vertices, including (1,1,1)
374 | double wins = 3 - inSum;
375 | if (wins < aScore || wins < bScore) { //(1,1,1) is one of the closest two tetrahedral vertices.
376 | byte c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b.
377 |
378 | if ((c & 0x01) != 0) {
379 | xsv_ext0 = xsb + 2;
380 | xsv_ext1 = xsb + 1;
381 | dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_3D;
382 | dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D;
383 | } else {
384 | xsv_ext0 = xsv_ext1 = xsb;
385 | dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_3D;
386 | }
387 |
388 | if ((c & 0x02) != 0) {
389 | ysv_ext0 = ysv_ext1 = ysb + 1;
390 | dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D;
391 | if ((c & 0x01) != 0) {
392 | ysv_ext1 += 1;
393 | dy_ext1 -= 1;
394 | } else {
395 | ysv_ext0 += 1;
396 | dy_ext0 -= 1;
397 | }
398 | } else {
399 | ysv_ext0 = ysv_ext1 = ysb;
400 | dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_3D;
401 | }
402 |
403 | if ((c & 0x04) != 0) {
404 | zsv_ext0 = zsb + 1;
405 | zsv_ext1 = zsb + 2;
406 | dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D;
407 | dz_ext1 = dz0 - 2 - 3 * SQUISH_CONSTANT_3D;
408 | } else {
409 | zsv_ext0 = zsv_ext1 = zsb;
410 | dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_3D;
411 | }
412 | } else { //(1,1,1) is not one of the closest two tetrahedral vertices.
413 | byte c = (byte)(aPoint & bPoint); //Our two extra vertices are determined by the closest two.
414 |
415 | if ((c & 0x01) != 0) {
416 | xsv_ext0 = xsb + 1;
417 | xsv_ext1 = xsb + 2;
418 | dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D;
419 | dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D;
420 | } else {
421 | xsv_ext0 = xsv_ext1 = xsb;
422 | dx_ext0 = dx0 - SQUISH_CONSTANT_3D;
423 | dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D;
424 | }
425 |
426 | if ((c & 0x02) != 0) {
427 | ysv_ext0 = ysb + 1;
428 | ysv_ext1 = ysb + 2;
429 | dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D;
430 | dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D;
431 | } else {
432 | ysv_ext0 = ysv_ext1 = ysb;
433 | dy_ext0 = dy0 - SQUISH_CONSTANT_3D;
434 | dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D;
435 | }
436 |
437 | if ((c & 0x04) != 0) {
438 | zsv_ext0 = zsb + 1;
439 | zsv_ext1 = zsb + 2;
440 | dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D;
441 | dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D;
442 | } else {
443 | zsv_ext0 = zsv_ext1 = zsb;
444 | dz_ext0 = dz0 - SQUISH_CONSTANT_3D;
445 | dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D;
446 | }
447 | }
448 |
449 | //Contribution (1,1,0)
450 | double dx3 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D;
451 | double dy3 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D;
452 | double dz3 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D;
453 | double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3;
454 | if (attn3 > 0) {
455 | attn3 *= attn3;
456 | value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx3, dy3, dz3);
457 | }
458 |
459 | //Contribution (1,0,1)
460 | double dx2 = dx3;
461 | double dy2 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D;
462 | double dz2 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D;
463 | double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2;
464 | if (attn2 > 0) {
465 | attn2 *= attn2;
466 | value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx2, dy2, dz2);
467 | }
468 |
469 | //Contribution (0,1,1)
470 | double dx1 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D;
471 | double dy1 = dy3;
472 | double dz1 = dz2;
473 | double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1;
474 | if (attn1 > 0) {
475 | attn1 *= attn1;
476 | value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx1, dy1, dz1);
477 | }
478 |
479 | //Contribution (1,1,1)
480 | dx0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D;
481 | dy0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D;
482 | dz0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D;
483 | double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0;
484 | if (attn0 > 0) {
485 | attn0 *= attn0;
486 | value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, dx0, dy0, dz0);
487 | }
488 | } else { //We're inside the octahedron (Rectified 3-Simplex) in between.
489 | double aScore;
490 | byte aPoint;
491 | boolean aIsFurtherSide;
492 | double bScore;
493 | byte bPoint;
494 | boolean bIsFurtherSide;
495 |
496 | //Decide between point (0,0,1) and (1,1,0) as closest
497 | double p1 = xins + yins;
498 | if (p1 > 1) {
499 | aScore = p1 - 1;
500 | aPoint = 0x03;
501 | aIsFurtherSide = true;
502 | } else {
503 | aScore = 1 - p1;
504 | aPoint = 0x04;
505 | aIsFurtherSide = false;
506 | }
507 |
508 | //Decide between point (0,1,0) and (1,0,1) as closest
509 | double p2 = xins + zins;
510 | if (p2 > 1) {
511 | bScore = p2 - 1;
512 | bPoint = 0x05;
513 | bIsFurtherSide = true;
514 | } else {
515 | bScore = 1 - p2;
516 | bPoint = 0x02;
517 | bIsFurtherSide = false;
518 | }
519 |
520 | //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.
521 | double p3 = yins + zins;
522 | if (p3 > 1) {
523 | double score = p3 - 1;
524 | if (aScore <= bScore && aScore < score) {
525 | aScore = score;
526 | aPoint = 0x06;
527 | aIsFurtherSide = true;
528 | } else if (aScore > bScore && bScore < score) {
529 | bScore = score;
530 | bPoint = 0x06;
531 | bIsFurtherSide = true;
532 | }
533 | } else {
534 | double score = 1 - p3;
535 | if (aScore <= bScore && aScore < score) {
536 | aScore = score;
537 | aPoint = 0x01;
538 | aIsFurtherSide = false;
539 | } else if (aScore > bScore && bScore < score) {
540 | bScore = score;
541 | bPoint = 0x01;
542 | bIsFurtherSide = false;
543 | }
544 | }
545 |
546 | //Where each of the two closest points are determines how the extra two vertices are calculated.
547 | if (aIsFurtherSide == bIsFurtherSide) {
548 | if (aIsFurtherSide) { //Both closest points on (1,1,1) side
549 |
550 | //One of the two extra points is (1,1,1)
551 | dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D;
552 | dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D;
553 | dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D;
554 | xsv_ext0 = xsb + 1;
555 | ysv_ext0 = ysb + 1;
556 | zsv_ext0 = zsb + 1;
557 |
558 | //Other extra point is based on the shared axis.
559 | byte c = (byte)(aPoint & bPoint);
560 | if ((c & 0x01) != 0) {
561 | dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D;
562 | dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D;
563 | dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D;
564 | xsv_ext1 = xsb + 2;
565 | ysv_ext1 = ysb;
566 | zsv_ext1 = zsb;
567 | } else if ((c & 0x02) != 0) {
568 | dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D;
569 | dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D;
570 | dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D;
571 | xsv_ext1 = xsb;
572 | ysv_ext1 = ysb + 2;
573 | zsv_ext1 = zsb;
574 | } else {
575 | dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D;
576 | dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D;
577 | dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D;
578 | xsv_ext1 = xsb;
579 | ysv_ext1 = ysb;
580 | zsv_ext1 = zsb + 2;
581 | }
582 | } else {//Both closest points on (0,0,0) side
583 |
584 | //One of the two extra points is (0,0,0)
585 | dx_ext0 = dx0;
586 | dy_ext0 = dy0;
587 | dz_ext0 = dz0;
588 | xsv_ext0 = xsb;
589 | ysv_ext0 = ysb;
590 | zsv_ext0 = zsb;
591 |
592 | //Other extra point is based on the omitted axis.
593 | byte c = (byte)(aPoint | bPoint);
594 | if ((c & 0x01) == 0) {
595 | dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D;
596 | dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D;
597 | dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D;
598 | xsv_ext1 = xsb - 1;
599 | ysv_ext1 = ysb + 1;
600 | zsv_ext1 = zsb + 1;
601 | } else if ((c & 0x02) == 0) {
602 | dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D;
603 | dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D;
604 | dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D;
605 | xsv_ext1 = xsb + 1;
606 | ysv_ext1 = ysb - 1;
607 | zsv_ext1 = zsb + 1;
608 | } else {
609 | dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D;
610 | dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D;
611 | dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D;
612 | xsv_ext1 = xsb + 1;
613 | ysv_ext1 = ysb + 1;
614 | zsv_ext1 = zsb - 1;
615 | }
616 | }
617 | } else { //One point on (0,0,0) side, one point on (1,1,1) side
618 | byte c1, c2;
619 | if (aIsFurtherSide) {
620 | c1 = aPoint;
621 | c2 = bPoint;
622 | } else {
623 | c1 = bPoint;
624 | c2 = aPoint;
625 | }
626 |
627 | //One contribution is a permutation of (1,1,-1)
628 | if ((c1 & 0x01) == 0) {
629 | dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_3D;
630 | dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D;
631 | dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D;
632 | xsv_ext0 = xsb - 1;
633 | ysv_ext0 = ysb + 1;
634 | zsv_ext0 = zsb + 1;
635 | } else if ((c1 & 0x02) == 0) {
636 | dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D;
637 | dy_ext0 = dy0 + 1 - SQUISH_CONSTANT_3D;
638 | dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D;
639 | xsv_ext0 = xsb + 1;
640 | ysv_ext0 = ysb - 1;
641 | zsv_ext0 = zsb + 1;
642 | } else {
643 | dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D;
644 | dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D;
645 | dz_ext0 = dz0 + 1 - SQUISH_CONSTANT_3D;
646 | xsv_ext0 = xsb + 1;
647 | ysv_ext0 = ysb + 1;
648 | zsv_ext0 = zsb - 1;
649 | }
650 |
651 | //One contribution is a permutation of (0,0,2)
652 | dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D;
653 | dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D;
654 | dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D;
655 | xsv_ext1 = xsb;
656 | ysv_ext1 = ysb;
657 | zsv_ext1 = zsb;
658 | if ((c2 & 0x01) != 0) {
659 | dx_ext1 -= 2;
660 | xsv_ext1 += 2;
661 | } else if ((c2 & 0x02) != 0) {
662 | dy_ext1 -= 2;
663 | ysv_ext1 += 2;
664 | } else {
665 | dz_ext1 -= 2;
666 | zsv_ext1 += 2;
667 | }
668 | }
669 |
670 | //Contribution (1,0,0)
671 | double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D;
672 | double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D;
673 | double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D;
674 | double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1;
675 | if (attn1 > 0) {
676 | attn1 *= attn1;
677 | value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1);
678 | }
679 |
680 | //Contribution (0,1,0)
681 | double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D;
682 | double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D;
683 | double dz2 = dz1;
684 | double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2;
685 | if (attn2 > 0) {
686 | attn2 *= attn2;
687 | value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2);
688 | }
689 |
690 | //Contribution (0,0,1)
691 | double dx3 = dx2;
692 | double dy3 = dy1;
693 | double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D;
694 | double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3;
695 | if (attn3 > 0) {
696 | attn3 *= attn3;
697 | value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3);
698 | }
699 |
700 | //Contribution (1,1,0)
701 | double dx4 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D;
702 | double dy4 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D;
703 | double dz4 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D;
704 | double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4;
705 | if (attn4 > 0) {
706 | attn4 *= attn4;
707 | value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx4, dy4, dz4);
708 | }
709 |
710 | //Contribution (1,0,1)
711 | double dx5 = dx4;
712 | double dy5 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D;
713 | double dz5 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D;
714 | double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5;
715 | if (attn5 > 0) {
716 | attn5 *= attn5;
717 | value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx5, dy5, dz5);
718 | }
719 |
720 | //Contribution (0,1,1)
721 | double dx6 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D;
722 | double dy6 = dy4;
723 | double dz6 = dz5;
724 | double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6;
725 | if (attn6 > 0) {
726 | attn6 *= attn6;
727 | value += attn6 * attn6 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx6, dy6, dz6);
728 | }
729 | }
730 |
731 | //First extra vertex
732 | double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0;
733 | if (attn_ext0 > 0)
734 | {
735 | attn_ext0 *= attn_ext0;
736 | value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, dx_ext0, dy_ext0, dz_ext0);
737 | }
738 |
739 | //Second extra vertex
740 | double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1;
741 | if (attn_ext1 > 0)
742 | {
743 | attn_ext1 *= attn_ext1;
744 | value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, dx_ext1, dy_ext1, dz_ext1);
745 | }
746 |
747 | return value / NORM_CONSTANT_3D;
748 | }
749 |
750 | //4D OpenSimplex Noise.
751 | public double eval(double x, double y, double z, double w) {
752 |
753 | //Place input coordinates on simplectic honeycomb.
754 | double stretchOffset = (x + y + z + w) * STRETCH_CONSTANT_4D;
755 | double xs = x + stretchOffset;
756 | double ys = y + stretchOffset;
757 | double zs = z + stretchOffset;
758 | double ws = w + stretchOffset;
759 |
760 | //Floor to get simplectic honeycomb coordinates of rhombo-hypercube super-cell origin.
761 | int xsb = fastFloor(xs);
762 | int ysb = fastFloor(ys);
763 | int zsb = fastFloor(zs);
764 | int wsb = fastFloor(ws);
765 |
766 | //Skew out to get actual coordinates of stretched rhombo-hypercube origin. We'll need these later.
767 | double squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_CONSTANT_4D;
768 | double xb = xsb + squishOffset;
769 | double yb = ysb + squishOffset;
770 | double zb = zsb + squishOffset;
771 | double wb = wsb + squishOffset;
772 |
773 | //Compute simplectic honeycomb coordinates relative to rhombo-hypercube origin.
774 | double xins = xs - xsb;
775 | double yins = ys - ysb;
776 | double zins = zs - zsb;
777 | double wins = ws - wsb;
778 |
779 | //Sum those together to get a value that determines which region we're in.
780 | double inSum = xins + yins + zins + wins;
781 |
782 | //Positions relative to origin point.
783 | double dx0 = x - xb;
784 | double dy0 = y - yb;
785 | double dz0 = z - zb;
786 | double dw0 = w - wb;
787 |
788 | //We'll be defining these inside the next block and using them afterwards.
789 | double dx_ext0, dy_ext0, dz_ext0, dw_ext0;
790 | double dx_ext1, dy_ext1, dz_ext1, dw_ext1;
791 | double dx_ext2, dy_ext2, dz_ext2, dw_ext2;
792 | int xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0;
793 | int xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1;
794 | int xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2;
795 |
796 | double value = 0;
797 | if (inSum <= 1) { //We're inside the pentachoron (4-Simplex) at (0,0,0,0)
798 |
799 | //Determine which two of (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0) are closest.
800 | byte aPoint = 0x01;
801 | double aScore = xins;
802 | byte bPoint = 0x02;
803 | double bScore = yins;
804 | if (aScore >= bScore && zins > bScore) {
805 | bScore = zins;
806 | bPoint = 0x04;
807 | } else if (aScore < bScore && zins > aScore) {
808 | aScore = zins;
809 | aPoint = 0x04;
810 | }
811 | if (aScore >= bScore && wins > bScore) {
812 | bScore = wins;
813 | bPoint = 0x08;
814 | } else if (aScore < bScore && wins > aScore) {
815 | aScore = wins;
816 | aPoint = 0x08;
817 | }
818 |
819 | //Now we determine the three lattice points not part of the pentachoron that may contribute.
820 | //This depends on the closest two pentachoron vertices, including (0,0,0,0)
821 | double uins = 1 - inSum;
822 | if (uins > aScore || uins > bScore) { //(0,0,0,0) is one of the closest two pentachoron vertices.
823 | byte c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b.
824 | if ((c & 0x01) == 0) {
825 | xsv_ext0 = xsb - 1;
826 | xsv_ext1 = xsv_ext2 = xsb;
827 | dx_ext0 = dx0 + 1;
828 | dx_ext1 = dx_ext2 = dx0;
829 | } else {
830 | xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1;
831 | dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1;
832 | }
833 |
834 | if ((c & 0x02) == 0) {
835 | ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb;
836 | dy_ext0 = dy_ext1 = dy_ext2 = dy0;
837 | if ((c & 0x01) == 0x01) {
838 | ysv_ext0 -= 1;
839 | dy_ext0 += 1;
840 | } else {
841 | ysv_ext1 -= 1;
842 | dy_ext1 += 1;
843 | }
844 | } else {
845 | ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1;
846 | dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1;
847 | }
848 |
849 | if ((c & 0x04) == 0) {
850 | zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb;
851 | dz_ext0 = dz_ext1 = dz_ext2 = dz0;
852 | if ((c & 0x03) != 0) {
853 | if ((c & 0x03) == 0x03) {
854 | zsv_ext0 -= 1;
855 | dz_ext0 += 1;
856 | } else {
857 | zsv_ext1 -= 1;
858 | dz_ext1 += 1;
859 | }
860 | } else {
861 | zsv_ext2 -= 1;
862 | dz_ext2 += 1;
863 | }
864 | } else {
865 | zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1;
866 | dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1;
867 | }
868 |
869 | if ((c & 0x08) == 0) {
870 | wsv_ext0 = wsv_ext1 = wsb;
871 | wsv_ext2 = wsb - 1;
872 | dw_ext0 = dw_ext1 = dw0;
873 | dw_ext2 = dw0 + 1;
874 | } else {
875 | wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1;
876 | dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1;
877 | }
878 | } else { //(0,0,0,0) is not one of the closest two pentachoron vertices.
879 | byte c = (byte)(aPoint | bPoint); //Our three extra vertices are determined by the closest two.
880 |
881 | if ((c & 0x01) == 0) {
882 | xsv_ext0 = xsv_ext2 = xsb;
883 | xsv_ext1 = xsb - 1;
884 | dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D;
885 | dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_4D;
886 | dx_ext2 = dx0 - SQUISH_CONSTANT_4D;
887 | } else {
888 | xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1;
889 | dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
890 | dx_ext1 = dx_ext2 = dx0 - 1 - SQUISH_CONSTANT_4D;
891 | }
892 |
893 | if ((c & 0x02) == 0) {
894 | ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb;
895 | dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D;
896 | dy_ext1 = dy_ext2 = dy0 - SQUISH_CONSTANT_4D;
897 | if ((c & 0x01) == 0x01) {
898 | ysv_ext1 -= 1;
899 | dy_ext1 += 1;
900 | } else {
901 | ysv_ext2 -= 1;
902 | dy_ext2 += 1;
903 | }
904 | } else {
905 | ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1;
906 | dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
907 | dy_ext1 = dy_ext2 = dy0 - 1 - SQUISH_CONSTANT_4D;
908 | }
909 |
910 | if ((c & 0x04) == 0) {
911 | zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb;
912 | dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D;
913 | dz_ext1 = dz_ext2 = dz0 - SQUISH_CONSTANT_4D;
914 | if ((c & 0x03) == 0x03) {
915 | zsv_ext1 -= 1;
916 | dz_ext1 += 1;
917 | } else {
918 | zsv_ext2 -= 1;
919 | dz_ext2 += 1;
920 | }
921 | } else {
922 | zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1;
923 | dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
924 | dz_ext1 = dz_ext2 = dz0 - 1 - SQUISH_CONSTANT_4D;
925 | }
926 |
927 | if ((c & 0x08) == 0) {
928 | wsv_ext0 = wsv_ext1 = wsb;
929 | wsv_ext2 = wsb - 1;
930 | dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D;
931 | dw_ext1 = dw0 - SQUISH_CONSTANT_4D;
932 | dw_ext2 = dw0 + 1 - SQUISH_CONSTANT_4D;
933 | } else {
934 | wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1;
935 | dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
936 | dw_ext1 = dw_ext2 = dw0 - 1 - SQUISH_CONSTANT_4D;
937 | }
938 | }
939 |
940 | //Contribution (0,0,0,0)
941 | double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0;
942 | if (attn0 > 0) {
943 | attn0 *= attn0;
944 | value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 0, dx0, dy0, dz0, dw0);
945 | }
946 |
947 | //Contribution (1,0,0,0)
948 | double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D;
949 | double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D;
950 | double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D;
951 | double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D;
952 | double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1;
953 | if (attn1 > 0) {
954 | attn1 *= attn1;
955 | value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1);
956 | }
957 |
958 | //Contribution (0,1,0,0)
959 | double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D;
960 | double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D;
961 | double dz2 = dz1;
962 | double dw2 = dw1;
963 | double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2;
964 | if (attn2 > 0) {
965 | attn2 *= attn2;
966 | value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2);
967 | }
968 |
969 | //Contribution (0,0,1,0)
970 | double dx3 = dx2;
971 | double dy3 = dy1;
972 | double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D;
973 | double dw3 = dw1;
974 | double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3;
975 | if (attn3 > 0) {
976 | attn3 *= attn3;
977 | value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3);
978 | }
979 |
980 | //Contribution (0,0,0,1)
981 | double dx4 = dx2;
982 | double dy4 = dy1;
983 | double dz4 = dz1;
984 | double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D;
985 | double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4;
986 | if (attn4 > 0) {
987 | attn4 *= attn4;
988 | value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4);
989 | }
990 | } else if (inSum >= 3) { //We're inside the pentachoron (4-Simplex) at (1,1,1,1)
991 | //Determine which two of (1,1,1,0), (1,1,0,1), (1,0,1,1), (0,1,1,1) are closest.
992 | byte aPoint = 0x0E;
993 | double aScore = xins;
994 | byte bPoint = 0x0D;
995 | double bScore = yins;
996 | if (aScore <= bScore && zins < bScore) {
997 | bScore = zins;
998 | bPoint = 0x0B;
999 | } else if (aScore > bScore && zins < aScore) {
1000 | aScore = zins;
1001 | aPoint = 0x0B;
1002 | }
1003 | if (aScore <= bScore && wins < bScore) {
1004 | bScore = wins;
1005 | bPoint = 0x07;
1006 | } else if (aScore > bScore && wins < aScore) {
1007 | aScore = wins;
1008 | aPoint = 0x07;
1009 | }
1010 |
1011 | //Now we determine the three lattice points not part of the pentachoron that may contribute.
1012 | //This depends on the closest two pentachoron vertices, including (0,0,0,0)
1013 | double uins = 4 - inSum;
1014 | if (uins < aScore || uins < bScore) { //(1,1,1,1) is one of the closest two pentachoron vertices.
1015 | byte c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b.
1016 |
1017 | if ((c & 0x01) != 0) {
1018 | xsv_ext0 = xsb + 2;
1019 | xsv_ext1 = xsv_ext2 = xsb + 1;
1020 | dx_ext0 = dx0 - 2 - 4 * SQUISH_CONSTANT_4D;
1021 | dx_ext1 = dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D;
1022 | } else {
1023 | xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb;
1024 | dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * SQUISH_CONSTANT_4D;
1025 | }
1026 |
1027 | if ((c & 0x02) != 0) {
1028 | ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1;
1029 | dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D;
1030 | if ((c & 0x01) != 0) {
1031 | ysv_ext1 += 1;
1032 | dy_ext1 -= 1;
1033 | } else {
1034 | ysv_ext0 += 1;
1035 | dy_ext0 -= 1;
1036 | }
1037 | } else {
1038 | ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb;
1039 | dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * SQUISH_CONSTANT_4D;
1040 | }
1041 |
1042 | if ((c & 0x04) != 0) {
1043 | zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1;
1044 | dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D;
1045 | if ((c & 0x03) != 0x03) {
1046 | if ((c & 0x03) == 0) {
1047 | zsv_ext0 += 1;
1048 | dz_ext0 -= 1;
1049 | } else {
1050 | zsv_ext1 += 1;
1051 | dz_ext1 -= 1;
1052 | }
1053 | } else {
1054 | zsv_ext2 += 1;
1055 | dz_ext2 -= 1;
1056 | }
1057 | } else {
1058 | zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb;
1059 | dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * SQUISH_CONSTANT_4D;
1060 | }
1061 |
1062 | if ((c & 0x08) != 0) {
1063 | wsv_ext0 = wsv_ext1 = wsb + 1;
1064 | wsv_ext2 = wsb + 2;
1065 | dw_ext0 = dw_ext1 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D;
1066 | dw_ext2 = dw0 - 2 - 4 * SQUISH_CONSTANT_4D;
1067 | } else {
1068 | wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb;
1069 | dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * SQUISH_CONSTANT_4D;
1070 | }
1071 | } else { //(1,1,1,1) is not one of the closest two pentachoron vertices.
1072 | byte c = (byte)(aPoint & bPoint); //Our three extra vertices are determined by the closest two.
1073 |
1074 | if ((c & 0x01) != 0) {
1075 | xsv_ext0 = xsv_ext2 = xsb + 1;
1076 | xsv_ext1 = xsb + 2;
1077 | dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1078 | dx_ext1 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D;
1079 | dx_ext2 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
1080 | } else {
1081 | xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb;
1082 | dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D;
1083 | dx_ext1 = dx_ext2 = dx0 - 3 * SQUISH_CONSTANT_4D;
1084 | }
1085 |
1086 | if ((c & 0x02) != 0) {
1087 | ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1;
1088 | dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
1089 | dy_ext1 = dy_ext2 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
1090 | if ((c & 0x01) != 0) {
1091 | ysv_ext2 += 1;
1092 | dy_ext2 -= 1;
1093 | } else {
1094 | ysv_ext1 += 1;
1095 | dy_ext1 -= 1;
1096 | }
1097 | } else {
1098 | ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb;
1099 | dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D;
1100 | dy_ext1 = dy_ext2 = dy0 - 3 * SQUISH_CONSTANT_4D;
1101 | }
1102 |
1103 | if ((c & 0x04) != 0) {
1104 | zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1;
1105 | dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
1106 | dz_ext1 = dz_ext2 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
1107 | if ((c & 0x03) != 0) {
1108 | zsv_ext2 += 1;
1109 | dz_ext2 -= 1;
1110 | } else {
1111 | zsv_ext1 += 1;
1112 | dz_ext1 -= 1;
1113 | }
1114 | } else {
1115 | zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb;
1116 | dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D;
1117 | dz_ext1 = dz_ext2 = dz0 - 3 * SQUISH_CONSTANT_4D;
1118 | }
1119 |
1120 | if ((c & 0x08) != 0) {
1121 | wsv_ext0 = wsv_ext1 = wsb + 1;
1122 | wsv_ext2 = wsb + 2;
1123 | dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
1124 | dw_ext1 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
1125 | dw_ext2 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D;
1126 | } else {
1127 | wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb;
1128 | dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D;
1129 | dw_ext1 = dw_ext2 = dw0 - 3 * SQUISH_CONSTANT_4D;
1130 | }
1131 | }
1132 |
1133 | //Contribution (1,1,1,0)
1134 | double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
1135 | double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
1136 | double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
1137 | double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D;
1138 | double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4;
1139 | if (attn4 > 0) {
1140 | attn4 *= attn4;
1141 | value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4);
1142 | }
1143 |
1144 | //Contribution (1,1,0,1)
1145 | double dx3 = dx4;
1146 | double dy3 = dy4;
1147 | double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D;
1148 | double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
1149 | double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3;
1150 | if (attn3 > 0) {
1151 | attn3 *= attn3;
1152 | value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3);
1153 | }
1154 |
1155 | //Contribution (1,0,1,1)
1156 | double dx2 = dx4;
1157 | double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D;
1158 | double dz2 = dz4;
1159 | double dw2 = dw3;
1160 | double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2;
1161 | if (attn2 > 0) {
1162 | attn2 *= attn2;
1163 | value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2);
1164 | }
1165 |
1166 | //Contribution (0,1,1,1)
1167 | double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D;
1168 | double dz1 = dz4;
1169 | double dy1 = dy4;
1170 | double dw1 = dw3;
1171 | double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1;
1172 | if (attn1 > 0) {
1173 | attn1 *= attn1;
1174 | value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1);
1175 | }
1176 |
1177 | //Contribution (1,1,1,1)
1178 | dx0 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D;
1179 | dy0 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D;
1180 | dz0 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D;
1181 | dw0 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D;
1182 | double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0;
1183 | if (attn0 > 0) {
1184 | attn0 *= attn0;
1185 | value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 1, dx0, dy0, dz0, dw0);
1186 | }
1187 | } else if (inSum <= 2) { //We're inside the first dispentachoron (Rectified 4-Simplex)
1188 | double aScore;
1189 | byte aPoint;
1190 | boolean aIsBiggerSide = true;
1191 | double bScore;
1192 | byte bPoint;
1193 | boolean bIsBiggerSide = true;
1194 |
1195 | //Decide between (1,1,0,0) and (0,0,1,1)
1196 | if (xins + yins > zins + wins) {
1197 | aScore = xins + yins;
1198 | aPoint = 0x03;
1199 | } else {
1200 | aScore = zins + wins;
1201 | aPoint = 0x0C;
1202 | }
1203 |
1204 | //Decide between (1,0,1,0) and (0,1,0,1)
1205 | if (xins + zins > yins + wins) {
1206 | bScore = xins + zins;
1207 | bPoint = 0x05;
1208 | } else {
1209 | bScore = yins + wins;
1210 | bPoint = 0x0A;
1211 | }
1212 |
1213 | //Closer between (1,0,0,1) and (0,1,1,0) will replace the further of a and b, if closer.
1214 | if (xins + wins > yins + zins) {
1215 | double score = xins + wins;
1216 | if (aScore >= bScore && score > bScore) {
1217 | bScore = score;
1218 | bPoint = 0x09;
1219 | } else if (aScore < bScore && score > aScore) {
1220 | aScore = score;
1221 | aPoint = 0x09;
1222 | }
1223 | } else {
1224 | double score = yins + zins;
1225 | if (aScore >= bScore && score > bScore) {
1226 | bScore = score;
1227 | bPoint = 0x06;
1228 | } else if (aScore < bScore && score > aScore) {
1229 | aScore = score;
1230 | aPoint = 0x06;
1231 | }
1232 | }
1233 |
1234 | //Decide if (1,0,0,0) is closer.
1235 | double p1 = 2 - inSum + xins;
1236 | if (aScore >= bScore && p1 > bScore) {
1237 | bScore = p1;
1238 | bPoint = 0x01;
1239 | bIsBiggerSide = false;
1240 | } else if (aScore < bScore && p1 > aScore) {
1241 | aScore = p1;
1242 | aPoint = 0x01;
1243 | aIsBiggerSide = false;
1244 | }
1245 |
1246 | //Decide if (0,1,0,0) is closer.
1247 | double p2 = 2 - inSum + yins;
1248 | if (aScore >= bScore && p2 > bScore) {
1249 | bScore = p2;
1250 | bPoint = 0x02;
1251 | bIsBiggerSide = false;
1252 | } else if (aScore < bScore && p2 > aScore) {
1253 | aScore = p2;
1254 | aPoint = 0x02;
1255 | aIsBiggerSide = false;
1256 | }
1257 |
1258 | //Decide if (0,0,1,0) is closer.
1259 | double p3 = 2 - inSum + zins;
1260 | if (aScore >= bScore && p3 > bScore) {
1261 | bScore = p3;
1262 | bPoint = 0x04;
1263 | bIsBiggerSide = false;
1264 | } else if (aScore < bScore && p3 > aScore) {
1265 | aScore = p3;
1266 | aPoint = 0x04;
1267 | aIsBiggerSide = false;
1268 | }
1269 |
1270 | //Decide if (0,0,0,1) is closer.
1271 | double p4 = 2 - inSum + wins;
1272 | if (aScore >= bScore && p4 > bScore) {
1273 | bScore = p4;
1274 | bPoint = 0x08;
1275 | bIsBiggerSide = false;
1276 | } else if (aScore < bScore && p4 > aScore) {
1277 | aScore = p4;
1278 | aPoint = 0x08;
1279 | aIsBiggerSide = false;
1280 | }
1281 |
1282 | //Where each of the two closest points are determines how the extra three vertices are calculated.
1283 | if (aIsBiggerSide == bIsBiggerSide) {
1284 | if (aIsBiggerSide) { //Both closest points on the bigger side
1285 | byte c1 = (byte)(aPoint | bPoint);
1286 | byte c2 = (byte)(aPoint & bPoint);
1287 | if ((c1 & 0x01) == 0) {
1288 | xsv_ext0 = xsb;
1289 | xsv_ext1 = xsb - 1;
1290 | dx_ext0 = dx0 - 3 * SQUISH_CONSTANT_4D;
1291 | dx_ext1 = dx0 + 1 - 2 * SQUISH_CONSTANT_4D;
1292 | } else {
1293 | xsv_ext0 = xsv_ext1 = xsb + 1;
1294 | dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
1295 | dx_ext1 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1296 | }
1297 |
1298 | if ((c1 & 0x02) == 0) {
1299 | ysv_ext0 = ysb;
1300 | ysv_ext1 = ysb - 1;
1301 | dy_ext0 = dy0 - 3 * SQUISH_CONSTANT_4D;
1302 | dy_ext1 = dy0 + 1 - 2 * SQUISH_CONSTANT_4D;
1303 | } else {
1304 | ysv_ext0 = ysv_ext1 = ysb + 1;
1305 | dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
1306 | dy_ext1 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
1307 | }
1308 |
1309 | if ((c1 & 0x04) == 0) {
1310 | zsv_ext0 = zsb;
1311 | zsv_ext1 = zsb - 1;
1312 | dz_ext0 = dz0 - 3 * SQUISH_CONSTANT_4D;
1313 | dz_ext1 = dz0 + 1 - 2 * SQUISH_CONSTANT_4D;
1314 | } else {
1315 | zsv_ext0 = zsv_ext1 = zsb + 1;
1316 | dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
1317 | dz_ext1 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
1318 | }
1319 |
1320 | if ((c1 & 0x08) == 0) {
1321 | wsv_ext0 = wsb;
1322 | wsv_ext1 = wsb - 1;
1323 | dw_ext0 = dw0 - 3 * SQUISH_CONSTANT_4D;
1324 | dw_ext1 = dw0 + 1 - 2 * SQUISH_CONSTANT_4D;
1325 | } else {
1326 | wsv_ext0 = wsv_ext1 = wsb + 1;
1327 | dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
1328 | dw_ext1 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
1329 | }
1330 |
1331 | //One combination is a permutation of (0,0,0,2) based on c2
1332 | xsv_ext2 = xsb;
1333 | ysv_ext2 = ysb;
1334 | zsv_ext2 = zsb;
1335 | wsv_ext2 = wsb;
1336 | dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D;
1337 | dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D;
1338 | dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D;
1339 | dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D;
1340 | if ((c2 & 0x01) != 0) {
1341 | xsv_ext2 += 2;
1342 | dx_ext2 -= 2;
1343 | } else if ((c2 & 0x02) != 0) {
1344 | ysv_ext2 += 2;
1345 | dy_ext2 -= 2;
1346 | } else if ((c2 & 0x04) != 0) {
1347 | zsv_ext2 += 2;
1348 | dz_ext2 -= 2;
1349 | } else {
1350 | wsv_ext2 += 2;
1351 | dw_ext2 -= 2;
1352 | }
1353 |
1354 | } else { //Both closest points on the smaller side
1355 | //One of the two extra points is (0,0,0,0)
1356 | xsv_ext2 = xsb;
1357 | ysv_ext2 = ysb;
1358 | zsv_ext2 = zsb;
1359 | wsv_ext2 = wsb;
1360 | dx_ext2 = dx0;
1361 | dy_ext2 = dy0;
1362 | dz_ext2 = dz0;
1363 | dw_ext2 = dw0;
1364 |
1365 | //Other two points are based on the omitted axes.
1366 | byte c = (byte)(aPoint | bPoint);
1367 |
1368 | if ((c & 0x01) == 0) {
1369 | xsv_ext0 = xsb - 1;
1370 | xsv_ext1 = xsb;
1371 | dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D;
1372 | dx_ext1 = dx0 - SQUISH_CONSTANT_4D;
1373 | } else {
1374 | xsv_ext0 = xsv_ext1 = xsb + 1;
1375 | dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D;
1376 | }
1377 |
1378 | if ((c & 0x02) == 0) {
1379 | ysv_ext0 = ysv_ext1 = ysb;
1380 | dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D;
1381 | if ((c & 0x01) == 0x01)
1382 | {
1383 | ysv_ext0 -= 1;
1384 | dy_ext0 += 1;
1385 | } else {
1386 | ysv_ext1 -= 1;
1387 | dy_ext1 += 1;
1388 | }
1389 | } else {
1390 | ysv_ext0 = ysv_ext1 = ysb + 1;
1391 | dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D;
1392 | }
1393 |
1394 | if ((c & 0x04) == 0) {
1395 | zsv_ext0 = zsv_ext1 = zsb;
1396 | dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D;
1397 | if ((c & 0x03) == 0x03)
1398 | {
1399 | zsv_ext0 -= 1;
1400 | dz_ext0 += 1;
1401 | } else {
1402 | zsv_ext1 -= 1;
1403 | dz_ext1 += 1;
1404 | }
1405 | } else {
1406 | zsv_ext0 = zsv_ext1 = zsb + 1;
1407 | dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D;
1408 | }
1409 |
1410 | if ((c & 0x08) == 0)
1411 | {
1412 | wsv_ext0 = wsb;
1413 | wsv_ext1 = wsb - 1;
1414 | dw_ext0 = dw0 - SQUISH_CONSTANT_4D;
1415 | dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D;
1416 | } else {
1417 | wsv_ext0 = wsv_ext1 = wsb + 1;
1418 | dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D;
1419 | }
1420 |
1421 | }
1422 | } else { //One point on each "side"
1423 | byte c1, c2;
1424 | if (aIsBiggerSide) {
1425 | c1 = aPoint;
1426 | c2 = bPoint;
1427 | } else {
1428 | c1 = bPoint;
1429 | c2 = aPoint;
1430 | }
1431 |
1432 | //Two contributions are the bigger-sided point with each 0 replaced with -1.
1433 | if ((c1 & 0x01) == 0) {
1434 | xsv_ext0 = xsb - 1;
1435 | xsv_ext1 = xsb;
1436 | dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D;
1437 | dx_ext1 = dx0 - SQUISH_CONSTANT_4D;
1438 | } else {
1439 | xsv_ext0 = xsv_ext1 = xsb + 1;
1440 | dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D;
1441 | }
1442 |
1443 | if ((c1 & 0x02) == 0) {
1444 | ysv_ext0 = ysv_ext1 = ysb;
1445 | dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D;
1446 | if ((c1 & 0x01) == 0x01) {
1447 | ysv_ext0 -= 1;
1448 | dy_ext0 += 1;
1449 | } else {
1450 | ysv_ext1 -= 1;
1451 | dy_ext1 += 1;
1452 | }
1453 | } else {
1454 | ysv_ext0 = ysv_ext1 = ysb + 1;
1455 | dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D;
1456 | }
1457 |
1458 | if ((c1 & 0x04) == 0) {
1459 | zsv_ext0 = zsv_ext1 = zsb;
1460 | dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D;
1461 | if ((c1 & 0x03) == 0x03) {
1462 | zsv_ext0 -= 1;
1463 | dz_ext0 += 1;
1464 | } else {
1465 | zsv_ext1 -= 1;
1466 | dz_ext1 += 1;
1467 | }
1468 | } else {
1469 | zsv_ext0 = zsv_ext1 = zsb + 1;
1470 | dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D;
1471 | }
1472 |
1473 | if ((c1 & 0x08) == 0) {
1474 | wsv_ext0 = wsb;
1475 | wsv_ext1 = wsb - 1;
1476 | dw_ext0 = dw0 - SQUISH_CONSTANT_4D;
1477 | dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D;
1478 | } else {
1479 | wsv_ext0 = wsv_ext1 = wsb + 1;
1480 | dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D;
1481 | }
1482 |
1483 | //One contribution is a permutation of (0,0,0,2) based on the smaller-sided point
1484 | xsv_ext2 = xsb;
1485 | ysv_ext2 = ysb;
1486 | zsv_ext2 = zsb;
1487 | wsv_ext2 = wsb;
1488 | dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D;
1489 | dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D;
1490 | dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D;
1491 | dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D;
1492 | if ((c2 & 0x01) != 0) {
1493 | xsv_ext2 += 2;
1494 | dx_ext2 -= 2;
1495 | } else if ((c2 & 0x02) != 0) {
1496 | ysv_ext2 += 2;
1497 | dy_ext2 -= 2;
1498 | } else if ((c2 & 0x04) != 0) {
1499 | zsv_ext2 += 2;
1500 | dz_ext2 -= 2;
1501 | } else {
1502 | wsv_ext2 += 2;
1503 | dw_ext2 -= 2;
1504 | }
1505 | }
1506 |
1507 | //Contribution (1,0,0,0)
1508 | double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D;
1509 | double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D;
1510 | double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D;
1511 | double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D;
1512 | double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1;
1513 | if (attn1 > 0) {
1514 | attn1 *= attn1;
1515 | value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1);
1516 | }
1517 |
1518 | //Contribution (0,1,0,0)
1519 | double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D;
1520 | double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D;
1521 | double dz2 = dz1;
1522 | double dw2 = dw1;
1523 | double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2;
1524 | if (attn2 > 0) {
1525 | attn2 *= attn2;
1526 | value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2);
1527 | }
1528 |
1529 | //Contribution (0,0,1,0)
1530 | double dx3 = dx2;
1531 | double dy3 = dy1;
1532 | double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D;
1533 | double dw3 = dw1;
1534 | double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3;
1535 | if (attn3 > 0) {
1536 | attn3 *= attn3;
1537 | value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3);
1538 | }
1539 |
1540 | //Contribution (0,0,0,1)
1541 | double dx4 = dx2;
1542 | double dy4 = dy1;
1543 | double dz4 = dz1;
1544 | double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D;
1545 | double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4;
1546 | if (attn4 > 0) {
1547 | attn4 *= attn4;
1548 | value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4);
1549 | }
1550 |
1551 | //Contribution (1,1,0,0)
1552 | double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1553 | double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
1554 | double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
1555 | double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
1556 | double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5;
1557 | if (attn5 > 0) {
1558 | attn5 *= attn5;
1559 | value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5);
1560 | }
1561 |
1562 | //Contribution (1,0,1,0)
1563 | double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1564 | double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
1565 | double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
1566 | double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
1567 | double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6;
1568 | if (attn6 > 0) {
1569 | attn6 *= attn6;
1570 | value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6);
1571 | }
1572 |
1573 | //Contribution (1,0,0,1)
1574 | double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1575 | double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
1576 | double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
1577 | double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
1578 | double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7;
1579 | if (attn7 > 0) {
1580 | attn7 *= attn7;
1581 | value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7);
1582 | }
1583 |
1584 | //Contribution (0,1,1,0)
1585 | double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
1586 | double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
1587 | double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
1588 | double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
1589 | double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8;
1590 | if (attn8 > 0) {
1591 | attn8 *= attn8;
1592 | value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8);
1593 | }
1594 |
1595 | //Contribution (0,1,0,1)
1596 | double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
1597 | double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
1598 | double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
1599 | double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
1600 | double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9;
1601 | if (attn9 > 0) {
1602 | attn9 *= attn9;
1603 | value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9);
1604 | }
1605 |
1606 | //Contribution (0,0,1,1)
1607 | double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
1608 | double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
1609 | double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
1610 | double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
1611 | double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10;
1612 | if (attn10 > 0) {
1613 | attn10 *= attn10;
1614 | value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10);
1615 | }
1616 | } else { //We're inside the second dispentachoron (Rectified 4-Simplex)
1617 | double aScore;
1618 | byte aPoint;
1619 | boolean aIsBiggerSide = true;
1620 | double bScore;
1621 | byte bPoint;
1622 | boolean bIsBiggerSide = true;
1623 |
1624 | //Decide between (0,0,1,1) and (1,1,0,0)
1625 | if (xins + yins < zins + wins) {
1626 | aScore = xins + yins;
1627 | aPoint = 0x0C;
1628 | } else {
1629 | aScore = zins + wins;
1630 | aPoint = 0x03;
1631 | }
1632 |
1633 | //Decide between (0,1,0,1) and (1,0,1,0)
1634 | if (xins + zins < yins + wins) {
1635 | bScore = xins + zins;
1636 | bPoint = 0x0A;
1637 | } else {
1638 | bScore = yins + wins;
1639 | bPoint = 0x05;
1640 | }
1641 |
1642 | //Closer between (0,1,1,0) and (1,0,0,1) will replace the further of a and b, if closer.
1643 | if (xins + wins < yins + zins) {
1644 | double score = xins + wins;
1645 | if (aScore <= bScore && score < bScore) {
1646 | bScore = score;
1647 | bPoint = 0x06;
1648 | } else if (aScore > bScore && score < aScore) {
1649 | aScore = score;
1650 | aPoint = 0x06;
1651 | }
1652 | } else {
1653 | double score = yins + zins;
1654 | if (aScore <= bScore && score < bScore) {
1655 | bScore = score;
1656 | bPoint = 0x09;
1657 | } else if (aScore > bScore && score < aScore) {
1658 | aScore = score;
1659 | aPoint = 0x09;
1660 | }
1661 | }
1662 |
1663 | //Decide if (0,1,1,1) is closer.
1664 | double p1 = 3 - inSum + xins;
1665 | if (aScore <= bScore && p1 < bScore) {
1666 | bScore = p1;
1667 | bPoint = 0x0E;
1668 | bIsBiggerSide = false;
1669 | } else if (aScore > bScore && p1 < aScore) {
1670 | aScore = p1;
1671 | aPoint = 0x0E;
1672 | aIsBiggerSide = false;
1673 | }
1674 |
1675 | //Decide if (1,0,1,1) is closer.
1676 | double p2 = 3 - inSum + yins;
1677 | if (aScore <= bScore && p2 < bScore) {
1678 | bScore = p2;
1679 | bPoint = 0x0D;
1680 | bIsBiggerSide = false;
1681 | } else if (aScore > bScore && p2 < aScore) {
1682 | aScore = p2;
1683 | aPoint = 0x0D;
1684 | aIsBiggerSide = false;
1685 | }
1686 |
1687 | //Decide if (1,1,0,1) is closer.
1688 | double p3 = 3 - inSum + zins;
1689 | if (aScore <= bScore && p3 < bScore) {
1690 | bScore = p3;
1691 | bPoint = 0x0B;
1692 | bIsBiggerSide = false;
1693 | } else if (aScore > bScore && p3 < aScore) {
1694 | aScore = p3;
1695 | aPoint = 0x0B;
1696 | aIsBiggerSide = false;
1697 | }
1698 |
1699 | //Decide if (1,1,1,0) is closer.
1700 | double p4 = 3 - inSum + wins;
1701 | if (aScore <= bScore && p4 < bScore) {
1702 | bScore = p4;
1703 | bPoint = 0x07;
1704 | bIsBiggerSide = false;
1705 | } else if (aScore > bScore && p4 < aScore) {
1706 | aScore = p4;
1707 | aPoint = 0x07;
1708 | aIsBiggerSide = false;
1709 | }
1710 |
1711 | //Where each of the two closest points are determines how the extra three vertices are calculated.
1712 | if (aIsBiggerSide == bIsBiggerSide) {
1713 | if (aIsBiggerSide) { //Both closest points on the bigger side
1714 | byte c1 = (byte)(aPoint & bPoint);
1715 | byte c2 = (byte)(aPoint | bPoint);
1716 |
1717 | //Two contributions are permutations of (0,0,0,1) and (0,0,0,2) based on c1
1718 | xsv_ext0 = xsv_ext1 = xsb;
1719 | ysv_ext0 = ysv_ext1 = ysb;
1720 | zsv_ext0 = zsv_ext1 = zsb;
1721 | wsv_ext0 = wsv_ext1 = wsb;
1722 | dx_ext0 = dx0 - SQUISH_CONSTANT_4D;
1723 | dy_ext0 = dy0 - SQUISH_CONSTANT_4D;
1724 | dz_ext0 = dz0 - SQUISH_CONSTANT_4D;
1725 | dw_ext0 = dw0 - SQUISH_CONSTANT_4D;
1726 | dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_4D;
1727 | dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_4D;
1728 | dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_4D;
1729 | dw_ext1 = dw0 - 2 * SQUISH_CONSTANT_4D;
1730 | if ((c1 & 0x01) != 0) {
1731 | xsv_ext0 += 1;
1732 | dx_ext0 -= 1;
1733 | xsv_ext1 += 2;
1734 | dx_ext1 -= 2;
1735 | } else if ((c1 & 0x02) != 0) {
1736 | ysv_ext0 += 1;
1737 | dy_ext0 -= 1;
1738 | ysv_ext1 += 2;
1739 | dy_ext1 -= 2;
1740 | } else if ((c1 & 0x04) != 0) {
1741 | zsv_ext0 += 1;
1742 | dz_ext0 -= 1;
1743 | zsv_ext1 += 2;
1744 | dz_ext1 -= 2;
1745 | } else {
1746 | wsv_ext0 += 1;
1747 | dw_ext0 -= 1;
1748 | wsv_ext1 += 2;
1749 | dw_ext1 -= 2;
1750 | }
1751 |
1752 | //One contribution is a permutation of (1,1,1,-1) based on c2
1753 | xsv_ext2 = xsb + 1;
1754 | ysv_ext2 = ysb + 1;
1755 | zsv_ext2 = zsb + 1;
1756 | wsv_ext2 = wsb + 1;
1757 | dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1758 | dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
1759 | dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
1760 | dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
1761 | if ((c2 & 0x01) == 0) {
1762 | xsv_ext2 -= 2;
1763 | dx_ext2 += 2;
1764 | } else if ((c2 & 0x02) == 0) {
1765 | ysv_ext2 -= 2;
1766 | dy_ext2 += 2;
1767 | } else if ((c2 & 0x04) == 0) {
1768 | zsv_ext2 -= 2;
1769 | dz_ext2 += 2;
1770 | } else {
1771 | wsv_ext2 -= 2;
1772 | dw_ext2 += 2;
1773 | }
1774 | } else { //Both closest points on the smaller side
1775 | //One of the two extra points is (1,1,1,1)
1776 | xsv_ext2 = xsb + 1;
1777 | ysv_ext2 = ysb + 1;
1778 | zsv_ext2 = zsb + 1;
1779 | wsv_ext2 = wsb + 1;
1780 | dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D;
1781 | dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D;
1782 | dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D;
1783 | dw_ext2 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D;
1784 |
1785 | //Other two points are based on the shared axes.
1786 | byte c = (byte)(aPoint & bPoint);
1787 |
1788 | if ((c & 0x01) != 0) {
1789 | xsv_ext0 = xsb + 2;
1790 | xsv_ext1 = xsb + 1;
1791 | dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D;
1792 | dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
1793 | } else {
1794 | xsv_ext0 = xsv_ext1 = xsb;
1795 | dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D;
1796 | }
1797 |
1798 | if ((c & 0x02) != 0) {
1799 | ysv_ext0 = ysv_ext1 = ysb + 1;
1800 | dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
1801 | if ((c & 0x01) == 0)
1802 | {
1803 | ysv_ext0 += 1;
1804 | dy_ext0 -= 1;
1805 | } else {
1806 | ysv_ext1 += 1;
1807 | dy_ext1 -= 1;
1808 | }
1809 | } else {
1810 | ysv_ext0 = ysv_ext1 = ysb;
1811 | dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D;
1812 | }
1813 |
1814 | if ((c & 0x04) != 0) {
1815 | zsv_ext0 = zsv_ext1 = zsb + 1;
1816 | dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
1817 | if ((c & 0x03) == 0)
1818 | {
1819 | zsv_ext0 += 1;
1820 | dz_ext0 -= 1;
1821 | } else {
1822 | zsv_ext1 += 1;
1823 | dz_ext1 -= 1;
1824 | }
1825 | } else {
1826 | zsv_ext0 = zsv_ext1 = zsb;
1827 | dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D;
1828 | }
1829 |
1830 | if ((c & 0x08) != 0)
1831 | {
1832 | wsv_ext0 = wsb + 1;
1833 | wsv_ext1 = wsb + 2;
1834 | dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
1835 | dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D;
1836 | } else {
1837 | wsv_ext0 = wsv_ext1 = wsb;
1838 | dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D;
1839 | }
1840 | }
1841 | } else { //One point on each "side"
1842 | byte c1, c2;
1843 | if (aIsBiggerSide) {
1844 | c1 = aPoint;
1845 | c2 = bPoint;
1846 | } else {
1847 | c1 = bPoint;
1848 | c2 = aPoint;
1849 | }
1850 |
1851 | //Two contributions are the bigger-sided point with each 1 replaced with 2.
1852 | if ((c1 & 0x01) != 0) {
1853 | xsv_ext0 = xsb + 2;
1854 | xsv_ext1 = xsb + 1;
1855 | dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D;
1856 | dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
1857 | } else {
1858 | xsv_ext0 = xsv_ext1 = xsb;
1859 | dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D;
1860 | }
1861 |
1862 | if ((c1 & 0x02) != 0) {
1863 | ysv_ext0 = ysv_ext1 = ysb + 1;
1864 | dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
1865 | if ((c1 & 0x01) == 0) {
1866 | ysv_ext0 += 1;
1867 | dy_ext0 -= 1;
1868 | } else {
1869 | ysv_ext1 += 1;
1870 | dy_ext1 -= 1;
1871 | }
1872 | } else {
1873 | ysv_ext0 = ysv_ext1 = ysb;
1874 | dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D;
1875 | }
1876 |
1877 | if ((c1 & 0x04) != 0) {
1878 | zsv_ext0 = zsv_ext1 = zsb + 1;
1879 | dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
1880 | if ((c1 & 0x03) == 0) {
1881 | zsv_ext0 += 1;
1882 | dz_ext0 -= 1;
1883 | } else {
1884 | zsv_ext1 += 1;
1885 | dz_ext1 -= 1;
1886 | }
1887 | } else {
1888 | zsv_ext0 = zsv_ext1 = zsb;
1889 | dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D;
1890 | }
1891 |
1892 | if ((c1 & 0x08) != 0) {
1893 | wsv_ext0 = wsb + 1;
1894 | wsv_ext1 = wsb + 2;
1895 | dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
1896 | dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D;
1897 | } else {
1898 | wsv_ext0 = wsv_ext1 = wsb;
1899 | dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D;
1900 | }
1901 |
1902 | //One contribution is a permutation of (1,1,1,-1) based on the smaller-sided point
1903 | xsv_ext2 = xsb + 1;
1904 | ysv_ext2 = ysb + 1;
1905 | zsv_ext2 = zsb + 1;
1906 | wsv_ext2 = wsb + 1;
1907 | dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1908 | dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
1909 | dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
1910 | dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
1911 | if ((c2 & 0x01) == 0) {
1912 | xsv_ext2 -= 2;
1913 | dx_ext2 += 2;
1914 | } else if ((c2 & 0x02) == 0) {
1915 | ysv_ext2 -= 2;
1916 | dy_ext2 += 2;
1917 | } else if ((c2 & 0x04) == 0) {
1918 | zsv_ext2 -= 2;
1919 | dz_ext2 += 2;
1920 | } else {
1921 | wsv_ext2 -= 2;
1922 | dw_ext2 += 2;
1923 | }
1924 | }
1925 |
1926 | //Contribution (1,1,1,0)
1927 | double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
1928 | double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
1929 | double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
1930 | double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D;
1931 | double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4;
1932 | if (attn4 > 0) {
1933 | attn4 *= attn4;
1934 | value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4);
1935 | }
1936 |
1937 | //Contribution (1,1,0,1)
1938 | double dx3 = dx4;
1939 | double dy3 = dy4;
1940 | double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D;
1941 | double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
1942 | double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3;
1943 | if (attn3 > 0) {
1944 | attn3 *= attn3;
1945 | value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3);
1946 | }
1947 |
1948 | //Contribution (1,0,1,1)
1949 | double dx2 = dx4;
1950 | double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D;
1951 | double dz2 = dz4;
1952 | double dw2 = dw3;
1953 | double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2;
1954 | if (attn2 > 0) {
1955 | attn2 *= attn2;
1956 | value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2);
1957 | }
1958 |
1959 | //Contribution (0,1,1,1)
1960 | double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D;
1961 | double dz1 = dz4;
1962 | double dy1 = dy4;
1963 | double dw1 = dw3;
1964 | double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1;
1965 | if (attn1 > 0) {
1966 | attn1 *= attn1;
1967 | value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1);
1968 | }
1969 |
1970 | //Contribution (1,1,0,0)
1971 | double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1972 | double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
1973 | double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
1974 | double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
1975 | double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5;
1976 | if (attn5 > 0) {
1977 | attn5 *= attn5;
1978 | value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5);
1979 | }
1980 |
1981 | //Contribution (1,0,1,0)
1982 | double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1983 | double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
1984 | double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
1985 | double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
1986 | double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6;
1987 | if (attn6 > 0) {
1988 | attn6 *= attn6;
1989 | value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6);
1990 | }
1991 |
1992 | //Contribution (1,0,0,1)
1993 | double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
1994 | double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
1995 | double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
1996 | double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
1997 | double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7;
1998 | if (attn7 > 0) {
1999 | attn7 *= attn7;
2000 | value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7);
2001 | }
2002 |
2003 | //Contribution (0,1,1,0)
2004 | double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
2005 | double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
2006 | double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
2007 | double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
2008 | double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8;
2009 | if (attn8 > 0) {
2010 | attn8 *= attn8;
2011 | value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8);
2012 | }
2013 |
2014 | //Contribution (0,1,0,1)
2015 | double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
2016 | double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
2017 | double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
2018 | double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
2019 | double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9;
2020 | if (attn9 > 0) {
2021 | attn9 *= attn9;
2022 | value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9);
2023 | }
2024 |
2025 | //Contribution (0,0,1,1)
2026 | double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
2027 | double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
2028 | double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
2029 | double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
2030 | double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10;
2031 | if (attn10 > 0) {
2032 | attn10 *= attn10;
2033 | value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10);
2034 | }
2035 | }
2036 |
2037 | //First extra vertex
2038 | double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0;
2039 | if (attn_ext0 > 0)
2040 | {
2041 | attn_ext0 *= attn_ext0;
2042 | value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0, dx_ext0, dy_ext0, dz_ext0, dw_ext0);
2043 | }
2044 |
2045 | //Second extra vertex
2046 | double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1;
2047 | if (attn_ext1 > 0)
2048 | {
2049 | attn_ext1 *= attn_ext1;
2050 | value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1, dx_ext1, dy_ext1, dz_ext1, dw_ext1);
2051 | }
2052 |
2053 | //Third extra vertex
2054 | double attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2;
2055 | if (attn_ext2 > 0)
2056 | {
2057 | attn_ext2 *= attn_ext2;
2058 | value += attn_ext2 * attn_ext2 * extrapolate(xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2, dx_ext2, dy_ext2, dz_ext2, dw_ext2);
2059 | }
2060 |
2061 | return value / NORM_CONSTANT_4D;
2062 | }
2063 |
2064 | private double extrapolate(int xsb, int ysb, double dx, double dy)
2065 | {
2066 | int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E;
2067 | return gradients2D[index] * dx
2068 | + gradients2D[index + 1] * dy;
2069 | }
2070 |
2071 | private double extrapolate(int xsb, int ysb, int zsb, double dx, double dy, double dz)
2072 | {
2073 | int index = permGradIndex3D[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF];
2074 | return gradients3D[index] * dx
2075 | + gradients3D[index + 1] * dy
2076 | + gradients3D[index + 2] * dz;
2077 | }
2078 |
2079 | private double extrapolate(int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw)
2080 | {
2081 | int index = perm[(perm[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF] + wsb) & 0xFF] & 0xFC;
2082 | return gradients4D[index] * dx
2083 | + gradients4D[index + 1] * dy
2084 | + gradients4D[index + 2] * dz
2085 | + gradients4D[index + 3] * dw;
2086 | }
2087 |
2088 | private static int fastFloor(double x) {
2089 | int xi = (int)x;
2090 | return x < xi ? xi - 1 : xi;
2091 | }
2092 |
2093 | //Gradients for 2D. They approximate the directions to the
2094 | //vertices of an octagon from the center.
2095 | private static byte[] gradients2D = new byte[] {
2096 | 5, 2, 2, 5,
2097 | -5, 2, -2, 5,
2098 | 5, -2, 2, -5,
2099 | -5, -2, -2, -5,
2100 | };
2101 |
2102 | //Gradients for 3D. They approximate the directions to the
2103 | //vertices of a rhombicuboctahedron from the center, skewed so
2104 | //that the triangular and square facets can be inscribed inside
2105 | //circles of the same radius.
2106 | private static byte[] gradients3D = new byte[] {
2107 | -11, 4, 4, -4, 11, 4, -4, 4, 11,
2108 | 11, 4, 4, 4, 11, 4, 4, 4, 11,
2109 | -11, -4, 4, -4, -11, 4, -4, -4, 11,
2110 | 11, -4, 4, 4, -11, 4, 4, -4, 11,
2111 | -11, 4, -4, -4, 11, -4, -4, 4, -11,
2112 | 11, 4, -4, 4, 11, -4, 4, 4, -11,
2113 | -11, -4, -4, -4, -11, -4, -4, -4, -11,
2114 | 11, -4, -4, 4, -11, -4, 4, -4, -11,
2115 | };
2116 |
2117 | //Gradients for 4D. They approximate the directions to the
2118 | //vertices of a disprismatotesseractihexadecachoron from the center,
2119 | //skewed so that the tetrahedral and cubic facets can be inscribed inside
2120 | //spheres of the same radius.
2121 | private static byte[] gradients4D = new byte[] {
2122 | 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3,
2123 | -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3,
2124 | 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3,
2125 | -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3,
2126 | 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3,
2127 | -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3,
2128 | 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3,
2129 | -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3,
2130 | 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3,
2131 | -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3,
2132 | 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3,
2133 | -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3,
2134 | 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3,
2135 | -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3,
2136 | 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3,
2137 | -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3,
2138 | };
2139 | }
--------------------------------------------------------------------------------