From ace545ddae107dae84f18d72e071a51d778da2b9 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 21 Jul 2020 20:24:09 +0200 Subject: [PATCH] collision with ground --- pom.xml | 394 +++--------------- .../game/datatypes/world/BlockPosition.java | 8 + .../minosoft/game/datatypes/world/Chunk.java | 3 + .../minosoft/game/datatypes/world/World.java | 3 + .../minosoft/movement/CameraMovement.java | 77 ++++ .../minosoft/movement/CollisionHandling.java | 133 ++++++ .../minosoft/movement/PlayerController.java | 110 +++++ .../minosoft/movement/PlayerMovement.java | 82 ++++ .../protocol/protocol/PacketHandler.java | 7 +- .../minosoft/render/FlyController.java | 115 ----- .../bixilon/minosoft/render/MainWindow.java | 18 +- .../minosoft/render/WorldRenderer.java | 4 + .../render/blockModels/BlockModelLoader.java | 5 +- .../render/blockModels/DrawDescription.java | 2 +- .../minosoft/render/face/FaceOrientation.java | 6 + .../minosoft/render/face/RenderConstants.java | 48 +-- .../render/texture/TextureLoader.java | 2 +- .../render/utility/AdditionalMath.java | 42 ++ .../bixilon/minosoft/render/utility/Vec3.java | 25 ++ 19 files changed, 587 insertions(+), 497 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/movement/CameraMovement.java create mode 100644 src/main/java/de/bixilon/minosoft/movement/CollisionHandling.java create mode 100644 src/main/java/de/bixilon/minosoft/movement/PlayerController.java create mode 100644 src/main/java/de/bixilon/minosoft/movement/PlayerMovement.java delete mode 100644 src/main/java/de/bixilon/minosoft/render/FlyController.java create mode 100644 src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java diff --git a/pom.xml b/pom.xml index 041aa8cfe..76f7316f1 100644 --- a/pom.xml +++ b/pom.xml @@ -1,22 +1,23 @@ - - + + + 4.0.0 - de.bixilon Minosoft 0.1 @@ -30,42 +31,18 @@ 11 - - org.openjfx - javafx-maven-plugin - 0.0.4 - - HelloFX - - - - 14 14 3.2.3 - natives-windows - - - - - org.lwjgl - lwjgl-bom - ${lwjgl.version} - import - pom - - - - - com.googlecode.json-simple - json-simple - 1.1 + org.openjfx + javafx-controls + 14 org.joda @@ -77,16 +54,6 @@ commons-primitives 1.0 - - org.l33tlabs.twl - pngdecoder - 1.0 - - - org.openjfx - javafx-controls - 14 - org.json json @@ -98,327 +65,60 @@ 1.25 - org.openjfx - javafx-fxml - 14 + org.lwjgl + lwjgl + natives-windows + ${lwjgl.version} org.lwjgl lwjgl - - - org.lwjgl - lwjgl-assimp - - - org.lwjgl - lwjgl-bgfx - - - org.lwjgl - lwjgl-cuda - - - org.lwjgl - lwjgl-egl - - - org.lwjgl - lwjgl-glfw - - - org.lwjgl - lwjgl-jawt - - - org.lwjgl - lwjgl-jemalloc - - - org.lwjgl - lwjgl-libdivide - - - org.lwjgl - lwjgl-llvm - - - org.lwjgl - lwjgl-lmdb - - - org.lwjgl - lwjgl-lz4 - - - org.lwjgl - lwjgl-meow - - - org.lwjgl - lwjgl-nanovg - - - org.lwjgl - lwjgl-nfd - - - org.lwjgl - lwjgl-nuklear - - - org.lwjgl - lwjgl-odbc - - - org.lwjgl - lwjgl-openal - - - org.lwjgl - lwjgl-opencl - - - org.lwjgl - lwjgl-opengl - - - org.lwjgl - lwjgl-opengles - - - org.lwjgl - lwjgl-openvr - - - org.lwjgl - lwjgl-opus - - - org.lwjgl - lwjgl-ovr - - - org.lwjgl - lwjgl-par - - - org.lwjgl - lwjgl-remotery - - - org.lwjgl - lwjgl-rpmalloc - - - org.lwjgl - lwjgl-shaderc - - - org.lwjgl - lwjgl-sse - - - org.lwjgl - lwjgl-stb - - - org.lwjgl - lwjgl-tinyexr - - - org.lwjgl - lwjgl-tinyfd - - - org.lwjgl - lwjgl-tootle - - - org.lwjgl - lwjgl-vma - - - org.lwjgl - lwjgl-vulkan - - - org.lwjgl - lwjgl-xxhash - - - org.lwjgl - lwjgl-yoga - - - org.lwjgl - lwjgl-zstd + natives-linux + ${lwjgl.version} org.lwjgl lwjgl - ${lwjgl.natives} - - - org.lwjgl - lwjgl-assimp - ${lwjgl.natives} - - - org.lwjgl - lwjgl-bgfx - ${lwjgl.natives} - - - org.lwjgl - lwjgl-glfw - ${lwjgl.natives} - - - org.lwjgl - lwjgl-jemalloc - ${lwjgl.natives} - - - org.lwjgl - lwjgl-libdivide - ${lwjgl.natives} - - - org.lwjgl - lwjgl-llvm - ${lwjgl.natives} - - - org.lwjgl - lwjgl-lmdb - ${lwjgl.natives} - - - org.lwjgl - lwjgl-lz4 - ${lwjgl.natives} - - - org.lwjgl - lwjgl-meow - ${lwjgl.natives} - - - org.lwjgl - lwjgl-nanovg - ${lwjgl.natives} - - - org.lwjgl - lwjgl-nfd - ${lwjgl.natives} - - - org.lwjgl - lwjgl-nuklear - ${lwjgl.natives} - - - org.lwjgl - lwjgl-openal - ${lwjgl.natives} + ${lwjgl.version} org.lwjgl lwjgl-opengl - ${lwjgl.natives} + ${lwjgl.version} org.lwjgl - lwjgl-opengles - ${lwjgl.natives} + lwjgl-opengl + natives-linux + ${lwjgl.version} org.lwjgl - lwjgl-openvr - ${lwjgl.natives} + lwjgl-opengl + natives-windows + ${lwjgl.version} + + + org.l33tlabs.twl + pngdecoder + 1.0 org.lwjgl - lwjgl-opus - ${lwjgl.natives} + lwjgl-glfw + ${lwjgl.version} org.lwjgl - lwjgl-ovr - ${lwjgl.natives} + lwjgl-glfw + natives-windows + ${lwjgl.version} org.lwjgl - lwjgl-par - ${lwjgl.natives} - - - org.lwjgl - lwjgl-remotery - ${lwjgl.natives} - - - org.lwjgl - lwjgl-rpmalloc - ${lwjgl.natives} - - - org.lwjgl - lwjgl-shaderc - ${lwjgl.natives} - - - org.lwjgl - lwjgl-sse - ${lwjgl.natives} - - - org.lwjgl - lwjgl-stb - ${lwjgl.natives} - - - org.lwjgl - lwjgl-tinyexr - ${lwjgl.natives} - - - org.lwjgl - lwjgl-tinyfd - ${lwjgl.natives} - - - org.lwjgl - lwjgl-tootle - ${lwjgl.natives} - - - org.lwjgl - lwjgl-vma - ${lwjgl.natives} - - - org.lwjgl - lwjgl-xxhash - ${lwjgl.natives} - - - org.lwjgl - lwjgl-yoga - ${lwjgl.natives} - - - org.lwjgl - lwjgl-zstd - ${lwjgl.natives} - - - org.jetbrains - annotations - 18.0.0 - compile + lwjgl-glfw + natives-linux + ${lwjgl.version} \ No newline at end of file diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java index 8e7b191bf..d997fe2f6 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java @@ -13,6 +13,8 @@ package de.bixilon.minosoft.game.datatypes.world; +import de.bixilon.minosoft.render.utility.Vec3; + public class BlockPosition { final int x; final int y; @@ -25,6 +27,12 @@ public class BlockPosition { this.z = z; } + public BlockPosition(Vec3 testPosition) { + x = (int) testPosition.x; + y = (short) testPosition.y; + z = (int) testPosition.z; + } + public int getX() { return x; } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java index 396ba944b..63cd69186 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java @@ -33,6 +33,9 @@ public class Chunk { throw new IllegalArgumentException(String.format("Invalid chunk location %s %s %s", x, y, z)); } byte section = (byte) (y / 16); + if (nibbles.get(section) == null) { + return Blocks.AIR; + } return nibbles.get(section).getBlock(x, y % 16, z); } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/World.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/World.java index 61db3eac5..25899acc5 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/World.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/World.java @@ -57,6 +57,9 @@ public class World { } public Blocks getBlock(BlockPosition pos) { + if (pos.y < 1) { + return Blocks.AIR; + } ChunkLocation loc = pos.getChunkLocation(); if (getChunk(loc) != null) { return getChunk(loc).getBlock(pos.getInChunkLocation()); diff --git a/src/main/java/de/bixilon/minosoft/movement/CameraMovement.java b/src/main/java/de/bixilon/minosoft/movement/CameraMovement.java new file mode 100644 index 000000000..1be35b0de --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/movement/CameraMovement.java @@ -0,0 +1,77 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.movement; + +import de.bixilon.minosoft.render.utility.Vec3; + +import static de.bixilon.minosoft.render.utility.Vec3.normalize; +import static java.lang.StrictMath.*; +import static org.lwjgl.opengl.GL11.glRotatef; + +public class CameraMovement { + Vec3 cameraFront = new Vec3(0.0f, 0.0f, -1.0f); + + private boolean firstMouse = false; + private float lastX; + private float lastY; + private float yaw; + private float pitch; + + public void mouseCallback(long l, double xPos, double yPos) { + // variable l is unused but always given by openGL so we need it in the method signature + if (firstMouse) { + lastX = (float) xPos; + lastY = (float) yPos; + firstMouse = false; + } + + float xoffset = (float) (xPos - lastX); + float yoffset = (float) (lastY - yPos); // reversed since y-coordinates go from bottom to top + lastX = (float) xPos; + lastY = (float) yPos; + + float sensitivity = 0.1f; // change this value to your liking + xoffset *= sensitivity; + yoffset *= sensitivity; + + yaw += xoffset; + pitch += yoffset; + + // make sure that pitch does not get out of bounds + if (pitch > 89.0f) + pitch = 89.0f; + if (pitch < -89.0f) + pitch = -89.0f; + + Vec3 front = new Vec3(); + front.x = (float) -(sin(toRadians(yaw)) * cos(toRadians(pitch))); + front.y = 0; + front.z = (float) ((cos(toRadians(yaw))) * cos(toRadians(pitch))); + cameraFront = normalize(front); + } + + public void loop() { + glRotatef(pitch, 1, 0, 0); + glRotatef(yaw, 0, 1, 0); + } + + public void setRotation(float pitch, float yaw) { + this.pitch = pitch; + this.yaw = yaw; + } + + public Vec3 getCameraFront() { + return cameraFront; + } +} diff --git a/src/main/java/de/bixilon/minosoft/movement/CollisionHandling.java b/src/main/java/de/bixilon/minosoft/movement/CollisionHandling.java new file mode 100644 index 000000000..6fc581103 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/movement/CollisionHandling.java @@ -0,0 +1,133 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Lukas Eisenhauer + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.movement; + +import de.bixilon.minosoft.game.datatypes.world.BlockPosition; +import de.bixilon.minosoft.game.datatypes.world.World; +import de.bixilon.minosoft.render.blockModels.BlockModelLoader; +import de.bixilon.minosoft.render.utility.Vec3; + +import java.util.ArrayList; +import java.util.List; + +import static de.bixilon.minosoft.render.utility.AdditionalMath.betterRound; +import static de.bixilon.minosoft.render.utility.AdditionalMath.valuesBetween; + +public class CollisionHandling { + private static Vec3 lastPosInverted; + private static Vec3 posDifference; + + public static void handleCollisions(World world, PlayerController controller, BlockModelLoader modelLoader, Vec3 deltaPos) { + + groundCollision(world, controller, modelLoader, deltaPos); + if (!controller.isOnGround()) { + // if we are stuck in a block, just stay there, otherwise, we would fall through the world + //topCollision(world, controller, modelLoader); + } + //xAxisCollision(world, controller, modelLoader, deltaPos); + } + + private static void xAxisCollision(World world, PlayerController controller, BlockModelLoader modelLoader, Vec3 deltaPos) { + Vec3 playerPos = controller.getPlayerPos(); + int xVelocityDirection = deltaPos.getXNormalized(); + if (xVelocityDirection == 0) { + return; + } + + BlockPosition[] testPositions = getXAxisTestPositions(controller, playerPos, xVelocityDirection); + + for (BlockPosition position : testPositions) { + if (modelLoader.isFull(world.getBlock(position))) { + playerPos.x = position.getX() - xVelocityDirection * controller.getPlayerWidth(); + controller.playerVelocity.x = 0; + return; + } + } + } + + private static void topCollision(World world, PlayerController controller, BlockModelLoader modelLoader) { + Vec3 headTop = controller.getPlayerPos().copy(); + headTop.y += controller.getPlayerHeight(); + + BlockPosition[] testPositions = getVerticalTestPositions(controller, headTop); + + for (BlockPosition position : testPositions) { + if (modelLoader.isFull(world.getBlock(position))) { + controller.playerVelocity.y = 0; + controller.playerPos.y = position.getY() - controller.getPlayerHeight(); + } + } + } + + public static void groundCollision(World world, PlayerController controller, BlockModelLoader modelLoader, Vec3 deltaPos) { + Vec3 playerPos = controller.playerPos.copy(); + playerPos.y++; + BlockPosition[] testPositions = getVerticalTestPositions(controller, playerPos); + + for (BlockPosition position : testPositions) { + if (modelLoader.isFull(world.getBlock(position))) { + controller.playerVelocity.y = 0; + controller.playerPos.y = position.getY(); + controller.onGround = true; + } + } + } + + private static BlockPosition[] getVerticalTestPositions(PlayerController controller, Vec3 testPos) { + List result = new ArrayList<>(); + float width = controller.getPlayerWidth(); + + List xPositions = new ArrayList<>(); + for (int xCoordinate : valuesBetween(betterRound(testPos.x + 0.5 * width), betterRound(testPos.x - 0.5 * width))) { + xPositions.add(xCoordinate); + } + + List zPositions = new ArrayList<>(); + for (int xCoordinate : valuesBetween(betterRound(testPos.z + 0.5 * width), betterRound(testPos.z - 0.5 * width))) { + zPositions.add(xCoordinate); + } + + for (int xPos : xPositions) { + for (int zPos : zPositions) { + result.add(new BlockPosition(xPos, (short) testPos.y, zPos)); + } + } + + return result.toArray(new BlockPosition[0]); + } + + private static BlockPosition[] getXAxisTestPositions(PlayerController controller, Vec3 testPos, int xVelocityDirection) { + List result = new ArrayList<>(); + float width = controller.getPlayerWidth(); + + List yPositions = new ArrayList<>(); + + for (int yCoordinate : valuesBetween(betterRound(testPos.y + 1), betterRound(testPos.y + controller.getPlayerHeight()))) { + yPositions.add(yCoordinate); + } + + List zPositions = new ArrayList<>(); + for (int zCoordinate : valuesBetween(betterRound(testPos.z + 0.5 * width), betterRound(testPos.z - 0.5 * width))) { + zPositions.add(zCoordinate); + } + + for (int yPos : yPositions) { + for (int zPos : zPositions) { + result.add(new BlockPosition(betterRound(testPos.x), (short) yPos, zPos)); + } + } + + return result.toArray(new BlockPosition[0]); + } +} diff --git a/src/main/java/de/bixilon/minosoft/movement/PlayerController.java b/src/main/java/de/bixilon/minosoft/movement/PlayerController.java new file mode 100644 index 000000000..fd3262284 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/movement/PlayerController.java @@ -0,0 +1,110 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.movement; + +import de.bixilon.minosoft.game.datatypes.GameMode; +import de.bixilon.minosoft.game.datatypes.world.World; +import de.bixilon.minosoft.render.MainWindow; +import de.bixilon.minosoft.render.blockModels.BlockModelLoader; +import de.bixilon.minosoft.render.utility.Vec3; + +import static org.lwjgl.opengl.GL11.glTranslatef; + +public class PlayerController { + private final float playerHeight = 1.8f; + private final float playerWidth = 0.5f; + CameraMovement cameraMovement; + PlayerMovement playerMovement; + Vec3 playerPos = new Vec3(0, 1, 0); // the feet position of the player + Vec3 playerVelocity = new Vec3(); + float gravity = 9.81f; + boolean onGround; + private boolean enableGravity; + + public PlayerController(long window) { + cameraMovement = new CameraMovement(); + playerMovement = new PlayerMovement(window); + } + + public void loop(float deltaTime) { + GameMode gameMode = MainWindow.getConnection().getPlayer().getGameMode(); + enableGravity = gameMode == GameMode.CREATIVE || gameMode == GameMode.SPECTATOR; + handleGravity(deltaTime); + cameraMovement.loop(); + playerMovement.loop(deltaTime); + applyVelocity(deltaTime); + + if (gameMode == GameMode.SPECTATOR) { + return; + } + handleCollisions(MainWindow.getConnection().getPlayer().getWorld()); + + glTranslatef(-playerPos.x, -(playerPos.y + playerHeight - 0.2f), -playerPos.z); + } + + private void handleCollisions(World world) { + onGround = false; + if (world == null) { + playerVelocity.zero(); + return; + } + BlockModelLoader modelLoader = MainWindow.getRenderer().getModelLoader(); + CollisionHandling.handleCollisions(world, this, modelLoader, playerMovement.deltaPos); + } + + public boolean isEnableGravity() { + return enableGravity; + } + + public Vec3 getPlayerPos() { + return playerPos; + } + + public void setPlayerPos(Vec3 playerPos) { + this.playerPos = playerPos; + } + + private void applyVelocity(float deltaTime) { + playerPos.add(Vec3.mul(playerVelocity, deltaTime)); + } + + private void handleGravity(float deltaTime) { + if (!enableGravity) { + return; + } + // a rather accurate model for the real world, but minecraft probably does it differently + playerVelocity.y -= gravity * deltaTime; + } + + public CameraMovement getCameraMovement() { + return cameraMovement; + } + + public boolean isOnGround() { + return onGround; + } + + public void jump() { + playerVelocity.y = 10; + onGround = false; + } + + public float getPlayerWidth() { + return playerWidth; + } + + public float getPlayerHeight() { + return playerHeight; + } +} diff --git a/src/main/java/de/bixilon/minosoft/movement/PlayerMovement.java b/src/main/java/de/bixilon/minosoft/movement/PlayerMovement.java new file mode 100644 index 000000000..dba0dc580 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/movement/PlayerMovement.java @@ -0,0 +1,82 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +/* + * A simple camera controller to fly around the scene + */ + +package de.bixilon.minosoft.movement; + +import de.bixilon.minosoft.render.MainWindow; +import de.bixilon.minosoft.render.utility.Vec3; + +import static de.bixilon.minosoft.render.utility.Vec3.*; +import static org.lwjgl.glfw.GLFW.*; + +public class PlayerMovement { + private final long window; + Vec3 cameraFront; + Vec3 cameraUp = new Vec3(0f, 1f, 0f); + + float flySpeed = 0.1f; + + Vec3 playerPos; + Vec3 deltaPos; + + public PlayerMovement(long window) { + this.window = window; + } + + private void processInput(float deltaTime) { + Vec3 posBefore = playerPos.copy(); + float cameraSpeed = flySpeed / deltaTime; + + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { + MainWindow.pause(); + } + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { + playerPos.add(mul(cameraFront, -cameraSpeed * deltaTime)); + } + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { + playerPos.add(mul(cameraFront, cameraSpeed * deltaTime)); + } + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { + playerPos.add(mul(cross(cameraUp, cameraFront), -cameraSpeed * deltaTime)); + } + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { + playerPos.add(mul(cross(cameraUp, cameraFront), cameraSpeed * deltaTime)); + } + + if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) { + if (!MainWindow.getPlayerMovement().isEnableGravity()) { + playerPos.add(0, cameraSpeed * deltaTime, 0); + } + } + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) { + if (!MainWindow.getPlayerMovement().isEnableGravity()) { + playerPos.add(0, -cameraSpeed * deltaTime, 0); + } + if (MainWindow.getPlayerMovement().isOnGround()) { + + MainWindow.getPlayerMovement().jump(); + } + } + deltaPos = add(playerPos, mul(posBefore, -1)); + } + + public void loop(float deltaTime) { + cameraFront = MainWindow.getPlayerMovement().getCameraMovement().getCameraFront(); + playerPos = MainWindow.getPlayerMovement().getPlayerPos(); + processInput(deltaTime); + } +} \ No newline at end of file diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java index 0329d72e6..f971ff92a 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -35,6 +35,8 @@ import de.bixilon.minosoft.protocol.packets.serverbound.login.PacketEncryptionRe import de.bixilon.minosoft.protocol.packets.serverbound.play.PacketKeepAliveResponse; import de.bixilon.minosoft.protocol.packets.serverbound.play.PacketPlayerPositionAndRotationSending; import de.bixilon.minosoft.protocol.packets.serverbound.play.PacketResourcePackStatus; +import de.bixilon.minosoft.render.MainWindow; +import de.bixilon.minosoft.render.utility.Vec3; import javax.crypto.SecretKey; import java.math.BigInteger; @@ -344,7 +346,10 @@ public class PacketHandler { } public void handle(PacketPlayerPositionAndRotation pkg) { - //ToDo handle with gui + MainWindow.getPlayerMovement().getCameraMovement().setRotation(pkg.getPitch(), pkg.getYaw()); + MainWindow.getPlayerMovement().setPlayerPos(new Vec3(pkg.getLocation())); + //TODO: location + if (!connection.getPlayer().isSpawnConfirmed()) { // oops, not spawned yet, confirming position //ToDo feet position diff --git a/src/main/java/de/bixilon/minosoft/render/FlyController.java b/src/main/java/de/bixilon/minosoft/render/FlyController.java deleted file mode 100644 index 1fdfb796d..000000000 --- a/src/main/java/de/bixilon/minosoft/render/FlyController.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Codename Minosoft - * Copyright (C) 2020 Lukas Eisenhauer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -/* - * A simple camera controller to fly around the scene - */ - -package de.bixilon.minosoft.render; - -import de.bixilon.minosoft.render.utility.Vec3; - -import static de.bixilon.minosoft.render.utility.Vec3.*; -import static java.lang.StrictMath.*; -import static org.lwjgl.glfw.GLFW.*; -import static org.lwjgl.opengl.GL11.*; - -public class FlyController { - private final long window; - Vec3 cameraPos = new Vec3(0.0f, 0.0f, 0.0f); - Vec3 cameraFront = new Vec3(0.0f, 0.0f, -1.0f); - Vec3 cameraUp = new Vec3(0.0f, 1.0f, 0.0f); - float lastX; - float lastY; - - float yaw = 0f; - float pitch = 0f; - - float flySpeed = 0.1f; - private boolean firstMouse = true; - - public FlyController(long window) { - this.window = window; - } - - private void processInput(long window, float deltaTime) { - float cameraSpeed = flySpeed / deltaTime; - - if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { - MainWindow.pause(); - } - if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { - cameraPos.add(mul(cameraFront, cameraSpeed * deltaTime)); - } - if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { - cameraPos.add(mul(cameraFront, -cameraSpeed * deltaTime)); - } - if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { - cameraPos.add(mul(cross(cameraUp, cameraFront), cameraSpeed * deltaTime)); - } - if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { - cameraPos.add(mul(cross(cameraUp, cameraFront), -cameraSpeed * deltaTime)); - } - - if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) { - cameraPos.add(0, cameraSpeed * deltaTime, 0); - } - if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) { - cameraPos.add(0, -cameraSpeed * deltaTime, 0); - } - } - - public void loop(float deltaTime) { - processInput(window, deltaTime); - //glLoadIdentity(); - //glTranslatef(cameraPos.x, cameraPos.y, cameraPos.z); - //glPushMatrix(); - //glTranslatef(-cameraPos.x, -cameraPos.y, -cameraPos.z); - glRotatef(pitch, 1, 0, 0); - glRotatef(yaw, 0, 1, 0); - glTranslatef(cameraPos.x, cameraPos.y, cameraPos.z); - glPushMatrix(); - } - - public void mouseCallback(long l, double xPos, double yPos) { - if (firstMouse) { - lastX = (float) xPos; - lastY = (float) yPos; - firstMouse = false; - } - - float xoffset = (float) (xPos - lastX); - float yoffset = (float) (lastY - yPos); // reversed since y-coordinates go from bottom to top - lastX = (float) xPos; - lastY = (float) yPos; - - float sensitivity = 0.1f; // change this value to your liking - xoffset *= sensitivity; - yoffset *= sensitivity; - - yaw += xoffset; - pitch += yoffset; - - // make sure that when pitch is out of bounds, screen doesn't get flipped - if (pitch > 89.0f) - pitch = 89.0f; - if (pitch < -89.0f) - pitch = -89.0f; - - Vec3 front = new Vec3(); - front.x = (float) -(sin(toRadians(yaw)) * cos(toRadians(pitch))); - front.y = 0;//(float) sin(toRadians(pitch)); - front.z = (float) ((cos(toRadians(yaw))) * cos(toRadians(pitch))); - cameraFront = normalize(front); - } -} \ No newline at end of file diff --git a/src/main/java/de/bixilon/minosoft/render/MainWindow.java b/src/main/java/de/bixilon/minosoft/render/MainWindow.java index 99e1e3030..c2ada5500 100644 --- a/src/main/java/de/bixilon/minosoft/render/MainWindow.java +++ b/src/main/java/de/bixilon/minosoft/render/MainWindow.java @@ -13,6 +13,7 @@ package de.bixilon.minosoft.render; +import de.bixilon.minosoft.movement.PlayerController; import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.render.MainMenu.MainMenu; import de.bixilon.minosoft.render.utility.RenderMode; @@ -33,7 +34,8 @@ public class MainWindow { static MainMenu mainMenu; static WorldRenderer renderer; static Connection connection; - static FlyController flyController; + private static PlayerController playerMovement; + public static void start(Connection serverConnection) { Thread guiThread = new Thread(() -> { @@ -42,15 +44,15 @@ public class MainWindow { openGLWindow.init(); renderer = new WorldRenderer(); renderer.init(); - flyController = new FlyController(openGLWindow.getWindow()); + playerMovement = new PlayerController(openGLWindow.getWindow()); renderMode = MAIN_MENU; mainMenu = new MainMenu(openGLWindow.getWidth(), openGLWindow.getHeight()); - runWindow(); + mainLoop(); }); guiThread.start(); } - private static void runWindow() { + private static void mainLoop() { while (!glfwWindowShouldClose(openGLWindow.getWindow())) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); @@ -67,7 +69,7 @@ public class MainWindow { break; case PLAY: OpenGLWindow.gluPerspective(FOVY, (float) WIDTH / (float) HEIGHT, 0.1f, 500f); - flyController.loop(deltaTime); + playerMovement.loop(deltaTime); renderer.draw(); break; } @@ -89,7 +91,7 @@ public class MainWindow { renderMode = PLAY; glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); - glfwSetCursorPosCallback(openGLWindow.getWindow(), flyController::mouseCallback); + glfwSetCursorPosCallback(openGLWindow.getWindow(), playerMovement.getCameraMovement()::mouseCallback); glfwSetInputMode(openGLWindow.getWindow(), GLFW_CURSOR, GLFW_CURSOR_DISABLED); glEnable(GL_TEXTURE_2D); connection.connect(); @@ -108,4 +110,8 @@ public class MainWindow { public static void close() { System.exit(1); } + + public static PlayerController getPlayerMovement() { + return playerMovement; + } } diff --git a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java index 6aad82746..bd844feb5 100644 --- a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java +++ b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java @@ -137,4 +137,8 @@ public class WorldRenderer { public TextureLoader getTextureLoader() { return textureLoader; } + + public BlockModelLoader getModelLoader() { + return modelLoader; + } } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java index 3b1bbde5e..c19180dfd 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java @@ -16,7 +16,6 @@ package de.bixilon.minosoft.render.blockModels; import de.bixilon.minosoft.Config; import de.bixilon.minosoft.game.datatypes.blocks.Blocks; import org.json.JSONObject; -import org.json.simple.parser.JSONParser; import java.io.File; import java.io.IOException; @@ -41,7 +40,6 @@ public class BlockModelLoader { private void loadModels(String path) throws IOException { File[] files = new File(path).listFiles(); - JSONParser parser = new JSONParser(); for (File file : files) { String fileName = file.getName().substring(0, file.getName().lastIndexOf('.')); @@ -59,6 +57,9 @@ public class BlockModelLoader { } public boolean isFull(Blocks block) { + if (block == Blocks.AIR || block == null) { + return false; + } return drawDescriptionMap.get(block).isFull(); } } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/DrawDescription.java b/src/main/java/de/bixilon/minosoft/render/blockModels/DrawDescription.java index 7ab104964..a34552db1 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/DrawDescription.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/DrawDescription.java @@ -34,7 +34,7 @@ public class DrawDescription { Map> faces; - boolean full; // is the block a completely filled block + boolean full = false; // is the block a completely filled block? public DrawDescription(JSONObject json) { if (!(json.has("parent") && json.has("textures"))) return; diff --git a/src/main/java/de/bixilon/minosoft/render/face/FaceOrientation.java b/src/main/java/de/bixilon/minosoft/render/face/FaceOrientation.java index 77d5de44d..e3ff36086 100644 --- a/src/main/java/de/bixilon/minosoft/render/face/FaceOrientation.java +++ b/src/main/java/de/bixilon/minosoft/render/face/FaceOrientation.java @@ -21,6 +21,12 @@ public enum FaceOrientation { this.id = id; } + public static FaceOrientation[] getNotVerticalValues() { + return new FaceOrientation[]{ + EAST, WEST, SOUTH, NORTH + }; + } + public int getId() { return this.id; } diff --git a/src/main/java/de/bixilon/minosoft/render/face/RenderConstants.java b/src/main/java/de/bixilon/minosoft/render/face/RenderConstants.java index 503f946df..4f5252c60 100644 --- a/src/main/java/de/bixilon/minosoft/render/face/RenderConstants.java +++ b/src/main/java/de/bixilon/minosoft/render/face/RenderConstants.java @@ -17,40 +17,40 @@ public class RenderConstants { //TODO: fix rotated faces public static final float[][][] FACE_VERTEX = new float[][][]{ { - {0.5f, 0.5f, -0.5f}, - {0.5f, -0.5f, -0.5f}, - {0.5f, -0.5f, 0.5f}, - {0.5f, 0.5f, 0.5f} + {1, 0, 0}, + {1, -1, 0}, + {1, -1, 1}, + {1, 0, 1} }, { - {-0.5f, 0.5f, -0.5f}, - {-0.5f, -0.5f, -0.5f}, - {-0.5f, -0.5f, 0.5f}, - {-0.5f, 0.5f, 0.5f} + {0, 0, 0}, + {0, -1, 0}, + {0, -1, 1}, + {0, 0, 1} }, { - {0.5f, 0.5f, 0.5f}, - {-0.5f, 0.5f, 0.5f}, - {-0.5f, 0.5f, -0.5f}, - {0.5f, 0.5f, -0.5f}, + {0, 0, 0}, + {1, 0, 0}, + {1, 0, 1}, + {0, 0, 1} }, { - {0.5f, -0.5f, 0.5f}, - {-0.5f, -0.5f, 0.5f}, - {-0.5f, -0.5f, -0.5f}, - {0.5f, -0.5f, -0.5f}, + {0, -1, 0}, + {1, -1, 0}, + {1, -1, 1}, + {0, -1, 1} }, { - {0.5f, 0.5f, 0.5f}, - {0.5f, -0.5f, 0.5f}, - {-0.5f, -0.5f, 0.5f}, - {-0.5f, 0.5f, 0.5f}, + {1, 0, 1}, + {1, -1, 1}, + {0, -1, 1}, + {0, 0, 1}, }, { - {0.5f, 0.5f, -0.5f}, - {0.5f, -0.5f, -0.5f}, - {-0.5f, -0.5f, -0.5f}, - {-0.5f, 0.5f, -0.5f}, + {1, 0, 0}, + {1, -1, 0}, + {0, -1, 0}, + {0, 0, 0} }, }; diff --git a/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java b/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java index d91bbb325..c3ffcbf96 100644 --- a/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java +++ b/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java @@ -109,7 +109,7 @@ public class TextureLoader { BufferedImage img = ImageIO.read(textureInputStream); allTextures.add(new Pair<>(img, textureName)); } - //else we have a .mcmeta file + //else we have a .mcmeta file describing animated blocks } // CONVERT ALL THE IMAGES INTO A SINGLE, VERY LONG IMAGE diff --git a/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java b/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java new file mode 100644 index 000000000..d049f7f13 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java @@ -0,0 +1,42 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.render.utility; + +import static java.lang.Math.abs; + +public class AdditionalMath { + public static int[] valuesBetween(int x, int y) { + int[] result = new int[abs(x - y) + 1]; + if (x > y) { + for (int z = y; z <= x; z++) { + result[x - z] = z; + } + } else if (y > x) { + for (int z = x; z <= y; z++) { + result[y - z] = z; + } + } else { + result[0] = x; + } + + return result; + } + + public static int betterRound(double x) { + if (x >= 0) { + return (int) x; + } + return (int) x - 1; + } +} diff --git a/src/main/java/de/bixilon/minosoft/render/utility/Vec3.java b/src/main/java/de/bixilon/minosoft/render/utility/Vec3.java index 16083d5af..2ac21ad58 100644 --- a/src/main/java/de/bixilon/minosoft/render/utility/Vec3.java +++ b/src/main/java/de/bixilon/minosoft/render/utility/Vec3.java @@ -13,6 +13,8 @@ package de.bixilon.minosoft.render.utility; +import de.bixilon.minosoft.game.datatypes.entities.Location; + import static java.lang.Math.pow; import static java.lang.Math.sqrt; @@ -29,6 +31,12 @@ public class Vec3 { z = z_; } + public Vec3(Location location) { + x = (float) location.getX(); + y = (float) location.getY(); + z = (float) location.getZ(); + } + public static Vec3 add(Vec3 v1, Vec3 v2) { return new Vec3( v1.x + v2.x, @@ -92,4 +100,21 @@ public class Vec3 { y /= l; z /= l; } + + public Vec3 copy() { + return new Vec3(x, y, z); + } + + public void zero() { + x = y = z = 0f; + } + + public int getXNormalized() { + if (x == 0f) { + return 0; + } else if (x > 0) { + return 1; + } + return -1; + } }