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