0022092: Crash of application on attempt to load a VRML file with all degenerated...
authorVRO <>
Fri, 10 Feb 2012 09:43:18 +0000 (09:43 +0000)
committerbugmaster <bugmaster@opencascade.com>
Mon, 5 Mar 2012 15:32:24 +0000 (19:32 +0400)
src/VrmlData/VrmlData_Group.cxx
src/VrmlData/VrmlData_IndexedFaceSet.cxx
src/VrmlData/VrmlData_Scene.cxx

index 509045a..4dea40b 100755 (executable)
@@ -193,6 +193,58 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
         if (isBracketed == Standard_False)
           break;
       }
+    }
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") ||
+             VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) {
+      Standard_Boolean isBracketed (Standard_False);
+      // Read the opening bracket for the list of children
+      if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
+        break;
+      
+      if (theBuffer.LinePtr[0] == '{') {
+        theBuffer.LinePtr++;
+        if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
+          break;
+        isBracketed = Standard_True;
+      }
+
+      // Read the child nodes
+      Handle(VrmlData_Node) aChildNode;
+      while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
+        // read the end-of-list bracket
+        if (isBracketed && theBuffer.LinePtr[0] == '}') {
+          theBuffer.LinePtr++;
+          break;
+        }
+       
+        // otherwise read a node
+        if (!OK(aStatus, ReadNode (theBuffer, aChildNode)))
+          break;
+       
+        AddNode (aChildNode);
+        if (isBracketed == Standard_False)
+          break;
+      }
+    }
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints")) {
+      // Skip this tag
+      if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
+        break;
+      
+      if (theBuffer.LinePtr[0] == '{') {
+        theBuffer.LinePtr++;
+        if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
+          break;
+       
+        while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
+          // read the end-of-list bracket
+          if (theBuffer.LinePtr[0] == '}') {
+            theBuffer.LinePtr++;
+            break;
+          }
+          theBuffer.LinePtr++;
+        }
+      }
     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "center"))
       if (myIsTransform)
         aStatus = Scene().ReadXYZ (theBuffer, aCenter,
index 053492a..c206378 100755 (executable)
@@ -102,87 +102,88 @@ const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
         mapNodeId.Bind (arrIndice[2], 0);
     }
     const Standard_Integer nbNodes (mapNodeId.Extent());
-    const Standard_Integer nNodesTri
-      (myNormalPerVertex && myArrNormalInd==0L ? nbNodes : nTri * 3);
-    // Create the CasCade triangulation
-    //Handle(BRep_Triangulation) aTriangulation =
-      //new BRep_Triangulation (nbNodes, nTri,
-                              //myNormalPerVertex && myArrNormalInd==0L);
+    if (!nbNodes)
+    {
+        myIsModified = Standard_False;
+        myTShape.Nullify();
+        return myTShape;
+    }
+
     Handle(Poly_Triangulation) aTriangulation =
-      new Poly_Triangulation (nNodesTri, nTri, Standard_False);
+      new Poly_Triangulation (nbNodes, nTri, Standard_False);
     Handle(BRep_TFace) aFace = new BRep_TFace();
     aFace->Triangulation (aTriangulation);
     myTShape = aFace;
 
+    // Copy the triangulation vertices
     TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
+    NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
+    for (i = 1; anIterN.More(); anIterN.Next()) {
+      const int aKey = anIterN.Key();
+      const gp_XYZ& aNodePnt = arrNodes[aKey];
+      aNodes(i) = gp_Pnt (aNodePnt);
+      anIterN.ChangeValue() = i++;
+    }
+
+    // Copy the triangles. Only the triangle-type polygons are supported.
+    // In this loop we also get rid of any possible degenerated triangles.
     Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
-    const Handle(TShort_HArray1OfShortReal) aNormals =
-      new TShort_HArray1OfShortReal(1, 3*nNodesTri);
-    aTriangulation->SetNormals(aNormals);
     nTri = 0;
+    for (i = 0; i < (int)myNbPolygons; i++) {
+      const Standard_Integer * arrIndice;
+      if (Polygon (i, arrIndice) == 3)
+        if (arrIndice[0] >= 0)  // check to avoid previously skipped faces
+          aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
+                                  mapNodeId(arrIndice[1]),
+                                  mapNodeId(arrIndice[2]));
+    }
 
-    // Copy the triangulation vertices
-    // This is only the case when normals are defined by node so each
-    // node can be shared by several triangles
-    if (nNodesTri == nbNodes)
-    {
-      NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
-      for (i = 1; anIterN.More(); anIterN.Next()) {
-        const int aKey = anIterN.Key();
-        const gp_XYZ& aNodePnt = arrNodes[aKey];
-        aNodes(i) = gp_Pnt (aNodePnt);
-        anIterN.ChangeValue() = i++;
-      }
-      // Fill the array of triangles
-      for (i = 0; i < (int)myNbPolygons; i++) {
-        const Standard_Integer * arrIndice;
-        if (Polygon(i, arrIndice) == 3)
-          if (arrIndice[0] >= 0) // check to avoid previously skipped faces
-            aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
-                                    mapNodeId(arrIndice[1]),
-                                    mapNodeId(arrIndice[2]));
-      }
-      // Normals should be defined; if they are not, compute them
-      if (myNormals.IsNull()) {
-        //aTriangulation->ComputeNormals();
-        Poly::ComputeNormals(aTriangulation);
-      } else {
-        // Copy the normals-per-vertex.
-        NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
-        for (; anIterNN.More(); anIterNN.Next()) {
-          const Standard_Integer ind = (anIterNN.Value() - 1) * 3 + 1;
-          const gp_XYZ& aNormal = myNormals->Normal(anIterNN.Key());
-          aNormals->SetValue(ind + 0, Standard_ShortReal(aNormal.X()));
-          aNormals->SetValue(ind + 1, Standard_ShortReal(aNormal.Y()));
-          aNormals->SetValue(ind + 2, Standard_ShortReal(aNormal.Z()));
-        }
-      }
+    // Normals should be defined; if they are not, compute them
+    if (myNormals.IsNull ()) {
+      //aTriangulation->ComputeNormals();
+      Poly::ComputeNormals(aTriangulation);
     }
     else {
-      // Copy the triangles. Only the triangle-type polygons are supported.
-      // In this loop we also get rid of any possible degenerated triangles.
-      for (i = 0; i < (int)myNbPolygons; i++) {
-        const Standard_Integer * arrIndice;
-        if (Polygon(i, arrIndice) == 3)
-          if (arrIndice[0] >= 0) { // check to avoid previously skipped faces
-            // normals by triangle - each node belongs to a perticular triangle
-            nTri++;
-            aTriangles(nTri).Set (nTri*3 - 2, nTri*3 - 1, nTri*3);
-            aNodes(nTri*3 - 2) = arrNodes[arrIndice[0]];
-            aNodes(nTri*3 - 1) = arrNodes[arrIndice[1]];
-            aNodes(nTri*3 - 0) = arrNodes[arrIndice[2]];
-            if (IndiceNormals(i, arrIndice) == 3) {
-              for (Standard_Integer j = 0; j < 3; j++) {
-                const Standard_Integer ind = ((nTri-1)*3 + j) * 3;
-                const gp_XYZ& aNormal = myNormals->Normal(arrIndice[j]);
-                aNormals->SetValue(ind + 1, Standard_ShortReal(aNormal.X()));
-                aNormals->SetValue(ind + 2, Standard_ShortReal(aNormal.Y()));
-                aNormals->SetValue(ind + 3, Standard_ShortReal(aNormal.Z()));
-              }
-            }
+      // Copy the normals. Currently only normals-per-vertex are supported.
+      Handle(TShort_HArray1OfShortReal) Normals =
+        new TShort_HArray1OfShortReal (1, 3*nbNodes);
+      if (myNormalPerVertex) {
+        if (myArrNormalInd == 0L) {
+          NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
+          for (; anIterNN.More (); anIterNN.Next ()) {
+            Standard_Integer anIdx = (anIterNN.Value() - 1) * 3 + 1;
+            const gp_XYZ& aNormal = myNormals->Normal (anIterNN.Key ());
+            Normals->SetValue (anIdx + 0, Standard_ShortReal (aNormal.X ()));
+            Normals->SetValue (anIdx + 1, Standard_ShortReal (aNormal.Y ()));
+            Normals->SetValue (anIdx + 2, Standard_ShortReal (aNormal.Z ()));
+          }
+        } else {
+          nTri = 0;
+          for (i = 0; i < (int)myNbPolygons; i++) {
+            const Standard_Integer * arrIndice;
+            if (Polygon(i, arrIndice) == 3)
+              if (arrIndice[0] >= 0)  // check to avoid previously skipped faces
+                if (IndiceNormals(i, arrIndice) == 3) {
+                  Standard_Integer anInd = (++nTri - 1) * 3 + 1;
+                  for (Standard_Integer j = 0; j < 3; j++) {
+                    const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
+                    Normals->SetValue (anInd + 0 + j*3,
+                                       Standard_ShortReal (aNormal.X ()));
+                    Normals->SetValue (anInd + 1 + j*3,
+                                       Standard_ShortReal (aNormal.Y ()));
+                    Normals->SetValue (anInd + 2 + j*3,
+                                       Standard_ShortReal (aNormal.Z ()));
+                  }
+                }
           }
+        }
+      } else {
+        //TODO ..
       }
+      aTriangulation->SetNormals(Normals);
     }
+
+    myIsModified = Standard_False;
   }
   return myTShape;
 }
index 69914bb..d419a28 100755 (executable)
@@ -458,8 +458,13 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
       aNode = new VrmlData_Color          (* this, strName);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cone"))
       aNode = new VrmlData_Cone           (* this, strName);
-    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Coordinate"))
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Coordinate")) {
       aNode = new VrmlData_Coordinate     (* this, strName);
+      
+      // Check for "Coordinate3"
+      if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "3"))
+        theBuffer.LinePtr++;
+    }
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cylinder"))
       aNode = new VrmlData_Cylinder       (* this, strName);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Group"))
@@ -471,6 +476,12 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Inline"))
       aNode = new VrmlData_Group          (* this, strName,
                                            Standard_False);
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Separator"))
+      aNode = new VrmlData_Group          (* this, strName,
+                                           Standard_False);
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Switch"))
+      aNode = new VrmlData_Group          (* this, strName,
+                                           Standard_False);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "ImageTexture"))
       aNode = new VrmlData_ImageTexture   (* this, strName);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "IndexedFaceSet"))
@@ -531,9 +542,6 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
     if (theType.IsNull() == Standard_False)
       if (aNode->IsKind(theType) == Standard_False)
         aStatus = VrmlData_VrmlFormatError;
-#ifdef _DEBUG
-    aNode->myLineCount = theBuffer.LineCount;
-#endif
   }
   if (aStatus == VrmlData_StatusOK)
     if (theBuffer.LinePtr[0] == '{') {
@@ -599,23 +607,24 @@ void VrmlData_Scene::createShape
           isSingleShape = Standard_False;
         const Handle(TopoDS_TShape) aTShape = aNodeGeom->TShape();
         aSingleShape.TShape(aTShape);
-        if (aSingleShape.IsNull() == Standard_False)
+        if (aSingleShape.IsNull() == Standard_False) {
           aBuilder.Add (outShape, aSingleShape);
-        if (pMapShapeApp != 0L) {
-          const Handle(VrmlData_Appearance)& anAppearance =
-            aNodeShape->Appearance();
-          if (anAppearance.IsNull() == Standard_False) {
-            // Check if the current topology is a single face
-            if (aTShape->IsKind(STANDARD_TYPE(TopoDS_TFace)))
-              pMapShapeApp->Bind(aTShape, anAppearance);
-            else {
-              // This is not a face, explode it in faces and bind each face
-              TopoDS_Shape aCurShape;
-              aCurShape.TShape(aTShape);
-              TopExp_Explorer anExp(aCurShape, TopAbs_FACE);
-              for (; anExp.More(); anExp.Next()) {
-                const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
-                pMapShapeApp->Bind(aFace.TShape(), anAppearance);
+          if (pMapShapeApp != 0L) {
+            const Handle(VrmlData_Appearance)& anAppearance =
+              aNodeShape->Appearance();
+            if (anAppearance.IsNull() == Standard_False) {
+              // Check if the current topology is a single face
+              if (aTShape->IsKind(STANDARD_TYPE(TopoDS_TFace)))
+                pMapShapeApp->Bind(aTShape, anAppearance);
+              else {
+                // This is not a face, explode it in faces and bind each face
+                TopoDS_Shape aCurShape;
+                aCurShape.TShape(aTShape);
+                TopExp_Explorer anExp(aCurShape, TopAbs_FACE);
+                for (; anExp.More(); anExp.Next()) {
+                  const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
+                  pMapShapeApp->Bind(aFace.TShape(), anAppearance);
+                }
               }
             }
           }