b311480e |
1 | // Created on: 2003-11-12 |
2 | // Created by: Alexander SOLOVYOV |
973c2be1 |
3 | // Copyright (c) 2003-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
7fd59977 |
15 | |
16 | #define _POLYGONES_ |
7fd59977 |
17 | |
42cf5bc1 |
18 | // if define _POLYGONES_ ColorPrsBuilder use ArrayOfPolygons for drawing faces |
7fd59977 |
19 | |
42cf5bc1 |
20 | #include <Aspect_SequenceOfColor.hxx> |
21 | #include <gp_Pnt.hxx> |
7fd59977 |
22 | #include <Graphic3d_ArrayOfPolygons.hxx> |
23 | #include <Graphic3d_ArrayOfPolylines.hxx> |
42cf5bc1 |
24 | #include <Graphic3d_ArrayOfPrimitives.hxx> |
37ac4a67 |
25 | #include <Graphic3d_ArrayOfSegments.hxx> |
26 | #include <Graphic3d_ArrayOfTriangles.hxx> |
42cf5bc1 |
27 | #include <Graphic3d_AspectFillArea3d.hxx> |
28 | #include <Graphic3d_AspectLine3d.hxx> |
7fd59977 |
29 | #include <Graphic3d_Group.hxx> |
42cf5bc1 |
30 | #include <Graphic3d_Texture2D.hxx> |
bf75be98 |
31 | #include <Graphic3d_TextureParams.hxx> |
42cf5bc1 |
32 | #include <Graphic3d_TypeOfTextureMode.hxx> |
33 | #include <Image_PixMap.hxx> |
34 | #include <MeshVS_Buffer.hxx> |
7fd59977 |
35 | #include <MeshVS_DataSource.hxx> |
42cf5bc1 |
36 | #include <MeshVS_DisplayModeFlags.hxx> |
7fd59977 |
37 | #include <MeshVS_Drawer.hxx> |
42cf5bc1 |
38 | #include <MeshVS_DrawerAttribute.hxx> |
39 | #include <MeshVS_HArray1OfSequenceOfInteger.hxx> |
7fd59977 |
40 | #include <MeshVS_Mesh.hxx> |
41 | #include <MeshVS_MeshPrsBuilder.hxx> |
42cf5bc1 |
42 | #include <MeshVS_NodalColorPrsBuilder.hxx> |
37ac4a67 |
43 | #include <MeshVS_SymmetricPairHasher.hxx> |
42cf5bc1 |
44 | #include <MeshVS_Tool.hxx> |
37ac4a67 |
45 | #include <NCollection_Map.hxx> |
46 | #include <NCollection_Vector.hxx> |
42cf5bc1 |
47 | #include <Prs3d_Drawer.hxx> |
48 | #include <Prs3d_LineAspect.hxx> |
49 | #include <Prs3d_Presentation.hxx> |
42cf5bc1 |
50 | #include <Prs3d_ShadingAspect.hxx> |
51 | #include <PrsMgr_PresentationManager3d.hxx> |
52 | #include <Quantity_Array1OfColor.hxx> |
53 | #include <Quantity_Color.hxx> |
54 | #include <Standard_Type.hxx> |
55 | #include <TColStd_Array1OfInteger.hxx> |
56 | #include <TColStd_Array1OfReal.hxx> |
57 | #include <TColStd_HArray1OfReal.hxx> |
58 | #include <TColStd_HPackedMapOfInteger.hxx> |
59 | #include <TColStd_ListIteratorOfListOfInteger.hxx> |
60 | #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx> |
61 | #include <TColStd_SequenceOfInteger.hxx> |
37ac4a67 |
62 | |
92efcf78 |
63 | IMPLEMENT_STANDARD_RTTIEXT(MeshVS_NodalColorPrsBuilder,MeshVS_PrsBuilder) |
64 | |
7fd59977 |
65 | /* |
66 | Class : MeshVS_ImageTexture2D |
67 | Description : Texture for nodal presentation |
68 | */ |
69 | class MeshVS_ImageTexture2D : public Graphic3d_Texture2D |
70 | { |
71 | public: |
bf75be98 |
72 | |
f376ac72 |
73 | MeshVS_ImageTexture2D (const Handle(Image_PixMap)& theImg) : Graphic3d_Texture2D (theImg, Graphic3d_TOT_2D) |
bf75be98 |
74 | { |
75 | myParams->SetModulate (Standard_True); |
76 | myParams->SetFilter (Graphic3d_TOTF_BILINEAR); |
77 | } |
78 | |
7fd59977 |
79 | public: |
bf75be98 |
80 | |
92efcf78 |
81 | DEFINE_STANDARD_RTTI_INLINE(MeshVS_ImageTexture2D,Graphic3d_Texture2D) |
7fd59977 |
82 | }; |
83 | |
3c3131a0 |
84 | DEFINE_STANDARD_HANDLE (MeshVS_ImageTexture2D, Graphic3d_Texture2D) |
ec357c5c |
85 | |
7fd59977 |
86 | |
7fd59977 |
87 | //================================================================ |
88 | // Function : getNearestPow2 |
3c3131a0 |
89 | // Purpose : Returns the nearest power of two greater than the |
7fd59977 |
90 | // argument value |
91 | //================================================================ |
92 | static inline Standard_Integer getNearestPow2( Standard_Integer theValue ) |
93 | { |
94 | // Precaution against overflow |
95 | Standard_Integer aHalfMax = IntegerLast() >> 1, aRes = 1; |
96 | if ( theValue > aHalfMax ) theValue = aHalfMax; |
97 | while ( aRes < theValue ) aRes <<= 1; |
98 | return aRes; |
99 | } |
100 | |
101 | /* |
102 | Class : MeshVS_NodalColorPrsBuilder |
3c3131a0 |
103 | Description : This class provides methods to create presentation of |
7fd59977 |
104 | nodes with assigned color (See hxx for more description ) |
105 | */ |
106 | |
107 | //================================================================ |
108 | // Function : Constructor MeshVS_NodalColorPrsBuilder |
109 | // Purpose : |
110 | //================================================================ |
111 | MeshVS_NodalColorPrsBuilder::MeshVS_NodalColorPrsBuilder ( const Handle(MeshVS_Mesh)& Parent, |
112 | const MeshVS_DisplayModeFlags& Flags, |
113 | const Handle (MeshVS_DataSource)& DS, |
114 | const Standard_Integer Id, |
115 | const MeshVS_BuilderPriority& Priority ) |
116 | : MeshVS_PrsBuilder ( Parent, Flags, DS, Id, Priority ), |
3c3131a0 |
117 | myUseTexture( Standard_False ), |
7fd59977 |
118 | myInvalidColor( Quantity_NOC_GRAY ) |
119 | { |
120 | SetExcluding ( Standard_True ); |
121 | } |
122 | |
123 | //================================================================ |
124 | // Function : Build |
125 | // Purpose : |
126 | //================================================================ |
127 | void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs, |
128 | const TColStd_PackedMapOfInteger& IDs, |
129 | TColStd_PackedMapOfInteger& IDsToExclude, |
130 | const Standard_Boolean IsElement, |
131 | const Standard_Integer DisplayMode) const |
132 | { |
133 | Handle (MeshVS_DataSource) aSource = GetDataSource(); |
134 | Handle (MeshVS_Drawer) aDrawer = GetDrawer(); |
135 | if ( aSource.IsNull() || aDrawer.IsNull() ) |
136 | return; |
137 | |
138 | Standard_Integer aMaxFaceNodes; |
139 | if ( !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, aMaxFaceNodes ) || aMaxFaceNodes <= 0 ) |
140 | return; |
141 | |
142 | MeshVS_Buffer aCoordsBuf (3*aMaxFaceNodes*sizeof(Standard_Real)); |
143 | TColStd_Array1OfReal aCoords ( aCoordsBuf, 1, 3 * aMaxFaceNodes ); |
144 | Standard_Integer NbNodes; |
145 | MeshVS_EntityType aType; |
146 | |
147 | if ( !( DisplayMode & GetFlags() ) || !IsElement ) |
148 | return; |
149 | |
0ebaa4db |
150 | if ( (myUseTexture && ( !myTextureCoords.Extent() || !myTextureColorMap.Length() )) || |
151 | (!myUseTexture && !myNodeColorMap.Extent()) ) |
7fd59977 |
152 | return; |
153 | |
37ac4a67 |
154 | // subtract the hidden elements and ids to exclude (to minimize allocated memory) |
7fd59977 |
155 | TColStd_PackedMapOfInteger anIDs; |
156 | anIDs.Assign( IDs ); |
157 | Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems(); |
158 | if ( !aHiddenElems.IsNull() ) |
159 | anIDs.Subtract( aHiddenElems->Map() ); |
160 | anIDs.Subtract( IDsToExclude ); |
161 | |
162 | Standard_Boolean IsReflect = Standard_False, IsMeshSmoothShading = Standard_False; |
163 | aDrawer->GetBoolean( MeshVS_DA_ColorReflection, IsReflect ); |
164 | aDrawer->GetBoolean( MeshVS_DA_SmoothShading, IsMeshSmoothShading ); |
3c3131a0 |
165 | |
7fd59977 |
166 | // Following parameter are used for texture presentation only |
167 | int nbColors = 0; // Number of colors from color map |
168 | int nbTextureColors = 0; // Number of colors in texture (it will be pow of 2) |
169 | if ( myUseTexture ) |
170 | { |
171 | nbColors = myTextureColorMap.Length(); |
172 | nbTextureColors = getNearestPow2( nbColors ); |
173 | } |
3c3131a0 |
174 | |
7fd59977 |
175 | Standard_Integer aSize = anIDs.Extent(); |
176 | |
177 | // Calculate maximum possible number of vertices and bounds |
178 | Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo; |
179 | Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0; |
180 | TColStd_MapIteratorOfPackedMapOfInteger it (anIDs); |
181 | for( ; it.More(); it.Next() ) |
182 | { |
183 | Standard_Integer aKey = it.Key(); |
184 | if ( aSource->Get3DGeom( aKey, NbNodes, aTopo ) ) |
185 | MeshVS_MeshPrsBuilder::HowManyPrimitives |
186 | ( aTopo, Standard_True, Standard_False, NbNodes, |
187 | PolygonVerticesFor3D, PolygonBoundsFor3D ); |
188 | } |
189 | |
190 | // Draw faces with nodal color |
61168418 |
191 | // OCC20644 Use "plastic" material as it is "non-physic" and so it is easier to get the required colors |
192 | Graphic3d_MaterialAspect aMaterial[2] = { Graphic3d_NOM_PLASTIC, Graphic3d_NOM_PLASTIC }; |
193 | for (Standard_Integer i = 0; i < 2; ++i) |
7fd59977 |
194 | { |
61168418 |
195 | aMaterial[i].SetSpecularColor (Quantity_NOC_BLACK); |
196 | aMaterial[i].SetEmissiveColor (Quantity_NOC_BLACK); |
7fd59977 |
197 | if ( !IsReflect ) |
198 | { |
61168418 |
199 | aMaterial[i].SetAmbientColor (Quantity_NOC_BLACK); |
200 | aMaterial[i].SetDiffuseColor (Quantity_NOC_BLACK); |
7fd59977 |
201 | } |
202 | else{ |
203 | // OCC20644 Using the material with reflection properties same as in |
204 | // ElementalColorPrsBuilder, to get the same colors. |
205 | // Additionally, ambient and diffuse coefficients are used below to scale incoming colors, |
206 | // to simulate TelUpdateMaterial() function from OpenGl_attri.c. |
207 | // This is mandatory, as these "scaled" colors are then passed directly to OpenGL |
208 | // as ambient and diffuse colors of the current material using glColorMaterial(). |
209 | // In ElementalColorPrsBuilder we do not need to do scale the colors, as this |
210 | // is done by TelUpdateMaterial(). |
211 | // 0.5 is used to have the colors in 3D maximally similar to those in the color scale. |
212 | // This is possible when the sum of all coefficient is equal to 1. |
61168418 |
213 | aMaterial[i].SetAmbientColor (Quantity_Color (Graphic3d_Vec3 (0.5f))); |
214 | aMaterial[i].SetDiffuseColor (Quantity_Color (Graphic3d_Vec3 (0.5f))); |
7fd59977 |
215 | } |
61168418 |
216 | } |
7fd59977 |
217 | |
218 | // Create array of polygons for interior presentation of faces and volumes |
219 | Handle(Graphic3d_ArrayOfPolygons) aCPolyArr = new Graphic3d_ArrayOfPolygons |
3c3131a0 |
220 | ( aMaxFaceNodes * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D, |
7fd59977 |
221 | 0, myUseTexture || IsReflect, !myUseTexture, Standard_False, myUseTexture ); |
222 | |
37ac4a67 |
223 | Standard_Integer aNbFacePrimitives = 0; |
224 | Standard_Integer aNbVolmPrimitives = 0; |
225 | Standard_Integer aNbEdgePrimitives = 0; |
226 | Standard_Integer aNbLinkPrimitives = 0; |
227 | |
228 | for (it.Reset(); it.More(); it.Next()) |
229 | { |
230 | Standard_Integer aNbNodes = 0; |
231 | |
232 | if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType)) |
233 | continue; |
234 | |
235 | if (aType == MeshVS_ET_Volume) |
236 | { |
237 | if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo)) |
238 | { |
239 | for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx) |
240 | { |
241 | const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx); |
242 | |
243 | aNbEdgePrimitives += aFaceNodes.Length(); // add edge segments |
244 | aNbVolmPrimitives += aFaceNodes.Length() - 2; // add volumetric cell triangles |
245 | } |
246 | } |
247 | } |
248 | else if (aType == MeshVS_ET_Link) |
249 | { |
250 | aNbLinkPrimitives += aNbNodes - 1; // add link segments |
251 | } |
252 | else if (aType == MeshVS_ET_Face) |
253 | { |
254 | aNbEdgePrimitives += aNbNodes; // add edge segments |
255 | aNbFacePrimitives += aNbNodes - 2; // add face triangles |
256 | } |
257 | } |
258 | |
259 | // Here we do not use indices arrays because they are not effective for some mesh |
260 | // drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D |
261 | // cell rendering (normal interpolation is not always applicable - flat shading), |
262 | // elemental coloring (color interpolation is impossible) |
263 | |
264 | // Create array of polygons for interior presentation of faces and volumes |
265 | Handle(Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles |
266 | ( (aNbFacePrimitives + aNbVolmPrimitives) * 3, 0, myUseTexture || IsReflect, !myUseTexture, myUseTexture ); |
267 | |
3c3131a0 |
268 | // Create array of polylines for presentation of edges |
37ac4a67 |
269 | Handle(Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments |
270 | (aNbEdgePrimitives * 2); |
7fd59977 |
271 | |
272 | gp_Pnt P, Start; |
273 | Standard_Real aMin = gp::Resolution() * gp::Resolution(); |
274 | gp_Dir aDefNorm( 0., 0., 1. ); |
275 | |
276 | // Prepare for scaling the incoming colors |
61168418 |
277 | const Standard_Real anColorRatio = !IsReflect ? 0.44f : 0.5f; |
7fd59977 |
278 | |
37ac4a67 |
279 | for (it.Reset(); it.More(); it.Next()) |
7fd59977 |
280 | { |
281 | Standard_Integer aKey = it.Key(); |
37ac4a67 |
282 | |
283 | if (aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType)) |
7fd59977 |
284 | { |
37ac4a67 |
285 | TColStd_Array1OfInteger aNodes (1, NbNodes); |
286 | |
287 | if (!aSource->GetNodesByElement (aKey, aNodes, NbNodes)) |
7fd59977 |
288 | continue; |
289 | |
290 | Quantity_Color aNColor; |
291 | |
292 | Standard_Boolean isValid = Standard_True; |
37ac4a67 |
293 | |
294 | if (myUseTexture) |
7fd59977 |
295 | { |
51740958 |
296 | for (Standard_Integer k = 1; k <= NbNodes && isValid; ++k) |
297 | isValid = myTextureCoords.IsBound (aNodes (k)); |
7fd59977 |
298 | } |
299 | else |
300 | { |
51740958 |
301 | for (Standard_Integer k = 1; k <= NbNodes && isValid; ++k) |
302 | isValid = GetColor (aNodes (k), aNColor); |
7fd59977 |
303 | } |
304 | |
37ac4a67 |
305 | if (!isValid) |
7fd59977 |
306 | continue; |
307 | |
308 | // Preparing normal(s) to show reflections if requested |
309 | Handle(TColStd_HArray1OfReal) aNormals; |
37ac4a67 |
310 | |
3c3131a0 |
311 | Standard_Boolean hasNormals = |
37ac4a67 |
312 | (IsReflect && aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals)); |
7fd59977 |
313 | |
37ac4a67 |
314 | if (aType == MeshVS_ET_Face) |
7fd59977 |
315 | { |
37ac4a67 |
316 | for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx) // triangulate polygon |
7fd59977 |
317 | { |
37ac4a67 |
318 | for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle |
7fd59977 |
319 | { |
37ac4a67 |
320 | gp_XYZ aPnt (aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1), |
321 | aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2), |
322 | aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3)); |
7fd59977 |
323 | |
37ac4a67 |
324 | gp_Vec aNorm = aDefNorm; |
7fd59977 |
325 | |
37ac4a67 |
326 | if (hasNormals) |
3ba3388b |
327 | { |
37ac4a67 |
328 | gp_Vec aTestNorm (aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1), |
329 | aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2), |
330 | aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3)); |
3c3131a0 |
331 | |
37ac4a67 |
332 | if (aTestNorm.SquareMagnitude() > aMin) |
7fd59977 |
333 | { |
37ac4a67 |
334 | aNorm = gp_Dir (aTestNorm); |
7fd59977 |
335 | } |
7fd59977 |
336 | } |
7fd59977 |
337 | |
37ac4a67 |
338 | if (myUseTexture) |
7fd59977 |
339 | { |
37ac4a67 |
340 | const Standard_Real aTexCoord = myTextureCoords (aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1))); |
341 | |
342 | // Transform texture coordinate in accordance with number of colors specified |
343 | // by upper level and real size of OpenGL texture. The OpenGL texture has border |
344 | // colors interpolated with the colors from the color map, thats why we need to |
345 | // shrink texture coordinates around the middle point to exclude areas where the |
346 | // map colors are interpolated with the borders color |
347 | aFaceTriangles->AddVertex (aPnt, aNorm, gp_Pnt2d ( |
348 | (aTexCoord * (nbColors - 1.0) + 0.5) / nbTextureColors, aTexCoord < 0 || aTexCoord > 1 ? 0.25 : 0.75)); |
7fd59977 |
349 | } |
350 | else |
351 | { |
37ac4a67 |
352 | GetColor (aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)), aNColor); |
353 | |
354 | if (IsReflect) |
3c3131a0 |
355 | { |
37ac4a67 |
356 | aNColor.SetValues (anColorRatio * aNColor.Red(), |
357 | anColorRatio * aNColor.Green(), |
358 | anColorRatio * aNColor.Blue(), |
359 | Quantity_TOC_RGB); |
360 | |
361 | aFaceTriangles->AddVertex (aPnt, aNorm, aNColor); |
7fd59977 |
362 | } |
363 | else |
37ac4a67 |
364 | { |
365 | aFaceTriangles->AddVertex (aPnt, aNColor); |
366 | } |
7fd59977 |
367 | } |
7fd59977 |
368 | } |
37ac4a67 |
369 | } |
370 | |
371 | for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx) // border segmentation |
372 | { |
373 | const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes; |
374 | |
375 | anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1), |
376 | aCoords (3 * aNodeIdx + 2), |
377 | aCoords (3 * aNodeIdx + 3)); |
378 | |
379 | anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1), |
380 | aCoords (3 * aNextIdx + 2), |
381 | aCoords (3 * aNextIdx + 3)); |
7fd59977 |
382 | } |
383 | |
384 | // if IsExcludingOn then presentation must not be built by other builders |
37ac4a67 |
385 | if (IsExcludingOn()) |
386 | { |
387 | IDsToExclude.Add (aKey); |
388 | } |
389 | } |
390 | else if (aType == MeshVS_ET_Volume) |
391 | { |
392 | if (!aSource->Get3DGeom (aKey, NbNodes, aTopo)) |
393 | continue; |
394 | |
395 | AddVolumePrs (aTopo, aNodes, aCoords, aFaceTriangles, |
396 | IsReflect, nbColors, nbTextureColors, anColorRatio); |
397 | |
398 | AddVolumePrs (aTopo, aNodes, aCoords, anEdgeSegments, |
399 | IsReflect, nbColors, nbTextureColors, anColorRatio); |
400 | |
401 | // if IsExcludingOn then presentation must not be built by other builders |
402 | if (IsExcludingOn()) |
403 | IDsToExclude.Add (aKey); |
3c3131a0 |
404 | } |
405 | } |
7fd59977 |
406 | } // for ( ... |
407 | |
408 | Handle(Graphic3d_AspectFillArea3d) anAsp; |
409 | |
410 | // Aspect_InteriorStyle aStyle; |
411 | // Standard_Integer aStyleInt; |
412 | Aspect_TypeOfLine anEdgeType = Aspect_TOL_SOLID; |
b1492cb3 |
413 | Standard_Real anEdgeWidth = 1.0; |
7fd59977 |
414 | Quantity_Color anInteriorColor; |
415 | Quantity_Color anEdgeColor, aLineColor; |
416 | Standard_Boolean aShowEdges = Standard_True; |
417 | |
418 | aDrawer->GetColor ( MeshVS_DA_InteriorColor, anInteriorColor ); |
419 | aDrawer->GetColor ( MeshVS_DA_EdgeColor, anEdgeColor ); |
420 | aDrawer->GetColor ( MeshVS_DA_BeamColor, aLineColor ); |
421 | aDrawer->GetDouble ( MeshVS_DA_EdgeWidth, anEdgeWidth ); |
422 | aDrawer->GetBoolean( MeshVS_DA_ShowEdges, aShowEdges ); |
423 | |
b1492cb3 |
424 | Standard_Integer anEdgeInt = Aspect_TOL_SOLID; |
7fd59977 |
425 | if ( aDrawer->GetInteger ( MeshVS_DA_EdgeType, anEdgeInt ) ) |
426 | anEdgeType = (Aspect_TypeOfLine) anEdgeInt; |
427 | |
428 | if ( myUseTexture ) |
429 | { |
6262338c |
430 | Handle(Prs3d_Drawer) aPrsDrawer = myParentMesh->Attributes(); |
431 | if ( aPrsDrawer.IsNull() ) |
7fd59977 |
432 | return; |
3c3131a0 |
433 | |
6262338c |
434 | aPrsDrawer->SetShadingAspect( new Prs3d_ShadingAspect() ); |
435 | anAsp = aPrsDrawer->ShadingAspect()->Aspect(); |
7fd59977 |
436 | if ( anAsp.IsNull() ) |
437 | return; |
438 | |
439 | anAsp->SetFrontMaterial( aMaterial[ 0 ] ); |
440 | anAsp->SetBackMaterial( aMaterial[ 1 ] ); |
3c3131a0 |
441 | |
7fd59977 |
442 | |
443 | Handle(Graphic3d_Texture2D) aTexture = CreateTexture(); |
444 | if ( aTexture.IsNull() ) |
445 | return; |
446 | |
3c3131a0 |
447 | anAsp->SetTextureMapOn(); |
7fd59977 |
448 | anAsp->SetTextureMap( aTexture ); |
3ba3388b |
449 | anAsp->SetInteriorColor( Quantity_NOC_WHITE ); |
7fd59977 |
450 | } |
451 | else |
452 | { |
453 | // if ( aDrawer->GetInteger ( MeshVS_DA_InteriorStyle, aStyleInt ) ) |
454 | // aStyle = (Aspect_InteriorStyle)aStyleInt; |
455 | |
3c3131a0 |
456 | anAsp = new Graphic3d_AspectFillArea3d ( |
7fd59977 |
457 | Aspect_IS_SOLID, Quantity_NOC_GRAY, anEdgeColor, |
458 | anEdgeType, anEdgeWidth, aMaterial[ 0 ], aMaterial[ 1 ] ); |
459 | } |
460 | |
461 | anAsp->SetDistinguishOff(); |
462 | anAsp->SetEdgeOff(); |
7fd59977 |
463 | |
3c3131a0 |
464 | Handle(Graphic3d_AspectLine3d) anLAsp = |
7fd59977 |
465 | new Graphic3d_AspectLine3d( anEdgeColor, anEdgeType, anEdgeWidth ); |
3c3131a0 |
466 | |
d6c48921 |
467 | Handle(Graphic3d_Group) aGroup1 = Prs->NewGroup(); |
cde2e2f0 |
468 | |
469 | Standard_Boolean toSupressBackFaces = Standard_False; |
470 | aDrawer->GetBoolean (MeshVS_DA_SupressBackFaces, toSupressBackFaces); |
471 | aGroup1->SetClosed (toSupressBackFaces == Standard_True); |
3c3131a0 |
472 | |
7fd59977 |
473 | aGroup1->SetPrimitivesAspect( anAsp ); |
37ac4a67 |
474 | aGroup1->AddPrimitiveArray( aFaceTriangles /*aCPolyArr*/ ); |
475 | //aGroup1->AddPrimitiveArray( aCPolyArr ); |
7fd59977 |
476 | |
477 | if (aShowEdges) |
478 | { |
d6c48921 |
479 | Handle(Graphic3d_Group) aGroup2 = Prs->NewGroup(); |
7fd59977 |
480 | |
b6472664 |
481 | Handle(Graphic3d_AspectFillArea3d) anAspCopy = new Graphic3d_AspectFillArea3d (*anAsp); |
482 | anAspCopy->SetTextureMapOff(); |
483 | aGroup2->SetPrimitivesAspect( anAspCopy ); |
7fd59977 |
484 | aGroup2->SetPrimitivesAspect( anLAsp ); |
37ac4a67 |
485 | aGroup2->AddPrimitiveArray( anEdgeSegments ); |
7fd59977 |
486 | } |
487 | } |
488 | |
37ac4a67 |
489 | //================================================================ |
490 | // Function : AddVolumePrs |
491 | // Purpose : |
492 | //================================================================ |
493 | void MeshVS_NodalColorPrsBuilder::AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& theTopo, |
494 | const TColStd_Array1OfInteger& theNodes, |
495 | const TColStd_Array1OfReal& theCoords, |
496 | const Handle(Graphic3d_ArrayOfPrimitives)& theArray, |
497 | const Standard_Boolean theIsShaded, |
498 | const Standard_Integer theNbColors, |
499 | const Standard_Integer theNbTexColors, |
500 | const Standard_Real theColorRatio) const |
501 | { |
502 | Standard_Integer aLow = theCoords.Lower(); |
503 | |
504 | if (theTopo.IsNull() || theArray.IsNull()) |
505 | return; |
506 | |
507 | Standard_Boolean aIsPolygons = theArray->IsKind (STANDARD_TYPE (Graphic3d_ArrayOfTriangles)); |
508 | |
509 | if (aIsPolygons) |
510 | { |
511 | for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx) |
512 | { |
513 | const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx); |
514 | |
515 | TColStd_Array1OfReal aPolyNodes (0, 3 * aFaceNodes.Length()); |
516 | |
517 | for (Standard_Integer aNodeIdx = 0; aNodeIdx < aFaceNodes.Length(); ++aNodeIdx) |
518 | { |
519 | Standard_Integer anIdx = aFaceNodes.Value (aNodeIdx + 1); |
520 | |
521 | Standard_Real aX = theCoords.Value (aLow + 3 * anIdx + 0); |
522 | Standard_Real aY = theCoords.Value (aLow + 3 * anIdx + 1); |
523 | Standard_Real aZ = theCoords.Value (aLow + 3 * anIdx + 2); |
524 | |
525 | aPolyNodes.SetValue (3 * aNodeIdx + 1, aX); |
526 | aPolyNodes.SetValue (3 * aNodeIdx + 2, aY); |
527 | aPolyNodes.SetValue (3 * aNodeIdx + 3, aZ); |
528 | } |
529 | |
530 | gp_Vec aNorm (0.0, 0.0, 1.0); |
531 | |
532 | if (theIsShaded) |
533 | { |
534 | aPolyNodes.SetValue (0, aFaceNodes.Length()); |
535 | |
536 | if (!MeshVS_Tool::GetAverageNormal (aPolyNodes, aNorm)) |
537 | { |
538 | aNorm.SetCoord (0.0, 0.0, 1.0); |
539 | } |
540 | } |
541 | |
542 | for (Standard_Integer aNodeIdx = 0; aNodeIdx < aFaceNodes.Length() - 2; ++aNodeIdx) // triangulate polygon |
543 | { |
544 | for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle |
545 | { |
546 | gp_Pnt aPnt (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1), |
547 | aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2), |
548 | aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3)); |
549 | |
550 | if (myUseTexture) |
551 | { |
552 | const Standard_Real aTexCoord = myTextureCoords (theNodes (aFaceNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)) + 1)); |
553 | |
554 | theArray->AddVertex (aPnt, aNorm, gp_Pnt2d ( |
555 | (aTexCoord * (theNbColors - 1.0) + 0.5) / theNbTexColors, aTexCoord < 0 || aTexCoord > 1 ? 0.25 : 0.75)); |
556 | } |
557 | else |
558 | { |
559 | Quantity_Color aNColor; |
560 | GetColor (theNodes ((aFaceNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)) + 1)), aNColor); |
561 | |
562 | if (theIsShaded) |
563 | { |
564 | aNColor.SetValues (theColorRatio * aNColor.Red(), |
565 | theColorRatio * aNColor.Green(), |
566 | theColorRatio * aNColor.Blue(), |
567 | Quantity_TOC_RGB); |
568 | |
569 | theArray->AddVertex (aPnt, aNorm, aNColor); |
570 | } |
571 | else |
572 | { |
573 | theArray->AddVertex (aPnt, aNColor); |
574 | } |
575 | } |
576 | } |
577 | } |
578 | } |
579 | } |
580 | else |
581 | { |
582 | // Find all pairs of nodes (edges) to draw (will be drawn only once) |
583 | NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aEdgeMap; |
584 | |
585 | for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx) |
586 | { |
587 | const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx); |
588 | |
589 | for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx) |
590 | { |
591 | const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes; |
592 | |
593 | aEdgeMap.Add (MeshVS_NodePair (aFaceNodes.Value (aNodeIdx + 1), |
594 | aFaceNodes.Value (aNextIdx + 1))); |
595 | } |
596 | } |
597 | |
598 | // Draw edges |
599 | for(NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher>::Iterator anIt (aEdgeMap); anIt.More(); anIt.Next()) |
600 | { |
601 | const Standard_Integer anIdx1 = aLow + 3 * anIt.Key().first; |
602 | const Standard_Integer anIdx2 = aLow + 3 * anIt.Key().second; |
603 | |
604 | Standard_Real aX[] = { theCoords.Value (anIdx1 + 0), theCoords.Value (anIdx2 + 0) }; |
605 | Standard_Real aY[] = { theCoords.Value (anIdx1 + 1), theCoords.Value (anIdx2 + 1) }; |
606 | Standard_Real aZ[] = { theCoords.Value (anIdx1 + 2), theCoords.Value (anIdx2 + 2) }; |
607 | |
608 | theArray->AddVertex (aX[0], aY[0], aZ[0]); |
609 | theArray->AddVertex (aX[1], aY[1], aZ[1]); |
610 | } |
611 | } |
612 | } |
613 | |
7fd59977 |
614 | //================================================================ |
615 | // Function : SetColors |
616 | // Purpose : |
617 | //================================================================ |
3c3131a0 |
618 | void MeshVS_NodalColorPrsBuilder::SetColors ( |
7fd59977 |
619 | const MeshVS_DataMapOfIntegerColor& theColorMap ) |
620 | { |
621 | myNodeColorMap = theColorMap; |
622 | } |
623 | |
624 | //================================================================ |
625 | // Function : GetColors |
626 | // Purpose : |
627 | //================================================================ |
628 | const MeshVS_DataMapOfIntegerColor& MeshVS_NodalColorPrsBuilder::GetColors() const |
629 | { |
630 | return myNodeColorMap; |
631 | } |
632 | |
633 | //================================================================ |
634 | // Function : HasColors |
635 | // Purpose : |
636 | //================================================================ |
637 | Standard_Boolean MeshVS_NodalColorPrsBuilder::HasColors () const |
638 | { |
639 | return ( myNodeColorMap.Extent() >0 ); |
640 | } |
641 | |
642 | //================================================================ |
643 | // Function : GetColor |
644 | // Purpose : |
645 | //================================================================ |
646 | Standard_Boolean MeshVS_NodalColorPrsBuilder::GetColor ( const Standard_Integer ID, |
647 | Quantity_Color& theColor ) const |
648 | { |
649 | Standard_Boolean aRes = myNodeColorMap.IsBound ( ID ); |
650 | if ( aRes ) |
651 | theColor = myNodeColorMap.Find ( ID ); |
652 | return aRes; |
653 | } |
654 | |
655 | //================================================================ |
656 | // Function : SetColor |
657 | // Purpose : |
658 | //================================================================ |
659 | void MeshVS_NodalColorPrsBuilder::SetColor ( const Standard_Integer theID, |
660 | const Quantity_Color& theCol ) |
661 | { |
662 | Standard_Boolean aRes = myNodeColorMap.IsBound ( theID ); |
663 | if ( aRes ) |
664 | myNodeColorMap.ChangeFind ( theID ) = theCol; |
665 | else |
666 | myNodeColorMap.Bind ( theID, theCol ); |
667 | } |
668 | |
669 | //================================================================ |
670 | // Function : UseTexture |
671 | // Purpose : Specify whether texture must be used to build presentation |
672 | //================================================================ |
673 | void MeshVS_NodalColorPrsBuilder::UseTexture( const Standard_Boolean theToUse ) |
674 | { |
675 | myUseTexture = theToUse; |
676 | if ( myUseTexture ) |
677 | myNodeColorMap.Clear(); |
678 | else |
679 | myTextureColorMap.Clear(); |
680 | } |
681 | |
682 | //================================================================ |
683 | // Function : IsUseTexture |
684 | // Purpose : Verify whether texture is used to build presentation |
685 | //================================================================ |
686 | Standard_Boolean MeshVS_NodalColorPrsBuilder::IsUseTexture() const |
687 | { |
688 | return myUseTexture; |
689 | } |
690 | |
691 | //================================================================ |
692 | // Function : SetColorMap |
3c3131a0 |
693 | // Purpose : Set colors to be used for texrture presentation. |
7fd59977 |
694 | // Generate texture in accordance with given parameters |
695 | //================================================================ |
696 | void MeshVS_NodalColorPrsBuilder::SetColorMap( const Aspect_SequenceOfColor& theColors ) |
697 | { |
698 | myTextureColorMap = theColors; |
699 | } |
700 | |
701 | //================================================================ |
702 | // Function : GetColorMap |
3c3131a0 |
703 | // Purpose : Return colors used for texrture presentation |
7fd59977 |
704 | //================================================================ |
705 | const Aspect_SequenceOfColor& MeshVS_NodalColorPrsBuilder::GetColorMap() const |
706 | { |
707 | return myTextureColorMap; |
708 | } |
709 | |
710 | //================================================================ |
711 | // Function : SetInvalidColor |
3c3131a0 |
712 | // Purpose : Set color representing invalid texture coordinate |
7fd59977 |
713 | // (laying outside range [0, 1]) |
714 | //================================================================ |
3c3131a0 |
715 | void MeshVS_NodalColorPrsBuilder::SetInvalidColor( |
7fd59977 |
716 | const Quantity_Color& theInvalidColor ) |
717 | { |
718 | myInvalidColor = theInvalidColor; |
719 | } |
720 | |
721 | //================================================================ |
722 | // Function : GetInvalidColor |
723 | // Purpose : Return color representing invalid texture coordinate |
724 | // (laying outside range [0, 1]) |
725 | //================================================================ |
726 | Quantity_Color MeshVS_NodalColorPrsBuilder::GetInvalidColor() const |
727 | { |
728 | return myInvalidColor; |
729 | } |
730 | |
731 | //================================================================ |
732 | // Function : SetTextureCoords |
3c3131a0 |
733 | // Purpose : Specify correspondence between node IDs and texture |
7fd59977 |
734 | // coordinates (range [0, 1]) |
735 | //================================================================ |
3c3131a0 |
736 | void MeshVS_NodalColorPrsBuilder::SetTextureCoords ( |
7fd59977 |
737 | const TColStd_DataMapOfIntegerReal& theMap ) |
738 | { |
739 | myTextureCoords = theMap; |
740 | } |
741 | |
742 | //================================================================ |
743 | // Function : GetTextureCoords |
3c3131a0 |
744 | // Purpose : Get correspondence between node IDs and texture |
745 | // coordinates (range [0, 1]) |
7fd59977 |
746 | //================================================================ |
747 | const TColStd_DataMapOfIntegerReal& MeshVS_NodalColorPrsBuilder::GetTextureCoords() const |
748 | { |
749 | return myTextureCoords; |
750 | } |
751 | |
752 | //================================================================ |
753 | // Function : SetTextureCoord |
3c3131a0 |
754 | // Purpose : Specify correspondence between node ID and texture |
755 | // coordinate (range [0, 1]) |
7fd59977 |
756 | //================================================================ |
757 | void MeshVS_NodalColorPrsBuilder::SetTextureCoord( const Standard_Integer theID, |
758 | const Standard_Real theCoord ) |
759 | { |
760 | myTextureCoords.Bind( theID, theCoord ); |
761 | } |
762 | |
763 | //================================================================ |
764 | // Function : GetTextureCoord |
3c3131a0 |
765 | // Purpose : Return correspondence between node IDs and texture |
766 | // coordinate (range [0, 1]) |
7fd59977 |
767 | //================================================================ |
768 | Standard_Real MeshVS_NodalColorPrsBuilder::GetTextureCoord( const Standard_Integer theID ) |
769 | { |
770 | return myTextureCoords.IsBound( theID ) ? myTextureCoords( theID ) : -1; |
771 | } |
772 | |
773 | //================================================================ |
774 | // Function : CreateTexture |
775 | // Purpose : Create texture in accordance with myTextureColorMap |
776 | //================================================================ |
777 | Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const |
778 | { |
3c3131a0 |
779 | const Standard_Integer aColorsNb = myTextureColorMap.Length(); |
780 | if (aColorsNb == 0) |
781 | { |
782 | return NULL; |
783 | } |
7fd59977 |
784 | |
3c3131a0 |
785 | // create and fill image with colors |
bf75be98 |
786 | Handle(Image_PixMap) anImage = new Image_PixMap(); |
dc858f4c |
787 | if (!anImage->InitTrash (Image_Format_RGBA, Standard_Size(getNearestPow2 (aColorsNb)), 2)) |
3c3131a0 |
788 | { |
789 | return NULL; |
790 | } |
7fd59977 |
791 | |
bf75be98 |
792 | anImage->SetTopDown (false); |
3c3131a0 |
793 | for (Standard_Size aCol = 0; aCol < Standard_Size(aColorsNb); ++aCol) |
794 | { |
795 | const Quantity_Color& aSrcColor = myTextureColorMap.Value (Standard_Integer(aCol) + 1); |
ca0c0b11 |
796 | Image_ColorRGBA& aColor = anImage->ChangeValue<Image_ColorRGBA> (0, aCol); |
8263fcd3 |
797 | aColor.r() = Standard_Byte(255.0 * aSrcColor.Red()); |
798 | aColor.g() = Standard_Byte(255.0 * aSrcColor.Green()); |
799 | aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue()); |
3c3131a0 |
800 | aColor.a() = 0xFF; |
801 | } |
7fd59977 |
802 | |
3c3131a0 |
803 | // fill padding bytes |
804 | const Quantity_Color& aLastColorSrc = myTextureColorMap.Last(); |
805 | const Image_ColorRGBA aLastColor = |
806 | {{ |
8263fcd3 |
807 | Standard_Byte(255.0 * aLastColorSrc.Red()), |
808 | Standard_Byte(255.0 * aLastColorSrc.Green()), |
809 | Standard_Byte(255.0 * aLastColorSrc.Blue()), |
3c3131a0 |
810 | 0xFF |
811 | }}; |
812 | |
813 | // fill second row |
bf75be98 |
814 | for (Standard_Size aCol = (Standard_Size )aColorsNb; aCol < anImage->SizeX(); ++aCol) |
7fd59977 |
815 | { |
ca0c0b11 |
816 | anImage->ChangeValue<Image_ColorRGBA> (0, aCol) = aLastColor; |
7fd59977 |
817 | } |
818 | |
3c3131a0 |
819 | const Image_ColorRGBA anInvalidColor = |
820 | {{ |
8263fcd3 |
821 | Standard_Byte(255.0 * myInvalidColor.Red()), |
822 | Standard_Byte(255.0 * myInvalidColor.Green()), |
823 | Standard_Byte(255.0 * myInvalidColor.Blue()), |
3c3131a0 |
824 | 0xFF |
825 | }}; |
bf75be98 |
826 | for (Standard_Size aCol = 0; aCol < anImage->SizeX(); ++aCol) |
3c3131a0 |
827 | { |
ca0c0b11 |
828 | anImage->ChangeValue<Image_ColorRGBA> (1, aCol) = anInvalidColor; |
3c3131a0 |
829 | } |
7fd59977 |
830 | |
3c3131a0 |
831 | // create texture |
bf75be98 |
832 | return new MeshVS_ImageTexture2D (anImage); |
7fd59977 |
833 | } |