0028466: Visualization, OpenGl_Context - read GPU memory using WGL_AMD_gpu_associatio...
[occt.git] / src / OpenGl / OpenGl_Structure.cxx
1 // Created on: 2011-08-01
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_CappingAlgo.hxx>
17 #include <OpenGl_Context.hxx>
18 #include <OpenGl_GlCore11.hxx>
19 #include <OpenGl_GraphicDriver.hxx>
20 #include <OpenGl_ShaderManager.hxx>
21 #include <OpenGl_ShaderProgram.hxx>
22 #include <OpenGl_StructureShadow.hxx>
23 #include <OpenGl_Vec.hxx>
24 #include <OpenGl_View.hxx>
25 #include <OpenGl_Workspace.hxx>
26
27 #include <Graphic3d_SequenceOfHClipPlane.hxx>
28
29
30 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
31
32 //! Auxiliary class for bounding box presentation
33 class OpenGl_BndBoxPrs : public OpenGl_Element
34 {
35
36 public:
37
38   //! Main constructor
39   OpenGl_BndBoxPrs (const Graphic3d_BndBox3d& theBndBox)
40   {
41     const float Xm = (float )theBndBox.CornerMin().x();
42     const float Ym = (float)theBndBox.CornerMin().y();
43     const float Zm = (float)theBndBox.CornerMin().z();
44     const float XM = (float)theBndBox.CornerMax().x();
45     const float YM = (float)theBndBox.CornerMax().y();
46     const float ZM = (float)theBndBox.CornerMax().z();
47
48     myVerts[0]  = OpenGl_Vec3 (Xm, Ym, Zm);
49     myVerts[1]  = OpenGl_Vec3 (Xm, Ym, ZM);
50     myVerts[2]  = OpenGl_Vec3 (Xm, YM, ZM);
51     myVerts[3]  = OpenGl_Vec3 (Xm, YM, Zm);
52     myVerts[4]  = OpenGl_Vec3 (Xm, Ym, Zm);
53     myVerts[5]  = OpenGl_Vec3 (XM, Ym, Zm);
54     myVerts[6]  = OpenGl_Vec3 (XM, Ym, ZM);
55     myVerts[7]  = OpenGl_Vec3 (XM, YM, ZM);
56     myVerts[8]  = OpenGl_Vec3 (XM, YM, Zm);
57     myVerts[9]  = OpenGl_Vec3 (XM, Ym, Zm);
58     myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
59     myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
60     myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
61     myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
62     myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
63     myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
64   }
65
66   //! Render presentation
67   virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const
68   {
69   #if !defined(GL_ES_VERSION_2_0)
70     // Apply line aspect
71     const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
72
73     theWorkspace->GetGlContext()->BindProgram (Handle(OpenGl_ShaderProgram)());
74     theWorkspace->GetGlContext()->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
75
76     glDisable (GL_LIGHTING);
77
78     // Use highlight colors
79     theWorkspace->GetGlContext()->core11->glColor3fv (theWorkspace->LineColor().GetData());
80
81     glEnableClientState (GL_VERTEX_ARRAY);
82     glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
83     glDrawArrays (GL_LINE_STRIP, 0, 16);
84     glDisableClientState (GL_VERTEX_ARRAY);
85
86     // restore aspects
87     if (!aPrevTexture.IsNull())
88     {
89       theWorkspace->EnableTexture (aPrevTexture);
90     }
91   #else
92     (void )theWorkspace;
93   #endif
94   }
95
96   //! Release graphical resources
97   virtual void Release (OpenGl_Context*)
98   {
99     //
100   }
101
102 protected:
103
104   //! Protected destructor
105   virtual ~OpenGl_BndBoxPrs() {}
106
107 private:
108
109   OpenGl_Vec3 myVerts[16]; //!< vertices array
110
111 public:
112
113   DEFINE_STANDARD_ALLOC
114
115 };
116
117 /*----------------------------------------------------------------------*/
118
119 // =======================================================================
120 // function : OpenGl_Structure
121 // purpose  :
122 // =======================================================================
123 OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
124 : Graphic3d_CStructure (theManager),
125   myInstancedStructure (NULL),
126   myIsRaytracable      (Standard_False),
127   myModificationState  (0),
128   myIsCulled           (Standard_True),
129   myIsMirrored         (Standard_False)
130 {
131   updateLayerTransformation();
132 }
133
134 // =======================================================================
135 // function : ~OpenGl_Structure
136 // purpose  :
137 // =======================================================================
138 OpenGl_Structure::~OpenGl_Structure()
139 {
140   Release (Handle(OpenGl_Context)());
141 }
142
143 // =======================================================================
144 // function : SetZLayer
145 // purpose  :
146 // =======================================================================
147 void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex)
148 {
149   Graphic3d_CStructure::SetZLayer (theLayerIndex);
150   updateLayerTransformation();
151 }
152
153 // =======================================================================
154 // function : SetTransformation
155 // purpose  :
156 // =======================================================================
157 void OpenGl_Structure::SetTransformation (const Handle(Geom_Transformation)& theTrsf)
158 {
159   myTrsf = theTrsf;
160   myIsMirrored = Standard_False;
161   if (!myTrsf.IsNull())
162   {
163     // Determinant of transform matrix less then 0 means that mirror transform applied.
164     const Standard_Real aDet = myTrsf->Value(1, 1) * (myTrsf->Value (2, 2) * myTrsf->Value (3, 3) - myTrsf->Value (3, 2) * myTrsf->Value (2, 3))
165                              - myTrsf->Value(1, 2) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 3) - myTrsf->Value (3, 1) * myTrsf->Value (2, 3))
166                              + myTrsf->Value(1, 3) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 2) - myTrsf->Value (3, 1) * myTrsf->Value (2, 2));
167     myIsMirrored = aDet < 0.0;
168   }
169
170   updateLayerTransformation();
171   if (IsRaytracable())
172   {
173     ++myModificationState;
174   }
175 }
176
177 // =======================================================================
178 // function : SetTransformPersistence
179 // purpose  :
180 // =======================================================================
181 void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
182 {
183   myTrsfPers = theTrsfPers;
184   updateLayerTransformation();
185 }
186
187 // =======================================================================
188 // function : updateLayerTransformation
189 // purpose  :
190 // =======================================================================
191 void OpenGl_Structure::updateLayerTransformation()
192 {
193   gp_Trsf aRenderTrsf;
194   if (!myTrsf.IsNull())
195   {
196     aRenderTrsf = myTrsf->Trsf();
197   }
198
199   const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
200   if (!aLayer.OriginTransformation().IsNull()
201     && myTrsfPers.IsNull())
202   {
203     aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin());
204   }
205   aRenderTrsf.GetMat4 (myRenderTrsf);
206 }
207
208 // =======================================================================
209 // function : clearHighlightBox
210 // purpose  :
211 // =======================================================================
212 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
213 {
214   if (!myHighlightBox.IsNull())
215   {
216     myHighlightBox->Release (theGlCtx);
217     myHighlightBox.Nullify();
218   }
219 }
220
221 // =======================================================================
222 // function : HighlightWithBndBox
223 // purpose  :
224 // =======================================================================
225 void OpenGl_Structure::highlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct)
226 {
227   const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
228
229   if (!myHighlightBox.IsNull())
230   {
231     myHighlightBox->Release (aContext);
232   }
233   else
234   {
235     myHighlightBox = new OpenGl_Group (theStruct);
236   }
237
238   myHighlightBox->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (myHighlightStyle->Color(), Aspect_TOL_SOLID, 1.0));
239
240   OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
241   myHighlightBox->AddElement (aBndBoxPrs);
242 }
243
244 // =======================================================================
245 // function : GraphicHighlight
246 // purpose  :
247 // =======================================================================
248 void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle,
249                                          const Handle(Graphic3d_Structure)& theStruct)
250 {
251   if (!myHighlightStyle.IsNull()
252     && myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX
253     && theStyle->Method() != Aspect_TOHM_BOUNDBOX)
254   {
255     const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
256     clearHighlightBox (aContext);
257   }
258
259   myHighlightStyle = theStyle;
260
261   highlight = 1;
262   if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
263   {
264     highlightWithBndBox (theStruct);
265   }
266 }
267
268 // =======================================================================
269 // function : GraphicUnhighlight
270 // purpose  :
271 // =======================================================================
272 void OpenGl_Structure::GraphicUnhighlight()
273 {
274   highlight = 0;
275
276   if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
277   {
278     const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
279     clearHighlightBox (aContext);
280   }
281
282   myHighlightStyle.Nullify();
283 }
284
285 // =======================================================================
286 // function : OnVisibilityChanged
287 // purpose  :
288 // =======================================================================
289 void OpenGl_Structure::OnVisibilityChanged()
290 {
291   if (IsRaytracable())
292   {
293     ++myModificationState;
294   }
295 }
296
297 // =======================================================================
298 // function : IsRaytracable
299 // purpose  :
300 // =======================================================================
301 Standard_Boolean OpenGl_Structure::IsRaytracable() const
302 {
303   if (!myGroups.IsEmpty()
304     && myIsRaytracable)
305   {
306     return Standard_True;
307   }
308
309   return myInstancedStructure != NULL
310      &&  myInstancedStructure->IsRaytracable();
311 }
312
313 // =======================================================================
314 // function : UpdateRaytracableState
315 // purpose  :
316 // =======================================================================
317 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
318 {
319   myIsRaytracable = !toCheck;
320   if (!myIsRaytracable)
321   {
322     for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
323     {
324       if (anIter.Value()->IsRaytracable())
325       {
326         myIsRaytracable = Standard_True;
327         break;
328       }
329     }
330   }
331
332   if (IsRaytracable())
333   {
334     ++myModificationState;
335   }
336 }
337
338 // =======================================================================
339 // function : Connect
340 // purpose  :
341 // =======================================================================
342 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
343 {
344   OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
345
346   Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
347     "Error! Instanced structure is already defined");
348
349   myInstancedStructure = aStruct;
350
351   if (aStruct->IsRaytracable())
352   {
353     UpdateStateIfRaytracable (Standard_False);
354   }
355 }
356
357 // =======================================================================
358 // function : Disconnect
359 // purpose  :
360 // =======================================================================
361 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
362 {
363   OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
364
365   if (myInstancedStructure == aStruct)
366   {
367     myInstancedStructure = NULL;
368
369     if (aStruct->IsRaytracable())
370     {
371       UpdateStateIfRaytracable();
372     }
373   }
374 }
375
376 // =======================================================================
377 // function : NewGroup
378 // purpose  :
379 // =======================================================================
380 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
381 {
382   Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
383   myGroups.Append (aGroup);
384   return aGroup;
385 }
386
387 // =======================================================================
388 // function : RemoveGroup
389 // purpose  :
390 // =======================================================================
391 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
392 {
393   if (theGroup.IsNull())
394   {
395     return;
396   }
397
398   for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
399   {
400     // Check for the given group
401     if (aGroupIter.Value() == theGroup)
402     {
403       const Standard_Boolean wasRaytracable =
404         static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
405
406       theGroup->Clear (Standard_False);
407
408       if (wasRaytracable)
409       {
410         UpdateStateIfRaytracable();
411       }
412
413       myGroups.Remove (aGroupIter);
414       return;
415     }
416   }
417 }
418
419 // =======================================================================
420 // function : Clear
421 // purpose  :
422 // =======================================================================
423 void OpenGl_Structure::Clear()
424 {
425   Clear (GlDriver()->GetSharedContext());
426 }
427
428 // =======================================================================
429 // function : Clear
430 // purpose  :
431 // =======================================================================
432 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
433 {
434   Standard_Boolean aRaytracableGroupDeleted (Standard_False);
435
436   // Release groups
437   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
438   {
439     aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
440
441     // Delete objects
442     aGroupIter.ChangeValue()->Release (theGlCtx);
443   }
444   myGroups.Clear();
445
446   if (aRaytracableGroupDeleted)
447   {
448     myIsRaytracable = Standard_False;
449   }
450
451   Is2dText       = Standard_False;
452   IsForHighlight = Standard_False;
453 }
454
455 // =======================================================================
456 // function : renderGeometry
457 // purpose  :
458 // =======================================================================
459 void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
460                                        bool&                           theHasClosed) const
461 {
462   if (myInstancedStructure != NULL)
463   {
464     myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
465   }
466
467   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
468   {
469     theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
470     aGroupIter.Value()->Render (theWorkspace);
471   }
472 }
473
474 // =======================================================================
475 // function : Render
476 // purpose  :
477 // =======================================================================
478 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
479 {
480   // Process the structure only if visible
481   if (!visible)
482   {
483     return;
484   }
485
486   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
487
488   // Render named status
489   if (highlight && myHighlightBox.IsNull())
490   {
491     theWorkspace->SetHighlightStyle (myHighlightStyle);
492   }
493
494   // Apply local transformation
495   aCtx->ModelWorldState.Push();
496   OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent();
497   aModelWorld = myRenderTrsf;
498
499   const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
500 #if !defined(GL_ES_VERSION_2_0)
501   // detect scale transform
502   if (aCtx->core11 != NULL
503   && !myTrsf.IsNull())
504   {
505     const Standard_Real aScale = myTrsf->ScaleFactor();
506     if (Abs (aScale - 1.0) > Precision::Confusion())
507     {
508       aCtx->SetGlNormalizeEnabled (Standard_True);
509     }
510   }
511 #endif
512
513   if (!myTrsfPers.IsNull())
514   {
515     aCtx->WorldViewState.Push();
516     OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent();
517     myTrsfPers->Apply (theWorkspace->View()->Camera(),
518                        aCtx->ProjectionState.Current(), aWorldView,
519                        aCtx->Viewport()[2], aCtx->Viewport()[3]);
520
521   #if !defined(GL_ES_VERSION_2_0)
522     if (!aCtx->IsGlNormalizeEnabled()
523       && aCtx->core11 != NULL)
524     {
525       const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
526       if (Abs (aScale - 1.0) > Precision::Confusion())
527       {
528         aCtx->SetGlNormalizeEnabled (Standard_True);
529       }
530     }
531   #endif
532   }
533
534   // Take into account transform persistence
535   aCtx->ApplyModelViewMatrix();
536
537   // remember aspects
538   const OpenGl_AspectLine*   aPrevAspectLine   = theWorkspace->AspectLine();
539   const OpenGl_AspectFace*   aPrevAspectFace   = theWorkspace->AspectFace();
540   const OpenGl_AspectMarker* aPrevAspectMarker = theWorkspace->AspectMarker();
541   const OpenGl_AspectText*   aPrevAspectText   = theWorkspace->AspectText();
542
543   // Apply correction for mirror transform
544   if (myIsMirrored)
545   {
546     aCtx->core11fwd->glFrontFace (GL_CW);
547   }
548
549   // Collect clipping planes of structure scope
550   aCtx->ChangeClipping().SetLocalPlanes (aCtx, myClipPlanes);
551
552   // True if structure is fully clipped
553   bool isClipped = false;
554   bool hasDisabled = false;
555   if (aCtx->Clipping().IsClippingOrCappingOn())
556   {
557     const Graphic3d_BndBox3d& aBBox = BoundingBox();
558     if (!myClipPlanes.IsNull()
559       && myClipPlanes->ToOverrideGlobal())
560     {
561       aCtx->ChangeClipping().DisableGlobal (aCtx);
562       hasDisabled = aCtx->Clipping().HasDisabled();
563     }
564     else if (!myTrsfPers.IsNull())
565     {
566       if (myTrsfPers->IsZoomOrRotate())
567       {
568         // Zoom/rotate persistence object lives in two worlds at the same time.
569         // Global clipping planes can not be trivially applied without being converted
570         // into local space of transformation persistence object.
571         // As more simple alternative - just clip entire object by its anchor point defined in the world space.
572         const gp_Pnt anAnchor = myTrsfPers->AnchorPoint();
573         for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More() && aPlaneIt.IsGlobal(); aPlaneIt.Next())
574         {
575           const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
576           if (!aPlane->IsOn())
577           {
578             continue;
579           }
580
581           // check for clipping
582           const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
583           const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
584           if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
585           {
586             isClipped = true;
587             break;
588           }
589         }
590       }
591
592       aCtx->ChangeClipping().DisableGlobal (aCtx);
593       hasDisabled = aCtx->Clipping().HasDisabled();
594     }
595
596     // Set of clipping planes that do not intersect the structure,
597     // and thus can be disabled to improve rendering performance
598     if (aBBox.IsValid()
599      && myTrsfPers.IsNull())
600     {
601       for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next())
602       {
603         const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
604         if (!aPlane->IsOn())
605         {
606           continue;
607         }
608
609         // check for clipping
610         const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
611         const Graphic3d_Vec4d aMaxPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMax().x() : aBBox.CornerMin().x(),
612                                        aPlaneEquation.y() > 0.0 ? aBBox.CornerMax().y() : aBBox.CornerMin().y(),
613                                        aPlaneEquation.z() > 0.0 ? aBBox.CornerMax().z() : aBBox.CornerMin().z(),
614                                        1.0);
615         if (aPlaneEquation.Dot (aMaxPnt) < 0.0) // max vertex is outside the half-space
616         {
617           isClipped = true;
618           break;
619         }
620
621         // check for no intersection (e.g. object is "entirely not clipped")
622         const Graphic3d_Vec4d aMinPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMin().x() : aBBox.CornerMax().x(),
623                                        aPlaneEquation.y() > 0.0 ? aBBox.CornerMin().y() : aBBox.CornerMax().y(),
624                                        aPlaneEquation.z() > 0.0 ? aBBox.CornerMin().z() : aBBox.CornerMax().z(),
625                                        1.0);
626         if (aPlaneEquation.Dot (aMinPnt) > 0.0) // min vertex is inside the half-space
627         {
628           aCtx->ChangeClipping().SetEnabled (aCtx, aPlaneIt, Standard_False);
629           hasDisabled = true;
630         }
631       }
632     }
633
634     if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
635      || hasDisabled)
636     {
637       // Set OCCT state uniform variables
638       aCtx->ShaderManager()->UpdateClippingState();
639     }
640   }
641
642   // Render groups
643   bool hasClosedPrims = false;
644   if (!isClipped)
645   {
646     renderGeometry (theWorkspace, hasClosedPrims);
647   }
648
649   // Reset correction for mirror transform
650   if (myIsMirrored)
651   {
652     aCtx->core11fwd->glFrontFace (GL_CCW);
653   }
654
655   // Render capping for structure groups
656   if (hasClosedPrims
657    && aCtx->Clipping().IsCappingOn())
658   {
659     OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
660   }
661
662   // Revert structure clippings
663   if (hasDisabled)
664   {
665     // enable planes that were previously disabled
666     aCtx->ChangeClipping().RestoreDisabled (aCtx);
667   }
668   aCtx->ChangeClipping().SetLocalPlanes (aCtx, Handle(Graphic3d_SequenceOfHClipPlane)());
669   if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
670     || hasDisabled)
671   {
672     // Set OCCT state uniform variables
673     aCtx->ShaderManager()->RevertClippingState();
674   }
675
676   // Restore local transformation
677   aCtx->ModelWorldState.Pop();
678   aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
679   if (!myTrsfPers.IsNull())
680   {
681     aCtx->WorldViewState.Pop();
682   }
683
684   // Restore aspects
685   theWorkspace->SetAspectLine   (aPrevAspectLine);
686   theWorkspace->SetAspectFace   (aPrevAspectFace);
687   theWorkspace->SetAspectMarker (aPrevAspectMarker);
688   theWorkspace->SetAspectText   (aPrevAspectText);
689
690   // Apply highlight box
691   if (!myHighlightBox.IsNull())
692   {
693     theWorkspace->SetHighlightStyle (myHighlightStyle);
694     myHighlightBox->Render (theWorkspace);
695   }
696
697   // Restore named status
698   theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)());
699 }
700
701 // =======================================================================
702 // function : Release
703 // purpose  :
704 // =======================================================================
705 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
706 {
707   // Release groups
708   Clear (theGlCtx);
709   clearHighlightBox (theGlCtx);
710   myHighlightStyle.Nullify();
711 }
712
713 // =======================================================================
714 // function : ReleaseGlResources
715 // purpose  :
716 // =======================================================================
717 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
718 {
719   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
720   {
721     aGroupIter.ChangeValue()->Release (theGlCtx);
722   }
723   if (!myHighlightBox.IsNull())
724   {
725     myHighlightBox->Release (theGlCtx.operator->());
726   }
727 }
728
729 //=======================================================================
730 //function : ShadowLink
731 //purpose  :
732 //=======================================================================
733 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
734 {
735   return new OpenGl_StructureShadow (theManager, this);
736 }