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