0024739: TKOpenGl - port ray-tracing from OpenCL to GLSL for better integration and...
[occt.git] / src / OpenGl / OpenGl_Structure.cxx
index 6bcd5bb..b0d8200 100644 (file)
@@ -1,34 +1,34 @@
 // 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_CappingAlgo.hxx>
+#include <OpenGl_Context.hxx>
 #include <OpenGl_GlCore11.hxx>
-
+#include <OpenGl_GraphicDriver.hxx>
+#include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_Structure.hxx>
-
-#include <OpenGl_Workspace.hxx>
+#include <OpenGl_telem_util.hxx>
 #include <OpenGl_Vec.hxx>
 #include <OpenGl_View.hxx>
-#include <OpenGl_CappingAlgo.hxx>
-#include <OpenGl_Context.hxx>
-#include <OpenGl_telem_util.hxx>
+#include <OpenGl_Workspace.hxx>
+
+#include <Graphic3d_SequenceOfHClipPlane_Handle.hxx>
 
-#include <Graphic3d_SetOfHClipPlane_Handle.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
@@ -71,7 +71,7 @@ public:
     const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
 
     glDisable (GL_LIGHTING);
-    if ((theWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0)
+    if ((theWorkspace->NamedStatus & OPENGL_NS_IMMEDIATE) != 0)
     {
       glDepthMask (GL_FALSE);
     }
@@ -131,18 +131,21 @@ static void call_util_transpose_mat (float tmat[16], float mat[4][4])
 // function : OpenGl_Structure
 // purpose  :
 // =======================================================================
-OpenGl_Structure::OpenGl_Structure ()
-: myTransformation(NULL),
+OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
+: Graphic3d_CStructure (theManager),
+  myTransformation(NULL),
   myTransPers(NULL),
   myAspectLine(NULL),
   myAspectFace(NULL),
   myAspectMarker(NULL),
   myAspectText(NULL),
-  myHighlightBox(NULL),
   myHighlightColor(NULL),
   myNamedStatus(0),
-  myZLayer(0)
+  myZLayer(0),
+  myIsRaytracable (Standard_False),
+  myModificationState (0)
 {
+  UpdateNamedStatus();
 }
 
 // =======================================================================
@@ -157,15 +160,43 @@ OpenGl_Structure::~OpenGl_Structure()
 }
 
 // =======================================================================
-// function : SetTransformation
+// function : UpdateAspects
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::SetTransformation(const float *AMatrix)
+void OpenGl_Structure::UpdateAspects()
 {
-  if (!myTransformation)
+  SetTransformPersistence (TransformPersistence);
+
+  if (ContextLine.IsDef)
+    SetAspectLine (ContextLine);
+
+  if (ContextFillArea.IsDef)
+    SetAspectFace (ContextFillArea);
+
+  if (ContextMarker.IsDef)
+    SetAspectMarker (ContextMarker);
+
+  if (ContextText.IsDef)
+    SetAspectText (ContextText);
+}
+
+// =======================================================================
+// function : UpdateTransformation
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::UpdateTransformation()
+{
+  if (myTransformation == NULL)
+  {
     myTransformation = new OpenGl_Matrix();
+  }
+
+  matcpy (myTransformation->mat, &Graphic3d_CStructure::Transformation[0][0]);
 
-  matcpy( myTransformation->mat, AMatrix );
+  if (myIsRaytracable)
+  {
+    UpdateStateWithAncestorStructures();
+  }
 }
 
 // =======================================================================
@@ -207,6 +238,11 @@ void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect)
     myAspectFace = new OpenGl_AspectFace();
   }
   myAspectFace->SetAspect (theAspect);
+
+  if (myIsRaytracable)
+  {
+    UpdateStateWithAncestorStructures();
+  }
 }
 
 // =======================================================================
@@ -236,149 +272,332 @@ void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &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)& aCtx = GlDriver()->GetSharedContext();
+  if (theToCreate)
+    setHighlightColor   (aCtx, theColor);
+  else
+    clearHighlightColor (aCtx);
+}
+
+// =======================================================================
+// function : HighlightWithBndBox
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
+                                            const Standard_Boolean             theToCreate)
+{
+  const Handle(OpenGl_Context)& aCtx = GlDriver()->GetSharedContext();
+  if (!theToCreate)
+  {
+    clearHighlightBox (aCtx);
+    return;
+  }
+
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Release (aCtx);
   }
   else
   {
-    myHighlightBox = new OpenGl_Group();
+    myHighlightBox = new OpenGl_Group (theStruct);
   }
 
-  CALL_DEF_CONTEXTLINE aContextLine;
-  aContextLine.Color    = theBoundBox.Color;
+  CALL_DEF_CONTEXTLINE& aContextLine = myHighlightBox->ChangeContextLine();
+  aContextLine.IsDef    = 1;
+  aContextLine.Color    = BoundBox.Color;
   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 (BoundBox);
+  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 : UpdateNamedStatus
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::UpdateNamedStatus()
+{
+  myNamedStatus = 0;
+  if (highlight) myNamedStatus |= OPENGL_NS_HIGHLIGHT;
+  if (!visible)  myNamedStatus |= OPENGL_NS_HIDE;
+
+  if (myIsRaytracable)
   {
-    myHighlightColor = new TEL_COLOUR();
+    UpdateStateWithAncestorStructures();
   }
+}
 
-  myHighlightColor->rgb[0] = R;
-  myHighlightColor->rgb[1] = G;
-  myHighlightColor->rgb[2] = B;
-  myHighlightColor->rgb[3] = 1.F;
+// =======================================================================
+// function : RegisterAncestorStructure
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::RegisterAncestorStructure (const OpenGl_Structure* theStructure) const
+{
+  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+  {
+    if (anIt.Value() == theStructure)
+    {
+      return;
+    }
+  }
+
+  myAncestorStructures.Append (theStructure);
 }
 
 // =======================================================================
-// function : ClearHighlightColor
+// function : UnregisterAncestorStructure
 // purpose  :
 // =======================================================================
-void OpenGl_Structure::ClearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
+void OpenGl_Structure::UnregisterAncestorStructure (const OpenGl_Structure* theStructure) const
 {
-  ClearHighlightBox(theGlCtx);
-  delete myHighlightColor;
-  myHighlightColor = NULL;
+  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+  {
+    if (anIt.Value() == theStructure)
+    {
+      myAncestorStructures.Remove (anIt);
+      return;
+    }
+  }
+}
+
+// =======================================================================
+// 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;
+      }
+    }
+  }
+}
+
+// =======================================================================
+// function : UpdateStateWithAncestorStructures
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::UpdateStateWithAncestorStructures() const
+{
+  myModificationState++;
+
+  for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+  {
+    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();
+    }
+  }
 }
 
 // =======================================================================
 // 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 = (OpenGl_Structure* )&theStructure;
+  Disconnect (theStructure);
+  myConnected.Append (aStruct);
+
+  if (aStruct->IsRaytracable())
+  {
+    UpdateStateWithAncestorStructures();
+    SetRaytracableWithAncestorStructures();
+  }
+
+  aStruct->RegisterAncestorStructure (this);
 }
 
 // =======================================================================
 // 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 = (OpenGl_Structure* )&theStructure;
+  for (OpenGl_ListOfStructure::Iterator anIter (myConnected); anIter.More(); anIter.Next())
   {
     // Check for the given structure
-    if (its.Value() == AStructure)
+    if (anIter.Value() == aStruct)
     {
-      myConnected.Remove(its);
+      myConnected.Remove (anIter);
+
+      if (aStruct->IsRaytracable())
+      {
+        UpdateStateWithAncestorStructures();
+        UpdateRaytracableWithAncestorStructures();
+      }
+
+      aStruct->UnregisterAncestorStructure (this);
       return;
     }
-    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);
+      theGroup->Clear (Standard_False);
+
+      if (((OpenGl_Group* )theGroup.operator->())->IsRaytracable())
+      {
+        UpdateStateWithAncestorStructures();
+        UpdateRaytracableWithAncestorStructures();
+      }
+
+      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)
+  {
+    UpdateStateWithAncestorStructures();
+    UpdateRaytracableWithAncestorStructures();
+  }
 }
 
 // =======================================================================
@@ -396,7 +615,9 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   AWorkspace->NamedStatus |= myNamedStatus;
 
   // Is rendering in ADD or IMMEDIATE mode?
-  const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
+  const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & OPENGL_NS_IMMEDIATE) != 0;
+
+  const Handle(OpenGl_Context)& aCtx = AWorkspace->GetGlContext();
 
   // Apply local transformation
   GLint matrix_mode = 0;
@@ -405,20 +626,34 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   {
     if (isImmediate)
     {
-      float mat16[16];
-      call_util_transpose_mat (mat16, myTransformation->mat);
+      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);
+      }
+
       glMatrixMode (GL_MODELVIEW);
       glPushMatrix ();
       glScalef (1.F, 1.F, 1.F);
-      glMultMatrixf (mat16);
+      glMultMatrixf (*aModelWorld);
     }
     else
     {
       glMatrixMode (GL_MODELVIEW);
       glPushMatrix();
 
-      local_trsf = AWorkspace->SetStructureMatrix(myTransformation);
+      local_trsf = AWorkspace->SetStructureMatrix (myTransformation);
     }
   }
 
@@ -426,7 +661,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   const TEL_TRANSFORM_PERSISTENCE *trans_pers = NULL;
   if ( myTransPers && myTransPers->mode != 0 )
   {
-    trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence( myTransPers );
+    trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence (aCtx, myTransPers);
   }
 
   // Apply aspects
@@ -444,8 +679,10 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
     AWorkspace->SetAspectText(myAspectText);
 
   // Apply highlight box
-  if (myHighlightBox)
-    myHighlightBox->Render( AWorkspace );
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Render (AWorkspace);
+  }
 
   // Apply highlight color
   const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
@@ -464,12 +701,12 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   const Handle(OpenGl_Context)& aContext = AWorkspace->GetGlContext();
 
   // List of planes to be applied to context state
-  Handle(Graphic3d_SetOfHClipPlane) aUserPlanes;
+  Handle(Graphic3d_SequenceOfHClipPlane) aUserPlanes;
 
   // Collect clipping planes of structure scope
   if (!myClipPlanes.IsEmpty())
   {
-    Graphic3d_SetOfHClipPlane::Iterator aClippingIt (myClipPlanes);
+    Graphic3d_SequenceOfHClipPlane::Iterator aClippingIt (myClipPlanes);
     for (; aClippingIt.More(); aClippingIt.Next())
     {
       const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
@@ -480,10 +717,10 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
 
       if (aUserPlanes.IsNull())
       {
-        aUserPlanes = new Graphic3d_SetOfHClipPlane();
+        aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
       }
 
-      aUserPlanes->Add (aClipPlane);
+      aUserPlanes->Append (aClipPlane);
     }
   }
 
@@ -491,26 +728,37 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   {
     // add planes at loaded view matrix state
     aContext->ChangeClipping().AddWorld (*aUserPlanes, AWorkspace);
+
+    // Set OCCT state uniform variables
+    if (!aContext->ShaderManager()->IsEmpty())
+    {
+      aContext->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 (AWorkspace);
   }
 
   // Render capping for structure groups
   if (!aContext->Clipping().Planes().IsEmpty())
   {
-    OpenGl_CappingAlgo::RenderCapping (AWorkspace, myGroups);
+    OpenGl_CappingAlgo::RenderCapping (AWorkspace, aGroups);
   }
 
   // Revert structure clippings
   if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
   {
     aContext->ChangeClipping().Remove (*aUserPlanes);
+
+    // Set OCCT state uniform variables
+    if (!aContext->ShaderManager()->IsEmpty())
+    {
+      aContext->ShaderManager()->RevertClippingState();
+    }
   }
 
   // Restore highlight color
@@ -525,7 +773,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
   // Restore transform persistence
   if ( myTransPers && myTransPers->mode != 0 )
   {
-    AWorkspace->ActiveView()->BeginTransformPersistence( trans_pers );
+    AWorkspace->ActiveView()->BeginTransformPersistence (aContext, trans_pers);
   }
 
   // Restore local transformation
@@ -535,10 +783,17 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
     {
       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);
+      AWorkspace->SetStructureMatrix (local_trsf, true);
 
       glMatrixMode (GL_MODELVIEW);
       glPopMatrix();
@@ -561,7 +816,10 @@ void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
   OpenGl_Element::Destroy (theGlCtx, myAspectFace);
   OpenGl_Element::Destroy (theGlCtx, myAspectMarker);
   OpenGl_Element::Destroy (theGlCtx, myAspectText);
-  ClearHighlightColor (theGlCtx);
+  clearHighlightColor (theGlCtx);
+
+  // Remove from connected list of ancestor
+  UnregisterFromAncestorStructure();
 }
 
 // =======================================================================
@@ -570,13 +828,9 @@ 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)
   {
@@ -594,7 +848,7 @@ void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCt
   {
     myAspectText->Release (theGlCtx);
   }
-  if (myHighlightBox != NULL)
+  if (!myHighlightBox.IsNull())
   {
     myHighlightBox->Release (theGlCtx);
   }
@@ -617,3 +871,62 @@ Standard_Integer OpenGl_Structure::GetZLayer () const
 {
   return myZLayer;
 }
+
+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_Structure) // Type definition
+
+};
+
+DEFINE_STANDARD_HANDLE(OpenGl_StructureShadow, OpenGl_Structure)
+
+IMPLEMENT_STANDARD_HANDLE (OpenGl_StructureShadow, OpenGl_Structure)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_StructureShadow, OpenGl_Structure)
+
+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  :
+//=======================================================================
+Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
+{
+  return new OpenGl_StructureShadow (theManager, this);
+}