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