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