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,87 +102,88 @@ 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 NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
if (nNodesTri == nbNodes) for (i = 1; anIterN.More(); anIterN.Next()) {
{ const int aKey = anIterN.Key();
NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId); const gp_XYZ& aNodePnt = arrNodes[aKey];
for (i = 1; anIterN.More(); anIterN.Next()) { aNodes(i) = gp_Pnt (aNodePnt);
const int aKey = anIterN.Key(); anIterN.ChangeValue() = i++;
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.
// Fill the array of triangles Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
for (i = 0; i < (int)myNbPolygons; i++) { nTri = 0;
const Standard_Integer * arrIndice; for (i = 0; i < (int)myNbPolygons; i++) {
if (Polygon(i, arrIndice) == 3) const Standard_Integer * arrIndice;
if (arrIndice[0] >= 0) // check to avoid previously skipped faces if (Polygon (i, arrIndice) == 3)
aTriangles(++nTri).Set (mapNodeId(arrIndice[0]), if (arrIndice[0] >= 0) // check to avoid previously skipped faces
mapNodeId(arrIndice[1]), aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
mapNodeId(arrIndice[2])); mapNodeId(arrIndice[1]),
} mapNodeId(arrIndice[2]));
// Normals should be defined; if they are not, compute them }
if (myNormals.IsNull()) {
//aTriangulation->ComputeNormals(); // Normals should be defined; if they are not, compute them
Poly::ComputeNormals(aTriangulation); if (myNormals.IsNull ()) {
} else { //aTriangulation->ComputeNormals();
// Copy the normals-per-vertex. Poly::ComputeNormals(aTriangulation);
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 =
for (i = 0; i < (int)myNbPolygons; i++) { new TShort_HArray1OfShortReal (1, 3*nbNodes);
const Standard_Integer * arrIndice; if (myNormalPerVertex) {
if (Polygon(i, arrIndice) == 3) if (myArrNormalInd == 0L) {
if (arrIndice[0] >= 0) { // check to avoid previously skipped faces NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
// normals by triangle - each node belongs to a perticular triangle for (; anIterNN.More (); anIterNN.Next ()) {
nTri++; Standard_Integer anIdx = (anIterNN.Value() - 1) * 3 + 1;
aTriangles(nTri).Set (nTri*3 - 2, nTri*3 - 1, nTri*3); const gp_XYZ& aNormal = myNormals->Normal (anIterNN.Key ());
aNodes(nTri*3 - 2) = arrNodes[arrIndice[0]]; Normals->SetValue (anIdx + 0, Standard_ShortReal (aNormal.X ()));
aNodes(nTri*3 - 1) = arrNodes[arrIndice[1]]; Normals->SetValue (anIdx + 1, Standard_ShortReal (aNormal.Y ()));
aNodes(nTri*3 - 0) = arrNodes[arrIndice[2]]; Normals->SetValue (anIdx + 2, Standard_ShortReal (aNormal.Z ()));
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()));
}
}
} }
} 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; 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,23 +607,24 @@ 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 =
aNodeShape->Appearance(); aNodeShape->Appearance();
if (anAppearance.IsNull() == Standard_False) { if (anAppearance.IsNull() == Standard_False) {
// Check if the current topology is a single face // Check if the current topology is a single face
if (aTShape->IsKind(STANDARD_TYPE(TopoDS_TFace))) if (aTShape->IsKind(STANDARD_TYPE(TopoDS_TFace)))
pMapShapeApp->Bind(aTShape, anAppearance); pMapShapeApp->Bind(aTShape, anAppearance);
else { else {
// This is not a face, explode it in faces and bind each face // This is not a face, explode it in faces and bind each face
TopoDS_Shape aCurShape; TopoDS_Shape aCurShape;
aCurShape.TShape(aTShape); aCurShape.TShape(aTShape);
TopExp_Explorer anExp(aCurShape, TopAbs_FACE); TopExp_Explorer anExp(aCurShape, TopAbs_FACE);
for (; anExp.More(); anExp.Next()) { for (; anExp.More(); anExp.Next()) {
const TopoDS_Face& aFace = TopoDS::Face(anExp.Current()); const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
pMapShapeApp->Bind(aFace.TShape(), anAppearance); pMapShapeApp->Bind(aFace.TShape(), anAppearance);
}
} }
} }
} }