0031704: Visualization - add an interactive object AIS_LightSource representing a...
[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_ClippingIterator.hxx>
20 #include <OpenGl_GraphicDriver.hxx>
21 #include <OpenGl_ShaderManager.hxx>
22 #include <OpenGl_ShaderProgram.hxx>
23 #include <OpenGl_StructureShadow.hxx>
24 #include <OpenGl_Vec.hxx>
25 #include <OpenGl_View.hxx>
26 #include <OpenGl_Workspace.hxx>
27
28 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
29
30 // =======================================================================
31 // function : renderBoundingBox
32 // purpose  :
33 // =======================================================================
34 void OpenGl_Structure::renderBoundingBox (const Handle(OpenGl_Workspace)& theWorkspace) const
35 {
36   if (!myBndBox.IsValid())
37   {
38     return;
39   }
40
41   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
42   const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
43   const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
44   const Graphic3d_Vec3d aMoveVec = myTrsfPers.IsNull()
45                                && !aLayer.OriginTransformation().IsNull()
46                                  ? -Graphic3d_Vec3d (aLayer.Origin().X(), aLayer.Origin().Y(), aLayer.Origin().Z())
47                                  :  Graphic3d_Vec3d (0.0, 0.0, 0.0);
48   if (aCtx->core20fwd != NULL
49    && aCtx->ShaderManager()->BindBoundBoxProgram())
50   {
51     const Graphic3d_Vec3d aCenter = myBndBox.Center() + aMoveVec;
52     const Graphic3d_Vec3d aSize   = myBndBox.Size();
53     aCtx->ActiveProgram()->SetUniform (aCtx, "occBBoxCenter", Graphic3d_Vec3 ((float )aCenter.x(), (float )aCenter.y(), (float )aCenter.z()));
54     aCtx->ActiveProgram()->SetUniform (aCtx, "occBBoxSize",   Graphic3d_Vec3 ((float )aSize.x(),   (float )aSize.y(),   (float )aSize.z()));
55     aCtx->SetColor4fv (theWorkspace->InteriorColor());
56
57     const Handle(OpenGl_VertexBuffer)& aBoundBoxVertBuffer = aCtx->ShaderManager()->BoundBoxVertBuffer();
58     aBoundBoxVertBuffer->BindAttribute  (aCtx, Graphic3d_TOA_POS);
59     aCtx->core20fwd->glDrawArrays (GL_LINES, 0, aBoundBoxVertBuffer->GetElemsNb());
60     aBoundBoxVertBuffer->UnbindAttribute(aCtx, Graphic3d_TOA_POS);
61   }
62 #if !defined(GL_ES_VERSION_2_0)
63   else if (aCtx->core11 != NULL)
64   {
65     const Graphic3d_Vec3d aMind = myBndBox.CornerMin() + aMoveVec;
66     const Graphic3d_Vec3d aMaxd = myBndBox.CornerMax() + aMoveVec;
67     const Graphic3d_Vec3 aMin ((float )aMind.x(), (float )aMind.y(), (float )aMind.z());
68     const Graphic3d_Vec3 aMax ((float )aMaxd.x(), (float )aMaxd.y(), (float )aMaxd.z());
69     const OpenGl_Vec3 aVerts[16] =
70     {
71       OpenGl_Vec3 (aMin.x(), aMin.y(), aMin.z()),
72       OpenGl_Vec3 (aMin.x(), aMin.y(), aMax.z()),
73       OpenGl_Vec3 (aMin.x(), aMax.y(), aMax.z()),
74       OpenGl_Vec3 (aMin.x(), aMax.y(), aMin.z()),
75       OpenGl_Vec3 (aMin.x(), aMin.y(), aMin.z()),
76       OpenGl_Vec3 (aMax.x(), aMin.y(), aMin.z()),
77       OpenGl_Vec3 (aMax.x(), aMin.y(), aMax.z()),
78       OpenGl_Vec3 (aMax.x(), aMax.y(), aMax.z()),
79       OpenGl_Vec3 (aMax.x(), aMax.y(), aMin.z()),
80       OpenGl_Vec3 (aMax.x(), aMin.y(), aMin.z()),
81       OpenGl_Vec3 (aMax.x(), aMax.y(), aMin.z()),
82       OpenGl_Vec3 (aMin.x(), aMax.y(), aMin.z()),
83       OpenGl_Vec3 (aMin.x(), aMax.y(), aMax.z()),
84       OpenGl_Vec3 (aMax.x(), aMax.y(), aMax.z()),
85       OpenGl_Vec3 (aMax.x(), aMin.y(), aMax.z()),
86       OpenGl_Vec3 (aMin.x(), aMin.y(), aMax.z())
87     };
88
89     aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID, Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, false, Handle(OpenGl_ShaderProgram)());
90     aCtx->SetColor4fv (theWorkspace->InteriorColor());
91     aCtx->core11fwd->glDisable (GL_LIGHTING);
92     aCtx->core11->glEnableClientState (GL_VERTEX_ARRAY);
93     aCtx->core11->glVertexPointer (3, GL_FLOAT, 0, aVerts[0].GetData());
94     aCtx->core11fwd->glDrawArrays (GL_LINE_STRIP, 0, 16);
95     aCtx->core11->glDisableClientState (GL_VERTEX_ARRAY);
96   }
97 #endif
98   aCtx->BindTextures (aPrevTexture, Handle(OpenGl_ShaderProgram)());
99 }
100
101 // =======================================================================
102 // function : OpenGl_Structure
103 // purpose  :
104 // =======================================================================
105 OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
106 : Graphic3d_CStructure (theManager),
107   myInstancedStructure (NULL),
108   myIsRaytracable      (Standard_False),
109   myModificationState  (0),
110   myIsMirrored         (Standard_False)
111 {
112   updateLayerTransformation();
113 }
114
115 // =======================================================================
116 // function : ~OpenGl_Structure
117 // purpose  :
118 // =======================================================================
119 OpenGl_Structure::~OpenGl_Structure()
120 {
121   Release (Handle(OpenGl_Context)());
122 }
123
124 // =======================================================================
125 // function : SetZLayer
126 // purpose  :
127 // =======================================================================
128 void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex)
129 {
130   Graphic3d_CStructure::SetZLayer (theLayerIndex);
131   updateLayerTransformation();
132 }
133
134 // =======================================================================
135 // function : SetTransformation
136 // purpose  :
137 // =======================================================================
138 void OpenGl_Structure::SetTransformation (const Handle(TopLoc_Datum3D)& theTrsf)
139 {
140   myTrsf = theTrsf;
141   myIsMirrored = Standard_False;
142   if (!myTrsf.IsNull())
143   {
144     // Determinant of transform matrix less then 0 means that mirror transform applied.
145     const gp_Trsf& aTrsf = myTrsf->Transformation();
146     const Standard_Real aDet = aTrsf.Value(1, 1) * (aTrsf.Value (2, 2) * aTrsf.Value (3, 3) - aTrsf.Value (3, 2) * aTrsf.Value (2, 3))
147                              - aTrsf.Value(1, 2) * (aTrsf.Value (2, 1) * aTrsf.Value (3, 3) - aTrsf.Value (3, 1) * aTrsf.Value (2, 3))
148                              + aTrsf.Value(1, 3) * (aTrsf.Value (2, 1) * aTrsf.Value (3, 2) - aTrsf.Value (3, 1) * aTrsf.Value (2, 2));
149     myIsMirrored = aDet < 0.0;
150   }
151
152   updateLayerTransformation();
153   if (IsRaytracable())
154   {
155     ++myModificationState;
156   }
157 }
158
159 // =======================================================================
160 // function : SetTransformPersistence
161 // purpose  :
162 // =======================================================================
163 void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
164 {
165   if ((myTrsfPers.IsNull() || theTrsfPers.IsNull()) && myTrsfPers != theTrsfPers)
166   {
167     ++myModificationState;
168   }
169   myTrsfPers = theTrsfPers;
170   updateLayerTransformation();
171 }
172
173 // =======================================================================
174 // function : updateLayerTransformation
175 // purpose  :
176 // =======================================================================
177 void OpenGl_Structure::updateLayerTransformation()
178 {
179   gp_Trsf aRenderTrsf;
180   if (!myTrsf.IsNull())
181   {
182     aRenderTrsf = myTrsf->Trsf();
183   }
184
185   const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
186   if (!aLayer.OriginTransformation().IsNull()
187     && myTrsfPers.IsNull())
188   {
189     aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin());
190   }
191   aRenderTrsf.GetMat4 (myRenderTrsf);
192 }
193
194 // =======================================================================
195 // function : GraphicHighlight
196 // purpose  :
197 // =======================================================================
198 void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle)
199 {
200   myHighlightStyle = theStyle;
201   highlight = 1;
202 }
203
204 // =======================================================================
205 // function : GraphicUnhighlight
206 // purpose  :
207 // =======================================================================
208 void OpenGl_Structure::GraphicUnhighlight()
209 {
210   highlight = 0;
211   myHighlightStyle.Nullify();
212 }
213
214 // =======================================================================
215 // function : OnVisibilityChanged
216 // purpose  :
217 // =======================================================================
218 void OpenGl_Structure::OnVisibilityChanged()
219 {
220   if (IsRaytracable())
221   {
222     ++myModificationState;
223   }
224 }
225
226 // =======================================================================
227 // function : IsRaytracable
228 // purpose  :
229 // =======================================================================
230 Standard_Boolean OpenGl_Structure::IsRaytracable() const
231 {
232   if (!myGroups.IsEmpty()
233     && myIsRaytracable
234     && myTrsfPers.IsNull())
235   {
236     return Standard_True;
237   }
238
239   return myInstancedStructure != NULL
240      &&  myInstancedStructure->IsRaytracable();
241 }
242
243 // =======================================================================
244 // function : UpdateRaytracableState
245 // purpose  :
246 // =======================================================================
247 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
248 {
249   myIsRaytracable = !toCheck;
250   if (!myIsRaytracable)
251   {
252     for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
253     {
254       if (anIter.Value()->IsRaytracable())
255       {
256         myIsRaytracable = Standard_True;
257         break;
258       }
259     }
260   }
261
262   if (IsRaytracable())
263   {
264     ++myModificationState;
265   }
266 }
267
268 // =======================================================================
269 // function : Connect
270 // purpose  :
271 // =======================================================================
272 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
273 {
274   OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
275
276   Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
277     "Error! Instanced structure is already defined");
278
279   myInstancedStructure = aStruct;
280
281   if (aStruct->IsRaytracable())
282   {
283     UpdateStateIfRaytracable (Standard_False);
284   }
285 }
286
287 // =======================================================================
288 // function : Disconnect
289 // purpose  :
290 // =======================================================================
291 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
292 {
293   OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
294
295   if (myInstancedStructure == aStruct)
296   {
297     myInstancedStructure = NULL;
298
299     if (aStruct->IsRaytracable())
300     {
301       UpdateStateIfRaytracable();
302     }
303   }
304 }
305
306 // =======================================================================
307 // function : NewGroup
308 // purpose  :
309 // =======================================================================
310 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
311 {
312   Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
313   myGroups.Append (aGroup);
314   return aGroup;
315 }
316
317 // =======================================================================
318 // function : RemoveGroup
319 // purpose  :
320 // =======================================================================
321 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
322 {
323   if (theGroup.IsNull())
324   {
325     return;
326   }
327
328   for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
329   {
330     // Check for the given group
331     if (aGroupIter.Value() == theGroup)
332     {
333       const Standard_Boolean wasRaytracable =
334         static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
335
336       theGroup->Clear (Standard_False);
337
338       if (wasRaytracable)
339       {
340         UpdateStateIfRaytracable();
341       }
342
343       myGroups.Remove (aGroupIter);
344       return;
345     }
346   }
347 }
348
349 // =======================================================================
350 // function : Clear
351 // purpose  :
352 // =======================================================================
353 void OpenGl_Structure::Clear()
354 {
355   Clear (GlDriver()->GetSharedContext());
356 }
357
358 // =======================================================================
359 // function : Clear
360 // purpose  :
361 // =======================================================================
362 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
363 {
364   Standard_Boolean aRaytracableGroupDeleted (Standard_False);
365
366   // Release groups
367   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
368   {
369     aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
370
371     // Delete objects
372     aGroupIter.ChangeValue()->Release (theGlCtx);
373   }
374   myGroups.Clear();
375
376   if (aRaytracableGroupDeleted)
377   {
378     myIsRaytracable = Standard_False;
379   }
380
381   Is2dText       = Standard_False;
382   IsForHighlight = Standard_False;
383 }
384
385 // =======================================================================
386 // function : renderGeometry
387 // purpose  :
388 // =======================================================================
389 void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
390                                        bool&                           theHasClosed) const
391 {
392   if (myInstancedStructure != NULL)
393   {
394     myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
395   }
396
397   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
398   {
399     theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
400     aGroupIter.Value()->Render (theWorkspace);
401   }
402 }
403
404 // =======================================================================
405 // function : Render
406 // purpose  :
407 // =======================================================================
408 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
409 {
410   // Process the structure only if visible
411   if (!visible)
412   {
413     return;
414   }
415
416   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
417
418   // Render named status
419   if (highlight && !myHighlightStyle.IsNull() && myHighlightStyle->Method() != Aspect_TOHM_BOUNDBOX)
420   {
421     theWorkspace->SetHighlightStyle (myHighlightStyle);
422   }
423
424   // Apply local transformation
425   aCtx->ModelWorldState.Push();
426   OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent();
427   aModelWorld = myRenderTrsf;
428
429   const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
430 #if !defined(GL_ES_VERSION_2_0)
431   // detect scale transform
432   if (aCtx->core11 != NULL
433   && !myTrsf.IsNull())
434   {
435     const Standard_Real aScale = myTrsf->Trsf().ScaleFactor();
436     if (Abs (aScale - 1.0) > Precision::Confusion())
437     {
438       aCtx->SetGlNormalizeEnabled (Standard_True);
439     }
440   }
441 #endif
442
443   bool anOldCastShadows = false;
444 #ifdef GL_DEPTH_CLAMP
445   bool toRestoreDepthClamp = false;
446 #endif
447   if (!myTrsfPers.IsNull())
448   {
449     // temporarily disable shadows on non-3d objects
450     anOldCastShadows = aCtx->ShaderManager()->SetCastShadows (false);
451
452     aCtx->WorldViewState.Push();
453     OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent();
454     myTrsfPers->Apply (aCtx->Camera(),
455                        aCtx->ProjectionState.Current(), aWorldView,
456                        aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]);
457
458   #if !defined(GL_ES_VERSION_2_0)
459     if (!aCtx->IsGlNormalizeEnabled()
460       && aCtx->core11 != NULL)
461     {
462       const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
463       if (Abs (aScale - 1.0) > Precision::Confusion())
464       {
465         aCtx->SetGlNormalizeEnabled (Standard_True);
466       }
467     }
468   #endif
469
470   #ifdef GL_DEPTH_CLAMP
471     if (myTrsfPers->Mode() == Graphic3d_TMF_CameraPers
472      && aCtx->arbDepthClamp)
473     {
474       toRestoreDepthClamp = true;
475       aCtx->core11fwd->glEnable (GL_DEPTH_CLAMP);
476     }
477   #endif
478   }
479
480   // Take into account transform persistence
481   aCtx->ApplyModelViewMatrix();
482
483   // remember aspects
484   const OpenGl_Aspects* aPrevAspectFace = theWorkspace->Aspects();
485
486   // Apply correction for mirror transform
487   if (myIsMirrored)
488   {
489     aCtx->core11fwd->glFrontFace (GL_CW);
490   }
491
492   // Collect clipping planes of structure scope
493   aCtx->ChangeClipping().SetLocalPlanes (myClipPlanes);
494
495   // True if structure is fully clipped
496   bool isClipped = false;
497   bool hasDisabled = false;
498   if (aCtx->Clipping().IsClippingOrCappingOn())
499   {
500     const Graphic3d_BndBox3d& aBBox = BoundingBox();
501     if (!myClipPlanes.IsNull()
502       && myClipPlanes->ToOverrideGlobal())
503     {
504       aCtx->ChangeClipping().DisableGlobal();
505       hasDisabled = aCtx->Clipping().HasDisabled();
506     }
507     else if (!myTrsfPers.IsNull())
508     {
509       if (myTrsfPers->IsZoomOrRotate())
510       {
511         // Zoom/rotate persistence object lives in two worlds at the same time.
512         // Global clipping planes can not be trivially applied without being converted
513         // into local space of transformation persistence object.
514         // As more simple alternative - just clip entire object by its anchor point defined in the world space.
515         const gp_Pnt anAnchor = myTrsfPers->AnchorPoint();
516         for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More() && aPlaneIt.IsGlobal(); aPlaneIt.Next())
517         {
518           const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
519           if (!aPlane->IsOn())
520           {
521             continue;
522           }
523
524           // check for clipping
525           const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
526           if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
527           {
528             isClipped = true;
529             break;
530           }
531         }
532       }
533
534       aCtx->ChangeClipping().DisableGlobal();
535       hasDisabled = aCtx->Clipping().HasDisabled();
536     }
537
538     // Set of clipping planes that do not intersect the structure,
539     // and thus can be disabled to improve rendering performance
540     if (aBBox.IsValid()
541      && myTrsfPers.IsNull())
542     {
543       for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next())
544       {
545         const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
546         if (aPlaneIt.IsDisabled())
547         {
548           continue;
549         }
550
551         const Graphic3d_ClipState aBoxState = aPlane->ProbeBox (aBBox);
552         if (aBoxState == Graphic3d_ClipState_In)
553         {
554           aCtx->ChangeClipping().SetEnabled (aPlaneIt, false);
555           hasDisabled = true;
556         }
557         else if (aBoxState == Graphic3d_ClipState_Out && myBndBoxClipCheck)
558         {
559           isClipped = true;
560           break;
561         }
562       }
563     }
564
565     if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
566      || hasDisabled)
567     {
568       // Set OCCT state uniform variables
569       aCtx->ShaderManager()->UpdateClippingState();
570     }
571   }
572
573   // Render groups
574   bool hasClosedPrims = false;
575   if (!isClipped)
576   {
577     renderGeometry (theWorkspace, hasClosedPrims);
578   }
579
580   // Reset correction for mirror transform
581   if (myIsMirrored)
582   {
583     aCtx->core11fwd->glFrontFace (GL_CCW);
584   }
585
586   // Render capping for structure groups
587   if (hasClosedPrims
588    && aCtx->Clipping().IsCappingOn())
589   {
590     OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
591   }
592
593   // Revert structure clippings
594   if (hasDisabled)
595   {
596     // enable planes that were previously disabled
597     aCtx->ChangeClipping().RestoreDisabled();
598   }
599   aCtx->ChangeClipping().SetLocalPlanes (Handle(Graphic3d_SequenceOfHClipPlane)());
600   if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
601     || hasDisabled)
602   {
603     // Set OCCT state uniform variables
604     aCtx->ShaderManager()->RevertClippingState();
605   }
606
607   // Restore local transformation
608   aCtx->ModelWorldState.Pop();
609   aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
610
611   // Restore aspects
612   theWorkspace->SetAspects (aPrevAspectFace);
613
614   // Apply highlight box
615   if (!isClipped
616    && !myHighlightStyle.IsNull()
617    &&  myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
618   {
619     aCtx->ApplyModelViewMatrix();
620     theWorkspace->SetHighlightStyle (myHighlightStyle);
621     renderBoundingBox (theWorkspace);
622   }
623
624   if (!myTrsfPers.IsNull())
625   {
626     aCtx->WorldViewState.Pop();
627     aCtx->ShaderManager()->SetCastShadows (anOldCastShadows);
628   #ifdef GL_DEPTH_CLAMP
629     if (toRestoreDepthClamp) { aCtx->core11fwd->glDisable (GL_DEPTH_CLAMP); }
630   #endif
631   }
632
633   // Restore named status
634   theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)());
635 }
636
637 // =======================================================================
638 // function : Release
639 // purpose  :
640 // =======================================================================
641 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
642 {
643   // Release groups
644   Clear (theGlCtx);
645   myHighlightStyle.Nullify();
646 }
647
648 // =======================================================================
649 // function : ReleaseGlResources
650 // purpose  :
651 // =======================================================================
652 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
653 {
654   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
655   {
656     aGroupIter.ChangeValue()->Release (theGlCtx);
657   }
658 }
659
660 //=======================================================================
661 //function : ShadowLink
662 //purpose  :
663 //=======================================================================
664 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
665 {
666   return new OpenGl_StructureShadow (theManager, this);
667 }
668
669 //=======================================================================
670 //function : DumpJson
671 //purpose  : 
672 //=======================================================================
673 void OpenGl_Structure::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
674 {
675   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
676
677   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Graphic3d_CStructure)
678
679   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myInstancedStructure)
680
681   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsRaytracable)
682   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myModificationState)
683   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsMirrored)
684 }