diff --git a/CMakeLists.txt b/CMakeLists.txt index df79a04..f04234c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,10 @@ add_executable(Dicewars_Siedler src/main.cpp src/engine/renderer/loader/OBJLoader.cpp src/engine/renderer/loader/OBJLoader.h src/engine/layer/entities/Light.cpp - src/engine/layer/entities/Light.h) + src/engine/layer/entities/Light.h + src/engine/platform/glfw/MousePicker.cpp + src/engine/platform/glfw/MousePicker.h +) target_include_directories(Dicewars_Siedler PRIVATE lib/glfw/include diff --git a/src/engine/layer/GameLayer.cpp b/src/engine/layer/GameLayer.cpp index 39631ff..ec0acab 100644 --- a/src/engine/layer/GameLayer.cpp +++ b/src/engine/layer/GameLayer.cpp @@ -9,6 +9,7 @@ #include "../renderer/loader/OBJLoader.h" #include "../renderer/model/TexturedModel.h" #include "../renderer/textures/ModelTexture.h" +#include "../toolbox/MathUtils.h" #include "entities/Light.h" GameLayer::GameLayer() :texturedModel(0,0) //Platzhalter, echtes Model kommt in onAttach @@ -40,6 +41,7 @@ void GameLayer::onAttach() entity = std::make_unique(Entity(std::make_shared(texturedModel), glm::vec3(0,0,-25), 0,0,0, 1.f)); camera = std::make_unique(); light = std::make_unique(glm::vec3(0,0,-20), glm::vec3(1,1,1)); + mousePicker = std::make_unique(renderer.getProjectionMatrix(), MathUtils::createViewMatrix(*camera)); } void GameLayer::onDetach() @@ -49,6 +51,8 @@ void GameLayer::onDetach() void GameLayer::onUpdate() { + mousePicker->update(*camera); + printf("Mouse Ray: %f, %f, %f\n", mousePicker->getCurrentRay().x, mousePicker->getCurrentRay().y, mousePicker->getCurrentRay().z); glm::vec3 moveDir = glm::vec3(0,0,0); if (InputManager::isKeyPressed(GLFW_KEY_W)) moveDir.z -= 1.0f; if (InputManager::isKeyPressed(GLFW_KEY_S)) moveDir.z += 1.0f; diff --git a/src/engine/layer/GameLayer.h b/src/engine/layer/GameLayer.h index abaa49a..37a848f 100644 --- a/src/engine/layer/GameLayer.h +++ b/src/engine/layer/GameLayer.h @@ -5,6 +5,7 @@ #ifndef DICEWARS_SIEDLER_GAMELAYER_H #define DICEWARS_SIEDLER_GAMELAYER_H #include "Layer.h" +#include "../platform/glfw/MousePicker.h" #include "../renderer/Renderer.h" #include "../renderer/loader/Loader.h" #include "../renderer/model/TexturedModel.h" @@ -26,6 +27,7 @@ private: std::unique_ptr entity; std::unique_ptr camera; std::unique_ptr light; + std::unique_ptr mousePicker; Renderer renderer; }; diff --git a/src/engine/platform/glfw/InputManager.cpp b/src/engine/platform/glfw/InputManager.cpp index 562a01b..84b9912 100644 --- a/src/engine/platform/glfw/InputManager.cpp +++ b/src/engine/platform/glfw/InputManager.cpp @@ -17,6 +17,13 @@ bool InputManager::isMouseButtonPressed(int button) { return glfwGetMouseButton(window, button) == GLFW_PRESS; } +glm::vec2 InputManager::getMousePosition() { + auto window = static_cast(Application::getInstance().getWindow().GetNativeWindow()); + double xpos, ypos; + glfwGetCursorPos(window, &xpos, &ypos); + return {xpos, ypos}; +} + glm::vec2 InputManager::getMouseDelta() { static double lastX = 0, lastY = 0; double xpos, ypos; diff --git a/src/engine/platform/glfw/InputManager.h b/src/engine/platform/glfw/InputManager.h index a013a90..21c7616 100644 --- a/src/engine/platform/glfw/InputManager.h +++ b/src/engine/platform/glfw/InputManager.h @@ -11,6 +11,8 @@ class InputManager { public: static bool isKeyPressed(int keycode); static bool isMouseButtonPressed(int button); + + static glm::vec2 getMousePosition(); glm::vec2 getMouseDelta(); }; diff --git a/src/engine/platform/glfw/MousePicker.cpp b/src/engine/platform/glfw/MousePicker.cpp new file mode 100644 index 0000000..d4f11f1 --- /dev/null +++ b/src/engine/platform/glfw/MousePicker.cpp @@ -0,0 +1,43 @@ +// +// Created by sebastian on 07.02.26. +// + +#include "MousePicker.h" + +#include "InputManager.h" +#include "../../core/Application.h" +#include "../../toolbox/MathUtils.h" + + +void MousePicker::update(const Camera& camera) { + viewMatrix = MathUtils::createViewMatrix(camera); + currentRay = calculateMouseRay(); +} + +glm::vec3 MousePicker::calculateMouseRay() { + glm::vec2 mouseXY = InputManager::getMousePosition(); + + glm::vec2 normalizedDeviceCoords = getNormalizedDeviceCoords(mouseXY.x, mouseXY.y); + glm::vec4 clipCoords = glm::vec4(normalizedDeviceCoords.x, normalizedDeviceCoords.y, -1.0f, 1.0f); + glm::vec4 eyeCoords = toEyeSpace(clipCoords); + glm::vec3 worldCoords = toWorldSpace(eyeCoords); + return glm::normalize(worldCoords); +} + +glm::vec2 MousePicker::getNormalizedDeviceCoords(float mouseX, float mouseY) { + float x = (2.f * mouseX) / static_cast(Application::getInstance().getWindow().GetWidth()) - 1.f; + float y = (2.f * mouseY) / static_cast(Application::getInstance().getWindow().GetHeight()) - 1.f; + return {x, y}; +} + +glm::vec4 MousePicker::toEyeSpace(const glm::vec4 clipCoords) const { + glm::mat4 inverseProjectionMatrix = glm::inverse(projectionMatrix); + glm::vec4 eyeCoords = inverseProjectionMatrix * clipCoords; + return {eyeCoords.x, eyeCoords.y, -1.0f, 0.0f}; +} + +glm::vec3 MousePicker::toWorldSpace(glm::vec4 eyeCoords) const { + glm::mat4 inverseViewMatrix = glm::inverse(viewMatrix); + glm::vec4 worldCoords = inverseViewMatrix * eyeCoords; + return {worldCoords.x, worldCoords.y, worldCoords.z}; +} diff --git a/src/engine/platform/glfw/MousePicker.h b/src/engine/platform/glfw/MousePicker.h new file mode 100644 index 0000000..c6430a7 --- /dev/null +++ b/src/engine/platform/glfw/MousePicker.h @@ -0,0 +1,36 @@ +// +// Created by sebastian on 07.02.26. +// + +#ifndef MOUSEPICKER_H +#define MOUSEPICKER_H +#include "glm/mat4x4.hpp" +#include "glm/vec3.hpp" + +class Camera; + +class MousePicker { +private: + glm::vec3 currentRay = glm::vec3(0.0f); + glm::mat4 projectionMatrix; + glm::mat4 viewMatrix; + + glm::vec3 calculateMouseRay(); + + static glm::vec2 getNormalizedDeviceCoords(float mouseX, float mouseY); + [[nodiscard]] glm::vec4 toEyeSpace(glm::vec4 clipCoords) const; + [[nodiscard]] glm::vec3 toWorldSpace(glm::vec4 eyeCoords) const; + +public: + MousePicker(const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix) : projectionMatrix(projectionMatrix), viewMatrix(viewMatrix) {}; + + [[nodiscard]] glm::vec3 getCurrentRay() const { + return currentRay; + } + + void update(const Camera& camera); +}; + + + +#endif //MOUSEPICKER_H diff --git a/src/engine/renderer/Renderer.h b/src/engine/renderer/Renderer.h index 849e338..1ba7fa2 100644 --- a/src/engine/renderer/Renderer.h +++ b/src/engine/renderer/Renderer.h @@ -22,6 +22,7 @@ public: }; void prepare(const ::Camera &camera, const Light& light); void renderFrame(const ::Entity &entity, const ::Camera &camera, const Light& light); + [[nodiscard]] glm::mat4 getProjectionMatrix() const {return projectionMatrix;} private: void renderRawModel(const Entity &entity); StaticShader staticShader;