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