0024131: TKOpenGL redesign GPU memory management for markers presentation
[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 #include <OpenGl_GlCore11.hxx>
21
22 #include <OpenGl_Structure.hxx>
23
24 #include <OpenGl_Workspace.hxx>
25 #include <OpenGl_Vec.hxx>
26 #include <OpenGl_View.hxx>
27
28 #include <OpenGl_telem_util.hxx>
29
30 //! Auxiliary class for bounding box presentation
31 class OpenGl_BndBoxPrs : public OpenGl_Element
32 {
33
34 public:
35
36   //! Main constructor
37   OpenGl_BndBoxPrs (const CALL_DEF_BOUNDBOX& theBndBox)
38   {
39     const float Xm = theBndBox.Pmin.x;
40     const float Ym = theBndBox.Pmin.y;
41     const float Zm = theBndBox.Pmin.z;
42     const float XM = theBndBox.Pmax.x;
43     const float YM = theBndBox.Pmax.y;
44     const float ZM = theBndBox.Pmax.z;
45     myVerts[0]  = OpenGl_Vec3 (Xm, Ym, Zm);
46     myVerts[1]  = OpenGl_Vec3 (Xm, Ym, ZM);
47     myVerts[2]  = OpenGl_Vec3 (Xm, YM, ZM);
48     myVerts[3]  = OpenGl_Vec3 (Xm, YM, Zm);
49     myVerts[4]  = OpenGl_Vec3 (Xm, Ym, Zm);
50     myVerts[5]  = OpenGl_Vec3 (XM, Ym, Zm);
51     myVerts[6]  = OpenGl_Vec3 (XM, Ym, ZM);
52     myVerts[7]  = OpenGl_Vec3 (XM, YM, ZM);
53     myVerts[8]  = OpenGl_Vec3 (XM, YM, Zm);
54     myVerts[9]  = OpenGl_Vec3 (XM, Ym, Zm);
55     myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
56     myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
57     myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
58     myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
59     myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
60     myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
61   }
62
63   //! Render presentation
64   virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const
65   {
66     // Apply line aspect
67     const OpenGl_AspectLine*     anAspectLine = theWorkspace->AspectLine (Standard_True);
68     const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
69
70     glDisable (GL_LIGHTING);
71     if ((theWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0)
72     {
73       glDepthMask (GL_FALSE);
74     }
75
76     // Use highlight colors
77     glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().rgb);
78
79     glEnableClientState (GL_VERTEX_ARRAY);
80     glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
81     glDrawArrays (GL_LINE_STRIP, 0, 16);
82     glDisableClientState (GL_VERTEX_ARRAY);
83
84     // restore aspects
85     if (!aPrevTexture.IsNull())
86     {
87       theWorkspace->EnableTexture (aPrevTexture);
88     }
89   }
90
91   //! Release graphical resources
92   virtual void Release (const Handle(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 static void call_util_transpose_mat (float tmat[16], float mat[4][4])
115 {
116   int i, j;
117
118   for (i=0; i<4; i++)
119     for (j=0; j<4; j++)
120       tmat[j*4+i] = mat[i][j];
121 }
122
123 /*----------------------------------------------------------------------*/
124
125 OpenGl_Structure::OpenGl_Structure ()
126 : myTransformation(NULL),
127   myTransPers(NULL),
128   myAspectLine(NULL),
129   myAspectFace(NULL),
130   myAspectMarker(NULL),
131   myAspectText(NULL),
132   myHighlightBox(NULL),
133   myHighlightColor(NULL),
134   myNamedStatus(0),
135   myZLayer(0)
136 {
137 }
138
139 /*----------------------------------------------------------------------*/
140
141 OpenGl_Structure::~OpenGl_Structure()
142 {
143   Release (Handle(OpenGl_Context)());
144   delete myTransformation;  myTransformation  = NULL;
145   delete myTransPers;       myTransPers       = NULL;
146 }
147
148 /*----------------------------------------------------------------------*/
149
150 void OpenGl_Structure::SetTransformation(const float *AMatrix)
151 {
152   if (!myTransformation)
153     myTransformation = new OpenGl_Matrix();
154
155   matcpy( myTransformation->mat, AMatrix );
156 }
157
158 /*----------------------------------------------------------------------*/
159
160 void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers)
161 {
162   if (!myTransPers)
163     myTransPers = new TEL_TRANSFORM_PERSISTENCE;
164
165   myTransPers->mode = ATransPers.Flag;
166   myTransPers->pointX = ATransPers.Point.x;
167   myTransPers->pointY = ATransPers.Point.y;
168   myTransPers->pointZ = ATransPers.Point.z;
169 }
170
171 /*----------------------------------------------------------------------*/
172
173 void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &AContext)
174 {
175   if (!myAspectLine)
176     myAspectLine = new OpenGl_AspectLine();
177   myAspectLine->SetContext( AContext );
178 }
179
180 /*----------------------------------------------------------------------*/
181
182 void OpenGl_Structure::SetAspectFace (const Handle(OpenGl_Context)&   theCtx,
183                                       const CALL_DEF_CONTEXTFILLAREA& theAspect)
184 {
185   if (!myAspectFace)
186   {
187     myAspectFace = new OpenGl_AspectFace();
188   }
189   myAspectFace->Init (theCtx, theAspect);
190 }
191
192 /*----------------------------------------------------------------------*/
193
194 void OpenGl_Structure::SetAspectMarker (const Handle(OpenGl_Context)& theCtx,
195                                         const CALL_DEF_CONTEXTMARKER& theAspect)
196 {
197   if (!myAspectMarker)
198   {
199     myAspectMarker = new OpenGl_AspectMarker();
200   }
201   myAspectMarker->Init (theCtx, theAspect);
202 }
203
204 /*----------------------------------------------------------------------*/
205
206 void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &AContext)
207 {
208   if (!myAspectText)
209     myAspectText = new OpenGl_AspectText();
210   myAspectText->SetContext( AContext );
211 }
212
213 /*----------------------------------------------------------------------*/
214
215 void OpenGl_Structure::SetHighlightBox (const Handle(OpenGl_Context)& theGlCtx,
216                                         const CALL_DEF_BOUNDBOX&      theBoundBox)
217 {
218   if (myHighlightBox != NULL)
219   {
220     myHighlightBox->Release (theGlCtx);
221   }
222   else
223   {
224     myHighlightBox = new OpenGl_Group();
225   }
226
227   CALL_DEF_CONTEXTLINE aContextLine;
228   aContextLine.Color    = theBoundBox.Color;
229   aContextLine.LineType = Aspect_TOL_SOLID;
230   aContextLine.Width    = 1.0f;
231   myHighlightBox->SetAspectLine (aContextLine);
232
233   OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (theBoundBox);
234   myHighlightBox->AddElement (TelParray, aBndBoxPrs);
235 }
236
237 /*----------------------------------------------------------------------*/
238
239 void OpenGl_Structure::ClearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
240 {
241   if (myHighlightBox != NULL)
242   {
243     OpenGl_Element::Destroy (theGlCtx, myHighlightBox);
244   }
245 }
246
247 /*----------------------------------------------------------------------*/
248
249 void OpenGl_Structure::SetHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
250                                           const Standard_ShortReal R,
251                                           const Standard_ShortReal G,
252                                           const Standard_ShortReal B)
253 {
254   ClearHighlightBox (theGlCtx);
255   if (myHighlightColor == NULL)
256   {
257     myHighlightColor = new TEL_COLOUR();
258   }
259
260   myHighlightColor->rgb[0] = R;
261   myHighlightColor->rgb[1] = G;
262   myHighlightColor->rgb[2] = B;
263   myHighlightColor->rgb[3] = 1.F;
264 }
265
266 /*----------------------------------------------------------------------*/
267
268 void OpenGl_Structure::ClearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
269 {
270   ClearHighlightBox(theGlCtx);
271   delete myHighlightColor;
272   myHighlightColor = NULL;
273 }
274
275 /*----------------------------------------------------------------------*/
276
277 void OpenGl_Structure::Connect (const OpenGl_Structure *AStructure)
278 {
279   Disconnect (AStructure);
280   myConnected.Append(AStructure);
281 }
282
283 /*----------------------------------------------------------------------*/
284
285 void OpenGl_Structure::Disconnect (const OpenGl_Structure *AStructure)
286 {
287   OpenGl_ListOfStructure::Iterator its(myConnected);
288   while (its.More())
289   {
290     // Check for the given structure
291     if (its.Value() == AStructure)
292     {
293       myConnected.Remove(its);
294       return;
295     }
296     its.Next();
297   }
298 }
299
300 /*----------------------------------------------------------------------*/
301
302 OpenGl_Group * OpenGl_Structure::AddGroup ()
303 {
304   // Create new group
305   OpenGl_Group *g = new OpenGl_Group;
306   myGroups.Append(g);
307   return g;
308 }
309
310 /*----------------------------------------------------------------------*/
311
312 void OpenGl_Structure::RemoveGroup (const Handle(OpenGl_Context)& theGlCtx,
313                                     const OpenGl_Group*           theGroup)
314 {
315   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
316   {
317     // Check for the given group
318     if (anIter.Value() == theGroup)
319     {
320       // Delete object
321       OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
322       myGroups.Remove (anIter);
323       return;
324     }
325   }
326 }
327
328 /*----------------------------------------------------------------------*/
329
330 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
331 {
332   // Release groups
333   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
334   {
335     // Delete objects
336     OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
337   }
338   myGroups.Clear();
339 }
340
341 /*----------------------------------------------------------------------*/
342
343 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
344 {
345   // Process the structure only if visible
346   if ( myNamedStatus & OPENGL_NS_HIDE )
347     return;
348
349   // Render named status
350   const Standard_Integer named_status = AWorkspace->NamedStatus;
351   AWorkspace->NamedStatus |= myNamedStatus;
352
353   // Is rendering in ADD or IMMEDIATE mode?
354   const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
355
356   // Apply local transformation
357   GLint matrix_mode = 0;
358   const OpenGl_Matrix *local_trsf = NULL;
359   if (myTransformation)
360   {
361     if (isImmediate)
362     {
363       float mat16[16];
364       call_util_transpose_mat (mat16, myTransformation->mat);
365       glGetIntegerv (GL_MATRIX_MODE, &matrix_mode);
366       glMatrixMode (GL_MODELVIEW);
367       glPushMatrix ();
368       glScalef (1.F, 1.F, 1.F);
369       glMultMatrixf (mat16);
370     }
371     else
372     {
373       glMatrixMode (GL_MODELVIEW);
374       glPushMatrix();
375
376       local_trsf = AWorkspace->SetStructureMatrix(myTransformation);
377     }
378   }
379
380   // Apply transform persistence
381   const TEL_TRANSFORM_PERSISTENCE *trans_pers = NULL;
382   if ( myTransPers && myTransPers->mode != 0 )
383   {
384     trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence( myTransPers );
385   }
386
387   // Apply aspects
388   const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine(Standard_False);
389   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace(Standard_False);
390   const OpenGl_AspectMarker *aspect_marker = AWorkspace->AspectMarker(Standard_False);
391   const OpenGl_AspectText *aspect_text = AWorkspace->AspectText(Standard_False);
392   if (myAspectLine)
393     AWorkspace->SetAspectLine(myAspectLine);
394   if (myAspectFace)
395     AWorkspace->SetAspectFace(myAspectFace);
396   if (myAspectMarker)
397     AWorkspace->SetAspectMarker(myAspectMarker);
398   if (myAspectText)
399     AWorkspace->SetAspectText(myAspectText);
400
401   // Apply highlight box
402   if (myHighlightBox)
403     myHighlightBox->Render( AWorkspace );
404
405   // Apply highlight color
406   const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
407   if (myHighlightColor)
408     AWorkspace->HighlightColor = myHighlightColor;
409
410   // Render connected structures
411   OpenGl_ListOfStructure::Iterator its(myConnected);
412   while (its.More())
413   {
414     its.Value()->Render(AWorkspace);
415     its.Next();
416   }
417
418   // Render groups
419   OpenGl_ListOfGroup::Iterator itg(myGroups);
420   while (itg.More())
421   {
422     itg.Value()->Render(AWorkspace);
423     itg.Next();
424   }
425
426   // Restore highlight color
427   AWorkspace->HighlightColor = highlight_color;
428
429   // Restore aspects
430   AWorkspace->SetAspectLine(aspect_line);
431   AWorkspace->SetAspectFace(aspect_face);
432   AWorkspace->SetAspectMarker(aspect_marker);
433   AWorkspace->SetAspectText(aspect_text);
434
435   // Restore transform persistence
436   if ( myTransPers && myTransPers->mode != 0 )
437   {
438     AWorkspace->ActiveView()->BeginTransformPersistence( trans_pers );
439   }
440
441   // Restore local transformation
442   if (myTransformation)
443   {
444     if (isImmediate)
445     {
446       glPopMatrix ();
447       glMatrixMode (matrix_mode);
448     }
449     else
450     {
451       AWorkspace->SetStructureMatrix(local_trsf);
452
453       glMatrixMode (GL_MODELVIEW);
454       glPopMatrix();
455     }
456   }
457
458   // Restore named status
459   AWorkspace->NamedStatus = named_status;
460 }
461
462 // =======================================================================
463 // function : Release
464 // purpose  :
465 // =======================================================================
466 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
467 {
468   // Release groups
469   Clear (theGlCtx);
470   OpenGl_Element::Destroy (theGlCtx, myAspectLine);
471   OpenGl_Element::Destroy (theGlCtx, myAspectFace);
472   OpenGl_Element::Destroy (theGlCtx, myAspectMarker);
473   OpenGl_Element::Destroy (theGlCtx, myAspectText);
474   ClearHighlightColor (theGlCtx);
475 }
476
477 // =======================================================================
478 // function : ReleaseGlResources
479 // purpose  :
480 // =======================================================================
481 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
482 {
483   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
484   {
485     OpenGl_Group* aGroup = const_cast<OpenGl_Group*& > (anIter.ChangeValue());
486     if (aGroup != NULL)
487     {
488       aGroup->Release (theGlCtx);
489     }
490   }
491   if (myAspectLine != NULL)
492   {
493     myAspectLine->Release (theGlCtx);
494   }
495   if (myAspectFace != NULL)
496   {
497     myAspectFace->Release (theGlCtx);
498   }
499   if (myAspectMarker != NULL)
500   {
501     myAspectMarker->Release (theGlCtx);
502   }
503   if (myAspectText != NULL)
504   {
505     myAspectText->Release (theGlCtx);
506   }
507   if (myHighlightBox != NULL)
508   {
509     myHighlightBox->Release (theGlCtx);
510   }
511 }
512
513 //=======================================================================
514 //function : SetZLayer
515 //purpose  :
516 //=======================================================================
517
518 void OpenGl_Structure::SetZLayer (const Standard_Integer theLayerIndex)
519 {
520   myZLayer = theLayerIndex;
521 }
522
523 //=======================================================================
524 //function : GetZLayer
525 //purpose  :
526 //=======================================================================
527
528 Standard_Integer OpenGl_Structure::GetZLayer () const
529 {
530   return myZLayer;
531 }