0022900: Problem with shape displaying in shading mode
[occt.git] / src / Prs3d / Prs3d_ShadedShape.gxx
CommitLineData
7fd59977 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
54static Standard_Real GetDeflection(const anyShape& aShape,
3c34883c 55 const Handle(Prs3d_Drawer)& aDrawer)
7fd59977 56{
3c34883c 57 Standard_Real aDeflection = aDrawer->MaximalChordialDeviation();
7fd59977 58 if (aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE) {
59 Bnd_Box B;
3c34883c 60 BRepBndLib::Add(aShape, B, Standard_False);
7fd59977 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)
3c34883c 66 * aDrawer->DeviationCoefficient()*4;
7fd59977 67 }
7fd59977 68 }
7fd59977 69 return aDeflection;
70}
71
72
73static Standard_Boolean ShadeFromShape(const anyShape& aShape,
3c34883c
O
74 const Standard_Real /*defle*/,
75 const Standard_Boolean /*share*/,
76 const Handle (Prs3d_Presentation)& aPresentation,
77 const Handle (Prs3d_Drawer)& aDrawer)
7fd59977 78{
3c34883c
O
79 anyShadedShapeTool SST;
80 Handle(Poly_Triangulation) T;
81 TopLoc_Location loc;
82 gp_Pnt p;
83 Standard_Integer i,j,k,decal ;
84 Standard_Integer t[3], n[3];
85 Standard_Integer nbTriangles = 0, nbVertices = 0;
7fd59977 86
3c34883c
O
87 // precision for compare square distances
88 double dPreci = Precision::Confusion()*Precision::Confusion();
7fd59977 89
3c34883c 90 if ( !aDrawer->ShadingAspectGlobal() ) {
7fd59977 91
3c34883c
O
92 Handle(Graphic3d_AspectFillArea3d) Asp = aDrawer->ShadingAspect()->Aspect();
93 if(anyShadedShapeTool::IsClosed(aShape)) {
94 Asp->SuppressBackFace();
95 } else {
96 Asp->AllowBackFace();
7fd59977 97 }
a10fa819 98 Prs3d_Root::CurrentGroup(aPresentation)->SetGroupPrimitivesAspect(Asp);
3c34883c 99 }
7fd59977 100
101#ifdef G005
3c34883c
O
102 if( Graphic3d_ArrayOfPrimitives::IsEnable() ) {
103
104 for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) {
105 const anyTopFace& F = SST.CurrentFace();
106 T = SST.Triangulation(F, loc);
107 if (!T.IsNull()) {
108 nbTriangles += T->NbTriangles();
109 nbVertices += T->NbNodes();
110 }
111 }
7fd59977 112
3c34883c
O
113 if (nbVertices > 2 && nbTriangles > 0) {
114 Handle(Graphic3d_ArrayOfTriangles) parray =
115 new Graphic3d_ArrayOfTriangles(nbVertices,3*nbTriangles,
116 Standard_True,Standard_False,Standard_False,Standard_True);
7fd59977 117 for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) {
118 const anyTopFace& F = SST.CurrentFace();
119 T = SST.Triangulation(F, loc);
120 if (!T.IsNull()) {
3c34883c
O
121 const gp_Trsf& trsf = loc.Transformation();
122 Poly_Connect pc(T);
123 // Extracts vertices & normals from nodes
124 const TColgp_Array1OfPnt& Nodes = T->Nodes();
125 TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper());
126 SST.Normal(F, pc, NORMAL);
7fd59977 127
3c34883c
O
128 decal = parray->VertexNumber();
129 for (i= Nodes.Lower(); i<= Nodes.Upper(); i++) {
130 p = Nodes(i);
131 if( !loc.IsIdentity() ) {
132 p.Transform(trsf);
133 NORMAL(i).Transform(trsf);
134 }
135 parray->AddVertex(p,NORMAL(i));
136 }
137
138 // Fill parray with vertex and edge visibillity info
139 const Poly_Array1OfTriangle& triangles = T->Triangles();
140 for (i = 1; i <= T->NbTriangles(); i++) {
141 pc.Triangles(i,t[0],t[1],t[2]);
142 if (SST.Orientation(F) == TopAbs_REVERSED)
143 triangles(i).Get(n[0],n[2],n[1]);
144 else
145 triangles(i).Get(n[0],n[1],n[2]);
146 gp_Pnt P1 = Nodes(n[0]);
147 gp_Pnt P2 = Nodes(n[1]);
148 gp_Pnt P3 = Nodes(n[2]);
149 gp_Vec V1(P1,P2);
150 if ( V1.SquareMagnitude() > dPreci ) {
151 gp_Vec V2(P2,P3);
152 if ( V2.SquareMagnitude() > dPreci ) {
153 gp_Vec V3(P3,P1);
154 if ( V3.SquareMagnitude() > dPreci ) {
155 V1.Normalize();
156 V2.Normalize();
157 V1.Cross(V2);
158 if ( V1.SquareMagnitude() > dPreci ) {
159 parray->AddEdge(n[0]+decal,t[0] == 0);
160 parray->AddEdge(n[1]+decal,t[1] == 0);
161 parray->AddEdge(n[2]+decal,t[2] == 0);
162 }
163 }
164 }
165 }
166 }
167 }
168 }
169 Prs3d_Root::CurrentGroup(aPresentation)->BeginPrimitives();
170 Prs3d_Root::CurrentGroup(aPresentation)->AddPrimitiveArray(parray);
171 Prs3d_Root::CurrentGroup(aPresentation)->EndPrimitives();
172 }
173 return Standard_True;
174 }
175#endif
7fd59977 176
3c34883c
O
177 // phase de comptage:
178 Standard_Integer nt, nnn, n1, n2, n3, nnv, EI;
179 static Standard_Integer plus1mod3[3] = {1, 2, 0};
180 for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) {
181 const anyTopFace& F = SST.CurrentFace();
182 T = SST.Triangulation(F, loc);
183 if (!T.IsNull()) {
184 nnn = T->NbTriangles();
185 const TColgp_Array1OfPnt& Nodes = T->Nodes();
186 const Poly_Array1OfTriangle& triangles = T->Triangles();
187 for (nt = 1; nt <= nnn; nt++) {
188 if (SST.Orientation(F) == TopAbs_REVERSED)
189 triangles(nt).Get(n1,n3,n2);
190 else
191 triangles(nt).Get(n1,n2,n3);
192 const gp_Pnt& P1 = Nodes(n1);
193 const gp_Pnt& P2 = Nodes(n2);
194 const gp_Pnt& P3 = Nodes(n3);
195 gp_Vec V1(P1,P2);
196 if ( V1.SquareMagnitude() > dPreci ) {
197 gp_Vec V2(P2,P3);
198 if (V2.SquareMagnitude() > dPreci ) {
199 gp_Vec V3(P3,P1);
200 if (V3.SquareMagnitude() > dPreci ) {
201 V1.Normalize();
202 V2.Normalize();
203 V1.Cross(V2);
204 if (V1.SquareMagnitude() > dPreci ) {
205 nbTriangles++;
206 }
207 }
7fd59977 208 }
3c34883c 209 }
7fd59977 210 }
3c34883c 211 nbVertices += T->NbNodes();
7fd59977 212 }
3c34883c 213 }
7fd59977 214
3c34883c
O
215 if (nbVertices > 2 && nbTriangles > 0) {
216 Graphic3d_Array1OfVertexN AVN(1, nbVertices);
217 Aspect_Array1OfEdge AE(1, 3*nbTriangles);
218
219 EI = 1;
220 nnv = 1;
221
7fd59977 222 for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) {
223 const anyTopFace& F = SST.CurrentFace();
224 T = SST.Triangulation(F, loc);
225 if (!T.IsNull()) {
3c34883c
O
226 Poly_Connect pc(T);
227 // 1- les noeuds.
228 const TColgp_Array1OfPnt& Nodes = T->Nodes();
229 TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper());
230 SST.Normal(F, pc, NORMAL);
231 decal = nnv-1;
232
233 for (j= Nodes.Lower(); j<= Nodes.Upper(); j++) {
234 p = Nodes(j).Transformed(loc.Transformation());
235 AVN(nnv).SetCoord(p.X(), p.Y(), p.Z());
236 AVN(nnv).SetNormal(NORMAL(j).X(), NORMAL(j).Y(), NORMAL(j).Z());
237 nnv++;
7fd59977 238 }
3c34883c
O
239 // 2- les edges.
240 nbTriangles = T->NbTriangles();
241 const Poly_Array1OfTriangle& triangles = T->Triangles();
242
243 for (i = 1; i <= nbTriangles; i++) {
244 pc.Triangles(i,t[0],t[1],t[2]);
245 if (SST.Orientation(F) == TopAbs_REVERSED)
246 triangles(i).Get(n[0],n[2],n[1]);
247 else
248 triangles(i).Get(n[0],n[1],n[2]);
249 const gp_Pnt& P1 = Nodes(n[0]);
250 const gp_Pnt& P2 = Nodes(n[1]);
251 const gp_Pnt& P3 = Nodes(n[2]);
252 gp_Vec V1(P1,P2);
253 if (V1.SquareMagnitude() > 1.e-10) {
254 gp_Vec V2(P2,P3);
255 if (V2.SquareMagnitude() > 1.e-10) {
256 gp_Vec V3(P3,P1);
257 if (V3.SquareMagnitude() > 1.e-10) {
258 V1.Normalize();
259 V2.Normalize();
260 V1.Cross(V2);
261 if (V1.SquareMagnitude() > 1.e-10) {
262 for (j = 0; j < 3; j++) {
263 k = plus1mod3[j];
264 if (t[j] == 0)
265 AE(EI).SetValues(n[j]+decal, n[k]+decal, Aspect_TOE_VISIBLE);
266 else
267 AE(EI).SetValues(n[j]+decal, n[k]+decal, Aspect_TOE_INVISIBLE);
268 EI++;
269 }
270 }
271 }
272 }
273 }
274 }
7fd59977 275 }
7fd59977 276 }
3c34883c
O
277 Prs3d_Root::CurrentGroup(aPresentation)->TriangleSet(AVN, AE);
278 }
279 return Standard_True;
7fd59977 280}
281
282
283
284void Prs3d_ShadedShape::Add(const Handle (Prs3d_Presentation)& aPresentation,
3c34883c
O
285 const anyShape& aShape,
286 const Handle (Prs3d_Drawer)& aDrawer)
7fd59977 287{
288
289 if (aShape.IsNull()) return;
290
291 TopAbs_ShapeEnum E = aShape.ShapeType();
292 if (E == TopAbs_COMPOUND) {
293 TopExp_Explorer ex;
294
295 ex.Init(aShape, TopAbs_FACE);
296 if (ex.More()) {
297 TopoDS_Compound CO;
298 BRep_Builder B;
299 B.MakeCompound(CO);
300 Standard_Boolean haselement = Standard_False;
301
302 // il faut presenter les edges isoles.
303 for (ex.Init(aShape, TopAbs_EDGE, TopAbs_FACE); ex.More(); ex.Next()) {
3c34883c
O
304 haselement = Standard_True;
305 B.Add(CO, ex.Current());
7fd59977 306 }
307 // il faut presenter les vertex isoles.
308 for (ex.Init(aShape, TopAbs_VERTEX, TopAbs_EDGE); ex.More(); ex.Next()) {
3c34883c
O
309 haselement = Standard_True;
310 B.Add(CO, ex.Current());
7fd59977 311 }
312 if (haselement) StdPrs_WFShape::Add(aPresentation, CO, aDrawer);
313 }
314 else {
315 StdPrs_WFShape::Add(aPresentation, aShape, aDrawer);
316 }
317 }
318 Standard_Real aDeflection = GetDeflection(aShape, aDrawer);
0b97567d 319
3c34883c
O
320 // Check if it is possible to avoid unnecessary recomputation
321 // of shape triangulation
0b97567d 322 if (!BRepTools::Triangulation (aShape, aDeflection))
3c34883c 323 {
0b97567d 324 BRepTools::Clean (aShape);
7fd59977 325
0b97567d
K
326 // retrieve meshing tool from Factory
327 Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (aShape,
328 aDeflection,
329 aDrawer->HLRAngle());
330 if (!aMeshAlgo.IsNull())
331 aMeshAlgo->Perform();
3c34883c 332 }
0b97567d 333
7fd59977 334 ShadeFromShape(aShape, aDeflection, Standard_True, aPresentation, aDrawer);
335}