0030698: Volume Rendering - Early clipping of volume object's bounding box
[occt.git] / src / OpenGl / OpenGl_Structure.cxx
index 537bfed..927a4a0 100644 (file)
 // Created on: 2011-08-01
 // Created by: Sergey ZERCHANINOV
-// Copyright (c) 2011-2012 OPEN CASCADE SAS
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
-#ifdef HAVE_CONFIG_H
-  #include <config.h>
-#endif
-
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #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_Structure.hxx>
-#include <OpenGl_telem_util.hxx>
+#include <OpenGl_StructureShadow.hxx>
 #include <OpenGl_Vec.hxx>
 #include <OpenGl_View.hxx>
 #include <OpenGl_Workspace.hxx>
 
-#include <Graphic3d_SequenceOfHClipPlane_Handle.hxx>
-
-//! Auxiliary class for bounding box presentation
-class OpenGl_BndBoxPrs : public OpenGl_Element
-{
-
-public:
-
-  //! Main constructor
-  OpenGl_BndBoxPrs (const CALL_DEF_BOUNDBOX& theBndBox)
-  {
-    const float Xm = theBndBox.Pmin.x;
-    const float Ym = theBndBox.Pmin.y;
-    const float Zm = theBndBox.Pmin.z;
-    const float XM = theBndBox.Pmax.x;
-    const float YM = theBndBox.Pmax.y;
-    const float ZM = theBndBox.Pmax.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
-  {
-    // Apply line aspect
-    const OpenGl_AspectLine*     anAspectLine = theWorkspace->AspectLine (Standard_True);
-    const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
-
-    glDisable (GL_LIGHTING);
-    if ((theWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0)
-    {
-      glDepthMask (GL_FALSE);
-    }
-
-    // Use highlight colors
-    glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().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);
-    }
-  }
-
-  //! Release graphical resources
-  virtual void Release (const Handle(OpenGl_Context)& )
-  {
-    //
-  }
-
-protected:
-
-  //! Protected destructor
-  virtual ~OpenGl_BndBoxPrs() {}
-
-private:
-
-  OpenGl_Vec3 myVerts[16]; //!< vertices array
-
-public:
-
-  DEFINE_STANDARD_ALLOC
-
-};
-
-/*----------------------------------------------------------------------*/
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
 
 // =======================================================================
-// function : call_util_transpose_mat
+// function : renderBoundingBox
 // purpose  :
 // =======================================================================
-static void call_util_transpose_mat (float tmat[16], float mat[4][4])
+void OpenGl_Structure::renderBoundingBox (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
-  int i, j;
+  if (!myBndBox.IsValid())
+  {
+    return;
+  }
 
-  for (i=0; i<4; i++)
-    for (j=0; j<4; j++)
-      tmat[j*4+i] = mat[i][j];
+  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
 // purpose  :
 // =======================================================================
-OpenGl_Structure::OpenGl_Structure ()
-: myTransformation(NULL),
-  myTransPers(NULL),
-  myAspectLine(NULL),
-  myAspectFace(NULL),
-  myAspectMarker(NULL),
-  myAspectText(NULL),
-  myHighlightBox(NULL),
-  myHighlightColor(NULL),
-  myNamedStatus(0),
-  myZLayer(0)
+OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
+: Graphic3d_CStructure (theManager),
+  myInstancedStructure (NULL),
+  myIsRaytracable      (Standard_False),
+  myModificationState  (0),
+  myIsMirrored         (Standard_False)
 {
-#if HAVE_OPENCL
-  myIsRaytracable = Standard_False;
-  myModificationState = 0;
-#endif
+  updateLayerTransformation();
 }
 
 // =======================================================================
@@ -161,629 +119,493 @@ OpenGl_Structure::OpenGl_Structure ()
 OpenGl_Structure::~OpenGl_Structure()
 {
   Release (Handle(OpenGl_Context)());
-  delete myTransformation;  myTransformation  = NULL;
-  delete myTransPers;       myTransPers       = NULL;
-}
-
-// =======================================================================
-// function : SetTransformation
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::SetTransformation (const float *theMatrix)
-{
-  if (!myTransformation)
-  {
-    myTransformation = new OpenGl_Matrix();
-  }
-
-  matcpy (myTransformation->mat, theMatrix);
-
-#ifdef HAVE_OPENCL
-  if (myIsRaytracable)
-  {
-    UpdateStateWithAncestorStructures();
-  }
-#endif
 }
 
 // =======================================================================
-// function : SetTransformPersistence
+// function : SetZLayer
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers)
+void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex)
 {
-  if (!myTransPers)
-    myTransPers = new TEL_TRANSFORM_PERSISTENCE;
-
-  myTransPers->mode = ATransPers.Flag;
-  myTransPers->pointX = ATransPers.Point.x;
-  myTransPers->pointY = ATransPers.Point.y;
-  myTransPers->pointZ = ATransPers.Point.z;
+  Graphic3d_CStructure::SetZLayer (theLayerIndex);
+  updateLayerTransformation();
 }
 
 // =======================================================================
-// function : SetAspectLine
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &theAspect)
-{
-  if (!myAspectLine)
-  {
-    myAspectLine = new OpenGl_AspectLine();
-  }
-  myAspectLine->SetAspect (theAspect);
-}
-
-// =======================================================================
-// function : SetAspectFace
+// function : SetTransformation
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect)
+void OpenGl_Structure::SetTransformation (const Handle(Geom_Transformation)& theTrsf)
 {
-  if (!myAspectFace)
+  myTrsf = theTrsf;
+  myIsMirrored = Standard_False;
+  if (!myTrsf.IsNull())
   {
-    myAspectFace = new OpenGl_AspectFace();
+    // 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;
   }
-  myAspectFace->SetAspect (theAspect);
 
-#ifdef HAVE_OPENCL
-  if (myIsRaytracable)
+  updateLayerTransformation();
+  if (IsRaytracable())
   {
-    UpdateStateWithAncestorStructures();
+    ++myModificationState;
   }
-#endif
 }
 
 // =======================================================================
-// function : SetAspectMarker
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theAspect)
-{
-  if (!myAspectMarker)
-  {
-    myAspectMarker = new OpenGl_AspectMarker();
-  }
-  myAspectMarker->SetAspect (theAspect);
-}
-
-// =======================================================================
-// function : SetAspectText
+// function : SetTransformPersistence
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect)
+void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
 {
-  if (!myAspectText)
-  {
-    myAspectText = new OpenGl_AspectText();
-  }
-  myAspectText->SetAspect (theAspect);
+  myTrsfPers = theTrsfPers;
+  updateLayerTransformation();
 }
 
 // =======================================================================
-// function : SetHighlightBox
+// function : updateLayerTransformation
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetHighlightBox (const Handle(OpenGl_Context)& theGlCtx,
-                                        const CALL_DEF_BOUNDBOX&      theBoundBox)
+void OpenGl_Structure::updateLayerTransformation()
 {
-  if (myHighlightBox != NULL)
+  gp_Trsf aRenderTrsf;
+  if (!myTrsf.IsNull())
   {
-    myHighlightBox->Release (theGlCtx);
+    aRenderTrsf = myTrsf->Trsf();
   }
-  else
-  {
-#ifndef HAVE_OPENCL
-    myHighlightBox = new OpenGl_Group();
-#else
-    myHighlightBox = new OpenGl_Group (this);
-#endif
-  }
-
-  CALL_DEF_CONTEXTLINE aContextLine;
-  aContextLine.Color    = theBoundBox.Color;
-  aContextLine.LineType = Aspect_TOL_SOLID;
-  aContextLine.Width    = 1.0f;
-  myHighlightBox->SetAspectLine (aContextLine);
 
-  OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (theBoundBox);
-  myHighlightBox->AddElement (TelParray, aBndBoxPrs);
-}
-
-// =======================================================================
-// function : ClearHighlightBox
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::ClearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
-{
-  if (myHighlightBox != NULL)
+  const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
+  if (!aLayer.OriginTransformation().IsNull()
+    && myTrsfPers.IsNull())
   {
-    OpenGl_Element::Destroy (theGlCtx, myHighlightBox);
+    aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin());
   }
+  aRenderTrsf.GetMat4 (myRenderTrsf);
 }
 
 // =======================================================================
-// function : SetHighlightColor
+// function : GraphicHighlight
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
-                                          const Standard_ShortReal R,
-                                          const Standard_ShortReal G,
-                                          const Standard_ShortReal B)
+void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle)
 {
-  ClearHighlightBox (theGlCtx);
-  if (myHighlightColor == NULL)
-  {
-    myHighlightColor = new TEL_COLOUR();
-  }
-
-  myHighlightColor->rgb[0] = R;
-  myHighlightColor->rgb[1] = G;
-  myHighlightColor->rgb[2] = 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();
 }
 
 // =======================================================================
-// function : SetNamedStatus
+// function : OnVisibilityChanged
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetNamedStatus (const Standard_Integer aStatus)
+void OpenGl_Structure::OnVisibilityChanged()
 {
-  myNamedStatus = aStatus;
-
-#ifdef HAVE_OPENCL
-  if (myIsRaytracable)
+  if (IsRaytracable())
   {
-    UpdateStateWithAncestorStructures();
+    ++myModificationState;
   }
-#endif
 }
 
-#ifdef HAVE_OPENCL
-
 // =======================================================================
-// function : RegisterAncestorStructure
+// function : IsRaytracable
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::RegisterAncestorStructure (const OpenGl_Structure* theStructure) const
+Standard_Boolean OpenGl_Structure::IsRaytracable() const
 {
-  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+  if (!myGroups.IsEmpty()
+    && myIsRaytracable)
   {
-    if (anIt.Value() == theStructure)
-    {
-      return;
-    }    
+    return Standard_True;
   }
 
-  myAncestorStructures.Append (theStructure);
+  return myInstancedStructure != NULL
+     &&  myInstancedStructure->IsRaytracable();
 }
 
 // =======================================================================
-// function : UnregisterAncestorStructure
+// function : UpdateRaytracableState
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::UnregisterAncestorStructure (const OpenGl_Structure* theStructure) const
+void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
 {
-  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+  myIsRaytracable = !toCheck;
+  if (!myIsRaytracable)
   {
-    if (anIt.Value() == theStructure)
+    for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
     {
-      myAncestorStructures.Remove (anIt);
-      return;
-    }    
+      if (anIter.Value()->IsRaytracable())
+      {
+        myIsRaytracable = Standard_True;
+        break;
+      }
+    }
   }
-}
 
-// =======================================================================
-// function : UnregisterFromAncestorStructure
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::UnregisterFromAncestorStructure() const
-{
-  for (OpenGl_ListOfStructure::Iterator anIta (myAncestorStructures); anIta.More(); anIta.Next())
+  if (IsRaytracable())
   {
-    OpenGl_Structure* anAncestor = const_cast<OpenGl_Structure*> (anIta.ChangeValue());
-
-    for (OpenGl_ListOfStructure::Iterator anIts (anAncestor->myConnected); anIts.More(); anIts.Next())
-    {
-      if (anIts.Value() == this)
-      {
-        anAncestor->myConnected.Remove (anIts);
-        return;
-      }      
-    }
+    ++myModificationState;
   }
 }
 
 // =======================================================================
-// function : UpdateStateWithAncestorStructures
+// function : Connect
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::UpdateStateWithAncestorStructures() const
+void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
 {
-  myModificationState++;
+  OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
+
+  Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
+    "Error! Instanced structure is already defined");
 
-  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+  myInstancedStructure = aStruct;
+
+  if (aStruct->IsRaytracable())
   {
-    anIt.Value()->UpdateStateWithAncestorStructures();
+    UpdateStateIfRaytracable (Standard_False);
   }
 }
 
 // =======================================================================
-// function : UpdateRaytracableWithAncestorStructures
+// function : Disconnect
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::UpdateRaytracableWithAncestorStructures() const
+void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
 {
-  myIsRaytracable = OpenGl_Raytrace::IsRaytracedStructure (this);
+  OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
 
-  if (!myIsRaytracable)
+  if (myInstancedStructure == aStruct)
   {
-    for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+    myInstancedStructure = NULL;
+
+    if (aStruct->IsRaytracable())
     {
-      anIt.Value()->UpdateRaytracableWithAncestorStructures();
+      UpdateStateIfRaytracable();
     }
   }
 }
 
 // =======================================================================
-// function : SetRaytracableWithAncestorStructures
+// function : NewGroup
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetRaytracableWithAncestorStructures() const
+Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
 {
-  myIsRaytracable = Standard_True;
-
-  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
-  {
-    if (!anIt.Value()->IsRaytracable())
-    {
-      anIt.Value()->SetRaytracableWithAncestorStructures();
-    }
-  }
+  Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
+  myGroups.Append (aGroup);
+  return aGroup;
 }
 
-#endif
-
 // =======================================================================
-// function : Connect
+// function : RemoveGroup
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::Connect (const OpenGl_Structure *theStructure)
+void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
 {
-  Disconnect (theStructure);
-  myConnected.Append (theStructure);
-
-#ifdef HAVE_OPENCL
-  if (theStructure->IsRaytracable())
+  if (theGroup.IsNull())
   {
-    UpdateStateWithAncestorStructures();
-    SetRaytracableWithAncestorStructures();
+    return;
   }
 
-  theStructure->RegisterAncestorStructure (this);
-#endif
-}
-
-// =======================================================================
-// function : Disconnect
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::Disconnect (const OpenGl_Structure *theStructure)
-{
-  OpenGl_ListOfStructure::Iterator its (myConnected);
-  while (its.More())
+  for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    // Check for the given structure
-    if (its.Value() == theStructure)
+    // Check for the given group
+    if (aGroupIter.Value() == theGroup)
     {
-      myConnected.Remove (its);
+      const Standard_Boolean wasRaytracable =
+        static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
+
+      theGroup->Clear (Standard_False);
 
-#ifdef HAVE_OPENCL
-      if (theStructure->IsRaytracable())
+      if (wasRaytracable)
       {
-        UpdateStateWithAncestorStructures();
-        UpdateRaytracableWithAncestorStructures();
+        UpdateStateIfRaytracable();
       }
 
-      theStructure->UnregisterAncestorStructure (this);
-#endif
-
+      myGroups.Remove (aGroupIter);
       return;
     }
-    its.Next();
   }
 }
 
 // =======================================================================
-// function : AddGroup
+// function : Clear
 // purpose  :
 // =======================================================================
-OpenGl_Group * OpenGl_Structure::AddGroup()
+void OpenGl_Structure::Clear()
 {
-  // Create new group
-#ifndef HAVE_OPENCL
-  OpenGl_Group *g = new OpenGl_Group();
-#else
-  OpenGl_Group *g = new OpenGl_Group (this);
-#endif
-
-  myGroups.Append(g);
-  return g;
+  Clear (GlDriver()->GetSharedContext());
 }
 
 // =======================================================================
-// function : RemoveGroup
+// function : Clear
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::RemoveGroup (const Handle(OpenGl_Context)& theGlCtx,
-                                    const OpenGl_Group*           theGroup)
+void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
 {
-  for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
+  Standard_Boolean aRaytracableGroupDeleted (Standard_False);
+
+  // Release groups
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    // Check for the given group
-    if (anIter.Value() == theGroup)
-    {
-      myGroups.Remove (anIter);
+    aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
 
-#ifdef HAVE_OPENCL
-      if (theGroup->IsRaytracable())
-      {
-        UpdateStateWithAncestorStructures();
-        UpdateRaytracableWithAncestorStructures();
-      }
-#endif
+    // Delete objects
+    aGroupIter.ChangeValue()->Release (theGlCtx);
+  }
+  myGroups.Clear();
 
-      // Delete object
-      OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (theGroup));
-      return;
-    }
+  if (aRaytracableGroupDeleted)
+  {
+    myIsRaytracable = Standard_False;
   }
+
+  Is2dText       = Standard_False;
+  IsForHighlight = Standard_False;
 }
 
 // =======================================================================
-// function : Clear
+// function : renderGeometry
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
+void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
+                                       bool&                           theHasClosed) const
 {
-#ifdef HAVE_OPENCL
-  Standard_Boolean aRaytracableGroupDeleted (Standard_False);
-#endif
-
-  // Release groups
-  for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
+  if (myInstancedStructure != NULL)
   {
-#ifdef HAVE_OPENCL
-    aRaytracableGroupDeleted |= anIter.Value()->IsRaytracable();
-#endif
-    
-    // Delete objects
-    OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
+    myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
   }
-  myGroups.Clear();
 
-#ifdef HAVE_OPENCL
-  if (aRaytracableGroupDeleted)
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    UpdateStateWithAncestorStructures();
-    UpdateRaytracableWithAncestorStructures();
+    theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
+    aGroupIter.Value()->Render (theWorkspace);
   }
-#endif
 }
 
 // =======================================================================
 // function : Render
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
+void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
 {
   // Process the structure only if visible
-  if ( myNamedStatus & OPENGL_NS_HIDE )
+  if (!visible)
+  {
     return;
+  }
 
-  // Render named status
-  const Standard_Integer named_status = AWorkspace->NamedStatus;
-  AWorkspace->NamedStatus |= myNamedStatus;
-
-  // Is rendering in ADD or IMMEDIATE mode?
-  const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
-
-  const Handle(OpenGl_Context)& aCtx = AWorkspace->GetGlContext();
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
 
-  // Apply local transformation
-  GLint matrix_mode = 0;
-  const OpenGl_Matrix *local_trsf = NULL;
-  if (myTransformation)
+  // Render named status
+  if (highlight && !myHighlightStyle.IsNull() && myHighlightStyle->Method() != Aspect_TOHM_BOUNDBOX)
   {
-    if (isImmediate)
-    {
-      Tmatrix3 aModelWorld;
-      call_util_transpose_mat (*aModelWorld, myTransformation->mat);
-      glGetIntegerv (GL_MATRIX_MODE, &matrix_mode);
-
-      if (!aCtx->ShaderManager()->IsEmpty())
-      {
-        Tmatrix3 aWorldView;
-        glGetFloatv (GL_MODELVIEW_MATRIX, *aWorldView);
-
-        Tmatrix3 aProjection;
-        glGetFloatv (GL_PROJECTION_MATRIX, *aProjection);
-
-        aCtx->ShaderManager()->UpdateModelWorldStateTo (aModelWorld);
-        aCtx->ShaderManager()->UpdateWorldViewStateTo (aWorldView);
-        aCtx->ShaderManager()->UpdateProjectionStateTo (aProjection);
-      }
+    theWorkspace->SetHighlightStyle (myHighlightStyle);
+  }
 
-      glMatrixMode (GL_MODELVIEW);
-      glPushMatrix ();
-      glScalef (1.F, 1.F, 1.F);
-      glMultMatrixf (*aModelWorld);
-    }
-    else
+  // Apply local transformation
+  aCtx->ModelWorldState.Push();
+  OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent();
+  aModelWorld = myRenderTrsf;
+
+  const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
+#if !defined(GL_ES_VERSION_2_0)
+  // detect scale transform
+  if (aCtx->core11 != NULL
+  && !myTrsf.IsNull())
+  {
+    const Standard_Real aScale = myTrsf->ScaleFactor();
+    if (Abs (aScale - 1.0) > Precision::Confusion())
     {
-      glMatrixMode (GL_MODELVIEW);
-      glPushMatrix();
-
-      local_trsf = AWorkspace->SetStructureMatrix (myTransformation);
+      aCtx->SetGlNormalizeEnabled (Standard_True);
     }
   }
+#endif
 
-  // Apply transform persistence
-  const TEL_TRANSFORM_PERSISTENCE *trans_pers = NULL;
-  if ( myTransPers && myTransPers->mode != 0 )
+  if (!myTrsfPers.IsNull())
   {
-    trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence (aCtx, myTransPers);
+    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
   }
 
-  // Apply aspects
-  const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine(Standard_False);
-  const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace(Standard_False);
-  const OpenGl_AspectMarker *aspect_marker = AWorkspace->AspectMarker(Standard_False);
-  const OpenGl_AspectText *aspect_text = AWorkspace->AspectText(Standard_False);
-  if (myAspectLine)
-    AWorkspace->SetAspectLine(myAspectLine);
-  if (myAspectFace)
-    AWorkspace->SetAspectFace(myAspectFace);
-  if (myAspectMarker)
-    AWorkspace->SetAspectMarker(myAspectMarker);
-  if (myAspectText)
-    AWorkspace->SetAspectText(myAspectText);
+  // Take into account transform persistence
+  aCtx->ApplyModelViewMatrix();
 
-  // Apply highlight box
-  if (myHighlightBox)
-    myHighlightBox->Render( AWorkspace );
+  // remember aspects
+  const OpenGl_Aspects* aPrevAspectFace = theWorkspace->Aspects();
 
-  // Apply highlight color
-  const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
-  if (myHighlightColor)
-    AWorkspace->HighlightColor = myHighlightColor;
-
-  // Render connected structures
-  OpenGl_ListOfStructure::Iterator its(myConnected);
-  while (its.More())
+  // Apply correction for mirror transform
+  if (myIsMirrored)
   {
-    its.Value()->Render(AWorkspace);
-    its.Next();
+    aCtx->core11fwd->glFrontFace (GL_CW);
   }
 
-  // Set up plane equations for non-structure transformed global model-view matrix
-  const Handle(OpenGl_Context)& aContext = AWorkspace->GetGlContext();
-
-  // List of planes to be applied to context state
-  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 aClippingIt (myClipPlanes);
-    for (; aClippingIt.More(); aClippingIt.Next())
+    const Graphic3d_BndBox3d& aBBox = BoundingBox();
+    if (!myClipPlanes.IsNull()
+      && myClipPlanes->ToOverrideGlobal())
     {
-      const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
-      if (!aClipPlane->IsOn())
+      aCtx->ChangeClipping().DisableGlobal();
+      hasDisabled = aCtx->Clipping().HasDisabled();
+    }
+    else if (!myTrsfPers.IsNull())
+    {
+      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
-    aContext->ChangeClipping().AddWorld (*aUserPlanes, AWorkspace);
-
-    // Set OCCT state uniform variables
-    if (!aContext->ShaderManager()->IsEmpty())
+    if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
+     || hasDisabled)
     {
-      aContext->ShaderManager()->UpdateClippingState();
+      // Set OCCT state uniform variables
+      aCtx->ShaderManager()->UpdateClippingState();
     }
   }
 
   // Render groups
-  OpenGl_ListOfGroup::Iterator itg(myGroups);
-  while (itg.More())
+  bool hasClosedPrims = false;
+  if (!isClipped)
   {
-    itg.Value()->Render(AWorkspace);
-    itg.Next();
+    renderGeometry (theWorkspace, hasClosedPrims);
+  }
+
+  // Reset correction for mirror transform
+  if (myIsMirrored)
+  {
+    aCtx->core11fwd->glFrontFace (GL_CCW);
   }
 
   // Render capping for structure groups
-  if (!aContext->Clipping().Planes().IsEmpty())
+  if (hasClosedPrims
+   && aCtx->Clipping().IsCappingOn())
   {
-    OpenGl_CappingAlgo::RenderCapping (AWorkspace, myGroups);
+    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)
   {
-    aContext->ChangeClipping().Remove (*aUserPlanes);
-
     // Set OCCT state uniform variables
-    if (!aContext->ShaderManager()->IsEmpty())
-    {
-      aContext->ShaderManager()->RevertClippingState();
-    }
+    aCtx->ShaderManager()->RevertClippingState();
   }
 
-  // Restore highlight color
-  AWorkspace->HighlightColor = highlight_color;
+  // Restore local transformation
+  aCtx->ModelWorldState.Pop();
+  aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
 
   // Restore aspects
-  AWorkspace->SetAspectLine(aspect_line);
-  AWorkspace->SetAspectFace(aspect_face);
-  AWorkspace->SetAspectMarker(aspect_marker);
-  AWorkspace->SetAspectText(aspect_text);
+  theWorkspace->SetAspects (aPrevAspectFace);
 
-  // Restore transform persistence
-  if ( myTransPers && myTransPers->mode != 0 )
+  // Apply highlight box
+  if (!isClipped
+   && !myHighlightStyle.IsNull()
+   &&  myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
   {
-    AWorkspace->ActiveView()->BeginTransformPersistence (aContext, trans_pers);
+    aCtx->ApplyModelViewMatrix();
+    theWorkspace->SetHighlightStyle (myHighlightStyle);
+    renderBoundingBox (theWorkspace);
   }
 
-  // Restore local transformation
-  if (myTransformation)
+  if (!myTrsfPers.IsNull())
   {
-    if (isImmediate)
-    {
-      glPopMatrix ();
-      glMatrixMode (matrix_mode);
-
-      Tmatrix3 aModelWorldState = { { 1.f, 0.f, 0.f, 0.f },
-                                    { 0.f, 1.f, 0.f, 0.f },
-                                    { 0.f, 0.f, 1.f, 0.f },
-                                    { 0.f, 0.f, 0.f, 1.f } };
-
-      aContext->ShaderManager()->RevertModelWorldStateTo (aModelWorldState);
-    }
-    else
-    {
-      AWorkspace->SetStructureMatrix (local_trsf, true);
-
-      glMatrixMode (GL_MODELVIEW);
-      glPopMatrix();
-    }
+    aCtx->WorldViewState.Pop();
   }
 
   // Restore named status
-  AWorkspace->NamedStatus = named_status;
+  theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)());
 }
 
 // =======================================================================
@@ -794,16 +616,7 @@ void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
 {
   // Release groups
   Clear (theGlCtx);
-  OpenGl_Element::Destroy (theGlCtx, myAspectLine);
-  OpenGl_Element::Destroy (theGlCtx, myAspectFace);
-  OpenGl_Element::Destroy (theGlCtx, myAspectMarker);
-  OpenGl_Element::Destroy (theGlCtx, myAspectText);
-  ClearHighlightColor (theGlCtx);
-
-#ifdef HAVE_OPENCL
-  // Remove from connected list of ancestor
-  UnregisterFromAncestorStructure();
-#endif
+  myHighlightStyle.Nullify();
 }
 
 // =======================================================================
@@ -812,50 +625,17 @@ void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
 // =======================================================================
 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
 {
-  for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
-  {
-    OpenGl_Group* aGroup = const_cast<OpenGl_Group*& > (anIter.ChangeValue());
-    if (aGroup != NULL)
-    {
-      aGroup->Release (theGlCtx);
-    }
-  }
-  if (myAspectLine != NULL)
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    myAspectLine->Release (theGlCtx);
+    aGroupIter.ChangeValue()->Release (theGlCtx);
   }
-  if (myAspectFace != NULL)
-  {
-    myAspectFace->Release (theGlCtx);
-  }
-  if (myAspectMarker != NULL)
-  {
-    myAspectMarker->Release (theGlCtx);
-  }
-  if (myAspectText != NULL)
-  {
-    myAspectText->Release (theGlCtx);
-  }
-  if (myHighlightBox != NULL)
-  {
-    myHighlightBox->Release (theGlCtx);
-  }
-}
-
-//=======================================================================
-//function : SetZLayer
-//purpose  :
-//=======================================================================
-void OpenGl_Structure::SetZLayer (const Standard_Integer theLayerIndex)
-{
-  myZLayer = theLayerIndex;
 }
 
 //=======================================================================
-//function : GetZLayer
+//function : ShadowLink
 //purpose  :
 //=======================================================================
-Standard_Integer OpenGl_Structure::GetZLayer () const
+Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
 {
-  return myZLayer;
+  return new OpenGl_StructureShadow (theManager, this);
 }