0025180: Visualization - Homogeneous transformation API in TKV3d
[occt.git] / src / OpenGl / OpenGl_Structure.cxx
index 4ce7d22..75a0ac2 100644 (file)
-// File:      OpenGl_Structure.cxx
-// Created:   1 August 2011
-// Author:    Sergey ZERCHANINOV
-// Copyright: OPEN CASCADE 2011
-
+// Created on: 2011-08-01
+// Created by: Sergey ZERCHANINOV
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// 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.
+//
+// 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_Structure.hxx>
-
-#include <OpenGl_Polyline.hxx>
-#include <OpenGl_Workspace.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_ShaderProgram.hxx>
+#include <OpenGl_StructureShadow.hxx>
+#include <OpenGl_Vec.hxx>
 #include <OpenGl_View.hxx>
+#include <OpenGl_Workspace.hxx>
 
-#include <OpenGl_telem_util.hxx>
+#include <Graphic3d_SequenceOfHClipPlane.hxx>
 
 
-/*----------------------------------------------------------------------*/
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
 
-static void call_util_transpose_mat (float tmat[16], float mat[4][4])
+//! Auxiliary class for bounding box presentation
+class OpenGl_BndBoxPrs : public OpenGl_Element
 {
-  int i, j;
 
-  for (i=0; i<4; i++)
-    for (j=0; j<4; j++)
-      tmat[j*4+i] = mat[i][j];
-}
+public:
 
-/*----------------------------------------------------------------------*/
-
-OpenGl_Structure::OpenGl_Structure ()
-: myTransformation(NULL),
-  myTransPers(NULL),
-  myDegenerateModel(NULL),
-  myAspectLine(NULL),
-  myAspectFace(NULL),
-  myAspectMarker(NULL),
-  myAspectText(NULL),
-  myHighlightBox(NULL),
-  myHighlightColor(NULL),
-  myNamedStatus(0),
-  myZLayer(0)
-{
-}
-
-/*----------------------------------------------------------------------*/
-
-OpenGl_Structure::~OpenGl_Structure ()
-{
-  if (myTransformation)
-  {
-    delete myTransformation;
-    myTransformation = NULL;
-  }
-  if (myTransPers)
-  {
-    delete myTransPers;
-    myTransPers = NULL;
-  }
-  if (myDegenerateModel)
+  //! Main constructor
+  OpenGl_BndBoxPrs (const Graphic3d_BndBox4f& theBndBox)
   {
-    delete myDegenerateModel;
-    myDegenerateModel = NULL;
+    const float Xm = theBndBox.CornerMin().x();
+    const float Ym = theBndBox.CornerMin().y();
+    const float Zm = theBndBox.CornerMin().z();
+    const float XM = theBndBox.CornerMax().x();
+    const float YM = theBndBox.CornerMax().y();
+    const float ZM = theBndBox.CornerMax().z();
+
+    myVerts[0]  = OpenGl_Vec3 (Xm, Ym, Zm);
+    myVerts[1]  = OpenGl_Vec3 (Xm, Ym, ZM);
+    myVerts[2]  = OpenGl_Vec3 (Xm, YM, ZM);
+    myVerts[3]  = OpenGl_Vec3 (Xm, YM, Zm);
+    myVerts[4]  = OpenGl_Vec3 (Xm, Ym, Zm);
+    myVerts[5]  = OpenGl_Vec3 (XM, Ym, Zm);
+    myVerts[6]  = OpenGl_Vec3 (XM, Ym, ZM);
+    myVerts[7]  = OpenGl_Vec3 (XM, YM, ZM);
+    myVerts[8]  = OpenGl_Vec3 (XM, YM, Zm);
+    myVerts[9]  = OpenGl_Vec3 (XM, Ym, Zm);
+    myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
+    myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
+    myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
+    myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
+    myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
+    myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
   }
-  if (myAspectLine)
-  {
-    delete myAspectLine;
-    myAspectLine = NULL;
-  }
-  if (myAspectFace)
-  {
-    delete myAspectFace;
-    myAspectFace = NULL;
-  }
-  if (myAspectMarker)
+
+  //! Render presentation
+  virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const
   {
-    delete myAspectMarker;
-    myAspectMarker = NULL;
+  #if !defined(GL_ES_VERSION_2_0)
+    // Apply line aspect
+    const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
+
+    glDisable (GL_LIGHTING);
+
+    // Use highlight colors
+    theWorkspace->GetGlContext()->core11->glColor3fv (theWorkspace->LineColor().GetData());
+
+    glEnableClientState (GL_VERTEX_ARRAY);
+    glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
+    glDrawArrays (GL_LINE_STRIP, 0, 16);
+    glDisableClientState (GL_VERTEX_ARRAY);
+
+    // restore aspects
+    if (!aPrevTexture.IsNull())
+    {
+      theWorkspace->EnableTexture (aPrevTexture);
+    }
+  #else
+    (void )theWorkspace;
+  #endif
   }
-  if (myAspectText)
+
+  //! Release graphical resources
+  virtual void Release (OpenGl_Context*)
   {
-    delete myAspectText;
-    myAspectText = NULL;
+    //
   }
-  ClearHighlightColor();
-  // Delete groups
-  Clear();
-}
 
-/*----------------------------------------------------------------------*/
+protected:
 
-void OpenGl_Structure::SetTransformation(const float *AMatrix)
-{
-  if (!myTransformation)
-    myTransformation = new OpenGl_Matrix;
+  //! Protected destructor
+  virtual ~OpenGl_BndBoxPrs() {}
 
-  matcpy( myTransformation->mat, AMatrix );
-}
+private:
 
-/*----------------------------------------------------------------------*/
+  OpenGl_Vec3 myVerts[16]; //!< vertices array
 
-void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers)
-{
-  if (!myTransPers)
-    myTransPers = new TEL_TRANSFORM_PERSISTENCE;
+public:
 
-  myTransPers->mode = ATransPers.Flag;
-  myTransPers->pointX = ATransPers.Point.x;
-  myTransPers->pointY = ATransPers.Point.y;
-  myTransPers->pointZ = ATransPers.Point.z;
-}
+  DEFINE_STANDARD_ALLOC
+
+};
 
 /*----------------------------------------------------------------------*/
 
-void OpenGl_Structure::SetDegenerateModel (const Standard_Integer AMode, const float ASkipRatio)
+// =======================================================================
+// function : OpenGl_Structure
+// purpose  :
+// =======================================================================
+OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
+: Graphic3d_CStructure (theManager),
+  myHighlightColor     (NULL),
+  myInstancedStructure (NULL),
+  myIsRaytracable      (Standard_False),
+  myModificationState  (0),
+  myIsCulled           (Standard_True),
+  myIsMirrored         (Standard_False)
 {
-  if (!myDegenerateModel)
-    myDegenerateModel = new DEGENERATION;
-
-  myDegenerateModel->mode = AMode;
-  myDegenerateModel->skipRatio = ASkipRatio;
+  //
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &AContext)
+// =======================================================================
+// function : ~OpenGl_Structure
+// purpose  :
+// =======================================================================
+OpenGl_Structure::~OpenGl_Structure()
 {
-  if (!myAspectLine)
-    myAspectLine = new OpenGl_AspectLine;
-  myAspectLine->SetContext( AContext );
+  Release (Handle(OpenGl_Context)());
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA &AContext)
+// =======================================================================
+// function : SetTransformation
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::SetTransformation (const Handle(Geom_Transformation)& theTrsf)
 {
-  if (!myAspectFace)
-    myAspectFace = new OpenGl_AspectFace;
-  myAspectFace->SetContext( AContext );
-}
+  myTrsf = theTrsf;
+  myIsMirrored = Standard_False;
+  if (!myTrsf.IsNull())
+  {
+    // Determinant of transform matrix less then 0 means that mirror transform applied.
+    const Standard_Real aDet = myTrsf->Value(1, 1) * (myTrsf->Value (2, 2) * myTrsf->Value (3, 3) - myTrsf->Value (3, 2) * myTrsf->Value (2, 3))
+                             - myTrsf->Value(1, 2) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 3) - myTrsf->Value (3, 1) * myTrsf->Value (2, 3))
+                             + myTrsf->Value(1, 3) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 2) - myTrsf->Value (3, 1) * myTrsf->Value (2, 2));
+    myIsMirrored = aDet < 0.0;
+  }
 
-/*----------------------------------------------------------------------*/
+  if (IsRaytracable())
+  {
+    ++myModificationState;
+  }
+}
 
-void OpenGl_Structure::SetAspectMarker (const CALL_DEF_CONTEXTMARKER &AContext)
+// =======================================================================
+// function : clearHighlightBox
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
 {
-  if (!myAspectMarker)
-    myAspectMarker = new OpenGl_AspectMarker;
-  myAspectMarker->SetContext( AContext );
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Release (theGlCtx);
+    myHighlightBox.Nullify();
+  }
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &AContext)
+// =======================================================================
+// function : HighlightWithColor
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3&  theColor,
+                                           const Standard_Boolean theToCreate)
 {
-  if (!myAspectText)
-    myAspectText = new OpenGl_AspectText;
-  myAspectText->SetContext( AContext );
+  const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
+  if (theToCreate)
+    setHighlightColor   (aContext, theColor);
+  else
+    clearHighlightColor (aContext);
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_Structure::SetHighlightBox (const CALL_DEF_BOUNDBOX &ABoundBox)
+// =======================================================================
+// function : HighlightWithBndBox
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
+                                            const Standard_Boolean             theToCreate)
 {
-  if (!myHighlightBox)
-    myHighlightBox = new OpenGl_Group;
+  const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
+  if (!theToCreate)
+  {
+    clearHighlightBox (aContext);
+    return;
+  }
+
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Release (aContext);
+  }
   else
-    myHighlightBox->Clear();
-
-  CALL_DEF_CONTEXTLINE context_line;
-  context_line.Color = ABoundBox.Color;
-  context_line.LineType = Aspect_TOL_SOLID;
-  context_line.Width = 1.0f;
-  myHighlightBox->SetAspectLine( context_line );
-
-#define CALL_MAX_BOUNDBOXSIZE 16
-
-  Graphic3d_Array1OfVertex points(1,CALL_MAX_BOUNDBOXSIZE);
-  const float Xm = ABoundBox.Pmin.x;
-  const float Ym = ABoundBox.Pmin.y;
-  const float Zm = ABoundBox.Pmin.z;
-  const float XM = ABoundBox.Pmax.x;
-  const float YM = ABoundBox.Pmax.y;
-  const float ZM = ABoundBox.Pmax.z;
-  points( 1).SetCoord(Xm,Ym,Zm);
-  points( 2).SetCoord(Xm,Ym,ZM);
-  points( 3).SetCoord(Xm,YM,ZM);
-  points( 4).SetCoord(Xm,YM,Zm);
-  points( 5).SetCoord(Xm,Ym,Zm);
-  points( 6).SetCoord(XM,Ym,Zm);
-  points( 7).SetCoord(XM,Ym,ZM);
-  points( 8).SetCoord(XM,YM,ZM);
-  points( 9).SetCoord(XM,YM,Zm);
-  points(10).SetCoord(XM,Ym,Zm);
-  points(11).SetCoord(XM,YM,Zm);
-  points(12).SetCoord(Xm,YM,Zm);
-  points(13).SetCoord(Xm,YM,ZM);
-  points(14).SetCoord(XM,YM,ZM);
-  points(15).SetCoord(XM,Ym,ZM);
-  points(16).SetCoord(Xm,Ym,ZM);
-
-  OpenGl_Polyline *apolyline = new OpenGl_Polyline(points);
-  myHighlightBox->AddElement( TelPolyline, apolyline );
-}
+  {
+    myHighlightBox = new OpenGl_Group (theStruct);
+  }
 
-/*----------------------------------------------------------------------*/
+  myHighlightBox->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (HighlightColor, Aspect_TOL_SOLID, 1.0));
+
+  OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
+  myHighlightBox->AddElement (aBndBoxPrs);
+}
 
-void OpenGl_Structure::ClearHighlightBox ()
+// =======================================================================
+// function : setHighlightColor
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::setHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
+                                          const Graphic3d_Vec3&         theColor)
 {
-  if (myHighlightBox)
+  clearHighlightBox (theGlCtx);
+  if (myHighlightColor == NULL)
+  {
+    myHighlightColor = new OpenGl_Vec4 (theColor, 1.0f);
+  }
+  else
   {
-    delete myHighlightBox;
-    myHighlightBox = NULL;
+    myHighlightColor->xyz() = theColor;
   }
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_Structure::SetHighlightColor (const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B)
+// =======================================================================
+// function : clearHighlightColor
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::clearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
 {
-  ClearHighlightBox();
-  if (!myHighlightColor)
-    myHighlightColor = new TEL_COLOUR;
-
-  myHighlightColor->rgb[0] = R;
-  myHighlightColor->rgb[1] = G;
-  myHighlightColor->rgb[2] = B;
-  myHighlightColor->rgb[3] = 1.F;
+  clearHighlightBox(theGlCtx);
+  delete myHighlightColor;
+  myHighlightColor = NULL;
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_Structure::ClearHighlightColor ()
+// =======================================================================
+// function : OnVisibilityChanged
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::OnVisibilityChanged()
 {
-  ClearHighlightBox();
-  if (myHighlightColor)
+  if (IsRaytracable())
   {
-    delete myHighlightColor;
-    myHighlightColor = NULL;
+    ++myModificationState;
   }
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_Structure::Connect (const OpenGl_Structure *AStructure)
+// =======================================================================
+// function : IsRaytracable
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_Structure::IsRaytracable() const
 {
-  Disconnect (AStructure);
-  myConnected.Append(AStructure);
-}
+  if (!myGroups.IsEmpty()
+    && myIsRaytracable)
+  {
+    return Standard_True;
+  }
 
-/*----------------------------------------------------------------------*/
+  return myInstancedStructure != NULL
+     &&  myInstancedStructure->IsRaytracable();
+}
 
-void OpenGl_Structure::Disconnect (const OpenGl_Structure *AStructure)
+// =======================================================================
+// function : UpdateRaytracableState
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
 {
-  OpenGl_ListOfStructure::Iterator its(myConnected);
-  while (its.More())
+  myIsRaytracable = !toCheck;
+  if (!myIsRaytracable)
   {
-    // Check for the given structure
-    if (its.Value() == AStructure)
+    for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
     {
-      myConnected.Remove(its);
-      return;
+      if (anIter.Value()->IsRaytracable())
+      {
+        myIsRaytracable = Standard_True;
+        break;
+      }
     }
-    its.Next();
+  }
+
+  if (IsRaytracable())
+  {
+    ++myModificationState;
   }
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : Connect
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
+{
+  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);
+  }
+}
 
-OpenGl_Group * OpenGl_Structure::AddGroup ()
+// =======================================================================
+// function : Disconnect
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
 {
-  // Create new group
-  OpenGl_Group *g = new OpenGl_Group;
-  myGroups.Append(g);
-  return g;
+  OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
+
+  if (myInstancedStructure == aStruct)
+  {
+    myInstancedStructure = NULL;
+
+    if (aStruct->IsRaytracable())
+    {
+      UpdateStateIfRaytracable();
+    }
+  }
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : NewGroup
+// purpose  :
+// =======================================================================
+Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
+{
+  Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
+  myGroups.Append (aGroup);
+  return aGroup;
+}
 
-void OpenGl_Structure::RemoveGroup (const OpenGl_Group *AGroup)
+// =======================================================================
+// function : RemoveGroup
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
 {
-  OpenGl_ListOfGroup::Iterator itg(myGroups);
-  while (itg.More())
+  if (theGroup.IsNull())
+  {
+    return;
+  }
+
+  for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
     // Check for the given group
-    if (itg.Value() == AGroup)
+    if (aGroupIter.Value() == theGroup)
     {
-      // Delete object
-      delete AGroup;
-      myGroups.Remove(itg);
+      const Standard_Boolean wasRaytracable =
+        static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
+
+      theGroup->Clear (Standard_False);
+
+      if (wasRaytracable)
+      {
+        UpdateStateIfRaytracable();
+      }
+
+      myGroups.Remove (aGroupIter);
       return;
     }
-    itg.Next();
   }
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : Clear
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::Clear()
+{
+  Clear (GlDriver()->GetSharedContext());
+}
 
-void OpenGl_Structure::Clear ()
+// =======================================================================
+// function : Clear
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
 {
-  OpenGl_ListOfGroup::Iterator itg(myGroups);
-  while (itg.More())
+  Standard_Boolean aRaytracableGroupDeleted (Standard_False);
+
+  // Release groups
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
+    aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
+
     // Delete objects
-    delete itg.Value();
-    itg.Next();
+    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,
+                                       bool&                           theHasClosed) const
+{
+  if (myInstancedStructure != NULL)
+  {
+    myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
+  }
 
-void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
+  {
+    theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
+    aGroupIter.Value()->Render (theWorkspace);
+  }
+}
+
+// =======================================================================
+// function : Render
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
 {
   // Process the structure only if visible
-  if ( myNamedStatus & OPENGL_NS_HIDE )
+  if (!visible)
+  {
     return;
+  }
 
-  // Render named status
-  const Standard_Integer named_status = AWorkspace->NamedStatus;
-  AWorkspace->NamedStatus |= myNamedStatus;
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
 
-  // Is rendering in ADD or IMMEDIATE mode?
-  const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
+  // Render named status
+  if (highlight)
+  {
+    theWorkspace->SetHighlight (true);
+  }
 
   // Apply local transformation
-  GLint matrix_mode = 0;
-  const OpenGl_Matrix *local_trsf = NULL;
-  if (myTransformation)
+  aCtx->ModelWorldState.Push();
+  OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent();
+  if (!myTrsf.IsNull())
   {
-    if (isImmediate)
-    {
-      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);
-    }
+    myTrsf->Trsf().GetMat4 (aModelWorld);
   }
-
-  // Apply transform persistence
-  const TEL_TRANSFORM_PERSISTENCE *trans_pers = NULL;
-  if ( myTransPers && myTransPers->mode != 0 )
+  else
   {
-    trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence( myTransPers );
+    aModelWorld.InitIdentity();
   }
 
-  // Apply degeneration
-  if (myDegenerateModel)
+  const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
+
+#if !defined(GL_ES_VERSION_2_0)
+  // detect scale transform
+  if (aCtx->core11 != NULL
+  && !myTrsf.IsNull())
   {
-    if ( AWorkspace->NamedStatus & OPENGL_NS_DEGENERATION )
+    const Standard_Real aScale = myTrsf->ScaleFactor();
+    if (Abs (aScale - 1.0) > Precision::Confusion())
     {
-      AWorkspace->DegenerateModel = myDegenerateModel->mode;
-      switch ( AWorkspace->DegenerateModel )
-      {
-        case 0: break;
+      aCtx->SetGlNormalizeEnabled (Standard_True);
+    }
+  }
+#endif
+
+  if (!myTrsfPers.IsNull())
+  {
+    OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current();
+    myTrsfPers->Apply (theWorkspace->View()->Camera(), aCtx->ProjectionState.Current(), aWorldView,
+                       aCtx->Viewport()[2], aCtx->Viewport()[3]);
 
-        default:
-          glLineWidth ( 1.0 );
-          glDisable   ( GL_LINE_STIPPLE );
+    aCtx->WorldViewState.Push();
+    aCtx->WorldViewState.SetCurrent (aWorldView);
 
-        case 1:
-          AWorkspace->SkipRatio = myDegenerateModel->skipRatio;
+  #if !defined(GL_ES_VERSION_2_0)
+    if (!aCtx->IsGlNormalizeEnabled()
+      && aCtx->core11 != NULL)
+    {
+      const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
+      if (Abs (aScale - 1.0f) > Precision::Confusion())
+      {
+        aCtx->SetGlNormalizeEnabled (Standard_True);
       }
     }
+  #endif
   }
 
-  // Apply aspects
-  const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine(Standard_False);
-  const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace(Standard_False);
-  const OpenGl_AspectMarker *aspect_marker = AWorkspace->AspectMarker(Standard_False);
-  const OpenGl_AspectText *aspect_text = AWorkspace->AspectText(Standard_False);
-  if (myAspectLine)
-    AWorkspace->SetAspectLine(myAspectLine);
-  if (myAspectFace)
-    AWorkspace->SetAspectFace(myAspectFace);
-  if (myAspectMarker)
-    AWorkspace->SetAspectMarker(myAspectMarker);
-  if (myAspectText)
-    AWorkspace->SetAspectText(myAspectText);
+  // Take into account transform persistence
+  aCtx->ApplyModelViewMatrix();
 
-  // Apply highlight box
-  if (myHighlightBox)
-    myHighlightBox->Render( AWorkspace );
+  // remember aspects
+  const OpenGl_AspectLine*   aPrevAspectLine   = theWorkspace->AspectLine();
+  const OpenGl_AspectFace*   aPrevAspectFace   = theWorkspace->AspectFace();
+  const OpenGl_AspectMarker* aPrevAspectMarker = theWorkspace->AspectMarker();
+  const OpenGl_AspectText*   aPrevAspectText   = theWorkspace->AspectText();
+
+  // Apply correction for mirror transform
+  if (myIsMirrored)
+  {
+    aCtx->core11fwd->glFrontFace (GL_CW);
+  }
 
   // Apply highlight color
-  const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
+  const OpenGl_Vec4* aHighlightColor = theWorkspace->HighlightColor;
   if (myHighlightColor)
-    AWorkspace->HighlightColor = myHighlightColor;
+    theWorkspace->HighlightColor = myHighlightColor;
 
-  // Render connected structures
-  OpenGl_ListOfStructure::Iterator its(myConnected);
-  while (its.More())
+  // Collect clipping planes of structure scope
+  aCtx->ChangeClipping().SetLocalPlanes (aCtx, myClipPlanes);
+
+  // True if structure is fully clipped
+  bool isClipped = false;
+  bool hasDisabled = false;
+  if (aCtx->Clipping().IsClippingOrCappingOn())
   {
-    its.Value()->Render(AWorkspace);
-    its.Next();
+    const Graphic3d_BndBox4f& aBBox = BoundingBox();
+    if ((!myTrsfPers.IsNull() && myTrsfPers->IsTrihedronOr2d())
+     || (!myClipPlanes.IsNull() && myClipPlanes->ToOverrideGlobal()))
+    {
+      aCtx->ChangeClipping().DisableGlobal (aCtx);
+      hasDisabled = aCtx->Clipping().HasDisabled();
+    }
+
+    // Set of clipping planes that do not intersect the structure,
+    // and thus can be disabled to improve rendering performance
+    if (aBBox.IsValid()
+     && myTrsfPers.IsNull())
+    {
+      for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next())
+      {
+        const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
+        if (!aPlane->IsOn())
+        {
+          continue;
+        }
+
+        // check for clipping
+        const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
+        const Graphic3d_Vec4d aMaxPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMax().x() : aBBox.CornerMin().x(),
+                                       aPlaneEquation.y() > 0.0 ? aBBox.CornerMax().y() : aBBox.CornerMin().y(),
+                                       aPlaneEquation.z() > 0.0 ? aBBox.CornerMax().z() : aBBox.CornerMin().z(),
+                                       1.0);
+        if (aPlaneEquation.Dot (aMaxPnt) < 0.0) // max vertex is outside the half-space
+        {
+          isClipped = true;
+          break;
+        }
+
+        // check for no intersection (e.g. object is "entirely not clipped")
+        const Graphic3d_Vec4d aMinPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMin().x() : aBBox.CornerMax().x(),
+                                       aPlaneEquation.y() > 0.0 ? aBBox.CornerMin().y() : aBBox.CornerMax().y(),
+                                       aPlaneEquation.z() > 0.0 ? aBBox.CornerMin().z() : aBBox.CornerMax().z(),
+                                       1.0);
+        if (aPlaneEquation.Dot (aMinPnt) > 0.0) // min vertex is inside the half-space
+        {
+          aCtx->ChangeClipping().SetEnabled (aCtx, aPlaneIt, Standard_False);
+          hasDisabled = true;
+        }
+      }
+    }
+
+    if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
+     || hasDisabled)
+    {
+      // Set OCCT state uniform variables
+      aCtx->ShaderManager()->UpdateClippingState();
+    }
   }
 
   // Render groups
-  OpenGl_ListOfGroup::Iterator itg(myGroups);
-  while (itg.More())
+  bool hasClosedPrims = false;
+  if (!isClipped)
   {
-    itg.Value()->Render(AWorkspace);
-    itg.Next();
+    renderGeometry (theWorkspace, hasClosedPrims);
   }
 
-  // Restore highlight color
-  AWorkspace->HighlightColor = highlight_color;
+  // Reset correction for mirror transform
+  if (myIsMirrored)
+  {
+    aCtx->core11fwd->glFrontFace (GL_CCW);
+  }
 
-  // Restore aspects
-  AWorkspace->SetAspectLine(aspect_line);
-  AWorkspace->SetAspectFace(aspect_face);
-  AWorkspace->SetAspectMarker(aspect_marker);
-  AWorkspace->SetAspectText(aspect_text);
+  // Render capping for structure groups
+  if (hasClosedPrims
+   && aCtx->Clipping().IsCappingOn())
+  {
+    OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
+  }
 
-  // Restore transform persistence
-  if ( myTransPers && myTransPers->mode != 0 )
+  // Revert structure clippings
+  if (hasDisabled)
+  {
+    // enable planes that were previously disabled
+    aCtx->ChangeClipping().RestoreDisabled (aCtx);
+  }
+  aCtx->ChangeClipping().SetLocalPlanes (aCtx, Handle(Graphic3d_SequenceOfHClipPlane)());
+  if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
+    || hasDisabled)
   {
-    AWorkspace->ActiveView()->BeginTransformPersistence( trans_pers );
+    // Set OCCT state uniform variables
+    aCtx->ShaderManager()->RevertClippingState();
   }
 
   // Restore local transformation
-  if (myTransformation)
+  aCtx->ModelWorldState.Pop();
+  aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
+  if (!myTrsfPers.IsNull())
   {
-    if (isImmediate)
-    {
-      glPopMatrix ();
-      glMatrixMode (matrix_mode);
-    }
-    else
-    {
-      AWorkspace->SetStructureMatrix(local_trsf);
+    aCtx->WorldViewState.Pop();
+  }
 
-      glMatrixMode (GL_MODELVIEW);
-      glPopMatrix();
-    }
+  // Restore highlight color
+  theWorkspace->HighlightColor = aHighlightColor;
+
+  // Restore aspects
+  theWorkspace->SetAspectLine   (aPrevAspectLine);
+  theWorkspace->SetAspectFace   (aPrevAspectFace);
+  theWorkspace->SetAspectMarker (aPrevAspectMarker);
+  theWorkspace->SetAspectText   (aPrevAspectText);
+
+  // Apply highlight box
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Render (theWorkspace);
   }
 
   // Restore named status
-  AWorkspace->NamedStatus = named_status;
+  theWorkspace->SetHighlight (false);
 }
 
-//=======================================================================
-//function : SetZLayer
-//purpose  : 
-//=======================================================================
+// =======================================================================
+// function : Release
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
+{
+  // Release groups
+  Clear (theGlCtx);
+  clearHighlightColor (theGlCtx);
+}
 
-void OpenGl_Structure::SetZLayer (const Standard_Integer theLayerIndex)
+// =======================================================================
+// function : ReleaseGlResources
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
 {
-  myZLayer = theLayerIndex;
+  for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
+  {
+    aGroupIter.ChangeValue()->Release (theGlCtx);
+  }
+  if (!myHighlightBox.IsNull())
+  {
+    myHighlightBox->Release (theGlCtx.operator->());
+  }
 }
 
 //=======================================================================
-//function : GetZLayer
-//purpose  : 
+//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);
 }