0026128: Visualization, TKOpenGl - fix misprint in external GLX context initialization
[occt.git] / src / OpenGl / OpenGl_View.cxx
1 // Created on: 2011-09-20
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 <NCollection_Mat4.hxx>
17
18 #include <OpenGl_Context.hxx>
19 #include <OpenGl_GlCore11.hxx>
20 #include <OpenGl_GraduatedTrihedron.hxx>
21 #include <OpenGl_GraphicDriver.hxx>
22 #include <OpenGl_ShaderManager.hxx>
23 #include <OpenGl_Texture.hxx>
24 #include <OpenGl_Trihedron.hxx>
25 #include <OpenGl_transform_persistence.hxx>
26 #include <OpenGl_View.hxx>
27 #include <OpenGl_Utils.hxx>
28 #include <OpenGl_Workspace.hxx>
29
30 #include <Graphic3d_TextureEnv.hxx>
31 #include <Graphic3d_Mat4d.hxx>
32
33 IMPLEMENT_STANDARD_HANDLE(OpenGl_View,MMgt_TShared)
34 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,MMgt_TShared)
35
36 /*----------------------------------------------------------------------*/
37
38 static const Tmatrix3 myDefaultMatrix = { { 1.F, 0.F, 0.F, 0.F }, { 0.F, 1.F, 0.F, 0.F }, { 0.F, 0.F, 1.F, 0.F }, { 0.F, 0.F, 0.F, 1.F } };
39 static const OPENGL_ZCLIP myDefaultZClip = { { Standard_True, 0.F }, { Standard_True, 1.F } };
40
41 static const OPENGL_FOG myDefaultFog = { Standard_False, 0.F, 1.F, { { 0.F, 0.F, 0.F, 1.F } } };
42 static const TEL_TRANSFORM_PERSISTENCE myDefaultTransPers = { 0, 0.F, 0.F, 0.F };
43 static const GLdouble THE_IDENTITY_MATRIX[4][4] =
44 {
45   {1.0, 0.0, 0.0, 0.0},
46   {0.0, 1.0, 0.0, 0.0},
47   {0.0, 0.0, 1.0, 0.0},
48   {0.0, 0.0, 0.0, 1.0}
49 };
50
51 /*----------------------------------------------------------------------*/
52
53 OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext,
54                           OpenGl_StateCounter*       theCounter)
55 : mySurfaceDetail(Visual3d_TOD_ALL),
56   myBackfacing(0),
57   //shield_indicator = TOn,
58   //shield_colour = { { 0.F, 0.F, 0.F, 1.F } },
59   //border_indicator = TOff,
60   //border_colour = { { 0.F, 0.F, 0.F, 1.F } },
61   //active_status = TOn,
62   myZClip(myDefaultZClip),
63   myCamera(AContext.Camera),
64   myFog(myDefaultFog),
65   myToShowTrihedron (false),
66   myToShowGradTrihedron (false),
67   myVisualization(AContext.Visualization),
68   myShadingModel ((Visual3d_TypeOfModel )AContext.Model),
69   myAntiAliasing(Standard_False),
70   myTransPers(&myDefaultTransPers),
71   myIsTransPers(Standard_False),
72   myProjectionState (0),
73   myModelViewState (0),
74   myStateCounter (theCounter),
75   myLastLightSourceState (0, 0),
76   myTextureParams   (new OpenGl_AspectFace()),
77   myBgGradientArray (new OpenGl_BackgroundArray (Graphic3d_TOB_GRADIENT)),
78   myBgTextureArray  (new OpenGl_BackgroundArray (Graphic3d_TOB_TEXTURE)),
79   // ray-tracing fields initialization
80   myRaytraceInitStatus (OpenGl_RT_NONE),
81   myIsRaytraceDataValid (Standard_False),
82   myIsRaytraceWarnTextures (Standard_False),
83   myToUpdateEnvironmentMap (Standard_False),
84   myLayersModificationStatus (0)
85 {
86   myCurrLightSourceState = myStateCounter->Increment();
87 }
88
89 /*----------------------------------------------------------------------*/
90
91 OpenGl_View::~OpenGl_View()
92 {
93   ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
94   OpenGl_Element::Destroy (NULL, myBgGradientArray);
95   OpenGl_Element::Destroy (NULL, myBgTextureArray);
96   OpenGl_Element::Destroy (NULL, myTextureParams);
97 }
98
99 void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
100 {
101   myTrihedron         .Release (theCtx.operator->());
102   myGraduatedTrihedron.Release (theCtx.operator->());
103
104   if (!myTextureEnv.IsNull())
105   {
106     theCtx->DelayedRelease (myTextureEnv);
107     myTextureEnv.Nullify();
108   }
109
110   if (myTextureParams != NULL)
111   {
112     myTextureParams->Release (theCtx.operator->());
113   }
114   if (myBgGradientArray != NULL)
115   {
116     myBgGradientArray->Release (theCtx.operator->());
117   }
118   if (myBgTextureArray != NULL)
119   {
120     myBgTextureArray->Release (theCtx.operator->());
121   }
122
123   releaseRaytraceResources (theCtx);
124 }
125
126 void OpenGl_View::SetTextureEnv (const Handle(OpenGl_Context)&       theCtx,
127                                  const Handle(Graphic3d_TextureEnv)& theTexture)
128 {
129   if (!myTextureEnv.IsNull())
130   {
131     theCtx->DelayedRelease (myTextureEnv);
132     myTextureEnv.Nullify();
133   }
134
135   if (theTexture.IsNull())
136   {
137     return;
138   }
139
140   myTextureEnv = new OpenGl_Texture (theTexture->GetParams());
141   Handle(Image_PixMap) anImage = theTexture->GetImage();
142   if (!anImage.IsNull())
143     myTextureEnv->Init (theCtx, *anImage.operator->(), theTexture->Type());
144
145   myToUpdateEnvironmentMap = Standard_True;
146 }
147
148 void OpenGl_View::SetSurfaceDetail (const Visual3d_TypeOfSurfaceDetail theMode)
149 {
150   mySurfaceDetail = theMode;
151
152   myToUpdateEnvironmentMap = Standard_True;
153 }
154
155 // =======================================================================
156 // function : SetBackfacing
157 // purpose  :
158 // =======================================================================
159 void OpenGl_View::SetBackfacing (const Standard_Integer theMode)
160 {
161   myBackfacing = theMode;
162 }
163
164 // =======================================================================
165 // function : SetLights
166 // purpose  :
167 // =======================================================================
168 void OpenGl_View::SetLights (const CALL_DEF_VIEWCONTEXT& theViewCtx)
169 {
170   myLights.Clear();
171   for (Standard_Integer aLightIt = 0; aLightIt < theViewCtx.NbActiveLight; ++aLightIt)
172   {
173     myLights.Append (theViewCtx.ActiveLight[aLightIt]);
174   }
175   myCurrLightSourceState = myStateCounter->Increment();
176 }
177
178 /*----------------------------------------------------------------------*/
179
180 //call_togl_setvisualisation
181 void OpenGl_View::SetVisualisation (const CALL_DEF_VIEWCONTEXT &AContext)
182 {
183   myVisualization = AContext.Visualization;
184   myShadingModel  = (Visual3d_TypeOfModel )AContext.Model;
185 }
186
187 /*----------------------------------------------------------------------*/
188
189 //call_togl_cliplimit
190 void OpenGl_View::SetClipLimit (const Graphic3d_CView& theCView)
191 {
192   myZClip.Back.Limit = theCView.Context.ZClipBackPlane;
193   myZClip.Front.Limit = theCView.Context.ZClipFrontPlane;
194
195   myZClip.Back.IsOn  = (theCView.Context.BackZClipping  != 0);
196   myZClip.Front.IsOn = (theCView.Context.FrontZClipping != 0);
197 }
198
199 /*----------------------------------------------------------------------*/
200
201 void OpenGl_View::SetFog (const Graphic3d_CView& theCView,
202                           const Standard_Boolean theFlag)
203 {
204   if (!theFlag)
205   {
206     myFog.IsOn = Standard_False;
207   }
208   else
209   {
210     myFog.IsOn = Standard_True;
211
212     myFog.Front = theCView.Context.DepthFrontPlane;
213     myFog.Back = theCView.Context.DepthBackPlane;
214
215     myFog.Color.rgb[0] = theCView.DefWindow.Background.r;
216     myFog.Color.rgb[1] = theCView.DefWindow.Background.g;
217     myFog.Color.rgb[2] = theCView.DefWindow.Background.b;
218     myFog.Color.rgb[3] = 1.0f;
219   }
220 }
221
222 /*----------------------------------------------------------------------*/
223
224 void OpenGl_View::TriedronDisplay (const Aspect_TypeOfTriedronPosition thePosition,
225                                    const Quantity_NameOfColor          theColor,
226                                    const Standard_Real                 theScale,
227                                    const Standard_Boolean              theAsWireframe)
228 {
229   myToShowTrihedron = true;
230   myTrihedron.SetWireframe   (theAsWireframe);
231   myTrihedron.SetPosition    (thePosition);
232   myTrihedron.SetScale       (theScale);
233   myTrihedron.SetLabelsColor (theColor);
234 }
235
236 /*----------------------------------------------------------------------*/
237
238 void OpenGl_View::TriedronErase (const Handle(OpenGl_Context)& theCtx)
239 {
240   myToShowTrihedron = false;
241   myTrihedron.Release (theCtx.operator->());
242 }
243
244 /*----------------------------------------------------------------------*/
245
246 void OpenGl_View::GraduatedTrihedronDisplay (const Handle(OpenGl_Context)&       theCtx,
247                                              const Graphic3d_GraduatedTrihedron& theData)
248 {
249   myToShowGradTrihedron = true;
250   myGraduatedTrihedron.SetValues (theCtx, theData);
251 }
252
253 /*----------------------------------------------------------------------*/
254
255 void OpenGl_View::GraduatedTrihedronErase (const Handle(OpenGl_Context)& theCtx)
256 {
257   myToShowGradTrihedron = false;
258   myGraduatedTrihedron.Release (theCtx.operator->());
259 }
260
261 /*----------------------------------------------------------------------*/
262
263 //transform_persistence_end
264 void OpenGl_View::EndTransformPersistence(const Handle(OpenGl_Context)& theCtx)
265 {
266   if (myIsTransPers)
267   {
268     theCtx->WorldViewState.Pop();
269     theCtx->ProjectionState.Pop();
270
271     theCtx->ApplyProjectionMatrix();
272     theCtx->ApplyWorldViewMatrix();
273
274     myIsTransPers = Standard_False;
275   }
276 }
277
278 /*----------------------------------------------------------------------*/
279
280 //transform_persistence_begin
281 const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const Handle(OpenGl_Context)& theCtx,
282                                                                          const TEL_TRANSFORM_PERSISTENCE* theTransPers,
283                                                                          Standard_Integer theWidth,
284                                                                          Standard_Integer theHeight)
285 {
286   const TEL_TRANSFORM_PERSISTENCE* aTransPersPrev = myTransPers;
287   myTransPers = theTransPers;
288   if (theTransPers->mode == 0)
289   {
290     EndTransformPersistence (theCtx);
291     return aTransPersPrev;
292   }
293
294   GLint aViewport[4];
295   OpenGl_Mat4d aModelMatrix, aProjMatrix;
296   theCtx->core11fwd->glGetIntegerv (GL_VIEWPORT, aViewport);
297   aModelMatrix.Convert (theCtx->ModelWorldState.Current() * theCtx->WorldViewState.Current());
298   aProjMatrix .Convert (theCtx->ProjectionState.Current());
299
300   const GLdouble aViewportW = (GLdouble )aViewport[2];
301   const GLdouble aViewportH = (GLdouble )aViewport[3];
302
303   if (myIsTransPers)
304   {
305     // pop matrix stack - it will be overridden later
306     theCtx->WorldViewState.Pop();
307     theCtx->ProjectionState.Pop();
308   }
309   else
310   {
311     myIsTransPers = Standard_True;
312   }
313
314   if (theTransPers->mode & TPF_2D)
315   {
316     GLfloat aLeft   = -static_cast<GLfloat> (theWidth  / 2);
317     GLfloat aRight  =  static_cast<GLfloat> (theWidth  / 2);
318     GLfloat aBottom = -static_cast<GLfloat> (theHeight / 2);
319     GLfloat aTop    =  static_cast<GLfloat> (theHeight / 2);
320     GLfloat aGap    =  static_cast<GLfloat> (theTransPers->pointZ);
321     if (theTransPers->pointX > 0)
322     {
323       aLeft  -= static_cast<GLfloat> (theWidth / 2) - aGap;
324       aRight -= static_cast<GLfloat> (theWidth / 2) - aGap;
325     }
326     else if (theTransPers->pointX < 0)
327     {
328       aLeft  += static_cast<GLfloat> (theWidth / 2) - aGap;
329       aRight += static_cast<GLfloat> (theWidth / 2) - aGap;
330     }
331     if (theTransPers->pointY > 0)
332     {
333       aBottom -= static_cast<GLfloat> (theHeight / 2) - aGap;
334       aTop    -= static_cast<GLfloat> (theHeight / 2) - aGap;
335     }
336     else if (theTransPers->pointY < 0)
337     {
338       aBottom += static_cast<GLfloat> (theHeight / 2) - aGap;
339       aTop    += static_cast<GLfloat> (theHeight / 2) - aGap;
340     }
341     if (theTransPers->mode == TPF_2D_ISTOPDOWN)
342     {
343       const GLfloat aTemp = aTop;
344       aTop    = aBottom;
345       aBottom = aTemp;
346     }
347
348     OpenGl_Mat4 aProjectMat;
349     OpenGl_Utils::Ortho2D<Standard_ShortReal> (aProjectMat,
350                                                aLeft, aRight,
351                                                aBottom, aTop);
352
353     theCtx->WorldViewState.Push();
354     theCtx->ProjectionState.Push();
355
356     theCtx->WorldViewState.SetIdentity();
357     theCtx->ProjectionState.SetCurrent (aProjectMat);
358
359     theCtx->ApplyWorldViewMatrix();
360     theCtx->ApplyProjectionMatrix();
361     return aTransPersPrev;
362   }
363
364   // push matrices into stack and reset them
365   theCtx->WorldViewState.Push();
366   theCtx->ProjectionState.Push();
367
368   // get the window's (fixed) coordinates for theTransPers->point before matrixes modifications
369   GLdouble aWinX = 0.0, aWinY = 0.0, aWinZ = 0.0;
370   if ((theTransPers->mode & TPF_PAN) != TPF_PAN)
371   {
372     OpenGl_Utils::Project<Standard_Real> (theTransPers->pointX,
373                                           theTransPers->pointY,
374                                           theTransPers->pointZ,
375                                           aModelMatrix,
376                                           aProjMatrix,
377                                           aViewport,
378                                           aWinX,
379                                           aWinY,
380                                           aWinZ);
381   }
382
383   // prevent zooming
384   if ((theTransPers->mode & TPF_ZOOM)
385    || (theTransPers->mode == TPF_TRIEDRON))
386   {
387     // compute fixed-zoom multiplier
388     // actually function works ugly with TelPerspective!
389     const GLdouble aDet2 = 0.002 / (aViewportW > aViewportH ? aProjMatrix.GetValue (1, 1) : aProjMatrix.GetValue (0, 0));
390     aProjMatrix.ChangeValue (0, 0) *= aDet2;
391     aProjMatrix.ChangeValue (1, 1) *= aDet2;
392     aProjMatrix.ChangeValue (2, 2) *= aDet2;
393   }
394
395   // prevent translation - annulate translate matrix
396   if ((theTransPers->mode & TPF_PAN)
397    || (theTransPers->mode == TPF_TRIEDRON))
398   {
399     aModelMatrix.SetValue (0, 3, 0.0);
400     aModelMatrix.SetValue (1, 3, 0.0);
401     aModelMatrix.SetValue (2, 3, 0.0);
402     aProjMatrix .SetValue (0, 3, 0.0);
403     aProjMatrix .SetValue (1, 3, 0.0);
404     aProjMatrix .SetValue (2, 3, 0.0);
405   }
406
407   // prevent scaling-on-axis
408   if (theTransPers->mode & TPF_ZOOM)
409   {
410     const gp_Pnt anAxialScale = myCamera->AxialScale();
411     const double aScaleX = anAxialScale.X();
412     const double aScaleY = anAxialScale.Y();
413     const double aScaleZ = anAxialScale.Z();
414     for (int i = 0; i < 3; ++i)
415     {
416       aModelMatrix.ChangeValue (0, i) /= aScaleX;
417       aModelMatrix.ChangeValue (1, i) /= aScaleY;
418       aModelMatrix.ChangeValue (2, i) /= aScaleZ;
419     }
420   }
421
422   // prevent rotating - annulate rotate matrix
423   if (theTransPers->mode & TPF_ROTATE)
424   {
425     aModelMatrix.SetValue (0, 0, 1.0);
426     aModelMatrix.SetValue (1, 1, 1.0);
427     aModelMatrix.SetValue (2, 2, 1.0);
428
429     aModelMatrix.SetValue (1, 0, 0.0);
430     aModelMatrix.SetValue (2, 0, 0.0);
431     aModelMatrix.SetValue (0, 1, 0.0);
432     aModelMatrix.SetValue (2, 1, 0.0);
433     aModelMatrix.SetValue (0, 2, 0.0);
434     aModelMatrix.SetValue (1, 2, 0.0);
435   }
436
437   // load computed matrices
438   theCtx->ModelWorldState.SetIdentity();
439   theCtx->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
440   theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjMatrix);
441
442   if (theTransPers->mode == TPF_TRIEDRON)
443   {
444     // move to the window corner
445     if (theTransPers->pointX != 0.0
446      && theTransPers->pointY != 0.0)
447     {
448       GLdouble aW1, aH1, aW2, aH2, aDummy;
449
450       OpenGl_Mat4d anIdentity;
451
452       OpenGl_Utils::UnProject<Standard_Real> (0.5 * aViewportW,
453                                               0.5 * aViewportH,
454                                               0.0,
455                                               anIdentity,
456                                               aProjMatrix,
457                                               aViewport,
458                                               aW1,
459                                               aH1,
460                                               aDummy);
461
462       OpenGl_Utils::UnProject<Standard_Real> (-0.5 * aViewportW,
463                                               -0.5 * aViewportH,
464                                               0.0,
465                                               anIdentity,
466                                               aProjMatrix,
467                                               aViewport,
468                                               aW2,
469                                               aH2,
470                                               aDummy);
471
472       GLdouble aMoveX = 0.5 * (aW1 - aW2 - theTransPers->pointZ);
473       GLdouble aMoveY = 0.5 * (aH1 - aH2 - theTransPers->pointZ);
474       aMoveX = (theTransPers->pointX > 0.0) ? aMoveX : -aMoveX;
475       aMoveY = (theTransPers->pointY > 0.0) ? aMoveY : -aMoveY;
476
477       OpenGl_Utils::Translate<Standard_Real> (aProjMatrix, aMoveX, aMoveY, 0.0);
478       theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjMatrix);
479     }
480   }
481   else if ((theTransPers->mode & TPF_PAN) != TPF_PAN)
482   {
483     // move to thePoint using saved win-coordinates ('marker-behaviour')
484     GLdouble aMoveX, aMoveY, aMoveZ;
485
486     OpenGl_Utils::UnProject<Standard_Real> (aWinX,
487                                             aWinY,
488                                             aWinZ,
489                                             aModelMatrix,
490                                             aProjMatrix,
491                                             aViewport,
492                                             aMoveX,
493                                             aMoveY,
494                                             aMoveZ);
495
496     OpenGl_Utils::Translate<Standard_Real> (aModelMatrix, aMoveX, aMoveY, aMoveZ);
497     theCtx->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
498   }
499
500   theCtx->ApplyProjectionMatrix();
501   return aTransPersPrev;
502 }