0030698: Volume Rendering - Early clipping of volume object's bounding box
[occt.git] / src / OpenGl / OpenGl_Structure.cxx
index 9d93bff..927a4a0 100644 (file)
@@ -16,6 +16,7 @@
 #include <OpenGl_CappingAlgo.hxx>
 #include <OpenGl_Context.hxx>
 #include <OpenGl_GlCore11.hxx>
+#include <OpenGl_ClippingIterator.hxx>
 #include <OpenGl_GraphicDriver.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_View.hxx>
 #include <OpenGl_Workspace.hxx>
 
-#include <Graphic3d_SequenceOfHClipPlane.hxx>
-
-
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
 
-//! Auxiliary class for bounding box presentation
-class OpenGl_BndBoxPrs : public OpenGl_Element
+// =======================================================================
+// function : renderBoundingBox
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::renderBoundingBox (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
-
-public:
-
-  //! Main constructor
-  OpenGl_BndBoxPrs (const Graphic3d_BndBox4f& theBndBox)
-  {
-    const float Xm = theBndBox.CornerMin().x();
-    const float Ym = theBndBox.CornerMin().y();
-    const float Zm = theBndBox.CornerMin().z();
-    const float XM = theBndBox.CornerMax().x();
-    const float YM = theBndBox.CornerMax().y();
-    const float ZM = theBndBox.CornerMax().z();
-
-    myVerts[0]  = OpenGl_Vec3 (Xm, Ym, Zm);
-    myVerts[1]  = OpenGl_Vec3 (Xm, Ym, ZM);
-    myVerts[2]  = OpenGl_Vec3 (Xm, YM, ZM);
-    myVerts[3]  = OpenGl_Vec3 (Xm, YM, Zm);
-    myVerts[4]  = OpenGl_Vec3 (Xm, Ym, Zm);
-    myVerts[5]  = OpenGl_Vec3 (XM, Ym, Zm);
-    myVerts[6]  = OpenGl_Vec3 (XM, Ym, ZM);
-    myVerts[7]  = OpenGl_Vec3 (XM, YM, ZM);
-    myVerts[8]  = OpenGl_Vec3 (XM, YM, Zm);
-    myVerts[9]  = OpenGl_Vec3 (XM, Ym, Zm);
-    myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
-    myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
-    myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
-    myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
-    myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
-    myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
-  }
-
-  //! Render presentation
-  virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const
+  if (!myBndBox.IsValid())
   {
-  #if !defined(GL_ES_VERSION_2_0)
-    // Apply line aspect
-    const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
-
-    glDisable (GL_LIGHTING);
-
-    // Use highlight colors
-    theWorkspace->GetGlContext()->core11->glColor3fv (theWorkspace->LineColor().rgb);
-
-    glEnableClientState (GL_VERTEX_ARRAY);
-    glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
-    glDrawArrays (GL_LINE_STRIP, 0, 16);
-    glDisableClientState (GL_VERTEX_ARRAY);
-
-    // restore aspects
-    if (!aPrevTexture.IsNull())
-    {
-      theWorkspace->EnableTexture (aPrevTexture);
-    }
-  #else
-    (void )theWorkspace;
-  #endif
-  }
-
-  //! Release graphical resources
-  virtual void Release (OpenGl_Context*)
-  {
-    //
+    return;
   }
 
-protected:
-
-  //! Protected destructor
-  virtual ~OpenGl_BndBoxPrs() {}
-
-private:
-
-  OpenGl_Vec3 myVerts[16]; //!< vertices array
-
-public:
-
-  DEFINE_STANDARD_ALLOC
-
-};
-
-/*----------------------------------------------------------------------*/
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
+  const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
+  const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
+  const Graphic3d_Vec3d aMoveVec = myTrsfPers.IsNull()
+                               && !aLayer.OriginTransformation().IsNull()
+                                 ? -Graphic3d_Vec3d (aLayer.Origin().X(), aLayer.Origin().Y(), aLayer.Origin().Z())
+                                 :  Graphic3d_Vec3d (0.0, 0.0, 0.0);
+  if (aCtx->core20fwd != NULL
+   && aCtx->ShaderManager()->BindBoundBoxProgram())
+  {
+    const Graphic3d_Vec3d aCenter = myBndBox.Center() + aMoveVec;
+    const Graphic3d_Vec3d aSize   = myBndBox.Size();
+    aCtx->ActiveProgram()->SetUniform (aCtx, "occBBoxCenter", Graphic3d_Vec3 ((float )aCenter.x(), (float )aCenter.y(), (float )aCenter.z()));
+    aCtx->ActiveProgram()->SetUniform (aCtx, "occBBoxSize",   Graphic3d_Vec3 ((float )aSize.x(),   (float )aSize.y(),   (float )aSize.z()));
+    aCtx->SetColor4fv (theWorkspace->InteriorColor());
+
+    const Handle(OpenGl_VertexBuffer)& aBoundBoxVertBuffer = aCtx->ShaderManager()->BoundBoxVertBuffer();
+    aBoundBoxVertBuffer->BindAttribute  (aCtx, Graphic3d_TOA_POS);
+    aCtx->core20fwd->glDrawArrays (GL_LINES, 0, aBoundBoxVertBuffer->GetElemsNb());
+    aBoundBoxVertBuffer->UnbindAttribute(aCtx, Graphic3d_TOA_POS);
+  }
+#if !defined(GL_ES_VERSION_2_0)
+  else if (aCtx->core11 != NULL)
+  {
+    const Graphic3d_Vec3d aMind = myBndBox.CornerMin() + aMoveVec;
+    const Graphic3d_Vec3d aMaxd = myBndBox.CornerMax() + aMoveVec;
+    const Graphic3d_Vec3 aMin ((float )aMind.x(), (float )aMind.y(), (float )aMind.z());
+    const Graphic3d_Vec3 aMax ((float )aMaxd.x(), (float )aMaxd.y(), (float )aMaxd.z());
+    const OpenGl_Vec3 aVerts[16] =
+    {
+      OpenGl_Vec3 (aMin.x(), aMin.y(), aMin.z()),
+      OpenGl_Vec3 (aMin.x(), aMin.y(), aMax.z()),
+      OpenGl_Vec3 (aMin.x(), aMax.y(), aMax.z()),
+      OpenGl_Vec3 (aMin.x(), aMax.y(), aMin.z()),
+      OpenGl_Vec3 (aMin.x(), aMin.y(), aMin.z()),
+      OpenGl_Vec3 (aMax.x(), aMin.y(), aMin.z()),
+      OpenGl_Vec3 (aMax.x(), aMin.y(), aMax.z()),
+      OpenGl_Vec3 (aMax.x(), aMax.y(), aMax.z()),
+      OpenGl_Vec3 (aMax.x(), aMax.y(), aMin.z()),
+      OpenGl_Vec3 (aMax.x(), aMin.y(), aMin.z()),
+      OpenGl_Vec3 (aMax.x(), aMax.y(), aMin.z()),
+      OpenGl_Vec3 (aMin.x(), aMax.y(), aMin.z()),
+      OpenGl_Vec3 (aMin.x(), aMax.y(), aMax.z()),
+      OpenGl_Vec3 (aMax.x(), aMax.y(), aMax.z()),
+      OpenGl_Vec3 (aMax.x(), aMin.y(), aMax.z()),
+      OpenGl_Vec3 (aMin.x(), aMin.y(), aMax.z())
+    };
+
+    aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID, Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, false, Handle(OpenGl_ShaderProgram)());
+    aCtx->SetColor4fv (theWorkspace->InteriorColor());
+    aCtx->core11fwd->glDisable (GL_LIGHTING);
+    aCtx->core11->glEnableClientState (GL_VERTEX_ARRAY);
+    aCtx->core11->glVertexPointer (3, GL_FLOAT, 0, aVerts[0].GetData());
+    aCtx->core11fwd->glDrawArrays (GL_LINE_STRIP, 0, 16);
+    aCtx->core11->glDisableClientState (GL_VERTEX_ARRAY);
+  }
+#endif
+  aCtx->BindTextures (aPrevTexture);
+}
 
 // =======================================================================
 // function : OpenGl_Structure
@@ -119,14 +104,12 @@ public:
 // =======================================================================
 OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
 : Graphic3d_CStructure (theManager),
-  myHighlightColor     (NULL),
   myInstancedStructure (NULL),
   myIsRaytracable      (Standard_False),
   myModificationState  (0),
-  myIsCulled           (Standard_True),
   myIsMirrored         (Standard_False)
 {
-  //
+  updateLayerTransformation();
 }
 
 // =======================================================================
@@ -139,115 +122,88 @@ OpenGl_Structure::~OpenGl_Structure()
 }
 
 // =======================================================================
-// function : UpdateTransformation
+// function : SetZLayer
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::UpdateTransformation()
+void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex)
 {
-  const OpenGl_Mat4& aMat = Graphic3d_CStructure::Transformation;
-  Standard_ShortReal aDet =
-    aMat.GetValue(0, 0) * (aMat.GetValue(1, 1) * aMat.GetValue(2, 2) - aMat.GetValue(2, 1) * aMat.GetValue(1, 2)) -
-    aMat.GetValue(0, 1) * (aMat.GetValue(1, 0) * aMat.GetValue(2, 2) - aMat.GetValue(2, 0) * aMat.GetValue(1, 2)) +
-    aMat.GetValue(0, 2) * (aMat.GetValue(1, 0) * aMat.GetValue(2, 1) - aMat.GetValue(2, 0) * aMat.GetValue(1, 1));
-
-  // Determinant of transform matrix less then 0 means that mirror transform applied.
-  myIsMirrored = aDet < 0.0f;
-
-  if (IsRaytracable())
-  {
-    ++myModificationState;
-  }
+  Graphic3d_CStructure::SetZLayer (theLayerIndex);
+  updateLayerTransformation();
 }
 
 // =======================================================================
-// function : clearHighlightBox
+// function : SetTransformation
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
+void OpenGl_Structure::SetTransformation (const Handle(Geom_Transformation)& theTrsf)
 {
-  if (!myHighlightBox.IsNull())
+  myTrsf = theTrsf;
+  myIsMirrored = Standard_False;
+  if (!myTrsf.IsNull())
+  {
+    // Determinant of transform matrix less then 0 means that mirror transform applied.
+    const Standard_Real aDet = myTrsf->Value(1, 1) * (myTrsf->Value (2, 2) * myTrsf->Value (3, 3) - myTrsf->Value (3, 2) * myTrsf->Value (2, 3))
+                             - myTrsf->Value(1, 2) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 3) - myTrsf->Value (3, 1) * myTrsf->Value (2, 3))
+                             + myTrsf->Value(1, 3) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 2) - myTrsf->Value (3, 1) * myTrsf->Value (2, 2));
+    myIsMirrored = aDet < 0.0;
+  }
+
+  updateLayerTransformation();
+  if (IsRaytracable())
   {
-    myHighlightBox->Release (theGlCtx);
-    myHighlightBox.Nullify();
+    ++myModificationState;
   }
 }
 
 // =======================================================================
-// function : HighlightWithColor
+// function : SetTransformPersistence
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3&  theColor,
-                                           const Standard_Boolean theToCreate)
+void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
 {
-  const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
-  if (theToCreate)
-    setHighlightColor   (aContext, theColor);
-  else
-    clearHighlightColor (aContext);
+  myTrsfPers = theTrsfPers;
+  updateLayerTransformation();
 }
 
 // =======================================================================
-// function : HighlightWithBndBox
+// function : updateLayerTransformation
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
-                                            const Standard_Boolean             theToCreate)
+void OpenGl_Structure::updateLayerTransformation()
 {
-  const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
-  if (!theToCreate)
+  gp_Trsf aRenderTrsf;
+  if (!myTrsf.IsNull())
   {
-    clearHighlightBox (aContext);
-    return;
+    aRenderTrsf = myTrsf->Trsf();
   }
 
-  if (!myHighlightBox.IsNull())
+  const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
+  if (!aLayer.OriginTransformation().IsNull()
+    && myTrsfPers.IsNull())
   {
-    myHighlightBox->Release (aContext);
+    aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin());
   }
-  else
-  {
-    myHighlightBox = new OpenGl_Group (theStruct);
-  }
-
-  CALL_DEF_CONTEXTLINE& aContextLine = myHighlightBox->ChangeContextLine();
-  aContextLine.IsDef    = 1;
-  aContextLine.Color    = HighlightColor;
-  aContextLine.LineType = Aspect_TOL_SOLID;
-  aContextLine.Width    = 1.0f;
-  myHighlightBox->UpdateAspectLine (Standard_True);
-
-  OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
-  myHighlightBox->AddElement (aBndBoxPrs);
+  aRenderTrsf.GetMat4 (myRenderTrsf);
 }
 
 // =======================================================================
-// function : setHighlightColor
+// function : GraphicHighlight
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::setHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
-                                          const Graphic3d_Vec3&         theColor)
+void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle)
 {
-  clearHighlightBox (theGlCtx);
-  if (myHighlightColor == NULL)
-  {
-    myHighlightColor = new TEL_COLOUR();
-  }
-
-  myHighlightColor->rgb[0] = theColor.r();
-  myHighlightColor->rgb[1] = theColor.g();
-  myHighlightColor->rgb[2] = theColor.b();
-  myHighlightColor->rgb[3] = 1.F;
+  myHighlightStyle = theStyle;
+  highlight = 1;
 }
 
 // =======================================================================
-// function : clearHighlightColor
+// function : GraphicUnhighlight
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::clearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
+void OpenGl_Structure::GraphicUnhighlight()
 {
-  clearHighlightBox(theGlCtx);
-  delete myHighlightColor;
-  myHighlightColor = NULL;
+  highlight = 0;
+  myHighlightStyle.Nullify();
 }
 
 // =======================================================================
@@ -268,16 +224,14 @@ void OpenGl_Structure::OnVisibilityChanged()
 // =======================================================================
 Standard_Boolean OpenGl_Structure::IsRaytracable() const
 {
-  if (!myGroups.IsEmpty())
+  if (!myGroups.IsEmpty()
+    && myIsRaytracable)
   {
-    return myIsRaytracable; // geometry structure
-  }
-  else if (myInstancedStructure != NULL)
-  {
-    return myInstancedStructure->IsRaytracable(); // instance structure
+    return Standard_True;
   }
 
-  return Standard_False; // has no any groups or structures
+  return myInstancedStructure != NULL
+     &&  myInstancedStructure->IsRaytracable();
 }
 
 // =======================================================================
@@ -286,7 +240,18 @@ Standard_Boolean OpenGl_Structure::IsRaytracable() const
 // =======================================================================
 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
 {
-  myIsRaytracable = !toCheck || OpenGl_Raytrace::IsRaytracedStructure (this);
+  myIsRaytracable = !toCheck;
+  if (!myIsRaytracable)
+  {
+    for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
+    {
+      if (anIter.Value()->IsRaytracable())
+      {
+        myIsRaytracable = Standard_True;
+        break;
+      }
+    }
+  }
 
   if (IsRaytracable())
   {
@@ -430,26 +395,6 @@ void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorksp
   }
 }
 
-// =======================================================================
-// function : renderClosedGeometry
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::renderClosedGeometry (const Handle(OpenGl_Workspace)& theWorkspace) const
-{
-  if (myInstancedStructure != NULL)
-  {
-    myInstancedStructure->renderClosedGeometry (theWorkspace);
-  }
-
-  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
-  {
-    if (aGroupIter.Value()->IsClosed())
-    {
-      aGroupIter.Value()->Render (theWorkspace);
-    }
-  }
-}
-
 // =======================================================================
 // function : Render
 // purpose  :
@@ -465,44 +410,56 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
 
   // Render named status
-  if (highlight)
+  if (highlight && !myHighlightStyle.IsNull() && myHighlightStyle->Method() != Aspect_TOHM_BOUNDBOX)
   {
-    theWorkspace->SetHighlight (true);
+    theWorkspace->SetHighlightStyle (myHighlightStyle);
   }
 
   // Apply local transformation
   aCtx->ModelWorldState.Push();
-  aCtx->ModelWorldState.SetCurrent (Transformation);
+  OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent();
+  aModelWorld = myRenderTrsf;
 
-  if (TransformPersistence.Flags)
+  const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
+#if !defined(GL_ES_VERSION_2_0)
+  // detect scale transform
+  if (aCtx->core11 != NULL
+  && !myTrsf.IsNull())
   {
-    OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current();
-    OpenGl_Mat4 aWorldView  = aCtx->WorldViewState.Current();
-    TransformPersistence.Apply (aProjection, aWorldView, theWorkspace->Width(), theWorkspace->Height());
-
-    aCtx->ProjectionState.Push();
-    aCtx->WorldViewState.Push();
-    aCtx->ProjectionState.SetCurrent (aProjection);
-    aCtx->WorldViewState.SetCurrent (aWorldView);
-    aCtx->ApplyProjectionMatrix();
+    const Standard_Real aScale = myTrsf->ScaleFactor();
+    if (Abs (aScale - 1.0) > Precision::Confusion())
+    {
+      aCtx->SetGlNormalizeEnabled (Standard_True);
+    }
   }
+#endif
 
-  // detect scale transform
-  const Standard_Boolean   anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
-  const Standard_ShortReal aScaleX          = aCtx->ModelWorldState.Current().GetRow (0).xyz().SquareModulus();
-  if (Abs (aScaleX - 1.f) > Precision::Confusion())
+  if (!myTrsfPers.IsNull())
   {
-    aCtx->SetGlNormalizeEnabled (Standard_True);
+    aCtx->WorldViewState.Push();
+    OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent();
+    myTrsfPers->Apply (theWorkspace->View()->Camera(),
+                       aCtx->ProjectionState.Current(), aWorldView,
+                       aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]);
+
+  #if !defined(GL_ES_VERSION_2_0)
+    if (!aCtx->IsGlNormalizeEnabled()
+      && aCtx->core11 != NULL)
+    {
+      const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
+      if (Abs (aScale - 1.0) > Precision::Confusion())
+      {
+        aCtx->SetGlNormalizeEnabled (Standard_True);
+      }
+    }
+  #endif
   }
 
   // Take into account transform persistence
   aCtx->ApplyModelViewMatrix();
 
   // remember aspects
-  const OpenGl_AspectLine*   aPrevAspectLine   = theWorkspace->AspectLine();
-  const OpenGl_AspectFace*   aPrevAspectFace   = theWorkspace->AspectFace();
-  const OpenGl_AspectMarker* aPrevAspectMarker = theWorkspace->AspectMarker();
-  const OpenGl_AspectText*   aPrevAspectText   = theWorkspace->AspectText();
+  const OpenGl_Aspects* aPrevAspectFace = theWorkspace->Aspects();
 
   // Apply correction for mirror transform
   if (myIsMirrored)
@@ -510,51 +467,93 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
     aCtx->core11fwd->glFrontFace (GL_CW);
   }
 
-  // Apply highlight color
-  const TEL_COLOUR *aHighlightColor = theWorkspace->HighlightColor;
-  if (myHighlightColor)
-    theWorkspace->HighlightColor = myHighlightColor;
-
-  // Set up plane equations for non-structure transformed global model-view matrix
-  // List of planes to be applied to context state
-  NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
-
   // Collect clipping planes of structure scope
-  if (!myClipPlanes.IsEmpty())
+  aCtx->ChangeClipping().SetLocalPlanes (myClipPlanes);
+
+  // True if structure is fully clipped
+  bool isClipped = false;
+  bool hasDisabled = false;
+  if (aCtx->Clipping().IsClippingOrCappingOn())
   {
-    Graphic3d_SequenceOfHClipPlane::Iterator aClippingIter (myClipPlanes);
-    for (; aClippingIter.More(); aClippingIter.Next())
+    const Graphic3d_BndBox3d& aBBox = BoundingBox();
+    if (!myClipPlanes.IsNull()
+      && myClipPlanes->ToOverrideGlobal())
+    {
+      aCtx->ChangeClipping().DisableGlobal();
+      hasDisabled = aCtx->Clipping().HasDisabled();
+    }
+    else if (!myTrsfPers.IsNull())
     {
-      const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIter.Value();
-      if (!aClipPlane->IsOn())
+      if (myTrsfPers->IsZoomOrRotate())
       {
-        continue;
+        // Zoom/rotate persistence object lives in two worlds at the same time.
+        // Global clipping planes can not be trivially applied without being converted
+        // into local space of transformation persistence object.
+        // As more simple alternative - just clip entire object by its anchor point defined in the world space.
+        const gp_Pnt anAnchor = myTrsfPers->AnchorPoint();
+        for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More() && aPlaneIt.IsGlobal(); aPlaneIt.Next())
+        {
+          const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+          if (!aPlane->IsOn())
+          {
+            continue;
+          }
+
+          // check for clipping
+          const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
+          if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
+          {
+            isClipped = true;
+            break;
+          }
+        }
       }
 
-      if (aUserPlanes.IsNull())
+      aCtx->ChangeClipping().DisableGlobal();
+      hasDisabled = aCtx->Clipping().HasDisabled();
+    }
+
+    // Set of clipping planes that do not intersect the structure,
+    // and thus can be disabled to improve rendering performance
+    if (aBBox.IsValid()
+     && myTrsfPers.IsNull())
+    {
+      for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next())
       {
-        aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
+        const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+        if (aPlaneIt.IsDisabled())
+        {
+          continue;
+        }
+
+        const Graphic3d_ClipState aBoxState = aPlane->ProbeBox (aBBox);
+        if (aBoxState == Graphic3d_ClipState_In)
+        {
+          aCtx->ChangeClipping().SetEnabled (aPlaneIt, false);
+          hasDisabled = true;
+        }
+        else if (aBoxState == Graphic3d_ClipState_Out && myBndBoxClipCheck)
+        {
+          isClipped = true;
+          break;
+        }
       }
-
-      aUserPlanes->Append (aClipPlane);
     }
-  }
-
-  if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
-  {
-    // add planes at loaded view matrix state
-    aCtx->ChangeClipping().AddWorld (aCtx, *aUserPlanes);
 
-    // Set OCCT state uniform variables
-    if (!aCtx->ShaderManager()->IsEmpty())
+    if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
+     || hasDisabled)
     {
+      // Set OCCT state uniform variables
       aCtx->ShaderManager()->UpdateClippingState();
     }
   }
 
   // Render groups
   bool hasClosedPrims = false;
-  renderGeometry (theWorkspace, hasClosedPrims);
+  if (!isClipped)
+  {
+    renderGeometry (theWorkspace, hasClosedPrims);
+  }
 
   // Reset correction for mirror transform
   if (myIsMirrored)
@@ -564,50 +563,49 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
 
   // Render capping for structure groups
   if (hasClosedPrims
-  && !aCtx->Clipping().Planes().IsEmpty())
+   && aCtx->Clipping().IsCappingOn())
   {
     OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
   }
 
   // Revert structure clippings
-  if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
+  if (hasDisabled)
+  {
+    // enable planes that were previously disabled
+    aCtx->ChangeClipping().RestoreDisabled();
+  }
+  aCtx->ChangeClipping().SetLocalPlanes (Handle(Graphic3d_SequenceOfHClipPlane)());
+  if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
+    || hasDisabled)
   {
-    aCtx->ChangeClipping().Remove (aCtx, *aUserPlanes);
-
     // Set OCCT state uniform variables
-    if (!aCtx->ShaderManager()->IsEmpty())
-    {
-      aCtx->ShaderManager()->RevertClippingState();
-    }
+    aCtx->ShaderManager()->RevertClippingState();
   }
 
   // Restore local transformation
   aCtx->ModelWorldState.Pop();
   aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
-  if (TransformPersistence.Flags)
-  {
-    aCtx->ProjectionState.Pop();
-    aCtx->WorldViewState.Pop();
-    aCtx->ApplyProjectionMatrix();
-  }
-
-  // Restore highlight color
-  theWorkspace->HighlightColor = aHighlightColor;
 
   // Restore aspects
-  theWorkspace->SetAspectLine   (aPrevAspectLine);
-  theWorkspace->SetAspectFace   (aPrevAspectFace);
-  theWorkspace->SetAspectMarker (aPrevAspectMarker);
-  theWorkspace->SetAspectText   (aPrevAspectText);
+  theWorkspace->SetAspects (aPrevAspectFace);
 
   // Apply highlight box
-  if (!myHighlightBox.IsNull())
+  if (!isClipped
+   && !myHighlightStyle.IsNull()
+   &&  myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
   {
-    myHighlightBox->Render (theWorkspace);
+    aCtx->ApplyModelViewMatrix();
+    theWorkspace->SetHighlightStyle (myHighlightStyle);
+    renderBoundingBox (theWorkspace);
+  }
+
+  if (!myTrsfPers.IsNull())
+  {
+    aCtx->WorldViewState.Pop();
   }
 
   // Restore named status
-  theWorkspace->SetHighlight (false);
+  theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)());
 }
 
 // =======================================================================
@@ -618,7 +616,7 @@ void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
 {
   // Release groups
   Clear (theGlCtx);
-  clearHighlightColor (theGlCtx);
+  myHighlightStyle.Nullify();
 }
 
 // =======================================================================
@@ -631,10 +629,6 @@ void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCt
   {
     aGroupIter.ChangeValue()->Release (theGlCtx);
   }
-  if (!myHighlightBox.IsNull())
-  {
-    myHighlightBox->Release (theGlCtx.operator->());
-  }
 }
 
 //=======================================================================