From 3e6ba273f76aca3086e5ea29f8565355052b89b5 Mon Sep 17 00:00:00 2001 From: Matt Dallmeyer Date: Sat, 8 Mar 2025 14:21:16 -0800 Subject: [PATCH] Dedupe custom level textures by height/width/data, not just name (#3874) I fixed this for the only up mod awhile back and forgot to PR it here. Some related discussion [here](https://discord.com/channels/756287461377703987/995787558816595968/1320482071583522878) where we realized Blender automatically "renames" the textures, but then the GLB export doesn't reflect those renames --- common/util/gltf_util.cpp | 29 +++++++++++++++++++++-------- common/util/gltf_util.h | 2 +- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/common/util/gltf_util.cpp b/common/util/gltf_util.cpp index d72ee6b099..682fe224bf 100644 --- a/common/util/gltf_util.cpp +++ b/common/util/gltf_util.cpp @@ -366,9 +366,11 @@ DrawMode make_default_draw_mode() { int texture_pool_debug_checker(TexturePool* pool) { const auto& existing = pool->textures_by_name.find("DEBUG_CHECKERBOARD"); - if (existing == pool->textures_by_name.end()) { + if (existing == pool->textures_by_name.end() || existing->second.size() == 0) { size_t idx = pool->textures_by_idx.size(); - pool->textures_by_name["DEBUG_CHECKERBOARD"] = idx; + std::vector v; + v.push_back(idx); + pool->textures_by_name["DEBUG_CHECKERBOARD"] = v; auto& tex = pool->textures_by_idx.emplace_back(); tex.w = 16; tex.h = 16; @@ -386,25 +388,36 @@ int texture_pool_debug_checker(TexturePool* pool) { } return idx; } else { - return existing->second; + return existing->second[0]; } } int texture_pool_add_texture(TexturePool* pool, const tinygltf::Image& tex, int alpha_shift) { const auto& existing = pool->textures_by_name.find(tex.name); - if (existing != pool->textures_by_name.end()) { - lg::info("Reusing image: {}", tex.name); - return existing->second; + if (existing != pool->textures_by_name.end() && existing->second.size() > 0) { + // name was found, see if we have a match on height+width+data + for (int ti : existing->second) { + auto& t = pool->textures_by_idx[ti]; + if (t.w == tex.width && t.h == tex.height && + memcmp(t.data.data(), tex.image.data(), t.data.size() * 4) == 0) { + lg::info("Reusing image: {} at idx {}", tex.name, ti); + return ti; + } + } } else { - lg::info("adding new texture: {}, size {} kB", tex.name, tex.width * tex.height * 4 / 1024); + // new name, insert empty vector + std::vector v; + pool->textures_by_name[tex.name] = v; } + lg::info("adding new texture: {}, size {} kB", tex.name, tex.width * tex.height * 4 / 1024); + ASSERT(tex.bits == 8); ASSERT(tex.component == 4); ASSERT(tex.pixel_type == TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE); size_t idx = pool->textures_by_idx.size(); - pool->textures_by_name[tex.name] = idx; + pool->textures_by_name[tex.name].push_back(idx); auto& tt = pool->textures_by_idx.emplace_back(); tt.w = tex.width; tt.h = tex.height; diff --git a/common/util/gltf_util.h b/common/util/gltf_util.h index f92f56c4b6..015704a009 100644 --- a/common/util/gltf_util.h +++ b/common/util/gltf_util.h @@ -59,7 +59,7 @@ ExtractedVertices gltf_vertices(const tinygltf::Model& model, DrawMode make_default_draw_mode(); struct TexturePool { - std::unordered_map textures_by_name; + std::unordered_map> textures_by_name; std::vector textures_by_idx; std::map, int> envmap_textures_by_gltf_id; };