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