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