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