0023428: Extend OpenGl_Context to use Geometry Shaders extension
[occt.git] / src / OpenGl / OpenGl_Workspace_3.cxx
1 // Created on: 2011-09-20
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 <math.h>
22 #include <stdio.h>
23
24 #include <OpenGl_GlCore11.hxx>
25 #include <OpenGl_Context.hxx>
26 #include <OpenGl_telem_util.hxx>
27 #include <OpenGl_AspectLine.hxx>
28 #include <OpenGl_Structure.hxx>
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #ifdef HAVE_GL2PS
35   #include <gl2ps.h>
36 #endif
37
38 /*----------------------------------------------------------------------*/
39 /*
40 * Prototypes Private functions
41 */
42
43 static void call_util_transform_pt (float *x, float *y, float *z);
44 static void call_util_transpose_mat (float tmat[16], float mat[4][4]);
45
46 /*----------------------------------------------------------------------*/
47 /* 
48 * Variables statiques
49 */
50
51 static int openglNumberOfPoints = 0;
52
53 static int myImmediateMatIsIdentity = 1;
54
55 static int partial = -1;  /* -1 init, 0 complete, 1 partielle */
56
57 static float xm, ym, zm, XM, YM, ZM;
58
59 static float myImmediateMat[4][4] = {
60   {1., 0., 0., 0.},
61   {0., 1., 0., 0.},
62   {0., 0., 1., 0.},
63   {0., 0., 0., 1.},
64 };
65
66 /*----------------------------------------------------------------------*/
67 /*  Mode Ajout              */
68 /*----------------------------------------------------------------------*/
69
70 //call_togl_begin_ajout_mode
71 Standard_Boolean OpenGl_Workspace::BeginAddMode ()
72 {
73   if (!Activate())
74     return Standard_False;
75
76   NamedStatus |= OPENGL_NS_ADD;
77
78   MakeFrontAndBackBufCurrent();
79
80   //TsmPushAttri();
81
82   return Standard_True;
83 }
84
85 /*----------------------------------------------------------------------*/
86
87 //call_togl_end_ajout_mode
88 void OpenGl_Workspace::EndAddMode ()
89 {
90   if (NamedStatus & OPENGL_NS_ADD)
91   {
92     OpenGl_Workspace::MakeBackBufCurrent();
93
94     // Clear add mode flag
95     NamedStatus &= ~OPENGL_NS_ADD;
96   }
97
98   myImmediateMatIsIdentity = 1;
99
100   /* FMN necessaire pour l'affichage sur WNT */
101   glFlush();
102
103   //TsmPopAttri();
104 }
105
106 /*----------------------------------------------------------------------*/
107 /*  Mode Transient              */
108 /*----------------------------------------------------------------------*/
109
110 //call_togl_clear_immediat_mode
111 void OpenGl_Workspace::ClearImmediatMode (const Graphic3d_CView& ACView, const Standard_Boolean AFlush)
112 {
113   if ( myIsTransientOpen )
114     EndImmediatMode();
115
116   if (!Activate()) return;
117
118   if ( !myBackBufferRestored )
119   {
120     EraseAnimation();
121
122     Redraw1(ACView,*((CALL_DEF_LAYER *)ACView.ptrUnderLayer),*((CALL_DEF_LAYER *)ACView.ptrOverLayer),AFlush);
123
124     // After a redraw,
125     // Made the back identical to the front buffer.
126     // Always perform full copy (partial update optimization is useless on mordern hardware)!
127     if (myRetainMode)
128       CopyBuffers (ACView.ViewId, 1 /* GL_FRONT -> GL_BACK */, xm, ym, zm, XM, YM, ZM, 0);
129
130     myBackBufferRestored = Standard_True;
131   }
132   else if ( partial >= 0 )
133   {
134     // Restore pixels from the back buffer.
135     // Always perform full copy (partial update optimization is useless on mordern hardware)!
136     CopyBuffers (ACView.ViewId, 0 /* GL_BACK -> GL_FRONT */, xm, ym, zm, XM, YM, ZM, 0);
137   }
138
139   if (myTransientList)
140   {
141     /* Clear current list contents */
142     glNewList( (GLuint) myTransientList, GL_COMPILE_AND_EXECUTE);
143     glEndList();
144   }
145   partial = -1;
146   XM = YM = ZM = (float ) shortrealfirst ();
147   xm = ym = zm = (float ) shortreallast ();
148 }
149
150 /*----------------------------------------------------------------------*/
151
152 //call_togl_redraw_immediat_mode
153 void OpenGl_Workspace::RedrawImmediatMode ()
154 {
155   if (myRetainMode)
156   {
157     if (myTransientList)
158     {
159       MakeFrontBufCurrent();
160       glDisable(GL_LIGHTING);
161       glCallList((GLuint) myTransientList);
162       /* FMN necessaire pour l'affichage sur WNT */
163       glFlush();
164       MakeBackBufCurrent();
165     } 
166   }
167 }
168
169 /*----------------------------------------------------------------------*/
170
171 //call_togl_begin_immediat_mode
172 Standard_Boolean OpenGl_Workspace::BeginImmediatMode (const Graphic3d_CView& ACView, const Standard_Boolean UseDepthTest, const Standard_Boolean RetainMode)
173 {
174   if (!Activate())
175     return Standard_False;
176
177   OpenGl_Workspace::ClearImmediatMode(ACView,1);
178
179   NamedStatus |= OPENGL_NS_IMMEDIATE;
180   myRetainMode = RetainMode;
181
182   MakeFrontBufCurrent();
183
184   //TsmPushAttri();
185
186   if ( myRetainMode )
187   {
188     GLuint listid = (GLuint) myTransientList;
189     if (!listid)
190       listid = glGenLists(1);
191     if (!listid) return Standard_False;
192
193     glNewList(listid, GL_COMPILE_AND_EXECUTE);
194     myTransientList = listid;
195     myIsTransientOpen = Standard_True;
196   }
197
198   if ( UseDepthTest )
199     glEnable(GL_DEPTH_TEST);
200   else
201     glDisable(GL_DEPTH_TEST);
202
203   return Standard_True;
204 }
205
206 /*----------------------------------------------------------------------*/
207
208 //call_togl_end_immediat_mode
209 void OpenGl_Workspace::EndImmediatMode ()
210 {
211   if (NamedStatus & OPENGL_NS_IMMEDIATE)
212   {
213     if (myIsTransientOpen)
214     {
215       glEndList();
216       myIsTransientOpen = Standard_False;
217     }
218     MakeBackBufCurrent();
219
220     // Clear immediate mode flag
221     NamedStatus &= ~OPENGL_NS_IMMEDIATE;
222   }
223
224   // Ajout CAL : pour voir quelque chose avant le prochain begin_immediat_mode
225   glFinish ();
226
227   myImmediateMatIsIdentity = 1;
228
229   //TsmPopAttri();
230 }
231
232 /*----------------------------------------------------------------------*/
233
234 //call_togl_transform
235 void OpenGl_Workspace::Transform (const TColStd_Array2OfReal& AMatrix, const Graphic3d_TypeOfComposition AType)
236 {
237   //call_togl_transform in OpenGl_togl_begin_immediat_mode.cxx
238   const Standard_Integer lr = AMatrix.LowerRow ();
239   const Standard_Integer lc = AMatrix.LowerCol ();
240
241   Standard_Integer i, j;
242   if ((AType == Graphic3d_TOC_REPLACE) || myImmediateMatIsIdentity)
243   {
244     for (i=0; i<4; i++)
245       for (j=0; j<4; j++)
246         myImmediateMat[i][j] = float (AMatrix (i+lr, j+lc));
247   }
248   else
249   {
250     float theMatrix[4][4];
251     for (i=0; i<4; i++)
252       for (j=0; j<4; j++)
253         theMatrix[i][j] = float (AMatrix (i+lr, j+lc));
254
255     TelMultiplymat3 (myImmediateMat, myImmediateMat, theMatrix);
256   }
257
258   myImmediateMatIsIdentity = 1;
259   for (i = 0; i < 4; i++)
260     for (j = 0; j < 4; j++)
261       if (myImmediateMat[i][j] != (i == j? 1. : 0.))
262       {
263         myImmediateMatIsIdentity = 0;
264         return;
265       }
266 }
267
268 /*----------------------------------------------------------------------*/
269
270 //call_togl_begin_polyline
271 void OpenGl_Workspace::BeginPolyline ()
272 {
273   if (NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE))
274   {
275     openglNumberOfPoints = 0;
276     glDisable(GL_LIGHTING);
277     glBegin(GL_LINE_STRIP);
278   }
279 }
280
281 /*----------------------------------------------------------------------*/
282
283 //call_togl_end_polyline
284 void OpenGl_Workspace::EndPolyline ()
285 {
286   if (NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE))
287     glEnd();
288 }
289
290 /*----------------------------------------------------------------------*/
291
292 //call_togl_draw
293 void OpenGl_Workspace::Draw (const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z)
294 {
295   if (NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE))
296   {
297     openglNumberOfPoints++;
298     float x = X, y = Y, z = Z;
299     if (!myImmediateMatIsIdentity)
300       call_util_transform_pt (&x, &y, &z);
301     if (x > XM) XM = x;
302     if (y > YM) YM = y;
303     if (z > ZM) ZM = z;
304     if (x < xm) xm = x;
305     if (y < ym) ym = y;
306     if (z < zm) zm = z;
307     glVertex3f (x, y, z);
308     partial = 1;
309   }
310 }
311
312 /*----------------------------------------------------------------------*/
313
314 //call_togl_move
315 void OpenGl_Workspace::Move (const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z)
316 {
317   if (NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE))
318   {
319     if (openglNumberOfPoints != 0)
320     {
321       OpenGl_Workspace::EndPolyline();
322       OpenGl_Workspace::BeginPolyline();
323     }
324     OpenGl_Workspace::Draw(X,Y,Z);
325   }
326 }
327
328 /*----------------------------------------------------------------------*/
329
330 //call_togl_set_linecolor
331 void OpenGl_Workspace::SetLineColor (const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B) 
332 {
333   if (NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE))
334   {
335     GLfloat color[3];
336     color[0] = R;
337     color[1] = G;
338     color[2] = B;
339     glColor3fv(color);
340   }
341 }
342
343 /*----------------------------------------------------------------------*/
344
345 //call_togl_set_linetype
346 void OpenGl_Workspace::SetLineType (const Standard_Integer Type)
347 {
348   if (NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE))
349   {
350     myDisplay->SetTypeOfLine((Aspect_TypeOfLine)Type);
351   }
352 }
353
354 /*----------------------------------------------------------------------*/
355
356 //call_togl_set_linewidth
357 void OpenGl_Workspace::SetLineWidth (const Standard_ShortReal Width)
358 {
359   if (NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE))
360   {
361     glLineWidth( (GLfloat)Width );
362 #ifdef HAVE_GL2PS
363     gl2psLineWidth( (GLfloat)Width );
364 #endif
365   }
366 }
367
368 /*----------------------------------------------------------------------*/
369
370 //call_togl_draw_structure
371 void OpenGl_Workspace::DrawStructure (const OpenGl_Structure *AStructure)
372 {
373   if (NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE))
374   {
375     float mat16[16];
376     GLint mode1;
377
378     //TsmPushAttri();
379
380     /* mise en place de la matrice de transformation du trace transient */
381     if (!myImmediateMatIsIdentity)
382     {
383       call_util_transpose_mat (mat16, myImmediateMat);
384       glGetIntegerv (GL_MATRIX_MODE, &mode1);
385       glMatrixMode (GL_MODELVIEW);
386       glPushMatrix ();
387       glScalef (1.F, 1.F, 1.F);
388       glMultMatrixf (mat16);
389     }
390
391     // Render structure
392     Handle(OpenGl_Workspace) aWS(this);
393     AStructure->Render(aWS);
394
395     //TsmPopAttri();
396
397     if (!myImmediateMatIsIdentity)
398     {
399       glPopMatrix ();
400       glMatrixMode (mode1);
401     }
402   }
403 }
404
405 /*----------------------------------------------------------------------*/
406
407 //call_togl_set_minmax
408 void OpenGl_Workspace::SetMinMax (const Standard_ShortReal X1, const Standard_ShortReal Y1, const Standard_ShortReal Z1, const Standard_ShortReal X2, const Standard_ShortReal Y2, const Standard_ShortReal Z2)
409 {
410   if ((X1 > shortreallast ()) || (Y1 > shortreallast ()) || (Z1 > shortreallast ()) ||
411       (X2 > shortreallast ()) || (Y2 > shortreallast ()) || (Z2 > shortreallast ()) ||
412       (X1 < shortrealfirst ()) || (Y1 < shortrealfirst ()) || (Z1 < shortrealfirst ()) ||
413       (X2 < shortrealfirst ()) || (Y2 < shortrealfirst ()) || (Z2 < shortrealfirst ()))
414   {
415     XM = YM = ZM = (float ) shortreallast ();
416     xm = ym = zm = (float ) shortrealfirst ();
417     partial = 0;
418   }
419   else
420   {
421     float x1=X1,y1=Y1,z1=Z1,x2=X2,y2=Y2,z2=Z2;
422     if (!myImmediateMatIsIdentity)
423     {
424       call_util_transform_pt (&x1, &y1, &z1);
425       call_util_transform_pt (&x2, &y2, &z2);
426     }
427     if (x1 > XM) XM = x1;
428     if (x1 < xm) xm = x1;
429     if (y1 > YM) YM = y1;
430     if (y1 < ym) ym = y1;
431     if (z1 > ZM) ZM = z1;
432     if (z1 < zm) zm = z1;
433
434     if (x2 > XM) XM = x2;
435     if (x2 < xm) xm = x2;
436     if (y2 > YM) YM = y2;
437     if (y2 < ym) ym = y2;
438     if (z2 > ZM) ZM = z2;
439     if (z2 < zm) zm = z2;
440     if (partial != 0) partial = 1;
441   }
442 }
443
444 /*----------------------------------------------------------------------*/
445 /*
446 * Private functions
447 */
448
449 /*----------------------------------------------------------------------*/
450 /*
451 Transform the point pt
452 */
453 static void call_util_transform_pt ( float *x, float *y, float *z )
454 {
455   float tpt[4], pt[4];
456   pt[0] = *x, pt[1] = *y, pt[2] = *z, pt[3] = 1.0;
457
458   int i, j;
459   for (i = 0; i < 4; i++)
460   {
461     float sum = 0.;
462     for (j = 0; j < 4; j++)
463       sum += myImmediateMat[i][j] * pt[j];
464     tpt[i] = sum;
465   }
466
467   *x = tpt[0], *y = tpt[1], *z = tpt[2];
468 }
469
470 /*----------------------------------------------------------------------*/
471 /*
472 void call_util_transpose_mat (tmat, mat)
473 float tmat[16];
474 float mat[4][4];
475
476 Transpose mat and returns tmat.
477 */
478
479 static void call_util_transpose_mat (float tmat[16], float mat[4][4])
480 {
481   int i, j;
482
483   for (i=0; i<4; i++)
484     for (j=0; j<4; j++)
485       tmat[j*4+i] = mat[i][j];
486 }