]> OCCT Git - occt.git/commitdiff
Coding - Fix draco buffer index out of bounds
authorElias Cohenca <elias@bananaz.ai>
Thu, 23 Jan 2025 00:25:08 +0000 (02:25 +0200)
committerGitHub <noreply@github.com>
Thu, 23 Jan 2025 00:25:08 +0000 (00:25 +0000)
Fixed an exception where the bufferIndex is out of bounds.
Happens when Draco compression is combined with SetMergeFaces.

src/RWGltf/RWGltf_CafWriter.cxx

index e33eac3fabf721302350cca937b2a72031f8c0c5..9ec8dd61850b58e6ea2ad5370e79ad46ce8c458f 100644 (file)
@@ -746,27 +746,27 @@ bool RWGltf_CafWriter::writeBinData (const Handle(TDocStd_Document)& theDocument
         continue;
       }
       
-      std::shared_ptr<RWGltf_CafWriter::Mesh> aMeshPtr;
-#ifdef HAVE_DRACO
-      ++aMeshIndex;
-      if (myDracoParameters.DracoCompression)
+      for (RWGltf_GltfFaceList::Iterator aGltfFaceIter (*aGltfFaceList); aGltfFaceIter.More() && aPSentryBin.More(); aGltfFaceIter.Next())
       {
-        if (aMeshIndex <= aMeshes.size())
-        {
-          aMeshPtr = aMeshes.at(aMeshIndex - 1);
-        }
-        else
+        const Handle(RWGltf_GltfFace)& aGltfFace = aGltfFaceIter.Value();
+
+        std::shared_ptr<RWGltf_CafWriter::Mesh> aMeshPtr;
+#ifdef HAVE_DRACO
+        ++aMeshIndex;
+        if (myDracoParameters.DracoCompression)
         {
-          aMeshes.push_back(std::make_shared<RWGltf_CafWriter::Mesh>(RWGltf_CafWriter::Mesh()));
-          aMeshPtr = aMeshes.back();
+            if (aMeshIndex <= aMeshes.size())
+            {
+                aMeshPtr = aMeshes.at(aMeshIndex - 1);
+            }
+            else
+            {
+                aMeshes.push_back(std::make_shared<RWGltf_CafWriter::Mesh>(RWGltf_CafWriter::Mesh()));
+                aMeshPtr = aMeshes.back();
+            }
         }
-      }
 #endif
 
-      for (RWGltf_GltfFaceList::Iterator aGltfFaceIter (*aGltfFaceList); aGltfFaceIter.More() && aPSentryBin.More(); aGltfFaceIter.Next())
-      {
-        const Handle(RWGltf_GltfFace)& aGltfFace = aGltfFaceIter.Value();
-
         Handle(RWGltf_GltfFace) anOldGltfFace;
         if (aWrittenPrimData.Find (aGltfFace->Shape, anOldGltfFace))
         {
@@ -1899,23 +1899,21 @@ void RWGltf_CafWriter::writeMeshes (const RWGltf_GltfSceneNodeMap& theSceneNodeM
       for (RWGltf_GltfFaceList::Iterator aFaceGroupIter (*aGltfFaceList); aFaceGroupIter.More(); aFaceGroupIter.Next())
       {
         const Handle(RWGltf_GltfFace)& aGltfFace = aFaceGroupIter.Value();
-        const int aPrevSize = aDracoBufIndMap.Size();
-        const int aTempDracoBufInd = aDracoBufInd;
-        if (myDracoParameters.DracoCompression
-        && !aDracoBufIndMap.FindFromKey (aGltfFace->NodePos.Id, aDracoBufInd))
-        {
-          aDracoBufIndMap.Add (aGltfFace->NodePos.Id, aDracoBufInd);
-        }
+        int aCurrentDracoBufInd = 0;
 
-        writePrimArray (*aGltfFace, aNodeName, aDracoBufInd, toStartPrims);
-        if (aTempDracoBufInd != aDracoBufInd)
-        {
-          aDracoBufInd = aTempDracoBufInd;
-        }
-        if (!myDracoParameters.DracoCompression || aDracoBufIndMap.Size() > aPrevSize)
+        if (myDracoParameters.DracoCompression)
         {
-          ++aDracoBufInd;
+            // Check if we've seen this NodePos.Id before
+            if (!aDracoBufIndMap.FindFromKey(aGltfFace->NodePos.Id, aCurrentDracoBufInd))
+            {
+                // New Draco buffer entry needed
+                aCurrentDracoBufInd = aDracoBufInd;
+                aDracoBufIndMap.Add(aGltfFace->NodePos.Id, aCurrentDracoBufInd);
+                ++aDracoBufInd;
+            }
         }
+
+        writePrimArray(*aGltfFace, aNodeName, aCurrentDracoBufInd, toStartPrims);
       }
     }
     else
@@ -1935,23 +1933,21 @@ void RWGltf_CafWriter::writeMeshes (const RWGltf_GltfSceneNodeMap& theSceneNodeM
         }
 
         const Handle(RWGltf_GltfFace)& aGltfFace = aGltfFaceList->First();
-        const int aPrevSize = aDracoBufIndMap.Size();
-        const int aTempDracoBufInd = aDracoBufInd;
-        if (myDracoParameters.DracoCompression
-        && !aDracoBufIndMap.FindFromKey(aGltfFace->NodePos.Id, aDracoBufInd))
-        {
-          aDracoBufIndMap.Add(aGltfFace->NodePos.Id, aDracoBufInd);
-        }
+        int aCurrentDracoBufInd = 0;
 
-        writePrimArray (*aGltfFace, aNodeName, aDracoBufInd, toStartPrims);
-        if (aTempDracoBufInd != aDracoBufInd)
-        {
-          aDracoBufInd = aTempDracoBufInd;
-        }
-        if (!myDracoParameters.DracoCompression || aDracoBufIndMap.Size() > aPrevSize)
+        if (myDracoParameters.DracoCompression)
         {
-          ++aDracoBufInd;
+            // Check if we've seen this NodePos.Id before
+            if (!aDracoBufIndMap.FindFromKey(aGltfFace->NodePos.Id, aCurrentDracoBufInd))
+            {
+                // New Draco buffer entry needed
+                aCurrentDracoBufInd = aDracoBufInd;
+                aDracoBufIndMap.Add(aGltfFace->NodePos.Id, aCurrentDracoBufInd);
+                ++aDracoBufInd;
+            }
         }
+
+        writePrimArray(*aGltfFace, aNodeName, aCurrentDracoBufInd, toStartPrims);
       }
     }