From f2f8ccc1c24ab372ffe5e932780eeb1c49a4d277 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 21 Feb 2020 05:10:13 +0100 Subject: Add third person camera (orbit camera) --- include/ThirdPersonCamera.hpp | 23 +++++++++++++ src/ThirdPersonCamera.cpp | 58 +++++++++++++++++++++++++++++++++ src/main.cpp | 75 +++++++++++++++++++++++++++++-------------- 3 files changed, 132 insertions(+), 24 deletions(-) create mode 100644 include/ThirdPersonCamera.hpp create mode 100644 src/ThirdPersonCamera.cpp diff --git a/include/ThirdPersonCamera.hpp b/include/ThirdPersonCamera.hpp new file mode 100644 index 0000000..00a22a4 --- /dev/null +++ b/include/ThirdPersonCamera.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace amalgine { + class ThirdPersonCamera { + public: + ThirdPersonCamera(); + + void zoom(float distance); + void rotate_horizontal(float radians); + void rotate_vertical(float radians); + void set_target_position(const glm::vec3 &target_pos); + glm::mat4 get_matrix() const; + glm::vec3 get_forward_vector() const; + glm::vec3 get_right_vector() const; + private: + glm::vec3 target_pos; + float camera_distance; + float angle_horizontal; + float angle_vertical; + }; +} \ No newline at end of file diff --git a/src/ThirdPersonCamera.cpp b/src/ThirdPersonCamera.cpp new file mode 100644 index 0000000..2404daf --- /dev/null +++ b/src/ThirdPersonCamera.cpp @@ -0,0 +1,58 @@ +#include "../include/ThirdPersonCamera.hpp" +#include +#include + +#define HALF_PI 1.5707963267948966f +#define PI 3.141592653589793f +#define TAU 6.283185307179586f + +namespace amalgine { + ThirdPersonCamera::ThirdPersonCamera() : target_pos(glm::vec3()), camera_distance(3.0f), angle_horizontal(0.0f), angle_vertical(0.0f) { + + } + + void ThirdPersonCamera::zoom(float distance) { + camera_distance += distance; + if(camera_distance < 0.1f) + camera_distance = 0.1f; + } + + void ThirdPersonCamera::rotate_horizontal(float radians) { + angle_horizontal = std::fmod(angle_horizontal + radians, TAU); + } + + void ThirdPersonCamera::rotate_vertical(float radians) { + const float max_angle = 1.56079632679f; + + angle_vertical = std::fmod(angle_vertical + radians, TAU); + if(angle_vertical > max_angle) + angle_vertical = max_angle; + else if(angle_vertical < -max_angle) + angle_vertical = -max_angle; + } + + void ThirdPersonCamera::set_target_position(const glm::vec3 &target_pos) { + this->target_pos = target_pos; + } + + glm::mat4 ThirdPersonCamera::get_matrix() const { + glm::vec3 eye = target_pos - get_forward_vector() * camera_distance; + return glm::lookAt(eye, target_pos, glm::vec3(0.0f, 0.0f, 1.0f)); + } + + glm::vec3 ThirdPersonCamera::get_forward_vector() const { + glm::vec3 vec; + vec.x = std::sin(angle_horizontal) * std::cos(angle_vertical); + vec.y = std::cos(angle_horizontal) * std::cos(angle_vertical); + vec.z = std::sin(angle_vertical); + return vec; + } + + glm::vec3 ThirdPersonCamera::get_right_vector() const { + glm::vec3 vec = get_forward_vector(); + float temp = vec.x; + vec.x = vec.y; + vec.y = -temp; + return vec; + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 04c1001..33488bb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include "../include/RenderBackend/OpenGL/Texture2D.hpp" #include "../include/Image.hpp" #include "../include/Triangle.hpp" +#include "../include/ThirdPersonCamera.hpp" #include "../include/model_loader/ObjModelLoader.hpp" @@ -25,7 +26,9 @@ static std::unique_ptr load_shader_from_file(const char *filepath, Shade static std::unique_ptr build_shader_program_from_shaders(const std::vector &shaders); struct Userdata { - float cam_dist; + ThirdPersonCamera *third_person_camera; + double prev_cursor_x; + double prev_cursor_y; }; static std::vector generate_sand() { @@ -54,8 +57,7 @@ static std::vector generate_sand() { static void create_sand(DeviceMemory *triangles, DeviceMemory *texcoords, Texture2D *texture); static DeviceMemory* load_model(const char *filepath); -int main() -{ +int main() { initGlfw(); glfwSetErrorCallback(glfwErrorHandler); GLFWwindow *window = createWindow(); @@ -115,15 +117,30 @@ int main() texture_coords.resize(0); Userdata userdata; - userdata.cam_dist = 3.0f; - glm::vec3 character_pos(0.0f, 0.0f, userdata.cam_dist); + ThirdPersonCamera third_person_camera; + userdata.third_person_camera = &third_person_camera; + glfwGetCursorPos(window, &userdata.prev_cursor_x, &userdata.prev_cursor_y); + + glm::vec3 character_pos(0.0f, 0.0f, 10.0f); auto t_start = std::chrono::high_resolution_clock::now(); glfwSetWindowUserPointer(window, &userdata); glfwSetScrollCallback(window, [](GLFWwindow *window, double xoffset, double yoffset){ Userdata *userdata = (Userdata*)glfwGetWindowUserPointer(window); - userdata->cam_dist += yoffset; + userdata->third_person_camera->zoom(-yoffset); + }); + + glfwSetCursorPosCallback(window, [](GLFWwindow *window, double xpos, double ypos) { + Userdata *userdata = (Userdata*)glfwGetWindowUserPointer(window); + double diff_x = xpos - userdata->prev_cursor_x; + double diff_y = ypos - userdata->prev_cursor_y; + userdata->prev_cursor_x = xpos; + userdata->prev_cursor_y = ypos; + if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_PRESS) { + userdata->third_person_camera->rotate_horizontal(diff_x * 0.005f); + userdata->third_person_camera->rotate_vertical(-diff_y * 0.005f); + } }); glEnable(GL_CULL_FACE); @@ -141,25 +158,34 @@ int main() t_start = t_now; time += time_delta; + glm::mat4 camera_matrix = third_person_camera.get_matrix(); + glm::vec3 camera_forward = third_person_camera.get_forward_vector(); + glm::vec3 camera_right = third_person_camera.get_right_vector(); + + sand_view_uniform->set(camera_matrix); + view_uniform->set(camera_matrix); + float move_speed = time_delta * 3.0f; - if(glfwGetKey(window, GLFW_KEY_W)) - character_pos.y -= move_speed; - if(glfwGetKey(window, GLFW_KEY_S)) - character_pos.y += move_speed; - if(glfwGetKey(window, GLFW_KEY_A)) - character_pos.x += move_speed; - if(glfwGetKey(window, GLFW_KEY_D)) - character_pos.x -= move_speed; - - character_pos.z = userdata.cam_dist; - - glm::mat4 view = glm::lookAt( - character_pos, - character_pos - glm::vec3(0.0f, 3.0f, 3.0f), - glm::vec3(0.0f, 0.0f, 1.0f) - ); - sand_view_uniform->set(view); - view_uniform->set(view); + glm::vec3 move_vec = glm::vec3(); + if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { + move_vec.x += camera_forward.x; + move_vec.y += camera_forward.y; + } + if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { + move_vec.x += -camera_forward.x; + move_vec.y += -camera_forward.y; + } + if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { + move_vec.x += -camera_right.x; + move_vec.y += -camera_right.y; + } + if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { + move_vec.x += camera_right.x; + move_vec.y += camera_right.y; + } + if(glm::length(move_vec) > 0.0f) + character_pos += (glm::normalize(move_vec) * move_speed); + third_person_camera.set_target_position(character_pos); glm::mat4 model = glm::mat4(1.0f); model = glm::rotate( @@ -284,6 +310,7 @@ GLFWwindow* createWindow() { exit(10); } + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_FALSE); glfwMakeContextCurrent(window); glfwSwapInterval(1); // 1 = enable vsync -- cgit v1.2.3