Merge branch 'main' into physics-upgrade

This commit is contained in:
MihailRis 2026-03-02 21:52:17 +03:00
commit 6676db3525
21 changed files with 249 additions and 53 deletions

View file

@ -140,6 +140,22 @@ VC_ENUM_METADATA(CullingMode)
{"disabled", CullingMode::DISABLED},
VC_ENUM_END
/// @brief Grounding behaviour for extended blocks
enum class GroundingBehaviour : uint8_t {
/// @brief at least one segment must be grounded
PARTIAL,
/// @brief all segments must be grounded
COMPLETE,
/// @brief origin segment must be grounded
ORIGIN
};
VC_ENUM_METADATA(GroundingBehaviour)
{"partial", GroundingBehaviour::PARTIAL},
{"complete", GroundingBehaviour::COMPLETE},
{"origin", GroundingBehaviour::ORIGIN},
VC_ENUM_END
/// @brief Common kit of block properties applied to groups of blocks
struct BlockMaterial : Serializable {
std::string name;
@ -239,6 +255,9 @@ public:
/// @brief Explicitly overriding 'solid' property if true assigned
bool explictlySolid = false;
/// @brief Grounding behaviour
GroundingBehaviour groundingBehaviour = GroundingBehaviour::PARTIAL;
/// @brief Set of block physical hitboxes
std::vector<AABB> hitboxes {AABB()};

View file

@ -95,7 +95,6 @@ inline const Block& get_block_def(const Storage& chunks, blockid_t id) {
return chunks.getContentIndices().blocks.require(id);
}
/// @brief Check if block at specified position is solid.
/// @tparam Storage chunks storage class
/// @param chunks chunks storage
@ -103,8 +102,10 @@ inline const Block& get_block_def(const Storage& chunks, blockid_t id) {
/// @param y position Y
/// @param z position Z
/// @return true if block exists and solid
template<class Storage>
inline bool is_solid_at(const Storage& chunks, int32_t x, int32_t y, int32_t z) {
template <class Storage>
inline bool is_solid_at(
const Storage& chunks, int32_t x, int32_t y, int32_t z
) {
if (auto vox = get(chunks, x, y, z)) {
return get_block_def(chunks, vox->id).rt.solid;
}
@ -118,8 +119,10 @@ inline bool is_solid_at(const Storage& chunks, int32_t x, int32_t y, int32_t z)
/// @param y position Y
/// @param z position Z
/// @return true if block exists and replaceable
template<class Storage>
inline bool is_replaceable_at(const Storage& chunks, int32_t x, int32_t y, int32_t z) {
template <class Storage>
inline bool is_replaceable_at(
const Storage& chunks, int32_t x, int32_t y, int32_t z
) {
if (auto vox = get(chunks, x, y, z)) {
return get_block_def(chunks, vox->id).replaceable;
}
@ -455,12 +458,18 @@ voxel* raycast(
bool includeNonSelectable
);
void get_voxels(const Chunks& chunks, VoxelsVolume* volume, bool backlight=false);
void get_voxels(
const Chunks& chunks, VoxelsVolume* volume, bool backlight = false
);
void get_voxels(const GlobalChunks& chunks, VoxelsVolume* volume, bool backlight=false);
void get_voxels(
const GlobalChunks& chunks, VoxelsVolume* volume, bool backlight = false
);
template <class Storage>
inline std::optional<AABB> is_obstacle_at(const Storage& chunks, float x, float y, float z, const AABB& aabb) {
inline std::optional<AABB> is_obstacle_at(
const Storage& chunks, float x, float y, float z, const AABB& aabb
) {
int ix = std::floor(x);
int iy = std::floor(y);
int iz = std::floor(z);
@ -497,4 +506,63 @@ inline std::optional<AABB> is_obstacle_at(const Storage& chunks, float x, float
return is_obstacle_at(chunks, x, y, z, AABB({x, y, z}, {x + 1, y + 1, z + 1}));
}
/// @brief Check block grounding
/// @tparam Storage chunks storage class
/// @param chunks chunks storage
/// @param def block definition
/// @param rotationIndex target block rotation index
/// @param origin target block origin
/// @return true if grounded
template <class Storage>
inline bool check_grounding(
const Storage& chunks,
const Block& def,
uint8_t rotationIndex,
const glm::ivec3& origin
) {
const auto& vec = get_ground_direction(def, rotationIndex);
if (!def.rt.extended) {
return blocks_agent::is_solid_at(
chunks, origin.x + vec.x, origin.y + vec.y, origin.z + vec.z
);
}
const auto& rotation = def.rotations.variants[rotationIndex];
if (def.groundingBehaviour == GroundingBehaviour::PARTIAL) {
for (int sz = 0; sz < def.size.z; sz++) {
for (int sx = 0; sx < def.size.x; sx++) {
auto pos = origin;
pos += rotation.axes[0] * sx;
pos += rotation.axes[2] * sz;
if (blocks_agent::is_solid_at(
chunks, pos.x + vec.x, pos.y + vec.y, pos.z + vec.z
)) {
return true;
}
}
}
return false;
} else if (def.groundingBehaviour == GroundingBehaviour::COMPLETE) {
for (int sz = 0; sz < def.size.z; sz++) {
for (int sx = 0; sx < def.size.x; sx++) {
auto pos = origin;
pos += rotation.axes[0] * sx;
pos += rotation.axes[2] * sz;
if (!blocks_agent::is_solid_at(
chunks, pos.x + vec.x, pos.y + vec.y, pos.z + vec.z
)) {
return false;
}
}
}
return true;
} else {
return blocks_agent::is_solid_at(
chunks, origin.x + vec.x, origin.y + vec.y, origin.z + vec.z
);
}
}
} // blocks_agent