0028762: Visualization, Ray tracing - Implement depth-of-field effect
[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 <OpenGl_View.hxx>
17
18 #include <Aspect_RenderingContext.hxx>
19 #include <Aspect_Window.hxx>
20 #include <Graphic3d_AspectFillArea3d.hxx>
21 #include <Graphic3d_Texture2Dmanual.hxx>
22 #include <Graphic3d_TextureEnv.hxx>
23 #include <Graphic3d_Mat4d.hxx>
24 #include <NCollection_Mat4.hxx>
25 #include <OpenGl_Context.hxx>
26 #include <OpenGl_FrameBuffer.hxx>
27 #include <OpenGl_GlCore11.hxx>
28 #include <OpenGl_GraduatedTrihedron.hxx>
29 #include <OpenGl_GraphicDriver.hxx>
30 #include <OpenGl_ShaderManager.hxx>
31 #include <OpenGl_Texture.hxx>
32 #include <OpenGl_Window.hxx>
33 #include <OpenGl_Workspace.hxx>
34 #include <OSD_Parallel.hxx>
35 #include <Standard_CLocaleSentry.hxx>
36
37 #include "../Graphic3d/Graphic3d_Structure.pxx"
38
39 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,Graphic3d_CView)
40
41 #ifdef HAVE_GL2PS
42 #include <gl2ps.h>
43 #endif
44
45 // =======================================================================
46 // function : Constructor
47 // purpose  :
48 // =======================================================================
49 OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
50                           const Handle(OpenGl_GraphicDriver)& theDriver,
51                           const Handle(OpenGl_Caps)& theCaps,
52                           Standard_Boolean& theDeviceLostFlag,
53                           OpenGl_StateCounter* theCounter)
54 : Graphic3d_CView  (theMgr),
55   myDriver         (theDriver.operator->()),
56   myCaps           (theCaps),
57   myDeviceLostFlag (theDeviceLostFlag),
58   myWasRedrawnGL   (Standard_False),
59   myCulling        (Standard_True),
60   myShadingModel   (Graphic3d_TOSM_FACET),
61   myBackfacing     (Graphic3d_TOBM_AUTOMATIC),
62   myBgColor        (Quantity_NOC_BLACK),
63   myCamera         (new Graphic3d_Camera()),
64   myToShowGradTrihedron  (false),
65   myZLayers        (Structure_MAX_PRIORITY - Structure_MIN_PRIORITY + 1),
66   myStateCounter         (theCounter),
67   myLastLightSourceState (0, 0),
68 #if !defined(GL_ES_VERSION_2_0)
69   myFboColorFormat       (GL_RGBA8),
70 #else
71   myFboColorFormat       (GL_RGBA),
72 #endif
73   myFboDepthFormat       (GL_DEPTH24_STENCIL8),
74   myToFlipOutput         (Standard_False),
75   myFrameCounter         (0),
76   myHasFboBlit           (Standard_True),
77   myToDisableOIT         (Standard_False),
78   myToDisableOITMSAA     (Standard_False),
79   myToDisableMSAA        (Standard_False),
80   myTransientDrawToFront (Standard_True),
81   myBackBufferRestored   (Standard_False),
82   myIsImmediateDrawn     (Standard_False),
83   myTextureParams   (new OpenGl_AspectFace()),
84   myBgGradientArray (new OpenGl_BackgroundArray (Graphic3d_TOB_GRADIENT)),
85   myBgTextureArray  (new OpenGl_BackgroundArray (Graphic3d_TOB_TEXTURE)),
86   // ray-tracing fields initialization
87   myRaytraceInitStatus     (OpenGl_RT_NONE),
88   myIsRaytraceDataValid    (Standard_False),
89   myIsRaytraceWarnTextures (Standard_False),
90   myRaytraceBVHBuilder (new BVH_BinnedBuilder<Standard_ShortReal, 3, BVH_Constants_NbBinsBest> (BVH_Constants_LeafNodeSizeAverage,
91                                                                                                 BVH_Constants_MaxTreeDepth,
92                                                                                                 Standard_False,
93                                                                                                 OSD_Parallel::NbLogicalProcessors() + 1)),
94   myRaytraceSceneRadius  (0.0f),
95   myRaytraceSceneEpsilon (1.0e-6f),
96   myToUpdateEnvironmentMap (Standard_False),
97   myRaytraceLayerListState (0),
98   myPrevCameraApertureRadius(0.f),
99   myPrevCameraFocalPlaneDist(0.f)
100 {
101   myWorkspace = new OpenGl_Workspace (this, NULL);
102
103   OpenGl_Light       aLight;
104   aLight.Type        = Graphic3d_TOLS_AMBIENT;
105   aLight.IsHeadlight = Standard_False;
106   aLight.Color.r()   = 1.;
107   aLight.Color.g()   = 1.;
108   aLight.Color.b()   = 1.;
109   myNoShadingLight.Append (aLight);
110
111   myCurrLightSourceState     = myStateCounter->Increment();
112   myMainSceneFbos[0]         = new OpenGl_FrameBuffer();
113   myMainSceneFbos[1]         = new OpenGl_FrameBuffer();
114   myMainSceneFbosOit[0]      = new OpenGl_FrameBuffer();
115   myMainSceneFbosOit[1]      = new OpenGl_FrameBuffer();
116   myImmediateSceneFbos[0]    = new OpenGl_FrameBuffer();
117   myImmediateSceneFbos[1]    = new OpenGl_FrameBuffer();
118   myImmediateSceneFbosOit[0] = new OpenGl_FrameBuffer();
119   myImmediateSceneFbosOit[1] = new OpenGl_FrameBuffer();
120   myOpenGlFBO                = new OpenGl_FrameBuffer();
121   myOpenGlFBO2               = new OpenGl_FrameBuffer();
122   myRaytraceFBO1[0]          = new OpenGl_FrameBuffer();
123   myRaytraceFBO1[1]          = new OpenGl_FrameBuffer();
124   myRaytraceFBO2[0]          = new OpenGl_FrameBuffer();
125   myRaytraceFBO2[1]          = new OpenGl_FrameBuffer();
126 }
127
128 // =======================================================================
129 // function : Destructor
130 // purpose  :
131 // =======================================================================
132 OpenGl_View::~OpenGl_View()
133 {
134   ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
135   OpenGl_Element::Destroy (NULL, myBgGradientArray);
136   OpenGl_Element::Destroy (NULL, myBgTextureArray);
137   OpenGl_Element::Destroy (NULL, myTextureParams);
138 }
139
140 // =======================================================================
141 // function : ReleaseGlResources
142 // purpose  :
143 // =======================================================================
144 void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
145 {
146   myGraduatedTrihedron.Release (theCtx.operator->());
147
148   if (!myTextureEnv.IsNull())
149   {
150     theCtx->DelayedRelease (myTextureEnv);
151     myTextureEnv.Nullify();
152   }
153
154   if (myTextureParams != NULL)
155   {
156     myTextureParams->Release (theCtx.operator->());
157   }
158   if (myBgGradientArray != NULL)
159   {
160     myBgGradientArray->Release (theCtx.operator->());
161   }
162   if (myBgTextureArray != NULL)
163   {
164     myBgTextureArray->Release (theCtx.operator->());
165   }
166
167   myMainSceneFbos[0]        ->Release (theCtx.operator->());
168   myMainSceneFbos[1]        ->Release (theCtx.operator->());
169   myMainSceneFbosOit[0]     ->Release (theCtx.operator->());
170   myMainSceneFbosOit[1]     ->Release (theCtx.operator->());
171   myImmediateSceneFbos[0]   ->Release (theCtx.operator->());
172   myImmediateSceneFbos[1]   ->Release (theCtx.operator->());
173   myImmediateSceneFbosOit[0]->Release (theCtx.operator->());
174   myImmediateSceneFbosOit[1]->Release (theCtx.operator->());
175   myOpenGlFBO               ->Release (theCtx.operator->());
176   myOpenGlFBO2              ->Release (theCtx.operator->());
177   myFullScreenQuad           .Release (theCtx.operator->());
178   myFullScreenQuadFlip       .Release (theCtx.operator->());
179
180   releaseRaytraceResources (theCtx);
181 }
182
183 // =======================================================================
184 // function : Remove
185 // purpose  :
186 // =======================================================================
187 void OpenGl_View::Remove()
188 {
189   if (IsRemoved())
190   {
191     return;
192   }
193
194   myDriver->RemoveView (this);
195   myWindow.Nullify();
196
197   Graphic3d_CView::Remove();
198 }
199
200 // =======================================================================
201 // function : SetTextureEnv
202 // purpose  :
203 // =======================================================================
204 void OpenGl_View::SetCamera(const Handle(Graphic3d_Camera)& theCamera)
205 {
206   myCamera = theCamera;
207 }
208
209 // =======================================================================
210 // function : SetLocalOrigin
211 // purpose  :
212 // =======================================================================
213 void OpenGl_View::SetLocalOrigin (const gp_XYZ& theOrigin)
214 {
215   myLocalOrigin = theOrigin;
216   const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
217   if (!aCtx.IsNull())
218   {
219     aCtx->ShaderManager()->SetLocalOrigin (theOrigin);
220   }
221 }
222
223 // =======================================================================
224 // function : SetTextureEnv
225 // purpose  :
226 // =======================================================================
227 void OpenGl_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTextureEnv)
228 {
229   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
230   if (!aCtx.IsNull() && !myTextureEnv.IsNull())
231   {
232     aCtx->DelayedRelease (myTextureEnv);
233   }
234
235   myToUpdateEnvironmentMap = Standard_True;
236   myTextureEnvData = theTextureEnv;
237   myTextureEnv.Nullify();
238   initTextureEnv (aCtx);
239 }
240
241 // =======================================================================
242 // function : initTextureEnv
243 // purpose  :
244 // =======================================================================
245 void OpenGl_View::initTextureEnv (const Handle(OpenGl_Context)& theContext)
246 {
247   if (myTextureEnvData.IsNull()
248     ||  theContext.IsNull()
249     || !theContext->MakeCurrent())
250   {
251     return;
252   }
253
254   myTextureEnv = new OpenGl_Texture (myTextureEnvData->GetParams());
255   Handle(Image_PixMap) anImage = myTextureEnvData->GetImage();
256   if (!anImage.IsNull())
257   {
258     myTextureEnv->Init (theContext, *anImage.operator->(), myTextureEnvData->Type());
259   }
260 }
261
262 // =======================================================================
263 // function : SetImmediateModeDrawToFront
264 // purpose  :
265 // =======================================================================
266 Standard_Boolean OpenGl_View::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
267 {
268   const Standard_Boolean aPrevMode = myTransientDrawToFront;
269   myTransientDrawToFront = theDrawToFrontBuffer;
270   return aPrevMode;
271 }
272
273 // =======================================================================
274 // function : SetWindow
275 // purpose  :
276 // =======================================================================
277 void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow,
278                              const Aspect_RenderingContext theContext)
279 {
280   myWindow = myDriver->CreateRenderWindow (theWindow, theContext);
281   Standard_ASSERT_RAISE (!myWindow.IsNull(),
282                          "OpenGl_View::SetWindow, "
283                          "Failed to create OpenGl window.");
284
285   myWorkspace = new OpenGl_Workspace (this, myWindow);
286   myWorldViewProjState.Reset();
287   myToUpdateEnvironmentMap = Standard_True;
288   myHasFboBlit = Standard_True;
289   Invalidate();
290
291   // Environment texture resource does not support lazy initialization.
292   initTextureEnv (myWorkspace->GetGlContext());
293 }
294
295 // =======================================================================
296 // function : Resized
297 // purpose  :
298 // =======================================================================
299 void OpenGl_View::Resized()
300 {
301   if (myWindow.IsNull())
302     return;
303
304   myWindow->Resize();
305 }
306
307 // =======================================================================
308 // function : SetMinMaxValuesCallback
309 // purpose  :
310 // =======================================================================
311 static void SetMinMaxValuesCallback (Graphic3d_CView* theView)
312 {
313   OpenGl_View* aView = dynamic_cast<OpenGl_View*>(theView);
314   if (aView == NULL)
315     return;
316
317   Bnd_Box aBox = theView->MinMaxValues();
318   if (!aBox.IsVoid())
319   {
320     gp_Pnt aMin = aBox.CornerMin();
321     gp_Pnt aMax = aBox.CornerMax();
322
323     Graphic3d_Vec3 aMinVec ((Standard_ShortReal )aMin.X(), (Standard_ShortReal )aMin.Y(), (Standard_ShortReal )aMin.Z());
324     Graphic3d_Vec3 aMaxVec ((Standard_ShortReal )aMax.X(), (Standard_ShortReal )aMax.Y(), (Standard_ShortReal )aMax.Z());
325     aView->GraduatedTrihedronMinMaxValues (aMinVec, aMaxVec);
326   }
327 }
328
329 // =======================================================================
330 // function : GraduatedTrihedronDisplay
331 // purpose  :
332 // =======================================================================
333 void OpenGl_View::GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData)
334 {
335   myGTrihedronData = theTrihedronData;
336   myGTrihedronData.PtrView = this;
337   myGTrihedronData.CubicAxesCallback = SetMinMaxValuesCallback;
338   myGraduatedTrihedron.SetValues (myGTrihedronData);
339   myToShowGradTrihedron = true;
340 }
341
342 // =======================================================================
343 // function : GraduatedTrihedronErase
344 // purpose  :
345 // =======================================================================
346 void OpenGl_View::GraduatedTrihedronErase()
347 {
348   myGTrihedronData.PtrView = NULL;
349   myGraduatedTrihedron.Release (myWorkspace->GetGlContext().operator->());
350   myToShowGradTrihedron = false;
351 }
352
353 // =======================================================================
354 // function : GraduatedTrihedronMinMaxValues
355 // purpose  :
356 // =======================================================================
357 void OpenGl_View::GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax)
358 {
359   myGraduatedTrihedron.SetMinMax (theMin, theMax);
360 }
361
362 // =======================================================================
363 // function : BufferDump
364 // purpose  :
365 // =======================================================================
366 Standard_Boolean OpenGl_View::BufferDump (Image_PixMap& theImage, const Graphic3d_BufferType& theBufferType)
367 {
368   if (theBufferType != Graphic3d_BT_RGB_RayTraceHdrLeft)
369   {
370     return myWorkspace->BufferDump(myFBO, theImage, theBufferType);
371   }
372
373   if (!myRaytraceParameters.AdaptiveScreenSampling)
374   {
375     return myWorkspace->BufferDump(myAccumFrames % 2 ? myRaytraceFBO2[0] : myRaytraceFBO1[0], theImage, theBufferType);
376   }
377
378 #if defined(GL_ES_VERSION_2_0)
379   return false;
380 #else
381   if (theImage.Format() != Image_Format_RGBF)
382   {
383     return false;
384   }
385
386   const GLuint aW = myRaytraceOutputTexture[0]->SizeX();
387   const GLuint aH = myRaytraceOutputTexture[0]->SizeY();
388   if (aW / 3 != theImage.SizeX() || aH / 2 != theImage.SizeY())
389   {
390     return false;
391   }
392
393   std::vector<GLfloat> aValues;
394   try
395   {
396     aValues.resize (aW * aH);
397   }
398   catch (const std::bad_alloc&)
399   {
400     return false;
401   }
402
403   glBindTexture (GL_TEXTURE_RECTANGLE, myRaytraceOutputTexture[0]->TextureId());
404   glGetTexImage (GL_TEXTURE_RECTANGLE, 0, OpenGl_TextureFormat::Create<GLfloat, 1>().Format(), GL_FLOAT, &aValues[0]);
405   glBindTexture (GL_TEXTURE_RECTANGLE, 0);
406   for (unsigned int aRow = 0; aRow < aH; aRow += 2)
407   {
408     for (unsigned int aCol = 0; aCol < aW; aCol += 3)
409     {
410       float* anImageValue = theImage.ChangeValue<float[3]> ((aH - aRow) / 2 - 1, aCol / 3);
411       float aInvNbSamples = 1.f / aValues[aRow * aW + aCol + aW];
412       anImageValue[0] = aValues[aRow * aW + aCol] * aInvNbSamples;
413       anImageValue[1] = aValues[aRow * aW + aCol + 1] * aInvNbSamples;
414       anImageValue[2] = aValues[aRow * aW + aCol + 1 + aW] * aInvNbSamples;
415     }
416   }
417
418   return true;
419 #endif
420 }
421
422 // =======================================================================
423 // function : Background
424 // purpose  :
425 // =======================================================================
426 Aspect_Background OpenGl_View::Background() const
427 {
428   return Aspect_Background (myBgColor.GetRGB());
429 }
430
431 // =======================================================================
432 // function : SetBackground
433 // purpose  :
434 // =======================================================================
435 void OpenGl_View::SetBackground (const Aspect_Background& theBackground)
436 {
437   myBgColor.SetRGB (theBackground.Color());
438 }
439
440 // =======================================================================
441 // function : GradientBackground
442 // purpose  :
443 // =======================================================================
444 Aspect_GradientBackground OpenGl_View::GradientBackground() const
445 {
446   Quantity_Color aColor1, aColor2;
447   aColor1.SetValues (myBgGradientArray->GradientColor (0).r(),
448                      myBgGradientArray->GradientColor (0).g(),
449                      myBgGradientArray->GradientColor (0).b(), Quantity_TOC_RGB);
450   aColor2.SetValues (myBgGradientArray->GradientColor (1).r(),
451                      myBgGradientArray->GradientColor (1).g(),
452                      myBgGradientArray->GradientColor (1).b(), Quantity_TOC_RGB);
453   return Aspect_GradientBackground (aColor1, aColor2, myBgGradientArray->GradientFillMethod());
454 }
455
456 // =======================================================================
457 // function : SetGradientBackground
458 // purpose  :
459 // =======================================================================
460 void OpenGl_View::SetGradientBackground (const Aspect_GradientBackground& theBackground)
461 {
462   Quantity_Color aColor1, aColor2;
463   theBackground.Colors (aColor1, aColor2);
464   myBgGradientArray->SetGradientParameters (aColor1, aColor2, theBackground.BgGradientFillMethod());
465 }
466
467 // =======================================================================
468 // function : SetBackgroundImage
469 // purpose  :
470 // =======================================================================
471 void OpenGl_View::SetBackgroundImage (const TCollection_AsciiString& theFilePath)
472 {
473   // Prepare aspect for texture storage
474   myBackgroundImagePath = theFilePath;
475   Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
476   Handle(Graphic3d_Texture2Dmanual) aTextureMap = new Graphic3d_Texture2Dmanual (TCollection_AsciiString (theFilePath));
477   aTextureMap->EnableRepeat();
478   aTextureMap->DisableModulate();
479   aTextureMap->GetParams()->SetGenMode (Graphic3d_TOTM_MANUAL,
480                                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
481                                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
482   anAspect->SetTextureMap (aTextureMap);
483   anAspect->SetInteriorStyle (Aspect_IS_SOLID);
484   anAspect->SetSuppressBackFaces (false);
485   // Enable texture mapping
486   if (aTextureMap->IsDone())
487   {
488     anAspect->SetTextureMapOn();
489   }
490   else
491   {
492     anAspect->SetTextureMapOff();
493     return;
494   }
495
496   // Set texture parameters
497   myTextureParams->SetAspect (anAspect);
498 }
499
500 // =======================================================================
501 // function : BackgroundImageStyle
502 // purpose  :
503 // =======================================================================
504 Aspect_FillMethod OpenGl_View::BackgroundImageStyle() const
505 {
506   return myBgTextureArray->TextureFillMethod();
507 }
508
509 // =======================================================================
510 // function : SetBackgroundImageStyle
511 // purpose  :
512 // =======================================================================
513 void OpenGl_View::SetBackgroundImageStyle (const Aspect_FillMethod theFillStyle)
514 {
515   myBgTextureArray->SetTextureFillMethod (theFillStyle);
516 }
517
518 //=======================================================================
519 //function : AddZLayer
520 //purpose  :
521 //=======================================================================
522 void OpenGl_View::AddZLayer (const Graphic3d_ZLayerId theLayerId)
523 {
524   myZLayers.AddLayer (theLayerId);
525 }
526
527 //=======================================================================
528 //function : RemoveZLayer
529 //purpose  :
530 //=======================================================================
531 void OpenGl_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
532 {
533   myZLayers.RemoveLayer (theLayerId);
534 }
535
536 //=======================================================================
537 //function : SetZLayerSettings
538 //purpose  :
539 //=======================================================================
540 void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId        theLayerId,
541                                      const Graphic3d_ZLayerSettings& theSettings)
542 {
543   myZLayers.SetLayerSettings (theLayerId, theSettings);
544 }
545
546 //=======================================================================
547 //function : ZLayerMax
548 //purpose  :
549 //=======================================================================
550 Standard_Integer OpenGl_View::ZLayerMax() const
551 {
552   Standard_Integer aLayerMax = Graphic3d_ZLayerId_Default;
553   for (OpenGl_LayerSeqIds::Iterator aMapIt(myZLayers.LayerIDs()); aMapIt.More(); aMapIt.Next())
554   {
555     aLayerMax = Max (aLayerMax, aMapIt.Value());
556   }
557
558   return aLayerMax;
559 }
560
561 //=======================================================================
562 //function : InvalidateZLayerBoundingBox
563 //purpose  :
564 //=======================================================================
565 void OpenGl_View::InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const
566 {
567   if (myZLayers.LayerIDs().IsBound (theLayerId))
568   {
569     myZLayers.Layer (theLayerId).InvalidateBoundingBox();
570   }
571   else
572   {
573     const Standard_Integer aLayerMax = ZLayerMax();
574     for (Standard_Integer aLayerId = Graphic3d_ZLayerId_Default; aLayerId < aLayerMax; ++aLayerId)
575     {
576       if (myZLayers.LayerIDs().IsBound (aLayerId))
577       {
578         const OpenGl_Layer& aLayer = myZLayers.Layer (aLayerId);
579         if (aLayer.NbOfTransformPersistenceObjects() > 0)
580         {
581           aLayer.InvalidateBoundingBox();
582         }
583       }
584     }
585   }
586 }
587
588 //=======================================================================
589 //function : ZLayerBoundingBox
590 //purpose  :
591 //=======================================================================
592 Bnd_Box OpenGl_View::ZLayerBoundingBox (const Graphic3d_ZLayerId        theLayerId,
593                                         const Handle(Graphic3d_Camera)& theCamera,
594                                         const Standard_Integer          theWindowWidth,
595                                         const Standard_Integer          theWindowHeight,
596                                         const Standard_Boolean          theToIncludeAuxiliary) const
597 {
598   Bnd_Box aBox;
599   if (myZLayers.LayerIDs().IsBound (theLayerId))
600   {
601     aBox = myZLayers.Layer (theLayerId).BoundingBox (Identification(),
602                                                      theCamera,
603                                                      theWindowWidth,
604                                                      theWindowHeight,
605                                                      theToIncludeAuxiliary);
606   }
607
608   // add bounding box of gradient/texture background for proper Z-fit
609   if (theToIncludeAuxiliary
610    && theLayerId == Graphic3d_ZLayerId_BotOSD
611    && (myBgTextureArray->IsDefined()
612     || myBgGradientArray->IsDefined()))
613   {
614     // Background is drawn using 2D transformation persistence
615     // (e.g. it is actually placed in 3D coordinates within active camera position).
616     // We add here full-screen plane with 2D transformation persistence
617     // for simplicity (myBgTextureArray might define a little bit different options
618     // but it is updated within ::Render())
619     const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix();
620     const Graphic3d_Mat4d& aWorldViewMat  = theCamera->OrientationMatrix();
621     Graphic3d_BndBox3d aBox2d (Graphic3d_Vec3d (0.0, 0.0, 0.0),
622                                Graphic3d_Vec3d (double(theWindowWidth), double(theWindowHeight), 0.0));
623
624     Graphic3d_TransformPers aTrsfPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER);
625     aTrsfPers.Apply (theCamera,
626                      aProjectionMat,
627                      aWorldViewMat,
628                      theWindowWidth,
629                      theWindowHeight,
630                      aBox2d);
631     aBox.Add (gp_Pnt (aBox2d.CornerMin().x(), aBox2d.CornerMin().y(), aBox2d.CornerMin().z()));
632     aBox.Add (gp_Pnt (aBox2d.CornerMax().x(), aBox2d.CornerMax().y(), aBox2d.CornerMax().z()));
633   }
634
635   return aBox;
636 }
637
638 //=======================================================================
639 //function : considerZoomPersistenceObjects
640 //purpose  :
641 //=======================================================================
642 Standard_Real OpenGl_View::considerZoomPersistenceObjects (const Graphic3d_ZLayerId        theLayerId,
643                                                            const Handle(Graphic3d_Camera)& theCamera,
644                                                            const Standard_Integer          theWindowWidth,
645                                                            const Standard_Integer          theWindowHeight) const
646 {
647   if (myZLayers.LayerIDs().IsBound (theLayerId))
648   {
649     return myZLayers.Layer (theLayerId).considerZoomPersistenceObjects (Identification(),
650                                                                         theCamera,
651                                                                         theWindowWidth,
652                                                                         theWindowHeight);
653   }
654
655   return 1.0;
656 }
657
658 //=======================================================================
659 //function : FBO
660 //purpose  :
661 //=======================================================================
662 Handle(Standard_Transient) OpenGl_View::FBO() const
663 {
664   return Handle(Standard_Transient)(myFBO);
665 }
666
667 //=======================================================================
668 //function : SetFBO
669 //purpose  :
670 //=======================================================================
671 void OpenGl_View::SetFBO (const Handle(Standard_Transient)& theFbo)
672 {
673   myFBO = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
674 }
675
676 //=======================================================================
677 //function : FBOCreate
678 //purpose  :
679 //=======================================================================
680 Handle(Standard_Transient) OpenGl_View::FBOCreate (const Standard_Integer theWidth,
681                                                    const Standard_Integer theHeight)
682 {
683   return myWorkspace->FBOCreate (theWidth, theHeight);
684 }
685
686 //=======================================================================
687 //function : FBORelease
688 //purpose  :
689 //=======================================================================
690 void OpenGl_View::FBORelease (Handle(Standard_Transient)& theFbo)
691 {
692   Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
693   if (aFrameBuffer.IsNull())
694   {
695     return;
696   }
697
698   myWorkspace->FBORelease (aFrameBuffer);
699   theFbo.Nullify();
700 }
701
702 //=======================================================================
703 //function : FBOGetDimensions
704 //purpose  :
705 //=======================================================================
706 void OpenGl_View::FBOGetDimensions (const Handle(Standard_Transient)& theFbo,
707                                     Standard_Integer& theWidth,
708                                     Standard_Integer& theHeight,
709                                     Standard_Integer& theWidthMax,
710                                     Standard_Integer& theHeightMax)
711 {
712   const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
713   if (aFrameBuffer.IsNull())
714   {
715     return;
716   }
717
718   theWidth     = aFrameBuffer->GetVPSizeX(); // current viewport size
719   theHeight    = aFrameBuffer->GetVPSizeY();
720   theWidthMax  = aFrameBuffer->GetSizeX(); // texture size
721   theHeightMax = aFrameBuffer->GetSizeY();
722 }
723
724 //=======================================================================
725 //function : FBOChangeViewport
726 //purpose  :
727 //=======================================================================
728 void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo,
729                                      const Standard_Integer theWidth,
730                                      const Standard_Integer theHeight)
731 {
732   const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
733   if (aFrameBuffer.IsNull())
734   {
735     return;
736   }
737
738   aFrameBuffer->ChangeViewport (theWidth, theHeight);
739 }
740
741 // =======================================================================
742 // function : Export
743 // purpose  :
744 // =======================================================================
745 #ifdef HAVE_GL2PS
746 Standard_Boolean OpenGl_View::Export (const Standard_CString theFileName,
747                                       const Graphic3d_ExportFormat theFormat,
748                                       const Graphic3d_SortType theSortType)
749 {
750   // gl2psBeginPage() will call OpenGL functions
751   // so we should activate correct GL context before redraw scene call
752   if (!myWorkspace->Activate())
753   {
754     return Standard_False;
755   }
756
757   Standard_Integer aFormat = -1;
758   Standard_Integer aSortType = Graphic3d_ST_BSP_Tree;
759   switch (theFormat)
760   {
761     case Graphic3d_EF_PostScript:
762       aFormat = GL2PS_PS;
763       break;
764     case Graphic3d_EF_EnhPostScript:
765       aFormat = GL2PS_EPS;
766       break;
767     case Graphic3d_EF_TEX:
768       aFormat = GL2PS_TEX;
769       break;
770     case Graphic3d_EF_PDF:
771       aFormat = GL2PS_PDF;
772       break;
773     case Graphic3d_EF_SVG:
774       aFormat = GL2PS_SVG;
775       break;
776     case Graphic3d_EF_PGF:
777       aFormat = GL2PS_PGF;
778       break;
779     case Graphic3d_EF_EMF:
780       //aFormat = GL2PS_EMF;
781       aFormat = GL2PS_PGF + 1; // 6
782       break;
783     default:
784       // unsupported format
785       return Standard_False;
786   }
787
788   switch (theSortType)
789   {
790     case Graphic3d_ST_Simple:
791       aSortType = GL2PS_SIMPLE_SORT;
792       break;
793     case Graphic3d_ST_BSP_Tree:
794       aSortType = GL2PS_BSP_SORT;
795       break;
796   }
797
798   GLint aViewport[4];
799   aViewport[0] = 0;
800   aViewport[1] = 0;
801   aViewport[2] = myWindow->Width();
802   aViewport[3] = myWindow->Height();
803
804   GLint aBufferSize = 1024 * 1024;
805   GLint anErrCode = GL2PS_SUCCESS;
806
807   // gl2ps uses standard write functions and do not check locale
808   Standard_CLocaleSentry aLocaleSentry;
809
810   while (aBufferSize > 0)
811   {
812     // current patch for EMF support in gl2ps uses WinAPI functions to create file
813     FILE* aFileH = (theFormat != Graphic3d_EF_EMF) ? fopen (theFileName, "wb") : NULL;
814     anErrCode = gl2psBeginPage ("", "", aViewport, aFormat, aSortType,
815                     GL2PS_DRAW_BACKGROUND | GL2PS_OCCLUSION_CULL | GL2PS_BEST_ROOT/* | GL2PS_SIMPLE_LINE_OFFSET*/,
816                     GL_RGBA, 0, NULL,
817                     0, 0, 0, aBufferSize, aFileH, theFileName);
818     if (anErrCode != GL2PS_SUCCESS)
819     {
820       // initialization failed
821       if (aFileH != NULL)
822         fclose (aFileH);
823       break;
824     }
825     Redraw();
826
827     anErrCode = gl2psEndPage();
828     if (aFileH != NULL)
829       fclose (aFileH);
830
831     if (anErrCode == GL2PS_OVERFLOW)
832       aBufferSize *= 2;
833     else
834       break;
835   }
836   return anErrCode == GL2PS_SUCCESS;
837 }
838 #else
839 Standard_Boolean OpenGl_View::Export (const Standard_CString /*theFileName*/,
840                                       const Graphic3d_ExportFormat /*theFormat*/,
841                                       const Graphic3d_SortType /*theSortType*/)
842 {
843     return Standard_False;
844 }
845 #endif
846
847 //=======================================================================
848 //function : displayStructure
849 //purpose  :
850 //=======================================================================
851 void OpenGl_View::displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
852                                     const Standard_Integer              thePriority)
853 {
854   const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
855   const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer();
856   myZLayers.AddStructure (aStruct, aZLayer, thePriority);
857 }
858
859 //=======================================================================
860 //function : eraseStructure
861 //purpose  :
862 //=======================================================================
863 void OpenGl_View::eraseStructure (const Handle(Graphic3d_CStructure)& theStructure)
864 {
865   const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
866   myZLayers.RemoveStructure (aStruct);
867 }
868
869 //=======================================================================
870 //function : changeZLayer
871 //purpose  :
872 //=======================================================================
873 void OpenGl_View::changeZLayer (const Handle(Graphic3d_CStructure)& theStructure,
874                                 const Graphic3d_ZLayerId theNewLayerId)
875 {
876   const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer();
877   const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
878   myZLayers.ChangeLayer (aStruct, anOldLayer, theNewLayerId);
879   Update (anOldLayer);
880   Update (theNewLayerId);
881 }
882
883 //=======================================================================
884 //function : changePriority
885 //purpose  :
886 //=======================================================================
887 void OpenGl_View::changePriority (const Handle(Graphic3d_CStructure)& theStructure,
888                                   const Standard_Integer theNewPriority)
889 {
890   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
891   const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
892   myZLayers.ChangePriority (aStruct, aLayerId, theNewPriority);
893 }
894
895 //=======================================================================
896 //function : DiagnosticInformation
897 //purpose  :
898 //=======================================================================
899 void OpenGl_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
900                                          Graphic3d_DiagnosticInfo theFlags) const
901 {
902   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
903   if (!myWorkspace->Activate()
904    || aCtx.IsNull())
905   {
906     return;
907   }
908
909   aCtx->DiagnosticInformation (theDict, theFlags);
910   if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0)
911   {
912     TCollection_AsciiString aResRatio (myRenderParams.ResolutionRatio());
913     theDict.ChangeFromIndex (theDict.Add ("ResolutionRatio", aResRatio)) = aResRatio;
914   }
915 }