diff --git a/app/src/main/java/chess/view/DDDrender/Camera.java b/app/src/main/java/chess/view/DDDrender/Camera.java index 02cbf8e..03f5375 100644 --- a/app/src/main/java/chess/view/DDDrender/Camera.java +++ b/app/src/main/java/chess/view/DDDrender/Camera.java @@ -1,7 +1,9 @@ package chess.view.DDDrender; import org.joml.Matrix4f; +import org.joml.Vector2f; import org.joml.Vector3f; +import org.joml.Vector4f; public class Camera { public static final float fov = 70.0f; @@ -14,7 +16,6 @@ public class Camera { private final float distance = 1.5f; private final float camHeight = 1.5f; - private float aspectRatio; private float angle; @@ -22,7 +23,7 @@ public class Camera { public Camera() { this.pos = new Vector3f(0.0f, camHeight, 0.0f); - this.angle = 0.0f; + setRotateAngle(0.0f); } public void move(float x, float y) { @@ -80,4 +81,22 @@ public class Camera { public Matrix4f getViewMatrix() { return new Matrix4f().lookAt(pos, center, up); } + + public Vector2f getCursorWorldFloorPos(Vector2f screenPos, int windowWidth, int windowHeight) { + float relativeX = (screenPos.x / (float) windowWidth * 2.0f) - 1.0f; + float relativeY = 1.0f - (screenPos.y / (float) windowHeight * 2.0f); + + Vector4f rayClip = new Vector4f(relativeX, relativeY, -1.0f, 1.0f); + + Vector4f rayEye = getPerspectiveMatrix().invert().transform(rayClip); + + rayEye = new Vector4f(rayEye.x, rayEye.y, -1.0f, 0.0f); + + Vector4f rayWorld = getViewMatrix().invert().transform(rayEye); + + float lambda = -this.pos.y / rayWorld.y; + + return new Vector2f(lambda * rayWorld.x + this.pos.x, lambda * + rayWorld.z + this.pos.z); + } } diff --git a/app/src/main/java/chess/view/DDDrender/DDDPlacement.java b/app/src/main/java/chess/view/DDDrender/DDDPlacement.java index 9300027..81275b8 100644 --- a/app/src/main/java/chess/view/DDDrender/DDDPlacement.java +++ b/app/src/main/java/chess/view/DDDrender/DDDPlacement.java @@ -5,12 +5,17 @@ import org.joml.Vector2f; import chess.model.Coordinate; class DDDPlacement { - static public Vector2f coordinates_to_vector(Coordinate coo) { + public static Vector2f coordinates_to_vector(Coordinate coo) { return coordinates_to_vector(coo.getX(), coo.getY()); } - static public Vector2f coordinates_to_vector(float x, float y) { + public static Vector2f coordinates_to_vector(float x, float y) { return new Vector2f(1.0f - 0.125f - x * 0.250f, 1.0f - 0.125f - y * 0.250f); } - + + public static Coordinate vector_to_coordinates(Vector2f pos) { + int x = (int) ((1.0f - pos.x) * 4.0f); + int y = (int) ((1.0f - pos.y) * 4.0f); + return new Coordinate(x, y); + } } \ No newline at end of file diff --git a/app/src/main/java/chess/view/DDDrender/DDDView.java b/app/src/main/java/chess/view/DDDrender/DDDView.java index b7b657f..0163bb2 100644 --- a/app/src/main/java/chess/view/DDDrender/DDDView.java +++ b/app/src/main/java/chess/view/DDDrender/DDDView.java @@ -28,11 +28,23 @@ public class DDDView extends GameAdaptator { this.world = new World(new Camera()); this.window = new Window(this.renderer, this.world); this.window.OnCellClick.connect(this::onCellClick); + this.window.OnCellEnter.connect(this::onCellEnter); + this.window.OnCellExit.connect(this::onCellExit); } // Invoked when a cell is clicked private void onCellClick(Coordinate coordinate) { + System.out.println("Cell clicked : " + coordinate); + } + // Invoked when a cell is hovered + private void onCellEnter(Coordinate coordinate) { + System.out.println("Enter : " + coordinate); + } + + // Invoked when a cell is not hovered anymore + private void onCellExit(Coordinate coordinate) { + System.out.println("Exit : " + coordinate); } private Piece pieceAt(Coordinate pos) { diff --git a/app/src/main/java/chess/view/DDDrender/Window.java b/app/src/main/java/chess/view/DDDrender/Window.java index 8841569..208885e 100644 --- a/app/src/main/java/chess/view/DDDrender/Window.java +++ b/app/src/main/java/chess/view/DDDrender/Window.java @@ -1,5 +1,6 @@ package chess.view.DDDrender; +import org.joml.Vector2f; import org.lwjgl.*; import org.lwjgl.glfw.*; import org.lwjgl.opengl.*; @@ -35,7 +36,11 @@ public class Window { private final Queue tasks; private final List> regularTasks; + private Coordinate lastCell = null; + public final Signal1 OnCellClick = new Signal1<>(); + public final Signal1 OnCellEnter = new Signal1<>(); + public final Signal1 OnCellExit = new Signal1<>(); public Window(Renderer renderer, World world) { this.renderer = new Renderer(); @@ -143,6 +148,32 @@ public class Window { } } + private void checkCursor(int windowWidth, int windowHeight) { + double x[] = new double[1]; + double y[] = new double[1]; + glfwGetCursorPos(this.window, x, y); + Vector2f cursorPos = this.cam.getCursorWorldFloorPos(new Vector2f((float) x[0], (float) y[0]), windowWidth, windowHeight); + Coordinate selectedCell = DDDPlacement.vector_to_coordinates(cursorPos); + if (this.lastCell == null) { + this.lastCell = selectedCell; + if (selectedCell.isValid()) + this.OnCellEnter.emit(selectedCell); + } + else if (!this.lastCell.equals(selectedCell)) { + if (this.lastCell.isValid()) + this.OnCellExit.emit(this.lastCell); + if (selectedCell.isValid()) + this.OnCellEnter.emit(selectedCell); + this.lastCell = selectedCell; + } + glfwSetMouseButtonCallback(this.window, (window, button, action, mods) -> { + if (button == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS) { + if (this.lastCell.isValid()) + this.OnCellClick.emit(this.lastCell); + } + }); + } + private void loop() { // This line is critical for LWJGL's interoperation with GLFW's // OpenGL context, or any context that is managed externally. @@ -186,6 +217,8 @@ public class Window { // invoked during this call. glfwPollEvents(); + checkCursor(width[0], height[0]); + executeTasks(deltaTime); glfwGetWindowSize(window, width, height);