0024534: Improve design of Image_PixMap class
[occt.git] / src / MeshVS / MeshVS_NodalColorPrsBuilder.cxx
1 // Created on: 2003-11-12
2 // Created by: Alexander SOLOVYOV
3 // Copyright (c) 2003-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #define _POLYGONES_
17 // if define _POLYGONES_ ColorPrsBuilder use ArrayOfPolygons for drawing faces
18
19 #include <MeshVS_NodalColorPrsBuilder.ixx>
20
21 #include <Graphic3d_AspectFillArea3d.hxx>
22 #include <Graphic3d_AspectLine3d.hxx>
23 #include <Graphic3d_ArrayOfPolygons.hxx>
24 #include <Graphic3d_ArrayOfPolylines.hxx>
25 #include <Graphic3d_Group.hxx>
26 #include <Graphic3d_TextureParams.hxx>
27
28 #include <Prs3d_ShadingAspect.hxx>
29 #include <Prs3d_Root.hxx>
30 #include <Prs3d_LineAspect.hxx>
31
32 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
33 #include <TColStd_ListIteratorOfListOfInteger.hxx>
34 #include <TColStd_Array1OfReal.hxx>
35 #include <TColStd_HArray1OfReal.hxx>
36 #include <TColStd_Array1OfInteger.hxx>
37 #include <TColStd_SequenceOfInteger.hxx>
38 #include <TColStd_HPackedMapOfInteger.hxx>
39
40 #include <MeshVS_DisplayModeFlags.hxx>
41 #include <MeshVS_DrawerAttribute.hxx>
42 #include <MeshVS_DataSource.hxx>
43 #include <MeshVS_Drawer.hxx>
44 #include <MeshVS_Mesh.hxx>
45 #include <MeshVS_MeshPrsBuilder.hxx>
46 #include <MeshVS_HArray1OfSequenceOfInteger.hxx>
47 #include <MeshVS_Buffer.hxx>
48
49 #include <gp_Pnt.hxx>
50 #include <Image_PixMap.hxx>
51 #include <Graphic3d_Texture2D.hxx>
52 #include <Graphic3d_TypeOfTextureMode.hxx>
53 #include <Standard_DefineHandle.hxx>
54 #include <PrsMgr_PresentationManager3d.hxx>
55 #include <AIS_Drawer.hxx>
56 #include <Quantity_Array1OfColor.hxx>
57 #include <Aspect_SequenceOfColor.hxx>
58
59 /*
60   Class       : MeshVS_ImageTexture2D
61   Description : Texture for nodal presentation
62 */
63 class MeshVS_ImageTexture2D : public Graphic3d_Texture2D
64 {
65 public:
66
67   MeshVS_ImageTexture2D (const Handle(Image_PixMap)& theImg) : Graphic3d_Texture2D (theImg, Graphic3d_TOT_2D)
68   {
69     myParams->SetModulate (Standard_True);
70     myParams->SetFilter   (Graphic3d_TOTF_BILINEAR);
71   }
72
73 public:
74
75   DEFINE_STANDARD_RTTI(MeshVS_ImageTexture2D)
76 };
77
78 DEFINE_STANDARD_HANDLE    (MeshVS_ImageTexture2D, Graphic3d_Texture2D)
79 IMPLEMENT_STANDARD_HANDLE (MeshVS_ImageTexture2D, Graphic3d_Texture2D)
80 IMPLEMENT_STANDARD_RTTIEXT(MeshVS_ImageTexture2D, Graphic3d_Texture2D)
81
82 //================================================================
83 // Function : getNearestPow2
84 // Purpose  : Returns the nearest power of two greater than the
85 //            argument value
86 //================================================================
87 static inline Standard_Integer getNearestPow2( Standard_Integer theValue )
88 {
89   // Precaution against overflow
90   Standard_Integer aHalfMax = IntegerLast() >> 1, aRes = 1;
91   if ( theValue > aHalfMax ) theValue = aHalfMax;
92   while ( aRes < theValue ) aRes <<= 1;
93   return aRes;
94 }
95
96 /*
97   Class       : MeshVS_NodalColorPrsBuilder
98   Description : This class provides methods to create presentation of
99                 nodes with assigned color (See hxx for more description )
100 */
101
102 //================================================================
103 // Function : Constructor MeshVS_NodalColorPrsBuilder
104 // Purpose  :
105 //================================================================
106 MeshVS_NodalColorPrsBuilder::MeshVS_NodalColorPrsBuilder ( const Handle(MeshVS_Mesh)& Parent,
107                                                            const MeshVS_DisplayModeFlags& Flags,
108                                                            const Handle (MeshVS_DataSource)& DS,
109                                                            const Standard_Integer Id,
110                                                            const MeshVS_BuilderPriority& Priority )
111 : MeshVS_PrsBuilder ( Parent, Flags, DS, Id, Priority ),
112   myUseTexture( Standard_False ),
113   myInvalidColor( Quantity_NOC_GRAY )
114 {
115   SetExcluding ( Standard_True );
116 }
117
118 //================================================================
119 // Function : Build
120 // Purpose  :
121 //================================================================
122 void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
123                                           const TColStd_PackedMapOfInteger& IDs,
124                                           TColStd_PackedMapOfInteger& IDsToExclude,
125                                           const Standard_Boolean IsElement,
126                                           const Standard_Integer DisplayMode) const
127 {
128   Handle (MeshVS_DataSource) aSource = GetDataSource();
129   Handle (MeshVS_Drawer)     aDrawer = GetDrawer();
130   if ( aSource.IsNull() || aDrawer.IsNull() )
131     return;
132
133   Standard_Integer aMaxFaceNodes;
134   if ( !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, aMaxFaceNodes ) || aMaxFaceNodes <= 0 )
135     return;
136
137   MeshVS_Buffer aCoordsBuf (3*aMaxFaceNodes*sizeof(Standard_Real));
138   TColStd_Array1OfReal aCoords ( aCoordsBuf, 1, 3 * aMaxFaceNodes );
139   Standard_Integer NbNodes;
140   MeshVS_EntityType aType;
141
142   if ( !( DisplayMode & GetFlags() ) || !IsElement )
143     return;
144
145   if ( (myUseTexture && ( !myTextureCoords.Extent() || !myTextureColorMap.Length() )) ||
146        (!myUseTexture && !myNodeColorMap.Extent()) )
147     return;
148
149   // subtract the hidden elements and ids to exclude (to minimise allocated memory)
150   TColStd_PackedMapOfInteger anIDs;
151   anIDs.Assign( IDs );
152   Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
153   if ( !aHiddenElems.IsNull() )
154     anIDs.Subtract( aHiddenElems->Map() );
155   anIDs.Subtract( IDsToExclude );
156
157   Standard_Boolean IsReflect = Standard_False, IsMeshSmoothShading = Standard_False;
158   aDrawer->GetBoolean( MeshVS_DA_ColorReflection, IsReflect );
159   aDrawer->GetBoolean( MeshVS_DA_SmoothShading,   IsMeshSmoothShading );
160
161   // Following parameter are used for texture presentation only
162   int nbColors = 0; // Number of colors from color map
163   int nbTextureColors = 0; // Number of colors in texture (it will be pow of 2)
164   if ( myUseTexture )
165   {
166     nbColors = myTextureColorMap.Length();
167     nbTextureColors = getNearestPow2( nbColors );
168   }
169
170   Standard_Integer aSize = anIDs.Extent();
171
172   // Calculate maximum possible number of vertices and bounds
173   Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
174   Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0;
175   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
176   for( ; it.More(); it.Next() )
177   {
178     Standard_Integer aKey = it.Key();
179     if ( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
180       MeshVS_MeshPrsBuilder::HowManyPrimitives
181       ( aTopo, Standard_True, Standard_False, NbNodes,
182       PolygonVerticesFor3D, PolygonBoundsFor3D );
183   }
184
185   // Draw faces with nodal color
186   // OCC20644 Use "plastic" material as it is "non-physic" and so it is easier
187   // to get the required colors (see TelUpdateMaterial() function in OpenGl_attri.c)
188   Graphic3d_MaterialAspect aMaterial[ 2 ];
189   aMaterial[ 0 ] = Graphic3d_MaterialAspect( Graphic3d_NOM_PLASTIC );
190   aMaterial[ 1 ] = Graphic3d_MaterialAspect( Graphic3d_NOM_PLASTIC );
191   Standard_Integer i;
192   for ( i = 0; i < 2; i++ )
193   {
194     if ( !IsReflect )
195     {
196       aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
197       aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_AMBIENT );
198       aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
199       aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_EMISSION );
200     }
201     else{
202       // OCC20644 Using the material with reflection properties same as in
203       // ElementalColorPrsBuilder, to get the same colors.
204       // Additionally, ambient and diffuse coefficients are used below to scale incoming colors,
205       // to simulate TelUpdateMaterial() function from OpenGl_attri.c.
206       // This is mandatory, as these "scaled" colors are then passed directly to OpenGL
207       // as ambient and diffuse colors of the current material using glColorMaterial().
208       // In ElementalColorPrsBuilder we do not need to do scale the colors, as this
209       // is done by TelUpdateMaterial().
210       // 0.5 is used to have the colors in 3D maximally similar to those in the color scale.
211       // This is possible when the sum of all coefficient is equal to 1.
212       aMaterial[i].SetAmbient( .5 );
213       aMaterial[i].SetDiffuse( .5 );
214       aMaterial[i].SetSpecular( 0. );
215       aMaterial[i].SetEmissive( 0. );
216     }
217
218  }
219
220
221   // Create array of polygons for interior presentation of faces and volumes
222   Handle(Graphic3d_ArrayOfPolygons) aCPolyArr = new Graphic3d_ArrayOfPolygons
223     ( aMaxFaceNodes * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D,
224     0, myUseTexture || IsReflect, !myUseTexture, Standard_False, myUseTexture );
225
226   // Create array of polylines for presentation of edges
227   // (used for optimization insted of SetEdgeOn method call)
228   Handle(Graphic3d_ArrayOfPolylines) aPolyL = new Graphic3d_ArrayOfPolylines
229     ( ( aMaxFaceNodes + 1 ) * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D );
230
231   gp_Pnt P, Start;
232   Standard_Real aMin = gp::Resolution() * gp::Resolution();
233   gp_Dir aDefNorm( 0., 0., 1. );
234
235   // Prepare for scaling the incoming colors
236   Standard_Real anColorRatio = aMaterial[0].Ambient();
237
238   for( it.Reset(); it.More(); it.Next() )
239   {
240     Standard_Integer aKey = it.Key();
241     if ( aSource->GetGeom  ( aKey, Standard_True, aCoords, NbNodes, aType ) )
242     {
243       MeshVS_Buffer aNodesBuf (NbNodes*sizeof(Standard_Integer));
244       TColStd_Array1OfInteger aNodes(aNodesBuf, 1, NbNodes);
245       if ( !aSource->GetNodesByElement ( aKey, aNodes, NbNodes ) )
246         continue;
247
248       Quantity_Color aNColor;
249
250       Standard_Boolean isValid = Standard_True;
251       Standard_Integer i;
252       if ( myUseTexture )
253       {
254         for ( i = 1; i <= NbNodes && isValid; i++ )
255           isValid = myTextureCoords.IsBound( aNodes( i ) );
256       }
257       else
258       {
259         for ( i = 1; i <= NbNodes && isValid; i++ )
260           isValid = GetColor ( aNodes( i ), aNColor );
261       }
262
263       if ( !isValid )
264         continue;
265
266       // Preparing normal(s) to show reflections if requested
267       Handle(TColStd_HArray1OfReal) aNormals;
268       Standard_Boolean hasNormals =
269         ( IsReflect && aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals ) );
270
271       if ( aType == MeshVS_ET_Face )
272       {
273         aCPolyArr->AddBound ( NbNodes );
274         aPolyL->AddBound ( NbNodes + 1 );
275
276         for ( i = 1; i <= NbNodes; i++)
277         {
278           P = gp_Pnt( aCoords( 3 * i - 2 ), aCoords( 3 * i - 1 ), aCoords( 3 * i ) );
279           if ( myUseTexture )
280           {
281             int anId = aNodes( i );
282             double aTexCoord = myTextureCoords( anId );
283
284             // transform texture coordinate in accordance with number of colors specified
285             // by upper level and real size of Gl texture
286             // The Gl texture has border colors interpolated with the colors from the color map,
287             // thats why we need to shrink texture coordinates around the middle point to
288             // exclude areas where the map colors are interpolated with the borders color
289             double aWrapCoord = 1.0 / (2.0 * nbTextureColors) + aTexCoord * (nbColors - 1.0) / nbTextureColors;
290
291             if ( hasNormals )
292             {
293               gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
294                            aNormals->Value( 3 * i - 1 ),
295                            aNormals->Value( 3 * i     ));
296               // There are two "rows" of colors: user's invalid color at the top
297               // of texture and line of map colors at the bottom of the texture.
298               // Since the texture has borders, which are interpolated with the "rows" of colors
299               // we should specify the 0.25 offset to get the correct texture color
300               aNorm.SquareMagnitude() > aMin ?
301                 aCPolyArr->AddVertex(P, gp_Dir( aNorm ),
302                   gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ) :
303                 aCPolyArr->AddVertex(P, aDefNorm,
304                   gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
305             }
306             else
307               aCPolyArr->AddVertex( P, aDefNorm,
308                 gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
309           }
310           else
311           {
312             GetColor ( aNodes( i ), aNColor );
313
314             if ( IsReflect )
315             {
316               // Simulating TelUpdateMaterial() from OpenGl_attri.c
317               // to get the same colors in elemental and nodal color prs builders
318               aNColor.SetValues(anColorRatio * aNColor.Red(),
319                                 anColorRatio * aNColor.Green(),
320                                 anColorRatio * aNColor.Blue(),
321                                 Quantity_TOC_RGB);
322
323               if ( hasNormals )
324               {
325                 gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
326                   aNormals->Value( 3 * i - 1 ),
327                   aNormals->Value( 3 * i     ));
328                 aNorm.SquareMagnitude() > aMin ?
329                   aCPolyArr->AddVertex(P, gp_Dir( aNorm ), aNColor ) :
330                 aCPolyArr->AddVertex(P, aDefNorm       , aNColor );
331               }
332               else
333                 aCPolyArr->AddVertex(P, aDefNorm, aNColor );
334             }
335             else
336               aCPolyArr->AddVertex( P, aNColor );
337           }
338           aPolyL->AddVertex ( P );
339           if ( i == 1 )
340             Start = P;
341         }
342         aPolyL->AddVertex ( Start );
343
344         // if IsExcludingOn then presentation must not be built by other builders
345         if ( IsExcludingOn() )
346           IDsToExclude.Add( aKey );
347       }
348       else if ( aType == MeshVS_ET_Volume )
349       {
350         if ( !aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
351           continue;
352
353         // iterate through faces of volume
354         for ( Standard_Integer k = aTopo->Lower(), last = aTopo->Upper(), normIndex = 1; k <= last; k++, normIndex++ )
355         {
356           const TColStd_SequenceOfInteger& aSeq = aTopo->Value( k );
357           Standard_Integer m = aSeq.Length(), ind;
358
359           // build polygon & polylines for current face
360           aCPolyArr->AddBound( m );
361           aPolyL->AddBound( m + 1 );
362           for ( Standard_Integer j = 1; j <= m; j++ )
363           {
364             ind = aSeq.Value( j );
365             P = gp_Pnt( aCoords( 3 * ind + 1 ),
366                         aCoords( 3 * ind + 2 ),
367                         aCoords( 3 * ind + 3 ) );
368             if ( myUseTexture )
369             {
370               Standard_Integer anId = aNodes( ind + 1 );
371               Standard_Real aTexCoord = myTextureCoords( anId );
372
373               // transform texture coordinate in accordance with number of colors specified
374               // by upper level and real size of Gl texture
375               // The Gl texture has border colors interpolated with the colors from the color map,
376               // thats why we need to shrink texture coordinates around the middle point to
377               // exclude areas where the map colors are interpolated with the borders color
378               double aWrapCoord = 1.0 / (2.0 * nbTextureColors) + aTexCoord * (nbColors - 1.0) / nbTextureColors;
379
380               if ( hasNormals )
381               {
382                 gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
383                              aNormals->Value( 3 * i - 1 ),
384                              aNormals->Value( 3 * i     ));
385                 // There are two "rows" of colors: user's invalid color at the top
386                 // of texture and line of map colors at the bottom of the texture.
387                 // Since the texture has borders, which are interpolated with the "rows" of colors
388                 // we should specify the 0.25 offset to get the correct texture color
389                 aNorm.SquareMagnitude() > aMin ?
390                   aCPolyArr->AddVertex(P, gp_Dir( aNorm ),
391                     gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ) :
392                   aCPolyArr->AddVertex(P, aDefNorm,
393                     gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
394               }
395               else
396                 aCPolyArr->AddVertex( P, aDefNorm,
397                   gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
398             }
399             else
400             {
401               GetColor( aNodes( ind + 1 ), aNColor );
402               if  ( IsReflect )
403               {
404                 // Simulating TelUpdateMaterial() from OpenGl_attri.c
405                 // to get the same colors in elemental and nodal color prs builders
406                 aNColor.SetValues(anColorRatio * aNColor.Red(),
407                                   anColorRatio * aNColor.Green(),
408                                   anColorRatio * aNColor.Blue(),
409                                   Quantity_TOC_RGB);
410
411                 if ( hasNormals )
412                 {
413                   gp_Vec aNorm(aNormals->Value( 3 * normIndex - 2 ),
414                     aNormals->Value( 3 * normIndex - 1 ),
415                     aNormals->Value( 3 * normIndex ));
416                   aNorm.SquareMagnitude() > aMin ?
417                     aCPolyArr->AddVertex( P, gp_Dir( aNorm ), aNColor ) :
418                   aCPolyArr->AddVertex( P, aDefNorm       , aNColor );
419                 }
420                 else
421                   aCPolyArr->AddVertex( P, aDefNorm, aNColor );
422               }
423               else
424                 aCPolyArr->AddVertex( P, aNColor );
425             }
426             aPolyL->AddVertex ( P );
427             if ( j == 1 )
428               Start = P;
429           }
430           aPolyL->AddVertex ( Start );
431         }
432
433         // if IsExcludingOn then presentation must not be built by other builders
434         if ( IsExcludingOn() )
435           IDsToExclude.Add( aKey );
436       }
437     }
438   } // for ( ...
439
440   Handle(Graphic3d_AspectFillArea3d) anAsp;
441
442 //  Aspect_InteriorStyle  aStyle;
443 //  Standard_Integer      aStyleInt;
444   Aspect_TypeOfLine     anEdgeType = Aspect_TOL_SOLID;
445   Standard_Integer      anEdgeInt;
446   Standard_Real         anEdgeWidth;
447   Quantity_Color        anInteriorColor;
448   Quantity_Color        anEdgeColor, aLineColor;
449   Standard_Boolean      aShowEdges = Standard_True;
450
451   aDrawer->GetColor  ( MeshVS_DA_InteriorColor, anInteriorColor );
452   aDrawer->GetColor  ( MeshVS_DA_EdgeColor, anEdgeColor );
453   aDrawer->GetColor  ( MeshVS_DA_BeamColor, aLineColor );
454   aDrawer->GetDouble ( MeshVS_DA_EdgeWidth, anEdgeWidth );
455   aDrawer->GetBoolean( MeshVS_DA_ShowEdges, aShowEdges );
456
457   if ( aDrawer->GetInteger ( MeshVS_DA_EdgeType, anEdgeInt ) )
458     anEdgeType = (Aspect_TypeOfLine) anEdgeInt;
459
460   if ( myUseTexture )
461   {
462     Handle(AIS_Drawer) anAISDrawer =  myParentMesh->Attributes();
463     if ( anAISDrawer.IsNull() )
464       return;
465
466     anAISDrawer->SetShadingAspect( new Prs3d_ShadingAspect() );
467     anAsp = anAISDrawer->ShadingAspect()->Aspect();
468     if ( anAsp.IsNull() )
469       return;
470
471     anAsp->SetFrontMaterial( aMaterial[ 0 ] );
472     anAsp->SetBackMaterial( aMaterial[ 1 ] );
473
474
475     Handle(Graphic3d_Texture2D) aTexture = CreateTexture();
476     if ( aTexture.IsNull() )
477       return;
478
479     anAsp->SetTextureMapOn();
480     anAsp->SetTextureMap( aTexture );
481     anAsp->SetInteriorColor( Quantity_NOC_WHITE );
482   }
483   else
484   {
485 //    if ( aDrawer->GetInteger ( MeshVS_DA_InteriorStyle, aStyleInt ) )
486 //      aStyle = (Aspect_InteriorStyle)aStyleInt;
487
488     anAsp = new Graphic3d_AspectFillArea3d (
489       Aspect_IS_SOLID, Quantity_NOC_GRAY, anEdgeColor,
490       anEdgeType, anEdgeWidth, aMaterial[ 0 ], aMaterial[ 1 ] );
491   }
492
493   anAsp->SetDistinguishOff();
494   anAsp->SetEdgeOff();
495
496   Handle(Graphic3d_AspectLine3d) anLAsp =
497     new Graphic3d_AspectLine3d( anEdgeColor, anEdgeType, anEdgeWidth );
498
499   Prs3d_Root::NewGroup ( Prs );
500   Handle(Graphic3d_Group) aGroup1 = Prs3d_Root::CurrentGroup ( Prs );
501
502   aGroup1->SetPrimitivesAspect( anAsp );
503   aGroup1->AddPrimitiveArray( aCPolyArr );
504
505   if (aShowEdges)
506   {
507     Prs3d_Root::NewGroup ( Prs );
508     Handle(Graphic3d_Group) aGroup2 = Prs3d_Root::CurrentGroup ( Prs );
509
510     anAsp->SetEdgeOff();
511     anAsp->SetTextureMapOff();
512     aGroup2->SetPrimitivesAspect( anAsp );
513     aGroup2->SetPrimitivesAspect( anLAsp );
514     aGroup2->AddPrimitiveArray( aPolyL );
515     anAsp->SetEdgeOn();
516   }
517 }
518
519 //================================================================
520 // Function : SetColors
521 // Purpose  :
522 //================================================================
523 void MeshVS_NodalColorPrsBuilder::SetColors (
524   const MeshVS_DataMapOfIntegerColor& theColorMap )
525 {
526   myNodeColorMap = theColorMap;
527 }
528
529 //================================================================
530 // Function : GetColors
531 // Purpose  :
532 //================================================================
533 const MeshVS_DataMapOfIntegerColor& MeshVS_NodalColorPrsBuilder::GetColors() const
534 {
535   return myNodeColorMap;
536 }
537
538 //================================================================
539 // Function : HasColors
540 // Purpose  :
541 //================================================================
542 Standard_Boolean MeshVS_NodalColorPrsBuilder::HasColors () const
543 {
544   return ( myNodeColorMap.Extent() >0 );
545 }
546
547 //================================================================
548 // Function : GetColor
549 // Purpose  :
550 //================================================================
551 Standard_Boolean MeshVS_NodalColorPrsBuilder::GetColor ( const Standard_Integer ID,
552                                                          Quantity_Color& theColor ) const
553 {
554   Standard_Boolean aRes = myNodeColorMap.IsBound ( ID );
555   if ( aRes )
556     theColor = myNodeColorMap.Find ( ID );
557   return aRes;
558 }
559
560 //================================================================
561 // Function : SetColor
562 // Purpose  :
563 //================================================================
564 void MeshVS_NodalColorPrsBuilder::SetColor ( const Standard_Integer theID,
565                                              const Quantity_Color& theCol )
566 {
567   Standard_Boolean aRes = myNodeColorMap.IsBound ( theID );
568   if ( aRes )
569     myNodeColorMap.ChangeFind ( theID ) = theCol;
570   else
571     myNodeColorMap.Bind ( theID, theCol );
572 }
573
574 //================================================================
575 // Function : UseTexture
576 // Purpose  : Specify whether texture must be used to build presentation
577 //================================================================
578 void MeshVS_NodalColorPrsBuilder::UseTexture( const Standard_Boolean theToUse )
579 {
580   myUseTexture = theToUse;
581   if ( myUseTexture )
582     myNodeColorMap.Clear();
583   else
584     myTextureColorMap.Clear();
585 }
586
587 //================================================================
588 // Function : IsUseTexture
589 // Purpose  : Verify whether texture is used to build presentation
590 //================================================================
591 Standard_Boolean MeshVS_NodalColorPrsBuilder::IsUseTexture() const
592 {
593   return myUseTexture;
594 }
595
596 //================================================================
597 // Function : SetColorMap
598 // Purpose  : Set colors to be used for texrture presentation.
599 //            Generate texture in accordance with given parameters
600 //================================================================
601 void MeshVS_NodalColorPrsBuilder::SetColorMap( const Aspect_SequenceOfColor& theColors )
602 {
603   myTextureColorMap = theColors;
604 }
605
606 //================================================================
607 // Function : GetColorMap
608 // Purpose  : Return colors used for texrture presentation
609 //================================================================
610 const Aspect_SequenceOfColor& MeshVS_NodalColorPrsBuilder::GetColorMap() const
611 {
612   return myTextureColorMap;
613 }
614
615 //================================================================
616 // Function : SetInvalidColor
617 // Purpose  : Set color representing invalid texture coordinate
618 //            (laying outside range [0, 1])
619 //================================================================
620 void MeshVS_NodalColorPrsBuilder::SetInvalidColor(
621   const Quantity_Color& theInvalidColor )
622 {
623   myInvalidColor = theInvalidColor;
624 }
625
626 //================================================================
627 // Function : GetInvalidColor
628 // Purpose  : Return color representing invalid texture coordinate
629 //            (laying outside range [0, 1])
630 //================================================================
631 Quantity_Color MeshVS_NodalColorPrsBuilder::GetInvalidColor() const
632 {
633   return myInvalidColor;
634 }
635
636 //================================================================
637 // Function : SetTextureCoords
638 // Purpose  : Specify correspondence between node IDs and texture
639 //            coordinates (range [0, 1])
640 //================================================================
641 void MeshVS_NodalColorPrsBuilder::SetTextureCoords (
642   const TColStd_DataMapOfIntegerReal& theMap )
643 {
644   myTextureCoords = theMap;
645 }
646
647 //================================================================
648 // Function : GetTextureCoords
649 // Purpose  : Get correspondence between node IDs and texture
650 //            coordinates (range [0, 1])
651 //================================================================
652 const TColStd_DataMapOfIntegerReal& MeshVS_NodalColorPrsBuilder::GetTextureCoords() const
653 {
654   return myTextureCoords;
655 }
656
657 //================================================================
658 // Function : SetTextureCoord
659 // Purpose  : Specify correspondence between node ID and texture
660 //            coordinate (range [0, 1])
661 //================================================================
662 void MeshVS_NodalColorPrsBuilder::SetTextureCoord( const Standard_Integer theID,
663                                                    const Standard_Real theCoord )
664 {
665   myTextureCoords.Bind( theID, theCoord );
666 }
667
668 //================================================================
669 // Function : GetTextureCoord
670 // Purpose  : Return correspondence between node IDs and texture
671 //            coordinate (range [0, 1])
672 //================================================================
673 Standard_Real MeshVS_NodalColorPrsBuilder::GetTextureCoord( const Standard_Integer theID )
674 {
675   return myTextureCoords.IsBound( theID ) ? myTextureCoords( theID ) : -1;
676 }
677
678 //================================================================
679 // Function : CreateTexture
680 // Purpose  : Create texture in accordance with myTextureColorMap
681 //================================================================
682 Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const
683 {
684   const Standard_Integer aColorsNb = myTextureColorMap.Length();
685   if (aColorsNb == 0)
686   {
687     return NULL;
688   }
689
690   // create and fill image with colors
691   Handle(Image_PixMap) anImage = new Image_PixMap();
692   if (!anImage->InitTrash (Image_PixMap::ImgRGBA, Standard_Size(getNearestPow2 (aColorsNb)), 2))
693   {
694     return NULL;
695   }
696
697   anImage->SetTopDown (false);
698   for (Standard_Size aCol = 0; aCol < Standard_Size(aColorsNb); ++aCol)
699   {
700     const Quantity_Color& aSrcColor = myTextureColorMap.Value (Standard_Integer(aCol) + 1);
701     Image_ColorRGBA& aColor = anImage->ChangeValue<Image_ColorRGBA> (0, aCol);
702     aColor.r() = Standard_Byte(255.0 * aSrcColor.Red());
703     aColor.g() = Standard_Byte(255.0 * aSrcColor.Green());
704     aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue());
705     aColor.a() = 0xFF;
706   }
707
708   // fill padding bytes
709   const Quantity_Color& aLastColorSrc = myTextureColorMap.Last();
710   const Image_ColorRGBA aLastColor =
711   {{
712     Standard_Byte(255.0 * aLastColorSrc.Red()),
713     Standard_Byte(255.0 * aLastColorSrc.Green()),
714     Standard_Byte(255.0 * aLastColorSrc.Blue()),
715     0xFF
716   }};
717
718   // fill second row
719   for (Standard_Size aCol = (Standard_Size )aColorsNb; aCol < anImage->SizeX(); ++aCol)
720   {
721     anImage->ChangeValue<Image_ColorRGBA> (0, aCol) = aLastColor;
722   }
723
724   const Image_ColorRGBA anInvalidColor =
725   {{
726     Standard_Byte(255.0 * myInvalidColor.Red()),
727     Standard_Byte(255.0 * myInvalidColor.Green()),
728     Standard_Byte(255.0 * myInvalidColor.Blue()),
729     0xFF
730   }};
731   for (Standard_Size aCol = 0; aCol < anImage->SizeX(); ++aCol)
732   {
733     anImage->ChangeValue<Image_ColorRGBA> (1, aCol) = anInvalidColor;
734   }
735
736   // create texture
737   return new MeshVS_ImageTexture2D (anImage);
738 }