0029902: Data Exchange, XCAF - provide extended Material definition for visualization...
[occt.git] / src / XDEDRAW / XDEDRAW_Colors.cxx
index 228f666..59b88e1 100644 (file)
 #include <Precision.hxx>
 #include <Quantity_Color.hxx>
 #include <Quantity_ColorRGBA.hxx>
+#include <OSD_File.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <TDF_Label.hxx>
 #include <TDF_LabelSequence.hxx>
 #include <TDF_Tool.hxx>
+#include <TDataStd_Name.hxx>
 #include <TDocStd_Document.hxx>
 #include <TopoDS_Shape.hxx>
 #include <ViewerTest.hxx>
 #include <XCAFDoc_ColorTool.hxx>
 #include <XCAFDoc_DocumentTool.hxx>
 #include <XCAFDoc_ShapeTool.hxx>
+#include <XCAFDoc_VisMaterial.hxx>
+#include <XCAFDoc_VisMaterialTool.hxx>
 #include <XDEDRAW_Colors.hxx>
 
 //! Parse XCAFDoc_ColorType enumeration argument.
@@ -60,6 +64,102 @@ static bool parseXDocColorType (const TCollection_AsciiString& theArg,
   return false;
 }
 
+//! Print triplet of values.
+template<class S, class T> static S& operator<< (S& theStream, const NCollection_Vec3<T>& theVec)
+{
+  theStream << theVec[0] << " " << theVec[1] << " " << theVec[2];
+  return theStream;
+}
+
+//! Print 4 values.
+template<class S, class T> static S& operator<< (S& theStream, const NCollection_Vec4<T>& theVec)
+{
+  theStream << theVec[0] << " " << theVec[1] << " " << theVec[2] << " " << theVec[3];
+  return theStream;
+}
+
+//! Convert alpha mode into string.
+static const char* alphaModeToString (Graphic3d_AlphaMode theMode)
+{
+  switch (theMode)
+  {
+    case Graphic3d_AlphaMode_Opaque:    return "Opaque";
+    case Graphic3d_AlphaMode_Mask:      return "Mask";
+    case Graphic3d_AlphaMode_Blend:     return "Blend";
+    case Graphic3d_AlphaMode_BlendAuto: return "BlendAuto";
+  }
+  return "";
+}
+
+//! Find existing visualization material in the document.
+static TDF_Label findVisMaterial (const Handle(TDocStd_Document)& theDoc,
+                                  const TCollection_AsciiString& theKey)
+{
+  Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool (theDoc->Main());
+  TDF_Label aMatLab;
+  TDF_Tool::Label (theDoc->GetData(), theKey, aMatLab);
+  if (!aMatLab.IsNull())
+  {
+    return aMatTool->IsMaterial (aMatLab) ? aMatLab : TDF_Label();
+  }
+
+  TDF_LabelSequence aLabels;
+  aMatTool->GetMaterials (aLabels);
+  for (TDF_LabelSequence::Iterator aLabIter (aLabels); aLabIter.More(); aLabIter.Next())
+  {
+    Handle(TDataStd_Name) aNodeName;
+    if (aLabIter.Value().FindAttribute (TDataStd_Name::GetID(), aNodeName)
+     && aNodeName->Get().IsEqual (theKey))
+    {
+      return aLabIter.Value();
+    }
+  }
+  return TDF_Label();
+}
+
+//! Check if image file exists.
+static bool isImageFileExist (const TCollection_AsciiString& thePath)
+{
+  const OSD_Path aPath (thePath);
+  if (!OSD_File (aPath).Exists())
+  {
+    std::cout << "Error: file '" << thePath << " not found\n";
+    return false;
+  }
+  return true;
+}
+
+//! Parse RGB values coming after specified argument.
+static bool parseRgbColor (Standard_Integer& theArgIter,
+                           Quantity_Color&   theColor,
+                           Standard_Integer  theNbArgs,
+                           const char**      theArgVec)
+{
+  Standard_Integer aNbParsed = ViewerTest::ParseColor (theNbArgs - theArgIter - 1,
+                                                       theArgVec + theArgIter + 1,
+                                                       theColor);
+  if (aNbParsed == 0)
+  {
+    std::cout << "Syntax error at '" << theArgVec[theArgIter] << "'\n";
+    return false;
+  }
+  theArgIter += aNbParsed;
+  return true;
+}
+
+//! Parse normalized real value within 0..1 range.
+static bool parseNormalizedReal (const char* theString,
+                                 Standard_ShortReal& theValue)
+{
+  theValue = (Standard_ShortReal )Draw::Atof (theString);
+  if (theValue < 0.0f || theValue > 1.0f)
+  {
+    std::cerr << "Syntax error at '" << theString << "'\n";
+    return false;
+  }
+  return true;
+}
+
 //=======================================================================
 // Section: Work with colors
 //=======================================================================
@@ -267,7 +367,6 @@ static Standard_Integer getAllColors (Draw_Interpretor& di, Standard_Integer arg
   return 0;
 }
 
-
 static Standard_Integer addColor (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
 {
   if (argc < 3)
@@ -620,6 +719,510 @@ static Standard_Integer setStyledcolor (Draw_Interpretor& , Standard_Integer arg
   return 0;
 }
 
+// ================================================================
+// Function : XGetAllVisMaterials
+// Purpose  :
+// ================================================================
+static Standard_Integer XGetAllVisMaterials (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgVec)
+{
+  if (theNbArgs != 2 && theNbArgs != 3)
+  {
+    std::cout << "Syntax error: wrong number of arguments\n";
+    return 1;
+  }
+
+  Handle(TDocStd_Document) aDoc;
+  DDocStd::GetDocument (theArgVec[1], aDoc);
+  if (aDoc.IsNull())
+  {
+    std::cout << "Syntax error: " << theArgVec[1] << " is not a document\n";
+    return 1;
+  }
+
+  bool toPrintNames = true;
+  if (theNbArgs == 3)
+  {
+    TCollection_AsciiString anArgCase (theArgVec[2]);
+    anArgCase.LowerCase();
+    if (anArgCase == "-names")
+    {
+      toPrintNames = true;
+    }
+    else if (anArgCase == "-labels")
+    {
+      toPrintNames = false;
+    }
+  }
+
+  Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool (aDoc->Main());
+  TDF_LabelSequence aLabels;
+  aMatTool->GetMaterials (aLabels);
+  Standard_Integer aMatIndex = 1;
+  for (TDF_LabelSequence::Iterator aLabIter (aLabels); aLabIter.More(); aLabIter.Next(), ++aMatIndex)
+  {
+    const TDF_Label& aMatLab = aLabIter.Value();
+    if (!toPrintNames)
+    {
+      TCollection_AsciiString anEntryId;
+      TDF_Tool::Entry (aMatLab, anEntryId);
+      theDI << anEntryId << " ";
+      continue;
+    }
+
+    Handle(TDataStd_Name) aNodeName;
+    if (aMatLab.FindAttribute (TDataStd_Name::GetID(), aNodeName))
+    {
+      theDI << aNodeName->Get() << " ";
+    }
+    else
+    {
+      TCollection_AsciiString aName = TCollection_AsciiString("<UNNAMED") + aMatIndex + ">";
+      theDI << aName << " ";
+    }
+  }
+  return 0;
+}
+
+// ================================================================
+// Function : XGetVisMaterial
+// Purpose  :
+// ================================================================
+static Standard_Integer XGetVisMaterial (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgVec)
+{
+  if (theNbArgs != 3)
+  {
+    std::cout << "Syntax error: wrong number of arguments\n";
+    return 1;
+  }
+
+  Handle(TDocStd_Document) aDoc;
+  DDocStd::GetDocument (theArgVec[1], aDoc);
+  if (aDoc.IsNull())
+  {
+    std::cout << "Syntax error: " << theArgVec[1] << " is not a document\n";
+    return 1;
+  }
+
+  Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool (aDoc->Main());
+  Handle(XCAFDoc_VisMaterial) aMat;
+  TDF_Label aMatLab = findVisMaterial (aDoc, theArgVec[2]);
+  if (!aMatLab.IsNull())
+  {
+    aMat = aMatTool->GetMaterial (aMatLab);
+  }
+  else
+  {
+    TDF_Label aShapeLab;
+    TDF_Tool::Label (aDoc->GetData(), theArgVec[2], aShapeLab);
+    if (aShapeLab.IsNull())
+    {
+      TopoDS_Shape aShape = DBRep::Get (theArgVec[2]);
+      if (!aShape.IsNull())
+      {
+        aShapeLab = aMatTool->ShapeTool()->FindShape (aShape);
+      }
+    }
+    if (!aShapeLab.IsNull()
+     && !aMatTool->ShapeTool()->IsShape (aShapeLab))
+    {
+      aShapeLab.Nullify();
+    }
+    if (aShapeLab.IsNull())
+    {
+      std::cout << "Syntax error: " << theArgVec[2] << " is not material nor shape\n";
+      return 1;
+    }
+
+    aMat = aMatTool->GetShapeMaterial (aShapeLab);
+  }
+
+  if (aMat.IsNull())
+  {
+    theDI << "EMPTY\n";
+    return 0;
+  }
+
+  TCollection_AsciiString anEntryId;
+  TDF_Tool::Entry (aMat->Label(), anEntryId);
+  theDI << "Label:                  " << anEntryId << "\n";
+
+  Handle(TDataStd_Name) aNodeName;
+  if (aMat->Label().FindAttribute (TDataStd_Name::GetID(), aNodeName))
+  {
+    theDI << "Name:                   " << aNodeName->Get() << "\n";
+  }
+  if (aMat->IsEmpty())
+  {
+    theDI << "EMPTY\n";
+    return 0;
+  }
+  theDI << "AlphaMode:              " << alphaModeToString (aMat->AlphaMode()) << "\n";
+  theDI << "AlphaCutOff:            " << aMat->AlphaCutOff() << "\n";
+  theDI << "IsDoubleSided:          " << aMat->IsDoubleSided() << "\n";
+  if (aMat->HasCommonMaterial())
+  {
+    const XCAFDoc_VisMaterialCommon& aMatCom = aMat->CommonMaterial();
+    theDI << "Common.Ambient:         " << (Graphic3d_Vec3 )aMatCom.AmbientColor << "\n";
+    theDI << "Common.Diffuse:         " << (Graphic3d_Vec3 )aMatCom.DiffuseColor << "\n";
+    if (!aMatCom.DiffuseTexture.IsNull())
+    {
+      theDI << "Common.DiffuseTexture:  " << aMatCom.DiffuseTexture->TextureId() << "\n";
+    }
+    theDI << "Common.Specular:        " << (Graphic3d_Vec3 )aMatCom.SpecularColor << "\n";
+    theDI << "Common.Emissive:        " << (Graphic3d_Vec3 )aMatCom.EmissiveColor << "\n";
+    theDI << "Common.Shininess:       " << aMatCom.Shininess << "\n";
+    theDI << "Common.Transparency:    " << aMatCom.Transparency << "\n";
+  }
+  if (aMat->HasPbrMaterial())
+  {
+    const XCAFDoc_VisMaterialPBR& aMatPbr = aMat->PbrMaterial();
+    theDI << "PBR.BaseColor:          " << (Graphic3d_Vec3 )aMatPbr.BaseColor.GetRGB() << "\n";
+    theDI << "PBR.Transparency:       " << (1.0 - aMatPbr.BaseColor.Alpha()) << "\n";
+    if (!aMatPbr.BaseColorTexture.IsNull())
+    {
+      theDI << "PBR.BaseColorTexture:   " << aMatPbr.BaseColorTexture->TextureId() << "\n";
+    }
+    theDI << "PBR.EmissiveFactor:     " << aMatPbr.EmissiveFactor << "\n";
+    if (!aMatPbr.EmissiveTexture.IsNull())
+    {
+      theDI << "PBR.EmissiveTexture:    " << aMatPbr.EmissiveTexture->TextureId() << "\n";
+    }
+    theDI << "PBR.Metallic:           " << aMatPbr.Metallic << "\n";
+    theDI << "PBR.Roughness:          " << aMatPbr.Roughness << "\n";
+    if (!aMatPbr.MetallicRoughnessTexture.IsNull())
+    {
+      theDI << "PBR.MetallicRoughnessTexture: " << aMatPbr.MetallicRoughnessTexture->TextureId() << "\n";
+    }
+    if (!aMatPbr.OcclusionTexture.IsNull())
+    {
+      theDI << "PBR.OcclusionTexture:   " << aMatPbr.OcclusionTexture->TextureId() << "\n";
+    }
+    if (!aMatPbr.NormalTexture.IsNull())
+    {
+      theDI << "PBR.NormalTexture:      " << aMatPbr.NormalTexture->TextureId() << "\n";
+    }
+  }
+  return 0;
+}
+
+// ================================================================
+// Function : XAddVisMaterial
+// Purpose  :
+// ================================================================
+static Standard_Integer XAddVisMaterial (Draw_Interpretor& , Standard_Integer theNbArgs, const char** theArgVec)
+{
+  if (theNbArgs < 3)
+  {
+    std::cout << "Syntax error: wrong number of arguments\n";
+    return 1;
+  }
+
+  Handle(TDocStd_Document) aDoc;
+  DDocStd::GetDocument (theArgVec[1], aDoc);
+  if (aDoc.IsNull())
+  {
+    std::cout << "Syntax error: " << theArgVec[1] << " is not a document\n";
+    return 1;
+  }
+
+  Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool (aDoc->Main());
+  TDF_Label aMatLab = findVisMaterial (aDoc, theArgVec[2]);
+  if (aMatLab.IsNull())
+  {
+    aMatLab = aMatTool->AddMaterial (theArgVec[2]);
+  }
+
+  Handle(XCAFDoc_VisMaterial) aMat = aMatTool->GetMaterial (aMatLab);
+  XCAFDoc_VisMaterialCommon aMatCom = aMat->CommonMaterial();
+  XCAFDoc_VisMaterialPBR    aMatPbr = aMat->PbrMaterial();
+  Standard_ShortReal aRealValue = 0.0f;
+  for (Standard_Integer anArgIter = 3; anArgIter < theNbArgs; ++anArgIter)
+  {
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if ((anArg == "-transparency"
+      || anArg == "-alpha")
+     && anArgIter + 1 < theNbArgs
+     && parseNormalizedReal (theArgVec[anArgIter + 1], aMatCom.Transparency))
+    {
+      ++anArgIter;
+      if (anArg == "-alpha")
+      {
+        aMatCom.Transparency = 1.0f - aMatCom.Transparency;
+      }
+      aMatPbr.BaseColor.SetAlpha (1.0f - aMatCom.Transparency);
+    }
+    else if (anArg == "-alphaMode"
+          && anArgIter + 2 < theNbArgs
+          && parseNormalizedReal (theArgVec[anArgIter + 2], aRealValue))
+    {
+      TCollection_AsciiString aModeStr (theArgVec[anArgIter + 1]);
+      aModeStr.LowerCase();
+      Graphic3d_AlphaMode anAlphaMode = Graphic3d_AlphaMode_Opaque;
+      if (aModeStr == "opaque")
+      {
+        anAlphaMode = Graphic3d_AlphaMode_Opaque;
+      }
+      else if (aModeStr == "mask")
+      {
+        anAlphaMode = Graphic3d_AlphaMode_Mask;
+      }
+      else if (aModeStr == "blend")
+      {
+        anAlphaMode = Graphic3d_AlphaMode_Blend;
+      }
+      else if (aModeStr == "blendauto")
+      {
+        anAlphaMode = Graphic3d_AlphaMode_BlendAuto;
+      }
+      else
+      {
+        std::cerr << "Syntax error at '" << anArg << "'\n";
+        return 1;
+      }
+      aMat->SetAlphaMode (anAlphaMode, aRealValue);
+      anArgIter += 2;
+    }
+    else if (anArg == "-diffuse"
+          || anArg == "-basecolor"
+          || anArg == "-albedo")
+    {
+      Quantity_ColorRGBA aColorRGBA;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theNbArgs - anArgIter - 1,
+                                                           theArgVec + anArgIter + 1,
+                                                           aColorRGBA);
+      if (aNbParsed == 0)
+      {
+        std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
+        return 1;
+      }
+      anArgIter += aNbParsed;
+
+      if (anArg == "-diffuse")
+      {
+        aMatCom.IsDefined = true;
+        aMatCom.DiffuseColor = aColorRGBA.GetRGB();
+        if (aNbParsed == 2 || aNbParsed == 4)
+        {
+          aMatCom.Transparency = 1.0f - aColorRGBA.Alpha();
+        }
+      }
+      else
+      {
+        aMatPbr.IsDefined = true;
+        if (aNbParsed == 2 || aNbParsed == 4)
+        {
+          aMatPbr.BaseColor = aColorRGBA;
+        }
+        else
+        {
+          aMatPbr.BaseColor.SetRGB (aColorRGBA.GetRGB());
+        }
+      }
+    }
+    else if (anArg == "-specular"
+          && parseRgbColor (anArgIter, aMatCom.SpecularColor,
+                            theNbArgs, theArgVec))
+    {
+      aMatCom.IsDefined = true;
+    }
+    else if (anArg == "-ambient"
+          && parseRgbColor (anArgIter, aMatCom.AmbientColor,
+                            theNbArgs, theArgVec))
+    {
+      aMatCom.IsDefined = true;
+    }
+    else if (anArg == "-emissive"
+          && parseRgbColor (anArgIter, aMatCom.EmissiveColor,
+                            theNbArgs, theArgVec))
+    {
+      aMatCom.IsDefined = true;
+    }
+    else if (anArg == "-shininess"
+          && anArgIter + 1 < theNbArgs)
+    {
+      aMatCom.IsDefined = true;
+      aMatCom.Shininess = (float )Draw::Atof (theArgVec[++anArgIter]);
+      if (aMatCom.Shininess < 0.0f || aMatCom.Shininess > 1.0f)
+      {
+        std::cout << "Syntax error at '" << anArg << "'\n";
+        return 1;
+      }
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-diffusetexture"
+          && isImageFileExist (theArgVec[anArgIter + 1]))
+    {
+      aMatCom.IsDefined = true;
+      aMatCom.DiffuseTexture = new Image_Texture (theArgVec[++anArgIter]);
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-basecolortexture"
+          && isImageFileExist (theArgVec[anArgIter + 1]))
+    {
+      aMatPbr.IsDefined = true;
+      aMatPbr.BaseColorTexture = new Image_Texture (theArgVec[++anArgIter]);
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-emissivetexture"
+          && isImageFileExist (theArgVec[anArgIter + 1]))
+    {
+      aMatPbr.IsDefined = true;
+      aMatPbr.EmissiveTexture = new Image_Texture (theArgVec[++anArgIter]);
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-metallicroughnesstexture"
+          && isImageFileExist (theArgVec[anArgIter + 1]))
+    {
+      aMatPbr.IsDefined = true;
+      aMatPbr.MetallicRoughnessTexture = new Image_Texture (theArgVec[++anArgIter]);
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-normaltexture"
+          && isImageFileExist (theArgVec[anArgIter + 1]))
+    {
+      aMatPbr.IsDefined = true;
+      aMatPbr.NormalTexture = new Image_Texture (theArgVec[++anArgIter]);
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-occlusiontexture"
+          && isImageFileExist (theArgVec[anArgIter + 1]))
+    {
+      aMatPbr.IsDefined = true;
+      aMatPbr.OcclusionTexture = new Image_Texture (theArgVec[++anArgIter]);
+    }
+    else if (anArg == "-emissivefactor"
+          && anArgIter + 4 < theNbArgs)
+    {
+      aMatPbr.IsDefined = true;
+      aMatPbr.EmissiveFactor.SetValues ((float )Draw::Atof (theArgVec[anArgIter + 1]),
+                                        (float )Draw::Atof (theArgVec[anArgIter + 2]),
+                                        (float )Draw::Atof (theArgVec[anArgIter + 3]));
+      anArgIter += 3;
+    }
+    else if (anArg == "-doublesided")
+    {
+      aMatPbr.IsDefined = true;
+      bool isDoubleSided = true;
+      if (anArgIter + 1 < theNbArgs
+       && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isDoubleSided))
+      {
+        ++anArgIter;
+      }
+      aMat->SetDoubleSided (isDoubleSided);
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-metallic"
+          && parseNormalizedReal (theArgVec[anArgIter + 1], aMatPbr.Metallic))
+    {
+      ++anArgIter;
+      aMatPbr.IsDefined = true;
+    }
+    else if (anArgIter + 1 < theNbArgs
+          && anArg == "-roughness"
+          && parseNormalizedReal (theArgVec[anArgIter + 1], aMatPbr.Roughness))
+    {
+      ++anArgIter;
+      aMatPbr.IsDefined = true;
+    }
+    else
+    {
+      std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
+      return 1;
+    }
+  }
+
+  aMat->SetCommonMaterial (aMatCom);
+  aMat->SetPbrMaterial (aMatPbr);
+  return 0;
+}
+
+// ================================================================
+// Function : XRemoveVisMaterial
+// Purpose  :
+// ================================================================
+static Standard_Integer XRemoveVisMaterial (Draw_Interpretor& , Standard_Integer theNbArgs, const char** theArgVec)
+{
+  if (theNbArgs != 3)
+  {
+    std::cout << "Syntax error: wrong number of arguments\n";
+    return 1;
+  }
+
+  Handle(TDocStd_Document) aDoc;
+  DDocStd::GetDocument (theArgVec[1], aDoc);
+  if (aDoc.IsNull())
+  {
+    std::cout << "Syntax error: " << theArgVec[1] << " is not a document\n";
+    return 1;
+  }
+
+  TDF_Label aMatLab = findVisMaterial (aDoc, theArgVec[2]);
+  if (aMatLab.IsNull())
+  {
+    std::cout << "Syntax error: " << theArgVec[2] << " is not a material\n";
+    return 1;
+  }
+
+  Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool (aDoc->Main());
+  aMatTool->RemoveMaterial (aMatLab);
+  return 0;
+}
+
+// ================================================================
+// Function : XSetVisMaterial
+// Purpose  :
+// ================================================================
+static Standard_Integer XSetVisMaterial (Draw_Interpretor& , Standard_Integer theNbArgs, const char** theArgVec)
+{
+  if (theNbArgs != 3 && theNbArgs != 4)
+  {
+    std::cout << "Syntax error: wrong number of arguments\n";
+    return 1;
+  }
+
+  Handle(TDocStd_Document) aDoc;
+  TDF_Label aShapeLab;
+  DDocStd::GetDocument (theArgVec[1], aDoc);
+  if (aDoc.IsNull())
+  {
+    std::cout << "Syntax error: " << theArgVec[1] << " is not a document\n";
+    return 1;
+  }
+
+  TDF_Tool::Label (aDoc->GetData(), theArgVec[2], aShapeLab);
+  Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool (aDoc->Main());
+  if (aShapeLab.IsNull())
+  {
+    // get label by shape
+    TopoDS_Shape aShape = DBRep::Get (theArgVec[2]);
+    if (!aShape.IsNull())
+    {
+      aShapeLab = aColorTool->ShapeTool()->FindShape (aShape, Standard_True);
+    }
+  }
+  if (aShapeLab.IsNull())
+  {
+    std::cout << "Syntax error: " << theArgVec[2] << " is not a label not shape\n";
+    return 1;
+  }
+
+  TDF_Label aMatLab;
+  if (theNbArgs == 4)
+  {
+    aMatLab = findVisMaterial (aDoc, theArgVec[3]);
+    if (aMatLab.IsNull())
+    {
+      std::cout << "Syntax error: " << theArgVec[3] << " is not a material\n";
+      return 1;
+    }
+  }
+
+  Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool (aDoc->Main());
+  aMatTool->SetShapeMaterial (aShapeLab, aMatLab);
+  return 0;
+}
+
 //=======================================================================
 //function : InitCommands
 //purpose  : 
@@ -689,4 +1292,32 @@ void XDEDRAW_Colors::InitCommands(Draw_Interpretor& di)
   di.Add ("XSetInstanceColor","Doc Shape R G B [alpha] [{generic|surface|curve}=gen]"
                               "\t: sets color for component of shape if SHUO structure exists already",
                   __FILE__, setStyledcolor, g);
+
+  di.Add ("XGetAllVisMaterials","Doc [{-names|-labels}=-names]"
+          "\t: Print all visualization materials defined in document",
+          __FILE__, XGetAllVisMaterials, g);
+  di.Add ("XGetVisMaterial","Doc {Material|Shape}"
+          "\t: Print visualization material properties",
+          __FILE__, XGetVisMaterial, g);
+  di.Add ("XAddVisMaterial",
+          "Doc Material"
+          "\n\t\t: [-transparency 0..1] [-alphaMode {Opaque|Mask|Blend|BlendAuto} CutOffValue]"
+          "\n\t\t: [-diffuse   RGB] [-diffuseTexture ImagePath]"
+          "\n\t\t: [-specular  RGB] [-ambient RGB] [-emissive  RGB] [-shininess 0..1]"
+          "\n\t\t: [-baseColor RGB] [-baseColorTexture ImagePath]"
+          "\n\t\t: [-emissiveFactor RGB] [-emissiveTexture ImagePath]"
+          "\n\t\t: [-metallic 0..1] [-roughness 0..1] [-metallicRoughnessTexture ImagePath]"
+          "\n\t\t: [-occlusionTexture ImagePath] [-normalTexture ImagePath]"
+          "\n\t\t: [-doubleSided {0|1}]"
+          "\n\t\t: Add material into Document's material table.",
+          __FILE__, XAddVisMaterial, g);
+  di.Add ("XRemoveVisMaterial","Doc Material"
+          "\t: Remove material in document from material table",
+          __FILE__, XRemoveVisMaterial, g);
+  di.Add ("XSetVisMaterial", "Doc Shape Material"
+          "\t: Set material to shape",
+          __FILE__, XSetVisMaterial, g);
+  di.Add ("XUnsetVisMaterial", "Doc Shape"
+          "\t: Unset material from shape",
+          __FILE__, XSetVisMaterial, g);
 }