0024926: MeshVS - improve generation of primitive arrays
authordbp <dbp@opencascade.com>
Thu, 24 Jul 2014 09:21:54 +0000 (13:21 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 24 Jul 2014 09:23:17 +0000 (13:23 +0400)
Remove redundant code.

Fix GCC compilation warnings.

Bug fix in MeshVS_ElementalColorPrsBuilder.

src/MeshVS/FILES
src/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx
src/MeshVS/MeshVS_MeshPrsBuilder.cdl
src/MeshVS/MeshVS_MeshPrsBuilder.cxx
src/MeshVS/MeshVS_NodalColorPrsBuilder.cdl
src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx
src/MeshVS/MeshVS_SymmetricPairHasher.hxx [new file with mode: 0644]
src/MeshVS/MeshVS_VectorPrsBuilder.cxx

index ad727f3..d85be04 100755 (executable)
@@ -7,3 +7,4 @@ MeshVS_TwoColors.hxx
 MeshVS_TwoColors.cxx
 MeshVS_TwoNodes.hxx
 MeshVS_SelectionModeFlags.hxx
+MeshVS_SymmetricPairHasher.hxx
index acf3d6b..5206f9f 100644 (file)
@@ -19,6 +19,8 @@
 #include <Graphic3d_AspectLine3d.hxx>
 #include <Graphic3d_ArrayOfPolygons.hxx>
 #include <Graphic3d_ArrayOfPolylines.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
 #include <Graphic3d_Group.hxx>
 
 #include <Prs3d_ShadingAspect.hxx>
@@ -47,7 +49,7 @@
 #include <MeshVS_DataMapIteratorOfDataMapOfColorMapOfInteger.hxx>
 #include <MeshVS_MeshPrsBuilder.hxx>
 #include <MeshVS_Buffer.hxx>
-
+#include <MeshVS_HArray1OfSequenceOfInteger.hxx>
 
 //================================================================
 // Function : Constructor MeshVS_ElementalColorPrsBuilder
@@ -210,8 +212,7 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)&
   }
 
   Graphic3d_MaterialAspect aMaterial[2];
-  Standard_Integer i;
-  for ( i=0; i<2; i++ )
+  for (Standard_Integer i = 0; i < 2; i++)
   {
     // OCC20644 "plastic" is most suitable here, as it is "non-physic"
     // so TelUpdateMaterial() from OpenGl_attri.c uses the interior
@@ -257,129 +258,227 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)&
     Handle ( Graphic3d_Group ) aGGroup = Prs3d_Root::CurrentGroup ( Prs );
     Prs3d_Root::NewGroup ( Prs );
     Handle ( Graphic3d_Group ) aLGroup = Prs3d_Root::CurrentGroup ( Prs );
+    Prs3d_Root::NewGroup ( Prs );
+    Handle ( Graphic3d_Group ) aSGroup = Prs3d_Root::CurrentGroup ( Prs );
+
+    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 (!aColIter.Value().Contains (it.Key()))
+        continue;
+
+      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);
 
-    Handle (Graphic3d_ArrayOfPolygons) aPolyGArr = new Graphic3d_ArrayOfPolygons
-      ( aMaxFaceNodes*aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D, 0, IsReflect );
+            if (anEdgeOn) // add edge segments
+            {
+              aNbEdgePrimitives += aFaceNodes.Length();
+            }
+
+            if (IsReflect) // add volumetric cell triangles
+            {
+              aNbVolmPrimitives += aFaceNodes.Length() - 2;
+            }
+          }
+        }
+      }
+      else if (aType == MeshVS_ET_Link)
+      {
+        if (anEdgeOn)
+        {
+          aNbLinkPrimitives += aNbNodes - 1; // add link segments
+        }
+      }
+      else if (aType == MeshVS_ET_Face)
+      {
+        if (anEdgeOn)
+        {
+          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)
+
+    Handle (Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles (
+     (aNbFacePrimitives + aNbVolmPrimitives) * 3, 0, IsReflect );
     Standard_Boolean IsPolyG = Standard_False;
 
-    Handle (Graphic3d_ArrayOfPolylines) aPolyLArr = new Graphic3d_ArrayOfPolylines
-      ( 2*aSize, aSize );
+    Handle (Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2);
+    Handle (Graphic3d_ArrayOfSegments) aLinkSegments = new Graphic3d_ArrayOfSegments (aNbLinkPrimitives * 2);
     Standard_Boolean IsPolyL = Standard_False;
 
     // OCC20644 NOTE: aColIter.Key() color is then scaled by TelUpdateMaterial() in OpenGl_attri.c
     // using the material reflection coefficients. This affects the visual result.
-    Handle(Graphic3d_AspectFillArea3d) anAsp =
+    Handle(Graphic3d_AspectFillArea3d) aFillAspect =
       new Graphic3d_AspectFillArea3d ( Aspect_IS_SOLID, aColIter.Key(), anEdgeColor,
                                        anEdgeType, anEdgeWidth, aMaterial[0], aMaterial[1] );
 
-    Handle(Graphic3d_AspectLine3d) anLAsp =
+    Handle(Graphic3d_AspectLine3d) aLinkAspect =
       new Graphic3d_AspectLine3d ( aColIter.Key(), aLineType, aLineWidth );
 
-    anAsp->SetDistinguishOff ();
-    anAsp->SetInteriorColor ( aColIter.Key() );
+    Handle(Graphic3d_AspectLine3d) anEdgeAspect =
+      new Graphic3d_AspectLine3d ( anEdgeColor, anEdgeType, anEdgeWidth );
+
+    aFillAspect->SetDistinguishOff ();
+    aFillAspect->SetInteriorColor ( aColIter.Key() );
     if (anEdgeOn)
-      anAsp->SetEdgeOn();
+      aFillAspect->SetEdgeOn();
     else
-      anAsp->SetEdgeOff();
+      aFillAspect->SetEdgeOff();
 
-    for( it.Reset(); it.More(); it.Next() )
+    for (it.Reset(); it.More(); it.Next())
     {
       Standard_Integer aKey = it.Key();
-      if( aColIter.Value().Contains( aKey ) )
+      
+      if (aColIter.Value().Contains (aKey))
       {
-        if ( !aSource->GetGeom  ( aKey, Standard_True, aCoords, NbNodes, aType ) )
+        if (!aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType))
           continue;
-
-        if( aType == MeshVS_ET_Face )
-        {
-          aPolyGArr->AddBound ( NbNodes );
-          if( IsExcludingOn() )
-            IDsToExclude.Add( aKey );
-        }
-        else if( aType == MeshVS_ET_Link )
+        
+        if (aType != MeshVS_ET_Face && aType != MeshVS_ET_Link && aType != MeshVS_ET_Volume)
         {
-          aPolyLArr->AddBound ( NbNodes );
-          if( IsExcludingOn() )
-            IDsToExclude.Add( aKey );
+          aCustomElements.Add (aKey);
+          continue;
         }
-        else if( aType == MeshVS_ET_Volume )
+        
+        if (IsExcludingOn())
+          IDsToExclude.Add (aKey);
+          
+        if (aType == MeshVS_ET_Volume)
         {
-          if( IsExcludingOn() )
-            IDsToExclude.Add( aKey );
-          if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
+          if (!aSource->Get3DGeom (aKey, NbNodes, aTopo))
           {
-            MeshVS_MeshPrsBuilder::AddVolumePrs( aTopo, aCoords, NbNodes, aPolyGArr, IsReflect, Standard_False, Standard_False, 1.0 );
-            IsPolyG = Standard_True;
-          }
-          else
             continue;
+          }
+          
+          MeshVS_MeshPrsBuilder::AddVolumePrs (aTopo, aCoords,
+            NbNodes, aFaceTriangles, IsReflect, Standard_False, Standard_False, 1.0);
+
+          if (anEdgeOn)
+          {
+            MeshVS_MeshPrsBuilder::AddVolumePrs (aTopo, aCoords,
+              NbNodes, anEdgeSegments, IsReflect, Standard_False, Standard_False, 1.0);
+          }
+
+          IsPolyG = Standard_True;
         }
-        else
+        else if (aType == MeshVS_ET_Face)
         {
-          aCustomElements.Add( aKey );
-          continue;
-        }
+          // Preparing normals
+          Handle(TColStd_HArray1OfReal) aNormals;
+          Standard_Boolean aHasNormals = IsReflect && aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals);
 
-        // Preparing normal(s) to show reflections if requested
-        Handle(TColStd_HArray1OfReal) aNormals;
-        Standard_Boolean hasNormals = IsReflect && aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals );
+          for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx)
+          {
+            for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx)
+            {
+              if (IsReflect)
+              {
+                aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1),
+                                           aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2),
+                                           aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3),
+                                           aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1) : 0.0,
+                                           aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2) : 0.0,
+                                           aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3) : 1.0);
+              }
+              else
+              {
+                aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1),
+                                           aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2),
+                                           aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3));
+              }
+            }
+          }
 
-        // Adding vertices (with normals if necessary)
-        for ( i=1; i<=NbNodes; i++ )
-          if ( aType == MeshVS_ET_Face )
+          if (anEdgeOn)
           {
-            if ( IsReflect )
+            for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx)
             {
-              hasNormals ? aPolyGArr->AddVertex ( aCoords(3 * i - 2), 
-                                                  aCoords(3 * i - 1), 
-                                                  aCoords(3 * i    ),
-                                                  aNormals->Value(3 * i - 2), 
-                                                  aNormals->Value(3 * i - 1), 
-                                                  aNormals->Value(3 * i    ) ) :
-                           aPolyGArr->AddVertex ( aCoords(3 * i - 2), 
-                                                  aCoords(3 * i - 1), 
-                                                  aCoords(3 * i    ),
-                                                  0., 
-                                                  0., 
-                                                  1. );
+              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));
             }
-            else
-              aPolyGArr->AddVertex ( aCoords(3 * i - 2), 
-                                     aCoords(3 * i - 1), 
-                                     aCoords(3 * i    ) );
-            IsPolyG = Standard_True;
           }
-          else if ( aType == MeshVS_ET_Link )
+
+          IsPolyG = Standard_True;
+        }
+        else if (aType == MeshVS_ET_Link)
+        {
+          for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 1; ++aNodeIdx)
           {
-            aPolyLArr->AddVertex ( aCoords(3*i-2), aCoords(3*i-1), aCoords(3*i) );
+            const Standard_Integer aNextIdx = aNodeIdx + 1;
+
+            aLinkSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
+                                      aCoords (3 * aNodeIdx + 2),
+                                      aCoords (3 * aNodeIdx + 3));
+
+            aLinkSegments->AddVertex (aCoords (3 * aNextIdx + 1),
+                                      aCoords (3 * aNextIdx + 2),
+                                      aCoords (3 * aNextIdx + 3));
+
             IsPolyL = Standard_True;
           }
+        }
       }
     }
 
-    if ( IsPolyG )
+    if (IsPolyG)
     {
-      aGGroup->SetPrimitivesAspect ( anAsp );
-      aGGroup->AddPrimitiveArray ( aPolyGArr );
+      aFillAspect->SetEdgeOff();
+      aGGroup->SetPrimitivesAspect (aFillAspect);
+      aGGroup->AddPrimitiveArray (aFaceTriangles);
+      
+      if (anEdgeOn)
+      {
+        aFillAspect->SetEdgeOff();
+        aSGroup->AddPrimitiveArray (anEdgeSegments);
+        aSGroup->SetGroupPrimitivesAspect (anEdgeAspect);
+      }
     }
-    if ( IsPolyL )
+    if (IsPolyL)
     {
-      anAsp->SetEdgeOff();
-      aLGroup->SetPrimitivesAspect ( anAsp );
-      aLGroup->SetPrimitivesAspect ( anLAsp );
-      aLGroup->AddPrimitiveArray ( aPolyLArr );
+      aFillAspect->SetEdgeOff();
+      aLGroup->SetPrimitivesAspect (aFillAspect);
+      aLGroup->SetPrimitivesAspect (aLinkAspect);
+      aLGroup->AddPrimitiveArray (aLinkSegments);
       if (anEdgeOn)
-        anAsp->SetEdgeOn();
+        aFillAspect->SetEdgeOn();
       else
-        anAsp->SetEdgeOff();
+        aFillAspect->SetEdgeOff();
     }
 
-    if( !aCustomElements.IsEmpty() )
-      CustomBuild( Prs, aCustomElements, IDsToExclude, DisplayMode );
+    if (!aCustomElements.IsEmpty())
+      CustomBuild(Prs, aCustomElements, IDsToExclude, DisplayMode);
   }
 
   Graphic3d_MaterialAspect aMaterial2[2];
-  for ( i=0; i<2; i++ )
+  for (Standard_Integer i = 0; i < 2; i++)
   {
     // OCC20644 "plastic" is most suitable here, as it is "non-physic"
     // so TelUpdateMaterial() from OpenGl_attri.c uses the interior
@@ -422,13 +521,42 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)&
   {
     Prs3d_Root::NewGroup ( Prs );
     Handle ( Graphic3d_Group ) aGroup2 = Prs3d_Root::CurrentGroup ( Prs );
+    Prs3d_Root::NewGroup ( Prs );
+    Handle ( Graphic3d_Group ) aGroup3 = Prs3d_Root::CurrentGroup ( Prs );
 
     Standard_Integer aSize = aColIter2.Value().Extent();
     if ( aSize<=0 )
       continue;
 
-    Handle (Graphic3d_ArrayOfPolygons) aPolyArr = new Graphic3d_ArrayOfPolygons
-      ( aMaxFaceNodes*aSize, aSize, 0, IsReflect );
+    Standard_Integer aNbFacePrimitives = 0;
+    Standard_Integer aNbEdgePrimitives = 0;
+    
+    for (it.Reset(); it.More(); it.Next())
+    {
+      Standard_Integer aNbNodes = 0;
+
+      if (!aColIter2.Value().Contains (it.Key()))
+        continue;
+
+      if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType))
+        continue;
+
+      if ( aType == MeshVS_ET_Face && aNbNodes > 0 )
+      {
+        if (anEdgeOn)
+        {
+          aNbEdgePrimitives += aNbNodes; // add edge segments
+        }
+
+        aNbFacePrimitives += aNbNodes - 2; // add face triangles
+      }
+    }
+
+    Handle (Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles
+      (aNbFacePrimitives * 3, 0, IsReflect);
+
+    Handle (Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments
+      (aNbEdgePrimitives * 2);
 
     MeshVS_TwoColors aTC = aColIter2.Key();
     Quantity_Color aMyIntColor, aMyBackColor;
@@ -442,12 +570,13 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)&
     anAsp->SetDistinguishOn ();
     anAsp->SetInteriorColor ( aMyIntColor );
     anAsp->SetBackInteriorColor ( aMyBackColor );
-    if (anEdgeOn)
+    /*if (anEdgeOn)
       anAsp->SetEdgeOn();
     else
-      anAsp->SetEdgeOff();
+      anAsp->SetEdgeOff();*/
 
-    aGroup2->SetPrimitivesAspect ( anAsp );
+    Handle(Graphic3d_AspectLine3d) anEdgeAspect =
+      new Graphic3d_AspectLine3d (anEdgeColor, anEdgeType, anEdgeWidth);
 
     for( it.Reset(); it.More(); it.Next() )
     {
@@ -460,43 +589,60 @@ void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)&
         if( IsExcludingOn() )
           IDsToExclude.Add( aKey );
 
-        if ( aType == MeshVS_ET_Face && NbNodes > 0 )
+        if (aType == MeshVS_ET_Face && NbNodes > 0)
         {
           // Preparing normal(s) to show reflections if requested
           Handle(TColStd_HArray1OfReal) aNormals;
           // OCC21720 Always passing normals to OpenGL to make materials work
           // For OpenGL: "No normals" -> "No lighting" -> "no materials taken into account"
-          Standard_Boolean hasNormals = /*IsReflect &&*/
-            aSource->GetNormalsByElement( aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals );
+          Standard_Boolean aHasNormals = /*IsReflect &&*/
+            aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals);
 
-          aPolyArr->AddBound ( NbNodes );
+          for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx)
+          {
+            for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx)
+            {
+              if (IsReflect)
+              {
+                aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1),
+                                           aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2),
+                                           aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3),
+                                           aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1) : 0.0,
+                                           aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2) : 0.0,
+                                           aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3) : 1.0);
+              }
+              else
+              {
+                aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1),
+                                           aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2),
+                                           aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3));
+              }
+            }
+          }
 
-          for ( i=1; i<=NbNodes; i++ )
+          if (anEdgeOn)
           {
-            if ( IsReflect )
+            for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx)
             {
-              hasNormals ? aPolyArr->AddVertex ( aCoords(3 * i - 2), 
-                                                 aCoords(3 * i - 1), 
-                                                 aCoords(3 * i    ),
-                                                 aNormals->Value(3 * i - 2), 
-                                                 aNormals->Value(3 * i - 1), 
-                                                 aNormals->Value(3 * i    ) ) :
-                           aPolyArr->AddVertex ( aCoords(3 * i - 2), 
-                                                 aCoords(3 * i - 1), 
-                                                 aCoords(3 * i    ),
-                                                 0., 
-                                                 0., 
-                                                 1. );
+              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));
             }
-            else
-              aPolyArr->AddVertex ( aCoords(3*i-2), 
-                                    aCoords(3*i-1), 
-                                    aCoords(3*i  ) );
           }
         }
       }
     }
-    aGroup2->AddPrimitiveArray ( aPolyArr );
+
+    aGroup2->AddPrimitiveArray (aFaceTriangles);
+    aGroup2->SetGroupPrimitivesAspect (anAsp);
+    aGroup3->AddPrimitiveArray (anEdgeSegments);
+    aGroup3->SetGroupPrimitivesAspect (anEdgeAspect);
   }
 }
 
index 50c3ec2..6cb0dc2 100644 (file)
@@ -37,8 +37,10 @@ uses
   AspectMarker3d             from Graphic3d,
   Array1OfReal               from TColStd,
   ArrayOfPolylines           from Graphic3d,
+  ArrayOfSegments            from Graphic3d,
   ArrayOfPolygons            from Graphic3d,
   ArrayOfPrimitives          from Graphic3d,
+  ArrayOfTriangles           from Graphic3d,
   PackedMapOfInteger         from TColStd
 
 is
@@ -76,29 +78,30 @@ is
        ---Purpose: Builds presentation of hilighted entity
 
   AddLinkPrs      ( me; theCoords    : Array1OfReal from TColStd;
-                        theLines     : ArrayOfPolylines from Graphic3d;
+                        theLines     : ArrayOfSegments from Graphic3d;
                         IsShrinked   : Boolean;
                         ShrinkCoef   : Real
                   )  is protected;
        ---Purpose: Add to array of polylines some lines representing link
 
-  AddFaceWirePrs      ( me; theCoords : Array1OfReal from TColStd;
-                        NbNodes       : Integer;
-                        theLines      : ArrayOfPolylines from Graphic3d;
-                        IsShrinked    : Boolean;
-                        ShrinkCoef    : Real
+  AddFaceWirePrs      ( me;
+                        theCoords        : Array1OfReal from TColStd;
+                        theNbNodes       : Integer;
+                        theLines         : ArrayOfSegments from Graphic3d;
+                        theIsShrinked    : Boolean;
+                        theShrinkingCoef : Real
                       )  is protected;
-    ---Purpose: Add to array of polylines some lines representing face's wire
-
-  AddFaceSolidPrs     ( me; ID              : Integer;
-                        theCoords           : Array1OfReal from TColStd;
-                        NbNodes             : Integer;
-                        MaxNodes            : Integer;
-                        thePolygons         : ArrayOfPolygons from Graphic3d;
-                        IsReflected         : Boolean;
-                        IsShrinked          : Boolean;
-                        ShrinkCoef          : Real; 
-                       IsMeshSmoothShading : Boolean
+    ---Purpose: Add to array of segments representing face's wire
+
+  AddFaceSolidPrs     ( me; ID                 : Integer;
+                        theCoords              : Array1OfReal from TColStd;
+                        theNbNodes             : Integer;
+                        theMaxNodes            : Integer;
+                        theTriangles           : ArrayOfTriangles from Graphic3d;
+                        theIsReflected         : Boolean;
+                        theIsShrinked          : Boolean;
+                        theShrinkCoef          : Real;
+                        theIsMeshSmoothShading : Boolean
                       )  is protected;
     ---Purpose: Add to array of polygons a polygon representing face
 
@@ -120,10 +123,10 @@ is
     ---Purpose: Calculate how many polygons or polylines are necessary to draw passed topology
 
   DrawArrays      ( me; Prs                : Presentation from Prs3d;
-                        thePolygons        : ArrayOfPolygons from Graphic3d;
-                        theLines           : ArrayOfPolylines from Graphic3d;
-                        theLinkLines       : ArrayOfPolylines from Graphic3d;
-                        theVolumesInShad   : ArrayOfPolygons from Graphic3d;
+                        thePolygons        : ArrayOfPrimitives from Graphic3d;
+                        theLines           : ArrayOfPrimitives from Graphic3d;
+                        theLinkLines       : ArrayOfPrimitives from Graphic3d;
+                        theVolumesInShad   : ArrayOfPrimitives from Graphic3d;
                         IsPolygonsEdgesOff : Boolean;
                         IsSelected         : Boolean;
                         theFillAsp         : AspectFillArea3d from Graphic3d;
index c4c748c..a3edb3b 100644 (file)
@@ -24,6 +24,7 @@
 #include <Graphic3d_AspectFillArea3d.hxx>
 #include <Graphic3d_AspectMarker3d.hxx>
 #include <Graphic3d_ArrayOfPolygons.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
 #include <Graphic3d_ArrayOfSegments.hxx>
 #include <Graphic3d_ArrayOfPoints.hxx>
 #include <Graphic3d_ArrayOfPolylines.hxx>
@@ -37,6 +38,7 @@
 #include <TColStd_SequenceOfInteger.hxx>
 #include <TColStd_PackedMapOfInteger.hxx>
 #include <TColStd_HPackedMapOfInteger.hxx>
+#include <TColStd_MapOfInteger.hxx>
 
 #include <Quantity_NameOfColor.hxx>
 #include <Aspect_InteriorStyle.hxx>
 #include <MeshVS_DrawerAttribute.hxx>
 #include <MeshVS_MapOfTwoNodes.hxx>
 #include <MeshVS_Buffer.hxx>
+#include <MeshVS_SymmetricPairHasher.hxx>
+
+#include <NCollection_Map.hxx>
+#include <NCollection_Vector.hxx>
 
 //================================================================
 // Function : Constructor MeshVS_MeshPrsBuilder
@@ -120,7 +126,7 @@ void MeshVS_MeshPrsBuilder::BuildNodes ( const Handle(Prs3d_Presentation)& Prs,
   anIDs.Assign( IDs );
   if ( !HasSelectFlag && !HasHilightFlag )
   {
-    // subtract the hidden nodes and ids to exclude (to minimise allocated memory)
+    // subtract the hidden nodes and ids to exclude (to minimize allocated memory)
     Handle(TColStd_HPackedMapOfInteger) aHiddenNodes = myParentMesh->GetHiddenNodes();
     if ( !aHiddenNodes.IsNull() )
       anIDs.Subtract( aHiddenNodes->Map() );
@@ -164,9 +170,9 @@ void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs
                                            TColStd_PackedMapOfInteger& IDsToExclude,
                                            const Standard_Integer DisplayMode ) const
 {
-  Standard_Integer maxnodes;   
+  Standard_Integer maxnodes;
 
-  Handle (MeshVS_DataSource) aSource = GetDataSource();
+  Handle(MeshVS_DataSource) aSource = GetDataSource();
   if ( aSource.IsNull() )
     return;
 
@@ -200,7 +206,7 @@ void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs
   IsReflect      = ( IsMeshReflect && !HasHilightFlag );
   aDrawer->GetBoolean  ( MeshVS_DA_SmoothShading, IsMeshSmoothShading );
 
-  // display mode for hilighted prs of groups
+  // display mode for highlighted prs of groups
   IsShrink       = ( IsShrink && !HasHilightFlag );
   IsShading      = ( IsShading || HasHilightFlag );
 
@@ -221,14 +227,7 @@ void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs
   Standard_Boolean IsOverlapControl =
     !IsMeshAllowOverlap && ( IsWireFrame || IsShading ) && !HasSelectFlag;
 
-  Handle (Graphic3d_ArrayOfPolygons)  aPolygons, aVolumes;
-  Handle (Graphic3d_ArrayOfPolylines) aPolylines, aLinkPolylines;
-
-  Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0,
-                   PolylineVerticesFor3D = 0, PolylineBoundsFor3D = 0,
-                   NbNodes;
-    
-  // 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();
@@ -238,180 +237,276 @@ void MeshVS_MeshPrsBuilder::BuildElements( const Handle(Prs3d_Presentation)& Prs
 
   Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
   TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
-  for( ; it.More(); it.Next() )
+
+  Standard_Boolean showEdges = Standard_True;
+  aDrawer->GetBoolean( MeshVS_DA_ShowEdges, showEdges );
+
+  showEdges = IsWireFrame || showEdges;
+
+  Standard_Integer* aNodesBuf  = (Standard_Integer*) alloca (maxnodes * sizeof (Standard_Integer));
+  Standard_Real*    aCoordsBuf = (Standard_Real*)    alloca (3 * maxnodes * sizeof (Standard_Real));
+
+  TColStd_Array1OfInteger aNodes  (*aNodesBuf, 1, maxnodes);
+  TColStd_Array1OfReal    aCoords (*aCoordsBuf, 1, 3 * maxnodes);
+
+  Standard_Integer aNbFacePrimitives = 0;
+  Standard_Integer aNbVolmPrimitives = 0;
+  Standard_Integer aNbEdgePrimitives = 0;
+  Standard_Integer aNbLinkPrimitives = 0;
+
+  MeshVS_EntityType aType;
+
+  for (it.Reset(); it.More(); it.Next())
   {
-    Standard_Integer aKey = it.Key();
-    if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
+    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);
+          
+          if (showEdges) // add edge segments
+          {
+            aNbEdgePrimitives += aFaceNodes.Length();
+          }
+          
+          if (IsShading || IsShrink) // add volumetric cell triangles
+          {
+            if (!HasSelectFlag)
+              aNbVolmPrimitives += aFaceNodes.Length() - 2;
+          }
+        }
+      }
+    }
+    else if (aType == MeshVS_ET_Link)
+    {
+      if (showEdges)
+      {
+        aNbLinkPrimitives += 1; // add link segment
+      }
+    }
+    else if (aType == MeshVS_ET_Face)
     {
-      if( !HasSelectFlag )
-        HowManyPrimitives( aTopo, Standard_True,  HasSelectFlag, NbNodes,
-                           PolygonVerticesFor3D, PolygonBoundsFor3D );      
-      HowManyPrimitives( aTopo, Standard_False, HasSelectFlag, NbNodes,
-                         PolylineVerticesFor3D, PolylineBoundsFor3D );
+      if (showEdges)
+      {
+        aNbEdgePrimitives += aNbNodes; // add edge segments
+      }
+
+      if (!IsOverlapControl || IsShading)
+      {
+        if ((IsShading || IsShrink) && !HasSelectFlag)
+        {
+          aNbFacePrimitives += aNbNodes - 2; // add face triangles
+        }
+      }
     }
   }
 
-  Standard_Integer Extent = anIDs.Extent();
+  // 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)
+  Handle (Graphic3d_ArrayOfTriangles) aVolmTriangles =
+    new Graphic3d_ArrayOfTriangles (aNbVolmPrimitives * 3, 0, IsReflect);
+  Handle (Graphic3d_ArrayOfTriangles) aFaceTriangles =
+    new Graphic3d_ArrayOfTriangles (aNbFacePrimitives * 3, 0, IsReflect);
 
-  if ( IsReflect )
-  {
-    aPolygons = new Graphic3d_ArrayOfPolygons
-      ( maxnodes*Extent, Extent, 0, Standard_True );
-    aVolumes = new Graphic3d_ArrayOfPolygons
-      ( PolygonVerticesFor3D, PolygonBoundsFor3D, 0, Standard_True );
-  }
-  else
+  Handle (Graphic3d_ArrayOfSegments) aLinkSegments;
+  Handle (Graphic3d_ArrayOfSegments) aEdgeSegments;
+
+  if (showEdges)
   {
-    aPolygons = new Graphic3d_ArrayOfPolygons( maxnodes*Extent, Extent );
-    aVolumes = new Graphic3d_ArrayOfPolygons ( PolygonVerticesFor3D, PolygonBoundsFor3D );
+    aLinkSegments = new Graphic3d_ArrayOfSegments (aNbLinkPrimitives * 2);
+    aEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2);
   }
 
   Standard_Integer howMany = 1;
   if ( IsOverlapControl )
     howMany = 2;
 
-  Standard_Boolean showEdges = Standard_True;
-  aDrawer->GetBoolean( MeshVS_DA_ShowEdges, showEdges );
-
-  showEdges = IsWireFrame || showEdges;
-  if ( showEdges )
-  {
-    aPolylines = new Graphic3d_ArrayOfPolylines ( ( maxnodes+1 )*Extent + PolylineVerticesFor3D,
-                                                  howMany * Extent + PolylineBoundsFor3D );
-    aLinkPolylines = new Graphic3d_ArrayOfPolylines ( 2*Extent, Extent );
-  }
-
-  MeshVS_Buffer aCoordsBuf (3*maxnodes*sizeof(Standard_Real));
-  TColStd_Array1OfReal aCoords( aCoordsBuf, 1, 3*maxnodes );  
-  MeshVS_EntityType aType;
-
   TColStd_PackedMapOfInteger aCustomElements;
 
   Quantity_Color       anOldEdgeColor;
+  Quantity_Color       anEdgeColor;
+  Quantity_Color       anIntColor;
   Aspect_InteriorStyle anIntType;
-  Quantity_Color       anIntColor, anEdgeColor;
   Aspect_TypeOfLine    aLine;
   Standard_Real        aWidth;
 
-  MeshVS_TwoNodes aTwoNodes;
-  aFill->Values ( anIntType, anIntColor, anEdgeColor, aLine, aWidth );
+  aFill->Values (anIntType, anIntColor, anEdgeColor, aLine, aWidth);
   
   MeshVS_MapOfTwoNodes aLinkNodes;
-  if ( showEdges && IsOverlapControl )
-    // Forbid drawings of edges, which overlap with some links
-    for( it.Reset(); it.More(); it.Next() )
+  
+  // Forbid drawings of edges which overlap with some links
+  if (showEdges && IsOverlapControl)
+  {
+    for (it.Reset(); it.More(); it.Next())
     {
-      Standard_Integer aKey = it.Key();
-      if ( aSource->GetGeomType ( aKey, Standard_True, aType ) &&
-           aType == MeshVS_ET_Link )
+      if (aSource->GetGeomType (it.Key(), Standard_True, aType) && aType == MeshVS_ET_Link)
       {
-        MeshVS_Buffer aNodesBuf (maxnodes * sizeof(Standard_Integer));
-        TColStd_Array1OfInteger aNodes (aNodesBuf, 1, maxnodes);
-        Standard_Integer nbNodes;
-        if ( aSource->GetNodesByElement( aKey, aNodes, nbNodes ) &&
-             nbNodes == 2 )
+        Standard_Integer aNbNodes;
+
+        if (aSource->GetNodesByElement (it.Key(), aNodes, aNbNodes) && aNbNodes == 2)
         {
-          aTwoNodes.First = aNodes(1);
-          aTwoNodes.Second = aNodes(2);
-          aLinkNodes.Add ( aTwoNodes );
+          aLinkNodes.Add (MeshVS_TwoNodes (aNodes(1), aNodes(2)));
         }
       }
     }
+  }
+
+  NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aSegmentMap;
 
-  for( it.Reset(); it.More(); it.Next() )
+  for (it.Reset(); it.More(); it.Next())
   {
-    Standard_Integer aKey = it.Key();
+    const Standard_Integer aKey = it.Key();
 
-    if ( ! aSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ) )
+    Standard_Integer NbNodes;
+    if (!aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType))
       continue;
 
-    switch ( aType )
+    if (!aSource->GetNodesByElement (aKey, aNodes, NbNodes))
+      continue;
+
+    switch (aType)
     {
-      case MeshVS_ET_Volume :
-        if( IsExcludingOn() )
+      case MeshVS_ET_Volume:
+      {
+        if (IsExcludingOn())
           IDsToExclude.Add (aKey);
-        if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
+
+        if (aSource->Get3DGeom (aKey, NbNodes, aTopo))
         {
-          // !!! TO DO: Overlap control
-          // add wireframe presentation (draw edges for shading mode as well)
-          if ( showEdges )
-            AddVolumePrs ( aTopo, aCoords, NbNodes, aPolylines, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef );
-
-          // add shading presentation
-          if ( ( IsShading || IsShrink ) && !HasSelectFlag )
-            AddVolumePrs ( aTopo, aCoords, NbNodes, aVolumes, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef );
+          // Add wire-frame presentation (draw edges for shading mode as well)
+          if (showEdges)
+          {
+            AddVolumePrs (aTopo, aCoords, NbNodes,
+              aEdgeSegments, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef);
+          }
+
+          // Add shading presentation
+          if ((IsShading || IsShrink) && !HasSelectFlag)
+          {
+            AddVolumePrs (aTopo, aCoords, NbNodes,
+              aVolmTriangles, IsReflect, IsShrink, HasSelectFlag, aShrinkCoef);
+          }
         }
-        break;
+      }
+      break;
 
-      case MeshVS_ET_Link :
-        if( IsExcludingOn() )
+      case MeshVS_ET_Link:
+      {
+        if (IsExcludingOn())
           IDsToExclude.Add (aKey);
-        if ( showEdges )
-          AddLinkPrs ( aCoords, aLinkPolylines, IsShrink || HasSelectFlag, aShrinkCoef );
-        break;
 
-      case MeshVS_ET_Face :
-        if( IsExcludingOn() )
-          IDsToExclude.Add (aKey);
-        if ( showEdges && IsOverlapControl )
+        if (showEdges)
         {
-          MeshVS_Buffer aNodesBuf (NbNodes * sizeof(Standard_Integer));
-          TColStd_Array1OfInteger aNodes (aNodesBuf, 1, NbNodes);
-          if ( !aSource->GetNodesByElement( aKey, aNodes, NbNodes ) )
-            continue;
+          AddLinkPrs (aCoords, aLinkSegments, IsShrink || HasSelectFlag, aShrinkCoef);
+        }
+      }
+      break;
 
+      case MeshVS_ET_Face:
+      {
+        if (IsExcludingOn())
+          IDsToExclude.Add (aKey);
+
+        if (showEdges && IsOverlapControl)
+        {
           Standard_Integer Last = 0;
-          for ( Standard_Integer i=1; i<=NbNodes; i++ )
+
+          MeshVS_TwoNodes aTwoNodes (aNodes (1));
+
+          for (Standard_Integer i = 1; i <= NbNodes; ++i)
           {
-            if ( i==1 )
-              aTwoNodes.First = aNodes(i);
-            else
+            if (i > 1)
               aTwoNodes.First = aTwoNodes.Second;
 
-            aTwoNodes.Second = ( i<NbNodes ? aNodes(i+1) : aNodes(1) );
-            if ( aLinkNodes.Contains ( aTwoNodes ) )
+            aTwoNodes.Second = (i < NbNodes) ? aNodes (i+1) : aNodes (1);
+
+            if (aLinkNodes.Contains (aTwoNodes))
+            {
+              for (Standard_Integer aNodeIdx = Last + 1; aNodeIdx < i; ++aNodeIdx)
               {
-                aPolylines->AddBound ( i-Last );
-                for (Standard_Integer j = Last+1; j<=i; j++)
-                  aPolylines->AddVertex ( aCoords(3*j-2), aCoords(3*j-1), aCoords(3*j) );
-                Last = i;
+                const Standard_Integer aNextIdx = aNodeIdx + 1;
+
+                aEdgeSegments->AddVertex (
+                  aCoords (3 * aNodeIdx - 2), aCoords (3 * aNodeIdx - 1), aCoords (3 * aNodeIdx));
+                aEdgeSegments->AddVertex (
+                  aCoords (3 * aNextIdx - 2), aCoords (3 * aNextIdx - 1), aCoords (3 * aNextIdx));
               }
+
+              Last = i;
+            }
           }
-          if ( NbNodes-Last > 0 )
+
+          if (NbNodes - Last > 0)
           {
-            aPolylines->AddBound ( NbNodes-Last+1 );
-            for (Standard_Integer j = Last+1; j<=NbNodes; j++)
-              aPolylines->AddVertex ( aCoords(3*j-2), aCoords(3*j-1), aCoords(3*j) );
+            for (Standard_Integer aNodeIdx = Last; aNodeIdx < NbNodes; ++aNodeIdx)
+            {
+              const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes;
+              
+              const MeshVS_NodePair aSegment (aNodes (aNodeIdx + 1),
+                                              aNodes (aNextIdx + 1));
+
+              if (!aSegmentMap.Contains (aSegment))
+              {
+                aEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
+                                          aCoords (3 * aNodeIdx + 2),
+                                          aCoords (3 * aNodeIdx + 3));
+
+                aEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
+                                          aCoords (3 * aNextIdx + 2),
+                                          aCoords (3 * aNextIdx + 3));
 
-            aPolylines->AddVertex ( aCoords(1), aCoords(2), aCoords(3) );
+                aSegmentMap.Add (aSegment);
+              }
+            }
           }
         }
 
-        if ( !IsOverlapControl || IsShading )
+        if (!IsOverlapControl || IsShading)
         {
-          if ( !IsOverlapControl && showEdges )
-            AddFaceWirePrs(aCoords, NbNodes, aPolylines,
-                           IsShrink || HasSelectFlag, aShrinkCoef );
-          if ( ( IsShading || IsShrink ) && !HasSelectFlag )
-            AddFaceSolidPrs(aKey, aCoords, NbNodes, maxnodes, aPolygons,
-                            IsReflect, IsShrink || HasSelectFlag,
-                            aShrinkCoef, IsMeshSmoothShading );
+          if (!IsOverlapControl && showEdges)
+          {
+            AddFaceWirePrs (aCoords, NbNodes,
+              aEdgeSegments, IsShrink || HasSelectFlag, aShrinkCoef);
+          }
+
+          if ((IsShading || IsShrink) && !HasSelectFlag)
+          {
+            AddFaceSolidPrs (aKey, aCoords, NbNodes, maxnodes, aFaceTriangles, IsReflect,
+              IsShrink || HasSelectFlag, aShrinkCoef, IsMeshSmoothShading);
+          }
         }
-        break;
+      }
+      break;
 
       default:
-        aCustomElements.Add( aKey );
-        break;
+      {
+        aCustomElements.Add (aKey);
+      }
     }
   }
 
-  if ( IsShrink )
+  if (IsShrink)
   {
     anOldEdgeColor = anEdgeColor;
-    aFill->SetEdgeColor ( Quantity_NOC_BLACK );
+    aFill->SetEdgeColor (Quantity_NOC_BLACK);
   }
 
-  DrawArrays ( Prs, aPolygons, aPolylines, aLinkPolylines, aVolumes,
+  //std::cout << "Actual extents: " << std::endl
+  //  << "Face tris: " << aFaceTriangles->ItemNumber() << " from " << aNbFacePrimitives << std::endl
+  //  << "Volm tris: " << aVolmTriangles->ItemNumber()  << " from " << aNbVolmPrimitives << std::endl
+  //  << "Face segs: " << aEdgeSegments->ItemNumber()  << " from " << aNbEdgePrimitives << std::endl
+  //  << "Link segs: " << aLinkSegments->ItemNumber()  << " from " << aNbLinkPrimitives << std::endl;
+
+  DrawArrays ( Prs, aFaceTriangles, aEdgeSegments, aLinkSegments, aVolmTriangles,
     !showEdges, HasSelectFlag, aFill, aBeam );
 
   if ( !aCustomElements.IsEmpty() )
@@ -542,126 +637,186 @@ void MeshVS_MeshPrsBuilder::BuildHilightPrs ( const Handle(Prs3d_Presentation)&
 // Function : AddLinkPrs
 // Purpose  :
 //================================================================
-void MeshVS_MeshPrsBuilder::AddLinkPrs (const TColStd_Array1OfReal& theCoords,
-                                        const Handle(Graphic3d_ArrayOfPolylines)& theLines,
-                                        const Standard_Boolean IsShrinked,
-                                        const Standard_Real ShrinkCoef) const
+void MeshVS_MeshPrsBuilder::AddLinkPrs (const TColStd_Array1OfReal&              theCoords,
+                                        const Handle(Graphic3d_ArrayOfSegments)& theSegments,
+                                        const Standard_Boolean                   theIsShrinked,
+                                        const Standard_Real                      theShrinkCoef) const
 {
-  Standard_Real x1 = theCoords(1);
-  Standard_Real y1 = theCoords(2);
-  Standard_Real z1 = theCoords(3);
-  Standard_Real x2 = theCoords(4);
-  Standard_Real y2 = theCoords(5);
-  Standard_Real z2 = theCoords(6);
-  Standard_Real xG, yG, zG;
-
-  if ( IsShrinked )
+  Standard_Real aX1 = theCoords (1);
+  Standard_Real aY1 = theCoords (2);
+  Standard_Real aZ1 = theCoords (3);
+  Standard_Real aX2 = theCoords (4);
+  Standard_Real aY2 = theCoords (5);
+  Standard_Real aZ2 = theCoords (6);
+
+  if (theIsShrinked)
   {
-    xG = (x1+x2)/2.0;
-    yG = (y1+y2)/2.0;
-    zG = (z1+z2)/2.0;
-    x1 = (x1 - xG) * ShrinkCoef + xG;
-    x2 = 2.0*xG - x1;
-    y1 = (y1 - yG) * ShrinkCoef + yG;
-    y2 = 2.0*yG - y1;
-    z1 = (z1 - zG) * ShrinkCoef + zG;
-    z2 = 2.0*zG - z1;
+    const Standard_Real xG = (aX1 + aX2) * 0.5;
+    const Standard_Real yG = (aY1 + aY2) * 0.5;
+    const Standard_Real zG = (aZ1 + aZ2) * 0.5;
+
+    aX1 = (aX1 - xG) * theShrinkCoef + xG;
+    aY1 = (aY1 - yG) * theShrinkCoef + yG;
+    aZ1 = (aZ1 - zG) * theShrinkCoef + zG;
+
+    aX2 = 2.0 * xG - aX1;
+    aY2 = 2.0 * yG - aY1;
+    aZ2 = 2.0 * zG - aZ1;
   }
-  theLines->AddBound ( 2 );
-  theLines->AddVertex ( x1, y1, z1 );
-  theLines->AddVertex ( x2, y2, z2 );
+
+  theSegments->AddVertex (aX1, aY1, aZ1);
+  theSegments->AddVertex (aX2, aY2, aZ2);
 }
 
 //================================================================
 // Function : AddFaceWirePrs
 // Purpose  :
 //================================================================
-void MeshVS_MeshPrsBuilder::AddFaceWirePrs (const TColStd_Array1OfReal& theCoords,
-                                            const Standard_Integer NbNodes,
-                                            const Handle(Graphic3d_ArrayOfPolylines)& theLines,
-                                            const Standard_Boolean IsShrinked,
-                                            const Standard_Real ShrinkCoef) const
+void MeshVS_MeshPrsBuilder::AddFaceWirePrs (const TColStd_Array1OfReal&              theCoords,
+                                            const Standard_Integer                   theNbNodes,
+                                            const Handle(Graphic3d_ArrayOfSegments)& theSegments,
+                                            const Standard_Boolean                   theIsShrinked,
+                                            const Standard_Real                      theShrinkingCoef) const
 {
-  Standard_Real xG = 0., yG = 0., zG = 0., X, Y, Z, startX=0., startY=0., startZ=0.;
-  theLines->AddBound ( NbNodes+1 );
-  if ( IsShrinked )
-    CalculateCenter( theCoords, NbNodes, xG, yG, zG );
+  Standard_Real aCenterX = 0.0;
+  Standard_Real aCenterY = 0.0;
+  Standard_Real aCenterZ = 0.0;
 
-  for ( Standard_Integer k=1; k<=NbNodes; k++)
+  if (theIsShrinked)
   {
-    X = theCoords(3*k-2);
-    Y = theCoords(3*k-1);
-    Z = theCoords(3*k);
-    if ( IsShrinked )
-    {
-      X = (X - xG) * ShrinkCoef + xG;
-      Y = (Y - yG) * ShrinkCoef + yG;
-      Z = (Z - zG) * ShrinkCoef + zG;
-    }
-    if( k==1 )
+    CalculateCenter (theCoords, theNbNodes, aCenterX, aCenterY, aCenterZ);
+  }
+
+  NCollection_Vector<gp_XYZ> aNodes (theNbNodes);
+
+  for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
+  {
+    gp_XYZ aPnt (theCoords (3 * aNodeIdx + 1),
+                 theCoords (3 * aNodeIdx + 2),
+                 theCoords (3 * aNodeIdx + 3));
+
+    if (theIsShrinked)
     {
-      startX = X; startY = Y; startZ = Z;
+      aPnt.SetX ((aPnt.X() - aCenterX) * theShrinkingCoef + aCenterX);
+      aPnt.SetY ((aPnt.Y() - aCenterY) * theShrinkingCoef + aCenterY);
+      aPnt.SetZ ((aPnt.Z() - aCenterZ) * theShrinkingCoef + aCenterZ);
     }
-    theLines->AddVertex ( X, Y, Z );
+
+    aNodes.Append (aPnt);
+  }
+
+  for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
+  {
+    theSegments->AddVertex (aNodes.Value (aNodeIdx).X(),
+                            aNodes.Value (aNodeIdx).Y(),
+                            aNodes.Value (aNodeIdx).Z());
+
+    const Standard_Integer aNextIdx = (aNodeIdx + 1) % theNbNodes;
+
+    theSegments->AddVertex (aNodes.Value (aNextIdx).X(),
+                            aNodes.Value (aNextIdx).Y(),
+                            aNodes.Value (aNextIdx).Z());
   }
-  theLines->AddVertex( startX, startY, startZ );
 }
 
 //================================================================
 // Function : AddFaceSolidPrs
 // Purpose  :
 //================================================================
-void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer ID,
-                                             const TColStd_Array1OfReal& theCoords,
-                                             const Standard_Integer NbNodes,
-                                             const Standard_Integer MaxNodes,
-                                             const Handle(Graphic3d_ArrayOfPolygons)& thePolygons,
-                                             const Standard_Boolean IsReflected,
-                                             const Standard_Boolean IsShrinked,
-                                             const Standard_Real ShrinkCoef,
-                                             const Standard_Boolean IsMeshSmoothShading) const
+void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer                    theID,
+                                             const TColStd_Array1OfReal&               theCoords,
+                                             const Standard_Integer                    theNbNodes,
+                                             const Standard_Integer                    theMaxNodes,
+                                             const Handle(Graphic3d_ArrayOfTriangles)& theTriangles,
+                                             const Standard_Boolean                    theIsShaded,
+                                             const Standard_Boolean                    theIsShrinked,
+                                             const Standard_Real                       theShrinkingCoef,
+                                             const Standard_Boolean                    theIsSmoothShading) const
 {
-  Handle( MeshVS_DataSource ) aDS = myParentMesh->GetDataSource();
-  if ( aDS.IsNull() )
+  Handle(MeshVS_DataSource) aDataSource = myParentMesh->GetDataSource();
+
+  if (aDataSource.IsNull())
     return;
 
-  Standard_Real xG = 0., yG = 0., zG = 0., X, Y, Z, nx = 0., ny = 0., nz = 0.;
-  thePolygons->AddBound ( NbNodes );
-  if ( IsShrinked )
-    CalculateCenter( theCoords, NbNodes, xG, yG, zG );
+  Standard_Real aCenterX = 0.0;
+  Standard_Real aCenterY = 0.0;
+  Standard_Real aCenterZ = 0.0;
+  Standard_Real aNormalX = 0.0;
+  Standard_Real aNormalY = 0.0;
+  Standard_Real aNormalZ = 0.0;
 
-  Standard_Boolean allNormals = Standard_True;
-  Standard_Integer k;
+  if (theIsShrinked)
+  {
+    CalculateCenter (theCoords, theNbNodes, aCenterX, aCenterY, aCenterZ);
+  }
 
-  if( IsReflected )
+  NCollection_Vector<gp_XYZ> aVertexNormals (theMaxNodes);
+  
+  if (theIsShaded)
   {
-    if( IsMeshSmoothShading )
-      for( k=1; k<=NbNodes && allNormals; k++ )
-        allNormals = aDS->GetNodeNormal (k, ID, nx, ny, nz);
-    if( !IsMeshSmoothShading || !allNormals )
-      aDS->GetNormal( ID, MaxNodes, nx, ny, nz );
+    if (theIsSmoothShading)
+    {
+      for (Standard_Integer aNodeIdx = 1; aNodeIdx <= theNbNodes; ++aNodeIdx)
+      {
+        if (!aDataSource->GetNodeNormal (aNodeIdx, theID, aNormalX, aNormalY, aNormalZ))
+          break;
+
+        aVertexNormals.Append (gp_XYZ (aNormalX, aNormalY, aNormalZ));
+      }
+    }
+
+    if (!theIsSmoothShading || aVertexNormals.Size() != theNbNodes)
+    {
+      aDataSource->GetNormal (theID, theMaxNodes, aNormalX, aNormalY, aNormalZ);
+    }
   }
 
-  for ( k=1; k<=NbNodes; k++)
+  NCollection_Vector<gp_XYZ> aNodes (theMaxNodes);
+
+  for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes; ++aNodeIdx)
   {
-    X = theCoords(3*k-2);
-    Y = theCoords(3*k-1);
-    Z = theCoords(3*k);
-    if ( IsShrinked )
+    gp_XYZ aPnt (theCoords (3 * aNodeIdx + 1),
+                 theCoords (3 * aNodeIdx + 2),
+                 theCoords (3 * aNodeIdx + 3));
+
+    if (theIsShrinked)
     {
-      X = (X - xG) * ShrinkCoef + xG;
-      Y = (Y - yG) * ShrinkCoef + yG;
-      Z = (Z - zG) * ShrinkCoef + zG;
+      aPnt.SetX ((aPnt.X() - aCenterX) * theShrinkingCoef + aCenterX);
+      aPnt.SetY ((aPnt.Y() - aCenterY) * theShrinkingCoef + aCenterY);
+      aPnt.SetZ ((aPnt.Z() - aCenterZ) * theShrinkingCoef + aCenterZ);
     }
 
-    if ( IsReflected )
+    aNodes.Append (aPnt);
+  }
+
+  // Triangulate polygon
+  for (Standard_Integer aNodeIdx = 0; aNodeIdx < theNbNodes - 2; ++aNodeIdx)
+  {
+    for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx)
     {
-      if( IsMeshSmoothShading && allNormals )
-        aDS->GetNodeNormal (k, ID, nx, ny, nz);
-      thePolygons->AddVertex ( X, Y, Z, nx, ny, nz );
+      if (theIsShaded)
+      {
+        if (theIsSmoothShading && aVertexNormals.Size() == theNbNodes)
+        {
+          aNormalX = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X();
+          aNormalY = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y();
+          aNormalZ = aVertexNormals.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z();
+        }
+
+        theTriangles->AddVertex (aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(),
+                                 aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(),
+                                 aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z(),
+                                 aNormalX,
+                                 aNormalY,
+                                 aNormalZ);
+      }
+      else
+      {
+        theTriangles->AddVertex (aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).X(),
+                                 aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Y(),
+                                 aNodes.Value (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)).Z());
+      }
     }
-    else
-      thePolygons->AddVertex ( X, Y, Z );
   }
 }
 
@@ -669,171 +824,178 @@ void MeshVS_MeshPrsBuilder::AddFaceSolidPrs (const Standard_Integer ID,
 // Function : AddVolumePrs
 // Purpose  :
 //================================================================
-void MeshVS_MeshPrsBuilder::AddVolumePrs (const Handle( MeshVS_HArray1OfSequenceOfInteger )& Topo,
-                                          const TColStd_Array1OfReal& Nodes,
-                                          const Standard_Integer NbNodes,
-                                          const Handle( Graphic3d_ArrayOfPrimitives )& Array,
-                                          const Standard_Boolean IsReflected,
-                                          const Standard_Boolean IsShrinked,
-                                          const Standard_Boolean IsSelect,
-                                          const Standard_Real ShrinkCoef)
+void MeshVS_MeshPrsBuilder::AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& theTopo,
+                                          const TColStd_Array1OfReal&                      theNodes,
+                                          const Standard_Integer                           theNbNodes,
+                                          const Handle(Graphic3d_ArrayOfPrimitives)&       theArray,
+                                          const Standard_Boolean                           theIsShaded,
+                                          const Standard_Boolean                           theIsShrinked,
+                                          const Standard_Boolean                           theIsSelected,
+                                          const Standard_Real                              theShrinkCoef)
 {
-  Standard_Real c[3]; c[0] = c[1] = c[2] = 0.0;
-  Standard_Integer low = Nodes.Lower(), n=NbNodes;
+  Standard_Real aCenter[] = { 0.0, 0.0, 0.0 };
 
-  if( Topo.IsNull() || Array.IsNull() )
+  Standard_Integer aLow = theNodes.Lower();
+
+  if (theTopo.IsNull() || theArray.IsNull())
     return;
 
-  if( IsShrinked )
+  if (theIsShrinked)
   {
-    for( Standard_Integer i=0; i<3*n; i++ )
-      c[i%3] += Nodes.Value( low + i );
+    for (Standard_Integer aNodeIdx = 0; aNodeIdx < 3 * theNbNodes; ++aNodeIdx)
+    {
+      aCenter[aNodeIdx % 3] += theNodes.Value (aLow + aNodeIdx);
+    }
 
-    c[0] /= n;
-    c[1] /= n;
-    c[2] /= n;
+    aCenter[0] /= theNbNodes;
+    aCenter[1] /= theNbNodes;
+    aCenter[2] /= theNbNodes;
   }
 
-  Standard_Boolean IsPolygons = Array->IsKind( STANDARD_TYPE( Graphic3d_ArrayOfPolygons ) );
-  Standard_Real x[2], y[2], z[2];
-  Standard_Integer ind;
-  gp_Vec norm;  
+  Standard_Boolean aIsPolygons = theArray->IsKind (STANDARD_TYPE (Graphic3d_ArrayOfTriangles));
 
-  if( IsPolygons )
-  {    
-    for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ )
+  if (aIsPolygons)
+  {
+    for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
     {
-      const TColStd_SequenceOfInteger& aSeq = Topo->Value( i );
-      
-      Standard_Integer m = aSeq.Length();
-      Array->AddBound( m );
+      const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
+      const Standard_Integer aNbPolyNodes = aFaceNodes.Length();
       
-      norm.SetCoord( 0, 0, 0 );
-      if( IsReflected )
+      Standard_Real* aPolyNodesBuf = (Standard_Real*) alloca ((3 * aNbPolyNodes + 1) * sizeof (Standard_Real));
+      TColStd_Array1OfReal aPolyNodes (*aPolyNodesBuf, 0, 3 * aNbPolyNodes);
+
+      for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbPolyNodes; ++aNodeIdx)
       {
-        MeshVS_Buffer PolyNodesBuf (3*m*sizeof(Standard_Real));
-        TColStd_Array1OfReal PolyNodes( PolyNodesBuf, 0, 3*m );
-        PolyNodes.SetValue( 0, m );
-        for( Standard_Integer j=1; j<=m; j++ )
-        {          
-          ind = aSeq.Value( j );
-          PolyNodes.SetValue( 3*j-2, Nodes.Value( low+3*ind ) );
-          PolyNodes.SetValue( 3*j-1, Nodes.Value( low+3*ind+1 ) );
-          PolyNodes.SetValue( 3*j,   Nodes.Value( low+3*ind+2 ) );
+        Standard_Integer anIdx = aFaceNodes.Value (aNodeIdx + 1);
+
+        Standard_Real aX = theNodes.Value (aLow + 3 * anIdx + 0);
+        Standard_Real aY = theNodes.Value (aLow + 3 * anIdx + 1);
+        Standard_Real aZ = theNodes.Value (aLow + 3 * anIdx + 2);
+
+        if (theIsShrinked)
+        {
+          aX = aCenter[0] + theShrinkCoef * (aX - aCenter[0]);
+          aY = aCenter[1] + theShrinkCoef * (aY - aCenter[1]);
+          aZ = aCenter[2] + theShrinkCoef * (aZ - aCenter[2]);
         }
 
-        // compute normal
-        // if( !MeshVS_Tool::GetNormal( PolyNodes, norm ) )
-        //   norm.SetCoord( 0, 0, 0 );
-        MeshVS_Tool::GetAverageNormal( PolyNodes, norm );
+        aPolyNodes.SetValue (3 * aNodeIdx + 1, aX);
+        aPolyNodes.SetValue (3 * aNodeIdx + 2, aY);
+        aPolyNodes.SetValue (3 * aNodeIdx + 3, aZ);
       }
+      
+      gp_Vec aNorm;
 
-      Standard_Real nx = norm.X(), ny = norm.Y(), nz = norm.Z();
-       
-
-      for( Standard_Integer j=1; j<=m; j++ )
+      if (theIsShaded)
       {
-        ind = aSeq.Value( j );
-        x[0] = Nodes.Value( low + 3*ind   );
-        y[0] = Nodes.Value( low + 3*ind+1 );
-        z[0] = Nodes.Value( low + 3*ind+2 );
+        aPolyNodes.SetValue (0, aNbPolyNodes);
+        
+        if (!MeshVS_Tool::GetAverageNormal (aPolyNodes, aNorm))
+        {
+          aNorm.SetCoord (0.0, 0.0, 1.0);
+        }
+      }
 
-        if( IsShrinked )
+      for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbPolyNodes - 2; ++aNodeIdx) // triangulate polygon
+      {
+        for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle
         {
-          x[0] = c[0] + ShrinkCoef * ( x[0]-c[0] );
-          y[0] = c[1] + ShrinkCoef * ( y[0]-c[1] );
-          z[0] = c[2] + ShrinkCoef * ( z[0]-c[2] );
+          if (theIsShaded)
+          {
+            theArray->AddVertex (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),
+                                 aNorm.X(),
+                                 aNorm.Y(),
+                                 aNorm.Z());
+          }
+          else
+          {
+            theArray->AddVertex (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( IsReflected )
-          Array->AddVertex( x[0], y[0], z[0], nx, ny, nz );
-        else
-          Array->AddVertex( x[0], y[0], z[0] );
       }
     }
   }
-  else if( IsSelect )
+  else if (theIsSelected)
   {
-    for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ )
+    for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
     {
-      const TColStd_SequenceOfInteger& aSeq = Topo->Value( i );
-      Standard_Real pc[3]; pc[0] = pc[1] = pc[2] = 0;
-      Standard_Integer j,m;
-      for( j=1, m=aSeq.Length(); j<=m; j++ )
+      const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
+
+      Standard_Real aFaceCenter[] = { 0.0, 0.0, 0.0 };
+
+      for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aFaceNodes.Length(); ++aNodeIdx)
       {
-        ind = aSeq.Value( j );
-        for( Standard_Integer k=0; k<3; k++ )
-          pc[k] += Nodes.Value( low + 3*ind+k );
+        for (Standard_Integer aAxisIdx = 0; aAxisIdx < 3; ++aAxisIdx)
+        {
+          aFaceCenter[aAxisIdx] += theNodes.Value (aLow + 3 * aFaceNodes.Value (aNodeIdx) + aAxisIdx);
+        }
       }
-      pc[0] /= m;
-      pc[1] /= m;
-      pc[2] /= m;
 
-      Array->AddBound( m+1 );
-      for( j=1, m=aSeq.Length(); j<=m+1; j++ )
+      aFaceCenter[0] /= aFaceNodes.Length();
+      aFaceCenter[1] /= aFaceNodes.Length();
+      aFaceCenter[2] /= aFaceNodes.Length();
+
+      for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx)
       {
-        ind = aSeq.Value( (j-1)%m + 1 );
-        x[0] = Nodes.Value( low + 3*ind   );
-        y[0] = Nodes.Value( low + 3*ind+1 );
-        z[0] = Nodes.Value( low + 3*ind+2 );
-        x[0] = pc[0] + ShrinkCoef * ( x[0]-pc[0] );
-        y[0] = pc[1] + ShrinkCoef * ( y[0]-pc[1] );
-        z[0] = pc[2] + ShrinkCoef * ( z[0]-pc[2] );
-        Array->AddVertex( x[0], y[0], z[0] );
+        for (Standard_Integer aSubIdx = 0; aSubIdx < 2; ++aSubIdx) // add segment
+        {
+          Standard_Integer anIdx = aFaceNodes.Value ((aNodeIdx + aSubIdx) % aNbNodes + 1);
+
+          Standard_Real aX = theNodes.Value (aLow + 3 * anIdx + 0);
+          Standard_Real aY = theNodes.Value (aLow + 3 * anIdx + 1);
+          Standard_Real aZ = theNodes.Value (aLow + 3 * anIdx + 2);
+
+          theArray->AddVertex (aFaceCenter[0] + theShrinkCoef * (aX - aFaceCenter[0]),
+                               aFaceCenter[1] + theShrinkCoef * (aY - aFaceCenter[1]),
+                               aFaceCenter[2] + theShrinkCoef * (aZ - aFaceCenter[2]));
+        }
       }
     }
   }
   else
   {
-    Standard_Integer F, S=0, k;
+    // Find all pairs of nodes (edges) to draw (will be drawn only once)
+    NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aEdgeMap;
 
-    // Find all pairs of nodes (edges) to draw;
-    // map is used to ensure that each edge will be drawn only once
-    TColStd_PackedMapOfInteger aMap;
-    for( Standard_Integer i=Topo->Lower(), topoup=Topo->Upper(); i<=topoup; i++ )
+    for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
     {
-      const TColStd_SequenceOfInteger& aSeq = Topo->Value( i );
-      for( Standard_Integer j=1, m=aSeq.Length(); j<=m; j++ )
+      const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
+      
+      for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx)
       {
-        if( j==1 )
-          F = aSeq.Value( j );
-        else
-          F = S;
+        const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes;
 
-        S = j<m ? aSeq.Value( j+1 ) : aSeq.Value( 1 );
-
-        if( F<S )
-          aMap.Add( F + NbNodes * S );
-        else
-          aMap.Add( S + NbNodes * F );
+        aEdgeMap.Add (MeshVS_NodePair (aFaceNodes.Value (aNodeIdx + 1),
+                                       aFaceNodes.Value (aNextIdx + 1)));
       }
     }
 
-    // draw edges
-    TColStd_MapIteratorOfPackedMapOfInteger anIt( aMap );
-    for( ; anIt.More(); anIt.Next() )
+    // Draw edges
+    for(NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher>::Iterator anIt (aEdgeMap); anIt.More(); anIt.Next())
     {      
-      F = low + 3*(anIt.Key()%NbNodes);
-      S = low + 3*(anIt.Key()/NbNodes);
-
-      x[0] = Nodes.Value( F );
-      y[0] = Nodes.Value( F+1 );
-      z[0] = Nodes.Value( F+2 );
-      x[1] = Nodes.Value( S );
-      y[1] = Nodes.Value( S+1 );
-      z[1] = Nodes.Value( S+2 );
-
-      if( IsShrinked )
-        for( k=0; k<2; k++ )
+      const Standard_Integer anIdx1 = aLow + 3 * anIt.Key().first;
+      const Standard_Integer anIdx2 = aLow + 3 * anIt.Key().second;
+
+      Standard_Real aX[] = { theNodes.Value (anIdx1 + 0), theNodes.Value (anIdx2 + 0) };
+      Standard_Real aY[] = { theNodes.Value (anIdx1 + 1), theNodes.Value (anIdx2 + 1) };
+      Standard_Real aZ[] = { theNodes.Value (anIdx1 + 2), theNodes.Value (anIdx2 + 2) };
+
+      if (theIsShrinked)
+      {
+        for (Standard_Integer anAxisIdx = 0; anAxisIdx < 2; ++anAxisIdx)
         {
-          x[k] = c[0] + ShrinkCoef * ( x[k]-c[0] );
-          y[k] = c[1] + ShrinkCoef * ( y[k]-c[1] );
-          z[k] = c[2] + ShrinkCoef * ( z[k]-c[2] );
+          aX[anAxisIdx] = aCenter[0] + theShrinkCoef * (aX[anAxisIdx] - aCenter[0]);
+          aY[anAxisIdx] = aCenter[1] + theShrinkCoef * (aY[anAxisIdx] - aCenter[1]);
+          aZ[anAxisIdx] = aCenter[2] + theShrinkCoef * (aZ[anAxisIdx] - aCenter[2]);
         }
+      }
 
-      Array->AddBound( 2 );
-      Array->AddVertex( x[0], y[0], z[0] );
-      Array->AddVertex( x[1], y[1], z[1] );
+      theArray->AddVertex (aX[0], aY[0], aZ[0]);
+      theArray->AddVertex (aX[1], aY[1], aZ[1]);
     }
   }
 }
@@ -877,10 +1039,10 @@ void MeshVS_MeshPrsBuilder::HowManyPrimitives (const Handle(MeshVS_HArray1OfSequ
 // Purpose  :
 //================================================================
 void MeshVS_MeshPrsBuilder::DrawArrays( const Handle(Prs3d_Presentation)& Prs,
-                                        const Handle(Graphic3d_ArrayOfPolygons)& thePolygons,
-                                        const Handle(Graphic3d_ArrayOfPolylines)& theLines,
-                                        const Handle(Graphic3d_ArrayOfPolylines)& theLinkLines,
-                                        const Handle(Graphic3d_ArrayOfPolygons)& theVolumesInShad,
+                                        const Handle(Graphic3d_ArrayOfPrimitives)& thePolygons,
+                                        const Handle(Graphic3d_ArrayOfPrimitives)& theLines,
+                                        const Handle(Graphic3d_ArrayOfPrimitives)& theLinkLines,
+                                        const Handle(Graphic3d_ArrayOfPrimitives)& theVolumesInShad,
                                         const Standard_Boolean IsPolygonsEdgesOff,
                                         const Standard_Boolean IsSelected,
                                         const Handle(Graphic3d_AspectFillArea3d)& theFillAsp,
index 00981f4..eaa77ad 100644 (file)
@@ -35,17 +35,21 @@ uses
   Boolean                 from Standard,
   Integer                 from Standard,
 
-  DisplayModeFlags        from MeshVS,
-  Mesh                    from MeshVS,
-  MeshPtr                 from MeshVS,
-  DataSource              from MeshVS,
-  DataMapOfIntegerColor   from MeshVS,
-  BuilderPriority         from MeshVS,
-  SequenceOfColor         from Aspect,
-  Color                   from Quantity,
-  DataMapOfIntegerReal    from TColStd,
-  Texture2D               from Graphic3d,
-  PackedMapOfInteger      from TColStd
+  DisplayModeFlags           from MeshVS,
+  Mesh                       from MeshVS,
+  MeshPtr                    from MeshVS,
+  DataSource                 from MeshVS,
+  DataMapOfIntegerColor      from MeshVS,
+  BuilderPriority            from MeshVS,
+  HArray1OfSequenceOfInteger from MeshVS,
+  SequenceOfColor            from Aspect,
+  Color                      from Quantity,
+  Texture2D                  from Graphic3d,
+  ArrayOfPrimitives          from Graphic3d,
+  DataMapOfIntegerReal       from TColStd,
+  PackedMapOfInteger         from TColStd,
+  Array1OfInteger            from TColStd,
+  Array1OfReal               from TColStd
   
 is
 
@@ -123,6 +127,16 @@ is
        ---Purpose: Create texture in accordance with myTextureColorMap
   is static private;
        
+  AddVolumePrs ( me;
+                 theTopo        : HArray1OfSequenceOfInteger from MeshVS;
+                 theNodes       : Array1OfInteger from TColStd;
+                 theCoords      : Array1OfReal from TColStd;
+                 theArray       : ArrayOfPrimitives from Graphic3d;
+                 theIsShaded    : Boolean;
+                 theNbColors    : Integer;
+                 theNbTexColors : Integer;
+                 theColorRatio  : Real );
+    ---Purpose: Add to array polygons or polylines representing volume
 
 fields
   myNodeColorMap    : DataMapOfIntegerColor from MeshVS;
index 9609098..4d9f6c4 100644 (file)
@@ -22,6 +22,8 @@
 #include <Graphic3d_AspectLine3d.hxx>
 #include <Graphic3d_ArrayOfPolygons.hxx>
 #include <Graphic3d_ArrayOfPolylines.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
 #include <Graphic3d_Group.hxx>
 #include <Graphic3d_TextureParams.hxx>
 
@@ -45,6 +47,8 @@
 #include <MeshVS_MeshPrsBuilder.hxx>
 #include <MeshVS_HArray1OfSequenceOfInteger.hxx>
 #include <MeshVS_Buffer.hxx>
+#include <MeshVS_Tool.hxx>
+#include <MeshVS_SymmetricPairHasher.hxx>
 
 #include <gp_Pnt.hxx>
 #include <Image_PixMap.hxx>
@@ -56,6 +60,9 @@
 #include <Quantity_Array1OfColor.hxx>
 #include <Aspect_SequenceOfColor.hxx>
 
+#include <NCollection_Map.hxx>
+#include <NCollection_Vector.hxx>
+
 /*
   Class       : MeshVS_ImageTexture2D
   Description : Texture for nodal presentation
@@ -146,7 +153,7 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
        (!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();
@@ -223,10 +230,54 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
     ( 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();
@@ -235,204 +286,132 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
   // Prepare for scaling the incoming colors
   Standard_Real anColorRatio = aMaterial[0].Ambient();
 
-  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 (i = 1; i <= NbNodes && isValid; ++i)
+          isValid = myTextureCoords.IsBound (aNodes (i));
       }
       else
       {
-        for ( i = 1; i <= NbNodes && isValid; i++ )
-          isValid = GetColor ( aNodes( i ), aNColor );
+        for (i = 1; i <= NbNodes && isValid; ++i)
+          isValid = GetColor (aNodes (i), 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 ( ...
@@ -500,7 +479,8 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
   Handle(Graphic3d_Group) aGroup1 = Prs3d_Root::CurrentGroup ( Prs );
 
   aGroup1->SetPrimitivesAspect( anAsp );
-  aGroup1->AddPrimitiveArray( aCPolyArr );
+  aGroup1->AddPrimitiveArray( aFaceTriangles /*aCPolyArr*/ );
+  //aGroup1->AddPrimitiveArray( aCPolyArr );
 
   if (aShowEdges)
   {
@@ -511,12 +491,137 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
     anAsp->SetTextureMapOff();
     aGroup2->SetPrimitivesAspect( anAsp );
     aGroup2->SetPrimitivesAspect( anLAsp );
-    aGroup2->AddPrimitiveArray( aPolyL );
+    aGroup2->AddPrimitiveArray( anEdgeSegments );
     anAsp->SetEdgeOn();
   }
 }
 
 //================================================================
+// 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]);
+    }
+  }
+}
+
+//================================================================
 // Function : SetColors
 // Purpose  :
 //================================================================
diff --git a/src/MeshVS/MeshVS_SymmetricPairHasher.hxx b/src/MeshVS/MeshVS_SymmetricPairHasher.hxx
new file mode 100644 (file)
index 0000000..8fd6422
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _MeshVS_SymmetricPairHasher_HeaderFile
+#define _MeshVS_SymmetricPairHasher_HeaderFile
+
+#include <Standard_Type.hxx>
+
+typedef std::pair<Standard_Integer, Standard_Integer> MeshVS_NodePair;
+
+//! Provides symmetric hash methods pair of integers.
+struct MeshVS_SymmetricPairHasher
+{
+  static Standard_Integer HashCode (const MeshVS_NodePair& thePair, const Standard_Integer theMaxCode)
+  {
+    return ((thePair.first + thePair.second) & 0x7FFFFFFF) % theMaxCode + 1;
+  }
+
+  static Standard_Boolean IsEqual (const MeshVS_NodePair& thePair1, const MeshVS_NodePair& thePair2)
+  {
+    return (thePair1.first == thePair2.first && thePair1.second == thePair2.second)
+        || (thePair1.first == thePair2.second && thePair1.second == thePair2.first);
+  }
+};
+
+#endif // _MeshVS_SymmetricPairHasher_HeaderFile
\ No newline at end of file
index aa784f4..df24073 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <Graphic3d_ArrayOfPolylines.hxx>
 #include <Graphic3d_ArrayOfPolygons.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
 #include <Graphic3d_ArrayOfTriangleFans.hxx>
 #include <Graphic3d_MaterialAspect.hxx>
 #include <Graphic3d_AspectLine3d.hxx>
@@ -225,20 +227,13 @@ void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
     return;
 
   // polylines
-  Standard_Integer aNbVertices         = aNbVectors  * NB_VERTICES;
-  Standard_Integer aNbBounds           = aNbVectors  * NB_BOUNDS;
+  Standard_Integer aNbVertices = aNbVectors  * NB_VERTICES;
 
-  // fans
-  Standard_Integer aNbTriangleVertices = aNbVectors  * (NB_TRIANGLES + 2);
-  Standard_Integer aNbFans             = aNbVectors  * NB_TRIANGLES;
+  Handle(Graphic3d_ArrayOfPrimitives) aLineArray = new Graphic3d_ArrayOfSegments (aNbVertices);
+  Handle(Graphic3d_ArrayOfPrimitives) aArrowLineArray = new Graphic3d_ArrayOfSegments (aNbVertices);
 
-  Handle(Graphic3d_ArrayOfPrimitives) aLineArray =
-    new Graphic3d_ArrayOfPolylines(aNbVertices, aNbBounds);
-  Handle(Graphic3d_ArrayOfPrimitives) aArrowLineArray =
-    new Graphic3d_ArrayOfPolylines(aNbVertices, aNbBounds);
-
-  Handle(Graphic3d_ArrayOfTriangleFans) aTriangleArray =
-    new Graphic3d_ArrayOfTriangleFans(aNbTriangleVertices, aNbFans);
+  Handle(Graphic3d_ArrayOfPrimitives) aTriangleArray = new Graphic3d_ArrayOfSegments (
+    aNbVectors * 8 /* vertices per arrow */, aNbVectors * 12 /* segments per arrow */ * 2 /* indices per segment */);
 
   TColgp_Array1OfPnt anArrowPnt(1,8);
   Standard_Real k, b, aMaxValue, aMinValue, aValue, X, Y, Z;
@@ -261,7 +256,7 @@ void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
 
   TColStd_PackedMapOfInteger aCustomElements;
 
-  // 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 );
   if ( IsElement )
@@ -338,17 +333,10 @@ void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
 
   if ( !myIsSimplePrs )
   {
-    Graphic3d_MaterialAspect aMatAspect;
-    aMatAspect.SetAmbient( 1 );
-    aMatAspect.SetDiffuse( 0 );
-    aMatAspect.SetEmissive( 0 );
-    aMatAspect.SetShininess( 1 );
-    aMatAspect.SetSpecular( 0 );
-    Handle(Graphic3d_AspectFillArea3d) aFillAspect =
-      new Graphic3d_AspectFillArea3d (Aspect_IS_HOLLOW, aColor, aColor, Aspect_TOL_SOLID,
-                                      1., aMatAspect, aMatAspect );
-
-    aVGroup->SetPrimitivesAspect( aFillAspect );
+    Handle(Graphic3d_AspectLine3d) anArrowLinAspect =
+      new Graphic3d_AspectLine3d (aColor, Aspect_TOL_SOLID, mySimpleWidthPrm);
+
+    aVGroup->SetPrimitivesAspect( anArrowLinAspect );
     aVGroup->AddPrimitiveArray( aTriangleArray );
   }
   else
@@ -369,58 +357,68 @@ void MeshVS_VectorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
 // Purpose : Fill arrays of primitives for drawing force
 //=======================================================================
 void MeshVS_VectorPrsBuilder::DrawVector ( const gp_Trsf& theTrsf,
-                                           const Standard_Real Length,
-                                           const Standard_Real MaxLength,
-                                           const TColgp_Array1OfPnt& ArrowPoints,
-                                           const Handle(Graphic3d_ArrayOfPrimitives)& Lines,
-                                           const Handle(Graphic3d_ArrayOfPrimitives)& ArrowLines,
-                                           const Handle(Graphic3d_ArrayOfPrimitives)& Triangles) const
+                                           const Standard_Real theLength,
+                                           const Standard_Real theMaxLength,
+                                           const TColgp_Array1OfPnt& theArrowPoints,
+                                           const Handle(Graphic3d_ArrayOfPrimitives)& theLines,
+                                           const Handle(Graphic3d_ArrayOfPrimitives)& theArrowLines,
+                                           const Handle(Graphic3d_ArrayOfPrimitives)& theTriangles) const
 {
   const int PntNum = 8;
 
-  const Standard_Real aMinLength = MaxLength * ( 1 - mySimpleStartPrm );
-  const Standard_Real aLocalLength = ( !myIsSimplePrs || Length > aMinLength ? Length : aMinLength );
+  const Standard_Real aMinLength = theMaxLength * ( 1 - mySimpleStartPrm );
+  const Standard_Real aLocalLength = ( !myIsSimplePrs || theLength > aMinLength ? theLength : aMinLength );
   // draw line
   gp_Pnt aLinePnt[ 2 ] = { gp_Pnt( 0, 0, 0 ) , gp_Pnt( 0, 0, aLocalLength ) };
-  theTrsf.Transforms( aLinePnt[ 0 ].ChangeCoord() );
-  theTrsf.Transforms( aLinePnt[ 1 ].ChangeCoord() );
+  theTrsf.Transforms (aLinePnt[0].ChangeCoord());
+  theTrsf.Transforms (aLinePnt[1].ChangeCoord());
 
-  Lines->AddBound( 2 );
-  Lines->AddVertex( aLinePnt[ 0 ] );
-  Lines->AddVertex( aLinePnt[ 1 ] );
+  theLines->AddVertex (aLinePnt[0]);
+  theLines->AddVertex (aLinePnt[1]);
 
   // draw arrow
-  if ( !myIsSimplePrs )
+  if (!myIsSimplePrs)
   {
-    Standard_Integer l = ArrowPoints.Lower(),
-                     u = ArrowPoints.Upper(),
-                     i;
-    if ( u-l < PntNum-1 )
+    Standard_Integer aLower = theArrowPoints.Lower(),
+                     aUpper = theArrowPoints.Upper();
+
+    if (aUpper - aLower < PntNum - 1)
       return;
 
-    TColgp_Array1OfPnt anArrowPnt( l, u );
-    for ( i = l; i < l+PntNum; i++ )
+    TColgp_Array1OfPnt anArrowPnt (aLower, aUpper);
+    for (Standard_Integer aPntIdx = aLower; aPntIdx < aLower + PntNum; ++aPntIdx)
     {
-      anArrowPnt( i ).ChangeCoord() = ArrowPoints ( i ).Coord() + gp_XYZ( 0, 0, aLocalLength );
-      theTrsf.Transforms( anArrowPnt( i ).ChangeCoord() );
+      anArrowPnt (aPntIdx).ChangeCoord() = theArrowPoints (aPntIdx).Coord() + gp_XYZ (0, 0, aLocalLength);
+      theTrsf.Transforms (anArrowPnt (aPntIdx).ChangeCoord());
     }
 
-    Triangles->AddBound(8);
-    for ( i = 0; i < PntNum; i++ )
-      Triangles->AddVertex( anArrowPnt( l+i ) );
+    const Standard_Integer aVrtOffset = theTriangles->VertexNumber() + 1;
+
+    for (Standard_Integer aPntIdx = 0; aPntIdx < PntNum; ++aPntIdx)
+    {
+      theTriangles->AddVertex (anArrowPnt (aLower + aPntIdx));
+    }
+
+    for (Standard_Integer aPntIdx = 1; aPntIdx <= PntNum - 2; ++aPntIdx)
+    {
+      theTriangles->AddEdge (aVrtOffset);
+      theTriangles->AddEdge (aVrtOffset + aPntIdx);
+
+      theTriangles->AddEdge (aVrtOffset + aPntIdx);
+      theTriangles->AddEdge (aVrtOffset + aPntIdx + 1);
+    }
   }
   else
   {
-    const Standard_Real aEndPos = aLocalLength - MaxLength * ( 1 - mySimpleEndPrm );
-    const Standard_Real aArrowLength = MaxLength * ( mySimpleEndPrm - mySimpleStartPrm );
+    const Standard_Real aEndPos = aLocalLength - theMaxLength * ( 1 - mySimpleEndPrm );
+    const Standard_Real aArrowLength = theMaxLength * ( mySimpleEndPrm - mySimpleStartPrm );
     gp_Pnt aArrowPnt[ 2 ] = { gp_Pnt( 0, 0, aEndPos - aArrowLength ),
                               gp_Pnt( 0, 0, aEndPos ) };
-    theTrsf.Transforms( aArrowPnt[ 0 ].ChangeCoord() );
-    theTrsf.Transforms( aArrowPnt[ 1 ].ChangeCoord() );
+    theTrsf.Transforms (aArrowPnt[0].ChangeCoord());
+    theTrsf.Transforms (aArrowPnt[1].ChangeCoord());
 
-    ArrowLines->AddBound( 2 );
-    ArrowLines->AddVertex( aArrowPnt[ 0 ] );
-    ArrowLines->AddVertex( aArrowPnt[ 1 ] );
+    theArrowLines->AddVertex (aArrowPnt[0]);
+    theArrowLines->AddVertex (aArrowPnt[1]);
   }
 }