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