From 3a607c545c1e23c55e2281701baf112f2cd3e1fc Mon Sep 17 00:00:00 2001 From: cx384 Date: Mon, 7 Apr 2025 21:51:01 +0200 Subject: [PATCH 1/5] Fix crack on animated tiles --- src/client/mapblock_mesh.cpp | 71 ++++++++++++++++++++++++++---------- src/client/mapblock_mesh.h | 7 +++- src/client/tile.cpp | 12 +++++- src/client/tile.h | 7 ++++ 4 files changed, 75 insertions(+), 22 deletions(-) diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index a53a5c073a..d94c28b078 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -647,6 +647,9 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): m_bounding_radius = std::sqrt(collector.m_bounding_radius_sq); + // Using the current time avoids flickering before animate() gets called + auto animation_time = client->getAnimationTime(); + for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) { scene::SMesh *mesh = static_cast(m_mesh[layer].get()); @@ -657,9 +660,39 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): p.applyTileColor(); // Generate animation data - // - Cracks - if (p.layer.material_flags & MATERIAL_FLAG_CRACK) { - // Find the texture name plus ^[crack:N: + if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) { + if (p.layer.material_flags & MATERIAL_FLAG_CRACK) { + // - Texture animation with crack + std::vector crack_frames{p.layer.frames->size()}; + for (std::size_t j = 0; j < p.layer.frames->size(); j++) { + std::ostringstream os(std::ios::binary); + os << m_tsrc->getTextureName((*p.layer.frames)[j].texture_id) << "^[crack"; + if (p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY) + os << "o"; // use ^[cracko + os << ":" << 1 << ":"; + + crack_frames[j] = os.str(); + } + AnimationInfo animation_info = AnimationInfo(p.layer); + animation_info.needUpdate(animation_time); // Update current frame + // Replace tile texture with the cracked animated one + p.layer.texture = m_tsrc->getTextureForMesh( + crack_frames[animation_info.getCurrentFrame()] + "0", + &p.layer.texture_id); + + m_animation_info_crack.emplace(std::make_pair(layer, i), + std::make_pair(std::move(animation_info), std::move(crack_frames))); + } else { + // - Texture animation + AnimationInfo animation_info = AnimationInfo(p.layer); + animation_info.needUpdate(animation_time); // Update current frame + // Replace tile texture with the current animation frame + p.layer.texture = (*p.layer.frames)[animation_info.getCurrentFrame()].texture; + // Add to MapBlockMesh in order to animate these tiles + m_animation_info.emplace(std::make_pair(layer, i), std::move(animation_info)); + } + } else if (p.layer.material_flags & MATERIAL_FLAG_CRACK) { + // - Cracks std::ostringstream os(std::ios::binary); os << m_tsrc->getTextureName(p.layer.texture_id) << "^[crack"; if (p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY) @@ -675,13 +708,6 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): os.str() + "0", &p.layer.texture_id); } - // - Texture animation - if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) { - // Add to MapBlockMesh in order to animate these tiles - m_animation_info.emplace(std::make_pair(layer, i), AnimationInfo(p.layer)); - // Replace tile texture with the first animation frame - p.layer.texture = (*p.layer.frames)[0].texture; - } // Create material video::SMaterial material; @@ -731,7 +757,8 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): // Check if animation is required for this mesh m_has_animation = !m_crack_materials.empty() || - !m_animation_info.empty(); + !m_animation_info.empty() || + !m_animation_info_crack.empty(); } MapBlockMesh::~MapBlockMesh() @@ -761,12 +788,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, // Cracks if (crack != m_last_crack) { for (auto &crack_material : m_crack_materials) { - - // TODO crack on animated tiles does not work - auto anim_it = m_animation_info.find(crack_material.first); - if (anim_it != m_animation_info.end()) - continue; - scene::IMeshBuffer *buf = m_mesh[crack_material.first.first]-> getMeshBuffer(crack_material.first.second); @@ -777,8 +798,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, m_tsrc->getTextureForMesh(s, &new_texture_id); buf->getMaterial().setTexture(0, new_texture); } - - m_last_crack = crack; } // Texture animation @@ -788,6 +807,20 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, it.second.updateTexture(material, time); } + // Texture animation with crack + for (auto &it : m_animation_info_crack) { + if (crack != m_last_crack || it.second.first.needUpdate(time)) { + scene::IMeshBuffer *buf = m_mesh[it.first.first]->getMeshBuffer(it.first.second); + + u16 frame = it.second.first.getCurrentFrame(); + std::string s = it.second.second[frame] + itos(crack); + u32 new_texture_id = 0; + video::ITexture *new_texture = m_tsrc->getTextureForMesh(s, &new_texture_id); + buf->getMaterial().setTexture(0, new_texture); + } + } + + m_last_crack = crack; return true; } diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index 6d8ddc36c6..9eb4fba84e 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -266,10 +266,15 @@ private: std::map, std::string> m_crack_materials; // Animation info: texture animation - // Maps mesh and mesh buffer indices to TileSpecs + // Maps mesh and mesh buffer indices to AnimationInfo // Keys are pairs of (mesh index, buffer index in the mesh) std::map, AnimationInfo> m_animation_info; + // Same as above, but in the case both are needed, animation and crack + // The vector contains base crack textures for each animation frame + std::map, std::pair>> + m_animation_info_crack; + // list of all semitransparent triangles in the mapblock std::vector m_transparent_triangles; // Binary Space Partitioning tree for the block diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 894e97339f..a6b20fd1a7 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -6,15 +6,23 @@ #include void AnimationInfo::updateTexture(video::SMaterial &material, float animation_time) +{ + if (needUpdate(animation_time)) { + assert(m_frame < m_frames->size()); + material.setTexture(0, (*m_frames)[m_frame].texture); + } +}; + +bool AnimationInfo::needUpdate(float animation_time) { // Figure out current frame u16 frame = (u16)(animation_time * 1000 / m_frame_length_ms) % m_frame_count; // Only adjust if frame changed if (frame != m_frame) { m_frame = frame; - assert(m_frame < m_frames->size()); - material.setTexture(0, (*m_frames)[m_frame].texture); + return true; } + return false; }; void TileLayer::applyMaterialOptions(video::SMaterial &material, int layer) const diff --git a/src/client/tile.h b/src/client/tile.h index ffbe78bac9..30e7bf5a7b 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -164,6 +164,13 @@ struct AnimationInfo { void updateTexture(video::SMaterial &material, float animation_time); + // Returns true if texture needs to be updated + // Also proceeds to next frame if update is needed + bool needUpdate(float animation_time); + + // Returns last used frame + u16 getCurrentFrame() const { return m_frame; }; + private: u16 m_frame = 0; // last animation frame u16 m_frame_length_ms = 0; From 77290934b79982eeedc5d9290af65024497b9ae8 Mon Sep 17 00:00:00 2001 From: cx384 Date: Sun, 21 Sep 2025 21:43:51 +0200 Subject: [PATCH 2/5] getTextureForMesh Co-authored-by: sfan5 --- src/client/mapblock_mesh.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index d94c28b078..14c97c7007 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -814,8 +814,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u16 frame = it.second.first.getCurrentFrame(); std::string s = it.second.second[frame] + itos(crack); - u32 new_texture_id = 0; - video::ITexture *new_texture = m_tsrc->getTextureForMesh(s, &new_texture_id); + video::ITexture *new_texture = m_tsrc->getTextureForMesh(s); buf->getMaterial().setTexture(0, new_texture); } } From bb38c0d1075074bdd46d60e992f7a41226c0c05c Mon Sep 17 00:00:00 2001 From: cx384 Date: Sun, 21 Sep 2025 22:17:31 +0200 Subject: [PATCH 3/5] Remove p.layer.animation_frame_count --- src/client/mapblock_mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 14c97c7007..d495b91558 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -700,7 +700,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): u8 tiles = p.layer.scale; if (tiles > 1) os << ":" << (u32)tiles; - os << ":" << (u32)p.layer.animation_frame_count << ":"; + os << ":" << 1 << ":"; m_crack_materials.insert(std::make_pair( std::pair(layer, i), os.str())); // Replace tile texture with the cracked one From bd6d2ecb5fe454e322be139c833416ca8f64e170 Mon Sep 17 00:00:00 2001 From: cx384 Date: Sun, 21 Sep 2025 22:38:41 +0200 Subject: [PATCH 4/5] Concat string --- src/client/mapblock_mesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index d495b91558..9d52bdb8c5 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -669,7 +669,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): os << m_tsrc->getTextureName((*p.layer.frames)[j].texture_id) << "^[crack"; if (p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY) os << "o"; // use ^[cracko - os << ":" << 1 << ":"; + os << ":1:"; crack_frames[j] = os.str(); } @@ -700,7 +700,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data): u8 tiles = p.layer.scale; if (tiles > 1) os << ":" << (u32)tiles; - os << ":" << 1 << ":"; + os << ":1:"; m_crack_materials.insert(std::make_pair( std::pair(layer, i), os.str())); // Replace tile texture with the cracked one From 0aa154a656264ef259a0e27091c420ada9cdd5bc Mon Sep 17 00:00:00 2001 From: cx384 Date: Mon, 22 Sep 2025 12:24:43 +0200 Subject: [PATCH 5/5] Remove ; --- src/client/tile.cpp | 4 ++-- src/client/tile.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/tile.cpp b/src/client/tile.cpp index a6b20fd1a7..12533b403c 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -11,7 +11,7 @@ void AnimationInfo::updateTexture(video::SMaterial &material, float animation_ti assert(m_frame < m_frames->size()); material.setTexture(0, (*m_frames)[m_frame].texture); } -}; +} bool AnimationInfo::needUpdate(float animation_time) { @@ -23,7 +23,7 @@ bool AnimationInfo::needUpdate(float animation_time) return true; } return false; -}; +} void TileLayer::applyMaterialOptions(video::SMaterial &material, int layer) const { diff --git a/src/client/tile.h b/src/client/tile.h index 30e7bf5a7b..559646982d 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -169,7 +169,7 @@ struct AnimationInfo { bool needUpdate(float animation_time); // Returns last used frame - u16 getCurrentFrame() const { return m_frame; }; + u16 getCurrentFrame() const { return m_frame; } private: u16 m_frame = 0; // last animation frame