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 | //========================================================================= |
59 | void 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 | |
125 | // cout << "nbTriangles = "<< nbTriangles << endl; |
126 | // cout << "nbVertices = "<< nbVertices << endl << endl; |
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 | /* |
245 | cout << " ******************** " << endl; |
246 | cout << " Array HAV1 - Coordinare3 " << endl; |
247 | |
248 | for ( i=HAV1->Lower(); i <= HAV1->Upper(); i++ ) |
249 | { |
250 | cout << HAV1->Value(i).X() << " " << HAV1->Value(i).Y()<< " " << HAV1->Value(i).Z() << endl; |
251 | } |
252 | |
253 | if(SA->HasNormals()) |
254 | { |
255 | |
256 | cout << " ******************** " << endl; |
257 | cout << " Array HAV2 - Normals " << endl; |
258 | |
259 | for ( i=HAV2->Lower(); i <= HAV2->Upper(); i++ ) |
260 | { |
261 | cout << HAV2->Value(i).X() << " " << HAV2->Value(i).Y()<< " " << HAV2->Value(i).Z() << endl; |
262 | } |
263 | |
264 | cout << " ******************** " << endl; |
265 | cout << " Array HAI3 - normalIndex " << endl; |
266 | |
267 | for ( i=HAI3->Lower(); i <= HAI3->Upper(); i++ ) |
268 | { |
269 | cout << HAI3->Value(i) << endl; |
270 | } |
271 | |
272 | } |
273 | |
274 | cout << " ******************** " << endl; |
275 | cout << " Array HAI1 - coordIndex " << endl; |
276 | |
277 | for ( i=HAI1->Lower(); i <= HAI1->Upper(); i++ ) |
278 | { |
279 | cout << HAI1->Value(i) << endl; |
280 | } |
281 | |
282 | cout << " ******************** " << endl; |
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 | |
372 | void 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 | |