From 68694a9c9d7d27d3b79c7b96bb67f56db2f75c45 Mon Sep 17 00:00:00 2001 From: untodesu Date: Thu, 11 Sep 2025 18:18:08 +0500 Subject: Metadata voxels! --- game/shared/world/voxel.hh | 236 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 game/shared/world/voxel.hh (limited to 'game/shared/world/voxel.hh') diff --git a/game/shared/world/voxel.hh b/game/shared/world/voxel.hh new file mode 100644 index 0000000..0bd83b7 --- /dev/null +++ b/game/shared/world/voxel.hh @@ -0,0 +1,236 @@ +#pragma once + +#include "core/math/aabb.hh" + +#include "shared/types.hh" + +namespace world +{ +class Dimension; +} // namespace world + +namespace world +{ +enum VoxelRender : unsigned short { + VRENDER_NONE = 0U, ///< The voxel is not rendered at all + VRENDER_OPAQUE, ///< The voxel is fully opaque + VRENDER_BLEND, ///< The voxel is blended (e.g. water, glass) +}; + +enum VoxelShape : unsigned short { + VSHAPE_CUBE = 0U, ///< Full cube shape + VSHAPE_CROSS, ///< TODO: Cross shape + VSHAPE_MODEL, ///< TODO: Custom model shape +}; + +enum VoxelFace : unsigned short { + VFACE_NORTH = 0U, ///< Positive Z face + VFACE_SOUTH, ///< Negative Z face + VFACE_EAST, ///< Positive X face + VFACE_WEST, ///< Negative X face + VFACE_TOP, ///< Positive Y face + VFACE_BOTTOM, ///< Negative Y face + VFACE_CROSS_NWSE, ///< Diagonal cross face northwest-southeast + VFACE_CROSS_NESW, ///< Diagonal cross face northeast-southwest + VFACE_COUNT +}; + +enum VoxelTouch : unsigned short { + VTOUCH_NONE = 0xFFFFU, + VTOUCH_SOLID = 0U, ///< The entity is stopped in its tracks + VTOUCH_BOUNCE, ///< The entity bounces back with some energy loss + VTOUCH_SINK, ///< The entity phases/sinks through the voxel +}; + +enum VoxelMaterial : unsigned short { + VMAT_DEFAULT = 0U, + VMAT_STONE, + VMAT_DIRT, + VMAT_GLASS, + VMAT_GRASS, + VMAT_GRAVEL, + VMAT_METAL, + VMAT_SAND, + VMAT_WOOD, + VMAT_SLOSH, + VMAT_COUNT +}; + +enum VoxelVisBits : unsigned short { + VVIS_NORTH = 1U << VFACE_NORTH, ///< Positive Z + VVIS_SOUTH = 1U << VFACE_SOUTH, ///< Negative Z + VVIS_EAST = 1U << VFACE_EAST, ///< Positive X + VVIS_WEST = 1U << VFACE_WEST, ///< Negative X + VVIS_UP = 1U << VFACE_TOP, ///< Positive Y + VVIS_DOWN = 1U << VFACE_BOTTOM, ///< Negative Y +}; +} // namespace world + +namespace world +{ +class Voxel { +public: + /// Called when the voxel is placed in the world + /// @param dimension The dimension the voxel is placed in + /// @param vpos The absolute voxel position where the voxel is placed + virtual void on_place(Dimension* dimension, const voxel_pos& vpos) const; + + /// Called when the voxel is removed from the world + /// @param dimension The dimension the voxel is removed from + /// @param vpos The absolute voxel position where the voxel is removed + virtual void on_remove(Dimension* dimension, const voxel_pos& vpos) const; + + /// Called when the voxel is ticked by something + /// @param dimension The dimension the voxel is ticked in + /// @param vpos The absolute voxel position where the voxel is ticked + virtual void on_tick(Dimension* dimension, const voxel_pos& vpos) const; + + constexpr std::string_view get_name(void) const noexcept; + constexpr voxel_id get_id(void) const noexcept; + void set_id(voxel_id id) noexcept; + + constexpr VoxelRender get_render_mode(void) const noexcept; + constexpr VoxelShape get_shape(void) const noexcept; + constexpr bool is_animated(void) const noexcept; + + constexpr VoxelTouch get_touch_type(void) const noexcept; + constexpr const glm::fvec3& get_touch_values(void) const noexcept; + constexpr VoxelMaterial get_surface_material(void) const noexcept; + + constexpr const math::AABBf& get_collision(void) const noexcept; + + constexpr const std::vector& get_default_textures(void) const noexcept; + constexpr const std::vector& get_face_textures(VoxelFace face) const noexcept; + constexpr std::size_t get_cached_face_offset(VoxelFace face) const noexcept; + constexpr std::size_t get_cached_face_plane(VoxelFace face) const noexcept; + + /// Non-model voxel shapes support texture variation based on the + /// voxel position on the world; this method handles the math behind this + /// @param face The face of the voxel to get the texture index for + /// @param vpos The absolute voxel position to get the texture index for + /// @return The index of the texture to use for the given face at the given position + /// @remarks On client-side: plane[get_cached_face_plane][get_cached_face_offset + thisFunctionResult] + std::size_t get_random_texture_index(VoxelFace face, const voxel_pos& vpos) const; + + /// Assign cached plane index and plane offset for a given face + /// @param face The face to assign the cache for + /// @param offset The offset to assign to the face + /// @param plane The plane index to assign to the face + void set_face_cache(VoxelFace face, std::size_t offset, std::size_t plane); + + /// Calculate a checksum for the voxel's properties + /// @param combine An optional initial checksum to combine with + /// @return The calculated checksum + std::uint64_t calculate_checksum(std::uint64_t combine = 0U) const; + + /// Produce a copy of itself as a shared pointer; the voxel registry + /// does not change the owner of a voxel instance it registers + virtual std::shared_ptr clone(void) const; + +protected: + void set_name(std::string_view name) noexcept; + + void set_render_mode(VoxelRender mode) noexcept; + void set_shape(VoxelShape shape) noexcept; + void set_animated(bool animated) noexcept; + + void set_touch_type(VoxelTouch type) noexcept; + void set_touch_values(const glm::fvec3& values) noexcept; + void set_surface_material(VoxelMaterial material) noexcept; + + void set_collision(const math::AABBf& box) noexcept; + + void add_default_texture(std::string_view path); + void add_face_texture(VoxelFace face, std::string_view path); + +private: + std::string m_name; + voxel_id m_id { NULL_VOXEL_ID }; + + VoxelRender m_render_mode { VRENDER_OPAQUE }; + VoxelShape m_shape { VSHAPE_CUBE }; + bool m_animated { false }; + + VoxelTouch m_touch_type { VTOUCH_SOLID }; + glm::fvec3 m_touch_values { 0.0f }; + VoxelMaterial m_surface_material { VMAT_DEFAULT }; + + math::AABBf m_collision { { 0.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f } }; + + std::vector m_default_textures; + std::array, VFACE_COUNT> m_face_textures; + std::array m_cached_face_offsets; + std::array m_cached_face_planes; +}; +} // namespace world + +constexpr std::string_view world::Voxel::get_name(void) const noexcept +{ + return m_name; +} + +constexpr voxel_id world::Voxel::get_id(void) const noexcept +{ + return m_id; +} + +constexpr world::VoxelRender world::Voxel::get_render_mode(void) const noexcept +{ + return m_render_mode; +} + +constexpr world::VoxelShape world::Voxel::get_shape(void) const noexcept +{ + return m_shape; +} + +constexpr bool world::Voxel::is_animated(void) const noexcept +{ + return m_animated; +} + +constexpr world::VoxelTouch world::Voxel::get_touch_type(void) const noexcept +{ + return m_touch_type; +} + +constexpr const glm::fvec3& world::Voxel::get_touch_values(void) const noexcept +{ + return m_touch_values; +} + +constexpr world::VoxelMaterial world::Voxel::get_surface_material(void) const noexcept +{ + return m_surface_material; +} + +constexpr const math::AABBf& world::Voxel::get_collision(void) const noexcept +{ + return m_collision; +} + +constexpr const std::vector& world::Voxel::get_default_textures(void) const noexcept +{ + return m_default_textures; +} + +constexpr const std::vector& world::Voxel::get_face_textures(VoxelFace face) const noexcept +{ + assert(face <= m_face_textures.size()); + + return m_face_textures[face]; +} + +constexpr std::size_t world::Voxel::get_cached_face_offset(VoxelFace face) const noexcept +{ + assert(face <= m_cached_face_offsets.size()); + + return m_cached_face_offsets[face]; +} + +constexpr std::size_t world::Voxel::get_cached_face_plane(VoxelFace face) const noexcept +{ + assert(face <= m_cached_face_planes.size()); + + return m_cached_face_planes[face]; +} -- cgit From e9076f22fe2a49d1cd8933e54b7b00c5dd943269 Mon Sep 17 00:00:00 2001 From: untodesu Date: Fri, 12 Sep 2025 13:33:52 +0500 Subject: It compiles --- game/shared/world/voxel.hh | 130 +++++++++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 40 deletions(-) (limited to 'game/shared/world/voxel.hh') diff --git a/game/shared/world/voxel.hh b/game/shared/world/voxel.hh index 0bd83b7..9cc0e4c 100644 --- a/game/shared/world/voxel.hh +++ b/game/shared/world/voxel.hh @@ -11,19 +11,19 @@ class Dimension; namespace world { -enum VoxelRender : unsigned short { +enum VoxelRender : unsigned int { VRENDER_NONE = 0U, ///< The voxel is not rendered at all VRENDER_OPAQUE, ///< The voxel is fully opaque VRENDER_BLEND, ///< The voxel is blended (e.g. water, glass) }; -enum VoxelShape : unsigned short { +enum VoxelShape : unsigned int { VSHAPE_CUBE = 0U, ///< Full cube shape VSHAPE_CROSS, ///< TODO: Cross shape VSHAPE_MODEL, ///< TODO: Custom model shape }; -enum VoxelFace : unsigned short { +enum VoxelFace : unsigned int { VFACE_NORTH = 0U, ///< Positive Z face VFACE_SOUTH, ///< Negative Z face VFACE_EAST, ///< Positive X face @@ -35,14 +35,15 @@ enum VoxelFace : unsigned short { VFACE_COUNT }; -enum VoxelTouch : unsigned short { +enum VoxelTouch : unsigned int { VTOUCH_NONE = 0xFFFFU, VTOUCH_SOLID = 0U, ///< The entity is stopped in its tracks VTOUCH_BOUNCE, ///< The entity bounces back with some energy loss VTOUCH_SINK, ///< The entity phases/sinks through the voxel }; -enum VoxelMaterial : unsigned short { +enum VoxelMaterial : unsigned int { + VMAT_UNKNOWN = 0xFFFFU, VMAT_DEFAULT = 0U, VMAT_STONE, VMAT_DIRT, @@ -56,7 +57,7 @@ enum VoxelMaterial : unsigned short { VMAT_COUNT }; -enum VoxelVisBits : unsigned short { +enum VoxelVisBits : unsigned int { VVIS_NORTH = 1U << VFACE_NORTH, ///< Positive Z VVIS_SOUTH = 1U << VFACE_SOUTH, ///< Negative Z VVIS_EAST = 1U << VFACE_EAST, ///< Positive X @@ -66,28 +67,26 @@ enum VoxelVisBits : unsigned short { }; } // namespace world +namespace world +{ +using VoxelOnPlaceFunc = std::function; +using VoxelOnRemoveFunc = std::function; +using VoxelOnTickFunc = std::function; +} // namespace world + namespace world { class Voxel { public: - /// Called when the voxel is placed in the world - /// @param dimension The dimension the voxel is placed in - /// @param vpos The absolute voxel position where the voxel is placed - virtual void on_place(Dimension* dimension, const voxel_pos& vpos) const; - - /// Called when the voxel is removed from the world - /// @param dimension The dimension the voxel is removed from - /// @param vpos The absolute voxel position where the voxel is removed - virtual void on_remove(Dimension* dimension, const voxel_pos& vpos) const; + Voxel(void) = default; + explicit Voxel(const Voxel& source, voxel_id id) noexcept; - /// Called when the voxel is ticked by something - /// @param dimension The dimension the voxel is ticked in - /// @param vpos The absolute voxel position where the voxel is ticked - virtual void on_tick(Dimension* dimension, const voxel_pos& vpos) const; + void on_place(Dimension* dimension, const voxel_pos& vpos) const; + void on_remove(Dimension* dimension, const voxel_pos& vpos) const; + void on_tick(Dimension* dimension, const voxel_pos& vpos) const; constexpr std::string_view get_name(void) const noexcept; constexpr voxel_id get_id(void) const noexcept; - void set_id(voxel_id id) noexcept; constexpr VoxelRender get_render_mode(void) const noexcept; constexpr VoxelShape get_shape(void) const noexcept; @@ -104,6 +103,15 @@ public: constexpr std::size_t get_cached_face_offset(VoxelFace face) const noexcept; constexpr std::size_t get_cached_face_plane(VoxelFace face) const noexcept; + template + constexpr bool is_render_mode(void) const noexcept; + template + constexpr bool is_shape(void) const noexcept; + template + constexpr bool is_touch_type(void) const noexcept; + template + constexpr bool is_surface_material(void) const noexcept; + /// Non-model voxel shapes support texture variation based on the /// voxel position on the world; this method handles the math behind this /// @param face The face of the voxel to get the texture index for @@ -123,27 +131,7 @@ public: /// @return The calculated checksum std::uint64_t calculate_checksum(std::uint64_t combine = 0U) const; - /// Produce a copy of itself as a shared pointer; the voxel registry - /// does not change the owner of a voxel instance it registers - virtual std::shared_ptr clone(void) const; - protected: - void set_name(std::string_view name) noexcept; - - void set_render_mode(VoxelRender mode) noexcept; - void set_shape(VoxelShape shape) noexcept; - void set_animated(bool animated) noexcept; - - void set_touch_type(VoxelTouch type) noexcept; - void set_touch_values(const glm::fvec3& values) noexcept; - void set_surface_material(VoxelMaterial material) noexcept; - - void set_collision(const math::AABBf& box) noexcept; - - void add_default_texture(std::string_view path); - void add_face_texture(VoxelFace face, std::string_view path); - -private: std::string m_name; voxel_id m_id { NULL_VOXEL_ID }; @@ -161,6 +149,40 @@ private: std::array, VFACE_COUNT> m_face_textures; std::array m_cached_face_offsets; std::array m_cached_face_planes; + + VoxelOnPlaceFunc m_on_place; + VoxelOnRemoveFunc m_on_remove; + VoxelOnTickFunc m_on_tick; +}; +} // namespace world + +namespace world +{ +class VoxelBuilder final : public Voxel { +public: + VoxelBuilder(void) = default; + explicit VoxelBuilder(std::string_view name); + + VoxelBuilder& set_on_place(VoxelOnPlaceFunc func) noexcept; + VoxelBuilder& set_on_remove(VoxelOnRemoveFunc func) noexcept; + VoxelBuilder& set_on_tick(VoxelOnTickFunc func) noexcept; + + VoxelBuilder& set_name(std::string_view name) noexcept; + + VoxelBuilder& set_render_mode(VoxelRender mode) noexcept; + VoxelBuilder& set_shape(VoxelShape shape) noexcept; + VoxelBuilder& set_animated(bool animated) noexcept; + + VoxelBuilder& set_touch_type(VoxelTouch type) noexcept; + VoxelBuilder& set_touch_values(const glm::fvec3& values) noexcept; + VoxelBuilder& set_surface_material(VoxelMaterial material) noexcept; + + VoxelBuilder& set_collision(const math::AABBf& box) noexcept; + + VoxelBuilder& add_default_texture(std::string_view path); + VoxelBuilder& add_face_texture(VoxelFace face, std::string_view path); + + std::unique_ptr build(voxel_id id) const; }; } // namespace world @@ -218,6 +240,10 @@ constexpr const std::vector& world::Voxel::get_face_textures(VoxelF { assert(face <= m_face_textures.size()); + if(m_face_textures[face].empty()) { + return m_default_textures; + } + return m_face_textures[face]; } @@ -234,3 +260,27 @@ constexpr std::size_t world::Voxel::get_cached_face_plane(VoxelFace face) const return m_cached_face_planes[face]; } + +template +constexpr bool world::Voxel::is_render_mode(void) const noexcept +{ + return m_render_mode == RenderMode; +} + +template +constexpr bool world::Voxel::is_shape(void) const noexcept +{ + return m_shape == Shape; +} + +template +constexpr bool world::Voxel::is_touch_type(void) const noexcept +{ + return m_touch_type == TouchType; +} + +template +constexpr bool world::Voxel::is_surface_material(void) const noexcept +{ + return m_surface_material == Material; +} -- cgit From 73cbcdd6e8c849e32abbf9757e603e6a6654e870 Mon Sep 17 00:00:00 2001 From: untodesu Date: Fri, 12 Sep 2025 14:09:34 +0500 Subject: Metaitems --- game/shared/world/voxel.hh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'game/shared/world/voxel.hh') diff --git a/game/shared/world/voxel.hh b/game/shared/world/voxel.hh index 9cc0e4c..6013962 100644 --- a/game/shared/world/voxel.hh +++ b/game/shared/world/voxel.hh @@ -129,7 +129,7 @@ public: /// Calculate a checksum for the voxel's properties /// @param combine An optional initial checksum to combine with /// @return The calculated checksum - std::uint64_t calculate_checksum(std::uint64_t combine = 0U) const; + std::uint64_t get_checksum(std::uint64_t combine = 0U) const; protected: std::string m_name; @@ -163,24 +163,24 @@ public: VoxelBuilder(void) = default; explicit VoxelBuilder(std::string_view name); - VoxelBuilder& set_on_place(VoxelOnPlaceFunc func) noexcept; - VoxelBuilder& set_on_remove(VoxelOnRemoveFunc func) noexcept; - VoxelBuilder& set_on_tick(VoxelOnTickFunc func) noexcept; + void set_on_place(VoxelOnPlaceFunc func) noexcept; + void set_on_remove(VoxelOnRemoveFunc func) noexcept; + void set_on_tick(VoxelOnTickFunc func) noexcept; - VoxelBuilder& set_name(std::string_view name) noexcept; + void set_name(std::string_view name) noexcept; - VoxelBuilder& set_render_mode(VoxelRender mode) noexcept; - VoxelBuilder& set_shape(VoxelShape shape) noexcept; - VoxelBuilder& set_animated(bool animated) noexcept; + void set_render_mode(VoxelRender mode) noexcept; + void set_shape(VoxelShape shape) noexcept; + void set_animated(bool animated) noexcept; - VoxelBuilder& set_touch_type(VoxelTouch type) noexcept; - VoxelBuilder& set_touch_values(const glm::fvec3& values) noexcept; - VoxelBuilder& set_surface_material(VoxelMaterial material) noexcept; + void set_touch_type(VoxelTouch type) noexcept; + void set_touch_values(const glm::fvec3& values) noexcept; + void set_surface_material(VoxelMaterial material) noexcept; - VoxelBuilder& set_collision(const math::AABBf& box) noexcept; + void set_collision(const math::AABBf& box) noexcept; - VoxelBuilder& add_default_texture(std::string_view path); - VoxelBuilder& add_face_texture(VoxelFace face, std::string_view path); + void add_default_texture(std::string_view path); + void add_face_texture(VoxelFace face, std::string_view path); std::unique_ptr build(voxel_id id) const; }; -- cgit