]> OCCT Git - occt.git/commitdiff
0033504: Visualization - Request OCC function extension AIS_InteractiveObject
authordrochalo <diogo.lopes@opencascade.com>
Mon, 9 Oct 2023 17:18:27 +0000 (18:18 +0100)
committerVadim Glukhikh <vadim.glukhikh@opencascade.com>
Mon, 8 Apr 2024 16:06:05 +0000 (17:06 +0100)
Modified Graphic3d_Group to have own zlayer.
Modified OpenGl multi render stage to check group zlayer.
Modified ZLayer rendering to consider group's zlayer value.
Added functionalities to update zlayer structures.
Added test.

14 files changed:
src/Graphic3d/Graphic3d_CStructure.cxx
src/Graphic3d/Graphic3d_CStructure.hxx
src/Graphic3d/Graphic3d_CView.cxx
src/Graphic3d/Graphic3d_CView.hxx
src/Graphic3d/Graphic3d_Group.cxx
src/Graphic3d/Graphic3d_Group.hxx
src/Graphic3d/Graphic3d_Structure.cxx
src/Graphic3d/Graphic3d_Structure.hxx
src/OpenGl/OpenGl_LayerList.cxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
tests/v3d/materials/bug33504 [new file with mode: 0644]

index 7da948ff3eeeda517741d37ab641d03b447108f1..58bc6e0fb3f482c5ab14300a4f96dbdb8091ad07 100644 (file)
@@ -27,21 +27,23 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CStructure,Standard_Transient)
 //purpose  :
 //=============================================================================
 Graphic3d_CStructure::Graphic3d_CStructure (const Handle(Graphic3d_StructureManager)& theManager)
-: myZLayer         (Graphic3d_ZLayerId_Default),
-  Priority         (Structure_MAX_PRIORITY / 2),
-  PreviousPriority (Structure_MAX_PRIORITY / 2),
-  ContainsFacet    (0),
-  IsInfinite       (0),
-  stick            (0),
-  highlight        (0),
-  visible          (1),
-  HLRValidation    (0),
-  IsForHighlight   (Standard_False),
-  IsMutable        (Standard_False),
-  Is2dText         (Standard_False),
-  myGraphicDriver  (theManager->GraphicDriver()),
-  myIsCulled       (Standard_True),
-  myBndBoxClipCheck(Standard_True)
+: myZLayer            (Graphic3d_ZLayerId_Default),
+  Priority            (Structure_MAX_PRIORITY / 2),
+  PreviousPriority    (Structure_MAX_PRIORITY / 2),
+  ContainsFacet       (0),
+  IsInfinite          (0),
+  stick               (0),
+  highlight           (0),
+  visible             (1),
+  HLRValidation       (0),
+  IsForHighlight      (Standard_False),
+  IsMutable           (Standard_False),
+  Is2dText            (Standard_False),
+  myGraphicDriver     (theManager->GraphicDriver()),
+  myIsCulled          (Standard_True),
+  myBndBoxClipCheck   (Standard_True),
+  myHasGroupZLayer    (Standard_False),
+  myCurrentZLayerMode (Graphic3d_ZLayerId_UNKNOWN)
 {
   Id = myGraphicDriver->NewIdentification();
 }
@@ -85,4 +87,6 @@ void Graphic3d_CStructure::DumpJson (Standard_OStream& theOStream, Standard_Inte
 
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsCulled)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myBndBoxClipCheck)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasGroupZLayer)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCurrentZLayerMode)
 }
index 6ce259927722ecfc2c7c12696ef3a313a59fae24..db15b19a9978aed9494d90c9373f0676903359c7 100644 (file)
@@ -149,7 +149,19 @@ public:
   Standard_Boolean BndBoxClipCheck() const { return myBndBoxClipCheck; }
 
   //! Enable/disable check of object's bounding box clipping before drawing of object.
-  void SetBndBoxClipCheck(Standard_Boolean theBndBoxClipCheck) { myBndBoxClipCheck = theBndBoxClipCheck; }
+  void SetBndBoxClipCheck (Standard_Boolean theBndBoxClipCheck) { myBndBoxClipCheck = theBndBoxClipCheck; }
+
+  //! Returns TRUE if some groups possess different zlayers; FALSE by default;
+  Standard_Boolean HasGroupZLayer() const { return myHasGroupZLayer; }
+
+  //! Set value defining if some groups possess different zlayers;
+  void SetGroupZLayer (Standard_Boolean theValue) { myHasGroupZLayer = theValue; }
+
+  //! Returns the current zlayer that is being rendered; Returns invalid layer if not initialized;
+  Graphic3d_ZLayerId CurrentZLayerMode() const { return myCurrentZLayerMode; }
+
+  //! Set value defining the current zlayer that is being rendered. Set invalid if not rendering;
+  void SetCurrentZLayerMode (const Graphic3d_ZLayerId theValue) const { myCurrentZLayerMode = theValue; }
 
   //! Checks if the structure should be included into BVH tree or not.
   Standard_Boolean IsAlwaysRendered() const
@@ -232,8 +244,10 @@ protected:
   Handle(Graphic3d_SequenceOfHClipPlane) myClipPlanes;
   Handle(Graphic3d_PresentationAttributes) myHighlightStyle; //! Current highlight style; is set only if highlight flag is true
 
-  mutable Standard_Boolean myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse
-  Standard_Boolean myBndBoxClipCheck;  //!< Flag responsible for checking of bounding box clipping before drawing of object
+  mutable Standard_Boolean myIsCulled;            //!< A status specifying is structure needs to be rendered after BVH tree traverse
+  Standard_Boolean myBndBoxClipCheck;             //!< Flag responsible for checking of bounding box clipping before drawing of object
+  Standard_Boolean myHasGroupZLayer;              //!< Flag specifying that some groups might have different zlayers
+  mutable Graphic3d_ZLayerId myCurrentZLayerMode; //!< Index of the zlayer that is being used during render stage for groups
 
 public:
 
index 2219b947e91dfaba7b661fc943ce30a26c23fbd5..6441f4450c5ff35673d43037d0515843e0086c78 100644 (file)
@@ -284,6 +284,12 @@ void Graphic3d_CView::ReCompute (const Handle(Graphic3d_Structure)& theStruct)
     InvalidateBVHData (aLayerId);
   }
 
+  if (theStruct->CStructure()->HasGroupZLayer())
+  {
+    updateStructure (theStruct->CStructure(), theStruct->DisplayPriority());
+    return;
+  }
+
   if (!ComputedMode()
    || !IsActive()
    || !theStruct->IsDisplayed())
index 07f48f47cbbaa0bed6ce407243d51098c4cd1f79..9c57b756e08148108fbcd7558e4071d84900fff2 100644 (file)
@@ -540,6 +540,10 @@ public: //! @name obsolete Graduated Trihedron functionality
 
 private:
 
+  //! Updates the structure for display lists of the view.
+  virtual void updateStructure (const Handle(Graphic3d_CStructure)& theStructure,
+                                const Standard_Integer thePriority) = 0;
+
   //! Adds the structure to display lists of the view.
   virtual void displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
                                  const Standard_Integer thePriority) = 0;
index 9ea7a7d29ba44608df87831f3cf0b38f15838e94..59f144cb16bed5f2c03d90527ebca6d77f0a6164 100644 (file)
@@ -49,7 +49,8 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Group,Standard_Transient)
 Graphic3d_Group::Graphic3d_Group (const Handle(Graphic3d_Structure)& theStruct)
 : myStructure     (theStruct.operator->()),
   myIsClosed      (false),
-  myContainsFacet (false)
+  myContainsFacet (false),
+  myZLayerId      (Graphic3d_ZLayerId_UNKNOWN)
 {
   //
 }
@@ -307,6 +308,21 @@ void Graphic3d_Group::Marker (const Graphic3d_Vertex& thePoint,
   AddPrimitiveArray (aPoints, theToEvalMinMax);
 }
 
+//=======================================================================
+//function : SetZLayer
+//purpose  : Set the value of the ZLayer for the group structure
+//           and update zlayer structures
+//=======================================================================
+void Graphic3d_Group::SetZLayer (const Graphic3d_ZLayerId theLayerId, Standard_Boolean theToUpdate)
+{
+  myZLayerId = theLayerId;
+  myStructure->myCStructure->SetGroupZLayer (Standard_True);
+  if (theToUpdate)
+  {
+    myStructure->ReCompute();
+  }
+}
+
 // =======================================================================
 // function : Text
 // purpose  :
@@ -463,4 +479,5 @@ void Graphic3d_Group::DumpJson (Standard_OStream& theOStream, Standard_Integer t
 
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsClosed)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myContainsFacet)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerId)
 }
index fb6748302edb32fa49a0635d5c12d3e911357c76..87a5d8799df6bdd7c5f6b4ec3efc3b1f00d4615b 100644 (file)
@@ -32,6 +32,7 @@
 #include <Graphic3d_IndexBuffer.hxx>
 #include <Graphic3d_Buffer.hxx>
 #include <Graphic3d_BoundBuffer.hxx>
+#include <Graphic3d_ZLayerId.hxx>
 #include <gp_Ax2.hxx>
 #include <TCollection_ExtendedString.hxx>
 
@@ -128,6 +129,14 @@ public:
   //! Creates a primitive array with single marker using AddPrimitiveArray().
   Standard_EXPORT void Marker (const Graphic3d_Vertex& thePoint, const Standard_Boolean theToEvalMinMax = Standard_True);
 
+  //! Get ID of Z layer for main presentation.
+  Standard_EXPORT Graphic3d_ZLayerId GetZLayer() const { return myZLayerId; }
+
+  //! Set Z layer ID and update all presentations of the presentable object.
+  //! The layers mechanism allows drawing objects in higher layers in overlay of objects in lower layers.
+  //! @theToUpdate is used to check if the group zlayer setting requires the updating in the zlayers list (FALSE by default).
+  Standard_EXPORT virtual void SetZLayer (const Graphic3d_ZLayerId theLayerId, Standard_Boolean theToUpdate = Standard_False);
+
 public:
 
   //! sets the stencil test to theIsEnabled state;
@@ -294,7 +303,7 @@ protected:
   Graphic3d_BndBox4f   myBounds;        //!< bounding box
   bool                 myIsClosed;      //!< flag indicating closed volume
   bool                 myContainsFacet; //!< flag indicating that this group contains face primitives
-
+  Graphic3d_ZLayerId   myZLayerId;      //!< current zlayer ID for this group
 };
 
 DEFINE_STANDARD_HANDLE(Graphic3d_Group, Standard_Transient)
index 3aa4780fdb3630b27c926008207dc792a76bf2c8..88eb43b4fb7f7adb610a954904eb06b0e1e4556f 100644 (file)
@@ -1023,7 +1023,7 @@ void Graphic3d_Structure::Update (const bool theUpdateLayer) const
 //function : SetZLayer
 //purpose  :
 //=======================================================================
-void Graphic3d_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerId)
+void Graphic3d_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerId, const Standard_Boolean theToPropagate)
 {
   // if the structure is not displayed, unable to change its display layer
   if (IsDeleted ())
@@ -1031,6 +1031,13 @@ void Graphic3d_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerId)
 
   myStructureManager->ChangeZLayer (this, theLayerId);
   myCStructure->SetZLayer (theLayerId);
+  if (theToPropagate)
+  {
+    for (Graphic3d_SequenceOfGroup::Iterator aGroupIter(Groups()); aGroupIter.More(); aGroupIter.Next())
+    {
+      aGroupIter.Value()->SetZLayer (theLayerId, Standard_True);
+    }
+  }
 }
 
 //=======================================================================
index facfcd281ed02e8a6e83e756f14efebd6dc683bc..455c4f460d17536b875447d2766080776d004c28 100644 (file)
@@ -135,7 +135,8 @@ public:
   //! allows to display structures presented in higher layers in overlay
   //! of structures in lower layers by switching off z buffer depth
   //! test between layers
-  Standard_EXPORT void SetZLayer (const Graphic3d_ZLayerId theLayerId);
+  //! @theToPropagate - flag to determine if structure zlayer should be the same for every group (TRUE by default.)
+  Standard_EXPORT void SetZLayer (const Graphic3d_ZLayerId theLayerId, const Standard_Boolean theToPropagate = Standard_True);
   
   //! Get Z layer ID of displayed structure.
   //! The method returns -1 if the structure has no ID (deleted from graphic driver).
index bd4708de1fda3279410a369f4596c2b31dd5f97c..2dfe7bf00d0ce5df7c492189c19a2ad8a7c40691 100644 (file)
@@ -319,6 +319,32 @@ void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
 
   Standard_Integer aPriority = -1;
 
+  // Check if structure has groups in multiple zlayers.
+  if (theStructure->HasGroupZLayer())
+  {
+    // Remove every reference of this structure from all zlayers
+    for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter(myLayers); aLayerIter.More(); aLayerIter.Next())
+    {
+      const Handle(Graphic3d_Layer)& aLayerEx = aLayerIter.ChangeValue();
+
+      if (aLayerEx->Remove (theStructure, aPriority))
+      {
+        --myNbStructures;
+        if (aLayerEx->IsImmediate())
+        {
+          --myImmediateNbStructures;
+        }
+
+        if (aLayerEx->LayerSettings().IsRaytracable()
+          && theStructure->IsRaytracable())
+        {
+          ++myModifStateOfRaytraceable;
+        }
+      }
+    }
+    return;
+  }
+
   // remove structure from associated list
   // if the structure is not found there,
   // scan through layers and remove it
@@ -658,7 +684,11 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
       {
         continue;
       }
-
+      // Check if within the structure, there are multiple groups assigned to different zlayers.
+      if (aStruct->HasGroupZLayer())
+      {
+        aStruct->SetCurrentZLayerMode (theLayer.LayerId());
+      }
       aStruct->Render (theWorkspace);
     }
   }
index b7533c16ffd00a68b526d50e42902d85978e99c0..29db04118090a5b6ba5fb7a704b3bce5b6157d30 100644 (file)
@@ -388,11 +388,14 @@ void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorksp
   {
     myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
   }
-
   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
-    aGroupIter.Value()->Render (theWorkspace);
+    Handle(OpenGl_Group) aGroup = aGroupIter.Value();
+    theHasClosed = theHasClosed || aGroup->IsClosed();
+    if (aGroup->GetZLayer() == CurrentZLayerMode())
+    {
+      aGroup->Render (theWorkspace);
+    }
   }
 }
 
index 25e5eb6ab211d31908d4b85c47b52dadaeeae40f..5ee69294964f6293fc4bc63051c6e2b2356488d2 100644 (file)
@@ -763,6 +763,27 @@ void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo,
   aFrameBuffer->ChangeViewport (theWidth, theHeight);
 }
 
+
+//=======================================================================
+//function : updateStructure
+//purpose  :
+//=======================================================================
+void OpenGl_View::updateStructure (const Handle(Graphic3d_CStructure)& theStructure,
+                                   const Standard_Integer thePriority)
+{
+  if (theStructure->HasGroupZLayer())
+  {
+    static Standard_Integer aDummyPriority;
+    // Remove existing structure references before adding them in case 
+    // there were changes in a group's zlayer.
+    for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter(myZLayers.Layers()); aLayerIter.More(); aLayerIter.Next())
+    {
+      aLayerIter.Value()->Remove (theStructure.get(), aDummyPriority);
+    }
+    displayStructure (theStructure, thePriority);
+  }
+}
+
 //=======================================================================
 //function : displayStructure
 //purpose  :
@@ -770,9 +791,26 @@ void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo,
 void OpenGl_View::displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
                                     const Standard_Integer              thePriority)
 {
-  const OpenGl_Structure*  aStruct = static_cast<const OpenGl_Structure*> (theStructure.get());
-  const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer();
-  myZLayers.AddStructure (aStruct, aZLayer, thePriority);
+  const OpenGl_Structure* aStruct = static_cast<const OpenGl_Structure*> (theStructure.get());
+  Graphic3d_SequenceOfGroup aSeqGroups = aStruct->Groups();
+  if (aStruct->HasGroupZLayer())
+  {
+    // Add structure reference to the different zlayers that each group is assigned to.
+    NCollection_List<Graphic3d_ZLayerId> aZList;
+    for (OpenGl_Structure::GroupIterator aGroupIter(aSeqGroups); aGroupIter.More(); aGroupIter.Next())
+    {
+      Graphic3d_ZLayerId aLayerId = aGroupIter.Value()->GetZLayer();
+      if (!aZList.Contains(aLayerId))
+      {
+        aZList.Append (aLayerId);
+        myZLayers.AddStructure (aStruct, aLayerId, thePriority);
+      }
+    }
+  }
+  else
+  {
+    myZLayers.AddStructure (aStruct, aStruct->ZLayer(), thePriority);
+  }
 }
 
 //=======================================================================
index ebaed8983ff923c24a8bd5baeb6924c6e2a0cd68..e5a0cd1410248a32d937eeecbec1819d7775ffb5 100644 (file)
@@ -429,6 +429,10 @@ protected: //! @name Rendering of GL graphics (with prepared drawing buffer).
 
 private:
 
+  //! Updates the structure for display lists of the view.
+  Standard_EXPORT virtual void updateStructure (const Handle(Graphic3d_CStructure)& theStructure,
+                                                const Standard_Integer thePriority) Standard_OVERRIDE;
+
   //! Adds the structure to display lists of the view.
   Standard_EXPORT virtual void displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
                                                  const Standard_Integer thePriority) Standard_OVERRIDE;
index cf6f8abf5e16890e837aadf97f12f2f4439b2ac5..b31597675aed3c24a5a272fb4208dda586496c14 100644 (file)
 #include <Graphic3d_AttribBuffer.hxx>
 #include <Graphic3d_AspectMarker3d.hxx>
 #include <Graphic3d_Group.hxx>
+#include <Graphic3d_Text.hxx>
 #include <Standard_Real.hxx>
 
 #include <AIS_Circle.hxx>
@@ -6844,6 +6845,142 @@ static int VNormals (Draw_Interpretor& theDI,
   return 0;
 }
 
+//=======================================================================
+//function : vAddGroup
+//purpose  : add group to existing interactive object
+//=======================================================================
+static int vAddGroup (Draw_Interpretor& /*theDI*/, Standard_Integer theNbArgs, const char** theArgVec)
+{
+  const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
+  const Handle(V3d_View)& aView = ViewerTest::CurrentView();
+  if (aContext.IsNull() || aView.IsNull())
+  {
+    Message::SendFail ("Error: no active viewer");
+    return 1;
+  }
+
+  if (theNbArgs < 3)
+  {
+    Message::SendFail ("Error: wrong number of arguments.");
+    return 1;
+  }
+
+  Standard_Integer anArgIter = 1;
+  Handle(AIS_InteractiveObject) anObj;
+
+  const TCollection_AsciiString aName (theArgVec[anArgIter++]);
+  GetMapOfAIS().Find2 (aName, anObj);
+  if (anObj.IsNull())
+  {
+    Message::SendFail() << "Error: object '" << aName << "' is not displayed";
+    return 1;
+  }
+  // Check for zlayer and color parameters.
+  Quantity_Color aColor(Quantity_NOC_INDIANRED);
+  Graphic3d_ZLayerId aLayerID = anObj->ZLayer();
+  for (Standard_Integer anIter = anArgIter; anIter < theNbArgs; ++anIter)
+  {
+    const TCollection_AsciiString anArg(theArgVec[anIter]);
+    if (anArg == "-zlayer")
+    {
+      if (!ViewerTest::ParseZLayer (theArgVec[++anIter], aLayerID))
+      {
+        Message::SendFail() << "Specified zlayer does not exist.";
+        return 1;
+      }
+      if (aLayerID == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        std::cout << "Warning: you set this group with unknown zlayer.";
+        aLayerID = anObj->ZLayer();
+      }
+    }
+    else if (anArg == "-color")
+    {
+      if (theNbArgs - anIter > 3)
+      {
+        Standard_Integer aNbParsed = Draw::ParseColor (3, theArgVec + anIter + 1, aColor);
+        if (aNbParsed == 0)
+        {
+          Message::SendFail() << "Syntax error for color.";
+          return 1;
+        }
+      }
+      else
+      {
+        std::cout << "\nIncorrect number of color values (RGB).\n";
+      }
+
+    }
+  }
+  // For the given type create primitive.
+  const TCollection_AsciiString aType(theArgVec[anArgIter++]);
+  if (aType == "quad")
+  {
+    if (theNbArgs < 8)
+    {
+      Message::SendFail ("Error: wrong number of arguments for quad group.");
+      return 1;
+    }
+    if (anObj->Presentation().IsNull())
+    {
+      Message::SendFail ("Error: Interactive object does not have current presentation.");
+      return 1;
+    }
+    // Get quad dimensions
+    Handle(Graphic3d_Group) aNewGroup = anObj->Presentation()->NewGroup();
+    Standard_Real aPx = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aPy = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aDx = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aDy = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aZ = Draw::Atof (theArgVec[anArgIter++]);
+
+    aNewGroup->SetZLayer (aLayerID, Standard_True);
+    Handle(Prs3d_LineAspect) anAspectQuadTop = new Prs3d_LineAspect(aColor, (Aspect_TypeOfLine)0, 2.0);
+    aNewGroup->SetGroupPrimitivesAspect (anAspectQuadTop->Aspect());
+    Handle(Graphic3d_ArrayOfTriangles) aPrim = new Graphic3d_ArrayOfTriangles(4, 6, Graphic3d_ArrayFlags_None);
+    aPrim->AddVertex (aPx - aDx, aPy, aZ);
+    aPrim->AddVertex (aPx + aDx, aPy, aZ);
+    aPrim->AddVertex (aPx, aPy + aDy, aZ);
+    aPrim->AddVertex (aPx, aPy - aDy, aZ);
+    aPrim->AddEdges (1, 2, 3);
+    aPrim->AddEdges (1, 2, 4);
+    aNewGroup->AddPrimitiveArray (aPrim);
+  }
+  else if (aType == "text")
+  {
+    if (theNbArgs < 8)
+    {
+      Message::SendFail ("Error: wrong number of arguments for text group.");
+      return 1;
+    }
+    if (anObj->Presentation().IsNull())
+    {
+      Message::SendFail ("Error: Interactive object does not have current presentation.");
+      return 1;
+    }
+    // Get text properties
+    Handle(Graphic3d_Group) aNewGroup = anObj->Presentation()->NewGroup();
+    const TCollection_AsciiString aTextValue (theArgVec[anArgIter++]);
+    Standard_Real aPx = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aPy = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aPz = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aHeight = Draw::Atof (theArgVec[anArgIter++]);
+
+    aNewGroup->SetZLayer (aLayerID, Standard_True);
+    Handle(Graphic3d_AspectText3d) aTextAspect = new Graphic3d_AspectText3d (aColor, Font_NOF_MONOSPACE, 1.0, 0.0);
+    aNewGroup->SetGroupPrimitivesAspect (aTextAspect);
+    Graphic3d_Vertex aMarker (aPx, aPy, aPz);
+    Handle(Graphic3d_Text) aText = new Graphic3d_Text (aHeight);
+    aText->SetText (aTextValue);
+    aText->SetOrientation (gp_Ax2(gp_Pnt(aPx, aPy, aPz), gp::DZ()));
+    aText->SetOwnAnchorPoint (Standard_False);
+    aNewGroup->AddText (aText);
+  }
+  aContext->Display (anObj, Standard_True);
+  return 0;
+}
+
+
 //=======================================================================
 //function : ObjectsCommands
 //purpose  :
@@ -7235,4 +7372,12 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
                    "\n\t\t:        [-useMesh] [-oriented {0}1}=0]"
                    "\n\t\t:  Displays/Hides normals calculated on shape geometry or retrieved from triangulation",
                    __FILE__, VNormals, group);
+
+  theCommands.Add ("vaddgroup",
+                   "vaddgroup name [type=quad|text] -zlayer=value\n"
+                   "quad: [x y dx dy depth color]\n"
+                   "text: [val px py pz height color]\n"
+                   "zlayer id of the zlayer\n"
+                   "add graphic3d_group to existing object",
+                   __FILE__, vAddGroup, group);
 }
diff --git a/tests/v3d/materials/bug33504 b/tests/v3d/materials/bug33504
new file mode 100644 (file)
index 0000000..55437e6
--- /dev/null
@@ -0,0 +1,37 @@
+puts "========"
+puts "0033504: Visualization - Request OCC function extension AIS_InteractiveObject"
+puts "========"
+puts ""
+
+pload MODELING VISUALIZATION
+vclear
+vinit
+vcylinder cyl 1 2 10 -nbSlices 100
+box b1 5 5 5 3 3 3
+vdisplay b1 -dispmode 1 -layer 0
+vobjzlayer set b1 -2
+vobjzlayer set b1 0
+vfit
+#add groups with different zlayer settings
+vaddgroup b1 quad 5 5 1 1 3 -zlayer 0 -color 0.0 0.0 1.0
+vaddgroup b1 quad 5 5 1 1 5 -zlayer -3 -color 0.0 1.0 0.0
+vaddgroup b1 quad 5 5 1 1 7 -zlayer -2 -color 1.0 0.0 0.0
+vaddgroup b1 text myKindOfText 5 5 10 20 -zlayer -4 -color 1.0 0.0 1.0
+
+#general perspective
+vviewparams -scale 40.0 -proj 0.0 -1.0 1.0 -up 0.0 0.0 1.0 -at 2.5 2.5 0.0
+vdump $imagedir/${casename}_generalperpective.png
+#front perspective
+vviewparams -scale 40.0 -proj 0.0 0.0 1.0 -up 0.0 0.0 1.0 -at 2.5 2.5 0.0
+if { [vreadpixel 245 150 rgb name] != "GREEN" } { puts "Error: Green quad should be visible." }
+vdump $imagedir/${casename}_front.png
+#back perspective
+vviewparams -scale 40.0 -proj 0.0 0.0 -1.0 -up 0.0 0.0 1.0 -at 2.5 2.5 0.0
+if { [vreadpixel 165 150 rgb name] != "GREEN" } { puts "Error: Green quad should be visible." }
+vdump $imagedir/${casename}_back.png
+#front cylinder
+vviewparams -scale 40.0 -proj -1.0 -1.0 -0.6 -up 0.0 0.0 1.0 -at -2.5 -2.5 0.0
+vdump $imagedir/${casename}_cylinderperpective.png
+#different perspective
+vviewparams -scale 40.0 -proj -1.0 -1.0 -1.9 -up 0.0 0.0 1.0 -at -0.5 -0.5 0.0
+vdump $imagedir/${casename}_generalperspective2.png