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 &center);
-
-        /**
-         * @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 &center) {
-        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,