Parcourir la source

Fix export of deleted meshes; Add LazyDict::Remove method

When I was merging a node’s multiple meshes into that node’s first mesh’s primitives, I was deleting the merged meshes from the node.

However, I wasn’t deleting the merged meshes from the mAsset->meshes Dict, causing the gltf2 export to contain extra unreferenced meshes and duplicate primitives.

This new code adds a new method to LazyDict, which removes the object from it, taking care to update indexes of the subsequent objects. This change also requires that `Ref`s of `Mesh`es (stored in node->meshes) have their indexes updated.
Daniel Hritzkiv il y a 7 ans
Parent
commit
9ec117d0bc
3 fichiers modifiés avec 73 ajouts et 3 suppressions
  1. 2 0
      code/glTF2Asset.h
  2. 44 0
      code/glTF2Asset.inl
  3. 27 3
      code/glTF2Exporter.cpp

+ 2 - 0
code/glTF2Asset.h

@@ -971,6 +971,8 @@ namespace glTF2
         Ref<T> Create(const std::string& id)
             { return Create(id.c_str()); }
 
+        unsigned int Remove(const char* id);
+
         inline unsigned int Size() const
             { return unsigned(mObjs.size()); }
 

+ 44 - 0
code/glTF2Asset.inl

@@ -193,6 +193,50 @@ inline void LazyDict<T>::DetachFromDocument()
     mDict = 0;
 }
 
+template<class T>
+unsigned int LazyDict<T>::Remove(const char* id)
+{
+    id = T::TranslateId(mAsset, id);
+
+    typename IdDict::iterator it = mObjsById.find(id);
+
+    if (it == mObjsById.end()) {
+        throw DeadlyExportError("GLTF: Object with id \"" + std::string(id) + "\" is not found");
+    }
+
+    const int index = it->second;
+
+    mAsset.mUsedIds[id] = false;
+    mObjsById.erase(id);
+    mObjsByOIndex.erase(index);
+    mObjs.erase(mObjs.begin() + index);
+
+    //update index of object in mObjs;
+    for (size_t i = index; i < mObjs.size(); ++i) {
+        T *obj = mObjs[i];
+
+        obj->index = i;
+    }
+
+    for (IdDict::iterator it = mObjsById.begin(); it != mObjsById.end(); ++it) {
+        if (it->second <= index) {
+            continue;
+        }
+
+        mObjsById[it->first] = it->second - 1;
+    }
+
+    for (Dict::iterator it = mObjsByOIndex.begin(); it != mObjsByOIndex.end(); ++it) {
+        if (it->second <= index) {
+            continue;
+        }
+
+        mObjsByOIndex[it->first] = it->second - 1;
+    }
+
+    return index;
+}
+
 template<class T>
 Ref<T> LazyDict<T>::Retrieve(unsigned int i)
 {

+ 27 - 3
code/glTF2Exporter.cpp

@@ -800,9 +800,33 @@ void glTF2Exporter::MergeMeshes()
             for (unsigned int m = nMeshes - 1; m >= 1; --m) {
                 Ref<Mesh> mesh = node->meshes.at(m);
 
-                firstMesh->primitives.insert(firstMesh->primitives.end(), mesh->primitives.begin(), mesh->primitives.end());
-
-                node->meshes.erase(node->meshes.begin() + m);
+                //append this mesh's primitives to the first mesh's primitives
+                firstMesh->primitives.insert(
+                    firstMesh->primitives.end(),
+                    mesh->primitives.begin(),
+                    mesh->primitives.end()
+                );
+
+                //remove the mesh from the list of meshes
+                unsigned int removedIndex = mAsset->meshes.Remove(mesh->id.c_str());
+
+                //find the presence of the removed mesh in other nodes
+                for (unsigned int nn = 0; nn < mAsset->nodes.Size(); ++nn) {
+                    Ref<Node> node = mAsset->nodes.Get(nn);
+
+                    for (unsigned int mm = 0; mm < node->meshes.size(); ++mm) {
+                        Ref<Mesh>& meshRef = node->meshes.at(mm);
+                        unsigned int meshIndex = meshRef.GetIndex();
+
+                        if (meshIndex == removedIndex) {
+                            node->meshes.erase(node->meshes.begin() + mm);
+                        } else if (meshIndex > removedIndex) {
+                            Ref<Mesh> newMeshRef = mAsset->meshes.Get(meshIndex - 1);
+
+                            meshRef = newMeshRef;
+                        }
+                    }
+                }
             }
 
             //since we were looping backwards, reverse the order of merged primitives to their original order