Merge branch 'main' into vcm-bones

This commit is contained in:
MihailRis 2026-01-09 00:11:32 +03:00
commit 586fc8fc46
8 changed files with 52 additions and 26 deletions

View file

@ -56,6 +56,11 @@ Enables translucency support in block textures (examples: water, ice).
Should only be used when needed, as it impacts performance. Should only be used when needed, as it impacts performance.
Not required for full transparency (grass, flowers). Not required for full transparency (grass, flowers).
### *solid*
Explicitly specifies that the block is solid - completely overlapping the blocks behind it.
Used by blocks with the `custom` model type, which must support culling of invisible geometry, as with the `block` type. If `false` specified then ignored.
### *rotation* ### *rotation*
Rotation profile (set of available block rotations and behaviour of placing block rotation) from list: Rotation profile (set of available block rotations and behaviour of placing block rotation) from list:

View file

@ -57,6 +57,11 @@
Следует использовать только при надобности, так как влияет на производительность. Следует использовать только при надобности, так как влияет на производительность.
Не требуется для полной прозрачности (трава, цветы). Не требуется для полной прозрачности (трава, цветы).
### Цельность - *solid*
Явно указывает, что блок является цельным (полным) - полностью перекрывает блоки за собой.
Используется блоками с типом модели `custom`, которые должны поддерживать отсечение невидимой геометрии, как у типа `block`. Свойство игнорируется при указании `false`.
### Вращение - *rotation* ### Вращение - *rotation*
Профиль вращения (набор положений, в которые можно установить блок) из списка: Профиль вращения (набор положений, в которые можно установить блок) из списка:

View file

@ -7,7 +7,7 @@ local names = {
"hidden", "draw-group", "picking-item", "surface-replacement", "script-name", "hidden", "draw-group", "picking-item", "surface-replacement", "script-name",
"ui-layout", "inventory-size", "tick-interval", "overlay-texture", "ui-layout", "inventory-size", "tick-interval", "overlay-texture",
"translucent", "fields", "particles", "icon-type", "icon", "placing-block", "translucent", "fields", "particles", "icon-type", "icon", "placing-block",
"stack-size", "name", "script-file", "culling" "stack-size", "name", "script-file", "culling", "solid"
} }
for name, _ in pairs(user_props) do for name, _ in pairs(user_props) do
table.insert(names, name) table.insert(names, name)

View file

@ -34,11 +34,15 @@ std::unique_ptr<Content> ContentBuilder::build() {
if (def.variants) { if (def.variants) {
for (auto& variant : def.variants->variants) { for (auto& variant : def.variants->variants) {
variant.rt.solid = variant.model.type == BlockModelType::BLOCK; variant.rt.solid =
variant.model.type == BlockModelType::BLOCK ||
def.explictlySolid;
} }
def.defaults = def.variants->variants.at(0); def.defaults = def.variants->variants.at(0);
} else { } else {
def.defaults.rt.solid = def.defaults.model.type == BlockModelType::BLOCK; def.defaults.rt.solid =
def.defaults.model.type == BlockModelType::BLOCK ||
def.explictlySolid;
} }
const float EPSILON = 0.01f; const float EPSILON = 0.01f;

View file

@ -227,6 +227,7 @@ template<> void ContentUnitLoader<Block>::loadUnit(
root.at("tick-interval").get(def.tickInterval); root.at("tick-interval").get(def.tickInterval);
root.at("overlay-texture").get(def.overlayTexture); root.at("overlay-texture").get(def.overlayTexture);
root.at("translucent").get(def.translucent); root.at("translucent").get(def.translucent);
root.at("solid").get(def.explictlySolid);
if (root.has("fields")) { if (root.has("fields")) {
def.dataStruct = std::make_unique<StructLayout>(); def.dataStruct = std::make_unique<StructLayout>();

View file

@ -80,7 +80,7 @@ void BlocksRenderer::face(
const glm::vec4(&lights)[4], const glm::vec4(&lights)[4],
const glm::vec4& tint const glm::vec4& tint
) { ) {
if (vertexCount + 4 >= capacity) { if (vertexCount + 4 >= capacity || indexCount + 6 >= capacity) {
overflow = true; overflow = true;
return; return;
} }
@ -120,7 +120,7 @@ void BlocksRenderer::faceAO(
const UVRegion& region, const UVRegion& region,
bool lights bool lights
) { ) {
if (vertexCount + 4 >= capacity) { if (vertexCount + 4 >= capacity || indexCount + 6 >= capacity) {
overflow = true; overflow = true;
return; return;
} }
@ -159,7 +159,7 @@ void BlocksRenderer::face(
glm::vec4 tint, glm::vec4 tint,
bool lights bool lights
) { ) {
if (vertexCount + 4 >= capacity) { if (vertexCount + 4 >= capacity || indexCount + 6 >= capacity) {
overflow = true; overflow = true;
return; return;
} }
@ -274,19 +274,6 @@ void BlocksRenderer::blockAABB(
} }
} }
static bool is_aligned(const glm::vec3& v, float e = 1e-6f) {
if (std::abs(v.y) < e && std::abs(v.z) < e && std::abs(v.x) > e) {
return true;
}
if (std::abs(v.x) < e && std::abs(v.z) < e && std::abs(v.y) > e) {
return true;
}
if (std::abs(v.x) < e && std::abs(v.y) < e && std::abs(v.z) > e) {
return true;
}
return false;
}
void BlocksRenderer::blockCustomModel( void BlocksRenderer::blockCustomModel(
const glm::ivec3& icoord, const Block& block, blockstate states, bool lights, bool ao const glm::ivec3& icoord, const Block& block, blockstate states, bool lights, bool ao
) { ) {
@ -303,14 +290,34 @@ void BlocksRenderer::blockCustomModel(
Z = orient.axes[2]; Z = orient.axes[2];
} }
if (!block.rt.extended) {
glm::ivec3 offsets[6] {
{-1, 0, 0}, {0, -1, 0}, {0, 0, -1},
{1, 0, 0}, {0, 1, 0}, {0, 0, 1},
};
bool culled = true;
for (int i = 0; i < 6; i++) {
if (isOpen(icoord + offsets[i], block, variant)) {
culled = false;
break;
}
}
if (culled) {
return;
}
}
const auto& model = cache.getModel(block.rt.id, block.getVariantIndex(states.userbits)); const auto& model = cache.getModel(block.rt.id, block.getVariantIndex(states.userbits));
for (const auto& mesh : model.meshes) { for (const auto& mesh : model.meshes) {
if (vertexCount + mesh.vertices.size() >= capacity) { if (vertexCount + mesh.vertices.size() >= capacity
|| indexCount + mesh.vertices.size() >= capacity) {
overflow = true; overflow = true;
return; return;
} }
bool shading = mesh.shading && !block.shadeless; bool shading = mesh.shading && !block.shadeless;
for (int triangle = 0; triangle < mesh.vertices.size() / 3; triangle++) {
int trianglesCount = mesh.vertices.size() / 3;
for (int triangle = 0; triangle < trianglesCount; triangle++) {
auto r = mesh.vertices[triangle * 3 + (triangle % 2) * 2].coord - auto r = mesh.vertices[triangle * 3 + (triangle % 2) * 2].coord -
mesh.vertices[triangle * 3 + 1].coord; mesh.vertices[triangle * 3 + 1].coord;
r = r.x * X + r.y * Y + r.z * Z; r = r.x * X + r.y * Y + r.z * Z;
@ -327,8 +334,7 @@ void BlocksRenderer::blockCustomModel(
vp = vp.x * X + vp.y * Y + vp.z * Z; vp = vp.x * X + vp.y * Y + vp.z * Z;
if (!block.rt.extended if (!block.rt.extended
&& !isOpen(glm::floor(coord + vp + 0.5f + n * 1e-3f), block, variant) && !isOpen(glm::floor(coord + vp + 0.5f + n * 1e-3f), block, variant)) {
&& is_aligned(n)) {
continue; continue;
} }
@ -778,6 +784,10 @@ ChunkMesh BlocksRenderer::render(
const Chunk* chunk, const VoxelsVolume& volume const Chunk* chunk, const VoxelsVolume& volume
) { ) {
build(chunk, volume); build(chunk, volume);
assert(vertexCount <= capacity);
assert(indexCount <= capacity);
assert(denseIndexCount <= capacity);
return ChunkMesh{std::make_unique<Mesh<ChunkVertex>>( return ChunkMesh{std::make_unique<Mesh<ChunkVertex>>(
vertexBuffer.get(), vertexCount, vertexBuffer.get(), vertexCount,

View file

@ -125,9 +125,6 @@ Block::Block(std::string name, const std::string& texture)
void Block::cloneTo(Block& dst) { void Block::cloneTo(Block& dst) {
dst.caption = caption; dst.caption = caption;
for (int i = 0; i < 6; i++) {
dst.defaults = defaults;
}
dst.defaults = defaults; dst.defaults = defaults;
if (variants) { if (variants) {
dst.variants = std::make_unique<Variants>(*variants); dst.variants = std::make_unique<Variants>(*variants);
@ -155,6 +152,7 @@ void Block::cloneTo(Block& dst) {
dst.tickInterval = tickInterval; dst.tickInterval = tickInterval;
dst.overlayTexture = overlayTexture; dst.overlayTexture = overlayTexture;
dst.translucent = translucent; dst.translucent = translucent;
dst.explictlySolid = explictlySolid;
dst.tags = tags; dst.tags = tags;
if (particles) { if (particles) {
dst.particles = std::make_unique<ParticlesPreset>(*particles); dst.particles = std::make_unique<ParticlesPreset>(*particles);

View file

@ -230,6 +230,9 @@ public:
/// @brief Block has semi-transparent texture /// @brief Block has semi-transparent texture
bool translucent = false; bool translucent = false;
/// @brief Explicitly overriding 'solid' property if true assigned
bool explictlySolid = false;
/// @brief Set of block physical hitboxes /// @brief Set of block physical hitboxes
std::vector<AABB> hitboxes {AABB()}; std::vector<AABB> hitboxes {AABB()};