56725e93b6ce254e2768f542596dd041f260b2ab
[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_Workspace.hxx>
28
29 #include <Graphic3d_TextureEnv.hxx>
30 #include <Graphic3d_Mat4d.hxx>
31
32 IMPLEMENT_STANDARD_HANDLE(OpenGl_View,MMgt_TShared)
33 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,MMgt_TShared)
34
35 /*----------------------------------------------------------------------*/
36
37 static const OPENGL_BG_TEXTURE myDefaultBgTexture = { 0, 0, 0, Aspect_FM_CENTERED };
38 static const OPENGL_BG_GRADIENT myDefaultBgGradient = { {{ 0.F, 0.F, 0.F, 1.F }}, {{ 0.F, 0.F, 0.F, 1.F }}, Aspect_GFM_NONE };
39 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 } };
40 static const OPENGL_ZCLIP myDefaultZClip = { { Standard_True, 0.F }, { Standard_True, 1.F } };
41
42 static const OPENGL_FOG myDefaultFog = { Standard_False, 0.F, 1.F, { { 0.F, 0.F, 0.F, 1.F } } };
43 static const TEL_TRANSFORM_PERSISTENCE myDefaultTransPers = { 0, 0.F, 0.F, 0.F };
44 static const GLdouble THE_IDENTITY_MATRIX[4][4] =
45 {
46   {1.0, 0.0, 0.0, 0.0},
47   {0.0, 1.0, 0.0, 0.0},
48   {0.0, 0.0, 1.0, 0.0},
49   {0.0, 0.0, 0.0, 1.0}
50 };
51
52 /*----------------------------------------------------------------------*/
53
54 OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext,
55                           OpenGl_StateCounter*       theCounter)
56 : mySurfaceDetail(Visual3d_TOD_NONE),
57   myBackfacing(0),
58   myBgTexture(myDefaultBgTexture),
59   myBgGradient(myDefaultBgGradient),
60   //shield_indicator = TOn,
61   //shield_colour = { { 0.F, 0.F, 0.F, 1.F } },
62   //border_indicator = TOff,
63   //border_colour = { { 0.F, 0.F, 0.F, 1.F } },
64   //active_status = TOn,
65   myZClip(myDefaultZClip),
66   myCamera(AContext.Camera),
67   myFog(myDefaultFog),
68   myTrihedron(NULL),
69   myGraduatedTrihedron(NULL),
70   myVisualization(AContext.Visualization),
71   myShadingModel ((Visual3d_TypeOfModel )AContext.Model),
72   myAntiAliasing(Standard_False),
73   myTransPers(&myDefaultTransPers),
74   myIsTransPers(Standard_False),
75   myProjectionState (0),
76   myModelViewState (0),
77   myStateCounter (theCounter),
78   myLastLightSourceState (0, 0)
79 {
80   myCurrLightSourceState = myStateCounter->Increment();
81   myModificationState = 1; // initial state
82 }
83
84 /*----------------------------------------------------------------------*/
85
86 OpenGl_View::~OpenGl_View ()
87 {
88   ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
89 }
90
91 void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
92 {
93   OpenGl_Element::Destroy (theCtx.operator->(), myTrihedron);
94   OpenGl_Element::Destroy (theCtx.operator->(), myGraduatedTrihedron);
95
96   if (!myTextureEnv.IsNull())
97   {
98     theCtx->DelayedRelease (myTextureEnv);
99     myTextureEnv.Nullify();
100   }
101   if (myBgTexture.TexId != 0)
102   {
103     glDeleteTextures (1, (GLuint*)&(myBgTexture.TexId));
104     myBgTexture.TexId = 0;
105   }
106 }
107
108 void OpenGl_View::SetTextureEnv (const Handle(OpenGl_Context)&       theCtx,
109                                  const Handle(Graphic3d_TextureEnv)& theTexture)
110 {
111   if (!myTextureEnv.IsNull())
112   {
113     theCtx->DelayedRelease (myTextureEnv);
114     myTextureEnv.Nullify();
115   }
116
117   if (theTexture.IsNull())
118   {
119     return;
120   }
121
122   myTextureEnv = new OpenGl_Texture (theTexture->GetParams());
123   Handle(Image_PixMap) anImage = theTexture->GetImage();
124   if (!anImage.IsNull())
125     myTextureEnv->Init (theCtx, *anImage.operator->(), theTexture->Type());
126
127   myModificationState++;
128 }
129
130 void OpenGl_View::SetSurfaceDetail (const Visual3d_TypeOfSurfaceDetail theMode)
131 {
132   mySurfaceDetail = theMode;
133
134   myModificationState++;
135 }
136
137 // =======================================================================
138 // function : SetBackfacing
139 // purpose  :
140 // =======================================================================
141 void OpenGl_View::SetBackfacing (const Standard_Integer theMode)
142 {
143   myBackfacing = theMode;
144 }
145
146 // =======================================================================
147 // function : SetLights
148 // purpose  :
149 // =======================================================================
150 void OpenGl_View::SetLights (const CALL_DEF_VIEWCONTEXT& theViewCtx)
151 {
152   myLights.Clear();
153   for (Standard_Integer aLightIt = 0; aLightIt < theViewCtx.NbActiveLight; ++aLightIt)
154   {
155     myLights.Append (theViewCtx.ActiveLight[aLightIt]);
156   }
157   myCurrLightSourceState = myStateCounter->Increment();
158 }
159
160 /*----------------------------------------------------------------------*/
161
162 //call_togl_setvisualisation
163 void OpenGl_View::SetVisualisation (const CALL_DEF_VIEWCONTEXT &AContext)
164 {
165   myVisualization = AContext.Visualization;
166   myShadingModel  = (Visual3d_TypeOfModel )AContext.Model;
167 }
168
169 /*----------------------------------------------------------------------*/
170
171 //call_togl_cliplimit
172 void OpenGl_View::SetClipLimit (const Graphic3d_CView& theCView)
173 {
174   myZClip.Back.Limit = theCView.Context.ZClipBackPlane;
175   myZClip.Front.Limit = theCView.Context.ZClipFrontPlane;
176
177   myZClip.Back.IsOn  = (theCView.Context.BackZClipping  != 0);
178   myZClip.Front.IsOn = (theCView.Context.FrontZClipping != 0);
179 }
180
181 /*----------------------------------------------------------------------*/
182
183 void OpenGl_View::SetFog (const Graphic3d_CView& theCView,
184                           const Standard_Boolean theFlag)
185 {
186   if (!theFlag)
187   {
188     myFog.IsOn = Standard_False;
189   }
190   else
191   {
192     myFog.IsOn = Standard_True;
193
194     myFog.Front = theCView.Context.DepthFrontPlane;
195     myFog.Back = theCView.Context.DepthBackPlane;
196
197     myFog.Color.rgb[0] = theCView.DefWindow.Background.r;
198     myFog.Color.rgb[1] = theCView.DefWindow.Background.g;
199     myFog.Color.rgb[2] = theCView.DefWindow.Background.b;
200     myFog.Color.rgb[3] = 1.0f;
201   }
202 }
203
204 /*----------------------------------------------------------------------*/
205
206 void OpenGl_View::TriedronDisplay (const Handle(OpenGl_Context)&       theCtx,
207                                    const Aspect_TypeOfTriedronPosition thePosition,
208                                    const Quantity_NameOfColor          theColor,
209                                    const Standard_Real                 theScale,
210                                    const Standard_Boolean              theAsWireframe)
211 {
212   OpenGl_Element::Destroy (theCtx.operator->(), myTrihedron);
213   myTrihedron = new OpenGl_Trihedron (thePosition, theColor, theScale, theAsWireframe);
214 }
215
216 /*----------------------------------------------------------------------*/
217
218 void OpenGl_View::TriedronErase (const Handle(OpenGl_Context)& theCtx)
219 {
220   OpenGl_Element::Destroy (theCtx.operator->(), myTrihedron);
221 }
222
223 /*----------------------------------------------------------------------*/
224
225 void OpenGl_View::GraduatedTrihedronDisplay (const Handle(OpenGl_Context)&        theCtx,
226                                              const Graphic3d_CGraduatedTrihedron& theData)
227 {
228   OpenGl_Element::Destroy (theCtx.operator->(), myGraduatedTrihedron);
229   myGraduatedTrihedron = new OpenGl_GraduatedTrihedron (theData);
230 }
231
232 /*----------------------------------------------------------------------*/
233
234 void OpenGl_View::GraduatedTrihedronErase (const Handle(OpenGl_Context)& theCtx)
235 {
236   OpenGl_Element::Destroy (theCtx.operator->(), myGraduatedTrihedron);
237 }
238
239 /*----------------------------------------------------------------------*/
240
241 //transform_persistence_end
242 void OpenGl_View::EndTransformPersistence(const Handle(OpenGl_Context)& theCtx)
243 {
244   if (myIsTransPers)
245   {
246   #if !defined(GL_ES_VERSION_2_0)
247     // restore matrix
248     glMatrixMode (GL_PROJECTION);
249     glPopMatrix();
250     glMatrixMode (GL_MODELVIEW);
251     glPopMatrix();
252     myIsTransPers = Standard_False;
253
254     // Note: the approach of accessing OpenGl matrices is used now since the matrix
255     // manipulation are made with help of OpenGl methods. This might be replaced by
256     // direct computation of matrices by OCC subroutines.
257     Tmatrix3 aResultWorldView;
258     glGetFloatv (GL_MODELVIEW_MATRIX, *aResultWorldView);
259
260     Tmatrix3 aResultProjection;
261     glGetFloatv (GL_PROJECTION_MATRIX, *aResultProjection);
262
263     // Set OCCT state uniform variables
264     theCtx->ShaderManager()->RevertWorldViewStateTo (&aResultWorldView);
265     theCtx->ShaderManager()->RevertProjectionStateTo (&aResultProjection);
266   #endif
267   }
268 }
269
270 /*----------------------------------------------------------------------*/
271
272 //transform_persistence_begin
273 const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const Handle(OpenGl_Context)& theCtx,
274                                                                          const TEL_TRANSFORM_PERSISTENCE* theTransPers)
275 {
276   const TEL_TRANSFORM_PERSISTENCE* aTransPersPrev = myTransPers;
277   myTransPers = theTransPers;
278   if (theTransPers->mode == 0)
279   {
280     EndTransformPersistence (theCtx);
281     return aTransPersPrev;
282   }
283
284 #if !defined(GL_ES_VERSION_2_0)
285   GLint aViewport[4];
286   GLdouble aModelMatrix[4][4];
287   GLdouble aProjMatrix[4][4];
288   glGetIntegerv (GL_VIEWPORT,          aViewport);
289   glGetDoublev  (GL_MODELVIEW_MATRIX,  (GLdouble* )aModelMatrix);
290   glGetDoublev  (GL_PROJECTION_MATRIX, (GLdouble *)aProjMatrix);
291
292   const GLdouble aViewportW = (GLdouble )aViewport[2];
293   const GLdouble aViewportH = (GLdouble )aViewport[3];
294
295   if (myIsTransPers)
296   {
297     // pop matrix stack - it will be overridden later
298     glMatrixMode (GL_PROJECTION);
299     glPopMatrix();
300     glMatrixMode (GL_MODELVIEW);
301     glPopMatrix();
302   }
303   else
304   {
305     myIsTransPers = Standard_True;
306   }
307
308   // push matrices into stack and reset them
309   glMatrixMode (GL_MODELVIEW);
310   glPushMatrix();
311   glLoadIdentity();
312
313   glMatrixMode (GL_PROJECTION);
314   glPushMatrix();
315   glLoadIdentity();
316
317   // get the window's (fixed) coordinates for theTransPers->point before matrixes modifications
318   GLdouble aWinX = 0.0, aWinY = 0.0, aWinZ = 0.0;
319   if ((theTransPers->mode & TPF_PAN) != TPF_PAN)
320   {
321     gluProject (theTransPers->pointX, theTransPers->pointY, theTransPers->pointZ,
322                 (GLdouble* )aModelMatrix, (GLdouble* )aProjMatrix, aViewport,
323                 &aWinX, &aWinY, &aWinZ);
324   }
325
326   // prevent zooming
327   if ((theTransPers->mode & TPF_ZOOM)
328    || (theTransPers->mode == TPF_TRIEDRON))
329   {
330     // compute fixed-zoom multiplier
331     // actually function works ugly with TelPerspective!
332     const GLdouble aDet2 = 0.002 / (aViewportW > aViewportH ? aProjMatrix[1][1] : aProjMatrix[0][0]);
333     aProjMatrix[0][0] *= aDet2;
334     aProjMatrix[1][1] *= aDet2;
335     aProjMatrix[2][2] *= aDet2;
336   }
337
338   // prevent translation - annulate translate matrix
339   if ((theTransPers->mode & TPF_PAN)
340    || (theTransPers->mode == TPF_TRIEDRON))
341   {
342     aModelMatrix[3][0] = 0.0;
343     aModelMatrix[3][1] = 0.0;
344     aModelMatrix[3][2] = 0.0;
345     aProjMatrix [3][0] = 0.0;
346     aProjMatrix [3][1] = 0.0;
347     aProjMatrix [3][2] = 0.0;
348   }
349
350   // prevent scaling-on-axis
351   if (theTransPers->mode & TPF_ZOOM)
352   {
353     const gp_Pnt anAxialScale = myCamera->AxialScale();
354     const double aScaleX = anAxialScale.X();
355     const double aScaleY = anAxialScale.Y();
356     const double aScaleZ = anAxialScale.Z();
357     for (int i = 0; i < 3; ++i)
358     {
359       aModelMatrix[0][i] /= aScaleX;
360       aModelMatrix[1][i] /= aScaleY;
361       aModelMatrix[2][i] /= aScaleZ;
362     }
363   }
364
365   // prevent rotating - annulate rotate matrix
366   if (theTransPers->mode & TPF_ROTATE)
367   {
368     aModelMatrix[0][0] = 1.0;
369     aModelMatrix[1][1] = 1.0;
370     aModelMatrix[2][2] = 1.0;
371
372     aModelMatrix[1][0] = 0.0;
373     aModelMatrix[2][0] = 0.0;
374     aModelMatrix[0][1] = 0.0;
375     aModelMatrix[2][1] = 0.0;
376     aModelMatrix[0][2] = 0.0;
377     aModelMatrix[1][2] = 0.0;
378   }
379
380   // load computed matrices
381   glMatrixMode (GL_MODELVIEW);
382   glMultMatrixd ((GLdouble* )aModelMatrix);
383
384   glMatrixMode (GL_PROJECTION);
385   glMultMatrixd ((GLdouble* )aProjMatrix);
386
387   if (theTransPers->mode == TPF_TRIEDRON)
388   {
389     // move to the window corner
390     if (theTransPers->pointX != 0.0
391      && theTransPers->pointY != 0.0)
392     {
393       GLdouble aW1, aH1, aW2, aH2, aDummy;
394       glMatrixMode (GL_PROJECTION);
395       gluUnProject ( 0.5 * aViewportW,  0.5 * aViewportH, 0.0,
396                     (GLdouble* )THE_IDENTITY_MATRIX, (GLdouble* )aProjMatrix, aViewport,
397                     &aW1, &aH1, &aDummy);
398       gluUnProject (-0.5 * aViewportW, -0.5 * aViewportH, 0.0,
399                     (GLdouble* )THE_IDENTITY_MATRIX, (GLdouble* )aProjMatrix, aViewport,
400                     &aW2, &aH2, &aDummy);
401
402       GLdouble aMoveX = 0.5 * (aW1 - aW2 - theTransPers->pointZ);
403       GLdouble aMoveY = 0.5 * (aH1 - aH2 - theTransPers->pointZ);
404       aMoveX = (theTransPers->pointX > 0.0) ? aMoveX : -aMoveX;
405       aMoveY = (theTransPers->pointY > 0.0) ? aMoveY : -aMoveY;
406       theCtx->core11->glTranslated (aMoveX, aMoveY, 0.0);
407     }
408   }
409   else if ((theTransPers->mode & TPF_PAN) != TPF_PAN)
410   {
411     // move to thePoint using saved win-coordinates ('marker-behaviour')
412     GLdouble aMoveX, aMoveY, aMoveZ;
413     glGetDoublev (GL_MODELVIEW_MATRIX,  (GLdouble* )aModelMatrix);
414     glGetDoublev (GL_PROJECTION_MATRIX, (GLdouble* )aProjMatrix);
415     gluUnProject (aWinX, aWinY, aWinZ,
416                   (GLdouble* )aModelMatrix, (GLdouble* )aProjMatrix, aViewport,
417                   &aMoveX, &aMoveY, &aMoveZ);
418
419     glMatrixMode (GL_MODELVIEW);
420     theCtx->core11->glTranslated (aMoveX, aMoveY, aMoveZ);
421   }
422
423   // Note: the approach of accessing OpenGl matrices is used now since the matrix
424   // manipulation are made with help of OpenGl methods. This might be replaced by
425   // direct computation of matrices by OCC subroutines.
426   Tmatrix3 aResultWorldView;
427   glGetFloatv (GL_MODELVIEW_MATRIX, *aResultWorldView);
428
429   Tmatrix3 aResultProjection;
430   glGetFloatv (GL_PROJECTION_MATRIX, *aResultProjection);
431
432   // Set OCCT state uniform variables
433   theCtx->ShaderManager()->UpdateWorldViewStateTo (&aResultWorldView);
434   theCtx->ShaderManager()->UpdateProjectionStateTo (&aResultProjection);
435 #endif
436   return aTransPersPrev;
437 }
438
439 /*----------------------------------------------------------------------*/
440
441 void OpenGl_View::GetMatrices (TColStd_Array2OfReal&  theMatOrient,
442                                TColStd_Array2OfReal&  theMatMapping) const
443 {
444   const Graphic3d_Mat4d& aProj   = myCamera->ProjectionMatrix();
445   const Graphic3d_Mat4d& aOrient = myCamera->OrientationMatrix();
446
447   for (Standard_Integer aRow = 0; aRow < 4; ++aRow)
448   {
449     for (Standard_Integer aCol = 0; aCol < 4; ++aCol)
450     {
451       theMatOrient  (aRow, aCol) = aOrient.GetValue (aRow, aCol);
452       theMatMapping (aRow, aCol) = aProj  .GetValue (aRow, aCol);
453     }
454   }
455 }
456 /*----------------------------------------------------------------------*/