]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Move input handling code to separate file and implement FPS camera
authorElias Fleckenstein <eliasfleckenstein@web.de>
Fri, 9 Jul 2021 17:49:31 +0000 (19:49 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Fri, 9 Jul 2021 17:49:31 +0000 (19:49 +0200)
src/Makefile
src/camera.c
src/camera.h
src/client.c
src/client.h
src/input.c [new file with mode: 0644]
src/input.h [new file with mode: 0644]

index 36f6394d004dffd2ebca2bf61c72663f358032fa..af1678ebd502ecb628cc9b38cf3ae107579ef6b5 100644 (file)
@@ -1,6 +1,6 @@
 COMMON = array.o list.o map.o signal.o util.o types.o node.o queue.o
 SERVER = $(COMMON) server.o servercommands.o servermap.o perlin.o facecache.o mapgen.o mapdb.o
-CLIENT = $(COMMON) camera.o client.o clientcommands.o clientmap.o clientnode.o mesh.o scene.o shaders.o blockmesh.o texture.o
+CLIENT = $(COMMON) camera.o client.o clientcommands.o clientmap.o clientnode.o input.o mesh.o scene.o shaders.o blockmesh.o texture.o
 LIBRARIES = -lpthread -lm -lz
 FLAGS = -g -fmax-errors=4
 
index 467cc7fea9b1eb0fba530e9ea09a533e10a6f423..ac675bd50166225d60dc22525141a71b3a6e1855 100644 (file)
@@ -1,20 +1,66 @@
+#include <math.h>
 #include "client.h"
 #include "camera.h"
 
-static mat4x4 view, projection;
-static GLFWwindow *window;
-static ShaderProgram *prog;
+static struct
+{
+       mat4x4 view, projection;
+       GLFWwindow *window;
+       ShaderProgram *prog;
+
+       vec3 eye, front, right, up;
+} camera;
+
+static vec3 world_up = {0.0f, 1.0f, 0.0f};
+
+struct movement_dirs movement_dirs;
+
+static void update_camera()
+{
+       vec3 center;
+       vec3_add(center, camera.eye, camera.front);
+
+       mat4x4_look_at(camera.view, camera.eye, center, camera.up);
+       glUniformMatrix4fv(camera.prog->loc_view, 1, GL_FALSE, camera.view[0]);
+}
 
 void set_camera_position(v3f pos)
 {
-       mat4x4_translate(view, -pos.x, -pos.y, -pos.z);
-       glUniformMatrix4fv(prog->loc_view, 1, GL_FALSE, view[0]);
+       camera.eye[0] = pos.x;
+       camera.eye[1] = pos.y;
+       camera.eye[2] = pos.z;
+
+       update_camera();
+}
+
+void set_camera_angle(float yaw, float pitch)
+{
+       camera.front[0] = movement_dirs.front[0] = cos(yaw) * cos(pitch);
+       camera.front[1] = sin(pitch);
+       camera.front[2] = movement_dirs.front[2] = sin(yaw) * cos(pitch);
+
+       vec3_norm(camera.front, camera.front);
+       vec3_norm(movement_dirs.front, movement_dirs.front);
+
+       vec3_mul_cross(camera.right, camera.front, world_up);
+       movement_dirs.right[0] = camera.right[0];
+       movement_dirs.right[2] = camera.right[2];
+
+       vec3_norm(camera.right, camera.right);
+       vec3_norm(movement_dirs.right, movement_dirs.right);
+
+       vec3_mul_cross(camera.up, camera.right, camera.front);
+       vec3_norm(camera.up, camera.up);
+
+       movement_dirs.up[1] = world_up[1];
+
+       update_camera();
 }
 
 void set_window_size(int width, int height)
 {
-       mat4x4_perspective(projection, 86.1f / 180.0f * M_PI, (float) width / (float) height, 0.01f, 1000.0f);
-       glUniformMatrix4fv(prog->loc_projection, 1, GL_FALSE, projection[0]);
+       mat4x4_perspective(camera.projection, 86.1f / 180.0f * M_PI, (float) width / (float) height, 0.01f, 1000.0f);
+       glUniformMatrix4fv(camera.prog->loc_projection, 1, GL_FALSE, camera.projection[0]);
 }
 
 static void framebuffer_size_callback(__attribute__((unused)) GLFWwindow* window, int width, int height)
@@ -23,10 +69,10 @@ static void framebuffer_size_callback(__attribute__((unused)) GLFWwindow* window
        set_window_size(width, height);
 }
 
-void init_camera(GLFWwindow *w, ShaderProgram *p)
+void init_camera(GLFWwindow *window, ShaderProgram *prog)
 {
-       window = w;
-       prog = p;
+       camera.window = window;
+       camera.prog = prog;
 
-       glfwSetFramebufferSizeCallback(window, &framebuffer_size_callback);
+       glfwSetFramebufferSizeCallback(camera.window, &framebuffer_size_callback);
 }
index cc9e29f8d5b782260b3b6aadd4f4e08f18a7f9d7..b2af78cb583208ad898d08a6499a9aab97ef5b63 100644 (file)
@@ -1,12 +1,22 @@
 #ifndef _CAMERA_H_
 #define _CAMERA_H_
 
+#include <GL/glew.h>
 #include <GLFW/glfw3.h>
+#include <linmath.h/linmath.h>
 #include "shaders.h"
 #include "types.h"
 
 void init_camera(GLFWwindow *window, ShaderProgram *prog);
 void set_camera_position(v3f pos);
+void set_camera_angle(float yaw, float pitch);
 void set_window_size(int width, int height);
 
+extern struct movement_dirs
+{
+       vec3 front;
+       vec3 right;
+       vec3 up;
+} movement_dirs;
+
 #endif
index aa3e342b1664a6f0923832f2b2564f8a85cbdb36..62e6ab3904eda96b195fa6b1cb24b2f21507787d 100644 (file)
@@ -13,6 +13,7 @@
 #include "client.h"
 #include "clientmap.h"
 #include "clientnode.h"
+#include "input.h"
 #include "signal.h"
 #include "shaders.h"
 #include "util.h"
@@ -76,6 +77,7 @@ static void client_loop()
        }
 
        glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
+       glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
 
        ShaderProgram *prog = create_shader_program(RESSOURCEPATH "shaders");
        if (! prog) {
@@ -89,43 +91,20 @@ static void client_loop()
        glUseProgram(prog->id);
 
        init_camera(window, prog);
+
+       set_camera_position(client.pos);
+       set_camera_angle(client.yaw, client.pitch);
+
        set_window_size(width, height);
 
-       bool pos_changed = true;
+       init_input(&client, window);
 
        while (! glfwWindowShouldClose(window) && client.state != CS_DISCONNECTED && ! interrupted) {
                glEnable(GL_DEPTH_TEST);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                glClearColor(0.52941176470588f, 0.8078431372549f, 0.92156862745098f, 1.0f);
 
-               if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
-                       pos_changed = true;
-                       client.pos.z -= 1.0f;
-               } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
-                       pos_changed = true;
-                       client.pos.z += 1.0f;
-               } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
-                       pos_changed = true;
-                       client.pos.x -= 1.0f;
-               } else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
-                       pos_changed = true;
-                       client.pos.x += 1.0f;
-               } if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) {
-                       pos_changed = true;
-                       client.pos.y -= 1.0f;
-               } else if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
-                       pos_changed = true;
-                       client.pos.y += 1.0f;
-               }
-
-               if (pos_changed) {
-                       set_camera_position(client.pos);
-                       pos_changed = false;
-
-                       pthread_mutex_lock(&client.mtx);
-                       (void) (write_u32(client.fd, SC_POS) && write_v3f32(client.fd, client.pos));
-                       pthread_mutex_unlock(&client.mtx);
-               }
+               process_input();
 
                scene_render(client.scene, prog);
 
@@ -186,6 +165,7 @@ static void client_start(int fd)
        client.map = map_create();
        client.scene = scene_create();
        client.pos = (v3f) {0.0f, 0.0f, 0.0f};
+       client.yaw = client.pitch = 0.0;
 
        clientmap_init(&client);
 
index 7f02e421f17b7c84a9eb41bd579391ca20972f00..3dd0f3d0abc3c21b88dd67bf76a2d317ecf859d1 100644 (file)
@@ -24,6 +24,7 @@ typedef struct Client
        Map *map;
        Scene *scene;
        v3f pos;
+       double yaw, pitch;
 } Client;
 
 void client_disconnect(bool send, const char *detail);
diff --git a/src/input.c b/src/input.c
new file mode 100644 (file)
index 0000000..71c0895
--- /dev/null
@@ -0,0 +1,70 @@
+#include <math.h>
+#include "camera.h"
+#include "client.h"
+#include "input.h"
+
+static struct
+{
+       GLFWwindow *window;
+       Client *client;
+} input;
+
+static void cursor_pos_callback(__attribute__((unused)) GLFWwindow* window, double current_x, double current_y)
+{
+       static double last_x, last_y = 0.0;
+
+       double delta_x = current_x - last_x;
+       double delta_y = current_y - last_y;
+       last_x = current_x;
+       last_y = current_y;
+
+       input.client->yaw += (float) delta_x * M_PI / 180.0f / 8.0f;
+       input.client->pitch -= (float) delta_y * M_PI / 180.0f / 8.0f;
+
+       input.client->pitch = fmax(fmin(input.client->pitch, 90.0f), -90.0f);
+
+       set_camera_angle(input.client->yaw, input.client->pitch);
+}
+
+static bool move(int forward, int backward, vec3 speed)
+{
+       float sign;
+
+       if (glfwGetKey(input.window, forward) == GLFW_PRESS)
+               sign = +1.0f;
+       else if (glfwGetKey(input.window, backward) == GLFW_PRESS)
+               sign = -1.0f;
+       else
+               return false;
+
+       input.client->pos.x += speed[0] * sign;
+       input.client->pos.y += speed[1] * sign;
+       input.client->pos.z += speed[2] * sign;
+
+       return true;
+}
+
+void process_input()
+{
+       bool moved_forward = move(GLFW_KEY_W, GLFW_KEY_S, movement_dirs.front);
+       bool moved_up = move(GLFW_KEY_SPACE, GLFW_KEY_LEFT_SHIFT, movement_dirs.up);
+       bool moved_right = move(GLFW_KEY_D, GLFW_KEY_A, movement_dirs.right);
+
+       if (moved_forward || moved_up || moved_right) {
+               set_camera_position(input.client->pos);
+
+               pthread_mutex_lock(&input.client->mtx);
+               (void) (write_u32(input.client->fd, SC_POS) && write_v3f32(input.client->fd, input.client->pos));
+               pthread_mutex_unlock(&input.client->mtx);
+       }
+}
+
+void init_input(Client *client, GLFWwindow *window)
+{
+       input.client = client;
+       input.window = window;
+
+       glfwSetCursorPosCallback(input.window, &cursor_pos_callback);
+}
+
+
diff --git a/src/input.h b/src/input.h
new file mode 100644 (file)
index 0000000..6b93a70
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+#include <GLFW/glfw3.h>
+
+void process_input();
+void init_input(Client *client, GLFWwindow *window);
+
+#endif