0024130: Implementing ray tracing visualization core
[occt.git] / src / OpenGl / OpenGl_Workspace.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #ifdef HAVE_CONFIG_H
22   #include <config.h>
23 #endif
24
25 #include <OpenGl_GlCore15.hxx>
26
27 #include <InterfaceGraphic.hxx>
28
29 #include <OpenGl_AspectLine.hxx>
30 #include <OpenGl_AspectFace.hxx>
31 #include <OpenGl_AspectMarker.hxx>
32 #include <OpenGl_AspectText.hxx>
33 #include <OpenGl_Context.hxx>
34 #include <OpenGl_FrameBuffer.hxx>
35 #include <OpenGl_Texture.hxx>
36 #include <OpenGl_View.hxx>
37 #include <OpenGl_Workspace.hxx>
38 #include <OpenGl_Element.hxx>
39
40 #include <Graphic3d_TextureParams.hxx>
41
42 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
43   #include <OpenGl_AVIWriter.hxx>
44 #endif
45
46 IMPLEMENT_STANDARD_HANDLE(OpenGl_Workspace,OpenGl_Window)
47 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,OpenGl_Window)
48
49 namespace
50 {
51   static const TEL_COLOUR myDefaultHighlightColor = { { 1.F, 1.F, 1.F, 1.F } };
52
53   static const OpenGl_AspectLine myDefaultAspectLine;
54   static const OpenGl_AspectFace myDefaultAspectFace;
55   static const OpenGl_AspectMarker myDefaultAspectMarker;
56   static const OpenGl_AspectText myDefaultAspectText;
57
58   static const OpenGl_TextParam myDefaultTextParam =
59   {
60     16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
61   };
62
63   static const OpenGl_Matrix myDefaultMatrix =
64   {
65     {{ 1.0F, 0.0F, 0.0F, 0.0F },
66      { 0.0F, 1.0F, 0.0F, 0.0F },
67      { 0.0F, 0.0F, 1.0F, 0.0F },
68      { 0.0F, 0.0F, 0.0F, 1.0F }}
69   };
70
71 };
72
73 // =======================================================================
74 // function : OpenGl_Workspace
75 // purpose  :
76 // =======================================================================
77 OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_Display)& theDisplay,
78                                     const CALL_DEF_WINDOW&        theCWindow,
79                                     Aspect_RenderingContext       theGContext,
80                                     const Handle(OpenGl_Caps)&    theCaps,
81                                     const Handle(OpenGl_Context)& theShareCtx)
82 : OpenGl_Window (theDisplay, theCWindow, theGContext, theCaps, theShareCtx),
83   NamedStatus (0),
84   HighlightColor (&myDefaultHighlightColor),
85   //
86   myIsTransientOpen (Standard_False),
87   myRetainMode (Standard_False),
88   myTransientDrawToFront (Standard_True),
89   myUseTransparency (Standard_False),
90   myUseZBuffer (Standard_False),
91   myUseDepthTest (Standard_True),
92   myUseGLLight (Standard_True),
93   myBackBufferRestored (Standard_False),
94   //
95   AspectLine_set (&myDefaultAspectLine),
96   AspectLine_applied (NULL),
97   AspectFace_set (&myDefaultAspectFace),
98   AspectFace_applied (NULL),
99   AspectMarker_set (&myDefaultAspectMarker),
100   AspectMarker_applied (NULL),
101   AspectText_set (&myDefaultAspectText),
102   AspectText_applied (NULL),
103   TextParam_set (&myDefaultTextParam),
104   TextParam_applied (NULL),
105   ViewMatrix_applied (&myDefaultMatrix),
106   StructureMatrix_applied (&myDefaultMatrix),
107   PolygonOffset_applied (NULL)
108 {
109   theDisplay->InitAttributes();
110
111   // General initialization of the context
112
113   // Eviter d'avoir les faces mal orientees en noir.
114   // Pourrait etre utiliser pour detecter les problemes d'orientation
115   glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
116
117   // Optimisation pour le Fog et l'antialiasing
118   glHint (GL_FOG_HINT,            GL_FASTEST);
119   glHint (GL_POINT_SMOOTH_HINT,   GL_FASTEST);
120   glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
121   glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
122
123   // Polygon Offset
124   EnablePolygonOffset();
125
126 #ifdef HAVE_OPENCL
127
128   myComputeInitStatus = OpenGl_CLIS_NONE;
129
130   myViewModificationStatus = 0;
131   myLayersModificationStatus = 0;
132
133   myRaytraceOutputTexture[0] = 0;
134   myRaytraceOutputTexture[1] = 0;
135
136   myIsRaytraceDataValid = Standard_False;
137   myToUpdateRaytraceData = Standard_False;
138
139 #endif
140 }
141
142 // =======================================================================
143 // function : SetImmediateModeDrawToFront
144 // purpose  :
145 // =======================================================================
146 Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
147 {
148   const Standard_Boolean aPrevMode = myTransientDrawToFront;
149   myTransientDrawToFront = theDrawToFrontBuffer;
150   return aPrevMode;
151 }
152
153 // =======================================================================
154 // function : ~OpenGl_Workspace
155 // purpose  :
156 // =======================================================================
157 OpenGl_Workspace::~OpenGl_Workspace()
158 {
159 #ifdef HAVE_OPENCL
160   ReleaseOpenCL();
161 #endif
162 }
163
164 // =======================================================================
165 // function : Activate
166 // purpose  :
167 // =======================================================================
168 Standard_Boolean OpenGl_Workspace::Activate()
169 {
170   if (!OpenGl_Window::Activate())
171     return Standard_False;
172
173   ViewMatrix_applied      = &myDefaultMatrix;
174   StructureMatrix_applied = &myDefaultMatrix;
175
176   ResetAppliedAspect();
177
178   return Standard_True;
179 }
180
181 // =======================================================================
182 // function : UseTransparency
183 // purpose  : call_togl_transparency
184 // =======================================================================
185 void OpenGl_Workspace::UseTransparency (const Standard_Boolean theFlag)
186 {
187   myUseTransparency = theFlag;
188 }
189
190 //=======================================================================
191 //function : ResetAppliedAspect
192 //purpose  : Sets default values of GL parameters in accordance with default aspects
193 //=======================================================================
194 void OpenGl_Workspace::ResetAppliedAspect()
195 {
196   NamedStatus           = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
197   HighlightColor        = &myDefaultHighlightColor;
198   AspectLine_set        = &myDefaultAspectLine;
199   AspectLine_applied    = NULL;
200   AspectFace_set        = &myDefaultAspectFace;
201   AspectFace_applied    = NULL;
202   AspectMarker_set      = &myDefaultAspectMarker;
203   AspectMarker_applied  = NULL;
204   AspectText_set        = &myDefaultAspectText;
205   AspectText_applied    = NULL;
206   TextParam_set         = &myDefaultTextParam;
207   TextParam_applied     = NULL;
208   PolygonOffset_applied = NULL;
209
210   AspectLine(Standard_True);
211   AspectFace(Standard_True);
212   AspectMarker(Standard_True);
213   AspectText(Standard_True);
214 }
215
216 // =======================================================================
217 // function : DisableTexture
218 // purpose  :
219 // =======================================================================
220 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
221 {
222   if (myTextureBound.IsNull())
223   {
224     return myTextureBound;
225   }
226
227   // reset texture matrix because some code may expect it is identity
228   GLint aMatrixMode = GL_TEXTURE;
229   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
230   glMatrixMode (GL_TEXTURE);
231   glLoadIdentity();
232   glMatrixMode (aMatrixMode);
233
234   myTextureBound->Unbind (myGlContext);
235   switch (myTextureBound->GetTarget())
236   {
237     case GL_TEXTURE_1D:
238     {
239       if (myTextureBound->GetParams()->GenMode() != GL_NONE)
240       {
241         glDisable (GL_TEXTURE_GEN_S);
242       }
243       glDisable (GL_TEXTURE_1D);
244       break;
245     }
246     case GL_TEXTURE_2D:
247     {
248       if (myTextureBound->GetParams()->GenMode() != GL_NONE)
249       {
250         glDisable (GL_TEXTURE_GEN_S);
251         glDisable (GL_TEXTURE_GEN_T);
252         if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
253         {
254           glDisable (GL_POINT_SPRITE);
255         }
256       }
257       glDisable (GL_TEXTURE_2D);
258       break;
259     }
260     default: break;
261   }
262
263   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
264   myTextureBound.Nullify();
265   return aPrevTexture;
266 }
267
268 // =======================================================================
269 // function : setTextureParams
270 // purpose  :
271 // =======================================================================
272 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
273                                          const Handle(Graphic3d_TextureParams)& theParams)
274 {
275   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
276   if (aParams.IsNull())
277   {
278     return;
279   }
280
281   GLint aMatrixMode = GL_TEXTURE;
282   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
283
284   // setup texture matrix
285   glMatrixMode (GL_TEXTURE);
286   glLoadIdentity();
287   const Graphic3d_Vec2& aScale = aParams->Scale();
288   const Graphic3d_Vec2& aTrans = aParams->Translation();
289   glScalef     ( aScale.x(),  aScale.y(), 1.0f);
290   glTranslatef (-aTrans.x(), -aTrans.y(), 0.0f);
291   glRotatef (-aParams->Rotation(), 0.0f, 0.0f, 1.0f);
292
293   // setup generation of texture coordinates
294   switch (aParams->GenMode())
295   {
296     case Graphic3d_TOTM_OBJECT:
297     {
298       glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
299       glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
300       if (theTexture->GetTarget() != GL_TEXTURE_1D)
301       {
302         glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
303         glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
304       }
305       break;
306     }
307     case Graphic3d_TOTM_SPHERE:
308     {
309       glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
310       if (theTexture->GetTarget() != GL_TEXTURE_1D)
311       {
312         glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
313       }
314       break;
315     }
316     case Graphic3d_TOTM_EYE:
317     {
318       glMatrixMode (GL_MODELVIEW);
319       glPushMatrix();
320       glLoadIdentity();
321
322       glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
323       glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
324
325       if (theTexture->GetTarget() != GL_TEXTURE_1D)
326       {
327         glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
328         glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
329       }
330       glPopMatrix();
331       break;
332     }
333     case Graphic3d_TOTM_SPRITE:
334     {
335       if (GetGlContext()->core20 != NULL)
336       {
337         glEnable  (GL_POINT_SPRITE);
338         glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
339         glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
340         GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
341       }
342       break;
343     }
344     case Graphic3d_TOTM_MANUAL:
345     default: break;
346   }
347
348   // setup lighting
349   if (aParams->GenMode() != Graphic3d_TOTM_SPRITE)
350   {
351     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aParams->IsModulate() ? GL_MODULATE : GL_DECAL);
352   }
353
354   // setup texture filtering and wrapping
355   //if (theTexture->GetParams() != theParams)
356   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
357   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : GL_CLAMP;
358   switch (theTexture->GetTarget())
359   {
360     case GL_TEXTURE_1D:
361     {
362       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
363       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
364       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
365       break;
366     }
367     case GL_TEXTURE_2D:
368     {
369       GLenum aFilterMin = aFilter;
370       if (theTexture->HasMipmaps())
371       {
372         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
373         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
374         {
375           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
376         }
377         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
378         {
379           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
380         }
381
382         if (myGlContext->extAnis)
383         {
384           // setup degree of anisotropy filter
385           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
386           switch (aParams->AnisoFilter())
387           {
388             case Graphic3d_LOTA_QUALITY:
389             {
390               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aMaxDegree);
391               break;
392             }
393             case Graphic3d_LOTA_MIDDLE:
394             {
395
396               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2));
397               break;
398             }
399             case Graphic3d_LOTA_FAST:
400             {
401               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2);
402               break;
403             }
404             case Graphic3d_LOTA_OFF:
405             default:
406             {
407               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
408               break;
409             }
410           }
411         }
412       }
413       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
414       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
415       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
416       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
417       break;
418     }
419     default: break;
420   }
421
422   switch (theTexture->GetTarget())
423   {
424     case GL_TEXTURE_1D:
425     {
426       if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
427       {
428         glEnable (GL_TEXTURE_GEN_S);
429       }
430       glEnable (GL_TEXTURE_1D);
431       break;
432     }
433     case GL_TEXTURE_2D:
434     {
435       if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
436       {
437         glEnable (GL_TEXTURE_GEN_S);
438         glEnable (GL_TEXTURE_GEN_T);
439       }
440       glEnable (GL_TEXTURE_2D);
441       break;
442     }
443     default: break;
444   }
445
446   glMatrixMode (aMatrixMode); // turn back active matrix
447   theTexture->SetParams (aParams);
448 }
449
450 // =======================================================================
451 // function : EnableTexture
452 // purpose  :
453 // =======================================================================
454 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
455                                                         const Handle(Graphic3d_TextureParams)& theParams)
456 {
457   if (theTexture.IsNull() || !theTexture->IsValid())
458   {
459     return DisableTexture();
460   }
461
462   if (myTextureBound == theTexture
463    && (theParams.IsNull() || theParams == theTexture->GetParams()))
464   {
465     // already bound
466     return myTextureBound;
467   }
468
469   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
470   myTextureBound = theTexture;
471   myTextureBound->Bind (myGlContext);
472   setTextureParams (myTextureBound, theParams);
473
474   return aPrevTexture;
475 }
476
477 // =======================================================================
478 // function : Redraw
479 // purpose  :
480 // =======================================================================
481 void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
482                                const Aspect_CLayer2d& theCUnderLayer,
483                                const Aspect_CLayer2d& theCOverLayer)
484 {
485   if (!Activate())
486   {
487     return;
488   }
489
490   // release pending GL resources
491   Handle(OpenGl_Context) aGlCtx = GetGlContext();
492   aGlCtx->ReleaseDelayed();
493
494   // cache render mode state
495   GLint aRendMode = GL_RENDER;
496   glGetIntegerv (GL_RENDER_MODE,  &aRendMode);
497   aGlCtx->SetFeedback (aRendMode == GL_FEEDBACK);
498
499   Tint toSwap = (aRendMode == GL_RENDER); // swap buffers
500   GLint aViewPortBack[4];
501   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
502   if (aFrameBuffer != NULL)
503   {
504     glGetIntegerv (GL_VIEWPORT, aViewPortBack);
505     aFrameBuffer->SetupViewport (aGlCtx);
506     aFrameBuffer->BindBuffer    (aGlCtx);
507     toSwap = 0; // no need to swap buffers
508   }
509
510 #ifdef HAVE_OPENCL
511   if (!theCView.IsRaytracing || myComputeInitStatus == OpenGl_CLIS_FAIL)
512   {
513 #endif
514     Redraw1 (theCView, theCUnderLayer, theCOverLayer, toSwap);
515     if (aFrameBuffer == NULL || !myTransientDrawToFront)
516     {
517       RedrawImmediatMode();
518     }
519
520     theCView.WasRedrawnGL = Standard_True;
521 #ifdef HAVE_OPENCL
522   }
523   else
524   {
525     int aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
526     int aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
527
528     Raytrace (theCView, aSizeX, aSizeY, toSwap);
529
530     theCView.WasRedrawnGL = Standard_False;
531   }
532 #endif
533
534   if (aFrameBuffer != NULL)
535   {
536     aFrameBuffer->UnbindBuffer (aGlCtx);
537     // move back original viewport
538     glViewport (aViewPortBack[0], aViewPortBack[1], aViewPortBack[2], aViewPortBack[3]);
539   }
540
541 #if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE)
542   if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
543   {
544     GLint params[4];
545     glGetIntegerv (GL_VIEWPORT, params);
546     int nWidth  = params[2] & ~0x7;
547     int nHeight = params[3] & ~0x7;
548
549     const int nBitsPerPixel = 24;
550     GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
551
552     glPixelStorei (GL_PACK_ALIGNMENT, 1);
553     glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
554     OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
555     delete[] aDumpData;
556   }
557 #endif
558
559   // reset render mode state
560   aGlCtx->SetFeedback (Standard_False);
561 }