diff --git a/meson.build b/meson.build index 806cc41..22fd378 100644 --- a/meson.build +++ b/meson.build @@ -37,7 +37,7 @@ deps += imgui_dep executable( 'graphics-test', - sources: files('src/main.cpp'), + sources: files('src/camera/camera.cpp', 'src/main.cpp'), include_directories: include_directories('include', is_system: true), dependencies: deps, ) \ No newline at end of file diff --git a/src/camera/camera.cpp b/src/camera/camera.cpp new file mode 100644 index 0000000..0e0620e --- /dev/null +++ b/src/camera/camera.cpp @@ -0,0 +1,98 @@ +#include "camera.hpp" + +#include "../util/constants.hpp" + +using namespace constants; + +Camera::Camera() + : mPosition(2.0, 2.0, 0.5), + mFront(glm::normalize(glm::dvec3(0.0, 1.0, 0.0))), + mUp(0.0, 0.0, 1.0), + mRight(glm::normalize(glm::cross(mFront, glm::dvec3(0.0, 0.0, 1.0)))), + mYaw(180.0), + mPitch(0.0) { + updateCameraVectors(); +} + +fn Camera::getPosition() const -> glm::dvec3 { return mPosition; } + +fn Camera::getFront() const -> glm::dvec3 { return mFront; } + +fn Camera::getYaw() const -> f64 { return mYaw; } + +fn Camera::getPitch() const -> f64 { return mPitch; } + +fn Camera::getViewMatrix() const -> glm::mat4 { return glm::lookAt(mPosition, mPosition + mFront, mUp); } + +fn Camera::moveForward(f64 deltaTime) -> void { + // Project front vector onto horizontal plane by zeroing Z component + glm::dvec3 horizontalFront = mFront; + horizontalFront.z = 0.0; + horizontalFront = glm::normalize(horizontalFront); + mPosition += horizontalFront * CAMERA_SPEED * deltaTime; +} + +fn Camera::moveBackward(f64 deltaTime) -> void { + // Project front vector onto horizontal plane by zeroing Z component + glm::dvec3 horizontalFront = mFront; + horizontalFront.z = 0.0; + horizontalFront = glm::normalize(horizontalFront); + mPosition -= horizontalFront * CAMERA_SPEED * deltaTime; +} + +fn Camera::moveLeft(f64 deltaTime) -> void { + // Project right vector onto horizontal plane by zeroing Z component + glm::dvec3 horizontalRight = mRight; + horizontalRight.z = 0.0; + horizontalRight = glm::normalize(horizontalRight); + mPosition -= horizontalRight * CAMERA_SPEED * deltaTime; +} + +fn Camera::moveRight(f64 deltaTime) -> void { + // Project right vector onto horizontal plane by zeroing Z component + glm::dvec3 horizontalRight = mRight; + horizontalRight.z = 0.0; + horizontalRight = glm::normalize(horizontalRight); + mPosition += horizontalRight * CAMERA_SPEED * deltaTime; +} + +fn Camera::moveUp(f64 deltaTime) -> void { + mPosition += glm::dvec3(0.0, 0.0, 1.0) * CAMERA_SPEED * deltaTime; +} + +fn Camera::moveDown(f64 deltaTime) -> void { + mPosition -= glm::dvec3(0.0, 0.0, 1.0) * CAMERA_SPEED * deltaTime; +} + +fn Camera::rotate(f64 xoffset, double yoffset) -> void { + const f64 sensitivity = 0.1; + mYaw += xoffset * sensitivity; + mPitch += yoffset * sensitivity; + + // Clamp yaw to [-180, 180] range + if (mYaw > 180.0) + mYaw -= 360.0; + if (mYaw < -180.0) + mYaw += 360.0; + + // Constrain pitch to avoid camera flipping + if (mPitch > 89.0) + mPitch = 89.0; + if (mPitch < -89.0) + mPitch = -89.0; + + updateCameraVectors(); +} + +fn Camera::updateCameraVectors() -> void { + // Calculate new front vector + glm::dvec3 newFront; + newFront.x = cos(glm::radians(mYaw)) * cos(glm::radians(mPitch)); + newFront.y = sin(glm::radians(mYaw)) * cos(glm::radians(mPitch)); + newFront.z = sin(glm::radians(mPitch)); + + mFront = glm::normalize(newFront); + // Recalculate right and up vectors + mRight = glm::normalize(glm::cross(mFront, glm::dvec3(0.0, 0.0, 1.0))); + mUp = glm::normalize(glm::cross(mRight, mFront)); +} diff --git a/src/camera/camera.hpp b/src/camera/camera.hpp new file mode 100644 index 0000000..eee79f8 --- /dev/null +++ b/src/camera/camera.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +#include "../util/types.hpp" + +struct CameraInfo { + alignas(16) glm::vec3 position; ///< Camera position +}; + +/** + * @brief Camera class for handling 3D camera movement and perspective + */ +class Camera { + public: + Camera(); + + [[nodiscard]] fn getPosition() const -> glm::dvec3; + [[nodiscard]] fn getFront() const -> glm::dvec3; + [[nodiscard]] fn getYaw() const -> f64; + [[nodiscard]] fn getPitch() const -> f64; + [[nodiscard]] fn getViewMatrix() const -> glm::mat4; + + fn moveForward(f64 deltaTime) -> void; + fn moveBackward(f64 deltaTime) -> void; + fn moveLeft(f64 deltaTime) -> void; + fn moveRight(f64 deltaTime) -> void; + fn moveUp(f64 deltaTime) -> void; + fn moveDown(f64 deltaTime) -> void; + fn rotate(f64 xoffset, f64 yoffset) -> void; + + private: + fn updateCameraVectors() -> void; + + glm::dvec3 mPosition; + glm::dvec3 mFront; + glm::dvec3 mUp; + glm::dvec3 mRight; + f64 mYaw; + f64 mPitch; +}; diff --git a/src/main.cpp b/src/main.cpp index 2dc7720..e90aa96 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE // Include custom utility headers +#include "camera/camera.hpp" // Camera class #include "util/constants.hpp" // Constants definitions #include "util/crosshair.hpp" // Crosshair definitions #include "util/shaders.hpp" // Compiled shader code @@ -152,6 +153,8 @@ class VulkanApp { std::vector mCommandBuffers; ///< Command buffers for drawing commands + Camera mCamera; ///< Camera object + // Light settings struct { glm::vec3 position = glm::vec3(2.0F, 2.0F, 2.0F); @@ -232,113 +235,6 @@ class VulkanApp { alignas(4) float specular_strength; ///< Specular strength }; - struct CameraInfo { - alignas(16) glm::vec3 position; ///< Camera position - }; - - struct Camera { - glm::dvec3 position; - glm::dvec3 front; - glm::dvec3 up; - glm::dvec3 right; - f64 yaw; - f64 pitch; - - Camera() - : position(2.0, 2.0, 0.5), - front(glm::normalize(glm::dvec3(0.0, 1.0, 0.0))), - up(0.0, 0.0, 1.0), - right(glm::normalize(glm::cross(front, glm::dvec3(0.0, 0.0, 1.0)))), - yaw(180.0), - pitch(0.0) { - updateCameraVectors(); - } - - [[nodiscard]] fn getPosition() const -> glm::dvec3 { return position; } - - [[nodiscard]] fn getFront() const -> glm::dvec3 { return front; } - - [[nodiscard]] fn getYaw() const -> f64 { return yaw; } - - [[nodiscard]] fn getPitch() const -> f64 { return pitch; } - - [[nodiscard]] fn getViewMatrix() const -> glm::mat4 { - return glm::lookAt(position, position + front, up); - } - - fn moveForward(f64 deltaTime) -> void { - // Project front vector onto horizontal plane by zeroing Z component - glm::dvec3 horizontalFront = front; - horizontalFront.z = 0.0; - horizontalFront = glm::normalize(horizontalFront); - position += horizontalFront * CAMERA_SPEED * deltaTime; - } - - fn moveBackward(f64 deltaTime) -> void { - // Project front vector onto horizontal plane by zeroing Z component - glm::dvec3 horizontalFront = front; - horizontalFront.z = 0.0; - horizontalFront = glm::normalize(horizontalFront); - position -= horizontalFront * CAMERA_SPEED * deltaTime; - } - - fn moveLeft(f64 deltaTime) -> void { - // Project right vector onto horizontal plane by zeroing Z component - glm::dvec3 horizontalRight = right; - horizontalRight.z = 0.0; - horizontalRight = glm::normalize(horizontalRight); - position -= horizontalRight * CAMERA_SPEED * deltaTime; - } - - fn moveRight(f64 deltaTime) -> void { - // Project right vector onto horizontal plane by zeroing Z component - glm::dvec3 horizontalRight = right; - horizontalRight.z = 0.0; - horizontalRight = glm::normalize(horizontalRight); - position += horizontalRight * CAMERA_SPEED * deltaTime; - } - - fn moveUp(f64 deltaTime) -> void { position += glm::dvec3(0.0, 0.0, 1.0) * CAMERA_SPEED * deltaTime; } - - fn moveDown(f64 deltaTime) -> void { position -= glm::dvec3(0.0, 0.0, 1.0) * CAMERA_SPEED * deltaTime; } - - fn rotate(f64 xoffset, f64 yoffset) -> void { - const f64 sensitivity = 0.1; - yaw += xoffset * sensitivity; - pitch += yoffset * sensitivity; - - // Clamp yaw to [-180, 180] range - if (yaw > 180.0) - yaw -= 360.0; - if (yaw < -180.0) - yaw += 360.0; - - // Constrain pitch to avoid camera flipping - if (pitch > 89.0) - pitch = 89.0; - if (pitch < -89.0) - pitch = -89.0; - - updateCameraVectors(); - } - - private: - fn updateCameraVectors() -> void { - // Calculate new front vector - glm::dvec3 newFront; - newFront.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); - newFront.y = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); - newFront.z = sin(glm::radians(pitch)); - - front = glm::normalize(newFront); - // Recalculate right and up vectors - right = glm::normalize(glm::cross(front, glm::dvec3(0.0, 0.0, 1.0))); - up = glm::normalize(glm::cross(right, front)); - } - }; - - Camera mCamera; ///< Camera object - static fn processInput(vkfw::Window& window, Camera& camera, const f32& deltaTime, const f32& cameraSpeed) -> void { if (window.getKey(vkfw::Key::eW) == vkfw::eTrue)