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
+#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)
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);
}
#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
#include "client.h"
#include "clientmap.h"
#include "clientnode.h"
+#include "input.h"
#include "signal.h"
#include "shaders.h"
#include "util.h"
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
ShaderProgram *prog = create_shader_program(RESSOURCEPATH "shaders");
if (! prog) {
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);
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);
Map *map;
Scene *scene;
v3f pos;
+ double yaw, pitch;
} Client;
void client_disconnect(bool send, const char *detail);
--- /dev/null
+#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);
+}
+
+
--- /dev/null
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+#include <GLFW/glfw3.h>
+
+void process_input();
+void init_input(Client *client, GLFWwindow *window);
+
+#endif