0023345: Crash when destroying OpenGl_Element
[occt.git] / src / OpenGl / OpenGl_Structure.cxx
1 // Created on: 2011-08-01
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <OpenGl_GlCore11.hxx>
22
23 #include <OpenGl_Structure.hxx>
24
25 #include <OpenGl_Polyline.hxx>
26 #include <OpenGl_Workspace.hxx>
27 #include <OpenGl_View.hxx>
28
29 #include <OpenGl_telem_util.hxx>
30
31
32 /*----------------------------------------------------------------------*/
33
34 static void call_util_transpose_mat (float tmat[16], float mat[4][4])
35 {
36   int i, j;
37
38   for (i=0; i<4; i++)
39     for (j=0; j<4; j++)
40       tmat[j*4+i] = mat[i][j];
41 }
42
43 /*----------------------------------------------------------------------*/
44
45 OpenGl_Structure::OpenGl_Structure ()
46 : myTransformation(NULL),
47   myTransPers(NULL),
48   myDegenerateModel(NULL),
49   myAspectLine(NULL),
50   myAspectFace(NULL),
51   myAspectMarker(NULL),
52   myAspectText(NULL),
53   myHighlightBox(NULL),
54   myHighlightColor(NULL),
55   myNamedStatus(0),
56   myZLayer(0)
57 {
58 }
59
60 /*----------------------------------------------------------------------*/
61
62 OpenGl_Structure::~OpenGl_Structure()
63 {
64   Release (Handle(OpenGl_Context)());
65   delete myTransformation;  myTransformation  = NULL;
66   delete myTransPers;       myTransPers       = NULL;
67   delete myDegenerateModel; myDegenerateModel = NULL;
68 }
69
70 /*----------------------------------------------------------------------*/
71
72 void OpenGl_Structure::SetTransformation(const float *AMatrix)
73 {
74   if (!myTransformation)
75     myTransformation = new OpenGl_Matrix();
76
77   matcpy( myTransformation->mat, AMatrix );
78 }
79
80 /*----------------------------------------------------------------------*/
81
82 void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers)
83 {
84   if (!myTransPers)
85     myTransPers = new TEL_TRANSFORM_PERSISTENCE;
86
87   myTransPers->mode = ATransPers.Flag;
88   myTransPers->pointX = ATransPers.Point.x;
89   myTransPers->pointY = ATransPers.Point.y;
90   myTransPers->pointZ = ATransPers.Point.z;
91 }
92
93 /*----------------------------------------------------------------------*/
94
95 void OpenGl_Structure::SetDegenerateModel (const Standard_Integer AMode, const float ASkipRatio)
96 {
97   if (!myDegenerateModel)
98     myDegenerateModel = new DEGENERATION;
99
100   myDegenerateModel->mode = AMode;
101   myDegenerateModel->skipRatio = ASkipRatio;
102 }
103
104 /*----------------------------------------------------------------------*/
105
106 void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &AContext)
107 {
108   if (!myAspectLine)
109     myAspectLine = new OpenGl_AspectLine();
110   myAspectLine->SetContext( AContext );
111 }
112
113 /*----------------------------------------------------------------------*/
114
115 void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA &AContext)
116 {
117   if (!myAspectFace)
118     myAspectFace = new OpenGl_AspectFace();
119   myAspectFace->SetContext( AContext );
120 }
121
122 /*----------------------------------------------------------------------*/
123
124 void OpenGl_Structure::SetAspectMarker (const CALL_DEF_CONTEXTMARKER &AContext)
125 {
126   if (!myAspectMarker)
127     myAspectMarker = new OpenGl_AspectMarker();
128   myAspectMarker->SetContext( AContext );
129 }
130
131 /*----------------------------------------------------------------------*/
132
133 void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &AContext)
134 {
135   if (!myAspectText)
136     myAspectText = new OpenGl_AspectText();
137   myAspectText->SetContext( AContext );
138 }
139
140 /*----------------------------------------------------------------------*/
141
142 void OpenGl_Structure::SetHighlightBox (const Handle(OpenGl_Context)& theGlCtx,
143                                         const CALL_DEF_BOUNDBOX&      theBoundBox)
144 {
145   if (myHighlightBox != NULL)
146   {
147     myHighlightBox->Release (theGlCtx);
148   }
149   else
150   {
151     myHighlightBox = new OpenGl_Group();
152   }
153
154   CALL_DEF_CONTEXTLINE aContextLine;
155   aContextLine.Color    = theBoundBox.Color;
156   aContextLine.LineType = Aspect_TOL_SOLID;
157   aContextLine.Width    = 1.0f;
158   myHighlightBox->SetAspectLine (aContextLine);
159
160 #define CALL_MAX_BOUNDBOXSIZE 16
161
162   Graphic3d_Array1OfVertex aPoints (1, CALL_MAX_BOUNDBOXSIZE);
163   const float Xm = theBoundBox.Pmin.x;
164   const float Ym = theBoundBox.Pmin.y;
165   const float Zm = theBoundBox.Pmin.z;
166   const float XM = theBoundBox.Pmax.x;
167   const float YM = theBoundBox.Pmax.y;
168   const float ZM = theBoundBox.Pmax.z;
169   aPoints( 1).SetCoord (Xm, Ym, Zm);
170   aPoints( 2).SetCoord (Xm, Ym, ZM);
171   aPoints( 3).SetCoord (Xm, YM, ZM);
172   aPoints( 4).SetCoord (Xm, YM, Zm);
173   aPoints( 5).SetCoord (Xm, Ym, Zm);
174   aPoints( 6).SetCoord (XM, Ym, Zm);
175   aPoints( 7).SetCoord (XM, Ym, ZM);
176   aPoints( 8).SetCoord (XM, YM, ZM);
177   aPoints( 9).SetCoord (XM, YM, Zm);
178   aPoints(10).SetCoord (XM, Ym, Zm);
179   aPoints(11).SetCoord (XM, YM, Zm);
180   aPoints(12).SetCoord (Xm, YM, Zm);
181   aPoints(13).SetCoord (Xm, YM, ZM);
182   aPoints(14).SetCoord (XM, YM, ZM);
183   aPoints(15).SetCoord (XM, Ym, ZM);
184   aPoints(16).SetCoord (Xm, Ym, ZM);
185
186   OpenGl_Polyline* aPolyline = new OpenGl_Polyline (aPoints);
187   myHighlightBox->AddElement (TelPolyline, aPolyline);
188 }
189
190 /*----------------------------------------------------------------------*/
191
192 void OpenGl_Structure::ClearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
193 {
194   if (myHighlightBox != NULL)
195   {
196     OpenGl_Element::Destroy (theGlCtx, myHighlightBox);
197   }
198 }
199
200 /*----------------------------------------------------------------------*/
201
202 void OpenGl_Structure::SetHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
203                                           const Standard_ShortReal R,
204                                           const Standard_ShortReal G,
205                                           const Standard_ShortReal B)
206 {
207   ClearHighlightBox (theGlCtx);
208   if (myHighlightColor == NULL)
209   {
210     myHighlightColor = new TEL_COLOUR();
211   }
212
213   myHighlightColor->rgb[0] = R;
214   myHighlightColor->rgb[1] = G;
215   myHighlightColor->rgb[2] = B;
216   myHighlightColor->rgb[3] = 1.F;
217 }
218
219 /*----------------------------------------------------------------------*/
220
221 void OpenGl_Structure::ClearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
222 {
223   ClearHighlightBox(theGlCtx);
224   delete myHighlightColor;
225   myHighlightColor = NULL;
226 }
227
228 /*----------------------------------------------------------------------*/
229
230 void OpenGl_Structure::Connect (const OpenGl_Structure *AStructure)
231 {
232   Disconnect (AStructure);
233   myConnected.Append(AStructure);
234 }
235
236 /*----------------------------------------------------------------------*/
237
238 void OpenGl_Structure::Disconnect (const OpenGl_Structure *AStructure)
239 {
240   OpenGl_ListOfStructure::Iterator its(myConnected);
241   while (its.More())
242   {
243     // Check for the given structure
244     if (its.Value() == AStructure)
245     {
246       myConnected.Remove(its);
247       return;
248     }
249     its.Next();
250   }
251 }
252
253 /*----------------------------------------------------------------------*/
254
255 OpenGl_Group * OpenGl_Structure::AddGroup ()
256 {
257   // Create new group
258   OpenGl_Group *g = new OpenGl_Group;
259   myGroups.Append(g);
260   return g;
261 }
262
263 /*----------------------------------------------------------------------*/
264
265 void OpenGl_Structure::RemoveGroup (const Handle(OpenGl_Context)& theGlCtx,
266                                     const OpenGl_Group*           theGroup)
267 {
268   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
269   {
270     // Check for the given group
271     if (anIter.Value() == theGroup)
272     {
273       // Delete object
274       OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
275       myGroups.Remove (anIter);
276       return;
277     }
278   }
279 }
280
281 /*----------------------------------------------------------------------*/
282
283 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
284 {
285   // Release groups
286   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
287   {
288     // Delete objects
289     OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
290   }
291   myGroups.Clear();
292 }
293
294 /*----------------------------------------------------------------------*/
295
296 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
297 {
298   // Process the structure only if visible
299   if ( myNamedStatus & OPENGL_NS_HIDE )
300     return;
301
302   // Render named status
303   const Standard_Integer named_status = AWorkspace->NamedStatus;
304   AWorkspace->NamedStatus |= myNamedStatus;
305
306   // Is rendering in ADD or IMMEDIATE mode?
307   const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
308
309   // Apply local transformation
310   GLint matrix_mode = 0;
311   const OpenGl_Matrix *local_trsf = NULL;
312   if (myTransformation)
313   {
314     if (isImmediate)
315     {
316       float mat16[16];
317       call_util_transpose_mat (mat16, myTransformation->mat);
318       glGetIntegerv (GL_MATRIX_MODE, &matrix_mode);
319       glMatrixMode (GL_MODELVIEW);
320       glPushMatrix ();
321       glScalef (1.F, 1.F, 1.F);
322       glMultMatrixf (mat16);
323     }
324     else
325     {
326       glMatrixMode (GL_MODELVIEW);
327       glPushMatrix();
328
329       local_trsf = AWorkspace->SetStructureMatrix(myTransformation);
330     }
331   }
332
333   // Apply transform persistence
334   const TEL_TRANSFORM_PERSISTENCE *trans_pers = NULL;
335   if ( myTransPers && myTransPers->mode != 0 )
336   {
337     trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence( myTransPers );
338   }
339
340   // Apply degeneration
341   if (myDegenerateModel)
342   {
343     if ( AWorkspace->NamedStatus & OPENGL_NS_DEGENERATION )
344     {
345       AWorkspace->DegenerateModel = myDegenerateModel->mode;
346       switch ( AWorkspace->DegenerateModel )
347       {
348         case 0: break;
349
350         default:
351           glLineWidth ( 1.0 );
352           glDisable   ( GL_LINE_STIPPLE );
353
354         case 1:
355           AWorkspace->SkipRatio = myDegenerateModel->skipRatio;
356       }
357     }
358   }
359
360   // Apply aspects
361   const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine(Standard_False);
362   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace(Standard_False);
363   const OpenGl_AspectMarker *aspect_marker = AWorkspace->AspectMarker(Standard_False);
364   const OpenGl_AspectText *aspect_text = AWorkspace->AspectText(Standard_False);
365   if (myAspectLine)
366     AWorkspace->SetAspectLine(myAspectLine);
367   if (myAspectFace)
368     AWorkspace->SetAspectFace(myAspectFace);
369   if (myAspectMarker)
370     AWorkspace->SetAspectMarker(myAspectMarker);
371   if (myAspectText)
372     AWorkspace->SetAspectText(myAspectText);
373
374   // Apply highlight box
375   if (myHighlightBox)
376     myHighlightBox->Render( AWorkspace );
377
378   // Apply highlight color
379   const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
380   if (myHighlightColor)
381     AWorkspace->HighlightColor = myHighlightColor;
382
383   // Render connected structures
384   OpenGl_ListOfStructure::Iterator its(myConnected);
385   while (its.More())
386   {
387     its.Value()->Render(AWorkspace);
388     its.Next();
389   }
390
391   // Render groups
392   OpenGl_ListOfGroup::Iterator itg(myGroups);
393   while (itg.More())
394   {
395     itg.Value()->Render(AWorkspace);
396     itg.Next();
397   }
398
399   // Restore highlight color
400   AWorkspace->HighlightColor = highlight_color;
401
402   // Restore aspects
403   AWorkspace->SetAspectLine(aspect_line);
404   AWorkspace->SetAspectFace(aspect_face);
405   AWorkspace->SetAspectMarker(aspect_marker);
406   AWorkspace->SetAspectText(aspect_text);
407
408   // Restore transform persistence
409   if ( myTransPers && myTransPers->mode != 0 )
410   {
411     AWorkspace->ActiveView()->BeginTransformPersistence( trans_pers );
412   }
413
414   // Restore local transformation
415   if (myTransformation)
416   {
417     if (isImmediate)
418     {
419       glPopMatrix ();
420       glMatrixMode (matrix_mode);
421     }
422     else
423     {
424       AWorkspace->SetStructureMatrix(local_trsf);
425
426       glMatrixMode (GL_MODELVIEW);
427       glPopMatrix();
428     }
429   }
430
431   // Restore named status
432   AWorkspace->NamedStatus = named_status;
433 }
434
435 // =======================================================================
436 // function : Release
437 // purpose  :
438 // =======================================================================
439 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
440 {
441   // Release groups
442   Clear (theGlCtx);
443   OpenGl_Element::Destroy (theGlCtx, myAspectLine);
444   OpenGl_Element::Destroy (theGlCtx, myAspectFace);
445   OpenGl_Element::Destroy (theGlCtx, myAspectMarker);
446   OpenGl_Element::Destroy (theGlCtx, myAspectText);
447   ClearHighlightColor (theGlCtx);
448 }
449
450 // =======================================================================
451 // function : ReleaseGlResources
452 // purpose  :
453 // =======================================================================
454 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
455 {
456   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
457   {
458     OpenGl_Group* aGroup = const_cast<OpenGl_Group*& > (anIter.ChangeValue());
459     if (aGroup != NULL)
460     {
461       aGroup->Release (theGlCtx);
462     }
463   }
464   if (myAspectLine != NULL)
465   {
466     myAspectLine->Release (theGlCtx);
467   }
468   if (myAspectFace != NULL)
469   {
470     myAspectFace->Release (theGlCtx);
471   }
472   if (myAspectMarker != NULL)
473   {
474     myAspectMarker->Release (theGlCtx);
475   }
476   if (myAspectText != NULL)
477   {
478     myAspectText->Release (theGlCtx);
479   }
480   if (myHighlightBox != NULL)
481   {
482     myHighlightBox->Release (theGlCtx);
483   }
484 }
485
486 //=======================================================================
487 //function : SetZLayer
488 //purpose  : 
489 //=======================================================================
490
491 void OpenGl_Structure::SetZLayer (const Standard_Integer theLayerIndex)
492 {
493   myZLayer = theLayerIndex;
494 }
495
496 //=======================================================================
497 //function : GetZLayer
498 //purpose  : 
499 //=======================================================================
500
501 Standard_Integer OpenGl_Structure::GetZLayer () const
502 {
503   return myZLayer;
504 }