diff --git a/modules/camera/CMakeLists.txt b/modules/camera/CMakeLists.txt index 28080bf2b1cd3bbc88d6c13d7ef26a43d7c3e19a..5c17d8d3c1ed4be8ba080ae0fd54a4a9057acc36 100644 --- a/modules/camera/CMakeLists.txt +++ b/modules/camera/CMakeLists.txt @@ -11,10 +11,14 @@ set(vkcv_camera_include ${PROJECT_SOURCE_DIR}/include) set(vkcv_camera_sources ${vkcv_camera_include}/vkcv/camera/Camera.hpp ${vkcv_camera_source}/vkcv/camera/Camera.cpp - ${vkcv_camera_include}/vkcv/camera/TrackballCamera.hpp - ${vkcv_camera_source}/vkcv/camera/TrackballCamera.cpp ${vkcv_camera_include}/vkcv/camera/CameraManager.hpp ${vkcv_camera_source}/vkcv/camera/CameraManager.cpp + ${vkcv_camera_include}/vkcv/camera/CameraController.hpp + ${vkcv_camera_source}/vkcv/camera/CameraController.cpp + ${vkcv_camera_include}/vkcv/camera/PilotCameraController.hpp + ${vkcv_camera_source}/vkcv/camera/PilotCameraController.cpp + ${vkcv_camera_include}/vkcv/camera/TrackballCameraController.hpp + ${vkcv_camera_source}/vkcv/camera/TrackballCameraController.cpp ) # adding source files to the project diff --git a/modules/camera/include/vkcv/camera/Camera.hpp b/modules/camera/include/vkcv/camera/Camera.hpp index aa0ec51995de8f8b432058f177fd2e6076c1bc4f..d9eacbee4df2080549a671e863682835d1bba538 100644 --- a/modules/camera/include/vkcv/camera/Camera.hpp +++ b/modules/camera/include/vkcv/camera/Camera.hpp @@ -9,38 +9,25 @@ namespace vkcv { /** - * @brief Used to create a camera whose position can be changed. + * @brief Used to create a camera which governs the view and projection matrices. */ - class Camera { + class Camera final { protected: glm::mat4 m_view; glm::mat4 m_projection; - int m_width; - int m_height; - float m_near; float m_far; float m_fov; float m_ratio; - glm::vec3 m_up; + glm::vec3 m_up; glm::vec3 m_position; - float m_cameraSpeed; + glm::vec3 m_center; + float m_pitch; float m_yaw; - int m_fov_nsteps; - float m_fov_min; - float m_fov_max; - - bool m_forward; - bool m_backward; - bool m_left; - bool m_right; - bool m_top; - bool m_bottom; - public: /** @@ -51,7 +38,7 @@ namespace vkcv { /** * @brief The destructor of the camera (default behavior) */ - virtual ~Camera(); + ~Camera(); /** * @brief Sets the perspective object according to @p fov, @p ratio, @p near and @p far. This leads to changes in the projection matrix of the camera @@ -66,14 +53,7 @@ namespace vkcv { * @brief Gets the view matrix of the camera * @return The view matrix of the camera */ - const glm::mat4& getView(); - - /** - * @brief Updates the view matrix of the camera with respect to @p deltaTime - * @param deltaTime The time that has passed since last update - * @return The updated view matrix of the camera - */ - glm::mat4 updateView(double deltaTime); + glm::mat4& getView(); /** * @brief Sets the view matrix of the camera according to @p position, @p center and @p up @@ -87,7 +67,7 @@ namespace vkcv { * @brief Gets the current projection of the camera * @return The current projection matrix */ - const glm::mat4& getProjection(); + glm::mat4& getProjection(); /** * @brief Sets the projection matrix of the camera to @p projection @@ -95,6 +75,12 @@ namespace vkcv { */ void setProjection(const glm::mat4 projection); + /** + * @brief Gets the model-view-projection matrix of the camera + * @return The model-view-projection matrix + */ + glm::mat4 getMVP() const; + /** * @brief Gets the near and far bounds of the view frustum of the camera. * @param[out] near The near bound of the view frustum @@ -102,41 +88,29 @@ namespace vkcv { */ void getNearFar(float &near, float &far) const; - /** - * @brief Sets the up vector of the camera to @p up - * @param[in] up The new up vector of the camera - */ - void setUp(const glm::vec3 &up); - /** * @brief Gets the current field of view of the camera in radians * @return[in] The current field of view in radians */ - float getFov() const; + const float getFov() const; /** * @brief Sets the field of view of the camera to @p fov in radians * @param[in] fov The new field of view in radians */ void setFov(float fov); - + /** - * @brief Changes the field of view of the camera with an @p offset in degrees - * @param[in] offset The offset in degrees + * @brief Gets the current aspect ratio of the camera + * @return The current aspect ratio of the camera */ - void changeFov(double offset); + float getRatio() const; /** * @brief Updates the aspect ratio of the camera with @p ratio and, thus, changes the projection matrix * @param[in] ratio The new aspect ratio of the camera */ - void updateRatio(float ratio); - - /** - * @brief Gets the current aspect ratio of the camera - * @return The current aspect ratio of the camera - */ - float getRatio() const; + void setRatio(float ratio); /** * @brief Sets @p near and @p far as new values for the view frustum of the camera. This leads to changes in the projection matrix according to these two values. @@ -164,78 +138,52 @@ namespace vkcv { void setPosition( glm::vec3 position ); /** - * @brief Gets the pitch value of the camera in degrees - * @return The pitch value in degrees - */ - float getPitch() const; - - /** - * @brief Sets the pitch value of the camera to @p pitch in degrees - * @param[in] pitch The new pitch value in degrees - */ - void setPitch(float pitch); - - /** - * @brief Gets the yaw value of the camera in degrees - * @return The yaw value in degrees + * @brief Gets the center point. + * @return The center point. */ - float getYaw() const; + glm::vec3 getCenter() const; /** - * @brief Sets the yaw value of the camera to @p yaw - * @param[in] yaw The new yaw value in degrees + * @brief Sets @p center as the new center point. + * @param center The new center point. */ - void setYaw(float yaw); + void setCenter(glm::vec3 center); /** - * @brief Pans the view of the camera according to the pitch and yaw values and additional offsets @p xOffset and @p yOffset (e.g. taken from mouse movement) - * @param[in] xOffset The offset added to the yaw value - * @param[in] yOffset The offset added to the pitch value + * @brief Gets the pitch value of the camera in degrees. + * @return The pitch value in degrees. */ - void panView( double xOffset, double yOffset ); - - /** - * @brief Updates the position of the camera with respect to @p deltaTime - * @param[in] deltaTime The time that has passed since last update - */ - void updatePosition(double deltaTime); - - /** - * @brief Indicates forward movement of the camera depending on the performed @p action - * @param[in] action The performed action - */ - void moveForward(int action); + float getPitch() const; /** - * @brief Indicates backward movement of the camera depending on the performed @p action - * @param[in] action The performed action + * @brief Sets the pitch value of the camera to @p pitch in degrees. + * @param[in] pitch The new pitch value in degrees. */ - void moveBackward(int action); + void setPitch(float pitch); /** - * @brief Indicates left movement of the camera depending on the performed @p action - * @param[in] action The performed action + * @brief Gets the yaw value of the camera in degrees. + * @return The yaw value in degrees. */ - void moveLeft(int action); + float getYaw() const; /** - * @brief Indicates right movement of the camera depending on the performed @p action - * @param[in] action The performed action + * @brief Sets the yaw value of the camera to @p yaw. + * @param[in] yaw The new yaw value in degrees. */ - void moveRight(int action); + void setYaw(float yaw); /** - * @brief Indicates top movement of the camera depending on the performed @p action - * @param[in] action The performed action + * @brief Gets the up vector. + * @return The up vector. */ - void moveTop(int action); + glm::vec3 getUp() const; /** - * @brief Indicates bottom movement of the camera depending on the performed @p action - * @param[in] action The performed action + * @brief Sets @p up as the new up vector. + * @param up The new up vector. */ - void moveBottom(int action); - + void setUp(const glm::vec3 &up); }; } diff --git a/modules/camera/include/vkcv/camera/CameraController.hpp b/modules/camera/include/vkcv/camera/CameraController.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0bdcf7885175a551cf71d25babf851adfc5017fd --- /dev/null +++ b/modules/camera/include/vkcv/camera/CameraController.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include "Camera.hpp" +#include "vkcv/Window.hpp" +#include <glfw/glfw3.h> + +namespace vkcv { + + /** + * @brief Used as a base class for defining camera controller classes with different behaviors, e.g. the + * #PilotCameraController. + */ + class CameraController { + protected: + Camera* m_camera; + Window* m_window; + double m_lastX; + double m_lastY; + + public: + + /** + * @brief The constructor of the #CameraController (default behavior). + */ + CameraController() = default; + + /** + * @brief Gets the camera object. + * @return The camera object. + */ + Camera& getCamera(); + + /** + * @brief Sets @p camera as the new camera object. + * @param camera The new camera object. + */ + virtual void setCamera(Camera &camera); + + /** + * @brief Sets @p window as the new window object. + * @param window The new window object. + */ + void setWindow(Window &window); + + /** + * @brief Updates the camera object in respect to @p deltaTime. + * @param deltaTime The time that has passed since last update. + */ + virtual void updateCamera(double deltaTime); + + /** + * @brief A callback function for key events. + * @param[in] key The keyboard key. + * @param[in] scancode The platform-specific scancode. + * @param[in] action The key action. + * @param[in] mods The modifier bits. + */ + virtual void keyCallback(int key, int scancode, int action, int mods); + + /** + * @brief A callback function for mouse scrolling events. + * @param[in] offsetX The offset in horizontal direction. + * @param[in] offsetY The offset in vertical direction. + */ + virtual void scrollCallback( double offsetX, double offsetY); + + /** + * @brief A callback function for mouse movement events. + * @param[in] x The horizontal mouse position. + * @param[in] y The vertical mouse position. + */ + virtual void mouseMoveCallback(double offsetX, double offsetY); + + /** + * @brief A callback function for mouse button events. + * @param[in] button The mouse button. + * @param[in] action The button action. + * @param[in] mods The modifier bits. + */ + virtual void mouseButtonCallback(int button, int action, int mods); + }; + +} \ No newline at end of file diff --git a/modules/camera/include/vkcv/camera/CameraManager.hpp b/modules/camera/include/vkcv/camera/CameraManager.hpp index 917d1915cf17b690ba0147516aded08409c99b16..400a4c453437b38688aaa5e8b032d5b2c53482db 100644 --- a/modules/camera/include/vkcv/camera/CameraManager.hpp +++ b/modules/camera/include/vkcv/camera/CameraManager.hpp @@ -1,87 +1,165 @@ #pragma once -#include "TrackballCamera.hpp" +#include "PilotCameraController.hpp" +#include "TrackballCameraController.hpp" +#include "CameraController.hpp" #include "vkcv/Window.hpp" #include <GLFW/glfw3.h> #include <functional> -namespace vkcv{ +namespace vkcv { + /** + * @brief Used for specifying existing types of camera controllers when adding a new controller object to the + * #CameraManager. + */ + enum class ControllerType { + PILOT, + TRACKBALL, + TRACE + }; + + /** + * @brief Used for managing an arbitrary amount of camera controllers. + */ class CameraManager{ private: std::function<void(int, int, int, int)> m_keyHandle; std::function<void(double, double)> m_mouseMoveHandle; std::function<void(double, double)> m_mouseScrollHandle; std::function<void(int, int, int)> m_mouseButtonHandle; + std::function<void(int, int)> m_resizeHandle; - Window &m_window; - Camera m_camera; - TrackballCamera m_trackball; // TODO: maybe there is a better way for switching between cameras? - float m_width; - float m_height; + Window& m_window; + std::vector<Camera*> m_cameras; + std::vector<CameraController*> m_controllers; + uint32_t m_activeControllerIndex; - bool m_rotationActive = false; - double m_lastX ; - double m_lastY ; /** - * @brief Binds the camera object to the window event handles + * @brief Binds the camera object to the window event handles. */ - void bindCamera(); + void bindCameraToEvents(); /** - * @brief A callback function for key events. Currently, 3D camera movement via W, A, S, D, E, Q and window closure via Escape are supported - * @param[in] key The keyboard key - * @param[in] scancode The platform-specific scancode - * @param[in] action The key action - * @param[in] mods The modifier bits + * @brief A callback function for key events. Currently, cycling between all existing camera controllers via Tab, + * window closure via Esc and polling key events from the active camera controller are supported. + * @param[in] key The keyboard key. + * @param[in] scancode The platform-specific scancode. + * @param[in] action The key action. + * @param[in] mods The modifier bits. */ void keyCallback(int key, int scancode, int action, int mods); /** - * @brief A callback function for mouse scrolling events. Currently, this leads to changes in the field of view of the camera object - * @param[in] offsetX The offset in horizontal direction - * @param[in] offsetY The offset in vertical direction + * @brief A callback function for mouse scrolling events. + * @param[in] offsetX The offset in horizontal direction. + * @param[in] offsetY The offset in vertical direction. */ - void scrollCallback( double offsetX, double offsetY); + void scrollCallback(double offsetX, double offsetY); /** - * @brief A callback function for mouse movement events. Currently, this leads to panning the view of the camera, if @fn mouseButtonCallback(int button, int action, int mods) enabled panning. - * @param[in] offsetX The offset in horizontal direction - * @param[in] offsetY The offset in vertical direction + * @brief A callback function for mouse movement events. + * @param[in] x The horizontal mouse position. + * @param[in] y The vertical mouse position. */ - void mouseMoveCallback( double offsetX, double offsetY); + void mouseMoveCallback(double x, double y); /** - * @brief A callback function for mouse button events. Currently, the right mouse button enables panning the view of the camera as long as it is pressed. - * @param[in] button The mouse button - * @param[in] action The button action - * @param[in] mods The modifier bits + * @brief A callback function for mouse button events. + * @param[in] button The mouse button. + * @param[in] action The button action. + * @param[in] mods The modifier bits. */ void mouseButtonCallback(int button, int action, int mods); + /** + * @brief A callback function for handling the window resizing event. Each existing camera is resized in respect + * of the window size. + * @param[in] width The new width of the window. + * @param[in] height The new height of the window. + */ + void resizeCallback(int width, int height); + + public: /** - * @brief The constructor - * @param[in] window The window - * @param[in] width The width of the window - * @param[in] height The height of the window - * @param[in] up The up vector of the camera. Per default: @code{.cpp} up = glm::vec3(0.0f, 1.0f, 0.0f) @endcode - * @param[in] position The position of the camera. Per default: @code{.cpp} position = glm::vec3(0.0f,0.0f,0.0f) @endcode + * @brief The constructor of the #CameraManager. + * @param[in] window The window. + * @param[in] width The width of the window. + * @param[in] height The height of the window. + */ + CameraManager(Window &window, float width, float height); + + /** + * @brief The destructor of the #CameraManager. Destroying the #CameraManager leads to deletion of all stored + * camera objects and camera controller objects. + */ + ~CameraManager(); + + /** + * @brief Adds a new camera object to the #CameraManager. + * @return The index of the newly created camera object. */ - CameraManager(Window &window, float width, float height, glm::vec3 up = glm::vec3(0.0f,1.0f,0.0f), glm::vec3 position = glm::vec3(0.0f,0.0f,0.0f)); + int addCamera(); /** - * @brief Gets the camera object - * @return The camera object + * @brief Gets the stored camera object located at @p cameraIndex. + * @param cameraIndex The index of the stored camera object. + * @return The camera object at @p cameraIndex. */ - Camera& getCamera(); + Camera& getCamera(uint32_t cameraIndex); /** - * @brief Gets the trackball camera object - * @return The trackball camera object + * @brief Adds a new camera controller object of @p controllerType to the #CameraManager. If the newly created + * camera controller object is the first controller object that has been added, it becomes the active + * controllerType. + * @param[in] controllerType The controllerType type that should be used. + * @param[in] cameraIndex The camera index. + * @return The index of the camera controllerType. */ - TrackballCamera& getTrackballCamera(); + int addController(ControllerType controllerType, uint32_t cameraIndex); + + /** + * @brief Gets the stored camera controller object located at @p controllerIndex. + * @param controllerIndex The controller index. + * @return The camera controller object at @p controllerIndex. + */ + CameraController& getController(uint32_t controllerIndex); + + /** + * @brief Binds the stored camera object located at @p cameraIndex to the stored camera controller object + * located at @p controllerIndex. + * @param cameraIndex The camera index. + * @param controllerIndex The controller index. + */ + void bindCameraToController(uint32_t cameraIndex, uint32_t controllerIndex); + + /** + * @brief Gets the currently active camera controller that is bound to the window. + * @return The currently active camera controller object. + */ + CameraController& getActiveController(); + + /** + * @brief Sets the camera controller located at @p controllerIndex as the active camera controller. + * @param controllerIndex The controller index. + */ + void setActiveController(uint32_t controllerIndex); + + /** + * @brief Updates all stored camera controllers in respect to @p deltaTime. + * @param deltaTime The time that has passed since last update. + */ + void update(double deltaTime); + + /** + * @brief Updates the stored camera controller located at @p controllerIndex in respect to @p deltaTime. + * @param deltaTime The time that has passed since last update. + * @param controllerIndex The controller index. + */ + void update(double deltaTime, uint32_t controllerIndex); + }; } diff --git a/modules/camera/include/vkcv/camera/PilotCameraController.hpp b/modules/camera/include/vkcv/camera/PilotCameraController.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c164710fddfc9c50b693f86107cb9e59a26e6e8a --- /dev/null +++ b/modules/camera/include/vkcv/camera/PilotCameraController.hpp @@ -0,0 +1,152 @@ +#pragma once + +#include <vkcv/camera/CameraController.hpp> + +namespace vkcv { + + /** + * @brief Used to move around a camera object in world space. + */ + class PilotCameraController final : public CameraController { + private: + // camera movement indicators + bool m_forward; + bool m_backward; + bool m_upward; + bool m_downward; + bool m_left; + bool m_right; + + bool m_rotationActive; + + float m_cameraSpeed; + + int m_fov_nsteps; + float m_fov_min; + float m_fov_max; + + + /** + * @brief Updates the position of the camera with respect to @p deltaTime. + * @param[in] deltaTime The time that has passed since last update. + * @return The updated camera position. + */ + glm::vec3 updatePosition(double deltaTime); + + /** + * @brief Updates the view matrix of the camera with respect to @p deltaTime. + * @param deltaTime The time that has passed since last update. + * @return The updated view matrix of the camera. + */ + glm::mat4 updateView(double deltaTime); + + /** + * @brief Indicates forward movement of the camera depending on the performed @p action. + * @param[in] action The performed action. + */ + void moveForward(int action); + + /** + * @brief Indicates backward movement of the camera depending on the performed @p action. + * @param[in] action The performed action. + */ + void moveBackward(int action); + + /** + * @brief Indicates left movement of the camera depending on the performed @p action. + * @param[in] action The performed action. + */ + void moveLeft(int action); + + /** + * @brief Indicates right movement of the camera depending on the performed @p action. + * @param[in] action The performed action. + */ + void moveRight(int action); + + /** + * @brief Indicates upward movement of the camera depending on the performed @p action. + * @param[in] action The performed action. + */ + void moveUpward(int action); + + /** + * @brief Indicates downward movement of the camera depending on the performed @p action. + * @param[in] action The performed action. + */ + void moveDownward(int action); + + public: + + /** + * @brief The default constructor of the #PilotCameraController. + */ + PilotCameraController(); + + /** + * @brief The destructor of the #PilotCameraController (default behavior). + */ + ~PilotCameraController() = default; + + /** + * @brief Changes the field of view of the camera with an @p offset in degrees. + * @param[in] offset The offset in degrees. + */ + void changeFov(double offset); + + /** + * @brief Pans the view of the camera according to the pitch and yaw values and additional offsets @p xOffset + * and @p yOffset. + * @param[in] xOffset The offset added to the yaw value. + * @param[in] yOffset The offset added to the pitch value. + */ + void panView(double xOffset, double yOffset); + + /** + * @brief Sets @p camera as the new camera object. + * @param camera The new camera object. + */ + virtual void setCamera(Camera &camera); + + /** + * @brief Updates the camera object in respect to @p deltaTime. + * @param deltaTime The time that has passed since last update. + */ + void updateCamera(double deltaTime); + + /** + * @brief A callback function for key events. Currently, 3D camera movement via W, A, S, D, E, Q are supported. + * @param[in] key The keyboard key. + * @param[in] scancode The platform-specific scancode. + * @param[in] action The key action. + * @param[in] mods The modifier bits. + */ + void keyCallback(int key, int scancode, int action, int mods); + + /** + * @brief A callback function for mouse scrolling events. Currently, this leads to changes in the field of view + * of the camera object. + * @param[in] offsetX The offset in horizontal direction. + * @param[in] offsetY The offset in vertical direction. + */ + void scrollCallback( double offsetX, double offsetY); + + /** + * @brief A callback function for mouse movement events. Currently, this leads to panning the view of the camera, + * if #mouseButtonCallback(int button, int action, int mods) enabled panning. + * @param[in] x The horizontal mouse position + * @param[in] y The vertical mouse position + */ + void mouseMoveCallback(double x, double y); + + /** + * @brief A callback function for mouse button events. Currently, the right mouse button enables panning the + * view of the camera as long as it is pressed. + * @param[in] button The mouse button + * @param[in] action The button action + * @param[in] mods The modifier bits + */ + void mouseButtonCallback(int button, int action, int mods); + }; + +} \ No newline at end of file diff --git a/modules/camera/include/vkcv/camera/TrackballCamera.hpp b/modules/camera/include/vkcv/camera/TrackballCamera.hpp deleted file mode 100644 index 21f79f9d2dab44e4828d17973a55fb789e8ba39d..0000000000000000000000000000000000000000 --- a/modules/camera/include/vkcv/camera/TrackballCamera.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once - -#include "Camera.hpp" - -namespace vkcv { - - class TrackballCamera : public vkcv::Camera { - protected: - glm::vec3 m_center; - float m_radius; - float m_scrollSensitivity; - - public: - - /** - * @brief The default constructor of the trackball camera - */ - TrackballCamera(); - - /** - * @brief The destructor of the trackball camera (default behavior) - */ - ~TrackballCamera(); - - /** - * @brief Gets the radius of the trackball camera that specifies the distance of the trackball camera to the center point - * @return The radius of the trackball camera - */ - float getRadius() const; - - /** - * @brief Sets the current radius of the trackball camera to @p radius - * @param[in] radius The new radius of the trackball camera - */ - void setRadius( const float radius); - - /** - * @brief Gets the center point the trackball camera is looking at - * @return The center point of the trackball camera - */ - const glm::vec3& getCenter(); - - /** - * @brief Sets the current center point of the trackball camera to @p center - * @param[in] center The new center point of the trackball camera - */ - void setCenter(const glm::vec3 ¢er); - - /** - * @brief Sets the pitch value of the trackball camera to @p pitch - * @param[in] pitch The new pitch value of the trackball camera - */ - void setPitch(float pitch); - - /** - * @brief Sets the yaw value of the trackball camera to @p yaw - * @param[in] yaw The new yaw value of the trackball camera - */ - void setYaw(float yaw); - - /** - * @brief Changes the field of view of the trackball camera with an @p offset in degrees - * @param[in] offset The offset in degrees - */ - void changeFov(double offset); - - /** - * @brief Pans the view of the trackball camera according to the pitch and yaw values and additional offsets @p xOffset and @p yOffset (e.g. taken from mouse movement) - * @param[in] xOffset The offset added to the yaw value - * @param[in] yOffset The offset added to the pitch value - */ - void panView(double xOffset, double yOffset); - - /** - * @brief Updates the view matrix of the trackball camera with respect to @p deltatime - * @param deltaTime The time that has passed since last update - * @return The updated view matrix of the trackball camera - */ - glm::mat4 updateView(double deltaTime); - - /** - * @brief Updates the position of the trackball camera with respect to @p deltaTime - * @param[in] deltaTime The time that has passed since last update - */ - void updatePosition(double deltaTime); - }; - -} \ No newline at end of file diff --git a/modules/camera/include/vkcv/camera/TrackballCameraController.hpp b/modules/camera/include/vkcv/camera/TrackballCameraController.hpp new file mode 100644 index 0000000000000000000000000000000000000000..31aecf13538db03b86d7005dded488fa9970cb70 --- /dev/null +++ b/modules/camera/include/vkcv/camera/TrackballCameraController.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include "CameraController.hpp" + +namespace vkcv { + + /** + * @brief Used to orbit a camera around its center point. + */ + class TrackballCameraController final : public CameraController { + private: + bool m_rotationActive; + + float m_cameraSpeed; + float m_scrollSensitivity; + float m_radius; + + + /** + * @brief Updates the position of the camera. + * @return The updated camera position. + */ + glm::vec3 updatePosition(); + + /** + * @brief Updates the view matrix of the camera. + * @return The updated view matrix of the camera. + */ + glm::mat4 updateView(); + + /** + * @brief Updates the current radius in respect to the @p offset. + * @param offset The offset between the old and new radius. + */ + void updateRadius(double offset); + + public: + + /** + * @brief The default constructor of the #TrackballCameraController. + */ + TrackballCameraController(); + + /** + * @brief The destructor of the #TrackballCameraController (default behavior). + */ + ~TrackballCameraController() = default; + + /** + * @brief Sets @p radius as the new radius for orbiting around the camera's center point. + * @param radius The new radius. + */ + void setRadius(const float radius); + + /** + * @brief Pans the view of the camera according to the pitch and yaw values and additional offsets @p xOffset + * and @p yOffset. + * @param[in] xOffset The offset added to the yaw value. + * @param[in] yOffset The offset added to the pitch value. + */ + void panView(double xOffset, double yOffset); + + /** + * @brief Updates the camera object in respect to @p deltaTime. + * @param deltaTime The time that has passed since last update. + */ + void updateCamera(double deltaTime); + + /** + * @brief A callback function for key events. Currently, the trackball camera does not support camera movement. + * It can only orbit around its center point. + * @param[in] key The keyboard key. + * @param[in] scancode The platform-specific scancode. + * @param[in] action The key action. + * @param[in] mods The modifier bits. + */ + void keyCallback(int key, int scancode, int action, int mods); + + /** + * @brief A callback function for mouse scrolling events. Currently, this leads to changes in the field of view + * of the camera object. + * @param[in] offsetX The offset in horizontal direction. + * @param[in] offsetY The offset in vertical direction. + */ + void scrollCallback(double offsetX, double offsetY); + + /** + * @brief A callback function for mouse movement events. Currently, this leads to panning the view of the + * camera, if #mouseButtonCallback(int button, int action, int mods) enabled panning. + * @param[in] x The horizontal mouse position. + * @param[in] y The vertical mouse position. + */ + void mouseMoveCallback(double x, double y); + + /** + * @brief A callback function for mouse button events. Currently, the right mouse button enables panning the + * view of the camera as long as it is pressed. + * @param[in] button The mouse button. + * @param[in] action The button action. + * @param[in] mods The modifier bits. + */ + void mouseButtonCallback(int button, int action, int mods); + + }; + +} \ No newline at end of file diff --git a/modules/camera/src/vkcv/camera/Camera.cpp b/modules/camera/src/vkcv/camera/Camera.cpp index dfda62db1633edf1595cb77b91923f3ea05af789..f721b7e2a38a47533a0775f50b9de294099a2107 100644 --- a/modules/camera/src/vkcv/camera/Camera.cpp +++ b/modules/camera/src/vkcv/camera/Camera.cpp @@ -3,35 +3,23 @@ namespace vkcv { - Camera::Camera(){ + Camera::Camera() { + m_position = glm::vec3(0.0f, 0.0f, -1.0f); m_up = glm::vec3(0.0f, 1.0f, 0.0f); - m_position = glm::vec3(0.0f, 0.0f, 0.0f); - m_cameraSpeed = 2.f; - - m_pitch = 0.0; - m_yaw = 180.0; - - m_fov_nsteps = 100; - m_fov_min = 10; - m_fov_max = 120; - - m_forward = false; - m_backward = false; - m_left = false; - m_right = false; - m_top = false; - m_bottom = false; + m_center = glm::vec3(0.0f, 0.0f, 0.0f); + lookAt(m_position, m_center, m_up); + glm::vec3 front = glm::normalize(m_center - m_position); + m_pitch = atan2(front.y, sqrt(front.x * front.x + front.z * front.z)); + m_yaw = atan2(front.x, front.z); } Camera::~Camera() = default; void Camera::lookAt(glm::vec3 position, glm::vec3 center, glm::vec3 up){ m_view = glm::lookAt(position, center, up); - } - - glm::mat4 Camera::updateView(double deltaTime){ - updatePosition(deltaTime); - return m_view = glm::lookAt(m_position, m_position + getFront() , m_up); + m_position = position; + m_up = up; + m_center = center; } void Camera::getNearFar( float &near, float &far) const { @@ -39,12 +27,11 @@ namespace vkcv { far = m_far; } - - const glm::mat4& Camera::getView() { + glm::mat4& Camera::getView() { return m_view; } - const glm::mat4& Camera::getProjection() { + glm::mat4& Camera::getProjection() { return m_projection; } @@ -52,7 +39,11 @@ namespace vkcv { m_projection = projection; } - float Camera::getFov() const { + glm::mat4 Camera::getMVP() const { + return m_projection * m_view; + } + + const float Camera::getFov() const { return m_fov; } @@ -61,29 +52,15 @@ namespace vkcv { setPerspective( m_fov, m_ratio, m_near, m_far); } - void Camera::changeFov(double offset){ - float fov = m_fov; - float fov_range = m_fov_max - m_fov_min; - float fov_stepsize = glm::radians(fov_range)/m_fov_nsteps; - fov -= (float) offset*fov_stepsize; - if (fov < glm::radians(m_fov_min)) { - fov = glm::radians(m_fov_min); - } - if (fov > glm::radians(m_fov_max)) { - fov = glm::radians(m_fov_max); - } - setFov(fov); + float Camera::getRatio() const { + return m_ratio; } - void Camera::updateRatio( float ratio){ + void Camera::setRatio(float ratio){ m_ratio = ratio; setPerspective( m_fov, m_ratio, m_near, m_far); } - float Camera::getRatio() const { - return 0.0f; - } - void Camera::setNearFar( float near, float far){ m_near = near; m_far = far; @@ -114,8 +91,12 @@ namespace vkcv { m_position = position; } - void Camera::setUp(const glm::vec3 &up) { - m_up = up; + glm::vec3 Camera::getCenter() const { + return m_center; + } + + void Camera::setCenter(glm::vec3 center) { + m_center = center; } float Camera::getPitch() const { @@ -123,12 +104,6 @@ namespace vkcv { } void Camera::setPitch(float pitch) { - if (pitch > 89.0f) { - pitch = 89.0f; - } - if (pitch < -89.0f) { - pitch = -89.0f; - } m_pitch = pitch; } @@ -137,50 +112,15 @@ namespace vkcv { } void Camera::setYaw(float yaw) { - if (yaw < 0.0f) { - yaw += 360.0f; - } - else if (yaw > 360.0f) { - yaw -= 360.0f; - } m_yaw = yaw; } - void Camera::panView(double xOffset, double yOffset) { - setYaw(m_yaw + xOffset); - setPitch(m_pitch + yOffset); - } - - void Camera::updatePosition(double deltaTime ){ - m_position += (m_cameraSpeed * getFront() * static_cast<float> (m_forward) * static_cast<float>(deltaTime)); - m_position -= (m_cameraSpeed * getFront() * static_cast<float> (m_backward) * static_cast<float>(deltaTime)); - m_position += (glm::normalize(glm::cross(getFront(), m_up)) * m_cameraSpeed * static_cast<float> (m_left) * static_cast<float>(deltaTime)); - m_position -= (glm::normalize(glm::cross(getFront(), m_up)) * m_cameraSpeed * static_cast<float> (m_right) * static_cast<float>(deltaTime)); - m_position -= m_up * m_cameraSpeed * static_cast<float> (m_top) * static_cast<float>(deltaTime); - m_position += m_up * m_cameraSpeed * static_cast<float> (m_bottom) * static_cast<float>(deltaTime); - } - - void Camera::moveForward(int action){ - m_forward = static_cast<bool>(action); - } - - void Camera::moveBackward(int action){ - m_backward = static_cast<bool>(action); + glm::vec3 Camera::getUp() const { + return m_up; } - void Camera::moveLeft(int action){ - m_left = static_cast<bool>(action); - } - - void Camera::moveRight(int action){ - m_right = static_cast<bool>(action); - } - - void Camera::moveTop(int action){ - m_top = static_cast<bool>(action); + void Camera::setUp(const glm::vec3 &up) { + m_up = up; } - void Camera::moveBottom(int action){ - m_bottom = static_cast<bool>(action); - } } \ No newline at end of file diff --git a/modules/camera/src/vkcv/camera/CameraController.cpp b/modules/camera/src/vkcv/camera/CameraController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..477d938077cd532dd70f572e7694df8929acccfd --- /dev/null +++ b/modules/camera/src/vkcv/camera/CameraController.cpp @@ -0,0 +1,29 @@ +#include "vkcv/camera/CameraController.hpp" + +namespace vkcv { + + Camera& CameraController::getCamera() { + return *m_camera; + } + + void CameraController::setCamera(Camera &camera) { + m_camera = &camera; + } + + void CameraController::setWindow(Window &window) { + m_window = &window; + m_lastX = m_window->getWidth() / 2.0; + m_lastY = m_window->getHeight() / 2.0; + } + + void CameraController::updateCamera(double deltaTime) {} + + void CameraController::keyCallback(int key, int scancode, int action, int mods) {} + + void CameraController::scrollCallback( double offsetX, double offsetY) {} + + void CameraController::mouseMoveCallback(double offsetX, double offsetY) {} + + void CameraController::mouseButtonCallback(int button, int action, int mods) {} + +} \ No newline at end of file diff --git a/modules/camera/src/vkcv/camera/CameraManager.cpp b/modules/camera/src/vkcv/camera/CameraManager.cpp index 1358d39fd3f0d7a15ff67c9917bbc6bc7c13ead3..35556abb8c86042fee41dfc5f18fdf988028b3bf 100644 --- a/modules/camera/src/vkcv/camera/CameraManager.cpp +++ b/modules/camera/src/vkcv/camera/CameraManager.cpp @@ -3,95 +3,129 @@ namespace vkcv{ - CameraManager::CameraManager(Window &window, float width, float height, glm::vec3 up, glm::vec3 position): - m_window(window), m_width(width), m_height(height) + CameraManager::CameraManager(Window &window, float width, float height) + : m_window(window) { - m_camera.setUp(up); - m_camera.setPosition(position); - m_camera.setPerspective( glm::radians(60.0f), m_width / m_height, 0.1f, 10.f); - m_trackball.setUp(up); - m_trackball.setPosition(position); - m_trackball.setPerspective( glm::radians(60.0f), m_width / m_height, 0.1f, 10.f); - m_lastX = width/2.0; - m_lastY = height/2.0; - bindCamera(); - } - - void CameraManager::bindCamera(){ + bindCameraToEvents(); + } + + CameraManager::~CameraManager() { + // free memory of allocated pointers (specified with 'new') + for (auto controller : m_controllers) { + delete controller; + } + + for (auto camera : m_cameras) { + delete camera; + } + } + + void CameraManager::bindCameraToEvents() { m_keyHandle = m_window.e_key.add( [&](int key, int scancode, int action, int mods) { this->keyCallback(key, scancode, action, mods); }); m_mouseMoveHandle = m_window.e_mouseMove.add( [&]( double offsetX, double offsetY) {this->mouseMoveCallback( offsetX, offsetY);} ); m_mouseScrollHandle = m_window.e_mouseScroll.add([&](double offsetX, double offsetY) {this->scrollCallback( offsetX, offsetY);} ); m_mouseButtonHandle = m_window.e_mouseButton.add([&] (int button, int action, int mods) {this->mouseButtonCallback( button, action, mods);}); + m_resizeHandle = m_window.e_resize.add([&](int width, int height) {this->resizeCallback(width, height);}); } - void CameraManager::mouseButtonCallback(int button, int action, int mods){ - if(button == GLFW_MOUSE_BUTTON_2 && m_rotationActive == false && action == GLFW_PRESS){ - glfwSetInputMode(m_window.getWindow(), GLFW_CURSOR, GLFW_CURSOR_DISABLED); - m_rotationActive = true; - }else if(button == GLFW_MOUSE_BUTTON_2 && m_rotationActive == true && action == GLFW_RELEASE){ - glfwSetInputMode(m_window.getWindow(), GLFW_CURSOR, GLFW_CURSOR_NORMAL); - m_rotationActive = false; + void CameraManager::resizeCallback(int width, int height) { + for (size_t i = 0; i < m_cameras.size(); i++) { + getCamera(i).setRatio(static_cast<float>(width) / static_cast<float>(height));; } } + void CameraManager::mouseButtonCallback(int button, int action, int mods){ + m_controllers[m_activeControllerIndex]->mouseButtonCallback(button, action, mods); + } + void CameraManager::mouseMoveCallback(double x, double y){ - float xoffset = x - m_lastX; - float yoffset = m_lastY - y; - m_lastX = x; - m_lastY = y; + m_controllers[m_activeControllerIndex]->mouseMoveCallback(x, y); + } - if(!m_rotationActive){ - return; - } + void CameraManager::scrollCallback(double offsetX, double offsetY) { + m_controllers[m_activeControllerIndex]->scrollCallback(offsetX, offsetY); + } - float sensitivity = 0.05f; - xoffset *= sensitivity; - yoffset *= sensitivity; + void CameraManager::keyCallback(int key, int scancode, int action, int mods) { + switch (action) { + case GLFW_RELEASE: + switch (key) { + case GLFW_KEY_TAB: + if (m_activeControllerIndex + 1 == m_controllers.size()) { + m_activeControllerIndex = 0; + } + else { + m_activeControllerIndex++; + } + return; + case GLFW_KEY_ESCAPE: + glfwSetWindowShouldClose(m_window.getWindow(), 1); + return; + } + default: + m_controllers[m_activeControllerIndex]->keyCallback(key, scancode, action, mods); + } + } - m_camera.panView( xoffset , yoffset ); - m_trackball.panView( xoffset , yoffset ); + int CameraManager::addCamera() { + m_cameras.push_back(new Camera()); // TODO: is there another way we can do this? + m_cameras.back()->setPerspective(glm::radians(60.0f), m_window.getWidth() / m_window.getHeight(), 0.1f, 10.0f); + return m_cameras.size() - 1; } - void CameraManager::scrollCallback(double offsetX, double offsetY) { - m_camera.changeFov(offsetY); - m_trackball.changeFov(offsetY); + Camera& CameraManager::getCamera(uint32_t cameraIndex) { + return *m_cameras[cameraIndex]; } - void CameraManager::keyCallback(int key, int scancode, int action, int mods) { - switch (key) { - case GLFW_KEY_W: - m_camera.moveForward(action); - break; - case GLFW_KEY_S: - m_camera.moveBackward(action); - break; - case GLFW_KEY_A: - m_camera.moveLeft(action); - break; - case GLFW_KEY_D: - m_camera.moveRight(action); - break; - case GLFW_KEY_E: - m_camera.moveTop(action); - break; - case GLFW_KEY_Q: - m_camera.moveBottom(action); - break; - case GLFW_KEY_ESCAPE: - glfwSetWindowShouldClose(m_window.getWindow(), 1); + + int CameraManager::addController(ControllerType controllerType, uint32_t cameraIndex) { + switch(controllerType) { + case ControllerType::PILOT: { + m_controllers.push_back(new PilotCameraController()); // TODO: is there another way we can do this? break; - default: + } + case ControllerType::TRACKBALL: { + m_controllers.push_back(new TrackballCameraController()); break; + } + case ControllerType::TRACE: { + // TODO: implement (Josch) + } } + + m_controllers.back()->setWindow(m_window); + + int controllerIndex = m_controllers.size() - 1; + bindCameraToController(cameraIndex, controllerIndex); + + if (controllerIndex == 0) { + setActiveController(0); + } + + return controllerIndex; } - Camera& CameraManager::getCamera(){ - return m_camera; + CameraController& CameraManager::getController(uint32_t controllerIndex) { + return *m_controllers[controllerIndex]; } - TrackballCamera& CameraManager::getTrackballCamera() { - return m_trackball; + void CameraManager::bindCameraToController(uint32_t cameraIndex, uint32_t controllerIndex) { + m_controllers[controllerIndex]->setCamera(*m_cameras[cameraIndex]); } + CameraController& CameraManager::getActiveController() { + return *m_controllers[m_activeControllerIndex]; + } + void CameraManager::setActiveController(uint32_t controllerIndex) { + m_activeControllerIndex = controllerIndex; + } + + void CameraManager::update(double deltaTime) { + m_controllers[m_activeControllerIndex]->updateCamera(deltaTime); + } + + void CameraManager::update(double deltaTime, uint32_t controllerIndex) { + m_controllers[controllerIndex]->updateCamera(deltaTime); + } } \ No newline at end of file diff --git a/modules/camera/src/vkcv/camera/PilotCameraController.cpp b/modules/camera/src/vkcv/camera/PilotCameraController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05bb6276503567a82c468c432f85ff44583aef3e --- /dev/null +++ b/modules/camera/src/vkcv/camera/PilotCameraController.cpp @@ -0,0 +1,176 @@ +#include "vkcv/camera/PilotCameraController.hpp" +#include <iostream> + +namespace vkcv { + + PilotCameraController::PilotCameraController() { + m_forward = false; + m_backward = false; + m_upward = false; + m_downward = false; + m_left = false; + m_right = false; + + m_rotationActive = false; + + m_cameraSpeed = 2.0f; + + m_fov_nsteps = 100; + m_fov_min = 10; + m_fov_max = 120; + + m_lastX = 0.0; + m_lastY = 0.0; + } + + void PilotCameraController::changeFov(double offset){ + float fov = m_camera->getFov(); + float fov_range = m_fov_max - m_fov_min; + float fov_stepsize = glm::radians(fov_range)/m_fov_nsteps; + fov -= (float) offset*fov_stepsize; + if (fov < glm::radians(m_fov_min)) { + fov = glm::radians(m_fov_min); + } + if (fov > glm::radians(m_fov_max)) { + fov = glm::radians(m_fov_max); + } + m_camera->setFov(fov); + } + + void PilotCameraController::panView(double xOffset, double yOffset) { + // handle yaw rotation + float yaw = m_camera->getYaw() + xOffset; + if (yaw < -180.0f) { + yaw += 360.0f; + } + else if (yaw > 180.0f) { + yaw -= 360.0f; + } + m_camera->setYaw(yaw); + + // handle pitch rotation + float pitch = m_camera->getPitch() - yOffset; + if (pitch > 89.0f) { + pitch = 89.0f; + } + if (pitch < -89.0f) { + pitch = -89.0f; + } + m_camera->setPitch(pitch); + } + + glm::mat4 PilotCameraController::updateView(double deltaTime){ + updatePosition(deltaTime); + glm::vec3 position = m_camera->getPosition(); + glm::vec3 front = m_camera->getFront(); + glm::vec3 up = m_camera->getUp(); + m_camera->lookAt(position, position + front, up); + return m_camera->getView(); + } + + glm::vec3 PilotCameraController::updatePosition(double deltaTime ){ + glm::vec3 position = m_camera->getPosition(); + glm::vec3 front = m_camera->getFront(); + glm::vec3 up = m_camera->getUp(); + position += (m_cameraSpeed * front * static_cast<float> (m_forward) * static_cast<float>(deltaTime)); + position -= (m_cameraSpeed * front * static_cast<float> (m_backward) * static_cast<float>(deltaTime)); + position += (glm::normalize(glm::cross(front, up)) * m_cameraSpeed * static_cast<float> (m_left) * static_cast<float>(deltaTime)); + position -= (glm::normalize(glm::cross(front, up)) * m_cameraSpeed * static_cast<float> (m_right) * static_cast<float>(deltaTime)); + position -= up * m_cameraSpeed * static_cast<float> (m_upward) * static_cast<float>(deltaTime); + position += up * m_cameraSpeed * static_cast<float> (m_downward) * static_cast<float>(deltaTime); + m_camera->setPosition(position); + return position; + } + + void PilotCameraController::setCamera(Camera &camera) { + m_camera = &camera; + m_camera->setYaw(180.0f); + } + + void PilotCameraController::updateCamera(double deltaTime) { + updateView(deltaTime); + } + + void PilotCameraController::keyCallback(int key, int scancode, int action, int mods) { + switch (key) { + case GLFW_KEY_W: + moveForward(action); + break; + case GLFW_KEY_S: + moveBackward(action); + break; + case GLFW_KEY_A: + moveLeft(action); + break; + case GLFW_KEY_D: + moveRight(action); + break; + case GLFW_KEY_E: + moveUpward(action); + break; + case GLFW_KEY_Q: + moveDownward(action); + break; + default: + break; + } + } + + void PilotCameraController::scrollCallback(double offsetX, double offsetY) { + changeFov(offsetY); + } + + void PilotCameraController::mouseMoveCallback(double x, double y) { + float xoffset = x - m_lastX; + float yoffset = m_lastY - y; + m_lastX = x; + m_lastY = y; + + if(!m_rotationActive){ + return; + } + + float sensitivity = 0.05f; + xoffset *= sensitivity; + yoffset *= sensitivity; + + panView(xoffset , yoffset); + } + + void PilotCameraController::mouseButtonCallback(int button, int action, int mods) { + if(button == GLFW_MOUSE_BUTTON_2 && m_rotationActive == false && action == GLFW_PRESS){ + glfwSetInputMode(m_window->getWindow(), GLFW_CURSOR, GLFW_CURSOR_DISABLED); + m_rotationActive = true; + } + else if(button == GLFW_MOUSE_BUTTON_2 && m_rotationActive == true && action == GLFW_RELEASE){ + glfwSetInputMode(m_window->getWindow(), GLFW_CURSOR, GLFW_CURSOR_NORMAL); + m_rotationActive = false; + } + } + + + void PilotCameraController::moveForward(int action){ + m_forward = static_cast<bool>(action); + } + + void PilotCameraController::moveBackward(int action){ + m_backward = static_cast<bool>(action); + } + + void PilotCameraController::moveLeft(int action){ + m_left = static_cast<bool>(action); + } + + void PilotCameraController::moveRight(int action){ + m_right = static_cast<bool>(action); + } + + void PilotCameraController::moveUpward(int action){ + m_upward = static_cast<bool>(action); + } + + void PilotCameraController::moveDownward(int action){ + m_downward = static_cast<bool>(action); + } + +} \ No newline at end of file diff --git a/modules/camera/src/vkcv/camera/TrackballCamera.cpp b/modules/camera/src/vkcv/camera/TrackballCamera.cpp deleted file mode 100644 index e99540e93f4c4530ba7bd17ea85436fffb30649b..0000000000000000000000000000000000000000 --- a/modules/camera/src/vkcv/camera/TrackballCamera.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "vkcv/camera/TrackballCamera.hpp" -#include <iostream> - -namespace vkcv { - - TrackballCamera::TrackballCamera() { - m_pitch = 0.0f; - m_yaw = 0.0f; - m_radius = 1.5f; - m_center = glm::vec3(0.0f,0.0f,0.0f); - m_cameraSpeed = 5.0f; - m_scrollSensitivity = 0.05f; - } - - TrackballCamera::~TrackballCamera() = default; - - float TrackballCamera::getRadius() const{ - return m_radius; - } - - void TrackballCamera::setRadius( const float radius) { - if (m_radius < 0.1f) { - m_radius = 0.1f; - } - m_radius = radius; - } - - const glm::vec3& TrackballCamera::getCenter() { - return m_center; - } - - void TrackballCamera::setCenter(const glm::vec3 ¢er) { - m_center = center; - } - - void TrackballCamera::setPitch(float pitch) { - if (pitch < 0.0f) { - pitch += 360.0f; - } - else if (pitch > 360.0f) { - pitch -= 360.0f; - } - m_pitch = pitch; - } - - void TrackballCamera::setYaw(float yaw) { - if (yaw < 0.0f) { - yaw += 360.0f; - } - else if (yaw > 360.0f) { - yaw -= 360.0f; - } - m_yaw = yaw; - } - - void TrackballCamera::changeFov(double offset) { - setRadius(m_radius - offset * m_scrollSensitivity); - } - - void TrackballCamera::panView(double xOffset, double yOffset) { - setYaw(m_yaw + xOffset * m_cameraSpeed); - setPitch(m_pitch + yOffset * m_cameraSpeed); - } - - glm::mat4 TrackballCamera::updateView(double deltaTime) { - updatePosition(deltaTime); - return m_view = glm::lookAt(m_position, m_center, m_up); - } - - void TrackballCamera::updatePosition(double deltaTime) { - glm::mat4 rotationY = glm::rotate(glm::mat4(1.0f), glm::radians(m_yaw), glm::vec3(0.0f, 1.0f, 0.0f)); - glm::mat4 rotationX = glm::rotate(rotationY, glm::radians(m_pitch), glm::vec3(1.0f, 0.0f, 0.0f)); - glm::vec3 translate = glm::vec3(0.0f,0.0f,m_radius); - translate = glm::vec3(rotationX * glm::vec4(translate, 0.0f)); - m_position = m_center + translate; - m_up = glm::vec3(rotationX * glm::vec4(glm::vec3(0.0f, 1.0f, 0.0f), 0.0f)); - } -} \ No newline at end of file diff --git a/modules/camera/src/vkcv/camera/TrackballCameraController.cpp b/modules/camera/src/vkcv/camera/TrackballCameraController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90673de37aff5c6b67196684d2941157d37ca3bc --- /dev/null +++ b/modules/camera/src/vkcv/camera/TrackballCameraController.cpp @@ -0,0 +1,111 @@ +#include "vkcv/camera/TrackballCameraController.hpp" + +namespace vkcv { + + TrackballCameraController::TrackballCameraController() { + m_rotationActive = false; + m_radius = 3.0f; + m_cameraSpeed = 2.5f; + m_scrollSensitivity = 0.05f; + } + + void TrackballCameraController::setRadius(const float radius) { + if (radius < 0.1f) { + m_radius = 0.1f; + } + else { + m_radius = radius; + } + } + + void TrackballCameraController::panView(double xOffset, double yOffset) { + // handle yaw rotation + float yaw = m_camera->getYaw() + xOffset * m_cameraSpeed; + if (yaw < 0.0f) { + yaw += 360.0f; + } + else if (yaw > 360.0f) { + yaw -= 360.0f; + } + m_camera->setYaw(yaw); + + // handle pitch rotation + float pitch = m_camera->getPitch() + yOffset * m_cameraSpeed; + if (pitch < 0.0f) { + pitch += 360.0f; + } + else if (pitch > 360.0f) { + pitch -= 360.0f; + } + m_camera->setPitch(pitch); + } + + glm::vec3 TrackballCameraController::updatePosition() { + float yaw = m_camera->getYaw(); + float pitch = m_camera->getPitch(); + glm::vec3 yAxis = glm::vec3(0.0f, 1.0f, 0.0f); + glm::vec3 xAxis = glm::vec3(1.0f, 0.0f, 0.0f); + + glm::mat4 rotationY = glm::rotate(glm::mat4(1.0f), glm::radians(yaw), yAxis); + glm::mat4 rotationX = glm::rotate(rotationY, glm::radians(pitch), xAxis); + glm::vec3 translate = glm::vec3(0.0f, 0.0f, m_radius); + translate = glm::vec3(rotationX * glm::vec4(translate, 0.0f)); + glm::vec3 center = m_camera->getCenter(); + glm::vec3 position = center +translate; + m_camera->setPosition(position); + glm::vec3 up = glm::vec3(rotationX * glm::vec4(glm::vec3(0.0f, 1.0f, 0.0f), 0.0f)); + m_camera->setUp(up); + return position; + } + + glm::mat4 TrackballCameraController::updateView() { + updatePosition(); + glm::vec3 position = m_camera->getPosition(); + glm::vec3 center = m_camera->getCenter(); + glm::vec3 up = m_camera->getUp(); + m_camera->lookAt(position, center, up); + return m_camera->getView(); + } + + void TrackballCameraController::updateRadius(double offset) { + setRadius(m_radius - offset * m_scrollSensitivity); + } + + void TrackballCameraController::updateCamera(double deltaTime) { + updateView(); + } + + void TrackballCameraController::keyCallback(int key, int scancode, int action, int mods) {} + + void TrackballCameraController::scrollCallback(double offsetX, double offsetY) { + updateRadius(offsetY); + } + + void TrackballCameraController::mouseMoveCallback(double x, double y) { + float xoffset = x - m_lastX; + float yoffset = m_lastY - y; + m_lastX = x; + m_lastY = y; + + if(!m_rotationActive){ + return; + } + + float sensitivity = 0.05f; + xoffset *= sensitivity; + yoffset *= sensitivity; + + panView(xoffset , yoffset); + } + + void TrackballCameraController::mouseButtonCallback(int button, int action, int mods) { + if(button == GLFW_MOUSE_BUTTON_2 && m_rotationActive == false && action == GLFW_PRESS){ + glfwSetInputMode(m_window->getWindow(), GLFW_CURSOR, GLFW_CURSOR_DISABLED); + m_rotationActive = true; + } + else if(button == GLFW_MOUSE_BUTTON_2 && m_rotationActive == true && action == GLFW_RELEASE){ + glfwSetInputMode(m_window->getWindow(), GLFW_CURSOR, GLFW_CURSOR_NORMAL); + m_rotationActive = false; + } + } +} \ No newline at end of file diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 93d8103d449ff6d3cccdee9298b816b0eb974b54..0fb352ac9ffb9ca79924499ba7e47a119ff4cf87 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -17,8 +17,6 @@ int main(int argc, const char** argv) { false ); - vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); - window.initEvents(); vkcv::Core core = vkcv::Core::create( @@ -140,17 +138,24 @@ int main(int argc, const char** argv) { setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) }; core.writeResourceDescription(set, 0, setWrites); - auto start = std::chrono::system_clock::now(); + vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); + uint32_t camIndex = cameraManager.addCamera(); + uint32_t controllerIndex = cameraManager.addController(vkcv::ControllerType::PILOT, camIndex); + + uint32_t camIndex2 = cameraManager.addCamera(); + uint32_t controllerIndex2 = cameraManager.addController(vkcv::ControllerType::TRACKBALL, camIndex2); + + + auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { core.beginFrame(); window.pollEvents(); auto end = std::chrono::system_clock::now(); auto deltatime = end - start; start = end; -// cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count()); -// const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); - cameraManager.getTrackballCamera().updateView(std::chrono::duration<double>(deltatime).count()); - const glm::mat4 mvp = cameraManager.getTrackballCamera().getProjection() * cameraManager.getTrackballCamera().getView(); + cameraManager.update(std::chrono::duration<double>(deltatime).count()); + glm::mat4 mvp = cameraManager.getActiveController().getCamera().getMVP(); + core.renderMesh( trianglePass, diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 5568a497a83be0f7b87f3d902020056886b8649f..1e8ae53ca14695970490c02c5d008455e35fcfc2 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -16,10 +16,6 @@ int main(int argc, const char** argv) { false ); - vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); - cameraManager.getTrackballCamera().setPosition(glm::vec3(0.0f,0.5f,0.0f)); - cameraManager.getTrackballCamera().setCenter(glm::vec3(0.0f,0.0f,-1.0f)); - window.initEvents(); vkcv::Core core = vkcv::Core::create( @@ -135,6 +131,18 @@ int main(int argc, const char** argv) { * * PipelineHandle trianglePipeline = core.CreatePipeline(trianglePipeline); */ + + vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); + uint32_t camIndex = cameraManager.addCamera(); + cameraManager.getCamera(camIndex).setPosition(glm::vec3(0.0f, 0.0f, 0.0f)); + cameraManager.getCamera(camIndex).setCenter(glm::vec3(0.0f, 0.0f, -1.0f)); + uint32_t controllerIndex = cameraManager.addController(vkcv::ControllerType::PILOT, camIndex); + + uint32_t camIndex2 = cameraManager.addCamera(); + cameraManager.getCamera(camIndex2).setPosition(glm::vec3(0.0f, 0.0f, 0.0f)); + cameraManager.getCamera(camIndex2).setCenter(glm::vec3(0.0f, 0.0f, -1.0f)); + uint32_t controllerIndex2 = cameraManager.addController(vkcv::ControllerType::TRACKBALL, camIndex2); + auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { @@ -143,10 +151,8 @@ int main(int argc, const char** argv) { auto end = std::chrono::system_clock::now(); auto deltatime = end - start; start = end; -// cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count()); -// const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); - cameraManager.getTrackballCamera().updateView(std::chrono::duration<double>(deltatime).count()); - const glm::mat4 mvp = cameraManager.getTrackballCamera().getProjection() * cameraManager.getTrackballCamera().getView(); + cameraManager.update(std::chrono::duration<double>(deltatime).count()); + glm::mat4 mvp = cameraManager.getActiveController().getCamera().getMVP(); core.renderMesh( trianglePass,