OCC22291 Improve meshcolors command to support texture interpolation
authorAPL <>
Thu, 28 Apr 2011 15:09:12 +0000 (15:09 +0000)
committerbugmaster <bugmaster@opencascade.com>
Mon, 5 Mar 2012 15:27:51 +0000 (19:27 +0400)
src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx
src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx

index 9cc7280..8900bb8 100755 (executable)
@@ -74,7 +74,7 @@ MeshVS_ImageTexture2D::MeshVS_ImageTexture2D
                          const Handle(AlienImage_AlienImage)& theImg)
 : Graphic3d_Texture2D( theSM, "", Graphic3d_TOT_2D )
 {
-  MyCInitTexture.doModulate = 0/*1*/;
+  MyCInitTexture.doModulate = 1;
   MyCInitTexture.doRepeat = 0;
   MyCInitTexture.Mode = (int)Graphic3d_TOTM_MANUAL;
   MyCInitTexture.doLinear = 1;
@@ -178,10 +178,6 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
   aDrawer->GetBoolean( MeshVS_DA_ColorReflection, IsReflect );
   aDrawer->GetBoolean( MeshVS_DA_SmoothShading,   IsMeshSmoothShading );
   
-  // NOTE: Lighting effect not tested with textures, so turning off reflectance when textures are used.
-  // This can be improved if necessary...
-  IsReflect = IsReflect && !myUseTexture;
-
   // Following parameter are used for texture presentation only
   int nbColors = 0; // Number of colors from color map
   int nbTextureColors = 0; // Number of colors in texture (it will be pow of 2)
@@ -307,10 +303,29 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
 
             // transform texture coordinate in accordance with number of colors specified 
             // by upper level and real size of Gl texture
-            aTexCoord = aTexCoord * nbColors / nbTextureColors;
+            // 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;
 
-            aCPolyArr->AddVertex( P, aDefNorm, 
-              gp_Pnt2d( aTexCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 1 : 0 ) );
+            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
           {
@@ -377,10 +392,29 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
 
               // transform texture coordinate in accordance with number of colors specified 
               // by upper level and real size of Gl texture
-              aTexCoord = aTexCoord * nbColors / nbTextureColors;
+              // 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_Pnt2d aTP( aTexCoord, aTexCoord >= 0 && aTexCoord <= 1 ? 1 : 0 );
-              aCPolyArr->AddVertex( P, aDefNorm, aTP );
+              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
             {
@@ -464,6 +498,7 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
 
     anAsp->SetTextureMapOn();  
     anAsp->SetTextureMap( aTexture );
+    anAsp->SetInteriorColor( Quantity_NOC_WHITE );
   }
   else
   {
@@ -477,7 +512,6 @@ void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
 
   anAsp->SetDistinguishOff();
   anAsp->SetEdgeOff();
-  anAsp->SetInteriorColor( Quantity_NOC_GRAY );
 
   Handle(Graphic3d_AspectLine3d) anLAsp = 
     new Graphic3d_AspectLine3d( anEdgeColor, anEdgeType, anEdgeWidth );
index a2ec688..93fafe7 100755 (executable)
@@ -58,7 +58,8 @@
 #include <VrmlData_Scene.hxx>
 #include <VrmlData_ShapeConvert.hxx>
 #include <VrmlData_DataMapOfShapeAppearance.hxx>
-
+#include <TColStd_Array1OfReal.hxx>
+#include <Bnd_Box.hxx>
 
 // avoid warnings on 'extern "C"' functions returning C++ classes
 #ifdef WNT
@@ -714,10 +715,11 @@ static Standard_Integer meshcolors( Draw_Interpretor& di,
       if ( argc < 2 )
       {
         di << "Use : meshcolors meshname mode isreflect" << "\n";
-        di << "mode : {elem1|elem2|nodal|none}"<< "\n";
+        di << "mode : {elem1|elem2|nodal|nodaltex|none}"<< "\n";
         di << "       elem1 - different color for each element" << "\n";
         di << "       elem2 - one color for one side"<<"\n";
-        di << "       nodal - different color for each node"<< "\n"; 
+        di << "       nodal - different color for each node"<< "\n";
+        di << "       nodaltex - different color for each node with texture interpolation"<< "\n";
         di << "       none  - clear"<< "\n"; 
         di << "isreflect : {0|1} "<< "\n";
          
@@ -742,7 +744,7 @@ static Standard_Integer meshcolors( Draw_Interpretor& di,
         TCollection_AsciiString aMode = TCollection_AsciiString (argv[2]);
         Quantity_Color aColor1( (Quantity_NameOfColor)( Quantity_NOC_BLUE1 ) );
         Quantity_Color aColor2( (Quantity_NameOfColor)( Quantity_NOC_RED1 ) );
-        if( aMode.IsEqual("elem1") || aMode.IsEqual("elem2") || aMode.IsEqual("nodal") || aMode.IsEqual("none") )
+        if( aMode.IsEqual("elem1") || aMode.IsEqual("elem2") || aMode.IsEqual("nodal") || aMode.IsEqual("nodaltex") || aMode.IsEqual("none") )
         {
           Handle(MeshVS_PrsBuilder) aTempBuilder;
           Standard_Integer reflection = atoi(argv[3]);
@@ -798,6 +800,67 @@ static Standard_Integer meshcolors( Draw_Interpretor& di,
             aMesh->AddBuilder( aBuilder, Standard_True );
           }
 
+          if(aMode.IsEqual("nodaltex"))
+          {
+            // assign nodal builder to the mesh
+            Handle(MeshVS_NodalColorPrsBuilder) aBuilder = new MeshVS_NodalColorPrsBuilder( 
+                   aMesh, MeshVS_DMF_NodalColorDataPrs | MeshVS_DMF_OCCMask);
+            aMesh->AddBuilder(aBuilder, Standard_True);
+            aBuilder->UseTexture(Standard_True);
+
+            // prepare color map for texture
+            Aspect_SequenceOfColor aColorMap;
+            aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_RED);
+            aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_YELLOW);
+            aColorMap.Append((Quantity_NameOfColor) Quantity_NOC_BLUE1);
+
+            // prepare scale map for mesh - it will be assigned to mesh as texture coordinates
+            // make mesh color interpolated from minimum X coord to maximum X coord
+            Handle(MeshVS_DataSource) aDataSource = aMesh->GetDataSource();
+            Standard_Real aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
+
+            // get bounding box for calculations
+            aDataSource->GetBoundingBox().Get(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ);
+            Standard_Real aDelta = aMaxX - aMinX;
+
+            // assign color scale map values (0..1) to nodes
+            TColStd_DataMapOfIntegerReal aScaleMap;
+            TColStd_Array1OfReal aCoords(1, 3);
+            Standard_Integer     aNbNodes;
+            MeshVS_EntityType    aType;
+
+            // iterate nodes
+            const TColStd_PackedMapOfInteger& anAllNodes =
+                  aMesh->GetDataSource()->GetAllNodes();
+            TColStd_MapIteratorOfPackedMapOfInteger anIter(anAllNodes);
+            for (; anIter.More(); anIter.Next())
+            {
+              //get node coordinates to aCoord variable
+              aDataSource->GetGeom(anIter.Key(), Standard_False, aCoords, aNbNodes, aType);
+
+              Standard_Real aScaleValue;
+              try {
+                OCC_CATCH_SIGNALS
+                aScaleValue = (aCoords.Value(1) - (Standard_Real) aMinX) / aDelta;
+              } catch(Standard_Failure) {
+                aScaleValue = 0;
+              }
+
+              aScaleMap.Bind(anIter.Key(), aScaleValue); 
+            }
+
+            //set color map for builder and a color for invalid scale value
+            aBuilder->SetColorMap(aColorMap);
+            aBuilder->SetInvalidColor(Quantity_NOC_BLACK);
+            aBuilder->SetTextureCoords(aScaleMap);
+            aMesh->AddBuilder(aBuilder, Standard_True);
+                       
+            //set viewer to display texures
+            const Handle(V3d_Viewer)& aViewer = anIC->CurrentViewer();
+            for (aViewer->InitActiveViews(); aViewer->MoreActiveViews(); aViewer->NextActiveViews())
+                 aViewer->ActiveView()->SetSurfaceDetail(V3d_TEX_ALL);
+          }
+
           aMesh->GetDrawer()->SetBoolean ( MeshVS_DA_ColorReflection, Standard_Boolean(reflection) );
 
           anIC->Redisplay( aMesh );