0031682: Visualization - Prs3d_ShadingAspect::SetTransparency() has no effect with...
[occt.git] / src / VrmlData / VrmlData_IndexedFaceSet.cxx
1 // Created on: 2006-11-04
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2006-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
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 IMPLEMENT_STANDARD_RTTIEXT(VrmlData_IndexedFaceSet,VrmlData_Faceted)
33
34 #ifdef _MSC_VER
35 #define _CRT_SECURE_NO_DEPRECATE
36 #pragma warning (disable:4996)
37 #endif
38
39
40
41
42 //=======================================================================
43 //function : readData
44 //purpose  : 
45 //=======================================================================
46
47 VrmlData_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,
63                                       Standard_False, Standard_False))) {
64       if (anAngle < -Precision::Confusion()*0.001)
65         aStatus = VrmlData_IrrelevantNumber;
66       else
67         myCreaseAngle = anAngle;
68     }
69   }
70   return aStatus;
71 }
72
73 //=======================================================================
74 //function : VrmlData_IndexedFaceSet::TShape
75 //purpose  : 
76 //=======================================================================
77
78 const 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
90     const int nNodes = (int)myCoords->Length();
91     for (i = 0; i < (int)myNbPolygons; i++) {
92       const Standard_Integer * arrIndice;
93       if (Polygon(i, arrIndice) == 3) {
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         }
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() >
107             Precision::SquareConfusion())
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());
122     if (!nbNodes)
123     {
124         myIsModified = Standard_False;
125         myTShape.Nullify();
126         return myTShape;
127     }
128
129     Handle(Poly_Triangulation) aTriangulation =
130       new Poly_Triangulation (nbNodes, nTri, Standard_False);
131     Handle(BRep_TFace) aFace = new BRep_TFace();
132     aFace->Triangulation (aTriangulation);
133     myTShape = aFace;
134
135     // Copy the triangulation vertices
136     TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
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.
147     Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
148     nTri = 0;
149     for (i = 0; i < (int)myNbPolygons; i++) {
150       const Standard_Integer * arrIndice;
151       if (Polygon (i, arrIndice) == 3)
152         if (arrIndice[0] >= 0 &&
153             arrIndice[0] < nNodes &&
154             arrIndice[1] < nNodes &&
155             arrIndice[2] < nNodes)  // check to avoid previously skipped faces
156           aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
157                                   mapNodeId(arrIndice[1]),
158                                   mapNodeId(arrIndice[2]));
159     }
160
161     // Normals should be defined; if they are not, compute them
162     if (myNormals.IsNull ()) {
163       //aTriangulation->ComputeNormals();
164       Poly::ComputeNormals(aTriangulation);
165     }
166     else {
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           }
180         }
181         else
182         {
183           for (i = 0; i < (int)myNbPolygons; i++) 
184           {
185             const Standard_Integer * anArrNodes;
186             if (Polygon(i, anArrNodes) == 3 &&
187               anArrNodes[0] >= 0 &&
188               anArrNodes[0] < nNodes &&
189               anArrNodes[1] < nNodes &&
190               anArrNodes[2] < nNodes)  // check to avoid previously skipped faces
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]);
196                   Standard_Integer anInd = (mapNodeId(anArrNodes[j]) - 1) * 3 + 1;
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()));
200                 }
201               }
202             }
203           }
204         }
205       } else {
206         //TODO ..
207       }
208       aTriangulation->SetNormals(Normals);
209     }
210
211     myIsModified = Standard_False;
212   }
213   return myTShape;
214 }
215
216 //=======================================================================
217 //function : VrmlData_IndexedFaceSet::Clone
218 //purpose  : 
219 //=======================================================================
220
221 Handle(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
268 VrmlData_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     {
294       Handle(VrmlData_Node) aNode;
295       aStatus = ReadNode (theBuffer, aNode,
296                           STANDARD_TYPE(VrmlData_TextureCoordinate));
297       myTxCoords = Handle(VrmlData_TextureCoordinate)::DownCast (aNode);
298     }
299     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "color"))
300     {
301       Handle(VrmlData_Node) aNode;
302       aStatus = ReadNode (theBuffer, aNode,
303                           STANDARD_TYPE(VrmlData_Color));
304       myColors = Handle(VrmlData_Color)::DownCast (aNode);
305     }
306     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coord"))
307     {
308       Handle(VrmlData_Node) aNode;
309       aStatus = ReadNode (theBuffer, aNode,
310                           STANDARD_TYPE(VrmlData_Coordinate));
311       myCoords = Handle(VrmlData_Coordinate)::DownCast (aNode);
312     }
313     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normal"))
314     {
315       Handle(VrmlData_Node) aNode;
316       aStatus = ReadNode (theBuffer, aNode,
317                           STANDARD_TYPE(VrmlData_Normal));
318       myNormals = Handle(VrmlData_Normal)::DownCast (aNode);
319     }
320     if (!OK(aStatus))
321       break;
322   }
323   // Read the terminating (closing) brace
324   if (OK(aStatus) || aStatus == VrmlData_EmptyData)
325     if (OK(aStatus, readBrace (theBuffer))) {
326       // Post-processing
327       ;
328     }
329   return aStatus;
330 }
331
332 // //=======================================================================
333 // //function : dummyReadBrackets
334 // //purpose  : static (local) function
335 // //=======================================================================
336
337 // VrmlData_ErrorStatus dummyReadBrackets (VrmlData_InBuffer& theBuffer)
338 // {
339 //   VrmlData_ErrorStatus aStatus;
340 //   Standard_Integer aLevelCounter (0);
341 //   // This loop searches for any opening bracket.
342 //   // Such bracket increments the level counter. A closing bracket decrements
343 //   // the counter. The loop terminates when the counter becomes zero.
344 //   while ((aStatus = VrmlData_Scene::ReadLine(theBuffer)) == VrmlData_StatusOK)
345 //   {
346 //     int aChar;
347 //     while ((aChar = theBuffer.LinePtr[0]) != '\0') {
348 //       theBuffer.LinePtr++;
349 //       if        (aChar == '[') {
350 //         aLevelCounter++;
351 //         break;
352 //       } else if (aChar == ']') {
353 //         aLevelCounter--;
354 //         break;
355 //       }
356 //     }
357 //     if (aLevelCounter <= 0)
358 //       break;
359 //   }
360 //   return aStatus;
361 // }
362
363 //=======================================================================
364 //function : IsDefault
365 //purpose  : 
366 //=======================================================================
367
368 Standard_Boolean VrmlData_IndexedFaceSet::IsDefault () const
369 {
370   Standard_Boolean aResult (Standard_True);
371   if (myNbPolygons)
372     aResult = Standard_False;
373   else if (myCoords.IsNull() == Standard_False)
374     aResult = myCoords->IsDefault();
375   return aResult;
376 }
377
378 //=======================================================================
379 //function : Write
380 //purpose  : 
381 //=======================================================================
382
383 VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Write
384                                                 (const char * thePrefix) const
385 {
386   static char header[] = "IndexedFaceSet {";
387   const VrmlData_Scene& aScene = Scene();
388   VrmlData_ErrorStatus aStatus;
389   if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent()))) {
390
391     // Write the attributes of interface "VrmlData_Faceted"
392     if (IsCCW() == Standard_False)
393       aStatus = aScene.WriteLine ("ccw         FALSE");
394     if (OK(aStatus) && IsSolid() == Standard_False)
395       aStatus = aScene.WriteLine ("solid       FALSE");
396     if (OK(aStatus) && IsConvex() == Standard_False)
397       aStatus = aScene.WriteLine ("convex      FALSE");
398     if (OK(aStatus) && CreaseAngle() > Precision::Confusion()) {
399       char buf[64];
400       Sprintf (buf, "%.9g", CreaseAngle());
401       aStatus = aScene.WriteLine ("creaseAngle", buf);
402     }
403
404     if (OK(aStatus) && myCoords.IsNull() == Standard_False)
405       aStatus = aScene.WriteNode ("coord", myCoords);
406     if (OK(aStatus))
407       aStatus = aScene.WriteArrIndex ("coordIndex", myArrPolygons,myNbPolygons);
408
409     if (OK(aStatus) && myNormalPerVertex == Standard_False)
410       aStatus = aScene.WriteLine ("normalPerVertex FALSE");
411     if (OK(aStatus) && myNormals.IsNull() == Standard_False)
412       aStatus = aScene.WriteNode ("normal", myNormals);
413     if (OK(aStatus))
414       aStatus = aScene.WriteArrIndex ("normalIndex",myArrNormalInd,myNbNormals);
415
416     if (OK(aStatus) && myColorPerVertex == Standard_False)
417       aStatus = aScene.WriteLine ("colorPerVertex  FALSE");
418     if (OK(aStatus) && myColors.IsNull() == Standard_False)
419       aStatus = aScene.WriteNode ("color", myColors);
420     if (OK(aStatus))
421       aStatus = aScene.WriteArrIndex ("colorIndex", myArrColorInd, myNbColors);
422
423     if (OK(aStatus) && myTxCoords.IsNull() == Standard_False)
424       aStatus = aScene.WriteNode ("texCoord", myTxCoords);
425     if (OK(aStatus))
426       aStatus = aScene.WriteArrIndex ("texCoordIndex", myArrTextureInd,
427                                       myNbTextures);
428
429     aStatus = WriteClosing();
430   }
431   return aStatus;
432 }
433
434 //=======================================================================
435 //function : GetColor
436 //purpose  : 
437 //=======================================================================
438
439 Quantity_Color VrmlData_IndexedFaceSet::GetColor
440                                         (const Standard_Integer /*iFace*/,
441                                          const Standard_Integer /*iVertex*/)
442 {
443   //TODO
444   return Quantity_NOC_BLACK;
445 }
446