diff --git a/gltf/gltfpack.cpp b/gltf/gltfpack.cpp index 7cda14f8..2e4584a9 100644 --- a/gltf/gltfpack.cpp +++ b/gltf/gltfpack.cpp @@ -411,14 +411,18 @@ static void process(cgltf_data* data, const char* input_path, const char* output #endif for (size_t i = 0; i < meshes.size(); ++i) - processMesh(meshes[i], settings); + { + Mesh& mesh = meshes[i]; + processMesh(mesh, settings); + + if (mesh.geometry_duplicate) + hashMesh(mesh); + } #ifndef NDEBUG meshes.insert(meshes.end(), debug_meshes.begin(), debug_meshes.end()); #endif - for (size_t i = 0; i < meshes.size(); ++i) - hashMesh(meshes[i]); filterEmptyMeshes(meshes); // some meshes may become empty after processing @@ -585,19 +589,27 @@ static void process(cgltf_data* data, const char* input_path, const char* output const QuantizationTexture& qt = qt_meshes[pi] == size_t(-1) ? qt_dummy : qt_materials[qt_meshes[pi]]; - std::pair& primitive_json = primitive_cache[std::make_pair(prim.geometry_hash[0], prim.geometry_hash[1])]; - comma(json_meshes); - if (primitive_json.second > 0) + if (prim.geometry_duplicate) { - json_meshes.append(json_meshes, primitive_json.first, primitive_json.second); + std::pair& primitive_json = primitive_cache[std::make_pair(prim.geometry_hash[0], prim.geometry_hash[1])]; + + if (primitive_json.second) + { + // reuse previously written accessors + json_meshes.append(json_meshes, primitive_json.first, primitive_json.second); + } + else + { + primitive_json.first = json_meshes.size(); + writeMeshGeometry(json_meshes, views, json_accessors, accr_offset, prim, qp, qt, settings); + primitive_json.second = json_meshes.size() - primitive_json.first; + } } else { - primitive_json.first = json_meshes.size(); writeMeshGeometry(json_meshes, views, json_accessors, accr_offset, prim, qp, qt, settings); - primitive_json.second = json_meshes.size() - primitive_json.first; } if (prim.material) diff --git a/gltf/gltfpack.h b/gltf/gltfpack.h index dc92f34c..061b6af1 100644 --- a/gltf/gltfpack.h +++ b/gltf/gltfpack.h @@ -56,6 +56,8 @@ struct Mesh std::vector streams; std::vector indices; + + bool geometry_duplicate; uint64_t geometry_hash[2]; size_t targets; diff --git a/gltf/mesh.cpp b/gltf/mesh.cpp index 7949fcbd..0de6ec6f 100644 --- a/gltf/mesh.cpp +++ b/gltf/mesh.cpp @@ -376,7 +376,12 @@ void dedupMeshes(std::vector& meshes) continue; if (mesh.scene != target.scene || mesh.material != target.material || mesh.skin != target.skin) + { + // mark both meshes as having duplicate geometry; we don't use this in dedupMeshes but it's useful later in the pipeline + target.geometry_duplicate = true; + mesh.geometry_duplicate = true; continue; + } // basic sanity test; these should be included in geometry hash assert(mesh.streams.size() == target.streams.size());