0031505: Point Cloud Rendering - fix on-screen statistics about number of visible...
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
index b7a2b56..9bc02b1 100644 (file)
@@ -416,6 +416,9 @@ namespace
     //! the option key for the command that sets inversion of Z axis for background cubemap
     ViewerTest_CommandOptionKey myCubeMapInvertedZOptionKey;
 
+    //! the option key for the command that allows skip IBL map generation
+    ViewerTest_CommandOptionKey myCubeMapDoNotGenPBREnvOptionKey;
+
     //! the variable set of options that are allowed for the old scenario (without any option passed)
     CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
 
@@ -466,6 +469,7 @@ namespace
       myCubeMapOrderOptionKey      = myCommandParser.AddOption ("order|o", "order of sides in one image packed cubemap");
       myCubeMapInvertedZOptionKey = myCommandParser.AddOption (
         "invertedz|invz|iz", "whether Z axis is inverted or not during background cubemap rendering");
+      myCubeMapDoNotGenPBREnvOptionKey = myCommandParser.AddOption ("nopbrenv", "whether IBL map generation should be skipped");
     }
 
     //! Creates option sets used to determine if a passed option set is valid or not
@@ -479,6 +483,7 @@ namespace
       aCubeMapOptionSet.insert (myCubeMapOptionKey);
       ViewerTest_CommandOptionKeySet aCubeMapAdditionalOptionKeySet;
       aCubeMapAdditionalOptionKeySet.insert (myCubeMapInvertedZOptionKey);
+      aCubeMapAdditionalOptionKeySet.insert (myCubeMapDoNotGenPBREnvOptionKey);
       aCubeMapAdditionalOptionKeySet.insert (myCubeMapOrderOptionKey);
       myCubeMapOptionVariableSet     = CommandOptionKeyVariableSet (aCubeMapOptionSet, aCubeMapAdditionalOptionKeySet);
 
@@ -852,7 +857,17 @@ namespace
         aZIsInverted = true;
       }
 
-      setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted);
+      bool aToGenPBREnv = true;
+      if (myCommandParser.HasOption (myCubeMapDoNotGenPBREnvOptionKey))
+      {
+        if (!processCubeMapDoNotGenPBREnvOptionSet())
+        {
+          return false;
+        }
+        aToGenPBREnv = false;
+      }
+
+      setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted, aToGenPBREnv);
       return true;
     }
 
@@ -1017,8 +1032,7 @@ namespace
       return true;
     }
 
-    //! Processes the cubemap option
-    //! @param theIsNeededToRedraw defines need of redraw after option's processing 
+    //! Processes the inverted z cubemap option
     //! @return true if processing was successful, or false otherwise
     bool processCubeMapInvertedZOptionSet () const
     {
@@ -1033,6 +1047,21 @@ namespace
       return true;
     }
 
+    //! Processes the option allowing to skip IBM maps generation
+    //! @return true if processing was successful, or false otherwise
+    bool processCubeMapDoNotGenPBREnvOptionSet() const
+    {
+      const Standard_Integer aNumberOfCubeMapDoNotGenPBREnvOptionArguments =
+        myCommandParser.GetNumberOfOptionArguments(myCubeMapDoNotGenPBREnvOptionKey);
+
+      if (aNumberOfCubeMapDoNotGenPBREnvOptionArguments != 0)
+      {
+        return false;
+      }
+
+      return true;
+    }
+
     //! Processes the tiles order option
     //! @param theOrder the array of indexes if cubemap sides in tile grid
     //! @return true if processing was successful, or false otherwise
@@ -1221,7 +1250,8 @@ namespace
     //! @param theOrder array of cubemap sides indexes mapping them from tiles in packed cubemap
     static void setCubeMap (const NCollection_Array1<TCollection_AsciiString>& theFileNames,
                             const Graphic3d_ValidatedCubeMapOrder              theOrder = Graphic3d_CubeMapOrder::Default(),
-                            bool                                               theZIsInverted = false)
+                            bool                                               theZIsInverted = false,
+                            bool                                               theToGenPBREnv = true)
     {
       const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
       Handle(Graphic3d_CubeMap) aCubeMap;
@@ -1237,7 +1267,7 @@ namespace
       aCubeMap->GetParams()->SetRepeat(Standard_False);
       aCubeMap->GetParams()->SetTextureUnit(Graphic3d_TextureUnit_EnvMap);
 
-      aCurrentView->SetBackgroundCubeMap (aCubeMap, Standard_True);
+      aCurrentView->SetBackgroundCubeMap (aCubeMap, theToGenPBREnv, Standard_True);
     }
 
     //! Sets the image as a background
@@ -1346,27 +1376,6 @@ namespace
 
 } // namespace
 
-typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
-
-Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
-{
-  static ViewerTest_MapOfAISManipulators aMap;
-  return aMap;
-}
-
-Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
-{
-  ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
-  for (; anIt.More(); anIt.Next())
-  {
-    if (anIt.Value()->HasActiveMode())
-    {
-      return anIt.Value();
-    }
-  }
-  return NULL;
-}
-
 //==============================================================================
 
 #ifdef _WIN32
@@ -1388,9 +1397,9 @@ static LRESULT WINAPI AdvViewerWindowProc(
 //purpose  :
 //==============================================================================
 
-const Handle(Standard_Transient)& ViewerTest::WClass()
+const Handle(WNT_WClass)& ViewerTest::WClass()
 {
-  static Handle(Standard_Transient) theWClass;
+  static Handle(WNT_WClass) theWClass;
 #if defined(_WIN32)
   if (theWClass.IsNull())
   {
@@ -1930,8 +1939,7 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
 
   // Create window
 #if defined(_WIN32)
-  VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
-                                    Handle(WNT_WClass)::DownCast (WClass()),
+  VT_GetWindow() = new WNT_Window (aTitle.ToCString(), WClass(),
                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
                                     aPxLeft, aPxTop,
                                     aPxWidth, aPxHeight,
@@ -2555,8 +2563,8 @@ void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const S
   if (!aCurrentContext.IsNull())
   {
     // Check if there are more difined views in the viewer
-    aCurrentContext->CurrentViewer()->InitDefinedViews();
-    if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
+    if ((isContextRemoved || ViewerTest_myContexts.Size() != 1)
+     && aCurrentContext->CurrentViewer()->DefinedViews().IsEmpty())
     {
       // Remove driver if there is no viewers that use it
       Standard_Boolean isRemoveDriver = Standard_True;
@@ -4823,6 +4831,14 @@ static int VColorScale (Draw_Interpretor& theDI,
       aColorScale->SetColors    (aSeq);
       aColorScale->SetColorType (Aspect_TOCSD_USER);
     }
+    else if (aFlag == "-uniform")
+    {
+      const Standard_Real aLightness = Draw::Atof (theArgVec[++anArgIter]);
+      const Standard_Real aHueStart = Draw::Atof (theArgVec[++anArgIter]);
+      const Standard_Real aHueEnd = Draw::Atof (theArgVec[++anArgIter]);
+      aColorScale->SetUniformColors (aLightness, aHueStart, aHueEnd);
+      aColorScale->SetColorType (Aspect_TOCSD_USER);
+    }
     else if (aFlag == "-labels"
           || aFlag == "-freelabels")
     {
@@ -5845,7 +5861,7 @@ void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePre
                             const Standard_Integer /*theMode*/)
 {
   thePresentation->Clear();
-  Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
+  Quantity_Color aColor (Quantity_NOC_RED);
   Standard_Integer aWidth, aHeight;
   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
@@ -6780,6 +6796,7 @@ static int VCaps (Draw_Interpretor& theDI,
 
   if (theArgNb < 2)
   {
+    theDI << "sRGB:    " << (aCaps->sRGBDisable       ? "0" : "1") << "\n";
     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
@@ -6835,6 +6852,16 @@ static int VCaps (Draw_Interpretor& theDI,
       }
       aCaps->usePolygonMode = toEnable;
     }
+    else if (anArgCase == "-srgb")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->sRGBDisable = !toEnable;
+    }
     else if (anArgCase == "-vbo")
     {
       Standard_Boolean toEnable = Standard_True;
@@ -7063,17 +7090,19 @@ static int VReadPixel (Draw_Interpretor& theDI,
     return 1;
   }
 
-  Standard_Boolean toShowName = Standard_False;
-  Standard_Boolean toShowHls  = Standard_False;
+  bool toShowName = false, toShowHls = false, toShowHex = false, toShow_sRGB = false;
   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
   {
     TCollection_AsciiString aParam (theArgVec[anIter]);
     aParam.LowerCase();
     if (aParam == "-rgb"
-     || aParam == "rgb")
+     || aParam == "rgb"
+     || aParam == "-srgb"
+     || aParam == "srgb")
     {
       aFormat     = Image_Format_RGB;
       aBufferType = Graphic3d_BT_RGB;
+      toShow_sRGB = aParam == "-srgb" || aParam == "srgb";
     }
     else if (aParam == "-hls"
           || aParam == "hls")
@@ -7089,10 +7118,13 @@ static int VReadPixel (Draw_Interpretor& theDI,
       aBufferType = Graphic3d_BT_RGB;
     }
     else if (aParam == "-rgba"
-          || aParam == "rgba")
+          || aParam == "rgba"
+          || aParam == "-srgba"
+          || aParam == "srgba")
     {
       aFormat     = Image_Format_RGBA;
       aBufferType = Graphic3d_BT_RGBA;
+      toShow_sRGB = aParam == "-srgba" || aParam == "srgba";
     }
     else if (aParam == "-rgbaf"
           || aParam == "rgbaf")
@@ -7111,9 +7143,15 @@ static int VReadPixel (Draw_Interpretor& theDI,
     {
       toShowName = Standard_True;
     }
+    else if (aParam == "-hex"
+          || aParam == "hex")
+    {
+      toShowHex = Standard_True;
+    }
     else
     {
       std::cout << "Syntax error at '" << aParam << "'\n";
+      return 1;
     }
   }
 
@@ -7139,7 +7177,7 @@ static int VReadPixel (Draw_Interpretor& theDI,
   }
   theDI.Reset();
 
-  Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
+  Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY, true);
   if (toShowName)
   {
     if (aBufferType == Graphic3d_BT_RGBA)
@@ -7151,6 +7189,17 @@ static int VReadPixel (Draw_Interpretor& theDI,
       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
     }
   }
+  else if (toShowHex)
+  {
+    if (aBufferType == Graphic3d_BT_RGBA)
+    {
+      theDI << Quantity_ColorRGBA::ColorToHex (aColor);
+    }
+    else
+    {
+      theDI << Quantity_Color::ColorToHex (aColor.GetRGB());
+    }
+  }
   else
   {
     switch (aBufferType)
@@ -7162,6 +7211,11 @@ static int VReadPixel (Draw_Interpretor& theDI,
         {
           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
         }
+        else if (toShow_sRGB)
+        {
+          const Graphic3d_Vec4 aColor_sRGB = Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec4 )aColor);
+          theDI << aColor_sRGB.r() << " " << aColor_sRGB.g() << " " << aColor_sRGB.b();
+        }
         else
         {
           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
@@ -7170,7 +7224,8 @@ static int VReadPixel (Draw_Interpretor& theDI,
       }
       case Graphic3d_BT_RGBA:
       {
-        theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
+        const Graphic3d_Vec4 aVec4 = toShow_sRGB ? Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec4 )aColor) : (Graphic3d_Vec4 )aColor;
+        theDI << aVec4.r() << " " << aVec4.g() << " " << aVec4.b() << " " << aVec4.a();
         break;
       }
       case Graphic3d_BT_Depth:
@@ -7203,18 +7258,10 @@ public:
       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
       Graphic3d_MaterialAspect aMat;
       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
-      aMat.SetAmbient  (1.0);
-      aMat.SetDiffuse  (1.0);
-      aMat.SetSpecular (1.0);
-      aMat.SetEmissive (1.0);
-      aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
-      aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
-      aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
-      aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
-      aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
-      aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
-      aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
-      aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
+      aMat.SetAmbientColor  (Quantity_NOC_BLACK);
+      aMat.SetDiffuseColor  (Quantity_NOC_WHITE);
+      aMat.SetSpecularColor (Quantity_NOC_BLACK);
+      aMat.SetEmissiveColor (Quantity_NOC_BLACK);
       aFillAspect->SetFrontMaterial (aMat);
       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
       aFillAspect->SetTextureMapOn();
@@ -9594,13 +9641,22 @@ static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, cons
         std::cout << "Syntax error: need more arguments.\n";
         return 1;
       }
-
-      Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
-      aMat.SetAmbientColor (aColor);
-      aMat.SetDiffuseColor (aColor);
-      aClipPlane->SetCappingMaterial (aMat);
+      aClipPlane->SetCappingColor (aColor);
       anArgIter += aNbParsed;
     }
+    else if (aNbChangeArgs >= 1
+          && (aChangeArg == "-material"
+           || aChangeArg == "material"))
+    {
+      ++anArgIter;
+      Graphic3d_NameOfMaterial aMatName;
+      if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeArgs[1], aMatName))
+      {
+        std::cout << "Syntax error: unknown material '" << aChangeArgs[1] << "'.\n";
+        return 1;
+      }
+      aClipPlane->SetCappingMaterial (aMatName);
+    }
     else if ((aChangeArg == "-transparency"
            || aChangeArg == "-transp")
           && aNbChangeArgs >= 2)
@@ -10466,7 +10522,7 @@ static int VDefaults (Draw_Interpretor& theDi,
   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
   if (aCtx.IsNull())
   {
-    std::cerr << "No active viewer!\n";
+    std::cout << "Error: no active viewer\n";
     return 1;
   }
 
@@ -10483,7 +10539,7 @@ static int VDefaults (Draw_Interpretor& theDi,
       theDi << "DeflType:           absolute\n"
             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
     }
-    theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
+    theDi << "AngularDeflection:  " << (180.0 * aDefParams->DeviationAngle() / M_PI) << "\n";
     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
     return 0;
   }
@@ -10528,34 +10584,26 @@ static int VDefaults (Draw_Interpretor& theDi,
         std::cout << "Error: wrong syntax at " << anArg << "\n";
         return 1;
       }
-      // currently HLRDeviationAngle is used instead of DeviationAngle in most places
-      aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
+      aDefParams->SetDeviationAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
     }
     else if (anArg == "-AUTOTR"
           || anArg == "-AUTOTRIANG"
           || anArg == "-AUTOTRIANGULATION")
     {
-      if (++anArgIter >= theArgsNb)
+      ++anArgIter;
+      bool toTurnOn = true;
+      if (anArgIter >= theArgsNb
+      || !ViewerTest::ParseOnOff (theArgVec[anArgIter], toTurnOn))
       {
-        std::cout << "Error: wrong syntax at " << anArg << "\n";
+        std::cout << "Syntax error at '" << anArg << "'\n";
         return 1;
       }
-      TCollection_AsciiString aValue (theArgVec[anArgIter]);
-      aValue.LowerCase();
-      if (aValue == "on"
-       || aValue == "1")
-      {
-        aDefParams->SetAutoTriangulation (Standard_True);
-      }
-      else if (aValue == "off"
-            || aValue == "0")
-      {
-        aDefParams->SetAutoTriangulation (Standard_False);
-      }
+      aDefParams->SetAutoTriangulation (toTurnOn);
     }
     else
     {
-      std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
+      std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
+      return 1;
     }
   }
 
@@ -10671,6 +10719,7 @@ static int VLight (Draw_Interpretor& theDi,
           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
           aLight->Attenuation (anAtten[0], anAtten[1]);
           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
+          theDi << "  Range:      " << aLight->Range() << "\n";
           break;
         }
         case V3d_SPOT:
@@ -10686,6 +10735,7 @@ static int VLight (Draw_Interpretor& theDi,
           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
+          theDi << "  Range:      " << aLight->Range() << "\n";
           break;
         }
         default:
@@ -11143,6 +11193,20 @@ static int VLight (Draw_Interpretor& theDi,
 
       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
     }
+    else if (anArgCase.IsEqual("RANGE")
+          || anArgCase.IsEqual("-RANGE"))
+    {
+      if (++anArgIt >= theArgsNb
+       || aLightCurr.IsNull()
+       || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT
+       || aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      aLightCurr->SetRange ((Standard_ShortReal)Atof (theArgVec[anArgIt]));
+    }
     else if (anArgCase.IsEqual ("HEAD")
           || anArgCase.IsEqual ("HEADLIGHT")
           || anArgCase.IsEqual ("-HEAD")
@@ -11173,6 +11237,48 @@ static int VLight (Draw_Interpretor& theDi,
   return 0;
 }
 
+//===============================================================================================
+//function : VPBREnvironment
+//purpose  :
+//===============================================================================================
+static int VPBREnvironment (Draw_Interpretor&,
+                            Standard_Integer theArgsNb,
+                            const char**     theArgVec)
+{
+  if (theArgsNb > 2)
+  {
+    std::cerr << "Error: 'vpbrenv' command has only one argument\n";
+    return 1;
+  }
+
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cerr << "Error: no active viewer!\n";
+    return 1;
+  }
+
+  TCollection_AsciiString anArg = TCollection_AsciiString (theArgVec[1]);
+  anArg.LowerCase();
+
+  if (anArg == "-generate"
+   || anArg == "-gen")
+  {
+    aView->GeneratePBREnvironment (Standard_True);
+  }
+  else if (anArg == "-clear")
+  {
+    aView->ClearPBREnvironment (Standard_True);
+  }
+  else
+  {
+    std::cerr << "Error: unknown argument [" << theArgVec[1] << "] for 'vpbrenv' command\n";
+    return 1;
+  }
+
+  return 0;
+}
+
 //! Read Graphic3d_RenderingParams::PerfCounters flag.
 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
                                             Standard_Boolean& theToReset,
@@ -11219,6 +11325,7 @@ static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theVa
         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
   else if (aVal == "pnts"
         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
+  else if (aVal == "lines")      aFlag = Graphic3d_RenderingParams::PerfCounters_Lines;
   else if (aVal == "mem"
         || aVal == "gpumem"
         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
@@ -11379,11 +11486,13 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
     theDI << "shadingModel: ";
     switch (aView->ShadingModel())
     {
-      case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
-      case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
-      case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
-      case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
-      case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
+      case Graphic3d_TOSM_DEFAULT:   theDI << "default";   break;
+      case Graphic3d_TOSM_UNLIT:     theDI << "unlit";     break;
+      case Graphic3d_TOSM_FACET:     theDI << "flat";      break;
+      case Graphic3d_TOSM_VERTEX:    theDI << "gouraud";   break;
+      case Graphic3d_TOSM_FRAGMENT:  theDI << "phong";     break;
+      case Graphic3d_TOSM_PBR:       theDI << "pbr";       break;
+      case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break;
     }
     {
       theDI << "perfCounters:";
@@ -11411,6 +11520,10 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       {
         theDI << " tris";
       }
+      if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Lines) != 0)
+      {
+        theDI << " lines";
+      }
       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
       {
         theDI << " pnts";
@@ -11921,6 +12034,22 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       }
       aParams.UseEnvironmentMapBackground = toEnable;
     }
+    else if (aFlag == "-ignorenormalmap")
+    {
+      if (toPrint)
+      {
+        theDI << (aParams.ToIgnoreNormalMapInRayTracing ? "on" : "off") << " ";
+        continue;
+      }
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.ToIgnoreNormalMapInRayTracing = toEnable;
+    }
     else if (aFlag == "-twoside")
     {
       if (toPrint)
@@ -11945,11 +12074,13 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       {
         switch (aView->ShadingModel())
         {
-          case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
-          case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
-          case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
-          case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
-          case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
+          case Graphic3d_TOSM_DEFAULT:   theDI << "default";   break;
+          case Graphic3d_TOSM_UNLIT:     theDI << "unlit ";    break;
+          case Graphic3d_TOSM_FACET:     theDI << "flat ";     break;
+          case Graphic3d_TOSM_VERTEX:    theDI << "gouraud ";  break;
+          case Graphic3d_TOSM_FRAGMENT:  theDI << "phong ";    break;
+          case Graphic3d_TOSM_PBR:       theDI << "pbr";       break;
+          case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break;
         }
         continue;
       }
@@ -11971,6 +12102,97 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
         return 1;
       }
     }
+    else if (aFlag == "-pbrenvpow2size"
+          || aFlag == "-pbrenvp2s"
+          || aFlag == "-pep2s")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Integer aPbrEnvPow2Size = Draw::Atoi (theArgVec[anArgIter]);
+      if (aPbrEnvPow2Size < 1)
+      {
+        std::cout << "Error: 'Pow2Size' of PBR Environment has to be greater or equal 1\n";
+        return 1;
+      }
+      aParams.PbrEnvPow2Size = aPbrEnvPow2Size;
+    }
+    else if (aFlag == "-pbrenvspecmaplevelsnumber"
+          || aFlag == "-pbrenvspecmapnblevels"
+          || aFlag == "-pbrenvspecmaplevels"
+          || aFlag == "-pbrenvsmln"
+          || aFlag == "-pesmln")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Integer aPbrEnvSpecMapNbLevels = Draw::Atoi (theArgVec[anArgIter]);
+      if (aPbrEnvSpecMapNbLevels < 2)
+      {
+        std::cout << "Error: 'SpecMapLevelsNumber' of PBR Environment has to be greater or equal 2\n";
+        return 1;
+      }
+      aParams.PbrEnvSpecMapNbLevels = aPbrEnvSpecMapNbLevels;
+    }
+    else if (aFlag == "-pbrenvbakngdiffsamplesnumber"
+          || aFlag == "-pbrenvbakingdiffsamples"
+          || aFlag == "-pbrenvbdsn")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Integer aPbrEnvBakingDiffNbSamples = Draw::Atoi (theArgVec[anArgIter]);
+      if (aPbrEnvBakingDiffNbSamples < 1)
+      {
+        std::cout << "Error: 'BakingDiffSamplesNumber' of PBR Environtment has to be greater or equal 1\n";
+        return 1;
+      }
+      aParams.PbrEnvBakingDiffNbSamples = aPbrEnvBakingDiffNbSamples;
+    }
+    else if (aFlag == "-pbrenvbakngspecsamplesnumber"
+          || aFlag == "-pbrenvbakingspecsamples"
+          || aFlag == "-pbrenvbssn")
+    {
+    if (++anArgIter >= theArgNb)
+    {
+      std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+      return 1;
+    }
+
+    const Standard_Integer aPbrEnvBakingSpecNbSamples = Draw::Atoi(theArgVec[anArgIter]);
+    if (aPbrEnvBakingSpecNbSamples < 1)
+    {
+      std::cout << "Error: 'BakingSpecSamplesNumber' of PBR Environtment has to be greater or equal 1\n";
+      return 1;
+    }
+    aParams.PbrEnvBakingSpecNbSamples = aPbrEnvBakingSpecNbSamples;
+    }
+    else if (aFlag == "-pbrenvbakingprobability"
+          || aFlag == "-pbrenvbp")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+      const Standard_ShortReal aPbrEnvBakingProbability = static_cast<Standard_ShortReal>(Draw::Atof (theArgVec[anArgIter]));
+      if (aPbrEnvBakingProbability < 0.f
+       || aPbrEnvBakingProbability > 1.f)
+      {
+        std::cout << "Error: 'BakingProbability' of PBR Environtment has to be in range of [0, 1]\n";
+        return 1;
+      }
+      aParams.PbrEnvBakingProbability = aPbrEnvBakingProbability;
+    }
     else if (aFlag == "-resolution")
     {
       if (++anArgIter >= theArgNb)
@@ -12269,7 +12491,9 @@ static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
       else if (aFlag == "alllayers"
             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
       else if (aFlag == "allstructs"
-            || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
+            || aFlag == "allstructures"
+            || aFlag == "structs"
+            || aFlag == "structures") aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
       else if (aFlag == "allarrays"
             || aFlag == "fillarrays"
@@ -12277,6 +12501,7 @@ static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
             || aFlag == "pointarrays"
             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
+      else if (aFlag == "lines")      aParam = Graphic3d_RenderingParams::PerfCounters_Lines;
       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
       else if (aFlag == "geommem"
             || aFlag == "texturemem"
@@ -12338,13 +12563,20 @@ static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
       {
         theDI << searchInfo (aDict, "Rendered layers") << " ";
       }
-      else if (aFlag == "allstructs")
+      else if (aFlag == "allstructs"
+            || aFlag == "allstructures")
       {
         theDI << searchInfo (aDict, "Structs") << " ";
       }
-      else if (aFlag == "structs")
+      else if (aFlag == "structs"
+            || aFlag == "structures")
       {
-        theDI << searchInfo (aDict, "Rendered structs") << " ";
+        TCollection_AsciiString aRend = searchInfo (aDict, "Rendered structs");
+        if (aRend.IsEmpty()) // all structures rendered
+        {
+          aRend = searchInfo (aDict, "Structs");
+        }
+        theDI << aRend << " ";
       }
       else if (aFlag == "groups")
       {
@@ -12483,32 +12715,6 @@ static Standard_Integer VXRotate (Draw_Interpretor& di,
   return 0;
 }
 
-//===============================================================================================
-//class   : ViewerTest_AISManipulator
-//purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
-//===============================================================================================
-DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
-
-class ViewerTest_AISManipulator : public AIS_Manipulator
-{
-public:
-
-  ViewerTest_AISManipulator() : AIS_Manipulator()
-  {
-    GetMapOfAISManipulators().Add (this);
-  }
-
-  virtual ~ViewerTest_AISManipulator()
-  {
-    GetMapOfAISManipulators().Remove (this);
-  }
-
-  DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
-};
-
-IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
-IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
-
 //===============================================================================================
 //function : VManipulator
 //purpose  :
@@ -12615,7 +12821,7 @@ static int VManipulator (Draw_Interpretor& theDi,
   {
     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
 
-    aManipulator = new ViewerTest_AISManipulator();
+    aManipulator = new AIS_Manipulator();
     aManipulator->SetModeActivationOnDetection (true);
     aMapAIS.Bind (aManipulator, aName);
   }
@@ -12721,10 +12927,13 @@ static int VManipulator (Draw_Interpretor& theDi,
       return 1;
     }
 
-    for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
+    for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (aMapAIS);
+         anIter.More(); anIter.Next())
     {
-      if (anIt.Value()->IsAttached()
-       && anIt.Value()->Object() == anObject)
+      Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (anIter.Key1());
+      if (!aManip.IsNull()
+       && aManip->IsAttached()
+       && aManip->Object() == anObject)
       {
         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
         return 1;
@@ -13524,6 +13733,21 @@ static int VViewCube (Draw_Interpretor& ,
     {
       aViewCube->SetDuration (Draw::Atof (theArgVec[++anArgIter]));
     }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-axesradius")
+    {
+      aViewCube->SetAxesRadius (Draw::Atof (theArgVec[++anArgIter]));
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-axesconeradius")
+    {
+      aViewCube->SetAxesConeRadius (Draw::Atof (theArgVec[++anArgIter]));
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-axessphereradius")
+    {
+      aViewCube->SetAxesSphereRadius (Draw::Atof (theArgVec[++anArgIter]));
+    }
     else
     {
       std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
@@ -13540,6 +13764,91 @@ static int VViewCube (Draw_Interpretor& ,
   return 0;
 }
 
+//===============================================================================================
+//function : VColorConvert
+//purpose  :
+//===============================================================================================
+static int VColorConvert (Draw_Interpretor& theDI, Standard_Integer  theNbArgs, const char** theArgVec)
+{
+  if (theNbArgs != 6)
+  {
+    std::cerr << "Error: command syntax is incorrect, see help" << std::endl;
+    return 1;
+  }
+
+  Standard_Boolean convertFrom = (! strcasecmp (theArgVec[1], "from"));
+  if (! convertFrom && strcasecmp (theArgVec[1], "to"))
+  {
+    std::cerr << "Error: first argument must be either \"to\" or \"from\"" << std::endl;
+    return 1;
+  }
+
+  const char* aTypeStr = theArgVec[2];
+  Quantity_TypeOfColor aType = Quantity_TOC_RGB;
+  if (! strcasecmp (aTypeStr, "srgb"))
+  {
+    aType = Quantity_TOC_sRGB;
+  }
+  else if (! strcasecmp (aTypeStr, "hls"))
+  {
+    aType = Quantity_TOC_HLS;
+  }
+  else if (! strcasecmp (aTypeStr, "lab"))
+  {
+    aType = Quantity_TOC_CIELab;
+  }
+  else if (! strcasecmp (aTypeStr, "lch"))
+  {
+    aType = Quantity_TOC_CIELch;
+  }
+  else
+  {
+    std::cerr << "Error: unknown colorspace type: " << aTypeStr << std::endl;
+    return 1;
+  }
+
+  double aC1 = Draw::Atof (theArgVec[3]);
+  double aC2 = Draw::Atof (theArgVec[4]);
+  double aC3 = Draw::Atof (theArgVec[5]);
+
+  Quantity_Color aColor (aC1, aC2, aC3, convertFrom ? aType : Quantity_TOC_RGB);
+  aColor.Values (aC1, aC2, aC3, convertFrom ? Quantity_TOC_RGB : aType);
+
+  // print values with 6 decimal digits
+  char buffer[1024];
+  Sprintf (buffer, "%.6f %.6f %.6f", aC1, aC2, aC3);
+  theDI << buffer;
+
+  return 0;
+}
+//===============================================================================================
+//function : VColorDiff
+//purpose  :
+//===============================================================================================
+static int VColorDiff (Draw_Interpretor& theDI, Standard_Integer  theNbArgs, const char** theArgVec)
+{
+  if (theNbArgs != 7)
+  {
+    std::cerr << "Error: command syntax is incorrect, see help" << std::endl;
+    return 1;
+  }
+
+  double aR1 = Draw::Atof (theArgVec[1]);
+  double aG1 = Draw::Atof (theArgVec[2]);
+  double aB1 = Draw::Atof (theArgVec[3]);
+  double aR2 = Draw::Atof (theArgVec[4]);
+  double aG2 = Draw::Atof (theArgVec[5]);
+  double aB2 = Draw::Atof (theArgVec[6]);
+
+  Quantity_Color aColor1 (aR1, aG1, aB1, Quantity_TOC_RGB);
+  Quantity_Color aColor2 (aR2, aG2, aB2, Quantity_TOC_RGB);
+
+  theDI << aColor1.DeltaE2000 (aColor2);
+
+  return 0;
+}
 //=======================================================================
 //function : ViewerCommands
 //purpose  :
@@ -13782,9 +14091,11 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
     "\n\t\t:       [-xy Left=0 Bottom=0]"
+    "\n\t\t:       [-uniform lightness hue_from hue_to]"
     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
     "\n\t\t:  -colors   - set colors for all intervals"
     "\n\t\t:  -color    - set color for specific interval"
+    "\n\t\t:  -uniform  - generate colors with the same lightness"
     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
     "\n\t\t:              at border means the value inbetween neighbor intervals,"
@@ -13796,7 +14107,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n\t\t:  -title    - set title"
     "\n\t\t:  -reversed - setup smooth color transition between intervals"
     "\n\t\t:  -smoothTransition - swap colorscale direction"
-    "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
+    "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values",
     __FILE__, VColorScale, group);
   theCommands.Add("vgraduatedtrihedron",
     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
@@ -13918,13 +14229,14 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n\t\t:  greenMagentaSimple",
     __FILE__, VStereo, group);
   theCommands.Add ("vcaps",
-            "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
+            "vcaps [-sRGB {0|1}] [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
     "\n\t\t:       [-compatibleProfile {0|1}]"
     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
     "\n\t\t:       [-noExtensions {0|1}] [-maxVersion Major Minor]"
     "\n\t\t: Modify particular graphic driver options:"
+    "\n\t\t:  sRGB     - enable/disable sRGB rendering"
     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
     "\n\t\t:             built-in GLSL programs"
     "\n\t\t:            (requires compatible profile)"
@@ -13950,7 +14262,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     " with f option returns free memory in bytes",
     __FILE__, VMemGpu, group);
   theCommands.Add ("vreadpixel",
-    "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
+    "vreadpixel xPixel yPixel [{rgb|rgba|sRGB|sRGBa|depth|hls|rgbf|rgbaf}=rgba] [-name|-hex]"
     " : Read pixel value for active view",
     __FILE__, VReadPixel, group);
   theCommands.Add("diffimage",
@@ -14211,10 +14523,17 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n        -{linearAtten}uation value"
     "\n        -angle angleDeg"
     "\n        -{spotexp}onent value"
+    "\n        -range value"
     "\n        -local|-global"
     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
     __FILE__, VLight, group);
+  theCommands.Add("vpbrenv",
+    "vpbrenv -clear|-generate"
+    "\n\t\t: Clears or generates PBR environment map of active view."
+    "\n\t\t:  -clear clears PBR environment (fills by white color)"
+    "\n\t\t:  -generate generates PBR environment from current background cubemap",
+    __FILE__, VPBREnvironment, group);
   theCommands.Add("vraytrace",
             "vraytrace [0|1]"
     "\n\t\t: Turns on/off ray-tracing renderer."
@@ -14239,6 +14558,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n      '-gi           on|off'      Enables/disables global illumination effects"
     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
     "\n      '-env          on|off'      Enables/disables environment map background"
+    "\n      '-ignoreNormalMap on|off'   Enables/disables normal map ignoring during path tracing"
     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
@@ -14247,14 +14567,19 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
     "\n      '-shadingModel model'       Controls shading model from enumeration"
-    "\n                                  color, flat, gouraud, phong"
+    "\n                                  unlit, flat, gouraud, phong"
+    "\n      '-pbrEnvPow2size > 0'       Controls size of IBL maps (real size can be calculates as 2^pbrenvpow2size)"
+    "\n      '-pbrEnvSMLN > 1'           Controls number of mipmap levels used in specular IBL map"
+    "\n      '-pbrEnvBDSN > 0'           Controls number of samples in Monte-Carlo integration during diffuse IBL map's sherical harmonics calculation"
+    "\n      '-pbrEnvBSSN > 0'           Controls maximum number of samples per mipmap level in Monte-Carlo integration during specular IBL maps generation"
+    "\n      '-pbrEnvBP [0, 1]'          Controls strength of samples number reducing during specular IBL maps generation (1 disables reducing)"
     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
-    "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
+    "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triangles|points"
     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
     "\n                                  Show/hide performance counters (flags can be combined)"
     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
@@ -14269,7 +14594,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
   theCommands.Add("vstatprofiler",
     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
-    "\n                |triagles|points|geomMem|textureMem|frameMem"
+    "\n                |triangles|points|geomMem|textureMem|frameMem"
     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
     "\n                [-noredraw]"
@@ -14375,8 +14700,20 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
                    "\n\t\t:   -boxCornerMinSize Value  minimal box corner size"
                    "\n\t\t:   -axesPadding Value       padding between box and arrows"
                    "\n\t\t:   -roundRadius Value       relative radius of corners of sides within [0.0, 0.5] range"
+                   "\n\t\t:   -axesRadius Value        radius of axes of the trihedron"
+                   "\n\t\t:   -axesConeRadius Value    radius of the cone (arrow) of the trihedron"
+                   "\n\t\t:   -axesSphereRadius Value  radius of the sphere (central point) of trihedron"
                    "\n\t\t:   -fixedanimation {0|1}    uninterruptible animation loop"
                    "\n\t\t:   -duration Seconds        animation duration in seconds",
     __FILE__, VViewCube, group);
 
+  theCommands.Add("vcolorconvert" ,
+                  "vcolorconvert {from|to} type C1 C2 C2"
+                  "\n\t\t: vcolorconvert from type C1 C2 C2: Converts color from specified color space to linear RGB"
+                  "\n\t\t: vcolorconvert to type R G B: Converts linear RGB color to specified color space"
+                  "\n\t\t: type can be sRGB, HLS, Lab, or Lch",
+                  __FILE__,VColorConvert,group);
+  theCommands.Add("vcolordiff" ,
+                  "vcolordiff R1 G1 B1 R2 G2 B2: returns CIEDE2000 color difference between two RGB colors",
+                  __FILE__,VColorDiff,group);
 }