diff --git a/deerith_engine_core/include/deerith/world/environment.h b/deerith_engine_core/include/deerith/world/environment.h new file mode 100644 index 0000000..28549a0 --- /dev/null +++ b/deerith_engine_core/include/deerith/world/environment.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include + +namespace deerith +{ + using voxel_coordinates_t = glm::ivec3; + using surface_coordinates_t = glm::ivec2; + + // This sets the terrain layer for default comosition y > height -> 0; y <= height -> 1 + void set_surface_height(surface_coordinates_t surface_pos, int height); + void set_voxel(voxel_type_id_t voxel_id, voxel_coordinates_t coordinates); + + voxel_type_id_t get_voxel_id(voxel_coordinates_t coordinates); + const voxel_type_t &get_voxel(voxel_coordinates_t coordinates); +} \ No newline at end of file diff --git a/deerith_engine_core/include/deerith/world/voxel_world.h b/deerith_engine_core/include/deerith/world/voxel_world.h deleted file mode 100644 index 204568d..0000000 --- a/deerith_engine_core/include/deerith/world/voxel_world.h +++ /dev/null @@ -1,6 +0,0 @@ -#include - -namespace deerith -{ - void init_world(); -} \ No newline at end of file diff --git a/deerith_engine_core/include/deerith/world/voxels.h b/deerith_engine_core/include/deerith/world/voxels.h index e336656..bbccf9f 100644 --- a/deerith_engine_core/include/deerith/world/voxels.h +++ b/deerith_engine_core/include/deerith/world/voxels.h @@ -12,7 +12,7 @@ namespace deerith enum class voxel_material_type_t : int { AIR = 0, - OPAQUE_BOX = 1 + SOLID = 1 }; struct voxel_material_t diff --git a/deerith_engine_core/include/deerith/world/world_core.h b/deerith_engine_core/include/deerith/world/world_core.h index 2db9faa..d476083 100644 --- a/deerith_engine_core/include/deerith/world/world_core.h +++ b/deerith_engine_core/include/deerith/world/world_core.h @@ -39,4 +39,6 @@ namespace deerith component_network_id_t &add_entity_network_with_id(entity_t ent, id_t id); entity_t get_network_entity_with_id(id_t id); bool exists_network_entity_with_id(id_t id); + + void init_world(); } diff --git a/deerith_engine_core/src/server_execution.cpp b/deerith_engine_core/src/core/execution.cpp similarity index 100% rename from deerith_engine_core/src/server_execution.cpp rename to deerith_engine_core/src/core/execution.cpp diff --git a/deerith_engine_core/src/log.cpp b/deerith_engine_core/src/core/log.cpp similarity index 94% rename from deerith_engine_core/src/log.cpp rename to deerith_engine_core/src/core/log.cpp index eb09e7f..d1444e3 100644 --- a/deerith_engine_core/src/log.cpp +++ b/deerith_engine_core/src/core/log.cpp @@ -1,5 +1,5 @@ #include "deerith/core/log.h" -#include "internal.h" +#include "../internal.h" #include diff --git a/deerith_engine_core/src/tick.cpp b/deerith_engine_core/src/core/tick.cpp similarity index 100% rename from deerith_engine_core/src/tick.cpp rename to deerith_engine_core/src/core/tick.cpp diff --git a/deerith_engine_core/src/router.cpp b/deerith_engine_core/src/network/router.cpp similarity index 100% rename from deerith_engine_core/src/router.cpp rename to deerith_engine_core/src/network/router.cpp diff --git a/deerith_engine_core/src/world/environment.cpp b/deerith_engine_core/src/world/environment.cpp new file mode 100644 index 0000000..fc3a842 --- /dev/null +++ b/deerith_engine_core/src/world/environment.cpp @@ -0,0 +1,220 @@ +#include +#include + +#include +#include +#include +#include + +#define CLUSTER_SIZE 32 +#define MAX_CLUSTER_IN_SURFACE 16 +#define STARTING_CLUSTER_HEIGHT 8 + +namespace deerith +{ + using surface_id_t = glm::ivec2; + using internal_voxel_id_t = glm::ivec3; + + struct voxel_cluster_t + { + voxel_type_id_t data[CLUSTER_SIZE][CLUSTER_SIZE][CLUSTER_SIZE] = {}; + }; + + struct surface_t + { + surface_id_t surface_id; + + int layer_height[CLUSTER_SIZE][CLUSTER_SIZE] = {}; + std::unique_ptr voxel_clusters[MAX_CLUSTER_IN_SURFACE] = {}; + }; + + std::vector> surfaces; + std::unordered_map surface_id_index_map; + + voxel_type_id_t get_default_voxel(voxel_coordinates_t); + + surface_id_t get_surface_id(voxel_coordinates_t coords); + internal_voxel_id_t get_internal_voxel_coords(voxel_coordinates_t coords); + internal_voxel_id_t get_internal_voxel_coords(surface_coordinates_t coords, int height = 0); + size_t get_voxel_cluster_height_id(int height); + + surface_t *create_surface(surface_id_t); +} + +deerith::surface_t *deerith::create_surface(surface_id_t surface_id) +{ + std::unique_ptr new_surface = std::make_unique(); + size_t surface_index = surfaces.size(); + + surfaces.push_back(std::move(new_surface)); + surface_id_index_map[surface_id] = surface_index; + + return surfaces.back().get(); +} + +deerith::voxel_type_id_t get_default_voxel(deerith::voxel_coordinates_t coords) +{ + if (coords.y > 0) + { + return 0; + } + else + { + return 1; + } +} + +size_t deerith::get_voxel_cluster_height_id(int height) +{ + // >= MAX_CLUSTER_IN_SURFACE means out of bounds + if (height < (STARTING_CLUSTER_HEIGHT)*CLUSTER_SIZE) + { + return MAX_CLUSTER_IN_SURFACE; + } + + int normalized_height = std::floor(static_cast(height) / static_cast(CLUSTER_SIZE)); + size_t cluster_height_id = normalized_height - STARTING_CLUSTER_HEIGHT; + + return cluster_height_id; +} + +deerith::internal_voxel_id_t deerith::get_internal_voxel_coords(voxel_coordinates_t coords) +{ + // this will invert negatives coords but we don't mind + internal_voxel_id_t ic = {}; + ic.x = std::abs(coords.x % (CLUSTER_SIZE)); + ic.y = std::abs(coords.y % (CLUSTER_SIZE)); + ic.z = std::abs(coords.z % (CLUSTER_SIZE)); + + return ic; +} + +deerith::internal_voxel_id_t deerith::get_internal_voxel_coords(surface_coordinates_t coords, int height = 0) +{ + // this will invert negatives coords but we don't mind + internal_voxel_id_t ic = {}; + ic.x = std::abs(coords.x % (CLUSTER_SIZE)); + ic.y = std::abs(height % (CLUSTER_SIZE)); + ic.z = std::abs(coords.y % (CLUSTER_SIZE)); + + return ic; +} + +deerith::surface_id_t deerith::get_surface_id(voxel_coordinates_t coords) +{ + surface_id_t surface_id = {}; + surface_id.x = std::floor(static_cast(coords.x) / static_cast(CLUSTER_SIZE)); + surface_id.y = std::floor(static_cast(coords.z) / static_cast(CLUSTER_SIZE)); + + return surface_id; +} + +deerith::surface_id_t deerith::get_surface_id(surface_coordinates_t coords) +{ + surface_id_t surface_id = {}; + surface_id.x = std::floor(static_cast(coords.x) / static_cast(CLUSTER_SIZE)); + surface_id.y = std::floor(static_cast(coords.y) / static_cast(CLUSTER_SIZE)); + + return surface_id; +} + +// This sets the terrain layer for default comosition y > height -> 0; y <= height -> 1 +void deerith::set_surface_height(surface_coordinates_t surface_pos, int height) +{ + surface_id_t surface_id = get_surface_id(surface_pos); + + surface_t *surface = nullptr; + if (surface_id_index_map.contains(surface_id)) + { + size_t surface_index = surface_id_index_map[surface_id]; + surface = surfaces[surface_index].get(); + } + + if (surface == nullptr) + { + surface = create_surface(surface_id); + } + + internal_voxel_id_t internal_voxel_id = get_internal_voxel_coords(surface_pos, height); + surface->layer_height[internal_voxel_id.x][internal_voxel_id.z] = height; +} + +void deerith::set_voxel(voxel_type_id_t voxel_id, voxel_coordinates_t coordinates) +{ + surface_id_t surface_id = get_surface_id(coordinates); + + surface_t *surface = nullptr; + if (surface_id_index_map.contains(surface_id)) + { + size_t surface_index = surface_id_index_map[surface_id]; + surface = surfaces[surface_index].get(); + } + + if (surface == nullptr) + { + surface = create_surface(surface_id); + } + + internal_voxel_id_t internal_voxel_id = get_internal_voxel_coords(coordinates); + + size_t cluster_height_id = get_voxel_cluster_height_id(coordinates.y); + if (cluster_height_id >= MAX_CLUSTER_IN_SURFACE) + { + deerith_warn("tried to build out of bounds set_voxel; pos {}.{}.{}", coordinates.x, coordinates.y, coordinates.z); + return; + } + + voxel_cluster_t *cluster = surface->voxel_clusters[cluster_height_id].get(); + if (cluster == nullptr) + { + surface->voxel_clusters[cluster_height_id] = std::make_unique(); + cluster = surface->voxel_clusters[cluster_height_id].get(); + } + + cluster->data[internal_voxel_id.x][internal_voxel_id.y][internal_voxel_id.z] = voxel_id; +} + +deerith::voxel_type_id_t deerith::get_voxel_id(voxel_coordinates_t coordinates) +{ + surface_id_t surface_id = get_surface_id(coordinates); + + if (!surface_id_index_map.contains(surface_id)) + { + return get_default_voxel(coordinates); + } + + size_t surface_index = surface_id_index_map[surface_id]; + surface_t *surface = surfaces[surface_index].get(); + + if (surface == nullptr) + { + return get_default_voxel(coordinates); + } + + size_t cluster_height_id = get_voxel_cluster_height_id(coordinates.y); + if (cluster_height_id >= MAX_CLUSTER_IN_SURFACE) + { + return get_default_voxel(coordinates); + } + + internal_voxel_id_t internal_voxel_id = get_internal_voxel_coords(coordinates); + voxel_cluster_t *cluster = surface->voxel_clusters[cluster_height_id].get(); + if (cluster == nullptr) + { + if (coordinates.y <= surface->layer_height[internal_voxel_id.x][internal_voxel_id.y]) + { + return 1; + } + else + { + return 0; + } + } + + return cluster->data[internal_voxel_id.x][internal_voxel_id.y][internal_voxel_id.z]; +} + +const deerith::voxel_type_t &deerith::get_voxel(voxel_coordinates_t coordinates) +{ + return get_voxel_type(get_voxel_id(coordinates)); +} \ No newline at end of file diff --git a/deerith_engine_core/src/voxels.cpp b/deerith_engine_core/src/world/voxels.cpp similarity index 100% rename from deerith_engine_core/src/voxels.cpp rename to deerith_engine_core/src/world/voxels.cpp diff --git a/deerith_engine_core/src/world.cpp b/deerith_engine_core/src/world/world.cpp similarity index 100% rename from deerith_engine_core/src/world.cpp rename to deerith_engine_core/src/world/world.cpp diff --git a/deerith_engine_server/src/world/world.cpp b/deerith_engine_server/src/world/world.cpp index 20e1c8c..3ac7cd5 100644 --- a/deerith_engine_server/src/world/world.cpp +++ b/deerith_engine_server/src/world/world.cpp @@ -32,17 +32,16 @@ void deerith::run_world(int port) { std::signal(SIGTERM, handle_signal); - if (init_server(port)) - { - deerith_trace("server init on port {}", port); - while (running) - { - world_simulation(); - } - } - else + if (!init_server(port)) { deerith_error("could not init server"); + return; + } + + deerith_trace("server init on port {}", port); + while (running) + { + world_simulation(); } } diff --git a/sandbox/include/world.h b/sandbox/include/world.h new file mode 100644 index 0000000..3e2d9ef --- /dev/null +++ b/sandbox/include/world.h @@ -0,0 +1,6 @@ +#pragma once + +namespace sandbox +{ + void build_world(); +} \ No newline at end of file diff --git a/sandbox/src/build_world.cpp b/sandbox/src/build_world.cpp new file mode 100644 index 0000000..e69de29 diff --git a/sandbox/src/define_voxels.cpp b/sandbox/src/define_voxels.cpp index e02fdd6..81840c6 100644 --- a/sandbox/src/define_voxels.cpp +++ b/sandbox/src/define_voxels.cpp @@ -16,7 +16,7 @@ void sandbox::define_voxel_materials() { deerith::voxel_material_t voxel_material; voxel_material.id = "rock"; - voxel_material.material_type = deerith::voxel_material_type_t::OPAQUE_BOX; + voxel_material.material_type = deerith::voxel_material_type_t::SOLID; // textures... diff --git a/sandbox/src/main.cpp b/sandbox/src/main.cpp index a31910c..b558749 100644 --- a/sandbox/src/main.cpp +++ b/sandbox/src/main.cpp @@ -5,6 +5,7 @@ #include #include "voxels.h" +#include "world.h" int main(int argc, const char **argv) { @@ -17,6 +18,8 @@ int main(int argc, const char **argv) sandbox::define_voxel_materials(); sandbox::define_voxels_types(); + // sandbox::build_world(); + #ifdef DEBUG if (cmdl[{"-s", "--single"}] && !deerith::execute_client("../deerith_client/DeerithClient", port)) {