From 1d0ec3330cee03b77b97da2d898b4c33782968b1 Mon Sep 17 00:00:00 2001 From: Benjamin Kyd Date: Sat, 29 Apr 2023 22:42:19 +0100 Subject: [PATCH] camera refactor --- libhart/scene/camera.hpp | 75 ++++++------ src/inferno.cpp | 42 ++++--- src/inferno.hpp | 17 ++- src/main.cpp | 2 +- src/scene/camera.cpp | 247 ++++++++++++++++++++------------------- 5 files changed, 194 insertions(+), 189 deletions(-) diff --git a/libhart/scene/camera.hpp b/libhart/scene/camera.hpp index 77213a0..3da09fe 100644 --- a/libhart/scene/camera.hpp +++ b/libhart/scene/camera.hpp @@ -3,56 +3,51 @@ #include #include +#include #include -namespace inferno { +namespace inferno::graphics { -class Camera { -public: - Camera(); - Camera(int w, int h); +struct _CameraImpl; - void update(); - bool didUpdate(); - void newFrame(); +typedef struct Camera { + glm::mat4 ViewMatrix; + glm::mat4 ProjectionMatrix; + glm::mat4 LookMatrix; + float MouseSensitivity = 0.4f; + float CameraSpeed = 0.1f; + float Roll, Pitch, Yaw; + float FOV = 45.0f; + glm::vec3 Position = {}; + glm::vec3 LookDirection = {}; - glm::mat4 getViewMatrix(); - glm::mat4 getProjectionMatrix(); - glm::mat4 getCameraLook(); + std::unique_ptr<_CameraImpl> _impl; +} Camera; - void setRasterViewport(glm::vec2 viewport); +std::unique_ptr camera_create(); +void camera_cleanup(std::unique_ptr& camera); - // Keyboard - void moveCamera(uint8_t posDelta); - // Mouse Delta - void mouseMoved(glm::vec2 mouseDelta); +void camera_update(std::unique_ptr& camera); +void camera_did_update(std::unique_ptr& camera); +void camera_new_frame(std::unique_ptr& camera); - void setPosition(glm::vec3 position); - void setEulerLook(float roll, float pitch, float yaw); - void setLook(glm::vec3 lookDirection); +glm::mat4 camera_get_view(std::unique_ptr& camera); +glm::mat4 camera_get_projection(std::unique_ptr& camera); +glm::mat4 camera_get_look(std::unique_ptr& camera); -public: - void setRayViewport(glm::vec2 viewport); - glm::vec2 getRayViewport(); +void raster_set_viewport(std::unique_ptr& camera, glm::ivec2 viewport); +glm::ivec2 raster_get_viewport(std::unique_ptr& camera); -public: - // necessary evil - float MouseSensitivity = 0.4f; - float CameraSpeed = 0.1f; - float Roll, Pitch, Yaw; - float FOV = 45.0f; - glm::vec3 Position = {}; - glm::vec3 LookDirection = {}; +void ray_set_viewport(std::unique_ptr& camera, glm::ivec2 viewport); +glm::ivec2 ray_get_viewport(std::unique_ptr& camera); -private: - glm::vec2 mViewport = { 100.0f, 100.0f }; - glm::vec2 mRayViewport = { 200.0f, 200.0f }; - glm::mat4 mViewMatrix = {}; - glm::mat4 mProjMatrix = {}; - glm::mat4 mCameraLook = {}; - bool mDidUpdate; +void camera_move(std::unique_ptr& camera, uint8_t movement_delta); +void camera_mouse_move(std::unique_ptr& camera, glm::vec2 mouse_delta); - std::mutex _mCam; -}; +void camera_set_position(std::unique_ptr& camera, glm::vec3 position); +void camera_set_euler_look(std::unique_ptr& camera, float roll, + float pitch, float yaw); +void camera_set_look(std::unique_ptr& camera, + glm::vec3 look_direction); -} +} // namespace inferno::graphics diff --git a/src/inferno.cpp b/src/inferno.cpp index 43900ad..ec10ab1 100644 --- a/src/inferno.cpp +++ b/src/inferno.cpp @@ -25,20 +25,24 @@ namespace inferno { -InfernoApp* inferno_create() +std::unique_ptr inferno_create() { // MOTD yolo::info("INFERNO HART v" INFERNO_VERSION); - InfernoApp* app = new InfernoApp(); + std::unique_ptr app = std::make_unique(); + app->Input = std::make_unique(); // Create window graphics::window_create("Inferno v" INFERNO_VERSION, 1280, 720); + return app; } -void inferno_cleanup(InfernoApp* app) +void inferno_cleanup(std::unique_ptr& app) { + graphics::window_cleanup(); + app.reset(); } static void inferno_gui_help_marker(const char* desc) @@ -53,7 +57,7 @@ static void inferno_gui_help_marker(const char* desc) } } -void inferno_preset_gui(InfernoApp* app) +void inferno_preset_gui(std::unique_ptr& app) { ImGuiID dockspace_id = ImGui::GetID("main"); @@ -70,7 +74,7 @@ void inferno_preset_gui(InfernoApp* app) yolo::info("LAYOUT SET TO DEFAULT"); } -void inferno_move_input(InfernoApp* app) +void inferno_move_input(std::unique_ptr& app) { static GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR); glfwSetCursor(graphics::window_get_glfw_window(), cursor); @@ -109,13 +113,13 @@ void inferno_move_input(InfernoApp* app) app->Input->MovementDelta |= 0b00000100; } -void inferno_stop_move_input(InfernoApp* app) +void inferno_stop_move_input(std::unique_ptr& app) { app->Input->MovementDelta = 0x0; app->Input->MouseDelta = { 0.0f, 0.0f }; } -int inferno_run(InfernoApp* app) +int inferno_run(std::unique_ptr& app) { while (true) { @@ -152,25 +156,25 @@ int inferno_run(InfernoApp* app) ImGui::EndMenuBar(); } - if (showPreview && ImGui::Begin("Preview", nullptr, ImGuiWindowFlags_NoScrollbar)) - { - if (ImGui::IsWindowHovered()) - { + if (showPreview && ImGui::Begin("Preview", nullptr, ImGuiWindowFlags_NoScrollbar)) { + if (ImGui::IsWindowHovered()) { inferno_move_input(app); - } else - { + } else { inferno_stop_move_input(app); } - if (glm::length(app->Input->MouseDelta) > 0.0f) camera.mouseMoved(mouseDelta); - if (movementDelta != 0b00000000) camera.moveCamera(movementDelta); + if (glm::length(app->Input->MouseDelta) > 0.0f) + camera.mouseMoved(app->Input->MouseDelta); + if (app->Input->MovementDelta != 0b00000000) + camera.moveCamera(app->Input->MovementDelta); - camera.setRasterViewport({ImGui::GetWindowSize().x, ImGui::GetWindowSize().y}); - mRasterRenderer->setTargetSize({ImGui::GetWindowSize().x, ImGui::GetWindowSize().y}); + camera.setRasterViewport({ ImGui::GetWindowSize().x, ImGui::GetWindowSize().y }); + mRasterRenderer->setTargetSize({ ImGui::GetWindowSize().x, ImGui::GetWindowSize().y }); mRasterRenderer->prepare(); mRasterRenderer->draw(); - ImGui::Image((ImTextureID)mRasterRenderer->getRenderedTexture(), + + ImGui::Image((ImTextureID)mRasterRenderer->getRenderedTexture(),inderno { mRasterRenderer->getTargetSize().x, mRasterRenderer->getTargetSize().y }, - ImVec2(0,1), ImVec2(1,0)); + ImVec2(0, 1), ImVec2(1, 0)); glBindFramebuffer(GL_FRAMEBUFFER, 0); ImGui::End(); } diff --git a/src/inferno.hpp b/src/inferno.hpp index 1b49a03..df8b222 100644 --- a/src/inferno.hpp +++ b/src/inferno.hpp @@ -6,23 +6,20 @@ namespace inferno { -class Window; -class HHM; - typedef struct InfernoInput { glm::vec2 MouseDelta; uint8_t MovementDelta; } InfernoInput; typedef struct InfernoApp { - InfernoInput* Input; + std::unique_ptr Input; } InfernoApp; -InfernoApp* inferno_create(); -void inferno_cleanup(InfernoApp* app); -void inferno_preset_gui(InfernoApp* app); -void inferno_move_input(InfernoApp* app); -void inferno_stop_move_input(InfernoApp* app); -int inferno_run(InfernoApp* app); +std::unique_ptr inferno_create(); +void inferno_cleanup(std::unique_ptr& app); +void inferno_preset_gui(std::unique_ptr& app); +void inferno_move_input(std::unique_ptr& app); +void inferno_stop_move_input(std::unique_ptr& app); +int inferno_run(std::unique_ptr& app); } diff --git a/src/main.cpp b/src/main.cpp index b082c79..85bd1d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,6 @@ int main(int argc, char** argv) { - auto* inferno = inferno::inferno_create(); + std::unique_ptr inferno = inferno::inferno_create(); return inferno::inferno_run(inferno); } diff --git a/src/scene/camera.cpp b/src/scene/camera.cpp index 2d37c2a..76def99 100644 --- a/src/scene/camera.cpp +++ b/src/scene/camera.cpp @@ -1,205 +1,214 @@ #include -using namespace inferno; +namespace inferno::graphics { -Camera::Camera() +typedef struct _CameraImpl { + glm::ivec2 Viewport = { 100, 100 }; + glm::ivec2 RayViewport = { 200, 200 }; + bool DidUpdate; + std::mutex CamMutex; +} _CameraImpl; + +std::unique_ptr camera_create() { - mProjMatrix = glm::perspective( glm::radians(FOV), 1.0f, 0.1f, 1000.0f ); + std::unique_ptr camera = std::make_unique(); + camera->_impl = std::make_unique<_CameraImpl>(); - Roll = 0.0f; - Pitch = 0.0f; - Yaw = 0.0f; + camera->ProjectionMatrix = glm::perspective( + glm::radians(camera->FOV), + 1.0f, + 0.1f, + 1000.0f); + camera->ViewMatrix = {}; - Position = {}; - LookDirection = {}; + camera->Roll = 0.0f; + camera->Pitch = 0.0f; + camera->Yaw = 0.0f; - mViewMatrix = {}; + camera->Position = {}; + camera->LookDirection = {}; - update(); + camera_update(camera); + return camera; } -Camera::Camera(int w, int h) +void camera_cleanup(std::unique_ptr& camera) { - mProjMatrix = glm::perspective(glm::radians(FOV), (float)w / (float)h, 0.1f, 1000.0f); - - Roll = 0.0f; - Pitch = 0.0f; - Yaw = 0.0f; - - Position = {}; - LookDirection = {}; - - mViewMatrix = {}; - - update(); + camera->_impl.reset(); + camera.reset(); } -void Camera::update() +void camera_update(std::unique_ptr& camera) { - glm::mat4 matRoll = glm::mat4(1.0f); - glm::mat4 matPitch = glm::mat4(1.0f); - glm::mat4 matYaw = glm::mat4(1.0f); + glm::mat4 matRoll = glm::mat4(1.0f); + glm::mat4 matPitch = glm::mat4(1.0f); + glm::mat4 matYaw = glm::mat4(1.0f); - matRoll = glm::rotate(matRoll, Roll, glm::vec3(0.0f, 0.0f, 1.0f)); - matPitch = glm::rotate(matPitch, Pitch, glm::vec3(1.0f, 0.0f, 0.0f)); - matYaw = glm::rotate(matYaw, Yaw, glm::vec3( 0.0f, 1.0f, 0.0f)); + matRoll = glm::rotate(matRoll, Roll, glm::vec3(0.0f, 0.0f, 1.0f)); + matPitch = glm::rotate(matPitch, Pitch, glm::vec3(1.0f, 0.0f, 0.0f)); + matYaw = glm::rotate(matYaw, Yaw, glm::vec3(0.0f, 1.0f, 0.0f)); - glm::mat4 rotate = matRoll * matPitch * matYaw; - mCameraLook = rotate; + glm::mat4 rotate = matRoll * matPitch * matYaw; + mCameraLook = rotate; - glm::mat4 translate = glm::mat4(1.0f); - translate = glm::translate(translate, -Position); + glm::mat4 translate = glm::mat4(1.0f); + translate = glm::translate(translate, -Position); - std::lock_guard lock(this->_mCam); + std::lock_guard lock(this->_mCam); - mViewMatrix = rotate * translate; - mProjMatrix = glm::perspective(glm::radians(FOV), mViewport.x / mViewport.y, 0.1f, 1000.0f); + mViewMatrix = rotate * translate; + mProjMatrix = glm::perspective(glm::radians(FOV), mViewport.x / mViewport.y, 0.1f, 1000.0f); - // Work out Look Vector - glm::mat4 inverseView = glm::inverse(mViewMatrix); + // Work out Look Vector + glm::mat4 inverseView = glm::inverse(mViewMatrix); - LookDirection.x = inverseView[2][0]; - LookDirection.y = inverseView[2][1]; - LookDirection.z = inverseView[2][2]; + LookDirection.x = inverseView[2][0]; + LookDirection.y = inverseView[2][1]; + LookDirection.z = inverseView[2][2]; - mDidUpdate = true; + mDidUpdate = true; } bool Camera::didUpdate() { - std::lock_guard lock(this->_mCam); - return mDidUpdate; + std::lock_guard lock(this->_mCam); + return mDidUpdate; } void Camera::newFrame() { - std::lock_guard lock(this->_mCam); - mDidUpdate = false; + std::lock_guard lock(this->_mCam); + mDidUpdate = false; } glm::mat4 Camera::getViewMatrix() { - std::lock_guard lock(this->_mCam); - return mViewMatrix; + std::lock_guard lock(this->_mCam); + return mViewMatrix; } glm::mat4 Camera::getProjectionMatrix() { - std::lock_guard lock(this->_mCam); - return mProjMatrix; + std::lock_guard lock(this->_mCam); + return mProjMatrix; } glm::mat4 Camera::getCameraLook() { - std::lock_guard lock(this->_mCam); - return mCameraLook; + std::lock_guard lock(this->_mCam); + return mCameraLook; } void Camera::setRasterViewport(glm::vec2 viewport) { - std::lock_guard lock(this->_mCam); - mViewport = viewport; - mProjMatrix = glm::perspective(glm::radians(FOV), (float)viewport.x / (float)viewport.y, 0.1f, 1000.0f); + std::lock_guard lock(this->_mCam); + mViewport = viewport; + mProjMatrix = glm::perspective(glm::radians(FOV), (float)viewport.x / (float)viewport.y, 0.1f, 1000.0f); } void Camera::moveCamera(uint8_t posDelta) { - if (posDelta == 0) return; + if (posDelta == 0) + return; - // Rotate by camera direction - glm::vec3 delta(0.0f); - - glm::mat2 rotate { - cos(Yaw), -sin(Yaw), - sin(Yaw), cos(Yaw) - }; + // Rotate by camera direction + glm::vec3 delta(0.0f); - glm::vec2 f(0.0, 1.0); - f = f * rotate; + glm::mat2 rotate { + cos(Yaw), -sin(Yaw), + sin(Yaw), cos(Yaw) + }; - if (posDelta & 0x80) { - delta.z -= f.y; - delta.x -= f.x; - } - if (posDelta & 0x20) { - delta.z += f.y; - delta.x += f.x; - } - if (posDelta & 0x40) { - delta.z += f.x; - delta.x += -f.y; - } - if (posDelta & 0x10) { - delta.z -= f.x; - delta.x -= -f.y; - } - if (posDelta & 0x8) { - delta.y += 1; - } - if (posDelta & 0x4) { - delta.y -= 1; - } + glm::vec2 f(0.0, 1.0); + f = f * rotate; - // get current view matrix - glm::mat4 mat = getViewMatrix(); - glm::vec3 forward(mat[0][2], mat[1][2], mat[2][2]); - glm::vec3 strafe(mat[0][0], mat[1][0], mat[2][0]); + if (posDelta & 0x80) { + delta.z -= f.y; + delta.x -= f.x; + } + if (posDelta & 0x20) { + delta.z += f.y; + delta.x += f.x; + } + if (posDelta & 0x40) { + delta.z += f.x; + delta.x += -f.y; + } + if (posDelta & 0x10) { + delta.z -= f.x; + delta.x -= -f.y; + } + if (posDelta & 0x8) { + delta.y += 1; + } + if (posDelta & 0x4) { + delta.y -= 1; + } - // forward vector must be negative to look forward. - // read :http://in2gpu.com/2015/05/17/view-matrix/ - Position += delta * CameraSpeed; + // get current view matrix + glm::mat4 mat = getViewMatrix(); + glm::vec3 forward(mat[0][2], mat[1][2], mat[2][2]); + glm::vec3 strafe(mat[0][0], mat[1][0], mat[2][0]); - // update the view matrix - update(); + // forward vector must be negative to look forward. + // read :http://in2gpu.com/2015/05/17/view-matrix/ + Position += delta * CameraSpeed; + + // update the view matrix + update(); } void Camera::mouseMoved(glm::vec2 mouseDelta) { - if (glm::length(mouseDelta) == 0) return; - // note that yaw and pitch must be converted to radians. - // this is done in update() by glm::rotate - Yaw += MouseSensitivity * (mouseDelta.x / 100); - Pitch += MouseSensitivity * (mouseDelta.y / 100); - Pitch = glm::clamp(Pitch, -M_PI / 2, M_PI / 2); + if (glm::length(mouseDelta) == 0) + return; + // note that yaw and pitch must be converted to radians. + // this is done in update() by glm::rotate + Yaw += MouseSensitivity * (mouseDelta.x / 100); + Pitch += MouseSensitivity * (mouseDelta.y / 100); + Pitch = glm::clamp(Pitch, -M_PI / 2, M_PI / 2); - update(); + update(); } void Camera::setPosition(glm::vec3 position) { - Position = position; + Position = position; - update(); + update(); } void Camera::setEulerLook(float roll, float pitch, float yaw) { - Roll = roll; Pitch = pitch; Yaw = yaw; - LookDirection.x = cos(Yaw) * cos(Pitch); - LookDirection.y = sin(Yaw) * cos(Pitch); - LookDirection.z = sin(Pitch); + Roll = roll; + Pitch = pitch; + Yaw = yaw; + LookDirection.x = cos(Yaw) * cos(Pitch); + LookDirection.y = sin(Yaw) * cos(Pitch); + LookDirection.z = sin(Pitch); - update(); + update(); } void Camera::setLook(glm::vec3 lookDirection) { - LookDirection = lookDirection; - Pitch = asin(-lookDirection.y); - Yaw = atan2(lookDirection.x, lookDirection.z); + LookDirection = lookDirection; + Pitch = asin(-lookDirection.y); + Yaw = atan2(lookDirection.x, lookDirection.z); - update(); + update(); } void Camera::setRayViewport(glm::vec2 viewport) { - std::lock_guard lock(this->_mCam); - mRayViewport = viewport; + std::lock_guard lock(this->_mCam); + mRayViewport = viewport; } glm::vec2 Camera::getRayViewport() { - std::lock_guard lock(this->_mCam); - return mRayViewport; + std::lock_guard lock(this->_mCam); + return mRayViewport; } +}