0026122: Visualization, TKOpenGl - clipping and capping is broken when ffp is disable...
[occt.git] / src / OpenGl / OpenGl_Structure.cxx
index 16a9ff9..69d2e4d 100644 (file)
@@ -1,32 +1,32 @@
 // 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.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
-#include <OpenGl_GlCore11.hxx>
-
-#include <OpenGl_Structure.hxx>
-
-#include <OpenGl_Workspace.hxx>
-#include <OpenGl_Vec.hxx>
-#include <OpenGl_View.hxx>
 #include <OpenGl_CappingAlgo.hxx>
 #include <OpenGl_Context.hxx>
+#include <OpenGl_GlCore11.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_ShaderProgram.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.hxx>
+
 
 //! Auxiliary class for bounding box presentation
 class OpenGl_BndBoxPrs : public OpenGl_Element
@@ -35,14 +35,15 @@ 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;
+  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);
@@ -64,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_ADD | 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);
@@ -87,10 +85,11 @@ public:
     {
       theWorkspace->EnableTexture (aPrevTexture);
     }
+  #endif
   }
 
   //! Release graphical resources
-  virtual void Release (const Handle(OpenGl_Context)& )
+  virtual void Release (OpenGl_Context*)
   {
     //
   }
@@ -112,35 +111,25 @@ 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 ()
-: 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),
+  myTransformation     (NULL),
+  myAspectLine         (NULL),
+  myAspectFace         (NULL),
+  myAspectMarker       (NULL),
+  myAspectText         (NULL),
+  myHighlightColor     (NULL),
+  myInstancedStructure (NULL),
+  myIsRaytracable      (Standard_False),
+  myModificationState  (0),
+  myIsCulled           (Standard_True),
+  myIsMirrored         (Standard_False)
 {
+  //
 }
 
 // =======================================================================
@@ -151,381 +140,573 @@ OpenGl_Structure::~OpenGl_Structure()
 {
   Release (Handle(OpenGl_Context)());
   delete myTransformation;  myTransformation  = NULL;
-  delete myTransPers;       myTransPers       = NULL;
 }
 
 // =======================================================================
-// function : SetTransformation
+// function : UpdateAspects
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetTransformation(const float *AMatrix)
+void OpenGl_Structure::UpdateAspects()
 {
-  if (!myTransformation)
-    myTransformation = new OpenGl_Matrix();
+  if (ContextLine.IsDef)
+    SetAspectLine (ContextLine);
 
-  matcpy( myTransformation->mat, AMatrix );
+  if (ContextFillArea.IsDef)
+    SetAspectFace (ContextFillArea);
+
+  if (ContextMarker.IsDef)
+    SetAspectMarker (ContextMarker);
+
+  if (ContextText.IsDef)
+    SetAspectText (ContextText);
 }
 
 // =======================================================================
-// function : SetTransformPersistence
+// function : UpdateTransformation
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers)
+void OpenGl_Structure::UpdateTransformation()
 {
-  if (!myTransPers)
-    myTransPers = new TEL_TRANSFORM_PERSISTENCE;
+  if (myTransformation == NULL)
+  {
+    myTransformation = new OpenGl_Matrix();
+  }
+
+  Standard_ShortReal (*aMat)[4] = Graphic3d_CStructure::Transformation;
 
-  myTransPers->mode = ATransPers.Flag;
-  myTransPers->pointX = ATransPers.Point.x;
-  myTransPers->pointY = ATransPers.Point.y;
-  myTransPers->pointZ = ATransPers.Point.z;
+  Standard_ShortReal aDet =
+    aMat[0][0] * (aMat[1][1] * aMat[2][2] - aMat[2][1] * aMat[1][2]) -
+    aMat[0][1] * (aMat[1][0] * aMat[2][2] - aMat[2][0] * aMat[1][2]) +
+    aMat[0][2] * (aMat[1][0] * aMat[2][1] - aMat[2][0] * aMat[1][1]);
+
+  // Determinant of transform matrix less then 0 means that mirror transform applied.
+  myIsMirrored = aDet < 0.0f;
+
+  matcpy (myTransformation->mat, &Graphic3d_CStructure::Transformation[0][0]);
+
+  if (IsRaytracable())
+  {
+    ++myModificationState;
+  }
 }
 
 // =======================================================================
 // function : SetAspectLine
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &AContext)
+void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &theAspect)
 {
   if (!myAspectLine)
+  {
     myAspectLine = new OpenGl_AspectLine();
-  myAspectLine->SetContext( AContext );
+  }
+  myAspectLine->SetAspect (theAspect);
 }
 
 // =======================================================================
 // function : SetAspectFace
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetAspectFace (const Handle(OpenGl_Context)&   theCtx,
-                                      const CALL_DEF_CONTEXTFILLAREA& theAspect)
+void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect)
 {
   if (!myAspectFace)
   {
     myAspectFace = new OpenGl_AspectFace();
   }
-  myAspectFace->Init (theCtx, theAspect);
+  myAspectFace->SetAspect (theAspect);
+
+  if (IsRaytracable())
+  {
+    ++myModificationState;
+  }
 }
 
 // =======================================================================
 // function : SetAspectMarker
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetAspectMarker (const Handle(OpenGl_Context)& theCtx,
-                                        const CALL_DEF_CONTEXTMARKER& theAspect)
+void OpenGl_Structure::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theAspect)
 {
   if (!myAspectMarker)
   {
     myAspectMarker = new OpenGl_AspectMarker();
   }
-  myAspectMarker->Init (theCtx, theAspect);
+  myAspectMarker->SetAspect (theAspect);
 }
 
 // =======================================================================
 // function : SetAspectText
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &AContext)
+void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect)
 {
   if (!myAspectText)
+  {
     myAspectText = new OpenGl_AspectText();
-  myAspectText->SetContext( AContext );
+  }
+  myAspectText->SetAspect (theAspect);
 }
 
 // =======================================================================
-// function : SetHighlightBox
+// function : clearHighlightBox
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetHighlightBox (const Handle(OpenGl_Context)& theGlCtx,
-                                        const CALL_DEF_BOUNDBOX&      theBoundBox)
+void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
 {
-  if (myHighlightBox != NULL)
+  if (!myHighlightBox.IsNull())
   {
     myHighlightBox->Release (theGlCtx);
+    myHighlightBox.Nullify();
   }
+}
+
+// =======================================================================
+// function : HighlightWithColor
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3&  theColor,
+                                           const Standard_Boolean theToCreate)
+{
+  const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
+  if (theToCreate)
+    setHighlightColor   (aContext, theColor);
   else
+    clearHighlightColor (aContext);
+}
+
+// =======================================================================
+// function : HighlightWithBndBox
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
+                                            const Standard_Boolean             theToCreate)
+{
+  const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
+  if (!theToCreate)
   {
-    myHighlightBox = new OpenGl_Group();
+    clearHighlightBox (aContext);
+    return;
   }
 
-  CALL_DEF_CONTEXTLINE aContextLine;
-  aContextLine.Color    = theBoundBox.Color;
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Release (aContext);
+  }
+  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->SetAspectLine (aContextLine);
+  myHighlightBox->UpdateAspectLine (Standard_True);
 
-  OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (theBoundBox);
-  myHighlightBox->AddElement (TelParray, aBndBoxPrs);
+  OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
+  myHighlightBox->AddElement (aBndBoxPrs);
 }
 
 // =======================================================================
-// function : ClearHighlightBox
+// function : setHighlightColor
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::ClearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
+void OpenGl_Structure::setHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
+                                          const Graphic3d_Vec3&         theColor)
 {
-  if (myHighlightBox != NULL)
+  clearHighlightBox (theGlCtx);
+  if (myHighlightColor == NULL)
   {
-    OpenGl_Element::Destroy (theGlCtx, myHighlightBox);
+    myHighlightColor = new TEL_COLOUR();
   }
+
+  myHighlightColor->rgb[0] = theColor.r();
+  myHighlightColor->rgb[1] = theColor.g();
+  myHighlightColor->rgb[2] = theColor.b();
+  myHighlightColor->rgb[3] = 1.F;
 }
 
 // =======================================================================
-// function : SetHighlightColor
+// function : clearHighlightColor
 // 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::clearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
 {
-  ClearHighlightBox (theGlCtx);
-  if (myHighlightColor == NULL)
+  clearHighlightBox(theGlCtx);
+  delete myHighlightColor;
+  myHighlightColor = NULL;
+}
+
+// =======================================================================
+// function : OnVisibilityChanged
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::OnVisibilityChanged()
+{
+  if (IsRaytracable())
   {
-    myHighlightColor = new TEL_COLOUR();
+    ++myModificationState;
   }
+}
 
-  myHighlightColor->rgb[0] = R;
-  myHighlightColor->rgb[1] = G;
-  myHighlightColor->rgb[2] = B;
-  myHighlightColor->rgb[3] = 1.F;
+// =======================================================================
+// function : IsRaytracable
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_Structure::IsRaytracable() const
+{
+  if (!myGroups.IsEmpty())
+  {
+    return myIsRaytracable; // geometry structure
+  }
+  else if (myInstancedStructure != NULL)
+  {
+    return myInstancedStructure->IsRaytracable(); // instance structure
+  }
+
+  return Standard_False; // has no any groups or structures
 }
 
 // =======================================================================
-// function : ClearHighlightColor
+// function : UpdateRaytracableState
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::ClearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
+void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
 {
-  ClearHighlightBox(theGlCtx);
-  delete myHighlightColor;
-  myHighlightColor = NULL;
+  myIsRaytracable = !toCheck || OpenGl_Raytrace::IsRaytracedStructure (this);
+
+  if (IsRaytracable())
+  {
+    ++myModificationState;
+  }
 }
 
 // =======================================================================
 // function : Connect
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::Connect (const OpenGl_Structure *AStructure)
+void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
 {
-  Disconnect (AStructure);
-  myConnected.Append(AStructure);
+  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())
+  {
+    UpdateStateIfRaytracable (Standard_False);
+  }
 }
 
 // =======================================================================
 // function : Disconnect
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::Disconnect (const OpenGl_Structure *AStructure)
+void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
 {
-  OpenGl_ListOfStructure::Iterator its(myConnected);
-  while (its.More())
+  OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
+
+  if (myInstancedStructure == aStruct)
   {
-    // Check for the given structure
-    if (its.Value() == AStructure)
+    myInstancedStructure = NULL;
+
+    if (aStruct->IsRaytracable())
     {
-      myConnected.Remove(its);
-      return;
+      UpdateStateIfRaytracable();
     }
-    its.Next();
   }
 }
 
 // =======================================================================
-// function : AddGroup
+// function : NewGroup
 // purpose  :
 // =======================================================================
-OpenGl_Group * OpenGl_Structure::AddGroup ()
+Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
 {
-  // Create new group
-  OpenGl_Group *g = new OpenGl_Group;
-  myGroups.Append(g);
-  return g;
+  Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
+  myGroups.Append (aGroup);
+  return aGroup;
 }
 
 // =======================================================================
 // function : RemoveGroup
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::RemoveGroup (const Handle(OpenGl_Context)& theGlCtx,
-                                    const OpenGl_Group*           theGroup)
+void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
 {
-  for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
+  if (theGroup.IsNull())
+  {
+    return;
+  }
+
+  for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
     // Check for the given group
-    if (anIter.Value() == theGroup)
+    if (aGroupIter.Value() == theGroup)
     {
-      // Delete object
-      OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
-      myGroups.Remove (anIter);
+      const Standard_Boolean wasRaytracable =
+        static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
+
+      theGroup->Clear (Standard_False);
+
+      if (wasRaytracable)
+      {
+        UpdateStateIfRaytracable();
+      }
+
+      myGroups.Remove (aGroupIter);
       return;
     }
   }
 }
 
+// =======================================================================
+// function : Clear
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::Clear()
+{
+  Clear (GlDriver()->GetSharedContext());
+}
+
 // =======================================================================
 // function : Clear
 // purpose  :
 // =======================================================================
 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
 {
+  Standard_Boolean aRaytracableGroupDeleted (Standard_False);
+
   // Release groups
-  for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
+    aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
+
     // Delete objects
-    OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
+    aGroupIter.ChangeValue()->Release (theGlCtx);
   }
   myGroups.Clear();
+
+  if (aRaytracableGroupDeleted)
+  {
+    myIsRaytracable = Standard_False;
+  }
+
+  Is2dText       = Standard_False;
+  IsForHighlight = Standard_False;
+}
+
+// =======================================================================
+// function : RenderGeometry
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::RenderGeometry (const Handle(OpenGl_Workspace) &theWorkspace) const
+{
+  // Render groups
+  const Graphic3d_SequenceOfGroup& aGroups = DrawGroups();
+  for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
+  {
+    aGroupIter.Value()->Render (theWorkspace);
+  }
 }
 
 // =======================================================================
 // 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;
+  }
+
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
 
   // Render named status
-  const Standard_Integer named_status = AWorkspace->NamedStatus;
-  AWorkspace->NamedStatus |= myNamedStatus;
+  const Standard_Integer aNamedStatus = theWorkspace->NamedStatus;
+  if (highlight)
+  {
+    theWorkspace->NamedStatus |= OPENGL_NS_HIGHLIGHT;
+  }
 
-  // Is rendering in ADD or IMMEDIATE mode?
-  const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
+  // Do we need to restore GL_NORMALIZE?
+  const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
 
   // Apply local transformation
-  GLint matrix_mode = 0;
-  const OpenGl_Matrix *local_trsf = NULL;
   if (myTransformation)
   {
-    if (isImmediate)
+    OpenGl_Matrix aModelWorld;
+    OpenGl_Transposemat3 (&aModelWorld, myTransformation);
+    aCtx->ModelWorldState.Push();
+    aCtx->ModelWorldState.SetCurrent (OpenGl_Mat4::Map ((Standard_ShortReal* )aModelWorld.mat));
+
+    Standard_ShortReal aScaleX = OpenGl_Vec3 (myTransformation->mat[0][0],
+                                              myTransformation->mat[0][1],
+                                              myTransformation->mat[0][2]).SquareModulus();
+    // Scale transform detected.
+    if (Abs (aScaleX - 1.f) > Precision::Confusion())
     {
-      float mat16[16];
-      call_util_transpose_mat (mat16, myTransformation->mat);
-      glGetIntegerv (GL_MATRIX_MODE, &matrix_mode);
-      glMatrixMode (GL_MODELVIEW);
-      glPushMatrix ();
-      glScalef (1.F, 1.F, 1.F);
-      glMultMatrixf (mat16);
-    }
-    else
-    {
-      glMatrixMode (GL_MODELVIEW);
-      glPushMatrix();
-
-      local_trsf = AWorkspace->SetStructureMatrix(myTransformation);
+      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( 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);
+  {
+    theWorkspace->SetAspectText (myAspectText);
+  }
 
-  // Apply highlight box
-  if (myHighlightBox)
-    myHighlightBox->Render( AWorkspace );
+  // Apply correction for mirror transform
+  if (myIsMirrored)
+  {
+    aCtx->core11fwd->glFrontFace (GL_CW);
+  }
 
   // Apply highlight color
-  const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
+  const TEL_COLOUR *aHighlightColor = theWorkspace->HighlightColor;
   if (myHighlightColor)
-    AWorkspace->HighlightColor = myHighlightColor;
+    theWorkspace->HighlightColor = myHighlightColor;
 
-  // Render connected structures
-  OpenGl_ListOfStructure::Iterator its(myConnected);
-  while (its.More())
+  // Render instanced structure (if exists)
+  if (myInstancedStructure != NULL)
   {
-    its.Value()->Render(AWorkspace);
-    its.Next();
+    myInstancedStructure->RenderGeometry (theWorkspace);
   }
 
   // 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
+  NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
 
-  // Collect planes which should be turned on for structure
-  Graphic3d_SetOfHClipPlane aPlanesOn;
-  Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (myClipPlanes);
-  for (; aPlaneIt.More(); aPlaneIt.Next())
+  // Collect clipping planes of structure scope
+  if (!myClipPlanes.IsEmpty())
   {
-    const Handle(Graphic3d_ClipPlane)& aUserPln = aPlaneIt.Value();
-    if (aUserPln->IsOn())
-      aPlanesOn.Add (aUserPln);
+    Graphic3d_SequenceOfHClipPlane::Iterator aClippingIter (myClipPlanes);
+    for (; aClippingIter.More(); aClippingIter.Next())
+    {
+      const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIter.Value();
+      if (!aClipPlane->IsOn())
+      {
+        continue;
+      }
+
+      if (aUserPlanes.IsNull())
+      {
+        aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
+      }
+
+      aUserPlanes->Append (aClipPlane);
+    }
   }
 
-  // set structure clipping planes
-  if (aPlanesOn.Size() > 0)
+  if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
   {
-    aContext->ChangeClipping().Set (aPlanesOn, AWorkspace->ViewMatrix());
+    // add planes at loaded view matrix state
+    aCtx->ChangeClipping().AddWorld (aCtx, *aUserPlanes);
+
+    // Set OCCT state uniform variables
+    if (!aCtx->ShaderManager()->IsEmpty())
+    {
+      aCtx->ShaderManager()->UpdateClippingState();
+    }
   }
 
   // Render groups
-  OpenGl_ListOfGroup::Iterator itg(myGroups);
-  while (itg.More())
+  const Graphic3d_SequenceOfGroup& aGroups = DrawGroups();
+  for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    itg.Value()->Render(AWorkspace);
-    itg.Next();
+    aGroupIter.Value()->Render (theWorkspace);
   }
 
-  // Render cappings for structure groups
-  OpenGl_CappingAlgo::RenderCapping (AWorkspace, myGroups);
-
-  // unset structure clipping planes
-  if (aPlanesOn.Size() > 0)
+  // Reset correction for mirror transform
+  if (myIsMirrored)
   {
-    aContext->ChangeClipping().Unset (aPlanesOn);
+    aCtx->core11fwd->glFrontFace (GL_CCW);
   }
 
-  // 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);
+  // Render capping for structure groups
+  if (!aCtx->Clipping().Planes().IsEmpty())
+  {
+    OpenGl_CappingAlgo::RenderCapping (theWorkspace, aGroups);
+  }
 
-  // Restore transform persistence
-  if ( myTransPers && myTransPers->mode != 0 )
+  // Revert structure clippings
+  if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
   {
-    AWorkspace->ActiveView()->BeginTransformPersistence( trans_pers );
+    aCtx->ChangeClipping().Remove (aCtx, *aUserPlanes);
+
+    // Set OCCT state uniform variables
+    if (!aCtx->ShaderManager()->IsEmpty())
+    {
+      aCtx->ShaderManager()->RevertClippingState();
+    }
   }
 
   // Restore local transformation
   if (myTransformation)
   {
-    if (isImmediate)
-    {
-      glPopMatrix ();
-      glMatrixMode (matrix_mode);
-    }
-    else
-    {
-      AWorkspace->SetStructureMatrix(local_trsf);
+    aCtx->ModelWorldState.Pop();
+    aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
+  }
+  if (TransformPersistence.Flags)
+  {
+    aCtx->ProjectionState.Pop();
+    aCtx->WorldViewState.Pop();
+    aCtx->ApplyProjectionMatrix();
+  }
 
-      glMatrixMode (GL_MODELVIEW);
-      glPopMatrix();
-    }
+  // Restore highlight color
+  theWorkspace->HighlightColor = aHighlightColor;
+
+  // Restore aspects
+  theWorkspace->SetAspectLine (anAspectLine);
+  theWorkspace->SetAspectFace (anAspectFace);
+  theWorkspace->SetAspectMarker (anAspectMarker);
+  theWorkspace->SetAspectText (anAspectText);
+
+  // Apply highlight box
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Render (theWorkspace);
   }
 
   // Restore named status
-  AWorkspace->NamedStatus = named_status;
+  theWorkspace->NamedStatus = aNamedStatus;
 }
 
 // =======================================================================
@@ -536,11 +717,11 @@ 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);
+  OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
+  OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
+  OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
+  OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
+  clearHighlightColor (theGlCtx);
 }
 
 // =======================================================================
@@ -549,50 +730,37 @@ 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())
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    OpenGl_Group* aGroup = const_cast<OpenGl_Group*& > (anIter.ChangeValue());
-    if (aGroup != NULL)
-    {
-      aGroup->Release (theGlCtx);
-    }
+    aGroupIter.ChangeValue()->Release (theGlCtx);
   }
   if (myAspectLine != NULL)
   {
-    myAspectLine->Release (theGlCtx);
+    myAspectLine->Release (theGlCtx.operator->());
   }
   if (myAspectFace != NULL)
   {
-    myAspectFace->Release (theGlCtx);
+    myAspectFace->Release (theGlCtx.operator->());
   }
   if (myAspectMarker != NULL)
   {
-    myAspectMarker->Release (theGlCtx);
+    myAspectMarker->Release (theGlCtx.operator->());
   }
   if (myAspectText != NULL)
   {
-    myAspectText->Release (theGlCtx);
+    myAspectText->Release (theGlCtx.operator->());
   }
-  if (myHighlightBox != NULL)
+  if (!myHighlightBox.IsNull())
   {
-    myHighlightBox->Release (theGlCtx);
+    myHighlightBox->Release (theGlCtx.operator->());
   }
 }
 
 //=======================================================================
-//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);
 }