0028838: Configuration - undefine macros coming from X11 headers in place of collision
[occt.git] / src / VrmlConverter / VrmlConverter_ShadedShape.cxx
1 // Copyright (c) 1999-2014 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 <VrmlConverter_Drawer.hxx>
15 #include <VrmlConverter_ShadedShape.hxx>
16 #include <Vrml_Normal.hxx>
17 #include <TopoDS_Shape.hxx>
18 #include <TopoDS_Face.hxx>
19 #include <TopoDS.hxx>
20 #include <TopAbs.hxx>
21 #include <Poly_Connect.hxx>
22 #include <TColgp_Array1OfDir.hxx>
23 #include <TColgp_HArray1OfVec.hxx>
24 #include <Poly_Triangle.hxx>
25 #include <Poly_Triangulation.hxx>
26 #include <BRepTools.hxx>
27 #include <BRep_Tool.hxx>
28 #include <gp_Pnt.hxx>
29 #include <gp_Vec.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopLoc_Location.hxx>
32 #include <TColgp_Array1OfPnt.hxx>
33 #include <Poly_Array1OfTriangle.hxx>
34 #include <Vrml_IndexedFaceSet.hxx>
35 #include <Vrml_Coordinate3.hxx>
36 #include <BRepBndLib.hxx>
37 #include <Bnd_Box.hxx>
38 #include <math.hxx>
39 #include <TColStd_HArray1OfInteger.hxx>
40 #include <Geom_Surface.hxx>
41 #include <CSLib_DerivativeStatus.hxx>
42 #include <CSLib_NormalStatus.hxx>
43 #include <CSLib.hxx>
44 #include <BRepAdaptor_Surface.hxx>
45 #include <TColgp_Array1OfPnt2d.hxx>
46 #include <Precision.hxx>
47 #include <Vrml_Material.hxx>
48 #include <VrmlConverter_ShadingAspect.hxx>
49 #include <Vrml_ShapeHints.hxx>
50 #include <Vrml_MaterialBindingAndNormalBinding.hxx>
51 #include <Vrml_NormalBinding.hxx>
52 #include <Vrml_Separator.hxx>
53 #include <Vrml_NormalBinding.hxx>
54 #include <BRepMesh_IncrementalMesh.hxx>
55
56 //=========================================================================
57 // function: Add
58 // purpose
59 //=========================================================================
60 void VrmlConverter_ShadedShape::Add( Standard_OStream& anOStream, 
61                                      const TopoDS_Shape& aShape,
62                                      const Handle(VrmlConverter_Drawer)& aDrawer )
63   {
64   Handle(Poly_Triangulation) T;
65   TopLoc_Location theLocation;
66   Standard_Integer i, j, k, decal, nnv, EI;
67   
68   Standard_Integer t[3], n[3];
69   gp_Pnt p;
70   TopExp_Explorer ex;
71
72   // counting phasis. This phasis will count the valid triangle
73   // and the vertices to allocate the correct size for the arrays: 
74   
75   Standard_Integer nbTriangles = 0, nbVertices = 0;
76   
77   Standard_Integer nt, nnn, n1, n2, n3;
78     
79   // iterating on each face of the shape:
80   for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {  
81     // getting the face:
82     const TopoDS_Face& F = TopoDS::Face(ex.Current());
83     // getting the triangulation of the face. The triangulation may not exist:
84     T = BRep_Tool::Triangulation(F, theLocation);
85       // number of triangles:
86     if (T.IsNull()) continue; //smh 
87       nnn = T->NbTriangles();            
88     
89     const TColgp_Array1OfPnt& Nodes = T->Nodes(); 
90     // getting a triangle. It is  a triplet of indices in the node table:       
91     const Poly_Array1OfTriangle& triangles = T->Triangles(); 
92     
93     // Taking the nodes of the triangle, taking into account the orientation
94     // of the triangle.
95     for (nt = 1; nt <= nnn; nt++) {
96       if (F.Orientation() == TopAbs_REVERSED) 
97         triangles(nt).Get(n1,n3,n2);
98       else 
99         triangles(nt).Get(n1,n2,n3);
100       
101       const gp_Pnt& P1 = Nodes(n1);
102       const gp_Pnt& P2 = Nodes(n2);
103       const gp_Pnt& P3 = Nodes(n3);
104       // controlling whether the triangle correct from a 3d point of 
105       // view: (the triangle may exist in the UV space but the
106       // in the 3d space a dimension is null for example)
107       gp_Vec V1(P1,P2);
108       if (V1.SquareMagnitude() > 1.e-10) {
109         gp_Vec V2(P2,P3);
110         if (V2.SquareMagnitude() > 1.e-10) {
111           gp_Vec V3(P3,P1);
112           if (V3.SquareMagnitude() > 1.e-10) {
113             V1.Normalize();
114             V2.Normalize();
115             V1.Cross(V2);
116             if (V1.SquareMagnitude() > 1.e-10) {
117               nbTriangles++;
118               }
119           }
120         }
121       }
122     }
123     nbVertices += T->NbNodes();
124   }      
125
126 //     cout << "nbTriangles = "<< nbTriangles << endl;
127 //     cout  << "nbVertices = "<< nbVertices << endl << endl;  
128
129 //----------------------------
130   // now we are going to iterate again to build graphic data from the triangle.   
131   if (nbVertices > 2 && nbTriangles > 0) {
132     // allocating the graphic arrays.
133
134      Handle(VrmlConverter_ShadingAspect) SA = new VrmlConverter_ShadingAspect;
135      SA = aDrawer->ShadingAspect();
136
137      Handle(TColgp_HArray1OfVec) HAV1 = new TColgp_HArray1OfVec(1, nbVertices);
138      Handle(TColgp_HArray1OfVec) HAV2 = new TColgp_HArray1OfVec(1, nbVertices);
139      
140      gp_Vec V, VV;
141
142      Handle(TColStd_HArray1OfInteger) HAI1 = new TColStd_HArray1OfInteger(1,4*nbTriangles);
143      Handle(TColStd_HArray1OfInteger) HAI3 = new TColStd_HArray1OfInteger(1,(nbVertices/3*4+nbVertices%3));
144      Handle(TColStd_HArray1OfInteger) HAI2 = new TColStd_HArray1OfInteger(1,1);
145      Handle(TColStd_HArray1OfInteger) HAI4 = new TColStd_HArray1OfInteger(1,1);
146
147         HAI2->SetValue (1,-1);
148         HAI4->SetValue (1,-1);
149
150 // !! Specialize HAI2 -  materialIndex  HAI4 - textureCoordinateIndex
151
152     EI = 1;
153     nnv = 1;
154
155     for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {
156       const TopoDS_Face& F = TopoDS::Face(ex.Current());
157       T = BRep_Tool::Triangulation(F, theLocation);
158       if (!T.IsNull()) {
159         Poly_Connect pc(T);
160         
161         // 1 -  Building HAV1 -  array of all XYZ of nodes for Vrml_Coordinate3 from the triangles
162         //            and HAV2 - array of all normals of nodes for Vrml_Normal
163         
164         const TColgp_Array1OfPnt& Nodes = T->Nodes();
165         TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper());
166
167           decal = nnv-1;
168         
169         for (j= Nodes.Lower(); j<= Nodes.Upper(); j++) {
170           p = Nodes(j).Transformed(theLocation.Transformation());
171
172           V.SetX(p.X()); V.SetY(p.Y()); V.SetZ(p.Z());
173           HAV1->SetValue(nnv,V);
174
175           if(SA->HasNormals())
176             {
177                 // to compute the normal.
178               ComputeNormal(F, pc, NORMAL);
179
180               VV.SetX(NORMAL(j).X());  VV.SetY(NORMAL(j).Y());  VV.SetZ(NORMAL(j).Z());
181               HAV2->SetValue(nnv,VV);
182             }
183           nnv++;
184         }
185         
186         // 2 -   Building HAI1 - array of indexes of all triangles and
187         //        HAI3 - array of indexes of all normales  for Vrml_IndexedFaceSet
188         nbTriangles = T->NbTriangles();
189         const Poly_Array1OfTriangle& triangles = T->Triangles();        
190         for (i = 1; i <= nbTriangles; i++) {
191           pc.Triangles(i,t[0],t[1],t[2]);
192           if (F.Orientation() == TopAbs_REVERSED) 
193             triangles(i).Get(n[0],n[2],n[1]);
194           else 
195             triangles(i).Get(n[0],n[1],n[2]);
196           const gp_Pnt& P1 = Nodes(n[0]);
197           const gp_Pnt& P2 = Nodes(n[1]);
198           const gp_Pnt& P3 = Nodes(n[2]);
199           gp_Vec V1(P1,P2);
200           if (V1.SquareMagnitude() > 1.e-10) {
201             gp_Vec V2(P2,P3);
202             if (V2.SquareMagnitude() > 1.e-10) {
203               gp_Vec V3(P3,P1);
204               if (V3.SquareMagnitude() > 1.e-10) {
205                 V1.Normalize();
206                 V2.Normalize();
207                 V1.Cross(V2);
208                 if (V1.SquareMagnitude() > 1.e-10) {
209                   for (j = 0; j < 3; j++) {
210                    
211                     HAI1->SetValue(EI, n[j]+decal-1);   // array of indexes of all triangles
212                     EI++;
213                   }
214
215                   HAI1->SetValue(EI, -1);                   
216                   EI++;           
217                 }
218               }
219             }
220           }
221         }
222       }
223     }
224   
225
226      if(SA->HasNormals())
227        {
228          j=1;
229          for (i=HAI3->Lower(); i <= HAI3->Upper(); i++)
230            {
231              k = i % 4;
232              if (k == 0)
233                {
234                  HAI3->SetValue(i, -1);
235                  j++;
236                }
237              else
238                {
239                  HAI3->SetValue(i, i-j);   
240                }
241            }
242        }
243
244 //-----------------------------
245 /*
246   cout  << " ******************** " << endl;  
247      cout  << " Array HAV1 - Coordinare3 " << endl;  
248
249      for ( i=HAV1->Lower(); i <= HAV1->Upper(); i++ )
250        {
251          cout << HAV1->Value(i).X() << " " << HAV1->Value(i).Y()<< " " << HAV1->Value(i).Z() << endl; 
252        }
253
254      if(SA->HasNormals())
255        {
256
257          cout  << " ******************** " << endl;         
258          cout  << " Array HAV2 - Normals " << endl;  
259
260          for ( i=HAV2->Lower(); i <= HAV2->Upper(); i++ )
261            {
262              cout << HAV2->Value(i).X() << " " << HAV2->Value(i).Y()<< " " << HAV2->Value(i).Z() << endl; 
263            }
264
265          cout  << " ******************** " << endl;  
266          cout  << " Array HAI3 - normalIndex " << endl;  
267
268          for ( i=HAI3->Lower(); i <= HAI3->Upper(); i++ )
269            {
270              cout << HAI3->Value(i) << endl;
271            }
272
273        }
274
275      cout  << " ******************** " << endl;         
276      cout  << " Array HAI1 - coordIndex " << endl;  
277        
278      for ( i=HAI1->Lower(); i <= HAI1->Upper(); i++ )
279        {
280          cout << HAI1->Value(i) << endl;
281        }
282    
283      cout  << " ******************** " << endl;       
284 */
285 //----------------------------
286
287 // creation of Vrml objects
288
289      Vrml_ShapeHints  SH; 
290      SH = SA->ShapeHints();
291
292      if(SA->HasNormals())
293        {
294 // Separator 1 {
295      Vrml_Separator SE1;
296      SE1.Print(anOStream);
297 // Material
298   if (SA->HasMaterial()){
299
300      Handle(Vrml_Material) M;
301      M = SA->FrontMaterial();
302
303      M->Print(anOStream);
304    }
305
306 // Coordinate3
307      Handle(Vrml_Coordinate3)  C3 = new Vrml_Coordinate3(HAV1);
308      C3->Print(anOStream);
309 // ShapeHints
310      SH.Print(anOStream);
311 // NormalBinding
312      Vrml_MaterialBindingAndNormalBinding MBNB1 = Vrml_PER_VERTEX_INDEXED;
313      Vrml_NormalBinding   NB(MBNB1);
314      NB.Print(anOStream);
315 // Separator 2 {
316      Vrml_Separator SE2;
317      SE2.Print(anOStream);
318 // Normal
319      Vrml_Normal  N(HAV2);
320      N.Print(anOStream);
321 // IndexedFaceSet
322      Vrml_IndexedFaceSet  IFS;
323      IFS.SetCoordIndex(HAI1);
324      IFS.SetNormalIndex(HAI3);
325      IFS.Print(anOStream);
326 // Separator 2 }     
327      SE2.Print(anOStream);
328 // Separator 1 }
329      SE1.Print(anOStream);
330         }
331      else 
332        { 
333 // Separator 1 {
334      Vrml_Separator SE1;
335      SE1.Print(anOStream);
336 // Material
337   if (SA->HasMaterial()){
338
339      Handle(Vrml_Material) M;
340      M = SA->FrontMaterial();
341
342      M->Print(anOStream);
343    }
344 // Coordinate3
345      Handle(Vrml_Coordinate3)  C3 = new Vrml_Coordinate3(HAV1);
346      C3->Print(anOStream);
347 // ShapeHints
348      SH.Print(anOStream);
349 // IndexedFaceSet
350      Vrml_IndexedFaceSet  IFS;
351      IFS.SetCoordIndex(HAI1);
352      IFS.Print(anOStream);
353 // Separator 1 }
354      SE1.Print(anOStream);
355        }
356   }
357 }
358
359
360 //--------- Notes -------------
361
362 // the necessary of calculation of Normals and Textures must be define in Drawer
363 // likes tolerance
364
365 //---------- End on notes ------------
366
367
368
369 //----------------------------
370 // Computing the normal
371 //-----------------------------
372
373 void VrmlConverter_ShadedShape::ComputeNormal(const TopoDS_Face& aFace, 
374                                               Poly_Connect& pc, 
375                                               TColgp_Array1OfDir& Nor)
376 {
377   const Handle(Poly_Triangulation)& T = pc.Triangulation();
378   BRepAdaptor_Surface S;
379   Standard_Boolean hasUV = T->HasUVNodes();
380   Standard_Integer i;
381   TopLoc_Location l;
382   Handle(Geom_Surface) GS = BRep_Tool::Surface(aFace, l);
383
384   if (hasUV && !GS.IsNull()) {
385     Standard_Boolean OK = Standard_True;
386     gp_Vec D1U,D1V;
387     gp_Vec D2U,D2V,D2UV;
388     gp_Pnt P;
389     Standard_Real U, V;
390     CSLib_DerivativeStatus aStatus;
391     CSLib_NormalStatus NStat;
392     S.Initialize(aFace);
393     const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes();
394     for (i = UVNodes.Lower(); i <= UVNodes.Upper(); i++) {
395       U = UVNodes(i).X();
396       V = UVNodes(i).Y();
397       S.D1(U,V,P,D1U,D1V);
398       CSLib::Normal(D1U,D1V,Precision::Angular(),aStatus,Nor(i));
399       if (aStatus != CSLib_Done) {
400         S.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
401         CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor(i));
402       }
403       if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
404     }
405   }
406   else {
407     const TColgp_Array1OfPnt& Nodes = T->Nodes();
408     Standard_Integer n[3];
409     const Poly_Array1OfTriangle& triangles = T->Triangles();
410
411     for (i = Nodes.Lower(); i <= Nodes.Upper(); i++) {
412       gp_XYZ eqPlan(0, 0, 0);
413       for (pc.Initialize(i);  pc.More(); pc.Next()) {
414         triangles(pc.Value()).Get(n[0], n[1], n[2]);
415         gp_XYZ v1(Nodes(n[1]).Coord()-Nodes(n[0]).Coord());
416         gp_XYZ v2(Nodes(n[2]).Coord()-Nodes(n[1]).Coord());
417         eqPlan += (v1^v2).Normalized();
418       }
419       Nor(i) = gp_Dir(eqPlan);
420       if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
421     }
422   }
423 }
424
425