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