diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c04295..9367d30 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ add_library(fever_engine mesh.cpp gltf_loader.cpp material.cpp + camera.cpp ) target_compile_features(fever_engine PUBLIC cxx_std_20) diff --git a/src/Camera.cpp b/src/Camera.cpp index 7f54247..b5dccc8 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -28,11 +28,6 @@ void Camera::translate(glm::vec3 translateVector) m_viewMatrix = glm::translate(m_viewMatrix, translateVector * -1.F); } -void Camera::lookAtTarget(glm::vec3 target) -{ - m_viewMatrix = glm::lookAt(m_position, target, UP_VEC); -} - void Camera::lookForward() { m_viewMatrix = glm::lookAt(m_position, m_position + m_front_vec, UP_VEC); @@ -98,21 +93,6 @@ void Camera::updateDirectionFromMouseInput(MouseCursorInput const &mouse_cursor_ m_front_vec = glm::normalize(direction); } -void Camera::setPosition(glm::vec3 position) -{ - this->m_position = position; -} - -auto Camera::getView() const -> glm::mat4 -{ - return m_viewMatrix; -} - -auto Camera::getProj() const -> glm::mat4 -{ - return m_projectionMatrix; -} - auto Camera::getViewProj() const -> glm::mat4 { return m_viewProjectionMatrix; @@ -123,7 +103,3 @@ auto Camera::getPosition() const -> glm::vec3 return m_position; } -auto Camera::getDirection() const -> glm::vec3 -{ - return m_front_vec; -} diff --git a/src/Camera.h b/src/Camera.h index 679023d..f1a5902 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -15,17 +15,10 @@ public: void updateDirectionFromMouseInput(MouseCursorInput const &mouse_cursor_input); void translate(glm::vec3 translateVector); - - void lookAtTarget(glm::vec3 target); void lookForward(); - [[nodiscard]] auto getView() const -> glm::mat4; - [[nodiscard]] auto getProj() const -> glm::mat4; [[nodiscard]] auto getViewProj() const -> glm::mat4; [[nodiscard]] auto getPosition() const -> glm::vec3; - [[nodiscard]] auto getDirection() const -> glm::vec3; - - void setPosition(glm::vec3 position); private: glm::mat4 m_viewMatrix; diff --git a/src/Controller.cpp b/src/Controller.cpp index 712d63f..3fa6e4a 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -36,7 +36,7 @@ Controller::Controller() // m_camera = std::make_shared(perspective.yfov, perspective.aspectRatio); // } else { - m_camera = std::make_shared(90., m_gameWindow->aspectRatio()); + // m_camera = std::make_shared(90., m_gameWindow->aspectRatio()); // } } @@ -44,7 +44,8 @@ void Controller::run() { updateExposure(postProcessingProgram); - m_camera->translate(glm::vec3(0., .5, 2.)); + // m_camera->translate(glm::vec3(0., .5, 2.)); + DirectionalLight directional_light( DirectionalLight::Prototype("", glm::vec3(-0.2, -1.0, -0.3), glm::vec3(1.0f), 5.f), &defaultProgram); @@ -70,17 +71,22 @@ void Controller::run() m_postProcessFrameBuffer.bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_camera->lookForward(); - m_camera->updateVPM(); + // m_camera->lookForward(); + // m_camera->updateVPM(); + + m_gameWindow->clear_mouse_cursor_input(); // MOVE DOWN AGAIN! + glfwPollEvents(); + + auto const &key_input = m_gameWindow->key_input(); + auto const &mouse_cursor_input = m_gameWindow->mouse_cursor_input(); static constexpr auto MICROSECONDS_PER_SECOND = 1'000'000; m_scene.update( std::chrono::microseconds(static_cast(m_deltaTime * MICROSECONDS_PER_SECOND)), &defaultProgram, - m_camera->getViewProj(), - m_camera->getPosition()); + key_input,mouse_cursor_input, m_gameWindow->aspectRatio()); - m_postProcessFrameBuffer.unbind(); + Framebuffer::unbind(); m_postProcessFrameBuffer.drawOnEntireScreen(); glfwSwapBuffers(&m_gameWindow->glfw_window()); @@ -92,17 +98,17 @@ void Controller::run() } // --- Check events, handle input --- - m_gameWindow->clear_mouse_cursor_input(); - glfwPollEvents(); + // m_gameWindow->clear_mouse_cursor_input(); + // glfwPollEvents(); - auto const &key_input = m_gameWindow->key_input(); - auto const &mouse_cursor_input = m_gameWindow->mouse_cursor_input(); + // auto const &key_input = m_gameWindow->key_input(); + // auto const &mouse_cursor_input = m_gameWindow->mouse_cursor_input(); - m_camera->updatePositionFromKeyboardInput(key_input, (float)m_deltaTime); + // m_camera->updatePositionFromKeyboardInput(key_input, (float)m_deltaTime); - if (m_gameWindow->cursor_catched()) { - m_camera->updateDirectionFromMouseInput(mouse_cursor_input); - } + // if (m_gameWindow->cursor_catched()) { + // m_camera->updateDirectionFromMouseInput(mouse_cursor_input); + // } } } @@ -128,7 +134,7 @@ void Controller::limit_framerate() void Controller::update_window_dimensions() { - m_camera->updateAspectRatio(m_gameWindow->aspectRatio()); + // m_camera->updateAspectRatio(m_gameWindow->aspectRatio()); // m_gameEventHandler->setFirstMouseInput(1); auto dimensions = m_gameWindow->dimensions(); diff --git a/src/Controller.h b/src/Controller.h index f44a1a3..a4e3423 100644 --- a/src/Controller.h +++ b/src/Controller.h @@ -28,7 +28,6 @@ private: void update_window_dimensions(); std::shared_ptr m_gameWindow; - std::shared_ptr m_camera; ShaderProgram defaultProgram{{"defaultProgram", "data/shaders/basic.vert", "data/shaders/basic.frag"}}; ShaderProgram skyboxProgram{{"skyboxProgram", "data/shaders/skybox.vert", "data/shaders/skybox.frag"}}; diff --git a/src/Scene.cpp b/src/Scene.cpp index 0f8605d..d6909db 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -1,11 +1,15 @@ #include "Scene.h" #include "ShaderProgram.h" +#include "camera.h" #include "mesh.h" #include "name.h" #include "relationship.h" #include "transform.h" #include "util/Log.h" +#include +#include + using namespace entt::literals; // TODO: make scene initialization part of gltf loader as seen in bevy @@ -87,29 +91,40 @@ Scene::Scene() // Remove Material resource as it is no longer needed. m_registry.erase>(entity); } + + // Spawn the camera + auto entity = m_registry.create(); + m_registry.emplace(entity, "Camera"); + m_registry.emplace(entity, Transform{.translation = glm::vec3(0.0, 0.5, -2.0)}); + m_registry.emplace(entity, GlobalTransform{}); + m_registry.emplace(entity, + Camera{.projection = Camera::Perspective{.aspect_ratio = 1.6}}); } void Scene::update(std::chrono::duration delta, ShaderProgram *shaderprogram, - glm::mat4 viewProjMatrix, - glm::vec3 viewPosition) + KeyInput const &key_input, + MouseCursorInput const &mouse_cursor_input, + float aspect_ratio) { - // Update GlobalTransform components - // TODO: Only do this when the Transform changed. - auto root_transform_view = - m_registry.view(entt::exclude); - auto transform_view = m_registry.view(); + { + // Update GlobalTransform components + // TODO: Only do this when the Transform changed. + auto root_transform_view = + m_registry.view(entt::exclude); + auto transform_view = m_registry.view(); - for (auto [entity, transform, global_transform] : root_transform_view.each()) { - global_transform = transform; + for (auto [entity, transform, global_transform] : root_transform_view.each()) { + global_transform = transform; - auto parent_global_transform = global_transform; - if (auto *children = m_registry.try_get(entity)) { - for (auto child : children->children) { - std::function - transform_propagate = - [this, &transform_propagate, &transform_view]( - entt::entity entity, GlobalTransform parent_global_transform) { + auto parent_global_transform = global_transform; + if (auto *children = m_registry.try_get(entity)) { + for (auto child : children->children) { + std::function + transform_propagate = [this, &transform_propagate, &transform_view]( + entt::entity entity, + GlobalTransform parent_global_transform) { auto [transform, global_transform, parent] = transform_view.get(entity); global_transform.transform = parent_global_transform.transform * GlobalTransform(transform).transform; @@ -121,30 +136,120 @@ void Scene::update(std::chrono::duration delta, } }; - transform_propagate(child, parent_global_transform); + transform_propagate(child, parent_global_transform); + } } } } - auto mesh_view = m_registry.view(); - for (auto [entity, mesh, material, transform] : mesh_view.each()) { - shaderprogram->bind(); + { + auto mesh_view = m_registry.view(); + auto camera_view = m_registry.view(); + auto camera_entity = camera_view.front(); + auto [camera, camera_transform] = camera_view.get(camera_entity); + glm::mat4 view_projection_matrix = + camera.projection_matrix() * Camera::view_matrix(camera_transform); - // Bind textures - material.bind(*shaderprogram); + for (auto [entity, mesh, material, transform] : mesh_view.each()) { + shaderprogram->bind(); - // Bind modelview matrix uniform - { - glm::mat4 modelViewProj = viewProjMatrix * transform.transform; - shaderprogram->setUniform("u_modelViewProjMatrix", modelViewProj); - shaderprogram->setUniform("u_modelMatrix", transform.transform); - shaderprogram->setUniform("u_viewPosition", viewPosition); + // Bind textures + material.bind(*shaderprogram); + + // Bind modelview matrix uniform + { + glm::mat4 modelViewProj = view_projection_matrix * transform.transform; + shaderprogram->setUniform("u_modelViewProjMatrix", modelViewProj); + shaderprogram->setUniform("u_modelMatrix", transform.transform); + shaderprogram->setUniform("u_viewPosition", camera_transform.position()); + } + + glBindVertexArray(mesh.vao); + glDrawElements(GL_TRIANGLES, mesh.indices_count, mesh.indices_type, nullptr); + glBindVertexArray(0); + + ShaderProgram::unbind(); + } + } + + // Camera keyboard update + { + auto camera_view = m_registry.view(); + auto camera_entity = camera_view.front(); + auto [camera, camera_transform, camera_global_transform] = camera_view.get(camera_entity); + + glm::vec3 front_vec = Camera::front_vector(camera_global_transform); + glm::vec3 front_vec_without_y = glm::vec3(front_vec.x, 0., front_vec.z); + glm::vec3 deltaPos = glm::vec3(0., 0., 0.); + // float deltaFactor = SPEED * deltaTime * (m_accellerate ? 5.0 : 1.0); + float delta_factor = 0.5 * delta.count(); + // m_accellerate = false; + + for (auto const &[key, pressed] : key_input) { + if (key == GLFW_KEY_W && pressed) { + deltaPos += delta_factor * glm::normalize(front_vec_without_y); + } + if (key == GLFW_KEY_S && pressed) { + deltaPos -= delta_factor * glm::normalize(front_vec_without_y); + } + if (key == GLFW_KEY_A && pressed) { + deltaPos -= delta_factor * glm::normalize(glm::cross(front_vec, Camera::UP_VECTOR)); + } + if (key == GLFW_KEY_D && pressed) { + deltaPos += delta_factor * glm::normalize(glm::cross(front_vec, Camera::UP_VECTOR)); + } + if (key == GLFW_KEY_SPACE && pressed) { + deltaPos += delta_factor * Camera::UP_VECTOR; + } + if (key == GLFW_KEY_LEFT_SHIFT && pressed) { + deltaPos -= delta_factor * Camera::UP_VECTOR; + } + // if (key == GLFW_KEY_LEFT_ALT && pressed) { + // m_accellerate = true; + // } + } + camera_transform.translation += deltaPos; + } + + // Camera mouse update + { + auto camera_view = m_registry.view(); + auto camera_entity = camera_view.front(); + auto [camera, camera_transform] = camera_view.get(camera_entity); + + auto [deltaX, deltaY] = mouse_cursor_input; + + if (std::abs(deltaX) < std::numeric_limits::epsilon() && + std::abs(deltaY) < std::numeric_limits::epsilon()) { + return; } - glBindVertexArray(mesh.vao); - glDrawElements(GL_TRIANGLES, mesh.indices_count, mesh.indices_type, nullptr); - glBindVertexArray(0); + auto pitch = static_cast(deltaY); + auto yaw = static_cast(deltaX); + auto roll = 0.0F; - ShaderProgram::unbind(); + // Orthographic projection currently unsupported + auto &camera_perspective = std::get(camera.projection); + + camera_perspective.pitch += glm::radians(pitch); + camera_perspective.yaw += glm::radians(yaw); + + static constexpr float PITCH_CLIP = glm::radians(89.); + camera_perspective.pitch = + std::clamp(static_cast(camera_perspective.pitch), -PITCH_CLIP, PITCH_CLIP); + + camera_transform.orientation = + glm::quat(glm::vec3(-camera_perspective.pitch, -camera_perspective.yaw, 0.0)); } -} + + // Camera aspect ratio update + { + auto camera_view = m_registry.view(); + auto camera_entity = camera_view.front(); + auto [camera] = camera_view.get(camera_entity); + + // Orthographic projection currently unsupported + auto &camera_perspective = std::get(camera.projection); + camera_perspective.aspect_ratio = aspect_ratio; + } +} \ No newline at end of file diff --git a/src/Scene.h b/src/Scene.h index 6686fd2..722afdd 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -3,6 +3,7 @@ #include "gltf_loader.h" #include "material.h" #include "mesh.h" +#include "Window.h" #include #include @@ -15,9 +16,7 @@ public: Scene(); void update(std::chrono::duration delta, - ShaderProgram *shaderprogram, - glm::mat4 viewProjMatrix, - glm::vec3 viewPosition); + ShaderProgram *shaderprogram, KeyInput const &key_input,MouseCursorInput const &mouse_cursor_input, float aspect_ratio); private: entt::registry m_registry; diff --git a/src/ShaderProgram.cpp b/src/ShaderProgram.cpp index 3c69006..6023160 100644 --- a/src/ShaderProgram.cpp +++ b/src/ShaderProgram.cpp @@ -24,12 +24,12 @@ ShaderProgram::ShaderProgram(Prototype prototype) : m_shaderProgramId(glCreatePr Log::logger().warn(R"(Failed to link shaderProgram "{}", "{}")", prototype.vertexPath, prototype.fragmentPath); } -#ifdef _RELEASE - glDetachShader(program, vs); - glDetachShader(program, fs); +#ifdef NDEBUG + glDetachShader(m_shaderProgramId, vertexShader); + glDetachShader(m_shaderProgramId, fragmentShader); - glDeleteShader(vs); - glDeleteShader(fs); + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); #endif Log::logger().trace(R"(Loaded shaderprogram "{}".)", prototype.name); diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 0000000..3d05882 --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,28 @@ +#include "camera.h" +#include "util/Log.h" +#include + +auto Camera::projection_matrix() const -> glm::mat4 +{ + return std::visit( + [](auto &&arg) -> glm::mat4 { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return glm::perspective(arg.fov / 2, arg.aspect_ratio, arg.near, arg.far); + } else { + return glm::ortho(arg.left, arg.right, arg.bottom, arg.top); + } + }, + projection); +}; + +auto Camera::view_matrix(GlobalTransform const &transform) -> glm::mat4 +{ + return glm::lookAt( + transform.position(), transform.position() + front_vector(transform), UP_VECTOR); +} + +auto Camera::front_vector(GlobalTransform const &transform) -> glm::vec3 +{ + return glm::normalize(transform.transform * glm::vec4(0.0, 0.0, 1.0, 0.0)); +} diff --git a/src/camera.h b/src/camera.h new file mode 100644 index 0000000..ed5bd4e --- /dev/null +++ b/src/camera.h @@ -0,0 +1,42 @@ +#pragma once + +#include "transform.h" + +#include +#include + +struct Camera +{ + static constexpr float DEFAULT_NEAR = 0.01; + static constexpr float DEFAULT_FAR = 1000.0; + static constexpr float DEFAULT_FOV = 90.0; + + static constexpr glm::vec3 UP_VECTOR = glm::vec3(0.0, 1.0, 0.0); + + struct Perspective + { + float fov = DEFAULT_FOV; + float aspect_ratio; + float near = DEFAULT_NEAR; + float far = DEFAULT_FAR; + + float pitch{}; + float yaw{}; + }; + + struct Orthographic + { + float left; + float right; + float top; + float bottom; + float near = DEFAULT_NEAR; + float far = DEFAULT_FAR; + }; + + std::variant projection; + + [[nodiscard]] auto projection_matrix() const -> glm::mat4; + [[nodiscard]] static auto view_matrix(GlobalTransform const &transform) -> glm::mat4; + [[nodiscard]] static auto front_vector(GlobalTransform const &transform) -> glm::vec3; +}; diff --git a/src/gltf_loader.cpp b/src/gltf_loader.cpp index 7960141..7aabd4b 100644 --- a/src/gltf_loader.cpp +++ b/src/gltf_loader.cpp @@ -313,7 +313,7 @@ auto GltfLoader::operator()(std::filesystem::path const &document_path) -> resul glm::quat rotation(node.rotation[3], node.rotation[0], node.rotation[1], node.rotation[2]); glm::vec3 scale(node.scale[0], node.scale[1], node.scale[2]); - Transform transform{.translation = translation, .rotation = rotation, .scale = scale}; + Transform transform{.translation = translation, .orientation = rotation, .scale = scale}; if (node.name.empty()) { Log::logger().warn("glTF node has no name."); diff --git a/src/transform.h b/src/transform.h index 626ffc5..f367ff5 100644 --- a/src/transform.h +++ b/src/transform.h @@ -6,7 +6,7 @@ struct Transform { glm::vec3 translation; - glm::quat rotation; + glm::quat orientation; glm::vec3 scale{1.0, 1.0, 1.0}; }; @@ -19,16 +19,18 @@ struct GlobalTransform // First scaling, then rotation, then translation // Translate - glm::mat4 translationMatrix = glm::translate(glm::mat4(1.0F), transform.translation); + glm::mat4 translation_matrix = glm::translate(glm::mat4(1.0F), transform.translation); // Rotate - glm::mat4 rotationMatrix = glm::toMat4(transform.rotation); + glm::mat4 rotation_matrix = glm::toMat4(transform.orientation); // Scale - glm::mat4 scaleMatrix = glm::scale(glm::mat4(1.0F), transform.scale); + glm::mat4 scale_matrix = glm::scale(glm::mat4(1.0F), transform.scale); - this->transform = translationMatrix * rotationMatrix * scaleMatrix; + this->transform = translation_matrix * rotation_matrix * scale_matrix; } glm::mat4 transform{}; + + [[nodiscard]] auto position() const -> glm::vec3 { return transform[3]; }; };