From 9ddd711fb904a6cc4029081d501e277db32416da Mon Sep 17 00:00:00 2001
From: Vanessa Karolek <vaka1997@uni-koblenz.de>
Date: Mon, 24 May 2021 20:35:15 +0200
Subject: [PATCH] [#35] add mouse scroll event, mouse move functionalities

For now, camera based callbacks are handled within main. For a camera controller, we need a way to pass callback functions to the 'add' function, i.e. replacing the lambda expressions.
---
 include/vkcv/Window.hpp                       |  3 +
 modules/testing/CMakeLists.txt                |  4 +-
 .../testing/include/vkcv/camera/Camera.hpp    | 26 ++++---
 projects/first_triangle/src/main.cpp          | 68 +++++++++++++++----
 src/vkcv/Window.cpp                           | 10 +++
 5 files changed, 82 insertions(+), 29 deletions(-)

diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp
index bb8081c1..6c0ddbcf 100644
--- a/include/vkcv/Window.hpp
+++ b/include/vkcv/Window.hpp
@@ -32,6 +32,8 @@ namespace vkcv {
          */
         static void onMouseMoveEvent(GLFWwindow *window, double x, double y);
 
+        static void onMouseScrollEvent(GLFWwindow *callbackWindow, double xoffset, double yoffset);
+
         /**
          * resize callback for the resize option of the window
          * @param[in] window The window that was resized.
@@ -82,6 +84,7 @@ namespace vkcv {
          * basic events of the window
          */
         event< double, double > e_mouseMove;
+        event< double, double > e_mouseScroll;
         event< int, int > e_resize;
         event< int, int, int, int > e_key;
 
diff --git a/modules/testing/CMakeLists.txt b/modules/testing/CMakeLists.txt
index 822a27c1..213bbb22 100644
--- a/modules/testing/CMakeLists.txt
+++ b/modules/testing/CMakeLists.txt
@@ -13,7 +13,9 @@ set(vkcv_testing_sources
 		${vkcv_testing_source}/vkcv/testing/Test.cpp
 		${vkcv_testing_include}/vkcv/camera/Camera.hpp
 		${vkcv_testing_source}/vkcv/camera/Camera.cpp
-		src/vkcv/camera/TrackballCamera.cpp)
+		${vkcv_testing_include}/vkcv/camera/TrackballCamera.hpp
+		${vkcv_testing_source}/vkcv/camera/TrackballCamera.cpp
+		)
 
 # adding source files to the project
 add_library(vkcv_testing STATIC ${vkcv_testing_sources})
diff --git a/modules/testing/include/vkcv/camera/Camera.hpp b/modules/testing/include/vkcv/camera/Camera.hpp
index d373e376..1f0cd580 100644
--- a/modules/testing/include/vkcv/camera/Camera.hpp
+++ b/modules/testing/include/vkcv/camera/Camera.hpp
@@ -15,46 +15,44 @@ namespace vkcv {
 
         int m_width, m_height;
 
-        float m_oldX, m_oldY;
+        float m_oldX, m_oldY,
+                m_near, m_far,
+                m_fov, m_ratio;
 
         glm::vec3 m_position, m_direction, m_up;
 
-        float m_near, m_far;
-        float m_fov, m_ratio;
-
     public:
         Camera();
 
         ~Camera();
 
-        virtual void update(GLFWwindow* window) {};
+        virtual void update(GLFWwindow *window) {};
 
         void setPerspective(float fov, float ratio, float near, float far);
 
-        const glm::mat4& getView();
+        const glm::mat4 &getView();
 
         void getView(glm::vec3 &x, glm::vec3 &y, glm::vec3 &z, glm::vec3 &pos);
 
-        void setView( const glm::mat4 view );
+        void setView(const glm::mat4 view);
 
         void lookAt(glm::vec3 position, glm::vec3 center, glm::vec3 up);
 
-        const glm::mat4& Camera::getProjection();
+        const glm::mat4 &Camera::getProjection();
 
-        void setProjection( const glm::mat4 projection);
+        void setProjection(const glm::mat4 projection);
 
-        void getNearFar( float &near, float &far);
+        void getNearFar(float &near, float &far);
 
         float getFov();
 
-        void setFov( float fov);
+        void setFov(float fov);
 
-        void updateRatio( float ratio);
+        void updateRatio(float ratio);
 
         float getRatio();
 
-        void setNearFar( float near, float far);
-
+        void setNearFar(float near, float far);
 
     };
 
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 2981e566..5ff33793 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -6,6 +6,7 @@
 #include <vkcv/camera/Camera.hpp>
 #include <vkcv/camera/TrackballCamera.hpp>
 
+
 int main(int argc, const char** argv) {
     const char* applicationName = "First Triangle";
 
@@ -32,28 +33,67 @@ int main(int argc, const char** argv) {
     float roll = 0.0;
     float pitch = 0.0;
     float yaw = 0.0;
-    // TODO: need scrolling event callback to set yoffset
-    float yoffset = 10;
-
-    // scroll callback
-    float fov = camera.getFov();
-    fov -= yoffset;
-    if (fov < 1.0f)
-        fov = 1.0f;
-    if (fov > 45.0f)
-        fov = 45.0f;
-    camera.setFov(fov);
 
     //TODO? should the standard camera support rotation?
 
+    bool firstMouse = true;
+    double lastX, lastY;
+
     // showing basic usage lambda events of window
-    window.e_mouseMove.add([&](double x, double y){
+    window.e_mouseMove.add([&](double x, double y) {
         std::cout << "movement: " << x << " , " << y << std::endl;
+
+        if (firstMouse) {
+            lastX = x;
+            lastY = y;
+            firstMouse = false;
+        }
+
+        float xoffset = x - lastX;
+        float yoffset = lastY - y;
+        lastX = x;
+        lastY = y;
+
+        float sensitivity = 0.1f;
+        xoffset *= sensitivity;
+        yoffset *= sensitivity;
+
+        yaw += xoffset;
+        pitch += yoffset;
+
+        if (pitch > 89.0f) {
+            pitch = 89.0f;
+        }
+        if (pitch < -89.0f) {
+            pitch = -89.0f;
+        }
+
+        glm::vec3 direction;
+        direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
+        direction.y = sin(glm::radians(pitch));
+        direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
+
+        front = glm::normalize(direction);
+        center = position + front;
+        camera.lookAt(position, center, up);
+
+        std::cout << "New center: " << center.x << ", " << center.y << ", " << center.z << std::endl;
     });
 
-    // TODO: need event for press mouse button
+    window.e_mouseScroll.add([&](double xoffset, double yoffset) {
+        float fov = camera.getFov();
+        fov -= (float)yoffset;
+        if (fov < 1.0f) {
+            fov = 1.0f;
+        }
+        if (fov > 45.0f) {
+            fov = 45.0f;
+        }
+        camera.setFov(fov);
+        std::cout << "New FOV: " << fov << std::endl;
+    });
 
-    window.e_key.add([&](int key, int scancode, int action, int mods){
+    window.e_key.add([&](int key, int scancode, int action, int mods) {
         switch (key) {
             case GLFW_KEY_W:
                 std::cout << "Move forward" << std::endl;
diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp
index 87f302c1..202f8d7e 100644
--- a/src/vkcv/Window.cpp
+++ b/src/vkcv/Window.cpp
@@ -51,6 +51,8 @@ namespace vkcv {
         glfwSetWindowSizeCallback(m_window, Window::onResize);
 
         glfwSetKeyCallback(m_window, Window::onKeyEvent);
+
+        glfwSetScrollCallback(m_window, Window::onMouseScrollEvent);
     }
 
     void Window::pollEvents() {
@@ -66,6 +68,14 @@ namespace vkcv {
         }
     }
 
+    void Window::onMouseScrollEvent(GLFWwindow *callbackWindow, double xoffset, double yoffset) {
+        auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow));
+
+        if (window != nullptr) {
+            window->e_mouseScroll(xoffset, yoffset);
+        }
+    }
+
     void Window::onResize(GLFWwindow *callbackWindow, int width, int height) {
 
         auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow));
-- 
GitLab