0026940: Visualization, TKOpenGl - capping plane should be applied to connected struc...
[occt.git] / src / OpenGl / OpenGl_Structure.cxx
index ec54411..01e0546 100644 (file)
 #include <OpenGl_GraphicDriver.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
-#include <OpenGl_Structure.hxx>
+#include <OpenGl_StructureShadow.hxx>
 #include <OpenGl_telem_util.hxx>
 #include <OpenGl_Vec.hxx>
 #include <OpenGl_View.hxx>
 #include <OpenGl_Workspace.hxx>
 
-#include <Graphic3d_SequenceOfHClipPlane_Handle.hxx>
+#include <Graphic3d_SequenceOfHClipPlane.hxx>
 
-IMPLEMENT_STANDARD_HANDLE (OpenGl_Structure, Graphic3d_CStructure)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure, Graphic3d_CStructure)
 
 //! Auxiliary class for bounding box presentation
 class OpenGl_BndBoxPrs : public OpenGl_Element
@@ -67,18 +65,15 @@ public:
   //! Render presentation
   virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const
   {
+  #if !defined(GL_ES_VERSION_2_0)
     // 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_IMMEDIATE) != 0)
-    {
-      glDepthMask (GL_FALSE);
-    }
 
     // Use highlight colors
-    glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().rgb);
+    theWorkspace->GetGlContext()->core11->glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().rgb);
 
     glEnableClientState (GL_VERTEX_ARRAY);
     glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
@@ -90,6 +85,7 @@ public:
     {
       theWorkspace->EnableTexture (aPrevTexture);
     }
+  #endif
   }
 
   //! Release graphical resources
@@ -115,39 +111,24 @@ public:
 
 /*----------------------------------------------------------------------*/
 
-// =======================================================================
-// function : call_util_transpose_mat
-// purpose  :
-// =======================================================================
-static void call_util_transpose_mat (float tmat[16], float mat[4][4])
-{
-  int i, j;
-
-  for (i=0; i<4; i++)
-    for (j=0; j<4; j++)
-      tmat[j*4+i] = mat[i][j];
-}
-
 // =======================================================================
 // function : OpenGl_Structure
 // purpose  :
 // =======================================================================
 OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
 : Graphic3d_CStructure (theManager),
-  myTransformation(NULL),
-  myTransPers(NULL),
-  myAspectLine(NULL),
-  myAspectFace(NULL),
-  myAspectMarker(NULL),
-  myAspectText(NULL),
-  myHighlightColor(NULL),
-  myNamedStatus(0),
-  myZLayer(0),
-  myIsRaytracable (Standard_False),
-  myModificationState (0),
-  myIsCulled (Standard_True)
+  myAspectLine         (NULL),
+  myAspectFace         (NULL),
+  myAspectMarker       (NULL),
+  myAspectText         (NULL),
+  myHighlightColor     (NULL),
+  myInstancedStructure (NULL),
+  myIsRaytracable      (Standard_False),
+  myModificationState  (0),
+  myIsCulled           (Standard_True),
+  myIsMirrored         (Standard_False)
 {
-  UpdateNamedStatus();
+  //
 }
 
 // =======================================================================
@@ -157,8 +138,6 @@ OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& th
 OpenGl_Structure::~OpenGl_Structure()
 {
   Release (Handle(OpenGl_Context)());
-  delete myTransformation;  myTransformation  = NULL;
-  delete myTransPers;       myTransPers       = NULL;
 }
 
 // =======================================================================
@@ -167,8 +146,6 @@ OpenGl_Structure::~OpenGl_Structure()
 // =======================================================================
 void OpenGl_Structure::UpdateAspects()
 {
-  SetTransformPersistence (TransformPersistence);
-
   if (ContextLine.IsDef)
     SetAspectLine (ContextLine);
 
@@ -188,35 +165,21 @@ void OpenGl_Structure::UpdateAspects()
 // =======================================================================
 void OpenGl_Structure::UpdateTransformation()
 {
-  if (myTransformation == NULL)
-  {
-    myTransformation = new OpenGl_Matrix();
-  }
+  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));
 
-  matcpy (myTransformation->mat, &Graphic3d_CStructure::Transformation[0][0]);
+  // Determinant of transform matrix less then 0 means that mirror transform applied.
+  myIsMirrored = aDet < 0.0f;
 
-  if (myIsRaytracable)
+  if (IsRaytracable())
   {
-    UpdateStateWithAncestorStructures();
+    ++myModificationState;
   }
 }
 
-// =======================================================================
-// function : SetTransformPersistence
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers)
-{
-  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;
-  MarkAsNotCulled();
-}
-
 // =======================================================================
 // function : SetAspectLine
 // purpose  :
@@ -242,9 +205,9 @@ void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect)
   }
   myAspectFace->SetAspect (theAspect);
 
-  if (myIsRaytracable)
+  if (IsRaytracable())
   {
-    UpdateStateWithAncestorStructures();
+    ++myModificationState;
   }
 }
 
@@ -294,11 +257,11 @@ void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx
 void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3&  theColor,
                                            const Standard_Boolean theToCreate)
 {
-  const Handle(OpenGl_Context)& aCtx = GlDriver()->GetSharedContext();
+  const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
   if (theToCreate)
-    setHighlightColor   (aCtx, theColor);
+    setHighlightColor   (aContext, theColor);
   else
-    clearHighlightColor (aCtx);
+    clearHighlightColor (aContext);
 }
 
 // =======================================================================
@@ -308,16 +271,16 @@ void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3&  theColor,
 void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
                                             const Standard_Boolean             theToCreate)
 {
-  const Handle(OpenGl_Context)& aCtx = GlDriver()->GetSharedContext();
+  const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
   if (!theToCreate)
   {
-    clearHighlightBox (aCtx);
+    clearHighlightBox (aContext);
     return;
   }
 
   if (!myHighlightBox.IsNull())
   {
-    myHighlightBox->Release (aCtx);
+    myHighlightBox->Release (aContext);
   }
   else
   {
@@ -366,120 +329,46 @@ void OpenGl_Structure::clearHighlightColor (const Handle(OpenGl_Context)& theGlC
 }
 
 // =======================================================================
-// function : UpdateNamedStatus
+// function : OnVisibilityChanged
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::UpdateNamedStatus()
+void OpenGl_Structure::OnVisibilityChanged()
 {
-  myNamedStatus = 0;
-  if (highlight) myNamedStatus |= OPENGL_NS_HIGHLIGHT;
-  if (!visible)  myNamedStatus |= OPENGL_NS_HIDE;
-
-  if (myIsRaytracable)
+  if (IsRaytracable())
   {
-    UpdateStateWithAncestorStructures();
+    ++myModificationState;
   }
 }
 
 // =======================================================================
-// 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())
   {
-    if (anIt.Value() == theStructure)
-    {
-      return;
-    }
+    return myIsRaytracable; // geometry structure
   }
-
-  myAncestorStructures.Append (theStructure);
-}
-
-// =======================================================================
-// function : UnregisterAncestorStructure
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::UnregisterAncestorStructure (const OpenGl_Structure* theStructure) const
-{
-  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+  else if (myInstancedStructure != NULL)
   {
-    if (anIt.Value() == theStructure)
-    {
-      myAncestorStructures.Remove (anIt);
-      return;
-    }
+    return myInstancedStructure->IsRaytracable(); // instance structure
   }
-}
-
-// =======================================================================
-// function : UnregisterFromAncestorStructure
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::UnregisterFromAncestorStructure() const
-{
-  for (OpenGl_ListOfStructure::Iterator anIta (myAncestorStructures); anIta.More(); anIta.Next())
-  {
-    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;
-      }
-    }
-  }
+  return Standard_False; // has no any groups or structures
 }
 
 // =======================================================================
-// function : UpdateStateWithAncestorStructures
+// function : UpdateRaytracableState
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::UpdateStateWithAncestorStructures() const
+void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
 {
-  myModificationState++;
+  myIsRaytracable = !toCheck || OpenGl_Raytrace::IsRaytracedStructure (this);
 
-  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+  if (IsRaytracable())
   {
-    anIt.Value()->UpdateStateWithAncestorStructures();
-  }
-}
-
-// =======================================================================
-// function : UpdateRaytracableWithAncestorStructures
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::UpdateRaytracableWithAncestorStructures() const
-{
-  myIsRaytracable = OpenGl_Raytrace::IsRaytracedStructure (this);
-
-  if (!myIsRaytracable)
-  {
-    for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
-    {
-      anIt.Value()->UpdateRaytracableWithAncestorStructures();
-    }
-  }
-}
-
-// =======================================================================
-// function : SetRaytracableWithAncestorStructures
-// purpose  :
-// =======================================================================
-void OpenGl_Structure::SetRaytracableWithAncestorStructures() const
-{
-  myIsRaytracable = Standard_True;
-
-  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
-  {
-    if (!anIt.Value()->IsRaytracable())
-    {
-      anIt.Value()->SetRaytracableWithAncestorStructures();
-    }
+    ++myModificationState;
   }
 }
 
@@ -489,17 +378,17 @@ void OpenGl_Structure::SetRaytracableWithAncestorStructures() const
 // =======================================================================
 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
 {
-  OpenGl_Structure* aStruct = (OpenGl_Structure* )&theStructure;
-  Disconnect (theStructure);
-  myConnected.Append (aStruct);
+  OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
+
+  Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
+    "Error! Instanced structure is already defined");
+
+  myInstancedStructure = aStruct;
 
   if (aStruct->IsRaytracable())
   {
-    UpdateStateWithAncestorStructures();
-    SetRaytracableWithAncestorStructures();
+    UpdateStateIfRaytracable (Standard_False);
   }
-
-  aStruct->RegisterAncestorStructure (this);
 }
 
 // =======================================================================
@@ -508,22 +397,15 @@ void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
 // =======================================================================
 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
 {
-  OpenGl_Structure* aStruct = (OpenGl_Structure* )&theStructure;
-  for (OpenGl_ListOfStructure::Iterator anIter (myConnected); anIter.More(); anIter.Next())
-  {
-    // Check for the given structure
-    if (anIter.Value() == aStruct)
-    {
-      myConnected.Remove (anIter);
+  OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
 
-      if (aStruct->IsRaytracable())
-      {
-        UpdateStateWithAncestorStructures();
-        UpdateRaytracableWithAncestorStructures();
-      }
+  if (myInstancedStructure == aStruct)
+  {
+    myInstancedStructure = NULL;
 
-      aStruct->UnregisterAncestorStructure (this);
-      return;
+    if (aStruct->IsRaytracable())
+    {
+      UpdateStateIfRaytracable();
     }
   }
 }
@@ -555,12 +437,14 @@ void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
     // Check for the given group
     if (aGroupIter.Value() == theGroup)
     {
+      const Standard_Boolean wasRaytracable =
+        static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
+
       theGroup->Clear (Standard_False);
 
-      if (((OpenGl_Group* )theGroup.operator->())->IsRaytracable())
+      if (wasRaytracable)
       {
-        UpdateStateWithAncestorStructures();
-        UpdateRaytracableWithAncestorStructures();
+        UpdateStateIfRaytracable();
       }
 
       myGroups.Remove (aGroupIter);
@@ -598,8 +482,7 @@ void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
 
   if (aRaytracableGroupDeleted)
   {
-    UpdateStateWithAncestorStructures();
-    UpdateRaytracableWithAncestorStructures();
+    myIsRaytracable = Standard_False;
   }
 
   Is2dText       = Standard_False;
@@ -607,109 +490,137 @@ void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
 }
 
 // =======================================================================
-// function : Render
+// function : renderGeometry
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
+void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
+                                       bool&                           theHasClosed) const
 {
-  // Process the structure only if visible
-  if ( myNamedStatus & OPENGL_NS_HIDE )
-    return;
-
-  const Handle(OpenGl_Context)& aCtx = AWorkspace->GetGlContext();
+  if (myInstancedStructure != NULL)
+  {
+    myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
+  }
 
-  // Render named status
-  const Standard_Integer named_status = AWorkspace->NamedStatus;
-  AWorkspace->NamedStatus |= myNamedStatus;
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
+  {
+    theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
+    aGroupIter.Value()->Render (theWorkspace);
+  }
+}
 
-  // Is rendering in ADD or IMMEDIATE mode?
-  const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & OPENGL_NS_IMMEDIATE) != 0;
+// =======================================================================
+// function : renderClosedGeometry
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::renderClosedGeometry (const Handle(OpenGl_Workspace)& theWorkspace) const
+{
+  if (myInstancedStructure != NULL)
+  {
+    myInstancedStructure->renderClosedGeometry (theWorkspace);
+  }
 
-  // Apply local transformation
-  GLint matrix_mode = 0;
-  const OpenGl_Matrix *local_trsf = NULL;
-  if (myTransformation)
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    if (isImmediate)
+    if (aGroupIter.Value()->IsClosed())
     {
-      Tmatrix3 aModelWorld;
-      call_util_transpose_mat (*aModelWorld, myTransformation->mat);
-      glGetIntegerv (GL_MATRIX_MODE, &matrix_mode);
+      aGroupIter.Value()->Render (theWorkspace);
+    }
+  }
+}
 
-      if (!aCtx->ShaderManager()->IsEmpty())
-      {
-        Tmatrix3 aWorldView;
-        glGetFloatv (GL_MODELVIEW_MATRIX, *aWorldView);
+// =======================================================================
+// function : Render
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
+{
+  // Process the structure only if visible
+  if (!visible)
+  {
+    return;
+  }
 
-        Tmatrix3 aProjection;
-        glGetFloatv (GL_PROJECTION_MATRIX, *aProjection);
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
 
-        aCtx->ShaderManager()->UpdateModelWorldStateTo (&aModelWorld);
-        aCtx->ShaderManager()->UpdateWorldViewStateTo (&aWorldView);
-        aCtx->ShaderManager()->UpdateProjectionStateTo (&aProjection);
-      }
+  // Render named status
+  const Standard_Integer aNamedStatus = theWorkspace->NamedStatus;
+  if (highlight)
+  {
+    theWorkspace->NamedStatus |= OPENGL_NS_HIGHLIGHT;
+  }
 
-      glMatrixMode (GL_MODELVIEW);
-      glPushMatrix ();
-      glScalef (1.F, 1.F, 1.F);
-      glMultMatrixf (*aModelWorld);
-    }
-    else
-    {
-      glMatrixMode (GL_MODELVIEW);
-      glPushMatrix();
+  // Apply local transformation
+  aCtx->ModelWorldState.Push();
+  aCtx->ModelWorldState.SetCurrent (Transformation);
 
-      local_trsf = AWorkspace->SetStructureMatrix (myTransformation);
-    }
+  // detect scale transform
+  const Standard_Boolean   anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
+  const Standard_ShortReal aScaleX          = Transformation.GetRow (0).xyz().SquareModulus();
+  if (Abs (aScaleX - 1.f) > Precision::Confusion())
+  {
+    aCtx->SetGlNormalizeEnabled (Standard_True);
   }
 
-  // Apply transform persistence
-  const TEL_TRANSFORM_PERSISTENCE *trans_pers = NULL;
-  if ( myTransPers && myTransPers->mode != 0 )
+  if (TransformPersistence.Flags)
   {
-    trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence (aCtx, myTransPers);
+    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();
   }
 
+  // Take into account transform persistence
+  aCtx->ApplyModelViewMatrix();
+
   // 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);
+  const OpenGl_AspectLine *anAspectLine = theWorkspace->AspectLine (Standard_False);
+  const OpenGl_AspectFace *anAspectFace = theWorkspace->AspectFace (Standard_False);
+  const OpenGl_AspectMarker *anAspectMarker = theWorkspace->AspectMarker (Standard_False);
+  const OpenGl_AspectText *anAspectText = theWorkspace->AspectText (Standard_False);
   if (myAspectLine)
-    AWorkspace->SetAspectLine(myAspectLine);
+  {
+    theWorkspace->SetAspectLine (myAspectLine);
+  }
   if (myAspectFace)
-    AWorkspace->SetAspectFace(myAspectFace);
+  {
+    theWorkspace->SetAspectFace (myAspectFace);
+  }
   if (myAspectMarker)
-    AWorkspace->SetAspectMarker(myAspectMarker);
+  {
+    theWorkspace->SetAspectMarker (myAspectMarker);
+  }
   if (myAspectText)
-    AWorkspace->SetAspectText(myAspectText);
-
-  // Apply highlight color
-  const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
-  if (myHighlightColor)
-    AWorkspace->HighlightColor = myHighlightColor;
+  {
+    theWorkspace->SetAspectText (myAspectText);
+  }
 
-  // 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();
+  // 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
-  Handle(Graphic3d_SequenceOfHClipPlane) aUserPlanes;
+  NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
 
   // Collect clipping planes of structure scope
   if (!myClipPlanes.IsEmpty())
   {
-    Graphic3d_SequenceOfHClipPlane::Iterator aClippingIt (myClipPlanes);
-    for (; aClippingIt.More(); aClippingIt.Next())
+    Graphic3d_SequenceOfHClipPlane::Iterator aClippingIter (myClipPlanes);
+    for (; aClippingIter.More(); aClippingIter.Next())
     {
-      const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
+      const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIter.Value();
       if (!aClipPlane->IsOn())
       {
         continue;
@@ -727,87 +638,71 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
   {
     // add planes at loaded view matrix state
-    aContext->ChangeClipping().AddWorld (*aUserPlanes, AWorkspace);
+    aCtx->ChangeClipping().AddWorld (aCtx, *aUserPlanes);
 
     // Set OCCT state uniform variables
-    if (!aContext->ShaderManager()->IsEmpty())
+    if (!aCtx->ShaderManager()->IsEmpty())
     {
-      aContext->ShaderManager()->UpdateClippingState();
+      aCtx->ShaderManager()->UpdateClippingState();
     }
   }
 
   // Render groups
-  const Graphic3d_SequenceOfGroup& aGroups = DrawGroups();
-  for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
+  bool hasClosedPrims = false;
+  renderGeometry (theWorkspace, hasClosedPrims);
+
+  // Reset correction for mirror transform
+  if (myIsMirrored)
   {
-    aGroupIter.Value()->Render (AWorkspace);
+    aCtx->core11fwd->glFrontFace (GL_CCW);
   }
 
   // Render capping for structure groups
-  if (!aContext->Clipping().Planes().IsEmpty())
+  if (hasClosedPrims
+  && !aCtx->Clipping().Planes().IsEmpty())
   {
-    OpenGl_CappingAlgo::RenderCapping (AWorkspace, aGroups);
+    OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
   }
 
   // Revert structure clippings
   if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
   {
-    aContext->ChangeClipping().Remove (*aUserPlanes);
+    aCtx->ChangeClipping().Remove (aCtx, *aUserPlanes);
 
     // Set OCCT state uniform variables
-    if (!aContext->ShaderManager()->IsEmpty())
+    if (!aCtx->ShaderManager()->IsEmpty())
     {
-      aContext->ShaderManager()->RevertClippingState();
+      aCtx->ShaderManager()->RevertClippingState();
     }
   }
 
-  // Restore highlight color
-  AWorkspace->HighlightColor = highlight_color;
-
-  // Restore aspects
-  AWorkspace->SetAspectLine(aspect_line);
-  AWorkspace->SetAspectFace(aspect_face);
-  AWorkspace->SetAspectMarker(aspect_marker);
-  AWorkspace->SetAspectText(aspect_text);
-
-  // Restore transform persistence
-  if ( myTransPers && myTransPers->mode != 0 )
-  {
-    AWorkspace->ActiveView()->BeginTransformPersistence (aContext, trans_pers);
-  }
-
   // Restore local transformation
-  if (myTransformation)
+  aCtx->ModelWorldState.Pop();
+  aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
+  if (TransformPersistence.Flags)
   {
-    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 } };
+    aCtx->ProjectionState.Pop();
+    aCtx->WorldViewState.Pop();
+    aCtx->ApplyProjectionMatrix();
+  }
 
-      aContext->ShaderManager()->RevertModelWorldStateTo (&aModelWorldState);
-    }
-    else
-    {
-      AWorkspace->SetStructureMatrix (local_trsf, true);
+  // Restore highlight color
+  theWorkspace->HighlightColor = aHighlightColor;
 
-      glMatrixMode (GL_MODELVIEW);
-      glPopMatrix();
-    }
-  }
+  // Restore aspects
+  theWorkspace->SetAspectLine (anAspectLine);
+  theWorkspace->SetAspectFace (anAspectFace);
+  theWorkspace->SetAspectMarker (anAspectMarker);
+  theWorkspace->SetAspectText (anAspectText);
 
   // Apply highlight box
   if (!myHighlightBox.IsNull())
   {
-    myHighlightBox->Render (AWorkspace);
+    myHighlightBox->Render (theWorkspace);
   }
 
   // Restore named status
-  AWorkspace->NamedStatus = named_status;
+  theWorkspace->NamedStatus = aNamedStatus;
 }
 
 // =======================================================================
@@ -823,9 +718,6 @@ void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
   clearHighlightColor (theGlCtx);
-
-  // Remove from connected list of ancestor
-  UnregisterFromAncestorStructure();
 }
 
 // =======================================================================
@@ -860,79 +752,6 @@ void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCt
   }
 }
 
-//=======================================================================
-//function : SetZLayer
-//purpose  :
-//=======================================================================
-void OpenGl_Structure::SetZLayer (const Standard_Integer theLayerIndex)
-{
-  myZLayer = theLayerIndex;
-}
-
-//=======================================================================
-//function : GetZLayer
-//purpose  :
-//=======================================================================
-Standard_Integer OpenGl_Structure::GetZLayer () const
-{
-  return myZLayer;
-}
-
-//! Dummy structure which just redirects to groups of another structure.
-class OpenGl_StructureShadow : public OpenGl_Structure
-{
-
-public:
-
-  //! Create empty structure
-  OpenGl_StructureShadow (const Handle(Graphic3d_StructureManager)& theManager,
-                          const Handle(OpenGl_Structure)&           theStructure);
-
-  virtual const Graphic3d_SequenceOfGroup& DrawGroups() const { return myParent->DrawGroups(); }
-
-private:
-
-  Handle(OpenGl_Structure) myParent;
-
-public:
-
-  DEFINE_STANDARD_RTTI(OpenGl_StructureShadow) // Type definition
-
-};
-
-DEFINE_STANDARD_HANDLE(OpenGl_StructureShadow, OpenGl_Structure)
-
-IMPLEMENT_STANDARD_HANDLE (OpenGl_StructureShadow, OpenGl_Structure)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_StructureShadow, OpenGl_Structure)
-
-//=======================================================================
-//function : OpenGl_StructureShadow
-//purpose  :
-//=======================================================================
-OpenGl_StructureShadow::OpenGl_StructureShadow (const Handle(Graphic3d_StructureManager)& theManager,
-                                                const Handle(OpenGl_Structure)&           theStructure)
-: OpenGl_Structure (theManager)
-{
-  Handle(OpenGl_StructureShadow) aShadow = Handle(OpenGl_StructureShadow)::DownCast (theStructure);
-  myParent = aShadow.IsNull() ? theStructure : aShadow->myParent;
-
-
-  Composition   = myParent->Composition;
-  ContainsFacet = myParent->ContainsFacet;
-  IsInfinite    = myParent->IsInfinite;
-  for (Standard_Integer i = 0; i <= 3; ++i)
-  {
-    for (Standard_Integer j = 0; j <= 3; ++j)
-    {
-      Graphic3d_CStructure::Transformation[i][j] = myParent->Graphic3d_CStructure::Transformation[i][j];
-    }
-  }
-
-  TransformPersistence.IsSet = myParent->TransformPersistence.IsSet;
-  TransformPersistence.Flag  = myParent->TransformPersistence.Flag;
-  TransformPersistence.Point = myParent->TransformPersistence.Point;
-}
-
 //=======================================================================
 //function : ShadowLink
 //purpose  :