From be82d76bba78a3c05a3fc45a8b23fcdb5087972f Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 6 Oct 2023 16:04:26 +0200 Subject: [PATCH] Fix offset when camera moving (offset with camera rotating remains) --- client/src/main/java/core/engine/Engine.java | 3 +- .../java/core/engine/toolbox/MousePicker.java | 81 ++++++++++++++----- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/client/src/main/java/core/engine/Engine.java b/client/src/main/java/core/engine/Engine.java index e3838ea..d7b6bee 100644 --- a/client/src/main/java/core/engine/Engine.java +++ b/client/src/main/java/core/engine/Engine.java @@ -138,6 +138,7 @@ public class Engine { MousePicker mousePicker = new MousePicker(camera, renderer.getProjectionMatrix(), terrain); input(camera, renderer, mousePicker); while ( !glfwWindowShouldClose(window) ) { + renderer.processTerrain(terrain); //renderer.processEntity(hexagonEntity); @@ -185,9 +186,7 @@ public class Engine { DoubleBuffer posX = BufferUtils.createDoubleBuffer(1); DoubleBuffer posY = BufferUtils.createDoubleBuffer(1); glfwGetCursorPos(window, posX, posY); - System.out.println(posX.get(0) + "|" + posY.get(0)); mousePicker.update((float) posX.get(0), (float) posY.get(0)); - mousePicker.calcIntersectingTerrainTile(); } } }; diff --git a/client/src/main/java/core/engine/toolbox/MousePicker.java b/client/src/main/java/core/engine/toolbox/MousePicker.java index f5dc7b7..22faf20 100644 --- a/client/src/main/java/core/engine/toolbox/MousePicker.java +++ b/client/src/main/java/core/engine/toolbox/MousePicker.java @@ -10,6 +10,9 @@ import utils.vectors.*; public class MousePicker { + private static final int RECURSION_COUNT = 200; + private static final float RAY_RANGE = 600; + private Vector3f currentRay = new Vector3f(); private Matrix4f projectionMatrix; @@ -18,7 +21,6 @@ public class MousePicker { private Terrain terrain; private Vector3f currentTerrainPoint; - private TerrainTile currentTerrainTile; public MousePicker(Camera cam, Matrix4f projection, Terrain terrain) { camera = cam; @@ -38,10 +40,15 @@ public class MousePicker { public void update(float mouseX, float mouseY) { viewMatrix = MatrixGraphicUtils.createViewMatrix(camera); currentRay = calculateMouseRay(mouseX, mouseY); - currentTerrainPoint = calcCurrentTerrainIntersection(); - currentTerrainTile = calcIntersectingTerrainTile(); - if(currentTerrainTile != null) { - currentTerrainTile.setColor(new Vector3f(1f, 1f, 1f)); + if (intersectionInRange(0, RAY_RANGE, currentRay)) { + currentTerrainPoint = binarySearch(0, 0, RAY_RANGE, currentRay); + } else { + currentTerrainPoint = null; + } + System.out.println(currentTerrainPoint); + TerrainTile terrainTile = calcIntersectingTerrainTile(); + if(terrainTile != null) { + terrainTile.setColor(new Vector3f(1f, 1f, 1f)); } } @@ -49,18 +56,16 @@ public class MousePicker { private Vector3f calculateMouseRay(float mouseX, float mouseY) { Vector2f normalizedCoords = getNormalisedDeviceCoordinates(mouseX, mouseY); Vector4f clipCoords = new Vector4f(normalizedCoords.x, normalizedCoords.y, -1.0f, 1.0f); - - // Transform the clip coordinates into eye coordinates using the projection matrix Vector4f eyeCoords = toEyeCoords(clipCoords); - - // Transform the eye coordinates into world coordinates using the view matrix - return toWorldCoords(eyeCoords); + Vector3f worldRay = toWorldCoords(eyeCoords); + return worldRay; } private Vector3f toWorldCoords(Vector4f eyeCoords) { Matrix4f invertedView = Matrix4f.invert(viewMatrix, null); Vector4f rayWorld = Matrix4f.transform(invertedView, eyeCoords, null); Vector3f mouseRay = new Vector3f(rayWorld.x, rayWorld.y, rayWorld.z); + mouseRay.normalise(); return mouseRay; } @@ -78,18 +83,55 @@ public class MousePicker { //********************************************************** - private Vector3f calcCurrentTerrainIntersection() { + private Vector3f getPointOnRay(Vector3f ray, float distance) { Vector3f camPos = camera.getPosition(); - float rayFactor = -camPos.y / currentRay.y; - - float terrainX = camPos.x + rayFactor * currentRay.x; - float terrainY = camPos.y + rayFactor * currentRay.y; - float terrainZ = camPos.z + rayFactor * currentRay.z; - - return new Vector3f(terrainX, terrainY, terrainZ); + Vector3f start = new Vector3f(camPos.x, camPos.y, -camPos.z); + Vector3f scaledRay = new Vector3f(ray.x * distance, ray.y * distance, ray.z * distance); + return Vector3f.add(start, scaledRay, null); + } + + private Vector3f binarySearch(int count, float start, float finish, Vector3f ray) { + float half = start + ((finish - start) / 2f); + if (count >= RECURSION_COUNT) { + Vector3f endPoint = getPointOnRay(ray, half); + Terrain terrain = getTerrain(endPoint.getX(), endPoint.getZ()); + if (terrain != null) { + return endPoint; + } else { + return null; + } + } + if (intersectionInRange(start, half, ray)) { + return binarySearch(count + 1, start, half, ray); + } else { + return binarySearch(count + 1, half, finish, ray); + } + } + + private boolean intersectionInRange(float start, float finish, Vector3f ray) { + Vector3f startPoint = getPointOnRay(ray, start); + Vector3f endPoint = getPointOnRay(ray, finish); + if (!isUnderGround(startPoint) && isUnderGround(endPoint)) { + return true; + } else { + return false; + } + } + + private boolean isUnderGround(Vector3f testPoint) { + Terrain terrain = getTerrain(testPoint.getX(), testPoint.getZ()); + float height = 0; + if (testPoint.y < height) { + return true; + } else { + return false; + } + } + + private Terrain getTerrain(float worldX, float worldZ) { + return terrain; } - //********************************************************** public TerrainTile calcIntersectingTerrainTile() { for(TerrainTile terrainTile : terrain.getTerrainTiles()) { @@ -109,4 +151,5 @@ public class MousePicker { return null; } + }