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