1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-07 18:30:55 +03:00

0022092: Crash of application on attempt to load a VRML file with all degenerated triangles

This commit is contained in:
VRO 2012-02-10 09:43:18 +00:00 committed by bugmaster
parent b0f0bd0c2f
commit bd754989e8
3 changed files with 152 additions and 90 deletions

View File

@ -193,6 +193,58 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
if (isBracketed == Standard_False) if (isBracketed == Standard_False)
break; 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")) } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "center"))
if (myIsTransform) if (myIsTransform)
aStatus = Scene().ReadXYZ (theBuffer, aCenter, aStatus = Scene().ReadXYZ (theBuffer, aCenter,

View File

@ -102,30 +102,21 @@ const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
mapNodeId.Bind (arrIndice[2], 0); mapNodeId.Bind (arrIndice[2], 0);
} }
const Standard_Integer nbNodes (mapNodeId.Extent()); const Standard_Integer nbNodes (mapNodeId.Extent());
const Standard_Integer nNodesTri if (!nbNodes)
(myNormalPerVertex && myArrNormalInd==0L ? nbNodes : nTri * 3); {
// Create the CasCade triangulation myIsModified = Standard_False;
//Handle(BRep_Triangulation) aTriangulation = myTShape.Nullify();
//new BRep_Triangulation (nbNodes, nTri, return myTShape;
//myNormalPerVertex && myArrNormalInd==0L); }
Handle(Poly_Triangulation) aTriangulation = 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(); Handle(BRep_TFace) aFace = new BRep_TFace();
aFace->Triangulation (aTriangulation); aFace->Triangulation (aTriangulation);
myTShape = aFace; 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 // Copy the triangulation vertices
// This is only the case when normals are defined by node so each TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
// node can be shared by several triangles
if (nNodesTri == nbNodes)
{
NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId); NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
for (i = 1; anIterN.More(); anIterN.Next()) { for (i = 1; anIterN.More(); anIterN.Next()) {
const int aKey = anIterN.Key(); const int aKey = anIterN.Key();
@ -133,7 +124,11 @@ const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
aNodes(i) = gp_Pnt (aNodePnt); aNodes(i) = gp_Pnt (aNodePnt);
anIterN.ChangeValue() = i++; anIterN.ChangeValue() = i++;
} }
// Fill the array of triangles
// 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++) { for (i = 0; i < (int)myNbPolygons; i++) {
const Standard_Integer * arrIndice; const Standard_Integer * arrIndice;
if (Polygon (i, arrIndice) == 3) if (Polygon (i, arrIndice) == 3)
@ -142,47 +137,53 @@ const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
mapNodeId(arrIndice[1]), mapNodeId(arrIndice[1]),
mapNodeId(arrIndice[2])); mapNodeId(arrIndice[2]));
} }
// Normals should be defined; if they are not, compute them // Normals should be defined; if they are not, compute them
if (myNormals.IsNull ()) { if (myNormals.IsNull ()) {
//aTriangulation->ComputeNormals(); //aTriangulation->ComputeNormals();
Poly::ComputeNormals(aTriangulation); 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()));
}
}
} }
else { else {
// Copy the triangles. Only the triangle-type polygons are supported. // Copy the normals. Currently only normals-per-vertex are supported.
// In this loop we also get rid of any possible degenerated triangles. 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++) { for (i = 0; i < (int)myNbPolygons; i++) {
const Standard_Integer * arrIndice; const Standard_Integer * arrIndice;
if (Polygon(i, arrIndice) == 3) if (Polygon(i, arrIndice) == 3)
if (arrIndice[0] >= 0) { // check to avoid previously skipped faces 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) { if (IndiceNormals(i, arrIndice) == 3) {
Standard_Integer anInd = (++nTri - 1) * 3 + 1;
for (Standard_Integer j = 0; j < 3; j++) { 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]); const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
aNormals->SetValue(ind + 1, Standard_ShortReal(aNormal.X())); Normals->SetValue (anInd + 0 + j*3,
aNormals->SetValue(ind + 2, Standard_ShortReal(aNormal.Y())); Standard_ShortReal (aNormal.X ()));
aNormals->SetValue(ind + 3, Standard_ShortReal(aNormal.Z())); 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; return myTShape;
} }

View File

@ -458,8 +458,13 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
aNode = new VrmlData_Color (* this, strName); aNode = new VrmlData_Color (* this, strName);
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cone")) else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cone"))
aNode = new VrmlData_Cone (* this, strName); 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); aNode = new VrmlData_Coordinate (* this, strName);
// Check for "Coordinate3"
if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "3"))
theBuffer.LinePtr++;
}
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cylinder")) else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cylinder"))
aNode = new VrmlData_Cylinder (* this, strName); aNode = new VrmlData_Cylinder (* this, strName);
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Group")) else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Group"))
@ -471,6 +476,12 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Inline")) else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Inline"))
aNode = new VrmlData_Group (* this, strName, aNode = new VrmlData_Group (* this, strName,
Standard_False); 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")) else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "ImageTexture"))
aNode = new VrmlData_ImageTexture (* this, strName); aNode = new VrmlData_ImageTexture (* this, strName);
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "IndexedFaceSet")) else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "IndexedFaceSet"))
@ -531,9 +542,6 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
if (theType.IsNull() == Standard_False) if (theType.IsNull() == Standard_False)
if (aNode->IsKind(theType) == Standard_False) if (aNode->IsKind(theType) == Standard_False)
aStatus = VrmlData_VrmlFormatError; aStatus = VrmlData_VrmlFormatError;
#ifdef _DEBUG
aNode->myLineCount = theBuffer.LineCount;
#endif
} }
if (aStatus == VrmlData_StatusOK) if (aStatus == VrmlData_StatusOK)
if (theBuffer.LinePtr[0] == '{') { if (theBuffer.LinePtr[0] == '{') {
@ -599,7 +607,7 @@ void VrmlData_Scene::createShape
isSingleShape = Standard_False; isSingleShape = Standard_False;
const Handle(TopoDS_TShape) aTShape = aNodeGeom->TShape(); const Handle(TopoDS_TShape) aTShape = aNodeGeom->TShape();
aSingleShape.TShape(aTShape); aSingleShape.TShape(aTShape);
if (aSingleShape.IsNull() == Standard_False) if (aSingleShape.IsNull() == Standard_False) {
aBuilder.Add (outShape, aSingleShape); aBuilder.Add (outShape, aSingleShape);
if (pMapShapeApp != 0L) { if (pMapShapeApp != 0L) {
const Handle(VrmlData_Appearance)& anAppearance = const Handle(VrmlData_Appearance)& anAppearance =
@ -621,6 +629,7 @@ void VrmlData_Scene::createShape
} }
} }
} }
}
continue; continue;
} }
// Try a Group type of node // Try a Group type of node