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