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 clientplayer.o input.o mesh.o scene.o shaders.o blockmesh.o texture.o
+CLIENT = $(COMMON) camera.o client.o clientcommands.o clientmap.o clientnode.o clientplayer.o cube.o input.o mesh.o scene.o shaders.o blockmesh.o texture.o
LIBRARIES = -lpthread -lm -lz
FLAGS = -g -fmax-errors=4
#include "blockmesh.h"
#include "clientnode.h"
-
-Vertex cube_vertices[6][6] = {
- {
- {-0.5, -0.5, -0.5, +0.0, +0.0},
- {+0.5, -0.5, -0.5, +1.0, +0.0},
- {+0.5, +0.5, -0.5, +1.0, +1.0},
- {+0.5, +0.5, -0.5, +1.0, +1.0},
- {-0.5, +0.5, -0.5, +0.0, +1.0},
- {-0.5, -0.5, -0.5, +0.0, +0.0},
- },
- {
- {-0.5, -0.5, +0.5, +0.0, +0.0},
- {+0.5, +0.5, +0.5, +1.0, +1.0},
- {+0.5, -0.5, +0.5, +1.0, +0.0},
- {+0.5, +0.5, +0.5, +1.0, +1.0},
- {-0.5, -0.5, +0.5, +0.0, +0.0},
- {-0.5, +0.5, +0.5, +0.0, +1.0},
- },
- {
- {-0.5, +0.5, +0.5, +1.0, +1.0},
- {-0.5, -0.5, -0.5, +0.0, +0.0},
- {-0.5, +0.5, -0.5, +0.0, +1.0},
- {-0.5, -0.5, -0.5, +0.0, +0.0},
- {-0.5, +0.5, +0.5, +1.0, +1.0},
- {-0.5, -0.5, +0.5, +1.0, +0.0},
- },
- {
- {+0.5, +0.5, +0.5, +1.0, +1.0},
- {+0.5, +0.5, -0.5, +0.0, +1.0},
- {+0.5, -0.5, -0.5, +0.0, +0.0},
- {+0.5, -0.5, -0.5, +0.0, +0.0},
- {+0.5, -0.5, +0.5, +1.0, +0.0},
- {+0.5, +0.5, +0.5, +1.0, +1.0},
- },
- {
- {-0.5, -0.5, -0.5, +0.0, +1.0},
- {+0.5, -0.5, -0.5, +1.0, +1.0},
- {+0.5, -0.5, +0.5, +1.0, +0.0},
- {+0.5, -0.5, +0.5, +1.0, +0.0},
- {-0.5, -0.5, +0.5, +0.0, +0.0},
- {-0.5, -0.5, -0.5, +0.0, +1.0},
- },
- {
- {-0.5, +0.5, -0.5, +0.0, +1.0},
- {+0.5, +0.5, -0.5, +1.0, +1.0},
- {+0.5, +0.5, +0.5, +1.0, +0.0},
- {+0.5, +0.5, +0.5, +1.0, +0.0},
- {-0.5, +0.5, +0.5, +0.0, +0.0},
- {-0.5, +0.5, -0.5, +0.0, +1.0},
- },
-};
+#include "cube.h"
static v3s8 fdir[6] = {
{+0, +0, -1},
ITERATE_MAPBLOCK {
if (node_definitions[block->data[x][y][z].type].visible) {
- v3f offset = {x + 8.5f, y + 8.5f, z + 8.5f};
+ v3f offset = {x + 8.0f, y + 8.0f, z + 8.0f};
vertexbuffer_set_texture(&buffer, client_node_definitions[block->data[x][y][z].type].texture);
vec3_mul_cross(camera.up, camera.right, camera.front);
vec3_norm(camera.up, camera.up);
- movement_dirs.up[1] = world_up[1];
-
update_camera();
}
{
vec3 front;
vec3 right;
- vec3 up;
} movement_dirs;
#endif
init_input(&client, window);
- clientplayer_send_pos(&client.player);
+ clientplayer_add_to_scene(&client.player);
struct timespec ts, ts_old;
clock_gettime(CLOCK_REALTIME, &ts_old);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.52941176470588f, 0.8078431372549f, 0.92156862745098f, 1.0f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
process_input();
clientplayer_tick(&client.player, dtime);
-#include <stdio.h>
#include "camera.h"
#include "client.h"
#include "clientplayer.h"
+#include "cube.h"
+#include "texture.h"
-void clientplayer_send_pos(ClientPlayer *player)
+static void update_pos(ClientPlayer *player)
{
+ set_camera_position((v3f) {player->pos.x, player->pos.y + player->eye_height, player->pos.z});
+
pthread_mutex_lock(&player->client->mtx);
(void) (write_u32(player->client->fd, SC_POS) && write_v3f32(player->client->fd, player->pos));
pthread_mutex_unlock(&player->client->mtx);
+
+ player->obj->pos = player->pos;
+ meshobject_transform(player->obj);
}
void clientplayer_init(Client *client)
{
client->player.client = client;
client->player.pos = (v3f) {0.0f, 25.0f, 0.0f};
- client->player.velocity = (v3f) {0.0f, 25.0f, 0.0f};
+ client->player.velocity = (v3f) {0.0f, 0.0f, 0.0f};
client->player.box = (aabb3f) {{-0.3f, 0.0f, -0.3f}, {0.3f, 1.75f, 0.3f}};
client->player.yaw = client->player.pitch = 0.0f;
- client->player.eye_height = 1.6f;
+ client->player.eye_height = 1.5f;
+}
+
+void clientplayer_add_to_scene(ClientPlayer *player)
+{
+ VertexBuffer buffer = vertexbuffer_create();
+ vertexbuffer_set_texture(&buffer, get_texture(RESSOURCEPATH "textures/player.png"));
+
+ for (int f = 0; f < 6; f++) {
+ for (int v = 0; v < 6; v++) {
+ Vertex vertex = cube_vertices[f][v];
+ vertex.y += 0.5;
+ vertexbuffer_add_vertex(&buffer, &vertex);
+ }
+ }
+
+ player->obj = meshobject_create(buffer, player->client->scene, (v3f) {0.0f, 0.0f, 0.0f});
+ player->obj->scale = (v3f) {0.6f, 1.75f, 0.6f};
+ player->obj->visible = false;
+
+ update_pos(player);
}
-static bool collision(ClientPlayer *player)
+static aabb3f get_box(ClientPlayer *player)
{
- aabb3f box = {
+ return (aabb3f) {
{player->box.min.x + player->pos.x, player->box.min.y + player->pos.y, player->box.min.z + player->pos.z},
{player->box.max.x + player->pos.x, player->box.max.y + player->pos.y, player->box.max.z + player->pos.z},
};
+}
- for (s32 x = floor(box.min.x); x <= ceil(box.max.x - 0.01f) - 1; x++) {
- for (s32 y = floor(box.min.y); y <= ceil(box.max.y - 0.01f) - 1; y++) {
- for (s32 z = floor(box.min.z); z <= ceil(box.max.z - 0.01f) - 1; z++) {
- Node node = map_get_node(player->client->map, (v3s32) {x, y, z}).type;
+static aabb3s32 round_box(aabb3f box)
+{
+ return (aabb3s32) {
+ {floor(box.min.x + 0.5f), floor(box.min.y + 0.5f), floor(box.min.z + 0.5f)},
+ {ceil(box.max.x - 0.5f), ceil(box.max.y - 0.5f), ceil(box.max.z - 0.5f)},
+ };
+}
- if (node == NODE_UNLOADED || node_definitions[node].solid)
- return true;
- }
- }
- }
+static bool is_solid(Map *map, s32 x, s32 y, s32 z)
+{
+ Node node = map_get_node(map, (v3s32) {x, y, z}).type;
+ return node == NODE_UNLOADED || node_definitions[node].solid;
+}
+
+static bool can_jump(ClientPlayer *player)
+{
+ aabb3f fbox = get_box(player);
+ fbox.min.y -= 0.5f;
+
+ aabb3s32 box = round_box(fbox);
+
+ if (fbox.min.y - (f32) box.min.y > 0.01f)
+ return false;
+
+ for (s32 x = box.min.x; x <= box.max.x; x++)
+ for (s32 z = box.min.z; z <= box.max.z; z++)
+ if (is_solid(player->client->map, x, box.min.y, z))
+ return true;
return false;
}
+void clientplayer_jump(ClientPlayer *player)
+{
+ if (can_jump(player))
+ player->velocity.y += 6.5f;
+}
+
void clientplayer_tick(ClientPlayer *player, f64 dtime)
{
v3f old_pos = player->pos;
player->velocity.y -= 9.81f * dtime;
-#define CALC_PHYSICS(pos, velocity, old_pos, old_velocity) \
- pos += (velocity + old_velocity) / 2.0f * dtime; \
- if (collision(player)) { \
- pos = old_pos; \
- velocity = 0.0f; \
+#define GETS(vec, comp) *(s32 *) ((char *) &vec + offsetof(v3s32, comp))
+#define GETF(vec, comp) *(f32 *) ((char *) &vec + offsetof(v3f32, comp))
+#define PHYSICS(a, b, c) { \
+ f32 v = (GETF(player->velocity, a) + GETF(old_velocity, a)) / 2.0f; \
+ if (v == 0.0f) \
+ goto a ## _physics_done; \
+ aabb3s32 box = round_box(get_box(player)); \
+ v3f old_pos = player->pos; \
+ GETF(player->pos, a) += v * dtime; \
+ s32 dir; \
+ f32 offset; \
+ if (v > 0.0f) { \
+ dir = +1; \
+ offset = GETF(player->box.max, a); \
+ GETS(box.min, a) = ceil(GETF(old_pos, a) + offset + 0.5f); \
+ GETS(box.max, a) = floor(GETF(player->pos, a) + offset + 0.5f); \
+ } else { \
+ dir = -1; \
+ offset = GETF(player->box.min, a); \
+ GETS(box.min, a) = floor(GETF(old_pos, a) + offset - 0.5f); \
+ GETS(box.max, a) = ceil(GETF(player->pos, a) + offset - 0.5f); \
+ } \
+ GETS(box.max, a) += dir; \
+ for (s32 a = GETS(box.min, a); a != GETS(box.max, a); a += dir) { \
+ for (s32 b = GETS(box.min, b); b <= GETS(box.max, b); b++) { \
+ for (s32 c = GETS(box.min, c); c <= GETS(box.max, c); c++) { \
+ if (is_solid(player->client->map, x, y, z)) { \
+ GETF(player->pos, a) = (f32) a - offset - 0.5f * (f32) dir; \
+ GETF(player->velocity, a) = 0.0f; \
+ goto a ## _physics_done; \
+ } \
+ } \
+ } \
+ } \
+ a ## _physics_done: (void) 0;\
}
- CALC_PHYSICS(player->pos.x, player->velocity.x, old_pos.x, old_velocity.x)
- CALC_PHYSICS(player->pos.y, player->velocity.y, old_pos.y, old_velocity.y)
- CALC_PHYSICS(player->pos.z, player->velocity.z, old_pos.z, old_velocity.z)
+ PHYSICS(x, y, z)
+ PHYSICS(y, x, z)
+ PHYSICS(z, x, y)
-#undef CALC_PHYSICS
+#undef GETS
+#undef GETF
+#undef PHYSICS
- if (old_pos.x != player->pos.x || old_pos.y != player->pos.y || old_pos.z != player->pos.z) {
- clientplayer_send_pos(player);
- set_camera_position((v3f) {player->pos.x, player->pos.y + player->eye_height, player->pos.z});
- }
+ if (old_pos.x != player->pos.x || old_pos.y != player->pos.y || old_pos.z != player->pos.z)
+ update_pos(player);
}
#ifndef _CLIENTPLAYER_H_
#define _CLIENTPLAYER_H_
+#include "mesh.h"
#include "types.h"
typedef struct
aabb3f box;
f32 yaw, pitch;
f32 eye_height;
+ MeshObject *obj;
} ClientPlayer;
void clientplayer_init(struct Client *client);
-void clientplayer_send_pos(ClientPlayer *player);
+void clientplayer_add_to_scene(ClientPlayer *player);
+void clientplayer_jump(ClientPlayer *player);
void clientplayer_tick(ClientPlayer *player, f64 dtime);
#endif
--- /dev/null
+#include "cube.h"
+
+Vertex cube_vertices[6][6] = {
+ {
+ {-0.5, -0.5, -0.5, +0.0, +0.0},
+ {+0.5, -0.5, -0.5, +1.0, +0.0},
+ {+0.5, +0.5, -0.5, +1.0, +1.0},
+ {+0.5, +0.5, -0.5, +1.0, +1.0},
+ {-0.5, +0.5, -0.5, +0.0, +1.0},
+ {-0.5, -0.5, -0.5, +0.0, +0.0},
+ },
+ {
+ {-0.5, -0.5, +0.5, +0.0, +0.0},
+ {+0.5, +0.5, +0.5, +1.0, +1.0},
+ {+0.5, -0.5, +0.5, +1.0, +0.0},
+ {+0.5, +0.5, +0.5, +1.0, +1.0},
+ {-0.5, -0.5, +0.5, +0.0, +0.0},
+ {-0.5, +0.5, +0.5, +0.0, +1.0},
+ },
+ {
+ {-0.5, +0.5, +0.5, +1.0, +1.0},
+ {-0.5, -0.5, -0.5, +0.0, +0.0},
+ {-0.5, +0.5, -0.5, +0.0, +1.0},
+ {-0.5, -0.5, -0.5, +0.0, +0.0},
+ {-0.5, +0.5, +0.5, +1.0, +1.0},
+ {-0.5, -0.5, +0.5, +1.0, +0.0},
+ },
+ {
+ {+0.5, +0.5, +0.5, +1.0, +1.0},
+ {+0.5, +0.5, -0.5, +0.0, +1.0},
+ {+0.5, -0.5, -0.5, +0.0, +0.0},
+ {+0.5, -0.5, -0.5, +0.0, +0.0},
+ {+0.5, -0.5, +0.5, +1.0, +0.0},
+ {+0.5, +0.5, +0.5, +1.0, +1.0},
+ },
+ {
+ {-0.5, -0.5, -0.5, +0.0, +1.0},
+ {+0.5, -0.5, -0.5, +1.0, +1.0},
+ {+0.5, -0.5, +0.5, +1.0, +0.0},
+ {+0.5, -0.5, +0.5, +1.0, +0.0},
+ {-0.5, -0.5, +0.5, +0.0, +0.0},
+ {-0.5, -0.5, -0.5, +0.0, +1.0},
+ },
+ {
+ {-0.5, +0.5, -0.5, +0.0, +1.0},
+ {+0.5, +0.5, -0.5, +1.0, +1.0},
+ {+0.5, +0.5, +0.5, +1.0, +0.0},
+ {+0.5, +0.5, +0.5, +1.0, +0.0},
+ {-0.5, +0.5, +0.5, +0.0, +0.0},
+ {-0.5, +0.5, -0.5, +0.0, +1.0},
+ },
+};
+
--- /dev/null
+#ifndef _CUBE_H_
+#define _CUBE_H_
+
+#include "mesh.h"
+
+extern Vertex cube_vertices[6][6];
+
+#endif
{
facecache.size = 0;
facecache.positions = array_create(sizeof(v3s32));
- v3s32 pos = {0};
+ v3s32 pos = {0, 0, 0};
array_append(&facecache.positions, &pos);
pthread_mutex_init(&facecache.mtx, NULL);
}
size_t get_face_count(u32 size)
{
size_t len = 1 + size * 2;
- return len * len * len;
+ return 1 + len * len * len;
}
static bool move(int forward, int backward, vec3 dir)
{
f32 sign;
- f32 speed = 10.0f;
+ f32 speed = 4.0f;
if (glfwGetKey(input.window, forward) == GLFW_PRESS)
sign = +1.0f;
return false;
input.client->player.velocity.x += dir[0] * speed * sign;
- // input.client->player.velocity.y += dir[1] * speed * sign;
input.client->player.velocity.z += dir[2] * speed * sign;
return true;
void process_input()
{
input.client->player.velocity.x = 0.0f;
- // input.client->player.velocity.y = 0.0f;
input.client->player.velocity.z = 0.0f;
move(GLFW_KEY_W, GLFW_KEY_S, movement_dirs.front);
- move(GLFW_KEY_SPACE, GLFW_KEY_LEFT_SHIFT, movement_dirs.up);
move(GLFW_KEY_D, GLFW_KEY_A, movement_dirs.right);
+
+ if (glfwGetKey(input.window, GLFW_KEY_SPACE) == GLFW_PRESS)
+ clientplayer_jump(&input.client->player);
}
void init_input(Client *client, GLFWwindow *window)
obj->rot = (v3f) {0.0f, 0.0f, 0.0f};
obj->scale = (v3f) {1.0f, 1.0f, 1.0f};
obj->angle = 0.0f;
+ obj->visible = true;
meshobject_transform(obj);
qsort(buffer.faces.ptr, buffer.faces.siz, sizeof(Face), &qsort_compare_faces);
void meshobject_render(MeshObject *obj, ShaderProgram *prog)
{
+ if (! obj->visible)
+ return;
+
glUniformMatrix4fv(prog->loc_model, 1, GL_FALSE, obj->transform[0]);
glActiveTexture(GL_TEXTURE0);
{
v3f pos, rot, scale;
f32 angle;
+ bool visible;
mat4x4 transform;
bool remove;
Mesh **meshes;