Program Listing for File camera.hpp

Return to documentation for file (inexor/vulkan-renderer/camera.hpp)

#pragma once

#include <glm/gtc/matrix_transform.hpp>
#include <glm/vec3.hpp>

#include <algorithm>
#include <array>
#include <vector>

namespace inexor::vulkan_renderer {

namespace directions {
constexpr glm::vec3 DEFAULT_FRONT{1.0f, 0.0f, 0.0f};
constexpr glm::vec3 DEFAULT_RIGHT{0.0f, 1.0f, 0.0f};
constexpr glm::vec3 DEFAULT_UP{0.0f, 0.0f, 1.0f};
} // namespace directions

enum class CameraMovement { FORWARD, BACKWARD, LEFT, RIGHT };

// TODO: Implement more camera types.
enum class CameraType { LOOK_AT };

class Camera {
private:
    CameraType m_type{CameraType::LOOK_AT};
    glm::vec3 m_position{0.0f, 0.0f, 0.0f};
    glm::vec3 m_front{directions::DEFAULT_FRONT};
    glm::vec3 m_right{directions::DEFAULT_RIGHT};
    glm::vec3 m_up{directions::DEFAULT_UP};
    glm::vec3 m_world_up{directions::DEFAULT_UP};
    glm::mat4 m_view_matrix{};
    glm::mat4 m_perspective_matrix{};

    float m_yaw{0.0f};
    float m_roll{0.0f};
    float m_pitch{0.0f};
    float m_pitch_min{-89.0f};
    float m_pitch_max{+89.0f};
    float m_fov{90.0f};
    float m_fov_max{90.0f};
    float m_fov_min{20.0f};
    float m_zoom_step{10.0f};
    float m_rotation_speed{1.0f};
    float m_movement_speed{2.0f};
    float m_aspect_ratio{1920.0f / 1080.0f};
    float m_mouse_sensitivity{0.005f};
    float m_near_plane{0.001f};
    float m_far_plane{1000.0f};

    std::array<bool, 4> m_keys{false, false, false, false};

    float m_vertical_fov{0.0f};

    bool m_update_vertical_fov{false};
    bool m_update_view_matrix{false};
    bool m_update_perspective_matrix{false};

    void update_vectors();

    void update_matrices();

    [[nodiscard]] bool is_moving() const;

public:
    Camera(const glm::vec3 &position, float yaw, float pitch, float window_width, float window_height);

    // TODO: Add more overloaded constructors.

    void set_type(CameraType type);

    [[nodiscard]] const CameraType &type() const {
        return m_type;
    }

    void set_movement_state(CameraMovement key, bool pressed);

    void set_position(glm::vec3 position);

    [[nodiscard]] const glm::vec3 &position() const {
        return m_position;
    }

    void set_aspect_ratio(float width, float height);

    [[nodiscard]] float aspect_ratio() const {
        return m_aspect_ratio;
    }

    [[nodiscard]] float fov() const {
        return m_fov;
    }

    void set_movement_speed(float speed);

    [[nodiscard]] float movement_speed() const {
        return m_movement_speed;
    }

    void set_rotation_speed(float speed);

    [[nodiscard]] float rotation_speed() const {
        return m_rotation_speed;
    }

    void rotate(float delta_yaw, float delta_pitch, float delta_roll = 0.0f);

    void set_rotation(float yaw, float pitch, float roll);

    [[nodiscard]] const glm::vec3 &rotation() const {
        return m_front;
    }

    [[nodiscard]] float yaw() const {
        return m_yaw;
    }

    [[nodiscard]] float pitch() const {
        return m_pitch;
    }

    [[nodiscard]] float roll() const {
        return m_roll;
    }

    [[nodiscard]] const glm::vec3 &front() const {
        return m_front;
    }

    [[nodiscard]] const glm::vec3 &up() const {
        return m_up;
    }

    [[nodiscard]] const glm::vec3 &right() const {
        return m_right;
    }

    void set_near_plane(float near_plane);

    [[nodiscard]] float near_plane() const {
        return m_near_plane;
    }

    void set_far_plane(float far_plane);

    [[nodiscard]] float far_plane() const {
        return m_far_plane;
    }

    void change_zoom(float offset);

    void update(float delta_time);

    [[nodiscard]] const glm::mat4 &view_matrix() {
        update_matrices();
        return m_view_matrix;
    }

    [[nodiscard]] const glm::mat4 &perspective_matrix() {
        update_matrices();
        return m_perspective_matrix;
    }
};
} // namespace inexor::vulkan_renderer