From decb9c4bd8fa313df3f7906dc8b823112a90555a Mon Sep 17 00:00:00 2001 From: Joseph Walton-Rivers <joseph@walton-rivers.uk> Date: Mon, 26 Jul 2021 07:22:00 +0100 Subject: [PATCH] RPG-style camera --- build.sh | 3 +- demo/main.cpp | 100 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 19 deletions(-) diff --git a/build.sh b/build.sh index b9b5e31..2bfc10f 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,4 @@ #! /bin/bash -set -e if [[ ! -d "build/" ]] then @@ -15,5 +14,5 @@ make popd pushd demo -gdb ../build/demo/FgglDemo +../build/demo/FgglDemo > /tmp/fggl.log 2>&1 & popd diff --git a/demo/main.cpp b/demo/main.cpp index 9e76acf..07cb316 100644 --- a/demo/main.cpp +++ b/demo/main.cpp @@ -1,4 +1,5 @@ #include <filesystem> +#include <glm/ext/matrix_transform.hpp> #include <glm/geometric.hpp> #include <glm/trigonometric.hpp> #include <iostream> @@ -45,28 +46,27 @@ void discover(std::filesystem::path base) { } +enum camera_type { cam_free, cam_arcball }; +camera_type cam_mode = cam_free; + //TODO proper input system void process_camera(fggl::gfx::Window& window, fggl::ecs::ECS& ecs, fggl::gfx::Input& input, fggl::ecs::entity_t cam) { - auto camTransform = ecs.getComponent<fggl::math::Transform>(cam); - auto camComp = ecs.getComponent<fggl::gfx::Camera>(cam); - float moveSpeed = 1.0f; - glm::vec3 dir = ( camTransform->origin() - camComp->target ); - glm::vec3 forward = glm::normalize( dir ); - - glm::vec3 motion(0.0f); - if ( glfwGetKey(window.handle(), GLFW_KEY_W) == GLFW_PRESS ) { - if ( glm::length( dir ) > 2.5f ) { - motion -= (forward * moveSpeed); - } + if ( glfwGetKey(window.handle(), GLFW_KEY_F2) == GLFW_PRESS ) { + cam_mode = cam_free; } - if ( glfwGetKey(window.handle(), GLFW_KEY_S) == GLFW_PRESS ) { - if ( glm::length( dir ) < 25.0f ) { - motion += (forward * moveSpeed); - } + if ( glfwGetKey(window.handle(), GLFW_KEY_F3) == GLFW_PRESS ) { + cam_mode = cam_arcball; } + auto camTransform = ecs.getComponent<fggl::math::Transform>(cam); + auto camComp = ecs.getComponent<fggl::gfx::Camera>(cam); + + const glm::vec3 dir = ( camTransform->origin() - camComp->target ); + const glm::vec3 forward = glm::normalize( dir ); + // scroll wheel + glm::vec3 motion(0.0f); float delta = (float)input.scrollDeltaY(); if ( (glm::length( dir ) < 25.0f && delta < 0.0f) || (glm::length( dir ) > 2.5f && delta > 0.0f) ) motion -= (forward * delta); @@ -108,6 +108,68 @@ void process_arcball(fggl::gfx::Window& window, fggl::ecs::ECS& ecs, fggl::gfx:: camTransform->origin( finalPos ); } +constexpr float ROT_SPEED = 0.05f; +constexpr float PAN_SPEED = 0.05f; +constexpr glm::mat4 MAT_IDENTITY(1.0f); + +void process_freecam(fggl::gfx::Window& window, fggl::ecs::ECS& ecs, fggl::gfx::Input& input, fggl::ecs::entity_t cam) { + float rotationValue = 0.0f; + glm::vec3 translation(0.0f); + + // calulate rotation (user input) + if ( glfwGetKey(window.handle(), GLFW_KEY_Q) == GLFW_PRESS ) { + rotationValue = ROT_SPEED; + } else if ( glfwGetKey(window.handle(), GLFW_KEY_E) == GLFW_PRESS ) { + rotationValue = -ROT_SPEED; + } + + // calulate movement (user input) + if ( glfwGetKey(window.handle(), GLFW_KEY_W) == GLFW_PRESS ) { + translation -= fggl::math::RIGHT; + } + + if ( glfwGetKey(window.handle(), GLFW_KEY_S) == GLFW_PRESS ) { + translation += fggl::math::RIGHT; + } + + if ( glfwGetKey(window.handle(), GLFW_KEY_D) == GLFW_PRESS ) { + translation += fggl::math::FORWARD; + } + + if ( glfwGetKey(window.handle(), GLFW_KEY_A) == GLFW_PRESS ) { + translation -= fggl::math::FORWARD; + } + + // apply rotation/movement + auto camTransform = ecs.getComponent<fggl::math::Transform>(cam); + auto camComp = ecs.getComponent<fggl::gfx::Camera>(cam); + + glm::vec4 position( camTransform->origin(), 1.0f ); + glm::vec4 pivot( camComp->target, 1.0f ); + + // apply movement + if ( translation != glm::vec3(0.0f) ) { + const auto rotation = (position - pivot); + const float angle = atan2( rotation.x, rotation.z ); + const auto rotationMat = glm::rotate( MAT_IDENTITY, angle, fggl::math::UP ); + + auto deltaMove = (rotationMat * glm::vec4( translation, 1.0f )) * PAN_SPEED; + deltaMove.w = 0.0f; + + position += deltaMove; + pivot += deltaMove; + } + + // apply rotation + if ( rotationValue != 0.0f ) { + glm::mat4 rotation = glm::rotate( MAT_IDENTITY, rotationValue, fggl::math::UP ); + position = ( rotation * ( position - pivot ) ) + pivot; + } + + camTransform->origin( position ); + camComp->target = pivot; +} + int main(int argc, char* argv[]) { fggl::gfx::Context ctx; @@ -228,8 +290,12 @@ int main(int argc, char* argv[]) { time += dt; process_camera(win, ecs, input, camEnt); - if ( input.mouseDown( fggl::gfx::MOUSE_2 ) ) { - process_arcball(win, ecs, input, camEnt); + if ( cam_mode == cam_arcball ) { + if ( input.mouseDown( fggl::gfx::MOUSE_2 ) ) { + process_arcball(win, ecs, input, camEnt); + } + } else if ( cam_mode == cam_free ) { + process_freecam(win, ecs, input, camEnt); } // imgui joystick debug -- GitLab