Commit 1bd7ed1e authored by Vanessa Karolek's avatar Vanessa Karolek
Browse files

[#42][Refactor] huge update - see body text

1) Now there is only one camera class (no inheritance anymore). Furthermore, the camera object is separated from camera controls and only manages camera specific information, such as the view matrix, projection matrix, the position, etc. Camera controls are now handled via camera controller objects.

2) The CameraManager now manages an arbitrary number of camera controllers, such as PilotCameraController or TrackballCameraController (TraceCameraController will be implemented soon!). Before you can use a camera object in your render loop, you need to add at least one camera. You do not have to use a camera controller to render something, but you need to implement camera movements yourself... If you want to CONTROL a camera object, you can make use of the existing camera controller objects. To create a controller, you need to add a camera controller object to the camera manager and specify which camera should be used for this controller. You can change the bound camera whenever you like to. To switch between all existing camera controllers, you can use the active controller in the render loop and change the cycle between all camera controllers via Tab.
See the example projects for an examplary application.

3) Currently, events are only handled for the active camera controller.

4) DISCUSSION: We use the 'new' keyword within the camera manager class. Unfortunately, we did not find any other way to create an object (such as the camera controller) inside the scope of one function and make use of the inheritance (only pointers seem to support this) or to refer to an object that updates everywhere where it is refered. To not lose the object at specified memory location, we need to create it via 'new' and ensure that all allocated objects are deleted within the destructor of the camera manager. Find this lines at the 'TODO' marked locations. If you have a better idea to solve this problem, please let us know. :)
parent 9eb16366
Pipeline #25670 canceled with stages
......@@ -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
......
......@@ -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);
};
}
#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
#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);
};
}
#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.