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