0029303: Data Exchange - add RWObj_CafWriter tool for wavefront OBJ file
[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   myHasNormals (false),
35   myIsMirrored (false),
36   myHasFaceColor (false)
37 {
38   TopoDS_Shape aShape;
39   if (!XCAFDoc_ShapeTool::GetShape (theLabel, aShape)
40    ||  aShape.IsNull())
41   {
42     return;
43   }
44
45   aShape.Location (theLocation);
46   myFaceIter.Init (aShape, TopAbs_FACE);
47
48   if (theToMapColors)
49   {
50     dispatchStyles (theLabel, theLocation, theStyle);
51   }
52
53   Next();
54 }
55
56 // =======================================================================
57 // function : dispatchStyles
58 // purpose  :
59 // =======================================================================
60 void RWMesh_FaceIterator::dispatchStyles (const TDF_Label&       theLabel,
61                                           const TopLoc_Location& theLocation,
62                                           const XCAFPrs_Style&   theStyle)
63 {
64   TopLoc_Location aDummyLoc;
65   XCAFPrs_IndexedDataMapOfShapeStyle aStyles;
66   XCAFPrs::CollectStyleSettings (theLabel, aDummyLoc, aStyles);
67
68   Standard_Integer aNbTypes[TopAbs_SHAPE] = {};
69   for (Standard_Integer aTypeIter = TopAbs_FACE; aTypeIter >= TopAbs_COMPOUND; --aTypeIter)
70   {
71     if (aTypeIter != TopAbs_FACE
72      && aNbTypes[aTypeIter] == 0)
73     {
74       continue;
75     }
76
77     for (XCAFPrs_IndexedDataMapOfShapeStyle::Iterator aStyleIter (aStyles); aStyleIter.More(); aStyleIter.Next())
78     {
79       const TopoDS_Shape&    aKeyShape     = aStyleIter.Key();
80       const TopAbs_ShapeEnum aKeyShapeType = aKeyShape.ShapeType();
81       if (aTypeIter == TopAbs_FACE)
82       {
83         ++aNbTypes[aKeyShapeType];
84       }
85       if (aTypeIter != aKeyShapeType)
86       {
87         continue;
88       }
89
90       XCAFPrs_Style aCafStyle = aStyleIter.Value();
91       if (!aCafStyle.IsSetColorCurv()
92          && theStyle.IsSetColorCurv())
93       {
94         aCafStyle.SetColorCurv (theStyle.GetColorCurv());
95       }
96       if (!aCafStyle.IsSetColorSurf()
97          && theStyle.IsSetColorSurf())
98       {
99         aCafStyle.SetColorSurf (theStyle.GetColorSurfRGBA());
100       }
101       if (aCafStyle.Material().IsNull()
102        && !theStyle.Material().IsNull())
103       {
104         aCafStyle.SetMaterial (theStyle.Material());
105       }
106
107       TopoDS_Shape aKeyShapeLocated = aKeyShape.Located (theLocation);
108       if (aKeyShapeType == TopAbs_FACE)
109       {
110         myStyles.Bind (aKeyShapeLocated, aCafStyle);
111       }
112       else
113       {
114         for (TopExp_Explorer aFaceIter (aKeyShapeLocated, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
115         {
116           if (!myStyles.IsBound (aFaceIter.Current()))
117           {
118             myStyles.Bind (aFaceIter.Current(), aCafStyle);
119           }
120         }
121       }
122     }
123   }
124 }
125
126 // =======================================================================
127 // function : normal
128 // purpose  :
129 // =======================================================================
130 gp_Dir RWMesh_FaceIterator::normal (Standard_Integer theNode) const
131 {
132   gp_Dir aNormal (gp::DZ());
133   if (myPolyTriang->HasNormals())
134   {
135     Graphic3d_Vec3 aNormVec3;
136     myPolyTriang->Normal (theNode, aNormVec3);
137     if (aNormVec3.Modulus() != 0.0f)
138     {
139       aNormal.SetCoord (aNormVec3.x(), aNormVec3.y(), aNormVec3.z());
140     }
141   }
142   else if (myHasNormals
143         && myPolyTriang->HasUVNodes())
144   {
145     const gp_XY anUV = myPolyTriang->UVNode (theNode).XY();
146     mySLTool.SetParameters (anUV.X(), anUV.Y());
147     if (mySLTool.IsNormalDefined())
148     {
149       aNormal = mySLTool.Normal();
150     }
151   }
152   return aNormal;
153 }
154
155 // =======================================================================
156 // function : Next
157 // purpose  :
158 // =======================================================================
159 void RWMesh_FaceIterator::Next()
160 {
161   for (; myFaceIter.More(); myFaceIter.Next())
162   {
163     myFace       = TopoDS::Face (myFaceIter.Current());
164     myPolyTriang = BRep_Tool::Triangulation (myFace, myFaceLocation);
165     myTrsf       = myFaceLocation.Transformation();
166     if (myPolyTriang.IsNull()
167      || myPolyTriang->NbTriangles() == 0)
168     {
169       resetFace();
170       continue;
171     }
172
173     initFace();
174     myFaceIter.Next();
175     return;
176   }
177
178   resetFace();
179 }
180
181 // =======================================================================
182 // function : initFace
183 // purpose  :
184 // =======================================================================
185 void RWMesh_FaceIterator::initFace()
186 {
187   myHasNormals   = false;
188   myHasFaceColor = false;
189   myIsMirrored   = myTrsf.VectorialPart().Determinant() < 0.0;
190   if (myPolyTriang->HasNormals())
191   {
192     myHasNormals = true;
193   }
194   if (myPolyTriang->HasUVNodes() && !myHasNormals)
195   {
196     TopoDS_Face aFaceFwd = TopoDS::Face (myFace.Oriented (TopAbs_FORWARD));
197     aFaceFwd.Location (TopLoc_Location());
198     TopLoc_Location aLoc;
199     if (!BRep_Tool::Surface (aFaceFwd, aLoc).IsNull())
200     {
201       myFaceAdaptor.Initialize (aFaceFwd, false);
202       mySLTool.SetSurface (myFaceAdaptor);
203       myHasNormals = true;
204     }
205   }
206   if (!myToMapColors)
207   {
208     return;
209   }
210
211   if (!myStyles.Find (myFace, myFaceStyle))
212   {
213     myFaceStyle = myDefStyle;
214   }
215
216   if (!myFaceStyle.Material().IsNull())
217   {
218     myHasFaceColor = true;
219     myFaceColor = myFaceStyle.Material()->BaseColor();
220   }
221   else if (myFaceStyle.IsSetColorSurf())
222   {
223     myHasFaceColor = true;
224     myFaceColor = myFaceStyle.GetColorSurfRGBA();
225   }
226 }