0026278: Canonical recognition from time to time raises exception on the attached...
[occt.git] / src / OpenGl / OpenGl_View.cxx
CommitLineData
b311480e 1// Created on: 2011-09-20
2// Created by: Sergey ZERCHANINOV
973c2be1 3// Copyright (c) 2011-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
30f0ad28 16#include <NCollection_Mat4.hxx>
5f8b738e 17
bf75be98 18#include <OpenGl_Context.hxx>
30f0ad28 19#include <OpenGl_GlCore11.hxx>
20#include <OpenGl_GraduatedTrihedron.hxx>
392ac980 21#include <OpenGl_GraphicDriver.hxx>
30f0ad28 22#include <OpenGl_ShaderManager.hxx>
bf75be98 23#include <OpenGl_Texture.hxx>
2166f0fa 24#include <OpenGl_Trihedron.hxx>
2166f0fa 25#include <OpenGl_transform_persistence.hxx>
30f0ad28 26#include <OpenGl_View.hxx>
c827ea3a 27#include <OpenGl_Utils.hxx>
30f0ad28 28#include <OpenGl_Workspace.hxx>
2166f0fa 29
bf75be98 30#include <Graphic3d_TextureEnv.hxx>
197ac94e 31#include <Graphic3d_Mat4d.hxx>
bf75be98 32
2166f0fa
SK
33IMPLEMENT_STANDARD_HANDLE(OpenGl_View,MMgt_TShared)
34IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,MMgt_TShared)
35
36/*----------------------------------------------------------------------*/
37
2166f0fa
SK
38static 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 } };
39static const OPENGL_ZCLIP myDefaultZClip = { { Standard_True, 0.F }, { Standard_True, 1.F } };
2166f0fa
SK
40
41static const OPENGL_FOG myDefaultFog = { Standard_False, 0.F, 1.F, { { 0.F, 0.F, 0.F, 1.F } } };
42static const TEL_TRANSFORM_PERSISTENCE myDefaultTransPers = { 0, 0.F, 0.F, 0.F };
c34dba32 43static 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};
2166f0fa
SK
50
51/*----------------------------------------------------------------------*/
52
392ac980 53OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext,
54 OpenGl_StateCounter* theCounter)
a6964ce6 55: mySurfaceDetail(Visual3d_TOD_ALL),
2166f0fa 56 myBackfacing(0),
2166f0fa
SK
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),
b5ac8292 63 myCamera(AContext.Camera),
2166f0fa 64 myFog(myDefaultFog),
536d98e2 65 myToShowTrihedron (false),
66 myToShowGradTrihedron (false),
2166f0fa 67 myVisualization(AContext.Visualization),
8625ef7e 68 myShadingModel ((Visual3d_TypeOfModel )AContext.Model),
2166f0fa 69 myAntiAliasing(Standard_False),
2166f0fa 70 myTransPers(&myDefaultTransPers),
30f0ad28 71 myIsTransPers(Standard_False),
b5ac8292 72 myProjectionState (0),
73 myModelViewState (0),
392ac980 74 myStateCounter (theCounter),
0b0320e7 75 myLastLightSourceState (0, 0),
0b0320e7 76 myTextureParams (new OpenGl_AspectFace()),
77 myBgGradientArray (new OpenGl_BackgroundArray (Graphic3d_TOB_GRADIENT)),
91c60b57 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)
2166f0fa 85{
392ac980 86 myCurrLightSourceState = myStateCounter->Increment();
2166f0fa
SK
87}
88
89/*----------------------------------------------------------------------*/
90
0b0320e7 91OpenGl_View::~OpenGl_View()
2166f0fa 92{
bf75be98 93 ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
0b0320e7 94 OpenGl_Element::Destroy (NULL, myBgGradientArray);
95 OpenGl_Element::Destroy (NULL, myBgTextureArray);
96 OpenGl_Element::Destroy (NULL, myTextureParams);
bf75be98 97}
98
99void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
100{
536d98e2 101 myTrihedron .Release (theCtx.operator->());
102 myGraduatedTrihedron.Release (theCtx.operator->());
30f0ad28 103
bf75be98 104 if (!myTextureEnv.IsNull())
105 {
106 theCtx->DelayedRelease (myTextureEnv);
107 myTextureEnv.Nullify();
108 }
0b0320e7 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)
bf75be98 119 {
0b0320e7 120 myBgTextureArray->Release (theCtx.operator->());
bf75be98 121 }
91c60b57 122
123 releaseRaytraceResources (theCtx);
bf75be98 124}
2166f0fa 125
bf75be98 126void 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();
e276548b 142 if (!anImage.IsNull())
da0e82aa 143 myTextureEnv->Init (theCtx, *anImage.operator->(), theTexture->Type());
e276548b 144
91c60b57 145 myToUpdateEnvironmentMap = Standard_True;
e276548b 146}
147
148void OpenGl_View::SetSurfaceDetail (const Visual3d_TypeOfSurfaceDetail theMode)
149{
150 mySurfaceDetail = theMode;
151
91c60b57 152 myToUpdateEnvironmentMap = Standard_True;
2166f0fa
SK
153}
154
12381341 155// =======================================================================
156// function : SetBackfacing
157// purpose :
158// =======================================================================
de75ed09 159void OpenGl_View::SetBackfacing (const Standard_Integer theMode)
2166f0fa 160{
de75ed09 161 myBackfacing = theMode;
2166f0fa
SK
162}
163
12381341 164// =======================================================================
165// function : SetLights
166// purpose :
167// =======================================================================
168void OpenGl_View::SetLights (const CALL_DEF_VIEWCONTEXT& theViewCtx)
2166f0fa
SK
169{
170 myLights.Clear();
12381341 171 for (Standard_Integer aLightIt = 0; aLightIt < theViewCtx.NbActiveLight; ++aLightIt)
2166f0fa 172 {
12381341 173 myLights.Append (theViewCtx.ActiveLight[aLightIt]);
2166f0fa 174 }
392ac980 175 myCurrLightSourceState = myStateCounter->Increment();
2166f0fa
SK
176}
177
178/*----------------------------------------------------------------------*/
179
2166f0fa
SK
180//call_togl_setvisualisation
181void OpenGl_View::SetVisualisation (const CALL_DEF_VIEWCONTEXT &AContext)
182{
183 myVisualization = AContext.Visualization;
8625ef7e 184 myShadingModel = (Visual3d_TypeOfModel )AContext.Model;
2166f0fa
SK
185}
186
187/*----------------------------------------------------------------------*/
188
189//call_togl_cliplimit
bf75be98 190void OpenGl_View::SetClipLimit (const Graphic3d_CView& theCView)
2166f0fa 191{
b5ac8292 192 myZClip.Back.Limit = theCView.Context.ZClipBackPlane;
193 myZClip.Front.Limit = theCView.Context.ZClipFrontPlane;
2166f0fa 194
bf75be98 195 myZClip.Back.IsOn = (theCView.Context.BackZClipping != 0);
196 myZClip.Front.IsOn = (theCView.Context.FrontZClipping != 0);
2166f0fa
SK
197}
198
199/*----------------------------------------------------------------------*/
200
bf75be98 201void OpenGl_View::SetFog (const Graphic3d_CView& theCView,
202 const Standard_Boolean theFlag)
2166f0fa 203{
bf75be98 204 if (!theFlag)
2166f0fa
SK
205 {
206 myFog.IsOn = Standard_False;
207 }
208 else
209 {
210 myFog.IsOn = Standard_True;
211
b5ac8292 212 myFog.Front = theCView.Context.DepthFrontPlane;
213 myFog.Back = theCView.Context.DepthBackPlane;
2166f0fa 214
bf75be98 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;
2166f0fa
SK
219 }
220}
221
222/*----------------------------------------------------------------------*/
223
536d98e2 224void OpenGl_View::TriedronDisplay (const Aspect_TypeOfTriedronPosition thePosition,
a174a3c5 225 const Quantity_NameOfColor theColor,
226 const Standard_Real theScale,
227 const Standard_Boolean theAsWireframe)
2166f0fa 228{
536d98e2 229 myToShowTrihedron = true;
230 myTrihedron.SetWireframe (theAsWireframe);
231 myTrihedron.SetPosition (thePosition);
232 myTrihedron.SetScale (theScale);
233 myTrihedron.SetLabelsColor (theColor);
2166f0fa
SK
234}
235
236/*----------------------------------------------------------------------*/
237
a174a3c5 238void OpenGl_View::TriedronErase (const Handle(OpenGl_Context)& theCtx)
2166f0fa 239{
536d98e2 240 myToShowTrihedron = false;
241 myTrihedron.Release (theCtx.operator->());
2166f0fa
SK
242}
243
244/*----------------------------------------------------------------------*/
245
536d98e2 246void OpenGl_View::GraduatedTrihedronDisplay (const Handle(OpenGl_Context)& theCtx,
a79f67f8 247 const Graphic3d_GraduatedTrihedron& theData)
2166f0fa 248{
536d98e2 249 myToShowGradTrihedron = true;
250 myGraduatedTrihedron.SetValues (theCtx, theData);
2166f0fa
SK
251}
252
253/*----------------------------------------------------------------------*/
254
a174a3c5 255void OpenGl_View::GraduatedTrihedronErase (const Handle(OpenGl_Context)& theCtx)
2166f0fa 256{
536d98e2 257 myToShowGradTrihedron = false;
258 myGraduatedTrihedron.Release (theCtx.operator->());
2166f0fa
SK
259}
260
261/*----------------------------------------------------------------------*/
262
263//transform_persistence_end
30f0ad28 264void OpenGl_View::EndTransformPersistence(const Handle(OpenGl_Context)& theCtx)
2166f0fa 265{
c34dba32 266 if (myIsTransPers)
2166f0fa 267 {
c827ea3a 268 theCtx->WorldViewState.Pop();
269 theCtx->ProjectionState.Pop();
30f0ad28 270
c827ea3a 271 theCtx->ApplyProjectionMatrix();
af65fb19 272 theCtx->ApplyWorldViewMatrix();
30f0ad28 273
c827ea3a 274 myIsTransPers = Standard_False;
2166f0fa 275 }
bf75be98 276}
2166f0fa
SK
277
278/*----------------------------------------------------------------------*/
279
280//transform_persistence_begin
30f0ad28 281const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const Handle(OpenGl_Context)& theCtx,
af65fb19 282 const TEL_TRANSFORM_PERSISTENCE* theTransPers,
283 Standard_Integer theWidth,
284 Standard_Integer theHeight)
2166f0fa 285{
c34dba32 286 const TEL_TRANSFORM_PERSISTENCE* aTransPersPrev = myTransPers;
287 myTransPers = theTransPers;
288 if (theTransPers->mode == 0)
2166f0fa 289 {
30f0ad28 290 EndTransformPersistence (theCtx);
c34dba32 291 return aTransPersPrev;
2166f0fa
SK
292 }
293
c34dba32 294 GLint aViewport[4];
c827ea3a 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());
ca3c13d1 299
c34dba32 300 const GLdouble aViewportW = (GLdouble )aViewport[2];
301 const GLdouble aViewportH = (GLdouble )aViewport[3];
af65fb19 302
c34dba32 303 if (myIsTransPers)
2166f0fa 304 {
c34dba32 305 // pop matrix stack - it will be overridden later
c827ea3a 306 theCtx->WorldViewState.Pop();
307 theCtx->ProjectionState.Pop();
2166f0fa
SK
308 }
309 else
c34dba32 310 {
2166f0fa 311 myIsTransPers = Standard_True;
c34dba32 312 }
2166f0fa 313
af65fb19 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
c34dba32 364 // push matrices into stack and reset them
c827ea3a 365 theCtx->WorldViewState.Push();
366 theCtx->ProjectionState.Push();
2166f0fa 367
c34dba32 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)
2166f0fa 371 {
c827ea3a 372 OpenGl_Utils::Project<Standard_Real> (theTransPers->pointX,
373 theTransPers->pointY,
374 theTransPers->pointZ,
375 aModelMatrix,
376 aProjMatrix,
377 aViewport,
8621cdc2 378 aWinX,
c827ea3a 379 aWinY,
380 aWinZ);
2166f0fa
SK
381 }
382
c34dba32 383 // prevent zooming
384 if ((theTransPers->mode & TPF_ZOOM)
385 || (theTransPers->mode == TPF_TRIEDRON))
2166f0fa 386 {
c34dba32 387 // compute fixed-zoom multiplier
388 // actually function works ugly with TelPerspective!
c827ea3a 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;
2166f0fa
SK
393 }
394
c34dba32 395 // prevent translation - annulate translate matrix
396 if ((theTransPers->mode & TPF_PAN)
397 || (theTransPers->mode == TPF_TRIEDRON))
2166f0fa 398 {
c827ea3a 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);
2166f0fa 405 }
2166f0fa 406
c34dba32 407 // prevent scaling-on-axis
408 if (theTransPers->mode & TPF_ZOOM)
409 {
b5ac8292 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();
c34dba32 414 for (int i = 0; i < 3; ++i)
415 {
c827ea3a 416 aModelMatrix.ChangeValue (0, i) /= aScaleX;
417 aModelMatrix.ChangeValue (1, i) /= aScaleY;
418 aModelMatrix.ChangeValue (2, i) /= aScaleZ;
c34dba32 419 }
2166f0fa
SK
420 }
421
c34dba32 422 // prevent rotating - annulate rotate matrix
423 if (theTransPers->mode & TPF_ROTATE)
2166f0fa 424 {
c827ea3a 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);
2166f0fa
SK
435 }
436
c34dba32 437 // load computed matrices
c827ea3a 438 theCtx->ModelWorldState.SetIdentity();
439 theCtx->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
440 theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjMatrix);
2166f0fa 441
c34dba32 442 if (theTransPers->mode == TPF_TRIEDRON)
2166f0fa 443 {
c34dba32 444 // move to the window corner
445 if (theTransPers->pointX != 0.0
446 && theTransPers->pointY != 0.0)
2166f0fa 447 {
c34dba32 448 GLdouble aW1, aH1, aW2, aH2, aDummy;
c827ea3a 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);
ca3c13d1 471
c34dba32 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;
c827ea3a 476
477 OpenGl_Utils::Translate<Standard_Real> (aProjMatrix, aMoveX, aMoveY, 0.0);
478 theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjMatrix);
2166f0fa
SK
479 }
480 }
c34dba32 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;
2166f0fa 485
c827ea3a 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 }
30f0ad28 499
c827ea3a 500 theCtx->ApplyProjectionMatrix();
c34dba32 501 return aTransPersPrev;
502}