From 32781feeff8f2bf0ba8257c37159473431cf75cd Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 18 Apr 2022 22:18:40 +0200 Subject: [PATCH] Add node selection box --- deps/dragonnet | 2 +- shaders/3d/selection/fragment.glsl | 8 +++ shaders/3d/selection/vertex.glsl | 8 +++ src/CMakeLists.txt | 2 + src/client/client_node.c | 32 +++++++++++ src/client/client_node.h | 2 + src/client/client_player.c | 2 +- src/client/game.c | 7 +++ src/client/interact.c | 91 ++++++++++++++++++++++++++++++ src/client/interact.h | 9 +++ src/client/raycast.c | 46 +++++++++++++++ src/client/raycast.h | 10 ++++ src/server/biomes.c | 7 +-- 13 files changed, 218 insertions(+), 8 deletions(-) create mode 100755 shaders/3d/selection/fragment.glsl create mode 100755 shaders/3d/selection/vertex.glsl create mode 100644 src/client/interact.c create mode 100644 src/client/interact.h create mode 100644 src/client/raycast.c create mode 100644 src/client/raycast.h diff --git a/deps/dragonnet b/deps/dragonnet index 6d8f26f..431e3bd 160000 --- a/deps/dragonnet +++ b/deps/dragonnet @@ -1 +1 @@ -Subproject commit 6d8f26f523570f440152abcfab5f2839d3c6b5b0 +Subproject commit 431e3bd29073d9c10ab3a853116860ba83ed1c5e diff --git a/shaders/3d/selection/fragment.glsl b/shaders/3d/selection/fragment.glsl new file mode 100755 index 0000000..b591cd7 --- /dev/null +++ b/shaders/3d/selection/fragment.glsl @@ -0,0 +1,8 @@ +out vec4 outColor; + +uniform vec3 color; + +void main() +{ + outColor = vec4(color, 0.1); +} diff --git a/shaders/3d/selection/vertex.glsl b/shaders/3d/selection/vertex.glsl new file mode 100755 index 0000000..65dc0d2 --- /dev/null +++ b/shaders/3d/selection/vertex.glsl @@ -0,0 +1,8 @@ +layout(location = 0) in vec3 vertexPosition; + +uniform mat4 MVP; + +void main() +{ + gl_Position = MVP * vec4(vertexPosition, 1.0); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fe2de51..4b7cede 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -106,9 +106,11 @@ add_executable(dragonblocks client/gl_debug.c client/gui.c client/input.c + client/interact.c client/light.c client/mesh.c client/model.c + client/raycast.c client/shader.c client/sky.c client/terrain_gfx.c diff --git a/src/client/client_node.c b/src/client/client_node.c index 3a40619..956e18f 100644 --- a/src/client/client_node.c +++ b/src/client/client_node.c @@ -45,6 +45,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = NULL, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // air { @@ -52,6 +54,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_NONE, .mipmap = true, .render = NULL, + .pointable = false, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // grass { @@ -59,6 +63,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = &render_grass, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // dirt { @@ -66,6 +72,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = NULL, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // stone { @@ -73,6 +81,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = &render_stone, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // snow { @@ -80,6 +90,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = NULL, + .pointable = true, + .selection_color = {0.1f, 0.5f, 1.0f}, }, // oak wood { @@ -91,6 +103,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = &render_color, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // oak leaves { @@ -98,6 +112,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = &render_color, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // pine wood { @@ -109,6 +125,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = &render_color, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // pine leaves { @@ -116,6 +134,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_CLIP, .mipmap = true, .render = &render_color, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // palm wood { @@ -127,6 +147,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = &render_color, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // palm leaves { @@ -134,6 +156,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = &render_color, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // sand { @@ -141,6 +165,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = NULL, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // water { @@ -148,6 +174,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_BLEND, .mipmap = true, .render = NULL, + .pointable = false, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // lava { @@ -155,6 +183,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_BLEND, .mipmap = true, .render = NULL, + .pointable = false, + .selection_color = {1.0f, 1.0f, 1.0f}, }, // vulcano_stone { @@ -162,6 +192,8 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .visibility = VISIBILITY_SOLID, .mipmap = true, .render = NULL, + .pointable = true, + .selection_color = {1.0f, 1.0f, 1.0f}, }, }; diff --git a/src/client/client_node.h b/src/client/client_node.h index a922df4..7edcf66 100644 --- a/src/client/client_node.h +++ b/src/client/client_node.h @@ -28,6 +28,8 @@ typedef struct { NodeVisibility visibility; bool mipmap; void (*render)(NodeArgsRender *args); + bool pointable; + v3f32 selection_color; } ClientNodeDefinition; extern ClientNodeDefinition client_node_definitions[]; diff --git a/src/client/client_player.c b/src/client/client_player.c index 3bc1b46..326ab53 100644 --- a/src/client/client_player.c +++ b/src/client/client_player.c @@ -101,7 +101,7 @@ static void on_add(ClientEntity *entity) }, 7); entity->nametag_offset = bones->nametag ? &bones->nametag->abs : NULL; - entity->box_collision = (aabb3f32) {{-0.3f, 0.0f, -0.3f}, {0.3f, 1.8f, 0.3f}}; + entity->box_collision = (aabb3f32) {{-0.45f, 0.0f, -0.45f}, {0.45f, 1.8f, 0.45f}}; model_scene_add(entity->model); client_entity_transform(entity); diff --git a/src/client/game.c b/src/client/game.c index 8cd2b74..c0554eb 100644 --- a/src/client/game.c +++ b/src/client/game.c @@ -18,6 +18,7 @@ #include "client/gl_debug.h" #include "client/gui.h" #include "client/input.h" +#include "client/interact.h" #include "client/sky.h" #include "client/window.h" #include "day.h" @@ -62,6 +63,7 @@ static void render(f64 dtime) sky_render(); model_scene_render(dtime); + interact_render(); gui_render(); } @@ -89,6 +91,7 @@ static void game_loop() input_tick(dtime); client_player_tick(dtime); + interact_tick(); debug_menu_changed(ENTRY_TIME); debug_menu_changed(ENTRY_DAYLIGHT); @@ -123,6 +126,9 @@ bool game(Flag *gfx_init) client_player_gfx_init(); + if (!interact_init()) + return false; + client_node_init(); client_terrain_start(); @@ -148,6 +154,7 @@ bool game(Flag *gfx_init) terrain_gfx_deinit(); client_entity_gfx_deinit(); client_player_gfx_deinit(); + interact_deinit(); return true; } diff --git a/src/client/interact.c b/src/client/interact.c new file mode 100644 index 0000000..728bc29 --- /dev/null +++ b/src/client/interact.c @@ -0,0 +1,91 @@ +#include +#include +#include "client/camera.h" +#include "client/client_node.h" +#include "client/cube.h" +#include "client/frustum.h" +#include "client/gl_debug.h" +#include "client/interact.h" +#include "client/mesh.h" +#include "client/raycast.h" +#include "client/shader.h" + +static bool pointed; +static v3s32 node_pos; +static GLuint shader_prog; +static GLint loc_MVP; +static GLint loc_color; +static mat4x4 model; + +typedef struct { + v3f32 position; +} __attribute__((packed)) SelectionVertex; +static Mesh selection_mesh = { + .layout = &(VertexLayout) { + .attributes = (VertexAttribute[]) { + {GL_FLOAT, 3, sizeof(v3f32)}, + }, + .count = 1, + .size = sizeof(SelectionVertex), + }, + .vao = 0, + .vbo = 0, + .data = NULL, + .count = 36, + .free_data = false, +}; + +bool interact_init() +{ + if (!shader_program_create(RESSOURCE_PATH "shaders/3d/selection", &shader_prog, NULL)) { + fprintf(stderr, "[error] failed to create selection shader program\n"); + return false; + } + + loc_MVP = glGetUniformLocation(shader_prog, "MVP"); GL_DEBUG + loc_color = glGetUniformLocation(shader_prog, "color"); GL_DEBUG + + SelectionVertex vertices[6][6]; + for (int f = 0; f < 6; f++) + for (int v = 0; v < 6; v++) + vertices[f][v].position = v3f32_scale(cube_vertices[f][v].position, 1.1f); + + selection_mesh.data = vertices; + mesh_upload(&selection_mesh); + + return true; +} + +void interact_deinit() +{ + glDeleteProgram(shader_prog); GL_DEBUG + mesh_destroy(&selection_mesh); +} + +void interact_tick() +{ + v3s32 old_node_pos = node_pos; + + NodeType node; + if ((pointed = raycast( + (v3f64) {camera.eye [0], camera.eye [1], camera.eye [2]}, + (v3f64) {camera.front[0], camera.front[1], camera.front[2]}, + 5, &node_pos, &node)) && !v3s32_equals(node_pos, old_node_pos)) { + mat4x4_translate(model, node_pos.x, node_pos.y, node_pos.z); + v3f32 *color = &client_node_definitions[node].selection_color; + glProgramUniform3f(shader_prog, loc_color, color->x, color->y, color->z); GL_DEBUG + } +} + +void interact_render() +{ + if (!pointed) + return; + + mat4x4 mvp; + mat4x4_mul(mvp, frustum, model); + + glUseProgram(shader_prog); GL_DEBUG + glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, mvp[0]); GL_DEBUG + mesh_render(&selection_mesh); +} diff --git a/src/client/interact.h b/src/client/interact.h new file mode 100644 index 0000000..707bb01 --- /dev/null +++ b/src/client/interact.h @@ -0,0 +1,9 @@ +#ifndef _INTERACT_H_ +#define _INTERACT_H_ + +bool interact_init(); +void interact_deinit(); +void interact_tick(); +void interact_render(); + +#endif // _INTERACT_H_ diff --git a/src/client/raycast.c b/src/client/raycast.c new file mode 100644 index 0000000..fba282d --- /dev/null +++ b/src/client/raycast.c @@ -0,0 +1,46 @@ +#include +#include "client/client_node.h" +#include "client/client_terrain.h" +#include "client/raycast.h" + +bool raycast(v3f64 pos, v3f64 dir, f64 len, v3s32 *node_pos, NodeType *node) +{ + f64 dir_len = sqrt(dir.x * dir.x + dir.y * dir.y + dir.z * dir.z); + + while (len > 0) { + *node = terrain_get_node(client_terrain, + *node_pos = (v3s32) {floor(pos.x + 0.5), floor(pos.y + 0.5), floor(pos.z + 0.5)}).type; + + if (*node == NODE_UNLOADED) + return false; + + if (client_node_definitions[*node].pointable) + return true; + + f64 vpos[3] = {pos.x, pos.y, pos.z}; + f64 vdir[3] = {dir.x, dir.y, dir.z}; + f64 min_mul = 1.0; + + for (int i = 0; i < 3; i++) { + if (!vdir[i]) + continue; + + f64 p = vpos[i] + 0.5; + f64 d = vdir[i] / fabs(vdir[i]); + + f64 f = floor(p) - p; + if (d > 0.0) + f += 1.0; + f += 0.001 * d; + + f64 mul = f / vdir[i]; + if (min_mul > mul && mul) + min_mul = mul; + } + + pos = v3f64_add(pos, v3f64_scale(dir, min_mul)); + len -= dir_len * min_mul; + } + + return false; +} diff --git a/src/client/raycast.h b/src/client/raycast.h new file mode 100644 index 0000000..eac7e17 --- /dev/null +++ b/src/client/raycast.h @@ -0,0 +1,10 @@ +#ifndef _RAYCAST_H_ +#define _RAYCAST_H_ + +#include +#include "node.h" +#include "types.h" + +bool raycast(v3f64 pos, v3f64 dir, f64 len, v3s32 *node_pos, NodeType *node); + +#endif // _RAYCAST_H_ diff --git a/src/server/biomes.c b/src/server/biomes.c index c034257..da21675 100644 --- a/src/server/biomes.c +++ b/src/server/biomes.c @@ -215,15 +215,10 @@ static void before_chunk_hills(BiomeArgsChunk *args) memset(chunk_data->boulder_success, 0, sizeof chunk_data->boulder_success); } -static void wrap_free(void *ptr) -{ - free(ptr); -} - static void after_chunk_hills(BiomeArgsChunk *args) { HillsChunkData *chunk_data = args->chunk_data; - tree_clr(&chunk_data->boulder_visit, &wrap_free, NULL, NULL, 0); + tree_clr(&chunk_data->boulder_visit, &free, NULL, NULL, 0); } static s32 height_hills(BiomeArgsHeight *args)