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