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