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