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