0030748: Visualization - Marker displayed in immediate layer ruins QT Quick view...
[occt.git] / src / OpenGl / OpenGl_Group.cxx
index c177cde..61ae607 100644 (file)
 #include <OpenGl_GraphicDriver.hxx>
 #include <OpenGl_Flipper.hxx>
 #include <OpenGl_PrimitiveArray.hxx>
+#include <OpenGl_SceneGeometry.hxx>
 #include <OpenGl_StencilTest.hxx>
 #include <OpenGl_Structure.hxx>
 #include <OpenGl_Text.hxx>
 #include <OpenGl_Workspace.hxx>
 
 #include <Graphic3d_ArrayOfPrimitives.hxx>
-#include <Graphic3d_CUserDraw.hxx>
 #include <Graphic3d_GroupDefinitionError.hxx>
 
-IMPLEMENT_STANDARD_HANDLE (OpenGl_Group, Graphic3d_Group)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Group, Graphic3d_Group)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Group,Graphic3d_Group)
+
+namespace
+{
+  //! Render element if it passes the filtering procedure. This method should
+  //! be used for elements which can be used in scope of rendering algorithms.
+  //! E.g. elements of groups during recursive rendering.
+  //! If render filter is null, pure rendering is performed.
+  //! @param theWorkspace [in] the rendering workspace.
+  //! @param theFilter [in] the rendering filter to check whether the element
+  //! should be rendered or not.
+  //! @return True if element passes the check and renders,
+  static bool renderFiltered (const Handle(OpenGl_Workspace)& theWorkspace,
+                              OpenGl_Element* theElement)
+  {
+    if (!theWorkspace->ShouldRender (theElement))
+    {
+      return false;
+    }
+
+    theElement->Render (theWorkspace);
+    return true;
+  }
+}
 
 // =======================================================================
 // function : OpenGl_Group
@@ -36,19 +58,15 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Group, Graphic3d_Group)
 // =======================================================================
 OpenGl_Group::OpenGl_Group (const Handle(Graphic3d_Structure)& theStruct)
 : Graphic3d_Group (theStruct),
-  myAspectLine(NULL),
-  myAspectFace(NULL),
-  myAspectMarker(NULL),
-  myAspectText(NULL),
+  myAspects(NULL),
   myFirst(NULL),
   myLast(NULL),
-  myIsRaytracable (Standard_False),
-  myModificationState (0)
+  myIsRaytracable (Standard_False)
 {
   Handle(OpenGl_Structure) aStruct = Handle(OpenGl_Structure)::DownCast (myStructure->CStructure());
-  if (aStruct == NULL)
+  if (aStruct.IsNull())
   {
-    Graphic3d_GroupDefinitionError::Raise ("OpenGl_Group should be created by OpenGl_Structure!");
+    throw Graphic3d_GroupDefinitionError("OpenGl_Group should be created by OpenGl_Structure!");
   }
 }
 
@@ -62,120 +80,103 @@ OpenGl_Group::~OpenGl_Group()
 }
 
 // =======================================================================
-// function : UpdateAspectLine
+// function : SetGroupPrimitivesAspect
 // purpose  :
 // =======================================================================
-void OpenGl_Group::UpdateAspectLine (const Standard_Boolean theIsGlobal)
+void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect)
 {
-  if (!ContextLine.IsDef)
+  if (IsDeleted())
   {
     return;
   }
 
-  if (theIsGlobal || myFirst == NULL)
+  if (myAspects == NULL)
   {
-    if (myAspectLine == NULL)
-    {
-      myAspectLine = new OpenGl_AspectLine();
-    }
-    myAspectLine->SetAspect (ContextLine);
+    myAspects = new OpenGl_Aspects (theAspect);
   }
   else
   {
-    OpenGl_AspectLine* anAspectLine = new OpenGl_AspectLine();
-    anAspectLine->SetAspect (ContextLine);
-    AddElement (anAspectLine);
+    myAspects->SetAspect (theAspect);
+  }
+
+  if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
+  {
+    aStruct->UpdateStateIfRaytracable (Standard_False);
   }
+
+  Update();
 }
 
 // =======================================================================
-// function : UpdateAspectFace
+// function : SetPrimitivesAspect
 // purpose  :
 // =======================================================================
-void OpenGl_Group::UpdateAspectFace (const Standard_Boolean theIsGlobal)
+void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect)
 {
-  if (!ContextFillArea.IsDef)
+  if (myAspects == NULL)
   {
+    SetGroupPrimitivesAspect (theAspect);
     return;
   }
-
-  if (theIsGlobal || myFirst == NULL)
-  {
-    if (myAspectFace == NULL)
-    {
-      myAspectFace = new OpenGl_AspectFace();
-    }
-    myAspectFace->SetAspect (ContextFillArea);
-  }
-  else
+  else if (IsDeleted())
   {
-    OpenGl_AspectFace* anAspectFace = new OpenGl_AspectFace();
-    anAspectFace->SetAspect (ContextFillArea);
-    AddElement (anAspectFace);
+    return;
   }
 
-  if (myIsRaytracable)
-  {
-    ++myModificationState;
-    OpenGl_Structure* aStruct = GlStruct();
-    if (aStruct != NULL)
-    {
-      aStruct->UpdateStateWithAncestorStructures();
-    }
-  }
+  OpenGl_Aspects* anAspects = new OpenGl_Aspects (theAspect);
+  AddElement (anAspects);
+  Update();
 }
 
 // =======================================================================
-// function : UpdateAspectMarker
+// function : SynchronizeAspects
 // purpose  :
 // =======================================================================
-void OpenGl_Group::UpdateAspectMarker (const Standard_Boolean theIsGlobal)
+void OpenGl_Group::SynchronizeAspects()
 {
-  if (!ContextMarker.IsDef)
+  if (myAspects != NULL)
   {
-    return;
-  }
-
-  if (theIsGlobal || myFirst == NULL)
-  {
-    if (myAspectMarker == NULL)
+    myAspects->SynchronizeAspects();
+    if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
     {
-      myAspectMarker = new OpenGl_AspectMarker();
+      aStruct->UpdateStateIfRaytracable (Standard_False);
     }
-    myAspectMarker->SetAspect (ContextMarker);
   }
-  else
+  for (OpenGl_ElementNode* aNode = myFirst; aNode != NULL; aNode = aNode->next)
   {
-    OpenGl_AspectMarker* anAspectMarker = new OpenGl_AspectMarker();
-    anAspectMarker->SetAspect (ContextMarker);
-    AddElement (anAspectMarker);
+    aNode->elem->SynchronizeAspects();
   }
 }
 
 // =======================================================================
-// function : UpdateAspectText
+// function : ReplaceAspects
 // purpose  :
 // =======================================================================
-void OpenGl_Group::UpdateAspectText (const Standard_Boolean theIsGlobal)
+void OpenGl_Group::ReplaceAspects (const Graphic3d_MapOfAspectsToAspects& theMap)
 {
-  if (!ContextText.IsDef)
+  if (theMap.IsEmpty())
   {
     return;
   }
 
-  if (theIsGlobal || myFirst == NULL)
+  Handle(Graphic3d_Aspects) anAspect;
+  if (myAspects != NULL
+   && theMap.Find (myAspects->Aspect(), anAspect))
   {
-    if (myAspectText == NULL)
+    myAspects->SetAspect (anAspect);
+    if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
     {
-      myAspectText = new OpenGl_AspectText();
+      aStruct->UpdateStateIfRaytracable (Standard_False);
     }
-    myAspectText->SetAspect (ContextText);
   }
-  else
+  for (OpenGl_ElementNode* aNode = myFirst; aNode != NULL; aNode = aNode->next)
   {
-    OpenGl_AspectText* anAspectText = new OpenGl_AspectText();
-    anAspectText->SetAspect (ContextText);
-    AddElement (anAspectText);
+    OpenGl_Aspects* aGlAspect = dynamic_cast<OpenGl_Aspects*> (aNode->elem);
+    if (aGlAspect != NULL
+     && theMap.Find (aGlAspect->Aspect(), anAspect))
+    {
+      aGlAspect->SetAspect (anAspect);
+    }
   }
 }
 
@@ -211,7 +212,7 @@ void OpenGl_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theTy
 void OpenGl_Group::Text (const Standard_CString                  theTextUtf,
                          const Graphic3d_Vertex&                 thePoint,
                          const Standard_Real                     theHeight,
-                         const Quantity_PlaneAngle               theAngle,
+                         const Standard_Real                     theAngle,
                          const Graphic3d_TextPath                theTp,
                          const Graphic3d_HorizontalTextAlignment theHta,
                          const Graphic3d_VerticalTextAlignment   theVta,
@@ -235,33 +236,45 @@ void OpenGl_Group::Text (const Standard_CString                  theTextUtf,
 }
 
 // =======================================================================
-// function : UserDraw
+// function : Text
 // purpose  :
 // =======================================================================
-void OpenGl_Group::UserDraw (const Standard_Address theObject,
-                             const Standard_Boolean theToEvalMinMax,
-                             const Standard_Boolean theContainsFacet)
+void OpenGl_Group::Text (const Standard_CString                  theTextUtf,
+                         const gp_Ax2&                           theOrientation,
+                         const Standard_Real                     theHeight,
+                         const Standard_Real                     theAngle,
+                         const Graphic3d_TextPath                theTp,
+                         const Graphic3d_HorizontalTextAlignment theHTA,
+                         const Graphic3d_VerticalTextAlignment   theVTA,
+                         const Standard_Boolean                  theToEvalMinMax,
+                         const Standard_Boolean                  theHasOwnAnchor)
 {
   if (IsDeleted())
   {
     return;
   }
 
+  OpenGl_TextParam  aParams;
   OpenGl_Structure* aStruct = GlStruct();
-  if (aStruct->GlDriver()->UserDrawCallback() == NULL)
-  {
-    return;
-  }
 
-  Graphic3d_CUserDraw aUserDraw;
-  aUserDraw.Data   = theObject;
-  aUserDraw.Bounds = theToEvalMinMax ? &myBounds : NULL;
-  OpenGl_Element* aUserDrawElem = aStruct->GlDriver()->UserDrawCallback()(&aUserDraw);
-  if (aUserDrawElem != NULL)
-  {
-    AddElement (aUserDrawElem);
-  }
-  Graphic3d_Group::UserDraw (theObject, theToEvalMinMax, theContainsFacet);
+  aParams.Height      = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
+  aParams.HAlign      = theHTA;
+  aParams.VAlign      = theVTA;
+
+  OpenGl_Text* aText = new OpenGl_Text (theTextUtf, theOrientation, aParams, theHasOwnAnchor != Standard_False);
+
+  AddElement (aText);
+
+  Graphic3d_Group::Text (theTextUtf,
+                         theOrientation,
+                         theHeight,
+                         theAngle,
+                         theTp,
+                         theHTA,
+                         theVTA,
+                         theToEvalMinMax,
+                         theHasOwnAnchor);
+
 }
 
 // =======================================================================
@@ -302,14 +315,12 @@ void OpenGl_Group::AddElement (OpenGl_Element* theElem)
 
   if (OpenGl_Raytrace::IsRaytracedElement (aNode))
   {
-    myModificationState++;
     myIsRaytracable = Standard_True;
 
     OpenGl_Structure* aStruct = GlStruct();
     if (aStruct != NULL)
     {
-      aStruct->UpdateStateWithAncestorStructures();
-      aStruct->SetRaytracableWithAncestorStructures();
+      aStruct->UpdateStateIfRaytracable (Standard_False);
     }
   }
 }
@@ -320,34 +331,21 @@ void OpenGl_Group::AddElement (OpenGl_Element* theElem)
 // =======================================================================
 void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
-  // Is rendering in ADD or IMMEDIATE mode?
-  const Handle(OpenGl_RenderFilter)& aFilter = theWorkspace->GetRenderFilter();
-
   // Setup aspects
-  const OpenGl_AspectLine*   aBackAspectLine   = theWorkspace->AspectLine   (Standard_False);
-  const OpenGl_AspectFace*   aBackAspectFace   = theWorkspace->AspectFace   (Standard_False);
-  const OpenGl_AspectMarker* aBackAspectMarker = theWorkspace->AspectMarker (Standard_False);
-  const OpenGl_AspectText*   aBackAspectText   = theWorkspace->AspectText   (Standard_False);
-  Standard_Boolean isLineSet   = myAspectLine   && myAspectLine->RenderFiltered (theWorkspace, aFilter);
-  Standard_Boolean isFaceSet   = myAspectFace   && myAspectFace->RenderFiltered (theWorkspace, aFilter);
-  Standard_Boolean isMarkerSet = myAspectMarker && myAspectMarker->RenderFiltered (theWorkspace, aFilter);
-  Standard_Boolean isTextSet   = myAspectText   && myAspectText->RenderFiltered (theWorkspace, aFilter);
+  theWorkspace->SetAllowFaceCulling (myIsClosed
+                                 && !theWorkspace->GetGlContext()->Clipping().IsClippingOrCappingOn());
+  const OpenGl_Aspects* aBackAspects = theWorkspace->Aspects();
+  const bool isAspectSet = myAspects != NULL && renderFiltered (theWorkspace, myAspects);
 
   // Render group elements
   for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next)
   {
-    aNodeIter->elem->RenderFiltered (theWorkspace, aFilter);
+    renderFiltered (theWorkspace, aNodeIter->elem);
   }
 
   // Restore aspects
-  if (isLineSet)
-    theWorkspace->SetAspectLine (aBackAspectLine);
-  if (isFaceSet)
-    theWorkspace->SetAspectFace (aBackAspectFace);
-  if (isMarkerSet)
-    theWorkspace->SetAspectMarker (aBackAspectMarker);
-  if (isTextSet)
-    theWorkspace->SetAspectText (aBackAspectText);
+  if (isAspectSet)
+    theWorkspace->SetAspects (aBackAspects);
 }
 
 // =======================================================================
@@ -366,6 +364,8 @@ void OpenGl_Group::Clear (const Standard_Boolean theToUpdateStructureMgr)
 
   Release (aCtx);
   Graphic3d_Group::Clear (theToUpdateStructureMgr);
+
+  myIsRaytracable = Standard_False;
 }
 
 // =======================================================================
@@ -378,14 +378,11 @@ void OpenGl_Group::Release (const Handle(OpenGl_Context)& theGlCtx)
   while (myFirst != NULL)
   {
     OpenGl_ElementNode* aNext = myFirst->next;
-    OpenGl_Element::Destroy (theGlCtx, myFirst->elem);
+    OpenGl_Element::Destroy (theGlCtx.get(), myFirst->elem);
     delete myFirst;
     myFirst = aNext;
   }
   myLast = NULL;
 
-  OpenGl_Element::Destroy (theGlCtx, myAspectLine);
-  OpenGl_Element::Destroy (theGlCtx, myAspectFace);
-  OpenGl_Element::Destroy (theGlCtx, myAspectMarker);
-  OpenGl_Element::Destroy (theGlCtx, myAspectText);
+  OpenGl_Element::Destroy (theGlCtx.get(), myAspects);
 }