a2edd4732990c920bdaf8f7a96db0a207cfeb46c
[occt.git] / src / Prs3d / Prs3d_ShadedShape.gxx
1 // File:        Prs3d_ShadedShape.gxx
2 // Created:     Thu Sep 23 18:47:22 1993
3 // Author:      Jean-Louis FRENKEL
4 //              <jlf@stylox>
5
6 //#define BUC60488//GG_081199 Enable the SuppressBackface() ShadingAspect attribute
7
8 #define G005    //ATS,GG 04/01/01 Use ArrayOfPrimitives instead Sets of primitives
9 //              for performance improvment
10
11 #include <Graphic3d_Vertex.hxx>
12 #include <Graphic3d_VertexN.hxx>
13 #include <Graphic3d_Array1OfVertexN.hxx>
14 #include <Graphic3d_Array1OfVertex.hxx>
15 #include <Aspect_Edge.hxx>
16 #include <Aspect_Array1OfEdge.hxx>
17 #include <gp_Pnt.hxx>
18 #include <gp_Dir.hxx>
19 #include <Prs3d_ShadingAspect.hxx>
20 #include <Graphic3d_Group.hxx>
21 #include <Aspect_TypeOfEdge.hxx>
22 #include <Bnd_Box.hxx>
23 #include <Graphic3d_AspectFillArea3d.hxx>
24 #include <BRepTools.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRep_Builder.hxx>
27 #include <TopoDS_Compound.hxx>
28 #include <Poly_Triangulation.hxx>
29 #include <TColgp_HArray1OfPnt.hxx>
30 #include <TColgp_Array1OfPnt.hxx>
31 #include <TColgp_Array1OfPnt2d.hxx>
32 #include <TColgp_Array1OfDir.hxx>
33 #include <Poly_Connect.hxx>
34 #include <TopAbs_Orientation.hxx>
35 #include <TColStd_MapOfInteger.hxx>
36 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
37 #include <BRepMesh_FactoryError.hxx>
38 #include <BRepMesh_DiscretRoot.hxx>
39 #include <BRepMesh_DiscretFactory.hxx>
40 #include <BRepMesh_PDiscretRoot.hxx>
41 #include <gp_Vec.hxx>
42 #include <StdPrs_WFShape.hxx>
43 #include <BRepBndLib.hxx>
44 #include <Precision.hxx>
45 #ifdef G005
46 #include <Graphic3d_ArrayOfTriangles.hxx>
47 #endif
48
49
50 #define MAX2(X, Y)      (  Abs(X) > Abs(Y)? Abs(X) : Abs(Y) )
51 #define MAX3(X, Y, Z)   ( MAX2 ( MAX2(X,Y) , Z) )
52
53
54 static Standard_Real GetDeflection(const anyShape&             aShape,
55                                    const Handle(Prs3d_Drawer)& aDrawer)
56 {
57   Standard_Real aDeflection;
58   if (aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE) {
59     Bnd_Box B;
60     BRepBndLib::Add(aShape, B);
61     if ( ! B.IsVoid() )
62     {
63       Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
64       B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
65       aDeflection = MAX3( aXmax-aXmin , aYmax-aYmin , aZmax-aZmin) 
66         * aDrawer->DeviationCoefficient()*4;    
67     }
68     else
69       aDeflection = aDrawer->MaximalChordialDeviation();
70   }
71   else
72     aDeflection = aDrawer->MaximalChordialDeviation();
73
74   return aDeflection;
75 }
76
77
78 static Standard_Boolean ShadeFromShape(const anyShape&                    aShape,
79                                        const Standard_Real                /*defle*/,
80                                        const Standard_Boolean             /*share*/,
81                                        const Handle (Prs3d_Presentation)& aPresentation,
82                                        const Handle (Prs3d_Drawer)&       aDrawer) 
83 {
84
85     anyShadedShapeTool SST;
86     Handle(Poly_Triangulation) T;
87     TopLoc_Location loc;
88     gp_Pnt p;
89     Standard_Integer i,j,k,decal ;
90     Standard_Integer t[3], n[3];
91     Standard_Integer nbTriangles = 0, nbVertices = 0;
92
93     // precision for compare square distances
94     double dPreci = Precision::Confusion()*Precision::Confusion();
95
96     if ( !aDrawer->ShadingAspectGlobal() ) {
97
98       Handle(Graphic3d_AspectFillArea3d) Asp = aDrawer->ShadingAspect()->Aspect();
99       if(anyShadedShapeTool::IsClosed(aShape)) {
100         Asp->SuppressBackFace();
101       } else {
102         Asp->AllowBackFace();
103       }
104       Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(Asp);
105     }
106
107 #ifdef G005
108     if( Graphic3d_ArrayOfPrimitives::IsEnable() ) {
109
110       for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) {
111         const anyTopFace& F = SST.CurrentFace();
112         T = SST.Triangulation(F, loc);
113         if (!T.IsNull()) {
114           nbTriangles += T->NbTriangles();
115           nbVertices += T->NbNodes();
116         }
117       } 
118
119       if (nbVertices > 2 && nbTriangles > 0) {
120         Handle(Graphic3d_ArrayOfTriangles) parray =
121                 new Graphic3d_ArrayOfTriangles(nbVertices,3*nbTriangles,
122                 Standard_True,Standard_False,Standard_False,Standard_True);
123         for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) {
124           const anyTopFace& F = SST.CurrentFace();
125           T = SST.Triangulation(F, loc);
126           if (!T.IsNull()) {
127             const gp_Trsf& trsf = loc.Transformation();
128             Poly_Connect pc(T);
129             // Extracts vertices & normals from nodes 
130             const TColgp_Array1OfPnt& Nodes = T->Nodes();
131             TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper());
132             SST.Normal(F, pc, NORMAL);
133
134             decal = parray->VertexNumber();
135             for (i= Nodes.Lower(); i<= Nodes.Upper(); i++) {
136               p = Nodes(i);
137               if( !loc.IsIdentity() ) {
138                 p.Transform(trsf);
139                 NORMAL(i).Transform(trsf);
140               }
141               parray->AddVertex(p,NORMAL(i));
142             }
143           
144             // Fill parray with vertex and edge visibillity info
145             const Poly_Array1OfTriangle& triangles = T->Triangles();
146             for (i = 1; i <= T->NbTriangles(); i++) {
147               pc.Triangles(i,t[0],t[1],t[2]);
148               if (SST.Orientation(F) == TopAbs_REVERSED) 
149                 triangles(i).Get(n[0],n[2],n[1]);
150               else 
151                 triangles(i).Get(n[0],n[1],n[2]);
152               gp_Pnt P1 = Nodes(n[0]);
153               gp_Pnt P2 = Nodes(n[1]);
154               gp_Pnt P3 = Nodes(n[2]);
155               gp_Vec V1(P1,P2);
156               if ( V1.SquareMagnitude() > dPreci ) {
157                 gp_Vec V2(P2,P3);
158                 if ( V2.SquareMagnitude() > dPreci ) {
159                   gp_Vec V3(P3,P1);
160                   if ( V3.SquareMagnitude() > dPreci ) {
161                     V1.Normalize();
162                     V2.Normalize();
163                     V1.Cross(V2);
164                     if ( V1.SquareMagnitude() > dPreci ) {
165                       parray->AddEdge(n[0]+decal,t[0] == 0);
166                       parray->AddEdge(n[1]+decal,t[1] == 0);
167                       parray->AddEdge(n[2]+decal,t[2] == 0);
168                     }
169                   }
170                 }
171               }
172             }
173           }
174         }    
175         Prs3d_Root::CurrentGroup(aPresentation)->BeginPrimitives();
176         Prs3d_Root::CurrentGroup(aPresentation)->AddPrimitiveArray(parray);
177         Prs3d_Root::CurrentGroup(aPresentation)->EndPrimitives();
178       }
179       return Standard_True;
180     }
181 #endif
182
183     // phase de comptage:
184     Standard_Integer nt, nnn, n1, n2, n3, nnv, EI;
185     static Standard_Integer plus1mod3[3] = {1, 2, 0};
186     for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) {
187       const anyTopFace& F = SST.CurrentFace();
188       T = SST.Triangulation(F, loc);
189       if (!T.IsNull()) {
190
191         nnn = T->NbTriangles();
192         const TColgp_Array1OfPnt& Nodes = T->Nodes();
193         const Poly_Array1OfTriangle& triangles = T->Triangles();
194         for (nt = 1; nt <= nnn; nt++) {
195           if (SST.Orientation(F) == TopAbs_REVERSED) 
196             triangles(nt).Get(n1,n3,n2);
197           else 
198             triangles(nt).Get(n1,n2,n3);
199           const gp_Pnt& P1 = Nodes(n1);
200           const gp_Pnt& P2 = Nodes(n2);
201           const gp_Pnt& P3 = Nodes(n3);
202           gp_Vec V1(P1,P2);
203           if ( V1.SquareMagnitude() > dPreci ) {
204             gp_Vec V2(P2,P3);
205             if (V2.SquareMagnitude() > dPreci ) {
206               gp_Vec V3(P3,P1);
207               if (V3.SquareMagnitude() > dPreci ) {
208                 V1.Normalize();
209                 V2.Normalize();
210                 V1.Cross(V2);
211                 if (V1.SquareMagnitude() > dPreci ) {
212                   nbTriangles++;
213                 }
214               }
215             }
216           }
217         }
218         nbVertices += T->NbNodes();
219       }
220     }      
221
222     if (nbVertices > 2 && nbTriangles > 0) {
223       Graphic3d_Array1OfVertexN AVN(1, nbVertices);
224       Aspect_Array1OfEdge AE(1, 3*nbTriangles);
225       
226       EI = 1;
227       nnv = 1;
228       
229       for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) {
230         const anyTopFace& F = SST.CurrentFace();
231         T = SST.Triangulation(F, loc);
232         if (!T.IsNull()) {
233           Poly_Connect pc(T);
234           // 1- les noeuds.
235           const TColgp_Array1OfPnt& Nodes = T->Nodes();
236           TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper());
237           SST.Normal(F, pc, NORMAL);
238           decal = nnv-1;
239          
240           for (j= Nodes.Lower(); j<= Nodes.Upper(); j++) {
241             p = Nodes(j).Transformed(loc.Transformation());
242             AVN(nnv).SetCoord(p.X(), p.Y(), p.Z());
243             AVN(nnv).SetNormal(NORMAL(j).X(), NORMAL(j).Y(), NORMAL(j).Z());
244             nnv++;
245           }
246           // 2- les edges.
247           nbTriangles = T->NbTriangles();
248           const Poly_Array1OfTriangle& triangles = T->Triangles();
249           
250           for (i = 1; i <= nbTriangles; i++) {
251             pc.Triangles(i,t[0],t[1],t[2]);
252             if (SST.Orientation(F) == TopAbs_REVERSED) 
253               triangles(i).Get(n[0],n[2],n[1]);
254             else 
255               triangles(i).Get(n[0],n[1],n[2]);
256             const gp_Pnt& P1 = Nodes(n[0]);
257             const gp_Pnt& P2 = Nodes(n[1]);
258             const gp_Pnt& P3 = Nodes(n[2]);
259             gp_Vec V1(P1,P2);
260             if (V1.SquareMagnitude() > 1.e-10) {
261               gp_Vec V2(P2,P3);
262               if (V2.SquareMagnitude() > 1.e-10) {
263                 gp_Vec V3(P3,P1);
264                 if (V3.SquareMagnitude() > 1.e-10) {
265                   V1.Normalize();
266                   V2.Normalize();
267                   V1.Cross(V2);
268                   if (V1.SquareMagnitude() > 1.e-10) {
269                     for (j = 0; j < 3; j++) {
270                       k = plus1mod3[j];
271                       if (t[j] == 0)
272                         AE(EI).SetValues(n[j]+decal, n[k]+decal, Aspect_TOE_VISIBLE);
273                       else
274                         AE(EI).SetValues(n[j]+decal, n[k]+decal, Aspect_TOE_INVISIBLE);
275                       EI++;
276                     }
277                   }
278                 }
279               }
280             }
281           }    
282         }
283       }
284       Prs3d_Root::CurrentGroup(aPresentation)->TriangleSet(AVN, AE);
285     }
286     return Standard_True;
287 }
288
289
290
291 void Prs3d_ShadedShape::Add(const Handle (Prs3d_Presentation)& aPresentation,
292                             const anyShape&                    aShape,
293                             const Handle (Prs3d_Drawer)&       aDrawer)
294 {
295
296   if (aShape.IsNull()) return;
297
298   TopAbs_ShapeEnum E = aShape.ShapeType();
299   if (E == TopAbs_COMPOUND) {
300     TopExp_Explorer ex;
301
302     ex.Init(aShape, TopAbs_FACE);
303     if (ex.More()) {
304       TopoDS_Compound CO;
305       BRep_Builder B;
306       B.MakeCompound(CO);
307       Standard_Boolean haselement = Standard_False;
308
309       // il faut presenter les edges  isoles.
310       for (ex.Init(aShape, TopAbs_EDGE, TopAbs_FACE); ex.More(); ex.Next()) {
311         haselement = Standard_True;
312         B.Add(CO, ex.Current());
313       }
314       // il faut presenter les vertex isoles.
315       for (ex.Init(aShape, TopAbs_VERTEX, TopAbs_EDGE); ex.More(); ex.Next()) {
316         haselement = Standard_True;
317         B.Add(CO, ex.Current());
318       }
319       if (haselement) StdPrs_WFShape::Add(aPresentation, CO, aDrawer);
320     }
321     else {
322       StdPrs_WFShape::Add(aPresentation, aShape, aDrawer);
323     }
324   }
325   Standard_Real aDeflection = GetDeflection(aShape, aDrawer);
326   //using of plugin
327   BRepMesh_PDiscretRoot pAlgo;
328   pAlgo=BRepMesh_DiscretFactory::Get().Discret(aShape,
329                                                aDeflection,
330                                                aDrawer->HLRAngle());
331   if (pAlgo)
332     pAlgo->Perform();
333
334   ShadeFromShape(aShape, aDeflection, Standard_True, aPresentation, aDrawer);
335 }
336
337