aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ThirdPersonCamera.hpp23
-rw-r--r--src/ThirdPersonCamera.cpp58
-rw-r--r--src/main.cpp75
3 files changed, 132 insertions, 24 deletions
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 <glm/glm.hpp>
+
+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 <glm/gtc/type_ptr.hpp>
+#include <stdio.h>
+
+#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<Shader> load_shader_from_file(const char *filepath, Shade
static std::unique_ptr<ShaderProgram> build_shader_program_from_shaders(const std::vector<Shader*> &shaders);
struct Userdata {
- float cam_dist;
+ ThirdPersonCamera *third_person_camera;
+ double prev_cursor_x;
+ double prev_cursor_y;
};
static std::vector<Triangle3D> generate_sand() {
@@ -54,8 +57,7 @@ static std::vector<Triangle3D> 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