From bd754989e8f5026d6294a28a051ee0bd8f21677c Mon Sep 17 00:00:00 2001 From: VRO <> Date: Fri, 10 Feb 2012 09:43:18 +0000 Subject: [PATCH] 0022092: Crash of application on attempt to load a VRML file with all degenerated triangles --- src/VrmlData/VrmlData_Group.cxx | 52 +++++++++ src/VrmlData/VrmlData_IndexedFaceSet.cxx | 141 ++++++++++++----------- src/VrmlData/VrmlData_Scene.cxx | 49 ++++---- 3 files changed, 152 insertions(+), 90 deletions(-) diff --git a/src/VrmlData/VrmlData_Group.cxx b/src/VrmlData/VrmlData_Group.cxx index 509045a0f9..4dea40b448 100755 --- a/src/VrmlData/VrmlData_Group.cxx +++ b/src/VrmlData/VrmlData_Group.cxx @@ -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, diff --git a/src/VrmlData/VrmlData_IndexedFaceSet.cxx b/src/VrmlData/VrmlData_IndexedFaceSet.cxx index 053492af4f..c206378c7c 100755 --- a/src/VrmlData/VrmlData_IndexedFaceSet.cxx +++ b/src/VrmlData/VrmlData_IndexedFaceSet.cxx @@ -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; - TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes(); - Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles(); - const Handle(TShort_HArray1OfShortReal) aNormals = - new TShort_HArray1OfShortReal(1, 3*nNodesTri); - aTriangulation->SetNormals(aNormals); - nTri = 0; - // 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 ::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 ::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())); - } - } + TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes(); + NCollection_DataMap ::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(); + 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])); + } + + // 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 ::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; } diff --git a/src/VrmlData/VrmlData_Scene.cxx b/src/VrmlData/VrmlData_Scene.cxx index 69914bbc1e..d419a28fc7 100755 --- a/src/VrmlData/VrmlData_Scene.cxx +++ b/src/VrmlData/VrmlData_Scene.cxx @@ -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); + } } } }