0026973: Visualization - selection of entities hidden by clipping planes is broken
[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_telem_util.hxx>
24 #include <OpenGl_Vec.hxx>
25 #include <OpenGl_View.hxx>
26 #include <OpenGl_Workspace.hxx>
27
28 #include <Graphic3d_SequenceOfHClipPlane.hxx>
29
30
31 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
32
33 //! Auxiliary class for bounding box presentation
34 class OpenGl_BndBoxPrs : public OpenGl_Element
35 {
36
37 public:
38
39   //! Main constructor
40   OpenGl_BndBoxPrs (const Graphic3d_BndBox4f& theBndBox)
41   {
42     const float Xm = theBndBox.CornerMin().x();
43     const float Ym = theBndBox.CornerMin().y();
44     const float Zm = theBndBox.CornerMin().z();
45     const float XM = theBndBox.CornerMax().x();
46     const float YM = theBndBox.CornerMax().y();
47     const float ZM = theBndBox.CornerMax().z();
48
49     myVerts[0]  = OpenGl_Vec3 (Xm, Ym, Zm);
50     myVerts[1]  = OpenGl_Vec3 (Xm, Ym, ZM);
51     myVerts[2]  = OpenGl_Vec3 (Xm, YM, ZM);
52     myVerts[3]  = OpenGl_Vec3 (Xm, YM, Zm);
53     myVerts[4]  = OpenGl_Vec3 (Xm, Ym, Zm);
54     myVerts[5]  = OpenGl_Vec3 (XM, Ym, Zm);
55     myVerts[6]  = OpenGl_Vec3 (XM, Ym, ZM);
56     myVerts[7]  = OpenGl_Vec3 (XM, YM, ZM);
57     myVerts[8]  = OpenGl_Vec3 (XM, YM, Zm);
58     myVerts[9]  = OpenGl_Vec3 (XM, Ym, Zm);
59     myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
60     myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
61     myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
62     myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
63     myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
64     myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
65   }
66
67   //! Render presentation
68   virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const
69   {
70   #if !defined(GL_ES_VERSION_2_0)
71     // Apply line aspect
72     const OpenGl_AspectLine*     anAspectLine = theWorkspace->AspectLine (Standard_True);
73     const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
74
75     glDisable (GL_LIGHTING);
76
77     // Use highlight colors
78     theWorkspace->GetGlContext()->core11->glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().rgb);
79
80     glEnableClientState (GL_VERTEX_ARRAY);
81     glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
82     glDrawArrays (GL_LINE_STRIP, 0, 16);
83     glDisableClientState (GL_VERTEX_ARRAY);
84
85     // restore aspects
86     if (!aPrevTexture.IsNull())
87     {
88       theWorkspace->EnableTexture (aPrevTexture);
89     }
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   myAspectLine         (NULL),
123   myAspectFace         (NULL),
124   myAspectMarker       (NULL),
125   myAspectText         (NULL),
126   myHighlightColor     (NULL),
127   myInstancedStructure (NULL),
128   myIsRaytracable      (Standard_False),
129   myModificationState  (0),
130   myIsCulled           (Standard_True),
131   myIsMirrored         (Standard_False)
132 {
133   //
134 }
135
136 // =======================================================================
137 // function : ~OpenGl_Structure
138 // purpose  :
139 // =======================================================================
140 OpenGl_Structure::~OpenGl_Structure()
141 {
142   Release (Handle(OpenGl_Context)());
143 }
144
145 // =======================================================================
146 // function : UpdateAspects
147 // purpose  :
148 // =======================================================================
149 void OpenGl_Structure::UpdateAspects()
150 {
151   if (ContextLine.IsDef)
152     SetAspectLine (ContextLine);
153
154   if (ContextFillArea.IsDef)
155     SetAspectFace (ContextFillArea);
156
157   if (ContextMarker.IsDef)
158     SetAspectMarker (ContextMarker);
159
160   if (ContextText.IsDef)
161     SetAspectText (ContextText);
162 }
163
164 // =======================================================================
165 // function : UpdateTransformation
166 // purpose  :
167 // =======================================================================
168 void OpenGl_Structure::UpdateTransformation()
169 {
170   const OpenGl_Mat4& aMat = Graphic3d_CStructure::Transformation;
171   Standard_ShortReal aDet =
172     aMat.GetValue(0, 0) * (aMat.GetValue(1, 1) * aMat.GetValue(2, 2) - aMat.GetValue(2, 1) * aMat.GetValue(1, 2)) -
173     aMat.GetValue(0, 1) * (aMat.GetValue(1, 0) * aMat.GetValue(2, 2) - aMat.GetValue(2, 0) * aMat.GetValue(1, 2)) +
174     aMat.GetValue(0, 2) * (aMat.GetValue(1, 0) * aMat.GetValue(2, 1) - aMat.GetValue(2, 0) * aMat.GetValue(1, 1));
175
176   // Determinant of transform matrix less then 0 means that mirror transform applied.
177   myIsMirrored = aDet < 0.0f;
178
179   if (IsRaytracable())
180   {
181     ++myModificationState;
182   }
183 }
184
185 // =======================================================================
186 // function : SetAspectLine
187 // purpose  :
188 // =======================================================================
189 void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &theAspect)
190 {
191   if (!myAspectLine)
192   {
193     myAspectLine = new OpenGl_AspectLine();
194   }
195   myAspectLine->SetAspect (theAspect);
196 }
197
198 // =======================================================================
199 // function : SetAspectFace
200 // purpose  :
201 // =======================================================================
202 void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect)
203 {
204   if (!myAspectFace)
205   {
206     myAspectFace = new OpenGl_AspectFace();
207   }
208   myAspectFace->SetAspect (theAspect);
209
210   if (IsRaytracable())
211   {
212     ++myModificationState;
213   }
214 }
215
216 // =======================================================================
217 // function : SetAspectMarker
218 // purpose  :
219 // =======================================================================
220 void OpenGl_Structure::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theAspect)
221 {
222   if (!myAspectMarker)
223   {
224     myAspectMarker = new OpenGl_AspectMarker();
225   }
226   myAspectMarker->SetAspect (theAspect);
227 }
228
229 // =======================================================================
230 // function : SetAspectText
231 // purpose  :
232 // =======================================================================
233 void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect)
234 {
235   if (!myAspectText)
236   {
237     myAspectText = new OpenGl_AspectText();
238   }
239   myAspectText->SetAspect (theAspect);
240 }
241
242 // =======================================================================
243 // function : clearHighlightBox
244 // purpose  :
245 // =======================================================================
246 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
247 {
248   if (!myHighlightBox.IsNull())
249   {
250     myHighlightBox->Release (theGlCtx);
251     myHighlightBox.Nullify();
252   }
253 }
254
255 // =======================================================================
256 // function : HighlightWithColor
257 // purpose  :
258 // =======================================================================
259 void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3&  theColor,
260                                            const Standard_Boolean theToCreate)
261 {
262   const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
263   if (theToCreate)
264     setHighlightColor   (aContext, theColor);
265   else
266     clearHighlightColor (aContext);
267 }
268
269 // =======================================================================
270 // function : HighlightWithBndBox
271 // purpose  :
272 // =======================================================================
273 void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
274                                             const Standard_Boolean             theToCreate)
275 {
276   const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
277   if (!theToCreate)
278   {
279     clearHighlightBox (aContext);
280     return;
281   }
282
283   if (!myHighlightBox.IsNull())
284   {
285     myHighlightBox->Release (aContext);
286   }
287   else
288   {
289     myHighlightBox = new OpenGl_Group (theStruct);
290   }
291
292   CALL_DEF_CONTEXTLINE& aContextLine = myHighlightBox->ChangeContextLine();
293   aContextLine.IsDef    = 1;
294   aContextLine.Color    = HighlightColor;
295   aContextLine.LineType = Aspect_TOL_SOLID;
296   aContextLine.Width    = 1.0f;
297   myHighlightBox->UpdateAspectLine (Standard_True);
298
299   OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
300   myHighlightBox->AddElement (aBndBoxPrs);
301 }
302
303 // =======================================================================
304 // function : setHighlightColor
305 // purpose  :
306 // =======================================================================
307 void OpenGl_Structure::setHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
308                                           const Graphic3d_Vec3&         theColor)
309 {
310   clearHighlightBox (theGlCtx);
311   if (myHighlightColor == NULL)
312   {
313     myHighlightColor = new TEL_COLOUR();
314   }
315
316   myHighlightColor->rgb[0] = theColor.r();
317   myHighlightColor->rgb[1] = theColor.g();
318   myHighlightColor->rgb[2] = theColor.b();
319   myHighlightColor->rgb[3] = 1.F;
320 }
321
322 // =======================================================================
323 // function : clearHighlightColor
324 // purpose  :
325 // =======================================================================
326 void OpenGl_Structure::clearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
327 {
328   clearHighlightBox(theGlCtx);
329   delete myHighlightColor;
330   myHighlightColor = NULL;
331 }
332
333 // =======================================================================
334 // function : OnVisibilityChanged
335 // purpose  :
336 // =======================================================================
337 void OpenGl_Structure::OnVisibilityChanged()
338 {
339   if (IsRaytracable())
340   {
341     ++myModificationState;
342   }
343 }
344
345 // =======================================================================
346 // function : IsRaytracable
347 // purpose  :
348 // =======================================================================
349 Standard_Boolean OpenGl_Structure::IsRaytracable() const
350 {
351   if (!myGroups.IsEmpty())
352   {
353     return myIsRaytracable; // geometry structure
354   }
355   else if (myInstancedStructure != NULL)
356   {
357     return myInstancedStructure->IsRaytracable(); // instance structure
358   }
359
360   return Standard_False; // has no any groups or structures
361 }
362
363 // =======================================================================
364 // function : UpdateRaytracableState
365 // purpose  :
366 // =======================================================================
367 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
368 {
369   myIsRaytracable = !toCheck || OpenGl_Raytrace::IsRaytracedStructure (this);
370
371   if (IsRaytracable())
372   {
373     ++myModificationState;
374   }
375 }
376
377 // =======================================================================
378 // function : Connect
379 // purpose  :
380 // =======================================================================
381 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
382 {
383   OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
384
385   Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
386     "Error! Instanced structure is already defined");
387
388   myInstancedStructure = aStruct;
389
390   if (aStruct->IsRaytracable())
391   {
392     UpdateStateIfRaytracable (Standard_False);
393   }
394 }
395
396 // =======================================================================
397 // function : Disconnect
398 // purpose  :
399 // =======================================================================
400 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
401 {
402   OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
403
404   if (myInstancedStructure == aStruct)
405   {
406     myInstancedStructure = NULL;
407
408     if (aStruct->IsRaytracable())
409     {
410       UpdateStateIfRaytracable();
411     }
412   }
413 }
414
415 // =======================================================================
416 // function : NewGroup
417 // purpose  :
418 // =======================================================================
419 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
420 {
421   Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
422   myGroups.Append (aGroup);
423   return aGroup;
424 }
425
426 // =======================================================================
427 // function : RemoveGroup
428 // purpose  :
429 // =======================================================================
430 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
431 {
432   if (theGroup.IsNull())
433   {
434     return;
435   }
436
437   for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
438   {
439     // Check for the given group
440     if (aGroupIter.Value() == theGroup)
441     {
442       const Standard_Boolean wasRaytracable =
443         static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
444
445       theGroup->Clear (Standard_False);
446
447       if (wasRaytracable)
448       {
449         UpdateStateIfRaytracable();
450       }
451
452       myGroups.Remove (aGroupIter);
453       return;
454     }
455   }
456 }
457
458 // =======================================================================
459 // function : Clear
460 // purpose  :
461 // =======================================================================
462 void OpenGl_Structure::Clear()
463 {
464   Clear (GlDriver()->GetSharedContext());
465 }
466
467 // =======================================================================
468 // function : Clear
469 // purpose  :
470 // =======================================================================
471 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
472 {
473   Standard_Boolean aRaytracableGroupDeleted (Standard_False);
474
475   // Release groups
476   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
477   {
478     aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
479
480     // Delete objects
481     aGroupIter.ChangeValue()->Release (theGlCtx);
482   }
483   myGroups.Clear();
484
485   if (aRaytracableGroupDeleted)
486   {
487     myIsRaytracable = Standard_False;
488   }
489
490   Is2dText       = Standard_False;
491   IsForHighlight = Standard_False;
492 }
493
494 // =======================================================================
495 // function : renderGeometry
496 // purpose  :
497 // =======================================================================
498 void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
499                                        bool&                           theHasClosed) const
500 {
501   if (myInstancedStructure != NULL)
502   {
503     myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
504   }
505
506   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
507   {
508     theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
509     aGroupIter.Value()->Render (theWorkspace);
510   }
511 }
512
513 // =======================================================================
514 // function : renderClosedGeometry
515 // purpose  :
516 // =======================================================================
517 void OpenGl_Structure::renderClosedGeometry (const Handle(OpenGl_Workspace)& theWorkspace) const
518 {
519   if (myInstancedStructure != NULL)
520   {
521     myInstancedStructure->renderClosedGeometry (theWorkspace);
522   }
523
524   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
525   {
526     if (aGroupIter.Value()->IsClosed())
527     {
528       aGroupIter.Value()->Render (theWorkspace);
529     }
530   }
531 }
532
533 // =======================================================================
534 // function : Render
535 // purpose  :
536 // =======================================================================
537 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
538 {
539   // Process the structure only if visible
540   if (!visible)
541   {
542     return;
543   }
544
545   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
546
547   // Render named status
548   const Standard_Integer aNamedStatus = theWorkspace->NamedStatus;
549   if (highlight)
550   {
551     theWorkspace->NamedStatus |= OPENGL_NS_HIGHLIGHT;
552   }
553
554   // Apply local transformation
555   aCtx->ModelWorldState.Push();
556   aCtx->ModelWorldState.SetCurrent (Transformation);
557
558   // detect scale transform
559   const Standard_Boolean   anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
560   const Standard_ShortReal aScaleX          = Transformation.GetRow (0).xyz().SquareModulus();
561   if (Abs (aScaleX - 1.f) > Precision::Confusion())
562   {
563     aCtx->SetGlNormalizeEnabled (Standard_True);
564   }
565
566   if (TransformPersistence.Flags)
567   {
568     OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current();
569     OpenGl_Mat4 aWorldView  = aCtx->WorldViewState.Current();
570     TransformPersistence.Apply (aProjection, aWorldView, theWorkspace->Width(), theWorkspace->Height());
571
572     aCtx->ProjectionState.Push();
573     aCtx->WorldViewState.Push();
574     aCtx->ProjectionState.SetCurrent (aProjection);
575     aCtx->WorldViewState.SetCurrent (aWorldView);
576     aCtx->ApplyProjectionMatrix();
577   }
578
579   // Take into account transform persistence
580   aCtx->ApplyModelViewMatrix();
581
582   // Apply aspects
583   const OpenGl_AspectLine *anAspectLine = theWorkspace->AspectLine (Standard_False);
584   const OpenGl_AspectFace *anAspectFace = theWorkspace->AspectFace (Standard_False);
585   const OpenGl_AspectMarker *anAspectMarker = theWorkspace->AspectMarker (Standard_False);
586   const OpenGl_AspectText *anAspectText = theWorkspace->AspectText (Standard_False);
587   if (myAspectLine)
588   {
589     theWorkspace->SetAspectLine (myAspectLine);
590   }
591   if (myAspectFace)
592   {
593     theWorkspace->SetAspectFace (myAspectFace);
594   }
595   if (myAspectMarker)
596   {
597     theWorkspace->SetAspectMarker (myAspectMarker);
598   }
599   if (myAspectText)
600   {
601     theWorkspace->SetAspectText (myAspectText);
602   }
603
604   // Apply correction for mirror transform
605   if (myIsMirrored)
606   {
607     aCtx->core11fwd->glFrontFace (GL_CW);
608   }
609
610   // Apply highlight color
611   const TEL_COLOUR *aHighlightColor = theWorkspace->HighlightColor;
612   if (myHighlightColor)
613     theWorkspace->HighlightColor = myHighlightColor;
614
615   // Set up plane equations for non-structure transformed global model-view matrix
616   // List of planes to be applied to context state
617   NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
618
619   // Collect clipping planes of structure scope
620   if (!myClipPlanes.IsEmpty())
621   {
622     Graphic3d_SequenceOfHClipPlane::Iterator aClippingIter (myClipPlanes);
623     for (; aClippingIter.More(); aClippingIter.Next())
624     {
625       const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIter.Value();
626       if (!aClipPlane->IsOn())
627       {
628         continue;
629       }
630
631       if (aUserPlanes.IsNull())
632       {
633         aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
634       }
635
636       aUserPlanes->Append (aClipPlane);
637     }
638   }
639
640   if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
641   {
642     // add planes at loaded view matrix state
643     aCtx->ChangeClipping().AddWorld (aCtx, *aUserPlanes);
644
645     // Set OCCT state uniform variables
646     if (!aCtx->ShaderManager()->IsEmpty())
647     {
648       aCtx->ShaderManager()->UpdateClippingState();
649     }
650   }
651
652   // Render groups
653   bool hasClosedPrims = false;
654   renderGeometry (theWorkspace, hasClosedPrims);
655
656   // Reset correction for mirror transform
657   if (myIsMirrored)
658   {
659     aCtx->core11fwd->glFrontFace (GL_CCW);
660   }
661
662   // Render capping for structure groups
663   if (hasClosedPrims
664   && !aCtx->Clipping().Planes().IsEmpty())
665   {
666     OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
667   }
668
669   // Revert structure clippings
670   if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
671   {
672     aCtx->ChangeClipping().Remove (aCtx, *aUserPlanes);
673
674     // Set OCCT state uniform variables
675     if (!aCtx->ShaderManager()->IsEmpty())
676     {
677       aCtx->ShaderManager()->RevertClippingState();
678     }
679   }
680
681   // Restore local transformation
682   aCtx->ModelWorldState.Pop();
683   aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
684   if (TransformPersistence.Flags)
685   {
686     aCtx->ProjectionState.Pop();
687     aCtx->WorldViewState.Pop();
688     aCtx->ApplyProjectionMatrix();
689   }
690
691   // Restore highlight color
692   theWorkspace->HighlightColor = aHighlightColor;
693
694   // Restore aspects
695   theWorkspace->SetAspectLine (anAspectLine);
696   theWorkspace->SetAspectFace (anAspectFace);
697   theWorkspace->SetAspectMarker (anAspectMarker);
698   theWorkspace->SetAspectText (anAspectText);
699
700   // Apply highlight box
701   if (!myHighlightBox.IsNull())
702   {
703     myHighlightBox->Render (theWorkspace);
704   }
705
706   // Restore named status
707   theWorkspace->NamedStatus = aNamedStatus;
708 }
709
710 // =======================================================================
711 // function : Release
712 // purpose  :
713 // =======================================================================
714 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
715 {
716   // Release groups
717   Clear (theGlCtx);
718   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
719   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
720   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
721   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
722   clearHighlightColor (theGlCtx);
723 }
724
725 // =======================================================================
726 // function : ReleaseGlResources
727 // purpose  :
728 // =======================================================================
729 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
730 {
731   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
732   {
733     aGroupIter.ChangeValue()->Release (theGlCtx);
734   }
735   if (myAspectLine != NULL)
736   {
737     myAspectLine->Release (theGlCtx.operator->());
738   }
739   if (myAspectFace != NULL)
740   {
741     myAspectFace->Release (theGlCtx.operator->());
742   }
743   if (myAspectMarker != NULL)
744   {
745     myAspectMarker->Release (theGlCtx.operator->());
746   }
747   if (myAspectText != NULL)
748   {
749     myAspectText->Release (theGlCtx.operator->());
750   }
751   if (!myHighlightBox.IsNull())
752   {
753     myHighlightBox->Release (theGlCtx.operator->());
754   }
755 }
756
757 //=======================================================================
758 //function : ShadowLink
759 //purpose  :
760 //=======================================================================
761 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
762 {
763   return new OpenGl_StructureShadow (theManager, this);
764 }