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