1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
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>
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>
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>
39 #include <TColStd_HArray1OfInteger.hxx>
40 #include <Geom_Surface.hxx>
41 #include <CSLib_DerivativeStatus.hxx>
42 #include <CSLib_NormalStatus.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>
56 //=========================================================================
59 //=========================================================================
60 void VrmlConverter_ShadedShape::Add( Standard_OStream& anOStream,
61 const TopoDS_Shape& aShape,
62 const Handle(VrmlConverter_Drawer)& aDrawer )
65 // here the triangulation is computed on the whole shape
66 // if it does not yet exist
69 Standard_Real theRequestedDeflection;
70 if(aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE) // TOD_RELATIVE, TOD_ABSOLUTE
73 BRepBndLib::AddClose(aShape, box);
75 Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax, diagonal;
76 box.Get( Xmin, Ymin, Zmin, Xmax, Ymax, Zmax );
77 if (!(box.IsOpenXmin() || box.IsOpenXmax() ||
78 box.IsOpenYmin() || box.IsOpenYmax() ||
79 box.IsOpenZmin() || box.IsOpenZmax()))
82 diagonal = Sqrt ((Xmax - Xmin)*( Xmax - Xmin) + ( Ymax - Ymin)*( Ymax - Ymin) + ( Zmax - Zmin)*( Zmax - Zmin));
83 diagonal = Max(diagonal, Precision::Confusion());
84 theRequestedDeflection = aDrawer->DeviationCoefficient() * diagonal;
89 theRequestedDeflection = aDrawer->DeviationCoefficient() * diagonal;
91 // cout << "diagonal = "<< diagonal << endl;
92 // cout << "theRequestedDeflection = "<< theRequestedDeflection << endl;
97 theRequestedDeflection = aDrawer->MaximalChordialDeviation();
100 if (!BRepTools::Triangulation(aShape,theRequestedDeflection))
102 // computes and save the triangulation in the face.
103 BRepMesh_IncrementalMesh(aShape,theRequestedDeflection);
107 Handle(Poly_Triangulation) T;
108 TopLoc_Location theLocation;
109 Standard_Integer i, j, k, decal, nnv, EI;
111 Standard_Integer t[3], n[3];
115 // counting phasis. This phasis will count the valid triangle
116 // and the vertices to allocate the correct size for the arrays:
118 Standard_Integer nbTriangles = 0, nbVertices = 0;
120 Standard_Integer nt, nnn, n1, n2, n3;
122 // iterating on each face of the shape:
123 for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {
125 const TopoDS_Face& F = TopoDS::Face(ex.Current());
126 // getting the triangulation of the face. The triangulation may not exist:
127 T = BRep_Tool::Triangulation(F, theLocation);
128 // number of triangles:
129 if (T.IsNull()) continue; //smh
130 nnn = T->NbTriangles();
132 const TColgp_Array1OfPnt& Nodes = T->Nodes();
133 // getting a triangle. It is a triplet of indices in the node table:
134 const Poly_Array1OfTriangle& triangles = T->Triangles();
136 // Taking the nodes of the triangle, taking into account the orientation
138 for (nt = 1; nt <= nnn; nt++) {
139 if (F.Orientation() == TopAbs_REVERSED)
140 triangles(nt).Get(n1,n3,n2);
142 triangles(nt).Get(n1,n2,n3);
144 const gp_Pnt& P1 = Nodes(n1);
145 const gp_Pnt& P2 = Nodes(n2);
146 const gp_Pnt& P3 = Nodes(n3);
147 // controlling whether the triangle correct from a 3d point of
148 // view: (the triangle may exist in the UV space but the
149 // in the 3d space a dimension is null for example)
151 if (V1.SquareMagnitude() > 1.e-10) {
153 if (V2.SquareMagnitude() > 1.e-10) {
155 if (V3.SquareMagnitude() > 1.e-10) {
159 if (V1.SquareMagnitude() > 1.e-10) {
166 nbVertices += T->NbNodes();
169 // cout << "nbTriangles = "<< nbTriangles << endl;
170 // cout << "nbVertices = "<< nbVertices << endl << endl;
172 //----------------------------
173 // now we are going to iterate again to build graphic data from the triangle.
174 if (nbVertices > 2 && nbTriangles > 0) {
175 // allocating the graphic arrays.
177 Handle(VrmlConverter_ShadingAspect) SA = new VrmlConverter_ShadingAspect;
178 SA = aDrawer->ShadingAspect();
180 Handle(TColgp_HArray1OfVec) HAV1 = new TColgp_HArray1OfVec(1, nbVertices);
181 Handle(TColgp_HArray1OfVec) HAV2 = new TColgp_HArray1OfVec(1, nbVertices);
185 Handle(TColStd_HArray1OfInteger) HAI1 = new TColStd_HArray1OfInteger(1,4*nbTriangles);
186 Handle(TColStd_HArray1OfInteger) HAI3 = new TColStd_HArray1OfInteger(1,(nbVertices/3*4+nbVertices%3));
187 Handle(TColStd_HArray1OfInteger) HAI2 = new TColStd_HArray1OfInteger(1,1);
188 Handle(TColStd_HArray1OfInteger) HAI4 = new TColStd_HArray1OfInteger(1,1);
190 HAI2->SetValue (1,-1);
191 HAI4->SetValue (1,-1);
193 // !! Specialize HAI2 - materialIndex HAI4 - textureCoordinateIndex
198 for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {
199 const TopoDS_Face& F = TopoDS::Face(ex.Current());
200 T = BRep_Tool::Triangulation(F, theLocation);
204 // 1 - Building HAV1 - array of all XYZ of nodes for Vrml_Coordinate3 from the triangles
205 // and HAV2 - array of all normals of nodes for Vrml_Normal
207 const TColgp_Array1OfPnt& Nodes = T->Nodes();
208 TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper());
212 for (j= Nodes.Lower(); j<= Nodes.Upper(); j++) {
213 p = Nodes(j).Transformed(theLocation.Transformation());
215 V.SetX(p.X()); V.SetY(p.Y()); V.SetZ(p.Z());
216 HAV1->SetValue(nnv,V);
220 // to compute the normal.
221 ComputeNormal(F, pc, NORMAL);
223 VV.SetX(NORMAL(j).X()); VV.SetY(NORMAL(j).Y()); VV.SetZ(NORMAL(j).Z());
224 HAV2->SetValue(nnv,VV);
229 // 2 - Building HAI1 - array of indexes of all triangles and
230 // HAI3 - array of indexes of all normales for Vrml_IndexedFaceSet
231 nbTriangles = T->NbTriangles();
232 const Poly_Array1OfTriangle& triangles = T->Triangles();
233 for (i = 1; i <= nbTriangles; i++) {
234 pc.Triangles(i,t[0],t[1],t[2]);
235 if (F.Orientation() == TopAbs_REVERSED)
236 triangles(i).Get(n[0],n[2],n[1]);
238 triangles(i).Get(n[0],n[1],n[2]);
239 const gp_Pnt& P1 = Nodes(n[0]);
240 const gp_Pnt& P2 = Nodes(n[1]);
241 const gp_Pnt& P3 = Nodes(n[2]);
243 if (V1.SquareMagnitude() > 1.e-10) {
245 if (V2.SquareMagnitude() > 1.e-10) {
247 if (V3.SquareMagnitude() > 1.e-10) {
251 if (V1.SquareMagnitude() > 1.e-10) {
252 for (j = 0; j < 3; j++) {
254 HAI1->SetValue(EI, n[j]+decal-1); // array of indexes of all triangles
258 HAI1->SetValue(EI, -1);
272 for (i=HAI3->Lower(); i <= HAI3->Upper(); i++)
277 HAI3->SetValue(i, -1);
282 HAI3->SetValue(i, i-j);
287 //-----------------------------
289 cout << " ******************** " << endl;
290 cout << " Array HAV1 - Coordinare3 " << endl;
292 for ( i=HAV1->Lower(); i <= HAV1->Upper(); i++ )
294 cout << HAV1->Value(i).X() << " " << HAV1->Value(i).Y()<< " " << HAV1->Value(i).Z() << endl;
300 cout << " ******************** " << endl;
301 cout << " Array HAV2 - Normals " << endl;
303 for ( i=HAV2->Lower(); i <= HAV2->Upper(); i++ )
305 cout << HAV2->Value(i).X() << " " << HAV2->Value(i).Y()<< " " << HAV2->Value(i).Z() << endl;
308 cout << " ******************** " << endl;
309 cout << " Array HAI3 - normalIndex " << endl;
311 for ( i=HAI3->Lower(); i <= HAI3->Upper(); i++ )
313 cout << HAI3->Value(i) << endl;
318 cout << " ******************** " << endl;
319 cout << " Array HAI1 - coordIndex " << endl;
321 for ( i=HAI1->Lower(); i <= HAI1->Upper(); i++ )
323 cout << HAI1->Value(i) << endl;
326 cout << " ******************** " << endl;
328 //----------------------------
330 // creation of Vrml objects
333 SH = SA->ShapeHints();
339 SE1.Print(anOStream);
341 if (SA->HasMaterial()){
343 Handle(Vrml_Material) M;
344 M = SA->FrontMaterial();
350 Handle(Vrml_Coordinate3) C3 = new Vrml_Coordinate3(HAV1);
351 C3->Print(anOStream);
355 Vrml_MaterialBindingAndNormalBinding MBNB1 = Vrml_PER_VERTEX_INDEXED;
356 Vrml_NormalBinding NB(MBNB1);
360 SE2.Print(anOStream);
365 Vrml_IndexedFaceSet IFS;
366 IFS.SetCoordIndex(HAI1);
367 IFS.SetNormalIndex(HAI3);
368 IFS.Print(anOStream);
370 SE2.Print(anOStream);
372 SE1.Print(anOStream);
378 SE1.Print(anOStream);
380 if (SA->HasMaterial()){
382 Handle(Vrml_Material) M;
383 M = SA->FrontMaterial();
388 Handle(Vrml_Coordinate3) C3 = new Vrml_Coordinate3(HAV1);
389 C3->Print(anOStream);
393 Vrml_IndexedFaceSet IFS;
394 IFS.SetCoordIndex(HAI1);
395 IFS.Print(anOStream);
397 SE1.Print(anOStream);
403 //--------- Notes -------------
405 // the necessary of calculation of Normals and Textures must be define in Drawer
408 //---------- End on notes ------------
412 //----------------------------
413 // Computing the normal
414 //-----------------------------
416 void VrmlConverter_ShadedShape::ComputeNormal(const TopoDS_Face& aFace,
418 TColgp_Array1OfDir& Nor)
420 const Handle(Poly_Triangulation)& T = pc.Triangulation();
421 BRepAdaptor_Surface S;
422 Standard_Boolean hasUV = T->HasUVNodes();
425 Handle(Geom_Surface) GS = BRep_Tool::Surface(aFace, l);
427 if (hasUV && !GS.IsNull()) {
428 Standard_Boolean OK = Standard_True;
433 CSLib_DerivativeStatus Status;
434 CSLib_NormalStatus NStat;
436 const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes();
437 for (i = UVNodes.Lower(); i <= UVNodes.Upper(); i++) {
441 CSLib::Normal(D1U,D1V,Precision::Angular(),Status,Nor(i));
442 if (Status != CSLib_Done) {
443 S.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
444 CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor(i));
446 if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
450 const TColgp_Array1OfPnt& Nodes = T->Nodes();
451 Standard_Integer n[3];
452 const Poly_Array1OfTriangle& triangles = T->Triangles();
454 for (i = Nodes.Lower(); i <= Nodes.Upper(); i++) {
455 gp_XYZ eqPlan(0, 0, 0);
456 for (pc.Initialize(i); pc.More(); pc.Next()) {
457 triangles(pc.Value()).Get(n[0], n[1], n[2]);
458 gp_XYZ v1(Nodes(n[1]).Coord()-Nodes(n[0]).Coord());
459 gp_XYZ v2(Nodes(n[2]).Coord()-Nodes(n[1]).Coord());
460 eqPlan += (v1^v2).Normalized();
462 Nor(i) = gp_Dir(eqPlan);
463 if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();