0030953: Data Exchange - implement export of mesh data into glTF 2.0 format
[occt.git] / src / RWMesh / RWMesh_FaceIterator.cxx
1 // Copyright (c) 2017-2019 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <RWMesh_FaceIterator.hxx>
15
16 #include <BRepAdaptor_Surface.hxx>
17 #include <BRep_Tool.hxx>
18 #include <TopExp.hxx>
19 #include <TopoDS.hxx>
20 #include <XCAFDoc_ShapeTool.hxx>
21 #include <XCAFPrs.hxx>
22
23 // =======================================================================
24 // function : RWMesh_FaceIterator
25 // purpose  :
26 // =======================================================================
27 RWMesh_FaceIterator::RWMesh_FaceIterator (const TDF_Label&       theLabel,
28                                           const TopLoc_Location& theLocation,
29                                           const Standard_Boolean theToMapColors,
30                                           const XCAFPrs_Style&   theStyle)
31 : myDefStyle (theStyle),
32   myToMapColors (theToMapColors),
33   mySLTool  (1, 1e-12),
34   myNodes   (NULL),
35   myNormals (NULL),
36   myNodeUVs (NULL),
37   myHasNormals (false),
38   myIsMirrored (false),
39   myHasFaceColor (false)
40 {
41   TopoDS_Shape aShape;
42   if (!XCAFDoc_ShapeTool::GetShape (theLabel, aShape)
43    ||  aShape.IsNull())
44   {
45     return;
46   }
47
48   aShape.Location (theLocation);
49   myFaceIter.Init (aShape, TopAbs_FACE);
50
51   if (theToMapColors)
52   {
53     dispatchStyles (theLabel, theLocation, theStyle);
54   }
55
56   Next();
57 }
58
59 // =======================================================================
60 // function : dispatchStyles
61 // purpose  :
62 // =======================================================================
63 void RWMesh_FaceIterator::dispatchStyles (const TDF_Label&       theLabel,
64                                           const TopLoc_Location& theLocation,
65                                           const XCAFPrs_Style&   theStyle)
66 {
67   TopLoc_Location aDummyLoc;
68   XCAFPrs_IndexedDataMapOfShapeStyle aStyles;
69   XCAFPrs::CollectStyleSettings (theLabel, aDummyLoc, aStyles);
70
71   Standard_Integer aNbTypes[TopAbs_SHAPE] = {};
72   for (Standard_Integer aTypeIter = TopAbs_FACE; aTypeIter >= TopAbs_COMPOUND; --aTypeIter)
73   {
74     if (aTypeIter != TopAbs_FACE
75      && aNbTypes[aTypeIter] == 0)
76     {
77       continue;
78     }
79
80     for (XCAFPrs_IndexedDataMapOfShapeStyle::Iterator aStyleIter (aStyles); aStyleIter.More(); aStyleIter.Next())
81     {
82       const TopoDS_Shape&    aKeyShape     = aStyleIter.Key();
83       const TopAbs_ShapeEnum aKeyShapeType = aKeyShape.ShapeType();
84       if (aTypeIter == TopAbs_FACE)
85       {
86         ++aNbTypes[aKeyShapeType];
87       }
88       if (aTypeIter != aKeyShapeType)
89       {
90         continue;
91       }
92
93       XCAFPrs_Style aCafStyle = aStyleIter.Value();
94       if (!aCafStyle.IsSetColorCurv()
95          && theStyle.IsSetColorCurv())
96       {
97         aCafStyle.SetColorCurv (theStyle.GetColorCurv());
98       }
99       if (!aCafStyle.IsSetColorSurf()
100          && theStyle.IsSetColorSurf())
101       {
102         aCafStyle.SetColorSurf (theStyle.GetColorSurfRGBA());
103       }
104       if (aCafStyle.Material().IsNull()
105        && !theStyle.Material().IsNull())
106       {
107         aCafStyle.SetMaterial (theStyle.Material());
108       }
109
110       TopoDS_Shape aKeyShapeLocated = aKeyShape.Located (theLocation);
111       if (aKeyShapeType == TopAbs_FACE)
112       {
113         myStyles.Bind (aKeyShapeLocated, aCafStyle);
114       }
115       else
116       {
117         for (TopExp_Explorer aFaceIter (aKeyShapeLocated, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
118         {
119           if (!myStyles.IsBound (aFaceIter.Current()))
120           {
121             myStyles.Bind (aFaceIter.Current(), aCafStyle);
122           }
123         }
124       }
125     }
126   }
127 }
128
129 // =======================================================================
130 // function : normal
131 // purpose  :
132 // =======================================================================
133 gp_Dir RWMesh_FaceIterator::normal (Standard_Integer theNode)
134 {
135   gp_Dir aNormal (gp::DZ());
136   if (myNormals != NULL)
137   {
138     const Standard_Integer aNodeIndex = theNode - myNodes->Lower();
139     const Graphic3d_Vec3 aNormVec3 (myNormals->Value (myNormals->Lower() + aNodeIndex * 3),
140                                     myNormals->Value (myNormals->Lower() + aNodeIndex * 3 + 1),
141                                     myNormals->Value (myNormals->Lower() + aNodeIndex * 3 + 2));
142     if (aNormVec3.Modulus() != 0.0f)
143     {
144       aNormal.SetCoord (aNormVec3.x(), aNormVec3.y(), aNormVec3.z());
145     }
146   }
147   else if (myHasNormals
148         && myNodeUVs != NULL)
149   {
150     const gp_XY& anUV = myNodeUVs->Value (theNode).XY();
151     mySLTool.SetParameters (anUV.X(), anUV.Y());
152     if (mySLTool.IsNormalDefined())
153     {
154       aNormal = mySLTool.Normal();
155     }
156   }
157   return aNormal;
158 }
159
160 // =======================================================================
161 // function : Next
162 // purpose  :
163 // =======================================================================
164 void RWMesh_FaceIterator::Next()
165 {
166   for (; myFaceIter.More(); myFaceIter.Next())
167   {
168     myFace       = TopoDS::Face (myFaceIter.Current());
169     myPolyTriang = BRep_Tool::Triangulation (myFace, myFaceLocation);
170     myTrsf       = myFaceLocation.Transformation();
171     if (myPolyTriang.IsNull()
172      || myPolyTriang->Triangles().Length() == 0)
173     {
174       resetFace();
175       continue;
176     }
177
178     initFace();
179     myFaceIter.Next();
180     return;
181   }
182
183   resetFace();
184 }
185
186 // =======================================================================
187 // function : initFace
188 // purpose  :
189 // =======================================================================
190 void RWMesh_FaceIterator::initFace()
191 {
192   myHasNormals   = false;
193   myHasFaceColor = false;
194   myIsMirrored   = myTrsf.VectorialPart().Determinant() < 0.0;
195   myNormals = NULL;
196   myNodeUVs = NULL;
197
198   myNodes = &myPolyTriang->Nodes();
199   if (myPolyTriang->HasNormals())
200   {
201     myNormals = &myPolyTriang->Normals();
202     myHasNormals = true;
203   }
204   if (myPolyTriang->HasUVNodes())
205   {
206     myNodeUVs = &myPolyTriang->UVNodes();
207     if (!myHasNormals)
208     {
209       TopoDS_Face aFaceFwd = TopoDS::Face (myFace.Oriented (TopAbs_FORWARD));
210       aFaceFwd.Location (TopLoc_Location());
211       TopLoc_Location aLoc;
212       if (!BRep_Tool::Surface (aFaceFwd, aLoc).IsNull())
213       {
214         myFaceAdaptor.Initialize (aFaceFwd, false);
215         mySLTool.SetSurface (myFaceAdaptor);
216         myHasNormals = true;
217       }
218     }
219   }
220   if (!myToMapColors)
221   {
222     return;
223   }
224
225   if (!myStyles.Find (myFace, myFaceStyle))
226   {
227     myFaceStyle = myDefStyle;
228   }
229
230   if (!myFaceStyle.Material().IsNull())
231   {
232     myHasFaceColor = true;
233     myFaceColor = myFaceStyle.Material()->BaseColor();
234   }
235   else if (myFaceStyle.IsSetColorSurf())
236   {
237     myHasFaceColor = true;
238     myFaceColor = myFaceStyle.GetColorSurfRGBA();
239   }
240 }