From 20688ed60849a582c736a5ef8285e1b3feb8ce15 Mon Sep 17 00:00:00 2001 From: Azat Akhunov Date: Fri, 22 Oct 2021 10:12:59 +0300 Subject: [PATCH 1/3] block selection added & refactoring made --- assets/shaders/scene.glsl | 9 +- src/main/java/ru/mycubecraft/block/Block.java | 1 + .../java/ru/mycubecraft/block/DirtBlock.java | 7 +- .../java/ru/mycubecraft/block/GrassBlock.java | 7 +- src/main/java/ru/mycubecraft/data/Hud.java | 8 +- .../mycubecraft/listener/MouseListener.java | 21 +-- .../java/ru/mycubecraft/renderer/Camera.java | 76 ----------- .../ru/mycubecraft/renderer/Renderer.java | 8 +- .../mycubecraft/renderer/Transformation.java | 7 +- .../java/ru/mycubecraft/scene/LevelScene.java | 80 +++++------- src/main/java/ru/mycubecraft/scene/Scene.java | 6 +- .../java/ru/mycubecraft/util/MathUtil.java | 30 +++++ src/main/java/ru/mycubecraft/world/Chunk.java | 10 +- .../world/MouseBoxSelectionDetector.java | 29 ++--- src/main/java/ru/mycubecraft/world/World.java | 64 ++++------ .../ru/mycubecraft/world/player/Player.java | 28 +++- .../world/player/impl/DefaultPlayer.java | 120 ++++++++++++++++++ 17 files changed, 297 insertions(+), 214 deletions(-) delete mode 100644 src/main/java/ru/mycubecraft/renderer/Camera.java diff --git a/assets/shaders/scene.glsl b/assets/shaders/scene.glsl index cf0992f..5752e3b 100644 --- a/assets/shaders/scene.glsl +++ b/assets/shaders/scene.glsl @@ -199,15 +199,16 @@ void main() if ( fog.activeFog == 1 ) { if ( outSelected > .0 ) { - fragColor = calcFog(mvVertexPos, ambientC * vec4(ambientLight, 1) + diffuseSpecularComp, fog, ambientLight, directionalLight); - } else { fragColor = calcFog(mvVertexPos, vec4(1.0, 0.1, 0.1, 1.0) * ambientC * vec4(ambientLight, 1) + diffuseSpecularComp, fog, ambientLight, directionalLight); + } else { + fragColor = calcFog(mvVertexPos, ambientC * vec4(ambientLight, 1) + diffuseSpecularComp, fog, ambientLight, directionalLight); + } } else { if ( outSelected > .0 ) { - fragColor = ambientC * vec4(ambientLight, 1) + diffuseSpecularComp; - } else { fragColor = vec4(1.0, 0.1, 0.1, 1.0) * ambientC * vec4(ambientLight, 1) + diffuseSpecularComp; + } else { + fragColor = ambientC * vec4(ambientLight, 1) + diffuseSpecularComp; } } } diff --git a/src/main/java/ru/mycubecraft/block/Block.java b/src/main/java/ru/mycubecraft/block/Block.java index 156ee46..429038f 100644 --- a/src/main/java/ru/mycubecraft/block/Block.java +++ b/src/main/java/ru/mycubecraft/block/Block.java @@ -13,6 +13,7 @@ public abstract class Block { final Vector3f position; boolean disableFrustumCulling; boolean visible; + boolean selected; float scale; float boundingRadius; private boolean insideFrustum; diff --git a/src/main/java/ru/mycubecraft/block/DirtBlock.java b/src/main/java/ru/mycubecraft/block/DirtBlock.java index a8dd3b6..0a5d902 100644 --- a/src/main/java/ru/mycubecraft/block/DirtBlock.java +++ b/src/main/java/ru/mycubecraft/block/DirtBlock.java @@ -37,7 +37,12 @@ public void render() { @Override public GameItem getGameCubeItem() { - return this.gameCubeItem; + if (this.gameCubeItem != null) { + GameItem item = this.gameCubeItem; + item.setSelected(this.selected); + return item; + } + return null; } } diff --git a/src/main/java/ru/mycubecraft/block/GrassBlock.java b/src/main/java/ru/mycubecraft/block/GrassBlock.java index 05d172b..33aee15 100644 --- a/src/main/java/ru/mycubecraft/block/GrassBlock.java +++ b/src/main/java/ru/mycubecraft/block/GrassBlock.java @@ -35,7 +35,12 @@ public void render() { @Override public GameItem getGameCubeItem() { - return this.gameCubeItem; + if (this.gameCubeItem != null) { + GameItem item = this.gameCubeItem; + item.setSelected(this.selected); + return item; + } + return null; } diff --git a/src/main/java/ru/mycubecraft/data/Hud.java b/src/main/java/ru/mycubecraft/data/Hud.java index 0e377d9..4f2817b 100644 --- a/src/main/java/ru/mycubecraft/data/Hud.java +++ b/src/main/java/ru/mycubecraft/data/Hud.java @@ -9,10 +9,10 @@ import ru.mycubecraft.engine.Material; import ru.mycubecraft.engine.TextItem; import ru.mycubecraft.engine.graph.FontTexture; -import ru.mycubecraft.renderer.Camera; import ru.mycubecraft.util.AssetPool; import ru.mycubecraft.window.Window; import ru.mycubecraft.world.World; +import ru.mycubecraft.world.player.Player; import java.awt.*; @@ -122,12 +122,12 @@ public GameItem[] getGameItems() { return gameItems; } - public void updateHud(Camera camera, World world, int filteredBlocksCount) { + public void updateHud(Player player, World world, int filteredBlocksCount) { Window window = Window.getInstance(); this.versionTextItem.setPosition(window.getWidth() - 100.0f, window.getHeight() - 20f, 0); - Vector4f cameraPosition = camera.getPosition(); - Vector3f cameraRotation = camera.getRotation(); + Vector4f cameraPosition = player.getPosition(); + Vector3f cameraRotation = player.getRotation(); this.coordinatesTextItem.setText(String.format("Position [X: %s Y: %s Z: %s]", cameraPosition.x, cameraPosition.y, cameraPosition.z)); this.coordinatesTextItem.setPosition(20.0f, 40f, 0); diff --git a/src/main/java/ru/mycubecraft/listener/MouseListener.java b/src/main/java/ru/mycubecraft/listener/MouseListener.java index 400d618..3bbccec 100644 --- a/src/main/java/ru/mycubecraft/listener/MouseListener.java +++ b/src/main/java/ru/mycubecraft/listener/MouseListener.java @@ -3,6 +3,8 @@ import lombok.Getter; import lombok.Setter; +import static org.lwjgl.glfw.GLFW.*; + @Getter @Setter public class MouseListener { @@ -11,10 +13,12 @@ public class MouseListener { private final boolean[] mouseButtonPressed = new boolean[3]; private final boolean inWindow = false; + private boolean leftButtonPressed = false; + private boolean rightButtonPressed = false; + private boolean firstCursorPos = true; private int mouseX, mouseY; private float angx, angy, dangx, dangy; - private boolean hasSelection; private MouseListener() { } @@ -50,13 +54,12 @@ public void onCursorPos(long window, double x, double y) { * GLFW callback for mouse buttons. */ public void onMouseButton(long window, int button, int action, int mods) { - // updateAndRenderRunnables.add(new DelayedRunnable(() -> { -// if (button == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS && hasSelection) { -// //placeAtSelectedBlock(); -// } else if (button == GLFW_MOUSE_BUTTON_2 && action == GLFW_PRESS && hasSelection) { -// //removeSelectedBlock(); -// } -// return null; -// }, "Mouse button event", 0)); + leftButtonPressed = button == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS; + rightButtonPressed = button == GLFW_MOUSE_BUTTON_2 && action == GLFW_PRESS; + } + + + public boolean isKeyPressed(int keyCode) { + return this.mouseButtonPressed[keyCode]; } } diff --git a/src/main/java/ru/mycubecraft/renderer/Camera.java b/src/main/java/ru/mycubecraft/renderer/Camera.java deleted file mode 100644 index a75a918..0000000 --- a/src/main/java/ru/mycubecraft/renderer/Camera.java +++ /dev/null @@ -1,76 +0,0 @@ -package ru.mycubecraft.renderer; - -import org.joml.Matrix4f; -import org.joml.Vector3f; -import org.joml.Vector4f; -import ru.mycubecraft.Settings; -import ru.mycubecraft.util.MathUtil; - -public class Camera { - - private static final float CAMERA_POS_STEP = 0.65f; - private final Matrix4f viewMatrix; - public Vector4f position; - public Vector3f rotation; - - public Camera() { - this.position = new Vector4f(47.0f, 130f, -179f, 1); - this.rotation = new Vector3f(32.0f, 9.0f, 0.0f); - this.viewMatrix = new Matrix4f(); - } - - public Matrix4f getViewMatrix() { - return viewMatrix; - } - - public Matrix4f updateViewMatrix() { - return Transformation.updateGenericViewMatrix(new Vector3f(position.x, position.y, position.z), rotation, viewMatrix); - } - - - public Vector4f getPosition() { - return position; - } - - public void setPosition(float x, float y, float z) { - this.position.x = x; - this.position.y = y; - this.position.z = z; - } - - public Vector3f getRotation() { - return rotation; - } - - public void setRotation(float x, float y, float z) { - this.rotation.x = x; - this.rotation.y = y; - this.rotation.z = z; - } - - public void moveRotation(double offsetX, double offsetY, double offsetZ) { - double xRotation = rotation.x; - double yRotation = rotation.y; - yRotation += offsetY; - if (yRotation > 360.0f || yRotation < -360.0f) { - yRotation = 0.0f; - } - xRotation += offsetX; - rotation.y = (float) yRotation; - rotation.z += offsetZ; - rotation.x = MathUtil.clamp((float) xRotation, (float) Settings.MIN_LOOK, (float) Settings.MAX_LOOK); - } - - public void movePosition(float offsetX, float offsetY, float offsetZ) { - if (offsetZ != 0) { - position.x += (float) Math.sin(Math.toRadians(rotation.y)) * -1.0f * offsetZ; - position.z += (float) Math.cos(Math.toRadians(rotation.y)) * offsetZ; - } - if (offsetX != 0) { - position.x += (float) Math.sin(Math.toRadians(rotation.y - 90)) * -1.0f * offsetX; - position.z += (float) Math.cos(Math.toRadians(rotation.y - 90)) * offsetX; - } - position.y += offsetY; - } - -} diff --git a/src/main/java/ru/mycubecraft/renderer/Renderer.java b/src/main/java/ru/mycubecraft/renderer/Renderer.java index 9329de1..521112a 100644 --- a/src/main/java/ru/mycubecraft/renderer/Renderer.java +++ b/src/main/java/ru/mycubecraft/renderer/Renderer.java @@ -17,6 +17,7 @@ import ru.mycubecraft.world.BlockField; import ru.mycubecraft.world.Chunk; import ru.mycubecraft.world.World; +import ru.mycubecraft.world.player.Player; import java.util.ArrayList; import java.util.Collections; @@ -56,7 +57,7 @@ public void clear() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - public void render(World world, Camera camera, Scene scene, IHud hud, Vector3f ambientLight) { + public void render(World world, Player player, Scene scene, IHud hud, Vector3f ambientLight) { clear(); filteredItems.clear(); @@ -68,7 +69,7 @@ public void render(World world, Camera camera, Scene scene, IHud hud, Vector3f a // Update projection and view atrices once per render cycle transformation.updateProjectionMatrix(window.getWidth(), window.getHeight()); - transformation.updateViewMatrix(camera); + transformation.updateViewMatrix(player); renderScene(world, scene, ambientLight); renderHud(window, hud); @@ -120,11 +121,10 @@ private void renderScene(World world, Scene scene, Vector3f ambientLight) { // Set world matrix for this item Matrix4f modelViewMatrix = transformation.buildModelViewMatrix(gameItem, viewMatrix); sceneShaderProgram.uploadMat4f("modelViewMatrix", modelViewMatrix); - + sceneShaderProgram.uploadFloat("selected", gameItem.isSelected() ? 1.0f : 0.0f); // Render the mesh for this game item gameItem.render(); } - sceneShaderProgram.uploadFloat("selected", 1.0f); // Unbind shader sceneShaderProgram.detach(); diff --git a/src/main/java/ru/mycubecraft/renderer/Transformation.java b/src/main/java/ru/mycubecraft/renderer/Transformation.java index 4e759e0..1e26e91 100644 --- a/src/main/java/ru/mycubecraft/renderer/Transformation.java +++ b/src/main/java/ru/mycubecraft/renderer/Transformation.java @@ -5,6 +5,7 @@ import org.joml.Vector4f; import ru.mycubecraft.Settings; import ru.mycubecraft.core.GameItem; +import ru.mycubecraft.world.player.Player; public class Transformation { @@ -47,9 +48,9 @@ public Matrix4f getProjectionMatrix() { return projectionMatrix; } - public Matrix4f updateViewMatrix(Camera camera) { - Vector4f cameraPos = camera.getPosition(); - Vector3f rotation = camera.getRotation(); + public Matrix4f updateViewMatrix(Player player) { + Vector4f cameraPos = player.getPosition(); + Vector3f rotation = player.getRotation(); viewMatrix.identity(); // First do the rotation so camera rotates over its position diff --git a/src/main/java/ru/mycubecraft/scene/LevelScene.java b/src/main/java/ru/mycubecraft/scene/LevelScene.java index 1703ec3..18ee300 100644 --- a/src/main/java/ru/mycubecraft/scene/LevelScene.java +++ b/src/main/java/ru/mycubecraft/scene/LevelScene.java @@ -5,17 +5,16 @@ import org.lwjgl.opengl.GL; import ru.mycubecraft.DelayedRunnable; import ru.mycubecraft.Settings; +import ru.mycubecraft.block.Block; import ru.mycubecraft.core.GameItem; import ru.mycubecraft.data.Contact; import ru.mycubecraft.data.Hud; import ru.mycubecraft.engine.Timer; import ru.mycubecraft.engine.graph.weather.Fog; -import ru.mycubecraft.renderer.Camera; import ru.mycubecraft.renderer.Renderer; import ru.mycubecraft.util.AssetPool; import ru.mycubecraft.window.Window; import ru.mycubecraft.world.Chunk; -import ru.mycubecraft.world.MouseBoxSelectionDetector; import ru.mycubecraft.world.World; import ru.mycubecraft.world.player.Player; import ru.mycubecraft.world.player.impl.DefaultPlayer; @@ -38,20 +37,16 @@ public class LevelScene extends Scene { * Used for timing calculations. */ private final Timer timer; - private final Player player; private Hud hud; private Vector3f ambientLight; private float lightAngle; private float spotAngle = 0; private float spotInc = 1; - private boolean leftButtonPressed = false; private boolean colourClearPButtonPressed; - private Vector3f selectedItemPosition; public LevelScene() { timer = new Timer(); System.err.println("Entered to a Level Scene"); - camera = new Camera(); world = new World(); lightAngle = -90; player = new DefaultPlayer(); @@ -75,7 +70,7 @@ public void runUpdateAndRenderLoop() { world.generateStartChunks(); /* Initialize timer */ timer.init(); - mouseBoxSelectionDetector = new MouseBoxSelectionDetector(); + // sun.getGameCubeItem().setScale(3f); // sun.getGameCubeItem().setPosition(-3000, 0.0f, 0F); ambientLight = new Vector3f(0.8f, 0.8f, 0.8f); @@ -136,8 +131,9 @@ public void runUpdateAndRenderLoop() { @Override public void update(float delta) { - int xPosition = (int) camera.getPosition().x; - int zPosition = (int) camera.getPosition().z; + int xPosition = (int) player.getPosition().x; + int zPosition = (int) player.getPosition().z; + world.ensureChunkIfVisible(xPosition, zPosition); updateAndRenderRunnables.add(new DelayedRunnable(() -> { @@ -160,12 +156,12 @@ public void update(float delta) { float fixedDelta = delta * Settings.MOVE_SPEED; if (!player.isFly()) { playerVelocity.add(playerAcceleration); - handleCollisions(fixedDelta, playerVelocity, camera); + handleCollisions(fixedDelta, playerVelocity, player); } - camera.moveRotation(angx, angy, 0); + player.moveRotation(angx, angy, 0); - camera.movePosition(playerVelocity.x * fixedDelta, playerVelocity.y * fixedDelta, playerVelocity.z * fixedDelta); + player.movePosition(playerVelocity.x * fixedDelta, playerVelocity.y * fixedDelta, playerVelocity.z * fixedDelta); } @@ -185,15 +181,15 @@ private void lightUpdate() { } private void hudUpdate(int fps, int ups, float delta) { - hud.rotateCompass(-camera.getRotation().y); + hud.rotateCompass(-player.getRotation().y); int filteredBlocksCount = renderer.getFilteredItems().size(); - hud.updateHud(camera, world, filteredBlocksCount); + hud.updateHud(player, world, filteredBlocksCount); hud.updateFps(fps); hud.updateUps(ups); hud.updateDelta(delta); - if (selectedItemPosition != null) { - hud.updateTargetObjectInfo(selectedItemPosition); - } +// if (selectedItemPosition != null) { +// hud.updateTargetObjectInfo(selectedItemPosition); +// } } @Override @@ -229,19 +225,7 @@ public void input() { } if (keyboardListener.isKeyPressed(GLFW_KEY_R)) { - camera.setPosition(47.0f, 130f, -179f); - } - - if (keyboardListener.isKeyPressed(GLFW_KEY_T)) { - camera.setPosition(-188f, 100f, -236f); - } - - if (keyboardListener.isKeyPressed(GLFW_KEY_Y)) { - camera.setPosition(-139.130f, 118.113f, -144.038f); - } - - if (keyboardListener.isKeyPressed(GLFW_KEY_U)) { - camera.setPosition(-210.962f, 113.468f, -215.272f); + player.setPosition(47.0f, 90f, -179f); } if (keyboardListener.isKeyPressed(GLFW_KEY_P)) { @@ -252,36 +236,38 @@ public void input() { this.fogLButtonPressed = !this.fogLButtonPressed; } - boolean aux = false; - if (aux && !this.leftButtonPressed) { - if (selectedItemPosition != null) { - createGameBlockItem(selectedItemPosition); - } + if (mouseListener.isLeftButtonPressed()) { + int xPosition = (int) player.getPosition().x; + int zPosition = (int) player.getPosition().z; + + Chunk chunk = world.getChunk(xPosition, zPosition); + + // Determine the selected block in the center of the viewport. + Block selectBlock = player.findAndSelectBlock(chunk.getBlockField()); } - this.leftButtonPressed = aux; } @Override public void render() { - renderer.render(world, camera, this, hud, ambientLight); + renderer.render(world, player, this, hud, ambientLight); } private void createGameBlockItem(Vector3f position) { Vector3f newBlockPosition = new Vector3f(position); - Vector3f ray = mouseBoxSelectionDetector.rayDirection().negate(); - float xStart = (float) Math.ceil(ray.x); - float yStart = (float) Math.ceil(ray.y); - float zStart = (float) Math.ceil(ray.z); - newBlockPosition.add(xStart, yStart, zStart); +// Vector3f ray = mouseBoxSelectionDetector.rayDirection().negate(); +// float xStart = (float) Math.ceil(ray.x); +// float yStart = (float) Math.ceil(ray.y); +// float zStart = (float) Math.ceil(ray.z); + //newBlockPosition.add(xStart, yStart, zStart); boolean containsChunk = world.containsChunk(newBlockPosition); Chunk chunk; if (!containsChunk) { - chunk = world.addChunk(newBlockPosition); + //chunk = world.addChunk(newBlockPosition); //chunk.addBlock(newBlockPosition); } else { - chunk = world.getChunk(newBlockPosition); + //chunk = world.getChunk(newBlockPosition); // //boolean chunkContainsBlock = chunk.containsBlock(newBlockPosition); // if (chunkContainsBlock) { // xStart = (float) Math.ceil(ray.x); @@ -297,10 +283,10 @@ private void createGameBlockItem(Vector3f position) { /** * Handle any collisions with the player and the blocks. */ - private void handleCollisions(float dt, Vector3f velocity, Camera camera) { + private void handleCollisions(float dt, Vector3f velocity, Player player) { List contacts = new ArrayList<>(); - world.collisionDetection(dt, velocity, camera, contacts); - world.collisionResponse(dt, velocity, camera, contacts); + world.collisionDetection(dt, velocity, player, contacts); + world.collisionResponse(dt, velocity, player, contacts); } @Override diff --git a/src/main/java/ru/mycubecraft/scene/Scene.java b/src/main/java/ru/mycubecraft/scene/Scene.java index 45e5499..7f938cf 100644 --- a/src/main/java/ru/mycubecraft/scene/Scene.java +++ b/src/main/java/ru/mycubecraft/scene/Scene.java @@ -8,10 +8,9 @@ import ru.mycubecraft.engine.graph.weather.Fog; import ru.mycubecraft.listener.KeyboardListener; import ru.mycubecraft.listener.MouseListener; -import ru.mycubecraft.renderer.Camera; import ru.mycubecraft.renderer.Renderer; -import ru.mycubecraft.world.MouseBoxSelectionDetector; import ru.mycubecraft.world.World; +import ru.mycubecraft.world.player.Player; import java.util.ArrayList; import java.util.Iterator; @@ -33,11 +32,10 @@ public abstract class Scene { // protected Window window = Window.getInstance(); protected SkyBox skyBox; protected Renderer renderer; - protected Camera camera; + protected Player player; protected ArrayList gameItems = new ArrayList<>(); protected Fog fog; protected boolean fogLButtonPressed = Settings.SHOW_FOG; - protected MouseBoxSelectionDetector mouseBoxSelectionDetector; protected KeyboardListener keyboardListener = KeyboardListener.getInstance(); protected MouseListener mouseListener = MouseListener.getInstance(); diff --git a/src/main/java/ru/mycubecraft/util/MathUtil.java b/src/main/java/ru/mycubecraft/util/MathUtil.java index 63e7d46..d6747f7 100644 --- a/src/main/java/ru/mycubecraft/util/MathUtil.java +++ b/src/main/java/ru/mycubecraft/util/MathUtil.java @@ -1,5 +1,10 @@ package ru.mycubecraft.util; +import org.joml.Vector3i; + +import static java.lang.Math.max; +import static java.lang.Math.min; + public class MathUtil { public static final float f_PI = (float) Math.PI; @@ -22,10 +27,35 @@ public static float simplifyRadians(float rad) { return rad; } + /** + * GLSL's clamp function. + */ public static > T clamp(T val, T min, T max) { if (val.compareTo(min) < 0) return min; else if (val.compareTo(max) > 0) return max; else return val; } + /** + * GLSL's step function. + */ + public static int step(float edge, float x) { + return x < edge ? 0 : 1; + } + + + /** + * Determine the side (as a normal vector) at which the ray + * (ox, oy, oz) + t * (dx, dy, dz) enters the unit box with min coordinates + * (x, y, z), and store the normal of that face into off. + */ + public static void enterSide(float ox, float oy, float oz, float dx, float dy, float dz, int x, int y, int z, Vector3i off) { + float tMinx = (x - ox) / dx, tMiny = (y - oy) / dy, tMinz = (z - oz) / dz; + float tMaxx = (x + 1 - ox) / dx, tMaxy = (y + 1 - oy) / dy, tMaxz = (z + 1 - oz) / dz; + float t1x = min(tMinx, tMaxx), t1y = min(tMiny, tMaxy), t1z = min(tMinz, tMaxz); + float tNear = max(max(t1x, t1y), t1z); + off.set(tNear == t1x ? dx > 0 ? -1 : 1 : 0, tNear == t1y ? dy > 0 ? -1 : 1 : 0, tNear == t1z ? dz > 0 ? -1 : 1 : 0); + } + + } diff --git a/src/main/java/ru/mycubecraft/world/Chunk.java b/src/main/java/ru/mycubecraft/world/Chunk.java index c1c33fa..93eeac3 100644 --- a/src/main/java/ru/mycubecraft/world/Chunk.java +++ b/src/main/java/ru/mycubecraft/world/Chunk.java @@ -22,17 +22,15 @@ @EqualsAndHashCode public class Chunk { + /** + * The width, height and depth of a chunk (in number of blocks). + */ + public static final int CHUNK_HEIGHT = 256; private static final int BLOCKS_COUNT = 8; - /** * The chunk offset for the noise function. */ private static final int GLOBAL_X = 2500, GLOBAL_Z = 851; - - /** - * The width, height and depth of a chunk (in number of blocks). - */ - private static final int CHUNK_HEIGHT = 256; private static final int CHUNK_SIZE_SHIFT = 5; private static final int CHUNK_SIZE = 1 << CHUNK_SIZE_SHIFT; diff --git a/src/main/java/ru/mycubecraft/world/MouseBoxSelectionDetector.java b/src/main/java/ru/mycubecraft/world/MouseBoxSelectionDetector.java index 6fbcf39..04bc4cd 100644 --- a/src/main/java/ru/mycubecraft/world/MouseBoxSelectionDetector.java +++ b/src/main/java/ru/mycubecraft/world/MouseBoxSelectionDetector.java @@ -4,8 +4,8 @@ import org.joml.Vector3f; import org.joml.Vector4f; import ru.mycubecraft.core.GameItem; -import ru.mycubecraft.renderer.Camera; import ru.mycubecraft.window.Window; +import ru.mycubecraft.world.player.Player; import java.util.List; @@ -13,27 +13,22 @@ public class MouseBoxSelectionDetector extends CameraBoxSelectionDetector { private final Matrix4f invProjectionMatrix; private final Matrix4f invViewMatrix; - - private Matrix4f projectionMatrix; - private Matrix4f viewMatrix; + private final Matrix4f viewMatrix; + private final Matrix4f projectionMatrix; public MouseBoxSelectionDetector() { super(); invProjectionMatrix = new Matrix4f(); invViewMatrix = new Matrix4f(); - viewMatrix = new Matrix4f(); - } - - public void update(Camera camera) { - viewMatrix = camera.updateViewMatrix(); + viewMatrix = transformation.getViewMatrix(); projectionMatrix = transformation.updateProjectionMatrix(window.getWidth(), window.getHeight()); } - public Vector3f getGameItemPosition(List gameItemList, Camera camera) { + public Vector3f getGameItemPosition(List gameItemList, Player player) { - float xStart = camera.getPosition().x; - float yStart = camera.getPosition().y; - float zStart = camera.getPosition().z; + float xStart = player.getPosition().x; + float yStart = player.getPosition().y; + float zStart = player.getPosition().z; // float xStart = (float) Math.floor(camera.getPosition().x); // float yStart = (float) Math.floor(camera.getPosition().y); @@ -51,11 +46,11 @@ public Vector3f getGameItemPosition(List gameItemList, Camera camera) return newGameItemPosition; } - public Vector3f getGameItemPosition(Camera camera) { + public Vector3f getGameItemPosition(Player player) { - float xStart = (float) Math.ceil(camera.getPosition().x); - float yStart = (float) Math.floor(camera.getPosition().y); - float zStart = (float) Math.ceil(camera.getPosition().z); + float xStart = (float) Math.ceil(player.getPosition().x); + float yStart = (float) Math.floor(player.getPosition().y); + float zStart = (float) Math.ceil(player.getPosition().z); Vector3f origin = new Vector3f(xStart, yStart, zStart); diff --git a/src/main/java/ru/mycubecraft/world/World.java b/src/main/java/ru/mycubecraft/world/World.java index 7b14d45..007e2e7 100644 --- a/src/main/java/ru/mycubecraft/world/World.java +++ b/src/main/java/ru/mycubecraft/world/World.java @@ -6,7 +6,6 @@ import ru.mycubecraft.block.Block; import ru.mycubecraft.block.EmptyBlock; import ru.mycubecraft.data.Contact; -import ru.mycubecraft.renderer.Camera; import ru.mycubecraft.world.player.Player; import java.util.Iterator; @@ -98,9 +97,9 @@ private Chunk generateChunk(int cx, int cz) { /** * Detect possible collision candidates. */ - public void collisionDetection(float dt, Vector3f velocity, Camera camera, List contacts) { + public void collisionDetection(float dt, Vector3f velocity, Player player, List contacts) { - Vector3f position = new Vector3f(camera.position.x, camera.position.y, camera.position.z); + Vector3f position = new Vector3f(player.getPosition().x, player.getPosition().y, player.getPosition().z); int xPosition = (int) position.x; int zPosition = (int) position.z; @@ -206,7 +205,7 @@ private void intersectSweptAabbAabb(int x, int y, int z, float px, float py, /** * Respond to all found collision contacts. */ - public void collisionResponse(float dt, Vector3f velocity, Camera camera, List contacts) { + public void collisionResponse(float dt, Vector3f velocity, Player player, List contacts) { sort(contacts); int minX = Integer.MIN_VALUE, maxX = Integer.MAX_VALUE, minY = Integer.MIN_VALUE, maxY = Integer.MAX_VALUE, minZ = Integer.MIN_VALUE, maxZ = Integer.MAX_VALUE; @@ -220,7 +219,7 @@ public void collisionResponse(float dt, Vector3f velocity, Camera camera, List> CHUNK_SIZE_SHIFT, + cz = zPosition >> CHUNK_SIZE_SHIFT; + String chunkKey = idx(cx, cz); return chunkMap.get(chunkKey); } - - public Chunk addChunk(Vector3f position) { - int xOffset = (int) position.x; - int yOffset = (int) position.y; - int zOffset = (int) position.z; - return addChunk(xOffset, yOffset, zOffset); - } - - public Chunk addChunk(int xPosition, int yPosition, int zPosition) { - int xOffset = xPosition / WORLD_WIDTH; - int yOffset = yPosition / WORLD_WIDTH; - int zOffset = zPosition / WORLD_WIDTH; - - String chunkKey = String.format("%s:%s:%s", xOffset, yOffset, zOffset); - Chunk chunk = new Chunk(xOffset, yOffset, zOffset); - chunkMap.put(chunkKey, chunk); - return chunk; - } +// +// public Chunk addChunk(Vector3f position) { +// int xOffset = (int) position.x; +// int yOffset = (int) position.y; +// int zOffset = (int) position.z; +// return addChunk(xOffset, yOffset, zOffset); +// } +// +// public Chunk addChunk(int xPosition, int yPosition, int zPosition) { +// int xOffset = xPosition / WORLD_WIDTH; +// int yOffset = yPosition / WORLD_WIDTH; +// int zOffset = zPosition / WORLD_WIDTH; +// +// String chunkKey = String.format("%s:%s:%s", xOffset, yOffset, zOffset); +// Chunk chunk = new Chunk(xOffset, yOffset, zOffset); +// chunkMap.put(chunkKey, chunk); +// return chunk; +// } /** * Ensure that a frontier neighbor chunk is created if it is visible. diff --git a/src/main/java/ru/mycubecraft/world/player/Player.java b/src/main/java/ru/mycubecraft/world/player/Player.java index 9dfcc78..18ab644 100644 --- a/src/main/java/ru/mycubecraft/world/player/Player.java +++ b/src/main/java/ru/mycubecraft/world/player/Player.java @@ -2,6 +2,12 @@ import lombok.Getter; import lombok.Setter; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.joml.Vector4f; +import ru.mycubecraft.block.Block; +import ru.mycubecraft.world.BlockField; +import ru.mycubecraft.world.MouseBoxSelectionDetector; @Setter @Getter @@ -19,8 +25,28 @@ public abstract class Player { * The width of the player's collision box. */ public static final float PLAYER_WIDTH = 1.00f; - protected boolean fly = false; protected boolean jumping; + protected Matrix4f viewMatrix; + protected Vector4f position; + protected Vector3f rotation; + protected MouseBoxSelectionDetector mouseBoxSelectionDetector; + + public void setPosition(float x, float y, float z) { + this.position.x = x; + this.position.y = y; + this.position.z = z; + } + + public void setRotation(float x, float y, float z) { + this.rotation.x = x; + this.rotation.y = y; + this.rotation.z = z; + } + + public abstract void moveRotation(double offsetX, double offsetY, double offsetZ); + + public abstract void movePosition(float offsetX, float offsetY, float offsetZ); + public abstract Block findAndSelectBlock(BlockField blockField); } diff --git a/src/main/java/ru/mycubecraft/world/player/impl/DefaultPlayer.java b/src/main/java/ru/mycubecraft/world/player/impl/DefaultPlayer.java index ad49a68..f151d0f 100644 --- a/src/main/java/ru/mycubecraft/world/player/impl/DefaultPlayer.java +++ b/src/main/java/ru/mycubecraft/world/player/impl/DefaultPlayer.java @@ -2,10 +2,130 @@ import lombok.Getter; import lombok.Setter; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.joml.Vector3i; +import org.joml.Vector4f; +import ru.mycubecraft.Settings; +import ru.mycubecraft.block.Block; +import ru.mycubecraft.block.EmptyBlock; +import ru.mycubecraft.util.MathUtil; +import ru.mycubecraft.world.BlockField; +import ru.mycubecraft.world.Chunk; +import ru.mycubecraft.world.MouseBoxSelectionDetector; import ru.mycubecraft.world.player.Player; +import static java.lang.Math.*; + @Getter @Setter public class DefaultPlayer extends Player { + private final Vector3i sideOffset = new Vector3i(); + private Block selectedBlock; + + public DefaultPlayer() { + this.viewMatrix = new Matrix4f(); + this.position = new Vector4f(47.0f, 130f, -179f, 1); + this.rotation = new Vector3f(32.0f, 9.0f, 0.0f); + this.mouseBoxSelectionDetector = new MouseBoxSelectionDetector(); + } + + /** + * Determine the block pointed to by a ray (rayOrigin.x, rayOrigin.y, rayOrigin.z) + t * (rayDirection.x, rayDirection.y, rayDirection.z) and store + * the block and side offset of that block (if any) into {@link #selectedBlock} and + * {@link #sideOffset}, respectively. + * + * @param blockField the chunks block field + */ + public Block findAndSelectBlock(BlockField blockField) { + if (blockField == null) { + return null; + } + float xStart = (float) Math.ceil(this.position.x); + float yStart = (float) Math.floor(this.position.y); + float zStart = (float) Math.ceil(this.position.z); + + Vector3f rayOrigin = new Vector3f(xStart, yStart, zStart); + Vector3f rayDirection = mouseBoxSelectionDetector.rayDirection(); + + /* "A Fast Voxel Traversal Algorithm for Ray Tracing" by John Amanatides, Andrew Woo */ + float big = 1E30f; + + int px = (int) floor(rayOrigin.x), + py = (int) floor(rayOrigin.y), + pz = (int) floor(rayOrigin.z); + + float dxi = 1f / rayDirection.x, + dyi = 1f / rayDirection.y, + dzi = 1f / rayDirection.z; + + float sx = rayDirection.x > 0 ? 1 : -1, + sy = rayDirection.y > 0 ? 1 : -1, + sz = rayDirection.z > 0 ? 1 : -1; + + float dtx = min(dxi * sx, big), + dty = min(dyi * sy, big), + dtz = min(dzi * sz, big); + + float tx = abs((px + max(sx, 0) - rayOrigin.x) * dxi), + ty = abs((py + max(sy, 0) - rayOrigin.y) * dyi), + tz = abs((pz + max(sz, 0) - rayOrigin.z) * dzi); + + int maxSteps = 16; + for (int i = 0; i < maxSteps && py >= 0; i++) { + if (i > 0 && py < Chunk.CHUNK_HEIGHT) { + Block block = blockField.load(px, py, pz); + if (block != null && !(block instanceof EmptyBlock)) { + MathUtil.enterSide(rayOrigin.x, rayOrigin.y, rayOrigin.z, rayDirection.x, + rayDirection.y, rayDirection.z, px, py, pz, sideOffset); + if (this.selectedBlock != null) { + this.selectedBlock.setSelected(false); + } + block.setSelected(true); + this.selectedBlock = block; + return block; + } + } + /* Advance to next block */ + int cmpx = MathUtil.step(tx, tz) * MathUtil.step(tx, ty); + int cmpy = MathUtil.step(ty, tx) * MathUtil.step(ty, tz); + int cmpz = MathUtil.step(tz, ty) * MathUtil.step(tz, tx); + tx += dtx * cmpx; + ty += dty * cmpy; + tz += dtz * cmpz; + px += sx * cmpx; + py += sy * cmpy; + pz += sz * cmpz; + } + return null; + } + + + @Override + public void moveRotation(double offsetX, double offsetY, double offsetZ) { + double xRotation = rotation.x; + double yRotation = rotation.y; + yRotation += offsetY; + if (yRotation > 360.0f || yRotation < -360.0f) { + yRotation = 0.0f; + } + xRotation += offsetX; + rotation.y = (float) yRotation; + rotation.z += offsetZ; + rotation.x = MathUtil.clamp((float) xRotation, (float) Settings.MIN_LOOK, (float) Settings.MAX_LOOK); + } + + @Override + public void movePosition(float offsetX, float offsetY, float offsetZ) { + if (offsetZ != 0) { + position.x += (float) Math.sin(Math.toRadians(rotation.y)) * -1.0f * offsetZ; + position.z += (float) Math.cos(Math.toRadians(rotation.y)) * offsetZ; + } + if (offsetX != 0) { + position.x += (float) Math.sin(Math.toRadians(rotation.y - 90)) * -1.0f * offsetX; + position.z += (float) Math.cos(Math.toRadians(rotation.y - 90)) * offsetX; + } + position.y += offsetY; + } } From 4fbf5138d599f8d6fb0de3883225b72eb426c622 Mon Sep 17 00:00:00 2001 From: Azat Akhunov Date: Fri, 22 Oct 2021 14:37:45 +0300 Subject: [PATCH 2/3] concurrent modification exception fixed --- src/main/java/ru/mycubecraft/world/Chunk.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/ru/mycubecraft/world/Chunk.java b/src/main/java/ru/mycubecraft/world/Chunk.java index 93eeac3..47f8442 100644 --- a/src/main/java/ru/mycubecraft/world/Chunk.java +++ b/src/main/java/ru/mycubecraft/world/Chunk.java @@ -11,6 +11,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Set; import static java.lang.Math.max; import static java.lang.Math.min; @@ -126,8 +127,9 @@ public void createBlockField() { } public void sortBlocksVisibility() { - Map blocks = this.blockField.getBlocks(); - for (Block block : blocks.values()) { + Set> blocks = this.blockField.getBlocks().entrySet(); + for (Map.Entry blocksEntry : blocks) { + Block block = blocksEntry.getValue(); Cube cube = calculateChunksBlocksFace(block); block.createCube(cube); } From b8f3fdab6ff992c3c57102bc771eac7be533027d Mon Sep 17 00:00:00 2001 From: Azat Akhunov Date: Fri, 22 Oct 2021 19:13:55 +0300 Subject: [PATCH 3/3] block apply and block remover added --- assets/shaders/scene.glsl | 2 +- src/main/java/ru/mycubecraft/block/Block.java | 2 + .../java/ru/mycubecraft/block/DirtBlock.java | 9 +---- .../java/ru/mycubecraft/block/EmptyBlock.java | 2 - .../java/ru/mycubecraft/block/GrassBlock.java | 10 +---- .../ru/mycubecraft/renderer/Renderer.java | 6 +-- .../mycubecraft/renderer/cube/BackCube.java | 1 - .../ru/mycubecraft/renderer/cube/Cube.java | 1 - .../mycubecraft/renderer/cube/FrontCube.java | 1 - .../java/ru/mycubecraft/scene/LevelScene.java | 25 +++++++++--- .../java/ru/mycubecraft/world/BlockField.java | 2 +- src/main/java/ru/mycubecraft/world/Chunk.java | 27 +++++++------ src/main/java/ru/mycubecraft/world/World.java | 3 +- .../ru/mycubecraft/world/player/Player.java | 5 +++ .../world/player/impl/DefaultPlayer.java | 38 +++++++++++++++---- 15 files changed, 81 insertions(+), 53 deletions(-) diff --git a/assets/shaders/scene.glsl b/assets/shaders/scene.glsl index 5752e3b..57a2acf 100644 --- a/assets/shaders/scene.glsl +++ b/assets/shaders/scene.glsl @@ -96,7 +96,7 @@ vec4 speculrC; void setupColours(Material material, vec2 textCoord) { - if (material.hasTexture == 1) + if (material.hasTexture >= 1) { ambientC = texture(texture_sampler, textCoord); diffuseC = ambientC; diff --git a/src/main/java/ru/mycubecraft/block/Block.java b/src/main/java/ru/mycubecraft/block/Block.java index 429038f..8019c6a 100644 --- a/src/main/java/ru/mycubecraft/block/Block.java +++ b/src/main/java/ru/mycubecraft/block/Block.java @@ -1,5 +1,6 @@ package ru.mycubecraft.block; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import org.joml.Vector3f; @@ -8,6 +9,7 @@ @Getter @Setter +@EqualsAndHashCode public abstract class Block { final Vector3f position; diff --git a/src/main/java/ru/mycubecraft/block/DirtBlock.java b/src/main/java/ru/mycubecraft/block/DirtBlock.java index 0a5d902..bf2069b 100644 --- a/src/main/java/ru/mycubecraft/block/DirtBlock.java +++ b/src/main/java/ru/mycubecraft/block/DirtBlock.java @@ -1,12 +1,10 @@ package ru.mycubecraft.block; -import lombok.EqualsAndHashCode; import lombok.Getter; import ru.mycubecraft.core.GameItem; import ru.mycubecraft.renderer.cube.Cube; @Getter -@EqualsAndHashCode(callSuper = false) public class DirtBlock extends Block { private final static String MODEL_TEXTURE_PATH = "assets/textures/dirt.png"; @@ -37,12 +35,7 @@ public void render() { @Override public GameItem getGameCubeItem() { - if (this.gameCubeItem != null) { - GameItem item = this.gameCubeItem; - item.setSelected(this.selected); - return item; - } - return null; + return this.gameCubeItem; } } diff --git a/src/main/java/ru/mycubecraft/block/EmptyBlock.java b/src/main/java/ru/mycubecraft/block/EmptyBlock.java index 0df51d4..7859f78 100644 --- a/src/main/java/ru/mycubecraft/block/EmptyBlock.java +++ b/src/main/java/ru/mycubecraft/block/EmptyBlock.java @@ -1,12 +1,10 @@ package ru.mycubecraft.block; -import lombok.EqualsAndHashCode; import lombok.Getter; import ru.mycubecraft.core.GameItem; import ru.mycubecraft.renderer.cube.Cube; @Getter -@EqualsAndHashCode(callSuper = false) public class EmptyBlock extends Block { private final static String MODEL_TEXTURE_PATH = "assets/textures/white.png"; diff --git a/src/main/java/ru/mycubecraft/block/GrassBlock.java b/src/main/java/ru/mycubecraft/block/GrassBlock.java index 33aee15..3b8929d 100644 --- a/src/main/java/ru/mycubecraft/block/GrassBlock.java +++ b/src/main/java/ru/mycubecraft/block/GrassBlock.java @@ -1,12 +1,10 @@ package ru.mycubecraft.block; -import lombok.EqualsAndHashCode; import lombok.Getter; import ru.mycubecraft.core.GameItem; import ru.mycubecraft.renderer.cube.Cube; @Getter -@EqualsAndHashCode(callSuper = false) public class GrassBlock extends Block { private final static String MODEL_TEXTURE_PATH = "assets/textures/grass.png"; @@ -22,6 +20,7 @@ public void createCube(Cube cube) { try { cube.setPosition(position.x, position.y, position.z); cube.setTexture(MODEL_TEXTURE_PATH); + cube.createCube(); this.gameCubeItem = cube; } catch (Exception e) { e.printStackTrace(); @@ -35,12 +34,7 @@ public void render() { @Override public GameItem getGameCubeItem() { - if (this.gameCubeItem != null) { - GameItem item = this.gameCubeItem; - item.setSelected(this.selected); - return item; - } - return null; + return this.gameCubeItem; } diff --git a/src/main/java/ru/mycubecraft/renderer/Renderer.java b/src/main/java/ru/mycubecraft/renderer/Renderer.java index 521112a..5fc16a3 100644 --- a/src/main/java/ru/mycubecraft/renderer/Renderer.java +++ b/src/main/java/ru/mycubecraft/renderer/Renderer.java @@ -19,10 +19,7 @@ import ru.mycubecraft.world.World; import ru.mycubecraft.world.player.Player; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.lwjgl.opengl.GL11.*; @@ -95,6 +92,7 @@ private void renderScene(World world, Scene scene, Vector3f ambientLight) { Map blocks = blockField.getBlocks(); blocks.values() .parallelStream() + .filter(Objects::nonNull) .filter(block -> block.getGameCubeItem() != null && block.isVisible() diff --git a/src/main/java/ru/mycubecraft/renderer/cube/BackCube.java b/src/main/java/ru/mycubecraft/renderer/cube/BackCube.java index 211c9a6..446c8ac 100644 --- a/src/main/java/ru/mycubecraft/renderer/cube/BackCube.java +++ b/src/main/java/ru/mycubecraft/renderer/cube/BackCube.java @@ -78,7 +78,6 @@ public Mesh getMesh() { @Override public void render() { mesh.render(); - } @Override diff --git a/src/main/java/ru/mycubecraft/renderer/cube/Cube.java b/src/main/java/ru/mycubecraft/renderer/cube/Cube.java index 30888ba..e597ee5 100644 --- a/src/main/java/ru/mycubecraft/renderer/cube/Cube.java +++ b/src/main/java/ru/mycubecraft/renderer/cube/Cube.java @@ -78,7 +78,6 @@ public Mesh getMesh() { @Override public void render() { mesh.render(); - } @Override diff --git a/src/main/java/ru/mycubecraft/renderer/cube/FrontCube.java b/src/main/java/ru/mycubecraft/renderer/cube/FrontCube.java index 000bf93..37c9f31 100644 --- a/src/main/java/ru/mycubecraft/renderer/cube/FrontCube.java +++ b/src/main/java/ru/mycubecraft/renderer/cube/FrontCube.java @@ -78,7 +78,6 @@ public Mesh getMesh() { @Override public void render() { mesh.render(); - } @Override diff --git a/src/main/java/ru/mycubecraft/scene/LevelScene.java b/src/main/java/ru/mycubecraft/scene/LevelScene.java index 18ee300..81c143f 100644 --- a/src/main/java/ru/mycubecraft/scene/LevelScene.java +++ b/src/main/java/ru/mycubecraft/scene/LevelScene.java @@ -5,7 +5,6 @@ import org.lwjgl.opengl.GL; import ru.mycubecraft.DelayedRunnable; import ru.mycubecraft.Settings; -import ru.mycubecraft.block.Block; import ru.mycubecraft.core.GameItem; import ru.mycubecraft.data.Contact; import ru.mycubecraft.data.Hud; @@ -187,9 +186,9 @@ private void hudUpdate(int fps, int ups, float delta) { hud.updateFps(fps); hud.updateUps(ups); hud.updateDelta(delta); -// if (selectedItemPosition != null) { -// hud.updateTargetObjectInfo(selectedItemPosition); -// } + if (player.getSelectedBlock() != null) { + hud.updateTargetObjectInfo(player.getSelectedBlock().getPosition()); + } } @Override @@ -243,7 +242,23 @@ public void input() { Chunk chunk = world.getChunk(xPosition, zPosition); // Determine the selected block in the center of the viewport. - Block selectBlock = player.findAndSelectBlock(chunk.getBlockField()); + player.findAndSelectBlock(chunk.getBlockField()); + player.placeAtSelectedBlock(chunk.getBlockField()); + chunk.sortBlocksVisibility(); + mouseListener.setLeftButtonPressed(false); + } + + if (mouseListener.isRightButtonPressed()) { + int xPosition = (int) player.getPosition().x; + int zPosition = (int) player.getPosition().z; + + Chunk chunk = world.getChunk(xPosition, zPosition); + + // Determine the selected block in the center of the viewport. + player.findAndSelectBlock(chunk.getBlockField()); + player.removeSelectedBlock(chunk.getBlockField()); + chunk.sortBlocksVisibility(); + mouseListener.setRightButtonPressed(false); } } diff --git a/src/main/java/ru/mycubecraft/world/BlockField.java b/src/main/java/ru/mycubecraft/world/BlockField.java index b0d26e1..43d95a3 100644 --- a/src/main/java/ru/mycubecraft/world/BlockField.java +++ b/src/main/java/ru/mycubecraft/world/BlockField.java @@ -62,7 +62,7 @@ private static String idx(int x, int y, int z) { * @param block the block value * @return this */ - private BlockField store(int x, int y, int z, Block block) { + public BlockField store(int x, int y, int z, Block block) { String key = idx(x, y, z); blocks.put(key, block); /* diff --git a/src/main/java/ru/mycubecraft/world/Chunk.java b/src/main/java/ru/mycubecraft/world/Chunk.java index 47f8442..fd8ee6d 100644 --- a/src/main/java/ru/mycubecraft/world/Chunk.java +++ b/src/main/java/ru/mycubecraft/world/Chunk.java @@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j; import ru.mycubecraft.block.Block; import ru.mycubecraft.block.DirtBlock; -import ru.mycubecraft.block.EmptyBlock; +import ru.mycubecraft.block.GrassBlock; import ru.mycubecraft.renderer.cube.*; import java.util.HashMap; @@ -110,12 +110,12 @@ public void createBlockField() { field.put(key, block); num++; } - for (int y0 = CHUNK_HEIGHT - 1; y0 > y; y0--) { - String key = idx(x + wX, y0, z + wZ); - Block block = new EmptyBlock(x + wX, y0, z + wZ); - field.put(key, block); - num++; - } +// for (int y0 = CHUNK_HEIGHT - 1; y0 > y; y0--) { +// String key = idx(x + wX, y0, z + wZ); +// Block block = new EmptyBlock(x + wX, y0, z + wZ); +// field.put(key, block); +// num++; +// } } } BlockField blockField = new BlockField(); @@ -130,6 +130,9 @@ public void sortBlocksVisibility() { Set> blocks = this.blockField.getBlocks().entrySet(); for (Map.Entry blocksEntry : blocks) { Block block = blocksEntry.getValue(); + if (block == null) { + continue; + } Cube cube = calculateChunksBlocksFace(block); block.createCube(cube); } @@ -137,8 +140,9 @@ public void sortBlocksVisibility() { public Cube calculateChunksBlocksFace(Block block) { - if (block instanceof EmptyBlock) { - return new EmptyCube(); + if (block instanceof GrassBlock) { + block.setVisible(true); + return new Cube("grass"); } int xPosition = (int) block.getPosition().x; @@ -268,7 +272,7 @@ public Cube calculateChunksBlocksFace(Block block) { return new BottomFrontRightCube(); } - return new EmptyCube(); + return new Cube(); } /** @@ -287,8 +291,7 @@ public String idx(int x, int y, int z) { private Block findNotEmptyBlock(int xPosition, int yPosition, int zPosition) { Block block = this.blockField.load(xPosition, yPosition, zPosition); - boolean isEmptyBlock = block instanceof EmptyBlock; - return isEmptyBlock ? null : block; + return block; } public void cleanup() { diff --git a/src/main/java/ru/mycubecraft/world/World.java b/src/main/java/ru/mycubecraft/world/World.java index 007e2e7..9499519 100644 --- a/src/main/java/ru/mycubecraft/world/World.java +++ b/src/main/java/ru/mycubecraft/world/World.java @@ -4,7 +4,6 @@ import lombok.extern.slf4j.Slf4j; import org.joml.Vector3f; import ru.mycubecraft.block.Block; -import ru.mycubecraft.block.EmptyBlock; import ru.mycubecraft.data.Contact; import ru.mycubecraft.world.player.Player; @@ -131,7 +130,7 @@ public void collisionDetection(float dt, Vector3f velocity, Player player, List< for (int z = minZ; z <= maxZ; z++) { for (int x = minX; x <= maxX; x++) { Block block = blockField.load(x, y, z); - if (block == null || block instanceof EmptyBlock) { + if (block == null) { continue; } diff --git a/src/main/java/ru/mycubecraft/world/player/Player.java b/src/main/java/ru/mycubecraft/world/player/Player.java index 18ab644..9e52c96 100644 --- a/src/main/java/ru/mycubecraft/world/player/Player.java +++ b/src/main/java/ru/mycubecraft/world/player/Player.java @@ -31,6 +31,7 @@ public abstract class Player { protected Vector4f position; protected Vector3f rotation; protected MouseBoxSelectionDetector mouseBoxSelectionDetector; + protected Block selectedBlock; public void setPosition(float x, float y, float z) { this.position.x = x; @@ -49,4 +50,8 @@ public void setRotation(float x, float y, float z) { public abstract void movePosition(float offsetX, float offsetY, float offsetZ); public abstract Block findAndSelectBlock(BlockField blockField); + + public abstract void removeSelectedBlock(BlockField blockField); + + public abstract void placeAtSelectedBlock(BlockField blockField); } diff --git a/src/main/java/ru/mycubecraft/world/player/impl/DefaultPlayer.java b/src/main/java/ru/mycubecraft/world/player/impl/DefaultPlayer.java index f151d0f..d1ace53 100644 --- a/src/main/java/ru/mycubecraft/world/player/impl/DefaultPlayer.java +++ b/src/main/java/ru/mycubecraft/world/player/impl/DefaultPlayer.java @@ -8,7 +8,7 @@ import org.joml.Vector4f; import ru.mycubecraft.Settings; import ru.mycubecraft.block.Block; -import ru.mycubecraft.block.EmptyBlock; +import ru.mycubecraft.block.GrassBlock; import ru.mycubecraft.util.MathUtil; import ru.mycubecraft.world.BlockField; import ru.mycubecraft.world.Chunk; @@ -22,7 +22,6 @@ public class DefaultPlayer extends Player { private final Vector3i sideOffset = new Vector3i(); - private Block selectedBlock; public DefaultPlayer() { this.viewMatrix = new Matrix4f(); @@ -76,13 +75,9 @@ public Block findAndSelectBlock(BlockField blockField) { for (int i = 0; i < maxSteps && py >= 0; i++) { if (i > 0 && py < Chunk.CHUNK_HEIGHT) { Block block = blockField.load(px, py, pz); - if (block != null && !(block instanceof EmptyBlock)) { + if (block != null) { MathUtil.enterSide(rayOrigin.x, rayOrigin.y, rayOrigin.z, rayDirection.x, rayDirection.y, rayDirection.z, px, py, pz, sideOffset); - if (this.selectedBlock != null) { - this.selectedBlock.setSelected(false); - } - block.setSelected(true); this.selectedBlock = block; return block; } @@ -128,4 +123,33 @@ public void movePosition(float offsetX, float offsetY, float offsetZ) { } position.y += offsetY; } + + @Override + public void removeSelectedBlock(BlockField blockField) { + if (this.selectedBlock == null) { + return; + } + int xPosition = (int) this.selectedBlock.getPosition().x; + int yPosition = (int) this.selectedBlock.getPosition().y; + int zPosition = (int) this.selectedBlock.getPosition().z; + + blockField.store(xPosition, yPosition, zPosition, null); + this.selectedBlock = null; + } + + @Override + public void placeAtSelectedBlock(BlockField blockField) { + if (this.selectedBlock == null || this.selectedBlock.getPosition().y + this.sideOffset.y < 0 || + this.selectedBlock.getPosition().y + this.sideOffset.y >= Chunk.CHUNK_HEIGHT) { + return; + } + + int xPosition = (int) (this.selectedBlock.getPosition().x + this.sideOffset.x); + int yPosition = (int) (this.selectedBlock.getPosition().y + this.sideOffset.y); + int zPosition = (int) (this.selectedBlock.getPosition().z + this.sideOffset.z); + + Block block = new GrassBlock(xPosition, yPosition, zPosition); + blockField.store(xPosition, yPosition, zPosition, block); + this.selectedBlock = null; + } }