0024171: Eliminate CLang compiler warning -Wreorder
[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         } else {
177           nTri = 0;
178           for (i = 0; i < (int)myNbPolygons; i++) {
179             const Standard_Integer * arrIndice;
180             if (Polygon(i, arrIndice) == 3)
181               if (arrIndice[0] >= 0)  // check to avoid previously skipped faces
182                 if (IndiceNormals(i, arrIndice) == 3) {
183                   Standard_Integer anInd = (++nTri - 1) * 3 + 1;
184                   for (Standard_Integer j = 0; j < 3; j++) {
185                     const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
186                     Normals->SetValue (anInd + 0 + j*3,
187                                        Standard_ShortReal (aNormal.X ()));
188                     Normals->SetValue (anInd + 1 + j*3,
189                                        Standard_ShortReal (aNormal.Y ()));
190                     Normals->SetValue (anInd + 2 + j*3,
191                                        Standard_ShortReal (aNormal.Z ()));
192                   }
193                 }
194           }
195         }
196       } else {
197         //TODO ..
198       }
199       aTriangulation->SetNormals(Normals);
200     }
201
202     myIsModified = Standard_False;
203   }
204   return myTShape;
205 }
206
207 //=======================================================================
208 //function : VrmlData_IndexedFaceSet::Clone
209 //purpose  : 
210 //=======================================================================
211
212 Handle(VrmlData_Node) VrmlData_IndexedFaceSet::Clone
213                                 (const Handle(VrmlData_Node)& theOther) const
214 {
215   Handle(VrmlData_IndexedFaceSet) aResult =
216     Handle(VrmlData_IndexedFaceSet)::DownCast (VrmlData_Node::Clone(theOther));
217   if (aResult.IsNull())
218     aResult =
219       new VrmlData_IndexedFaceSet(theOther.IsNull()? Scene(): theOther->Scene(),
220                                   Name());
221
222   if (&aResult->Scene() == &Scene()) {
223     aResult->SetCoordinates     (myCoords);
224     aResult->SetNormals         (myNormals);
225     aResult->SetColors          (myColors);
226     aResult->SetPolygons        (myNbPolygons, myArrPolygons);
227     aResult->SetNormalInd       (myNbNormals, myArrNormalInd);
228     aResult->SetColorInd        (myNbColors, myArrColorInd);
229     aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
230   } else {
231     // Create a dummy node to pass the different Scene instance to methods Clone
232     const Handle(VrmlData_UnknownNode) aDummyNode =
233       new VrmlData_UnknownNode (aResult->Scene());
234     if (myCoords.IsNull() == Standard_False)
235       aResult->SetCoordinates (Handle(VrmlData_Coordinate)::DownCast
236                                (myCoords->Clone (aDummyNode)));
237     if (myNormals.IsNull() == Standard_False)
238       aResult->SetNormals (Handle(VrmlData_Normal)::DownCast
239                            (myNormals->Clone (aDummyNode)));
240     if (myColors.IsNull() == Standard_False)
241       aResult->SetColors (Handle(VrmlData_Color)::DownCast
242                           (myColors->Clone (aDummyNode)));
243     //TODO: Replace the following lines with the relevant copying
244     aResult->SetPolygons        (myNbPolygons, myArrPolygons);
245     aResult->SetNormalInd       (myNbNormals, myArrNormalInd);
246     aResult->SetColorInd        (myNbColors, myArrColorInd);
247     aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
248   }
249   aResult->SetNormalPerVertex (myNormalPerVertex);
250   aResult->SetColorPerVertex  (myColorPerVertex);
251   return aResult;
252 }
253
254 //=======================================================================
255 //function : VrmlData_IndexedFaceSet::Read
256 //purpose  : 
257 //=======================================================================
258
259 VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Read(VrmlData_InBuffer& theBuffer)
260 {
261   VrmlData_ErrorStatus aStatus;
262   const VrmlData_Scene& aScene = Scene();
263   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
264   {
265     if (OK(aStatus, VrmlData_Faceted::readData (theBuffer)))
266       continue;
267     if (aStatus != VrmlData_EmptyData)
268       break;
269     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorPerVertex"))
270       aStatus = ReadBoolean (theBuffer, myColorPerVertex);
271     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex"))
272       aStatus = ReadBoolean (theBuffer, myNormalPerVertex);
273     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coordIndex"))
274       aStatus = aScene.ReadArrIndex (theBuffer, myArrPolygons, myNbPolygons);
275     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorIndex"))
276       aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors);
277     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex"))
278       aStatus = aScene.ReadArrIndex (theBuffer, myArrNormalInd, myNbNormals);
279     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoordIndex"))
280       aStatus = aScene.ReadArrIndex (theBuffer, myArrTextureInd, myNbTextures);
281     // These four checks should be the last one to avoid their interference
282     // with the other tokens (e.g., coordIndex)
283     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoord"))
284       aStatus = ReadNode (theBuffer, myTxCoords,
285                           STANDARD_TYPE(VrmlData_TextureCoordinate));
286     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "color"))
287       aStatus = ReadNode (theBuffer, myColors,
288                           STANDARD_TYPE(VrmlData_Color));
289     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coord"))
290       aStatus = ReadNode (theBuffer, myCoords,
291                           STANDARD_TYPE(VrmlData_Coordinate));
292     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normal"))
293       aStatus = ReadNode (theBuffer, myNormals,
294                           STANDARD_TYPE(VrmlData_Normal));
295     if (!OK(aStatus))
296       break;
297   }
298   // Read the terminating (closing) brace
299   if (OK(aStatus) || aStatus == VrmlData_EmptyData)
300     if (OK(aStatus, readBrace (theBuffer))) {
301       // Post-processing
302       ;
303     }
304   return aStatus;
305 }
306
307 // //=======================================================================
308 // //function : dummyReadBrackets
309 // //purpose  : static (local) function
310 // //=======================================================================
311
312 // VrmlData_ErrorStatus dummyReadBrackets (VrmlData_InBuffer& theBuffer)
313 // {
314 //   VrmlData_ErrorStatus aStatus;
315 //   Standard_Integer aLevelCounter (0);
316 //   // This loop searches for any opening bracket.
317 //   // Such bracket increments the level counter. A closing bracket decrements
318 //   // the counter. The loop terminates when the counter becomes zero.
319 //   while ((aStatus = VrmlData_Scene::ReadLine(theBuffer)) == VrmlData_StatusOK)
320 //   {
321 //     int aChar;
322 //     while ((aChar = theBuffer.LinePtr[0]) != '\0') {
323 //       theBuffer.LinePtr++;
324 //       if        (aChar == '[') {
325 //         aLevelCounter++;
326 //         break;
327 //       } else if (aChar == ']') {
328 //         aLevelCounter--;
329 //         break;
330 //       }
331 //     }
332 //     if (aLevelCounter <= 0)
333 //       break;
334 //   }
335 //   return aStatus;
336 // }
337
338 //=======================================================================
339 //function : IsDefault
340 //purpose  : 
341 //=======================================================================
342
343 Standard_Boolean VrmlData_IndexedFaceSet::IsDefault () const
344 {
345   Standard_Boolean aResult (Standard_True);
346   if (myNbPolygons)
347     aResult = Standard_False;
348   else if (myCoords.IsNull() == Standard_False)
349     aResult = myCoords->IsDefault();
350   return aResult;
351 }
352
353 //=======================================================================
354 //function : Write
355 //purpose  : 
356 //=======================================================================
357
358 VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Write
359                                                 (const char * thePrefix) const
360 {
361   static char header[] = "IndexedFaceSet {";
362   const VrmlData_Scene& aScene = Scene();
363   VrmlData_ErrorStatus aStatus;
364   if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent()))) {
365
366     // Write the attributes of interface "VrmlData_Faceted"
367     if (IsCCW() == Standard_False)
368       aStatus = aScene.WriteLine ("ccw         FALSE");
369     if (OK(aStatus) && IsSolid() == Standard_False)
370       aStatus = aScene.WriteLine ("solid       FALSE");
371     if (OK(aStatus) && IsConvex() == Standard_False)
372       aStatus = aScene.WriteLine ("convex      FALSE");
373     if (OK(aStatus) && CreaseAngle() > Precision::Confusion()) {
374       char buf[64];
375       Sprintf (buf, "%.9g", CreaseAngle());
376       aStatus = aScene.WriteLine ("creaseAngle", buf);
377     }
378
379     if (OK(aStatus) && myCoords.IsNull() == Standard_False)
380       aStatus = aScene.WriteNode ("coord", myCoords);
381     if (OK(aStatus))
382       aStatus = aScene.WriteArrIndex ("coordIndex", myArrPolygons,myNbPolygons);
383
384     if (OK(aStatus) && myNormalPerVertex == Standard_False)
385       aStatus = aScene.WriteLine ("normalPerVertex FALSE");
386     if (OK(aStatus) && myNormals.IsNull() == Standard_False)
387       aStatus = aScene.WriteNode ("normal", myNormals);
388     if (OK(aStatus))
389       aStatus = aScene.WriteArrIndex ("normalIndex",myArrNormalInd,myNbNormals);
390
391     if (OK(aStatus) && myColorPerVertex == Standard_False)
392       aStatus = aScene.WriteLine ("colorPerVertex  FALSE");
393     if (OK(aStatus) && myColors.IsNull() == Standard_False)
394       aStatus = aScene.WriteNode ("color", myColors);
395     if (OK(aStatus))
396       aStatus = aScene.WriteArrIndex ("colorIndex", myArrColorInd, myNbColors);
397
398     if (OK(aStatus) && myTxCoords.IsNull() == Standard_False)
399       aStatus = aScene.WriteNode ("texCoord", myTxCoords);
400     if (OK(aStatus))
401       aStatus = aScene.WriteArrIndex ("texCoordIndex", myArrTextureInd,
402                                       myNbTextures);
403
404     aStatus = WriteClosing();
405   }
406   return aStatus;
407 }
408
409 //=======================================================================
410 //function : GetColor
411 //purpose  : 
412 //=======================================================================
413
414 Quantity_Color VrmlData_IndexedFaceSet::GetColor
415                                         (const Standard_Integer /*iFace*/,
416                                          const Standard_Integer /*iVertex*/)
417 {
418   //TODO
419   return Quantity_NOC_BLACK;
420 }
421