0024675: Crash reading a VRML file
[occt.git] / src / VrmlData / VrmlData_IndexedFaceSet.cxx
CommitLineData
b311480e 1// Created on: 2006-11-04
2// Created by: Alexander GRIGORIEV
973c2be1 3// Copyright (c) 2006-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
16#include <VrmlData_IndexedFaceSet.hxx>
17#include <VrmlData_InBuffer.hxx>
18#include <VrmlData_UnknownNode.hxx>
19#include <Poly_Triangulation.hxx>
20#include <BRep_TFace.hxx>
21#include <VrmlData_Coordinate.hxx>
22#include <VrmlData_Color.hxx>
23#include <VrmlData_Normal.hxx>
24#include <VrmlData_TextureCoordinate.hxx>
25#include <VrmlData_Scene.hxx>
26#include <Precision.hxx>
27#include <NCollection_Vector.hxx>
28#include <NCollection_DataMap.hxx>
29#include <Poly.hxx>
30#include <TShort_HArray1OfShortReal.hxx>
31
32#ifdef WNT
33#define _CRT_SECURE_NO_DEPRECATE
34#pragma warning (disable:4996)
35#endif
36
37IMPLEMENT_STANDARD_HANDLE (VrmlData_Faceted, VrmlData_Geometry)
38IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Faceted, VrmlData_Geometry)
39IMPLEMENT_STANDARD_HANDLE (VrmlData_IndexedFaceSet, VrmlData_Faceted)
40IMPLEMENT_STANDARD_RTTIEXT (VrmlData_IndexedFaceSet, VrmlData_Faceted)
41
42//=======================================================================
43//function : readData
44//purpose :
45//=======================================================================
46
47VrmlData_ErrorStatus VrmlData_Faceted::readData (VrmlData_InBuffer& theBuffer)
48{
49 VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
50 Standard_Boolean aBool;
51 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ccw")) {
52 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
53 myIsCCW = aBool;
54 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "convex")) {
55 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
56 myIsConvex = aBool;
57 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "solid")) {
58 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
59 myIsSolid = aBool;
60 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "creaseAngle")) {
61 Standard_Real anAngle;
62 if (OK(aStatus, Scene().ReadReal (theBuffer, anAngle,
eafb234b 63 Standard_False, Standard_False))) {
7fd59977 64 if (anAngle < -Precision::Confusion()*0.001)
65 aStatus = VrmlData_IrrelevantNumber;
66 else
67 myCreaseAngle = anAngle;
eafb234b 68 }
7fd59977 69 }
70 return aStatus;
71}
72
73//=======================================================================
74//function : VrmlData_IndexedFaceSet::TShape
75//purpose :
76//=======================================================================
77
78const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
79{
80 if (myNbPolygons == 0)
81 myTShape.Nullify();
82 else if (myIsModified) {
83 // Create an empty topological Face
84 const gp_XYZ * arrNodes = myCoords->Values();
85 Standard_Integer i, nTri(0);
86
87 NCollection_DataMap <int, int> mapNodeId;
88
89 // Count non-degenerated triangles
bd0b3e60 90 const int nNodes = (int)myCoords->Length();
7fd59977 91 for (i = 0; i < (int)myNbPolygons; i++) {
92 const Standard_Integer * arrIndice;
93 if (Polygon(i, arrIndice) == 3) {
14b04bd2 94 //Check indices for out of bound
95 if (arrIndice[0] < 0 ||
96 arrIndice[0] >= nNodes ||
97 arrIndice[1] >= nNodes ||
98 arrIndice[2] >= nNodes)
99 {
100 continue;
101 }
7fd59977 102 const gp_XYZ aVec[2] = {
103 arrNodes[arrIndice[1]] - arrNodes[arrIndice[0]],
104 arrNodes[arrIndice[2]] - arrNodes[arrIndice[0]]
105 };
106 if ((aVec[0] ^ aVec[1]).SquareModulus() >
08cd2f6b 107 Precision::SquareConfusion())
7fd59977 108 ++nTri;
109 else {
110 const_cast<Standard_Integer&> (arrIndice[0]) = -1;
111 continue;
112 }
113 }
114 if (mapNodeId.IsBound (arrIndice[0]) == Standard_False)
115 mapNodeId.Bind (arrIndice[0], 0);
116 if (mapNodeId.IsBound (arrIndice[1]) == Standard_False)
117 mapNodeId.Bind (arrIndice[1], 0);
118 if (mapNodeId.IsBound (arrIndice[2]) == Standard_False)
119 mapNodeId.Bind (arrIndice[2], 0);
120 }
121 const Standard_Integer nbNodes (mapNodeId.Extent());
bd754989
V
122 if (!nbNodes)
123 {
124 myIsModified = Standard_False;
125 myTShape.Nullify();
126 return myTShape;
127 }
128
7fd59977 129 Handle(Poly_Triangulation) aTriangulation =
bd754989 130 new Poly_Triangulation (nbNodes, nTri, Standard_False);
7fd59977 131 Handle(BRep_TFace) aFace = new BRep_TFace();
132 aFace->Triangulation (aTriangulation);
133 myTShape = aFace;
134
bd754989 135 // Copy the triangulation vertices
7fd59977 136 TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
bd754989
V
137 NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
138 for (i = 1; anIterN.More(); anIterN.Next()) {
139 const int aKey = anIterN.Key();
140 const gp_XYZ& aNodePnt = arrNodes[aKey];
141 aNodes(i) = gp_Pnt (aNodePnt);
142 anIterN.ChangeValue() = i++;
143 }
144
145 // Copy the triangles. Only the triangle-type polygons are supported.
146 // In this loop we also get rid of any possible degenerated triangles.
7fd59977 147 Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
7fd59977 148 nTri = 0;
bd754989
V
149 for (i = 0; i < (int)myNbPolygons; i++) {
150 const Standard_Integer * arrIndice;
151 if (Polygon (i, arrIndice) == 3)
14b04bd2 152 if (arrIndice[0] >= 0 &&
153 arrIndice[0] < nNodes &&
154 arrIndice[1] < nNodes &&
155 arrIndice[2] < nNodes) // check to avoid previously skipped faces
bd754989
V
156 aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
157 mapNodeId(arrIndice[1]),
158 mapNodeId(arrIndice[2]));
159 }
7fd59977 160
bd754989
V
161 // Normals should be defined; if they are not, compute them
162 if (myNormals.IsNull ()) {
163 //aTriangulation->ComputeNormals();
164 Poly::ComputeNormals(aTriangulation);
7fd59977 165 }
166 else {
bd754989
V
167 // Copy the normals. Currently only normals-per-vertex are supported.
168 Handle(TShort_HArray1OfShortReal) Normals =
169 new TShort_HArray1OfShortReal (1, 3*nbNodes);
170 if (myNormalPerVertex) {
171 if (myArrNormalInd == 0L) {
172 NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
173 for (; anIterNN.More (); anIterNN.Next ()) {
174 Standard_Integer anIdx = (anIterNN.Value() - 1) * 3 + 1;
175 const gp_XYZ& aNormal = myNormals->Normal (anIterNN.Key ());
176 Normals->SetValue (anIdx + 0, Standard_ShortReal (aNormal.X ()));
177 Normals->SetValue (anIdx + 1, Standard_ShortReal (aNormal.Y ()));
178 Normals->SetValue (anIdx + 2, Standard_ShortReal (aNormal.Z ()));
179 }
cccf81ea 180 }
181 else
182 {
183 for (i = 0; i < (int)myNbPolygons; i++)
184 {
185 const Standard_Integer * arrNodes;
14b04bd2 186 if (Polygon(i, arrNodes) == 3 &&
187 arrNodes[0] >= 0 &&
188 arrNodes[0] < nNodes &&
189 arrNodes[1] < nNodes &&
190 arrNodes[2] < nNodes) // check to avoid previously skipped faces
cccf81ea 191 {
192 const Standard_Integer * arrIndice;
193 if (IndiceNormals(i, arrIndice) == 3) {
194 for (Standard_Integer j = 0; j < 3; j++) {
195 const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
5064550f 196 Standard_Integer anInd = (mapNodeId(arrNodes[j]) - 1) * 3 + 1;
cccf81ea 197 Normals->SetValue (anInd + 0, Standard_ShortReal (aNormal.X()));
198 Normals->SetValue (anInd + 1, Standard_ShortReal (aNormal.Y()));
199 Normals->SetValue (anInd + 2, Standard_ShortReal (aNormal.Z()));
bd754989 200 }
cccf81ea 201 }
202 }
7fd59977 203 }
bd754989
V
204 }
205 } else {
206 //TODO ..
7fd59977 207 }
bd754989 208 aTriangulation->SetNormals(Normals);
7fd59977 209 }
bd754989
V
210
211 myIsModified = Standard_False;
7fd59977 212 }
213 return myTShape;
214}
215
216//=======================================================================
217//function : VrmlData_IndexedFaceSet::Clone
218//purpose :
219//=======================================================================
220
221Handle(VrmlData_Node) VrmlData_IndexedFaceSet::Clone
222 (const Handle(VrmlData_Node)& theOther) const
223{
224 Handle(VrmlData_IndexedFaceSet) aResult =
225 Handle(VrmlData_IndexedFaceSet)::DownCast (VrmlData_Node::Clone(theOther));
226 if (aResult.IsNull())
227 aResult =
228 new VrmlData_IndexedFaceSet(theOther.IsNull()? Scene(): theOther->Scene(),
229 Name());
230
231 if (&aResult->Scene() == &Scene()) {
232 aResult->SetCoordinates (myCoords);
233 aResult->SetNormals (myNormals);
234 aResult->SetColors (myColors);
235 aResult->SetPolygons (myNbPolygons, myArrPolygons);
236 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
237 aResult->SetColorInd (myNbColors, myArrColorInd);
238 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
239 } else {
240 // Create a dummy node to pass the different Scene instance to methods Clone
241 const Handle(VrmlData_UnknownNode) aDummyNode =
242 new VrmlData_UnknownNode (aResult->Scene());
243 if (myCoords.IsNull() == Standard_False)
244 aResult->SetCoordinates (Handle(VrmlData_Coordinate)::DownCast
245 (myCoords->Clone (aDummyNode)));
246 if (myNormals.IsNull() == Standard_False)
247 aResult->SetNormals (Handle(VrmlData_Normal)::DownCast
248 (myNormals->Clone (aDummyNode)));
249 if (myColors.IsNull() == Standard_False)
250 aResult->SetColors (Handle(VrmlData_Color)::DownCast
251 (myColors->Clone (aDummyNode)));
252 //TODO: Replace the following lines with the relevant copying
253 aResult->SetPolygons (myNbPolygons, myArrPolygons);
254 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
255 aResult->SetColorInd (myNbColors, myArrColorInd);
256 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
257 }
258 aResult->SetNormalPerVertex (myNormalPerVertex);
259 aResult->SetColorPerVertex (myColorPerVertex);
260 return aResult;
261}
262
263//=======================================================================
264//function : VrmlData_IndexedFaceSet::Read
265//purpose :
266//=======================================================================
267
268VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Read(VrmlData_InBuffer& theBuffer)
269{
270 VrmlData_ErrorStatus aStatus;
271 const VrmlData_Scene& aScene = Scene();
272 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
273 {
274 if (OK(aStatus, VrmlData_Faceted::readData (theBuffer)))
275 continue;
276 if (aStatus != VrmlData_EmptyData)
277 break;
278 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorPerVertex"))
279 aStatus = ReadBoolean (theBuffer, myColorPerVertex);
280 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex"))
281 aStatus = ReadBoolean (theBuffer, myNormalPerVertex);
282 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coordIndex"))
283 aStatus = aScene.ReadArrIndex (theBuffer, myArrPolygons, myNbPolygons);
284 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorIndex"))
285 aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors);
286 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex"))
287 aStatus = aScene.ReadArrIndex (theBuffer, myArrNormalInd, myNbNormals);
288 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoordIndex"))
289 aStatus = aScene.ReadArrIndex (theBuffer, myArrTextureInd, myNbTextures);
290 // These four checks should be the last one to avoid their interference
291 // with the other tokens (e.g., coordIndex)
292 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoord"))
293 aStatus = ReadNode (theBuffer, myTxCoords,
294 STANDARD_TYPE(VrmlData_TextureCoordinate));
295 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "color"))
296 aStatus = ReadNode (theBuffer, myColors,
297 STANDARD_TYPE(VrmlData_Color));
298 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coord"))
299 aStatus = ReadNode (theBuffer, myCoords,
300 STANDARD_TYPE(VrmlData_Coordinate));
301 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normal"))
302 aStatus = ReadNode (theBuffer, myNormals,
303 STANDARD_TYPE(VrmlData_Normal));
304 if (!OK(aStatus))
305 break;
306 }
307 // Read the terminating (closing) brace
308 if (OK(aStatus) || aStatus == VrmlData_EmptyData)
309 if (OK(aStatus, readBrace (theBuffer))) {
310 // Post-processing
311 ;
312 }
313 return aStatus;
314}
315
316// //=======================================================================
317// //function : dummyReadBrackets
318// //purpose : static (local) function
319// //=======================================================================
320
321// VrmlData_ErrorStatus dummyReadBrackets (VrmlData_InBuffer& theBuffer)
322// {
323// VrmlData_ErrorStatus aStatus;
324// Standard_Integer aLevelCounter (0);
325// // This loop searches for any opening bracket.
326// // Such bracket increments the level counter. A closing bracket decrements
327// // the counter. The loop terminates when the counter becomes zero.
328// while ((aStatus = VrmlData_Scene::ReadLine(theBuffer)) == VrmlData_StatusOK)
329// {
330// int aChar;
331// while ((aChar = theBuffer.LinePtr[0]) != '\0') {
332// theBuffer.LinePtr++;
333// if (aChar == '[') {
334// aLevelCounter++;
335// break;
336// } else if (aChar == ']') {
337// aLevelCounter--;
338// break;
339// }
340// }
341// if (aLevelCounter <= 0)
342// break;
343// }
344// return aStatus;
345// }
346
347//=======================================================================
348//function : IsDefault
349//purpose :
350//=======================================================================
351
352Standard_Boolean VrmlData_IndexedFaceSet::IsDefault () const
353{
354 Standard_Boolean aResult (Standard_True);
355 if (myNbPolygons)
356 aResult = Standard_False;
357 else if (myCoords.IsNull() == Standard_False)
358 aResult = myCoords->IsDefault();
359 return aResult;
360}
361
362//=======================================================================
363//function : Write
364//purpose :
365//=======================================================================
366
367VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Write
368 (const char * thePrefix) const
369{
370 static char header[] = "IndexedFaceSet {";
371 const VrmlData_Scene& aScene = Scene();
372 VrmlData_ErrorStatus aStatus;
373 if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent()))) {
374
375 // Write the attributes of interface "VrmlData_Faceted"
376 if (IsCCW() == Standard_False)
377 aStatus = aScene.WriteLine ("ccw FALSE");
378 if (OK(aStatus) && IsSolid() == Standard_False)
379 aStatus = aScene.WriteLine ("solid FALSE");
380 if (OK(aStatus) && IsConvex() == Standard_False)
381 aStatus = aScene.WriteLine ("convex FALSE");
382 if (OK(aStatus) && CreaseAngle() > Precision::Confusion()) {
383 char buf[64];
91322f44 384 Sprintf (buf, "%.9g", CreaseAngle());
7fd59977 385 aStatus = aScene.WriteLine ("creaseAngle", buf);
386 }
387
388 if (OK(aStatus) && myCoords.IsNull() == Standard_False)
389 aStatus = aScene.WriteNode ("coord", myCoords);
390 if (OK(aStatus))
391 aStatus = aScene.WriteArrIndex ("coordIndex", myArrPolygons,myNbPolygons);
392
393 if (OK(aStatus) && myNormalPerVertex == Standard_False)
394 aStatus = aScene.WriteLine ("normalPerVertex FALSE");
395 if (OK(aStatus) && myNormals.IsNull() == Standard_False)
396 aStatus = aScene.WriteNode ("normal", myNormals);
397 if (OK(aStatus))
398 aStatus = aScene.WriteArrIndex ("normalIndex",myArrNormalInd,myNbNormals);
399
400 if (OK(aStatus) && myColorPerVertex == Standard_False)
401 aStatus = aScene.WriteLine ("colorPerVertex FALSE");
402 if (OK(aStatus) && myColors.IsNull() == Standard_False)
403 aStatus = aScene.WriteNode ("color", myColors);
404 if (OK(aStatus))
405 aStatus = aScene.WriteArrIndex ("colorIndex", myArrColorInd, myNbColors);
406
407 if (OK(aStatus) && myTxCoords.IsNull() == Standard_False)
408 aStatus = aScene.WriteNode ("texCoord", myTxCoords);
409 if (OK(aStatus))
410 aStatus = aScene.WriteArrIndex ("texCoordIndex", myArrTextureInd,
411 myNbTextures);
412
413 aStatus = WriteClosing();
414 }
415 return aStatus;
416}
417
418//=======================================================================
419//function : GetColor
420//purpose :
421//=======================================================================
422
423Quantity_Color VrmlData_IndexedFaceSet::GetColor
424 (const Standard_Integer /*iFace*/,
425 const Standard_Integer /*iVertex*/)
426{
427 //TODO
428 return Quantity_NOC_BLACK;
429}
430