0022777: Visualization - Unsafe way to get attribute values from MeshVS_Drawer
[occt.git] / src / MeshVS / MeshVS_NodalColorPrsBuilder.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 566f3f7..8856854
@@ -1,68 +1,67 @@
 // Created on: 2003-11-12
 // Created by: Alexander SOLOVYOV
-// Copyright (c) 2003-2012 OPEN CASCADE SAS
+// Copyright (c) 2003-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #define _POLYGONES_
-// if define _POLYGONES_ ColorPrsBuilder use ArrayOfPolygons for drawing faces
 
-#include <MeshVS_NodalColorPrsBuilder.ixx>
+// if define _POLYGONES_ ColorPrsBuilder use ArrayOfPolygons for drawing faces
 
-#include <Graphic3d_AspectFillArea3d.hxx>
-#include <Graphic3d_AspectLine3d.hxx>
+#include <Aspect_SequenceOfColor.hxx>
+#include <gp_Pnt.hxx>
 #include <Graphic3d_ArrayOfPolygons.hxx>
 #include <Graphic3d_ArrayOfPolylines.hxx>
-#include <Graphic3d_Vertex.hxx>
+#include <Graphic3d_ArrayOfPrimitives.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Graphic3d_AspectFillArea3d.hxx>
+#include <Graphic3d_AspectLine3d.hxx>
 #include <Graphic3d_Group.hxx>
-#include <Graphic3d_Array1OfVertex.hxx>
+#include <Graphic3d_Texture2D.hxx>
 #include <Graphic3d_TextureParams.hxx>
-
-#include <Prs3d_ShadingAspect.hxx>
-#include <Prs3d_Root.hxx>
-#include <Prs3d_LineAspect.hxx>
-
-#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
-#include <TColStd_ListIteratorOfListOfInteger.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TColStd_HArray1OfReal.hxx>
-#include <TColStd_Array1OfInteger.hxx>
-#include <TColStd_SequenceOfInteger.hxx>
-#include <TColStd_HPackedMapOfInteger.hxx>
-
-#include <MeshVS_DisplayModeFlags.hxx>
-#include <MeshVS_DrawerAttribute.hxx>
+#include <Graphic3d_TypeOfTextureMode.hxx>
+#include <Image_PixMap.hxx>
+#include <MeshVS_Buffer.hxx>
 #include <MeshVS_DataSource.hxx>
+#include <MeshVS_DisplayModeFlags.hxx>
 #include <MeshVS_Drawer.hxx>
+#include <MeshVS_DrawerAttribute.hxx>
+#include <MeshVS_HArray1OfSequenceOfInteger.hxx>
 #include <MeshVS_Mesh.hxx>
 #include <MeshVS_MeshPrsBuilder.hxx>
-#include <MeshVS_HArray1OfSequenceOfInteger.hxx>
-#include <MeshVS_Buffer.hxx>
-
-#include <gp_Pnt.hxx>
-#include <Image_PixMap.hxx>
-#include <Graphic3d_Texture2D.hxx>
-#include <Graphic3d_TypeOfTextureMode.hxx>
-#include <Standard_DefineHandle.hxx>
+#include <MeshVS_NodalColorPrsBuilder.hxx>
+#include <MeshVS_SymmetricPairHasher.hxx>
+#include <MeshVS_Tool.hxx>
+#include <NCollection_Map.hxx>
+#include <NCollection_Vector.hxx>
+#include <Prs3d_Drawer.hxx>
+#include <Prs3d_LineAspect.hxx>
+#include <Prs3d_Presentation.hxx>
+#include <Prs3d_Root.hxx>
+#include <Prs3d_ShadingAspect.hxx>
 #include <PrsMgr_PresentationManager3d.hxx>
-#include <Graphic3d_Array1OfVertexNT.hxx>
-#include <AIS_Drawer.hxx>
 #include <Quantity_Array1OfColor.hxx>
-#include <Aspect_SequenceOfColor.hxx>
+#include <Quantity_Color.hxx>
+#include <Standard_Type.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+#include <TColStd_HPackedMapOfInteger.hxx>
+#include <TColStd_ListIteratorOfListOfInteger.hxx>
+#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
+#include <TColStd_SequenceOfInteger.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(MeshVS_NodalColorPrsBuilder,MeshVS_PrsBuilder)
 
 /*
   Class       : MeshVS_ImageTexture2D
 */
 class MeshVS_ImageTexture2D : public Graphic3d_Texture2D
 {
-
 public:
 
-  MeshVS_ImageTexture2D (const Handle(Image_PixMap)& theImg)
-  : Graphic3d_Texture2D ("", Graphic3d_TOT_2D),
-    myImage (theImg)
+  MeshVS_ImageTexture2D (const Handle(Image_PixMap)& theImg) : Graphic3d_Texture2D (theImg, Graphic3d_TOT_2D)
   {
     myParams->SetModulate (Standard_True);
     myParams->SetFilter   (Graphic3d_TOTF_BILINEAR);
   }
 
-  virtual ~MeshVS_ImageTexture2D()
-  {
-    //
-  }
-
-  virtual Standard_Boolean IsDone() const
-  {
-    return !myImage.IsNull() && !myImage->IsEmpty();
-  }
-
-  virtual Handle(Image_PixMap) GetImage() const
-  {
-    return myImage;
-  }
-
-private:
-
-  Handle(Image_PixMap) myImage;
-
 public:
 
-  DEFINE_STANDARD_RTTI(MeshVS_ImageTexture2D)
-
+  DEFINE_STANDARD_RTTI_INLINE(MeshVS_ImageTexture2D,Graphic3d_Texture2D)
 };
 
 DEFINE_STANDARD_HANDLE    (MeshVS_ImageTexture2D, Graphic3d_Texture2D)
-IMPLEMENT_STANDARD_HANDLE (MeshVS_ImageTexture2D, Graphic3d_Texture2D)
-IMPLEMENT_STANDARD_RTTIEXT(MeshVS_ImageTexture2D, Graphic3d_Texture2D)
+
 
 //================================================================
 // Function : getNearestPow2
@@ -173,11 +148,11 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
   if ( !( DisplayMode & GetFlags() ) || !IsElement )
     return;
 
-  if ( myUseTexture && ( !myTextureCoords.Extent() || !myTextureColorMap.Length() ) ||
-       !myUseTexture && !myNodeColorMap.Extent() )
+  if ( (myUseTexture && ( !myTextureCoords.Extent() || !myTextureColorMap.Length() )) ||
+       (!myUseTexture && !myNodeColorMap.Extent()) )
     return;
 
-  // subtract the hidden elements and ids to exclude (to minimise allocated memory)
+  // subtract the hidden elements and ids to exclude (to minimize allocated memory)
   TColStd_PackedMapOfInteger anIDs;
   anIDs.Assign( IDs );
   Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
@@ -214,20 +189,16 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
   }
 
   // Draw faces with nodal color
-  // OCC20644 Use "plastic" material as it is "non-physic" and so it is easier
-  // to get the required colors (see TelUpdateMaterial() function in OpenGl_attri.c)
-  Graphic3d_MaterialAspect aMaterial[ 2 ];
-  aMaterial[ 0 ] = Graphic3d_MaterialAspect( Graphic3d_NOM_PLASTIC );
-  aMaterial[ 1 ] = Graphic3d_MaterialAspect( Graphic3d_NOM_PLASTIC );
-  Standard_Integer i;
-  for ( i = 0; i < 2; i++ )
+  // OCC20644 Use "plastic" material as it is "non-physic" and so it is easier to get the required colors
+  Graphic3d_MaterialAspect aMaterial[2] = { Graphic3d_NOM_PLASTIC, Graphic3d_NOM_PLASTIC };
+  for (Standard_Integer i = 0; i < 2; ++i)
   {
+    aMaterial[i].SetSpecularColor (Quantity_NOC_BLACK);
+    aMaterial[i].SetEmissiveColor (Quantity_NOC_BLACK);
     if ( !IsReflect )
     {
-      aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
-      aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_AMBIENT );
-      aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
-      aMaterial[ i ].SetReflectionModeOff( Graphic3d_TOR_EMISSION );
+      aMaterial[i].SetAmbientColor (Quantity_NOC_BLACK);
+      aMaterial[i].SetDiffuseColor (Quantity_NOC_BLACK);
     }
     else{
       // OCC20644 Using the material with reflection properties same as in
@@ -240,230 +211,197 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
       // is done by TelUpdateMaterial().
       // 0.5 is used to have the colors in 3D maximally similar to those in the color scale.
       // This is possible when the sum of all coefficient is equal to 1.
-      aMaterial[i].SetAmbient( .5 );
-      aMaterial[i].SetDiffuse( .5 );
-      aMaterial[i].SetSpecular( 0. );
-      aMaterial[i].SetEmissive( 0. );
+      aMaterial[i].SetAmbientColor (Quantity_Color (Graphic3d_Vec3 (0.5f)));
+      aMaterial[i].SetDiffuseColor (Quantity_Color (Graphic3d_Vec3 (0.5f)));
     }
-
- }
-
+  }
 
   // Create array of polygons for interior presentation of faces and volumes
   Handle(Graphic3d_ArrayOfPolygons) aCPolyArr = new Graphic3d_ArrayOfPolygons
     ( aMaxFaceNodes * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D,
     0, myUseTexture || IsReflect, !myUseTexture, Standard_False, myUseTexture );
 
+    Standard_Integer aNbFacePrimitives = 0;
+    Standard_Integer aNbVolmPrimitives = 0;
+    Standard_Integer aNbEdgePrimitives = 0;
+    Standard_Integer aNbLinkPrimitives = 0;
+
+    for (it.Reset(); it.More(); it.Next())
+    {
+      Standard_Integer aNbNodes = 0;
+
+      if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType))
+        continue;
+
+      if (aType == MeshVS_ET_Volume)
+      {
+        if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo))
+        {
+          for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx)
+          {
+            const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx);
+
+            aNbEdgePrimitives += aFaceNodes.Length();     // add edge segments
+            aNbVolmPrimitives += aFaceNodes.Length() - 2; // add volumetric cell triangles
+          }
+        }
+      }
+      else if (aType == MeshVS_ET_Link)
+      {
+        aNbLinkPrimitives += aNbNodes - 1; // add link segments
+      }
+      else if (aType == MeshVS_ET_Face)
+      {
+        aNbEdgePrimitives += aNbNodes;     // add edge segments
+        aNbFacePrimitives += aNbNodes - 2; // add face triangles
+      }
+    }
+
+  // Here we do not use indices arrays because they are not effective for some mesh
+  // drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D
+  // cell rendering (normal interpolation is not always applicable - flat shading),
+  // elemental coloring (color interpolation is impossible)
+
+  // Create array of polygons for interior presentation of faces and volumes
+  Handle(Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles
+    ( (aNbFacePrimitives + aNbVolmPrimitives) * 3, 0, myUseTexture || IsReflect, !myUseTexture, myUseTexture );
+
   // Create array of polylines for presentation of edges
-  // (used for optimization insted of SetEdgeOn method call)
-  Handle(Graphic3d_ArrayOfPolylines) aPolyL = new Graphic3d_ArrayOfPolylines
-    ( ( aMaxFaceNodes + 1 ) * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D );
+  Handle(Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments
+    (aNbEdgePrimitives * 2);
 
   gp_Pnt P, Start;
   Standard_Real aMin = gp::Resolution() * gp::Resolution();
   gp_Dir aDefNorm( 0., 0., 1. );
 
   // Prepare for scaling the incoming colors
-  Standard_Real anColorRatio = aMaterial[0].Ambient();
+  const Standard_Real anColorRatio = !IsReflect ? 0.44f : 0.5f;
 
-  for( it.Reset(); it.More(); it.Next() )
+  for (it.Reset(); it.More(); it.Next())
   {
     Standard_Integer aKey = it.Key();
-    if ( aSource->GetGeom  ( aKey, Standard_True, aCoords, NbNodes, aType ) )
+
+    if (aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType))
     {
-      MeshVS_Buffer aNodesBuf (NbNodes*sizeof(Standard_Integer));
-      TColStd_Array1OfInteger aNodes(aNodesBuf, 1, NbNodes);
-      if ( !aSource->GetNodesByElement ( aKey, aNodes, NbNodes ) )
+      TColStd_Array1OfInteger aNodes (1, NbNodes);
+      
+      if (!aSource->GetNodesByElement (aKey, aNodes, NbNodes))
         continue;
 
       Quantity_Color aNColor;
 
       Standard_Boolean isValid = Standard_True;
-      Standard_Integer i;
-      if ( myUseTexture )
+      
+      if (myUseTexture)
       {
-        for ( i = 1; i <= NbNodes && isValid; i++ )
-          isValid = myTextureCoords.IsBound( aNodes( i ) );
+        for (Standard_Integer k = 1; k <= NbNodes && isValid; ++k)
+          isValid = myTextureCoords.IsBound (aNodes (k));
       }
       else
       {
-        for ( i = 1; i <= NbNodes && isValid; i++ )
-          isValid = GetColor ( aNodes( i ), aNColor );
+        for (Standard_Integer k = 1; k <= NbNodes && isValid; ++k)
+          isValid = GetColor (aNodes (k), aNColor);
       }
 
-      if ( !isValid )
+      if (!isValid)
         continue;
 
       // Preparing normal(s) to show reflections if requested
       Handle(TColStd_HArray1OfReal) aNormals;
+
       Standard_Boolean hasNormals =
-        ( IsReflect && aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals ) );
+        (IsReflect && aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals));
 
-      if ( aType == MeshVS_ET_Face )
+      if (aType == MeshVS_ET_Face)
       {
-        aCPolyArr->AddBound ( NbNodes );
-        aPolyL->AddBound ( NbNodes + 1 );
-
-        for ( i = 1; i <= NbNodes; i++)
+        for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx) // triangulate polygon
         {
-          P = gp_Pnt( aCoords( 3 * i - 2 ), aCoords( 3 * i - 1 ), aCoords( 3 * i ) );
-          if ( myUseTexture )
+          for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle
           {
-            int anId = aNodes( i );
-            double aTexCoord = myTextureCoords( anId );
+            gp_XYZ aPnt (aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
+                         aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
+                         aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
 
-            // transform texture coordinate in accordance with number of colors specified
-            // by upper level and real size of Gl texture
-            // The Gl texture has border colors interpolated with the colors from the color map,
-            // thats why we need to shrink texture coordinates around the middle point to
-            // exclude areas where the map colors are interpolated with the borders color
-            double aWrapCoord = 1.0 / (2.0 * nbTextureColors) + aTexCoord * (nbColors - 1.0) / nbTextureColors;
+            gp_Vec aNorm = aDefNorm;
 
-            if ( hasNormals )
+            if (hasNormals)
             {
-              gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
-                           aNormals->Value( 3 * i - 1 ),
-                           aNormals->Value( 3 * i     ));
-              // There are two "rows" of colors: user's invalid color at the top
-              // of texture and line of map colors at the bottom of the texture.
-              // Since the texture has borders, which are interpolated with the "rows" of colors
-              // we should specify the 0.25 offset to get the correct texture color
-              aNorm.SquareMagnitude() > aMin ?
-                aCPolyArr->AddVertex(P, gp_Dir( aNorm ),
-                  gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ) :
-                aCPolyArr->AddVertex(P, aDefNorm,
-                  gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
-            }
-            else
-              aCPolyArr->AddVertex( P, aDefNorm,
-                gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
-          }
-          else
-          {
-            GetColor ( aNodes( i ), aNColor );
+              gp_Vec aTestNorm (aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
+                                aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
+                                aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
 
-            if ( IsReflect )
-            {
-              // Simulating TelUpdateMaterial() from OpenGl_attri.c
-              // to get the same colors in elemental and nodal color prs builders
-              aNColor.SetValues(anColorRatio * aNColor.Red(),
-                                anColorRatio * aNColor.Green(),
-                                anColorRatio * aNColor.Blue(),
-                                Quantity_TOC_RGB);
-
-              if ( hasNormals )
+              if (aTestNorm.SquareMagnitude() > aMin)
               {
-                gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
-                  aNormals->Value( 3 * i - 1 ),
-                  aNormals->Value( 3 * i     ));
-                aNorm.SquareMagnitude() > aMin ?
-                  aCPolyArr->AddVertex(P, gp_Dir( aNorm ), aNColor ) :
-                aCPolyArr->AddVertex(P, aDefNorm       , aNColor );
+                aNorm = gp_Dir (aTestNorm);
               }
-              else
-                aCPolyArr->AddVertex(P, aDefNorm, aNColor );
             }
-            else
-              aCPolyArr->AddVertex( P, aNColor );
-          }
-          aPolyL->AddVertex ( P );
-          if ( i == 1 )
-            Start = P;
-        }
-        aPolyL->AddVertex ( Start );
-
-        // if IsExcludingOn then presentation must not be built by other builders
-        if ( IsExcludingOn() )
-          IDsToExclude.Add( aKey );
-      }
-      else if ( aType == MeshVS_ET_Volume )
-      {
-        if ( !aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
-          continue;
-
-        // iterate through faces of volume
-        for ( Standard_Integer k = aTopo->Lower(), last = aTopo->Upper(), normIndex = 1; k <= last; k++, normIndex++ )
-        {
-          const TColStd_SequenceOfInteger& aSeq = aTopo->Value( k );
-          Standard_Integer m = aSeq.Length(), ind;
 
-          // build polygon & polylines for current face
-          aCPolyArr->AddBound( m );
-          aPolyL->AddBound( m + 1 );
-          for ( Standard_Integer j = 1; j <= m; j++ )
-          {
-            ind = aSeq.Value( j );
-            P = gp_Pnt( aCoords( 3 * ind + 1 ),
-                        aCoords( 3 * ind + 2 ),
-                        aCoords( 3 * ind + 3 ) );
-            if ( myUseTexture )
+            if (myUseTexture)
             {
-              Standard_Integer anId = aNodes( ind + 1 );
-              Standard_Real aTexCoord = myTextureCoords( anId );
-
-              // transform texture coordinate in accordance with number of colors specified
-              // by upper level and real size of Gl texture
-              // The Gl texture has border colors interpolated with the colors from the color map,
-              // thats why we need to shrink texture coordinates around the middle point to
-              // exclude areas where the map colors are interpolated with the borders color
-              double aWrapCoord = 1.0 / (2.0 * nbTextureColors) + aTexCoord * (nbColors - 1.0) / nbTextureColors;
-
-              if ( hasNormals )
-              {
-                gp_Vec aNorm(aNormals->Value( 3 * i - 2 ),
-                             aNormals->Value( 3 * i - 1 ),
-                             aNormals->Value( 3 * i     ));
-                // There are two "rows" of colors: user's invalid color at the top
-                // of texture and line of map colors at the bottom of the texture.
-                // Since the texture has borders, which are interpolated with the "rows" of colors
-                // we should specify the 0.25 offset to get the correct texture color
-                aNorm.SquareMagnitude() > aMin ?
-                  aCPolyArr->AddVertex(P, gp_Dir( aNorm ),
-                    gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) ) :
-                  aCPolyArr->AddVertex(P, aDefNorm,
-                    gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
-              }
-              else
-                aCPolyArr->AddVertex( P, aDefNorm,
-                  gp_Pnt2d( aWrapCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 0.75 : 0.25 ) );
+              const Standard_Real aTexCoord = myTextureCoords (aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)));
+
+              // Transform texture coordinate in accordance with number of colors specified
+              // by upper level and real size of OpenGL texture. The OpenGL texture has border
+              // colors interpolated with the colors from the color map, thats why we need to
+              // shrink texture coordinates around the middle point to exclude areas where the
+              // map colors are interpolated with the borders color
+              aFaceTriangles->AddVertex (aPnt, aNorm, gp_Pnt2d (
+                (aTexCoord * (nbColors - 1.0) + 0.5) / nbTextureColors, aTexCoord < 0 || aTexCoord > 1 ? 0.25 : 0.75));
             }
             else
             {
-              GetColor( aNodes( ind + 1 ), aNColor );
-              if  ( IsReflect )
+              GetColor (aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)), aNColor);
+              
+              if (IsReflect)
               {
-                // Simulating TelUpdateMaterial() from OpenGl_attri.c
-                // to get the same colors in elemental and nodal color prs builders
-                aNColor.SetValues(anColorRatio * aNColor.Red(),
-                                  anColorRatio * aNColor.Green(),
-                                  anColorRatio * aNColor.Blue(),
-                                  Quantity_TOC_RGB);
-
-                if ( hasNormals )
-                {
-                  gp_Vec aNorm(aNormals->Value( 3 * normIndex - 2 ),
-                    aNormals->Value( 3 * normIndex - 1 ),
-                    aNormals->Value( 3 * normIndex ));
-                  aNorm.SquareMagnitude() > aMin ?
-                    aCPolyArr->AddVertex( P, gp_Dir( aNorm ), aNColor ) :
-                  aCPolyArr->AddVertex( P, aDefNorm       , aNColor );
-                }
-                else
-                  aCPolyArr->AddVertex( P, aDefNorm, aNColor );
+                aNColor.SetValues (anColorRatio * aNColor.Red(),
+                                   anColorRatio * aNColor.Green(),
+                                   anColorRatio * aNColor.Blue(),
+                                   Quantity_TOC_RGB);
+
+                aFaceTriangles->AddVertex (aPnt, aNorm, aNColor);
               }
               else
-                aCPolyArr->AddVertex( P, aNColor );
+              {
+                aFaceTriangles->AddVertex (aPnt, aNColor);
+              }
             }
-            aPolyL->AddVertex ( P );
-            if ( j == 1 )
-              Start = P;
           }
-          aPolyL->AddVertex ( Start );
+        }
+
+        for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx) // border segmentation
+        {
+          const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes;
+
+          anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
+                                     aCoords (3 * aNodeIdx + 2),
+                                     aCoords (3 * aNodeIdx + 3));
+
+          anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
+                                     aCoords (3 * aNextIdx + 2),
+                                     aCoords (3 * aNextIdx + 3));
         }
 
         // if IsExcludingOn then presentation must not be built by other builders
-        if ( IsExcludingOn() )
-          IDsToExclude.Add( aKey );
+        if (IsExcludingOn())
+        {
+          IDsToExclude.Add (aKey);
+        }
+      }
+      else if (aType == MeshVS_ET_Volume)
+      {
+        if (!aSource->Get3DGeom (aKey, NbNodes, aTopo))
+          continue;
+
+        AddVolumePrs (aTopo, aNodes, aCoords, aFaceTriangles,
+          IsReflect, nbColors, nbTextureColors, anColorRatio);
+        
+        AddVolumePrs (aTopo, aNodes, aCoords, anEdgeSegments,
+          IsReflect, nbColors, nbTextureColors, anColorRatio);
+
+        // if IsExcludingOn then presentation must not be built by other builders
+        if (IsExcludingOn())
+          IDsToExclude.Add (aKey);
       }
     }
   } // for ( ...
@@ -473,8 +411,7 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
 //  Aspect_InteriorStyle  aStyle;
 //  Standard_Integer      aStyleInt;
   Aspect_TypeOfLine     anEdgeType = Aspect_TOL_SOLID;
-  Standard_Integer      anEdgeInt;
-  Standard_Real         anEdgeWidth;
+  Standard_Real         anEdgeWidth = 1.0;
   Quantity_Color        anInteriorColor;
   Quantity_Color        anEdgeColor, aLineColor;
   Standard_Boolean      aShowEdges = Standard_True;
@@ -485,17 +422,18 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
   aDrawer->GetDouble ( MeshVS_DA_EdgeWidth, anEdgeWidth );
   aDrawer->GetBoolean( MeshVS_DA_ShowEdges, aShowEdges );
 
+  Standard_Integer anEdgeInt = Aspect_TOL_SOLID;
   if ( aDrawer->GetInteger ( MeshVS_DA_EdgeType, anEdgeInt ) )
     anEdgeType = (Aspect_TypeOfLine) anEdgeInt;
 
   if ( myUseTexture )
   {
-    Handle(AIS_Drawer) anAISDrawer =  myParentMesh->Attributes();
-    if ( anAISDrawer.IsNull() )
+    Handle(Prs3d_Drawer) aPrsDrawer =  myParentMesh->Attributes();
+    if ( aPrsDrawer.IsNull() )
       return;
 
-    anAISDrawer->SetShadingAspect( new Prs3d_ShadingAspect() );
-    anAsp = anAISDrawer->ShadingAspect()->Aspect();
+    aPrsDrawer->SetShadingAspect( new Prs3d_ShadingAspect() );
+    anAsp = aPrsDrawer->ShadingAspect()->Aspect();
     if ( anAsp.IsNull() )
       return;
 
@@ -527,27 +465,151 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
   Handle(Graphic3d_AspectLine3d) anLAsp =
     new Graphic3d_AspectLine3d( anEdgeColor, anEdgeType, anEdgeWidth );
 
-  Prs3d_Root::NewGroup ( Prs );
-  Handle(Graphic3d_Group) aGroup1 = Prs3d_Root::CurrentGroup ( Prs );
+  Handle(Graphic3d_Group) aGroup1 = Prs3d_Root::NewGroup (Prs);
+
+  Standard_Boolean toSupressBackFaces = Standard_False;
+  aDrawer->GetBoolean (MeshVS_DA_SupressBackFaces, toSupressBackFaces);
+  aGroup1->SetClosed (toSupressBackFaces == Standard_True);
 
   aGroup1->SetPrimitivesAspect( anAsp );
-  aGroup1->BeginPrimitives();
-  aGroup1->AddPrimitiveArray( aCPolyArr );
-  aGroup1->EndPrimitives();
+  aGroup1->AddPrimitiveArray( aFaceTriangles /*aCPolyArr*/ );
+  //aGroup1->AddPrimitiveArray( aCPolyArr );
 
   if (aShowEdges)
   {
     Prs3d_Root::NewGroup ( Prs );
     Handle(Graphic3d_Group) aGroup2 = Prs3d_Root::CurrentGroup ( Prs );
 
-    anAsp->SetEdgeOff();
-    anAsp->SetTextureMapOff();
-    aGroup2->SetPrimitivesAspect( anAsp );
+    Handle(Graphic3d_AspectFillArea3d) anAspCopy = new Graphic3d_AspectFillArea3d (*anAsp);
+    anAspCopy->SetTextureMapOff();
+    aGroup2->SetPrimitivesAspect( anAspCopy );
     aGroup2->SetPrimitivesAspect( anLAsp );
-    aGroup2->BeginPrimitives();
-    aGroup2->AddPrimitiveArray( aPolyL );
-    aGroup2->EndPrimitives();
-    anAsp->SetEdgeOn();
+    aGroup2->AddPrimitiveArray( anEdgeSegments );
+  }
+}
+
+//================================================================
+// Function : AddVolumePrs
+// Purpose  :
+//================================================================
+void MeshVS_NodalColorPrsBuilder::AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& theTopo,
+                                                const TColStd_Array1OfInteger&                   theNodes,
+                                                const TColStd_Array1OfReal&                      theCoords,
+                                                const Handle(Graphic3d_ArrayOfPrimitives)&       theArray,
+                                                const Standard_Boolean                           theIsShaded,
+                                                const Standard_Integer                           theNbColors,
+                                                const Standard_Integer                           theNbTexColors,
+                                                const Standard_Real                              theColorRatio) const
+{
+  Standard_Integer aLow = theCoords.Lower();
+
+  if (theTopo.IsNull() || theArray.IsNull())
+    return;
+
+  Standard_Boolean aIsPolygons = theArray->IsKind (STANDARD_TYPE (Graphic3d_ArrayOfTriangles));
+
+  if (aIsPolygons)
+  {    
+    for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
+    {
+      const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
+      
+      TColStd_Array1OfReal aPolyNodes (0, 3 * aFaceNodes.Length());
+
+      for (Standard_Integer aNodeIdx = 0; aNodeIdx < aFaceNodes.Length(); ++aNodeIdx)
+      {
+        Standard_Integer anIdx = aFaceNodes.Value (aNodeIdx + 1);
+
+        Standard_Real aX = theCoords.Value (aLow + 3 * anIdx + 0);
+        Standard_Real aY = theCoords.Value (aLow + 3 * anIdx + 1);
+        Standard_Real aZ = theCoords.Value (aLow + 3 * anIdx + 2);
+
+        aPolyNodes.SetValue (3 * aNodeIdx + 1, aX);
+        aPolyNodes.SetValue (3 * aNodeIdx + 2, aY);
+        aPolyNodes.SetValue (3 * aNodeIdx + 3, aZ);
+      }
+      
+      gp_Vec aNorm (0.0, 0.0, 1.0);
+
+      if (theIsShaded)
+      {
+        aPolyNodes.SetValue (0, aFaceNodes.Length());
+        
+        if (!MeshVS_Tool::GetAverageNormal (aPolyNodes, aNorm))
+        {
+          aNorm.SetCoord (0.0, 0.0, 1.0);
+        }
+      }
+
+      for (Standard_Integer aNodeIdx = 0; aNodeIdx < aFaceNodes.Length() - 2; ++aNodeIdx) // triangulate polygon
+      {
+        for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle
+        {
+          gp_Pnt aPnt (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
+                       aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
+                       aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
+
+          if (myUseTexture)
+          {
+            const Standard_Real aTexCoord = myTextureCoords (theNodes (aFaceNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)) + 1));
+
+            theArray->AddVertex (aPnt, aNorm, gp_Pnt2d (
+              (aTexCoord * (theNbColors - 1.0) + 0.5) / theNbTexColors, aTexCoord < 0 || aTexCoord > 1 ? 0.25 : 0.75));
+          }
+          else
+          {
+            Quantity_Color aNColor;
+            GetColor (theNodes ((aFaceNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)) + 1)), aNColor);
+
+            if (theIsShaded)
+            {
+              aNColor.SetValues (theColorRatio * aNColor.Red(),
+                                 theColorRatio * aNColor.Green(),
+                                 theColorRatio * aNColor.Blue(),
+                                 Quantity_TOC_RGB);
+
+              theArray->AddVertex (aPnt, aNorm, aNColor);
+            }
+            else
+            {
+              theArray->AddVertex (aPnt, aNColor);
+            }
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    // Find all pairs of nodes (edges) to draw (will be drawn only once)
+    NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aEdgeMap;
+
+    for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
+    {
+      const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
+      
+      for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx)
+      {
+        const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes;
+
+        aEdgeMap.Add (MeshVS_NodePair (aFaceNodes.Value (aNodeIdx + 1),
+                                       aFaceNodes.Value (aNextIdx + 1)));
+      }
+    }
+
+    // Draw edges
+    for(NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher>::Iterator anIt (aEdgeMap); anIt.More(); anIt.Next())
+    {      
+      const Standard_Integer anIdx1 = aLow + 3 * anIt.Key().first;
+      const Standard_Integer anIdx2 = aLow + 3 * anIt.Key().second;
+
+      Standard_Real aX[] = { theCoords.Value (anIdx1 + 0), theCoords.Value (anIdx2 + 0) };
+      Standard_Real aY[] = { theCoords.Value (anIdx1 + 1), theCoords.Value (anIdx2 + 1) };
+      Standard_Real aZ[] = { theCoords.Value (anIdx1 + 2), theCoords.Value (anIdx2 + 2) };
+
+      theArray->AddVertex (aX[0], aY[0], aZ[0]);
+      theArray->AddVertex (aX[1], aY[1], aZ[1]);
+    }
   }
 }
 
@@ -724,20 +786,19 @@ Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const
 
   // create and fill image with colors
   Handle(Image_PixMap) anImage = new Image_PixMap();
-  if (!anImage->InitTrash (Image_PixMap::ImgRGBA, Standard_Size(getNearestPow2 (aColorsNb)), 2))
+  if (!anImage->InitTrash (Image_Format_RGBA, Standard_Size(getNearestPow2 (aColorsNb)), 2))
   {
     return NULL;
   }
 
   anImage->SetTopDown (false);
-  Image_PixMapData<Image_ColorRGBA>& aData = anImage->EditData<Image_ColorRGBA>();
   for (Standard_Size aCol = 0; aCol < Standard_Size(aColorsNb); ++aCol)
   {
     const Quantity_Color& aSrcColor = myTextureColorMap.Value (Standard_Integer(aCol) + 1);
-    Image_ColorRGBA& aColor = aData.ChangeValue (0, aCol);
-    aColor.r() = int(255.0 * aSrcColor.Red());
-    aColor.g() = int(255.0 * aSrcColor.Green());
-    aColor.b() = int(255.0 * aSrcColor.Blue());
+    Image_ColorRGBA& aColor = anImage->ChangeValue<Image_ColorRGBA> (0, aCol);
+    aColor.r() = Standard_Byte(255.0 * aSrcColor.Red());
+    aColor.g() = Standard_Byte(255.0 * aSrcColor.Green());
+    aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue());
     aColor.a() = 0xFF;
   }
 
@@ -745,28 +806,28 @@ Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const
   const Quantity_Color& aLastColorSrc = myTextureColorMap.Last();
   const Image_ColorRGBA aLastColor =
   {{
-    int(255.0 * aLastColorSrc.Red()),
-    int(255.0 * aLastColorSrc.Green()),
-    int(255.0 * aLastColorSrc.Blue()),
+    Standard_Byte(255.0 * aLastColorSrc.Red()),
+    Standard_Byte(255.0 * aLastColorSrc.Green()),
+    Standard_Byte(255.0 * aLastColorSrc.Blue()),
     0xFF
   }};
 
   // fill second row
   for (Standard_Size aCol = (Standard_Size )aColorsNb; aCol < anImage->SizeX(); ++aCol)
   {
-    aData.ChangeValue (0, aCol) = aLastColor;
+    anImage->ChangeValue<Image_ColorRGBA> (0, aCol) = aLastColor;
   }
 
   const Image_ColorRGBA anInvalidColor =
   {{
-    int(255.0 * myInvalidColor.Red()),
-    int(255.0 * myInvalidColor.Green()),
-    int(255.0 * myInvalidColor.Blue()),
+    Standard_Byte(255.0 * myInvalidColor.Red()),
+    Standard_Byte(255.0 * myInvalidColor.Green()),
+    Standard_Byte(255.0 * myInvalidColor.Blue()),
     0xFF
   }};
   for (Standard_Size aCol = 0; aCol < anImage->SizeX(); ++aCol)
   {
-    aData.ChangeValue (1, aCol) = anInvalidColor;
+    anImage->ChangeValue<Image_ColorRGBA> (1, aCol) = anInvalidColor;
   }
 
   // create texture