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