1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
20 #include <OpenGl_GlCore15.hxx>
22 #include <InterfaceGraphic.hxx>
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>
35 #include <Graphic3d_TextureParams.hxx>
37 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
38 #include <OpenGl_AVIWriter.hxx>
41 IMPLEMENT_STANDARD_HANDLE(OpenGl_Workspace,OpenGl_Window)
42 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,OpenGl_Window)
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);
49 static const OpenGl_AspectLine myDefaultAspectLine;
50 static const OpenGl_AspectFace myDefaultAspectFace;
51 static const OpenGl_AspectMarker myDefaultAspectMarker;
52 static const OpenGl_AspectText myDefaultAspectText;
54 static const OpenGl_TextParam myDefaultTextParam =
56 16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
59 static const OpenGl_Matrix myDefaultMatrix =
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 }}
69 // =======================================================================
72 // =======================================================================
73 void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp)
76 if (theProp.color_mask & OPENGL_AMBIENT_MASK)
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,
86 Ambient = THE_BLACK_COLOR;
89 // diffusion component
90 if (theProp.color_mask & OPENGL_DIFFUSE_MASK)
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,
100 Diffuse = THE_BLACK_COLOR;
103 // specular component
104 if (theProp.color_mask & OPENGL_SPECULAR_MASK)
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,
114 Specular = THE_BLACK_COLOR;
117 // emission component
118 if (theProp.color_mask & OPENGL_EMISSIVE_MASK)
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,
128 Emission = THE_BLACK_COLOR;
131 ChangeShine() = theProp.shine;
132 ChangeTransparency() = theProp.trans;
135 // =======================================================================
136 // function : OpenGl_Workspace
138 // =======================================================================
139 OpenGl_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),
146 HighlightColor (&THE_WHITE_COLOR),
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),
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)
173 theDisplay->InitAttributes();
175 // General initialization of the context
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);
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);
188 EnablePolygonOffset();
192 myComputeInitStatus = OpenGl_CLIS_NONE;
194 myViewModificationStatus = 0;
195 myLayersModificationStatus = 0;
197 myIsRaytraceDataValid = Standard_False;
198 myToUpdateRaytraceData = Standard_False;
203 // =======================================================================
204 // function : SetImmediateModeDrawToFront
206 // =======================================================================
207 Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
209 const Standard_Boolean aPrevMode = myTransientDrawToFront;
210 myTransientDrawToFront = theDrawToFrontBuffer;
214 // =======================================================================
215 // function : ~OpenGl_Workspace
217 // =======================================================================
218 OpenGl_Workspace::~OpenGl_Workspace()
225 // =======================================================================
226 // function : Activate
228 // =======================================================================
229 Standard_Boolean OpenGl_Workspace::Activate()
231 if (!OpenGl_Window::Activate())
232 return Standard_False;
234 ViewMatrix_applied = &myDefaultMatrix;
235 StructureMatrix_applied = &myDefaultMatrix;
237 ResetAppliedAspect();
239 return Standard_True;
242 // =======================================================================
243 // function : UseTransparency
244 // purpose : call_togl_transparency
245 // =======================================================================
246 void OpenGl_Workspace::UseTransparency (const Standard_Boolean theFlag)
248 myUseTransparency = theFlag;
251 //=======================================================================
252 //function : ResetAppliedAspect
253 //purpose : Sets default values of GL parameters in accordance with default aspects
254 //=======================================================================
255 void OpenGl_Workspace::ResetAppliedAspect()
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;
272 AspectLine(Standard_True);
273 AspectFace(Standard_True);
274 AspectMarker(Standard_True);
275 AspectText(Standard_True);
278 // =======================================================================
279 // function : DisableTexture
281 // =======================================================================
282 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
284 if (myTextureBound.IsNull())
286 return myTextureBound;
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);
294 glMatrixMode (aMatrixMode);
296 myTextureBound->Unbind (myGlContext);
297 switch (myTextureBound->GetTarget())
301 if (myTextureBound->GetParams()->GenMode() != GL_NONE)
303 glDisable (GL_TEXTURE_GEN_S);
305 glDisable (GL_TEXTURE_1D);
310 if (myTextureBound->GetParams()->GenMode() != GL_NONE)
312 glDisable (GL_TEXTURE_GEN_S);
313 glDisable (GL_TEXTURE_GEN_T);
314 if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
316 glDisable (GL_POINT_SPRITE);
319 glDisable (GL_TEXTURE_2D);
325 Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
326 myTextureBound.Nullify();
330 // =======================================================================
331 // function : setTextureParams
333 // =======================================================================
334 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& theTexture,
335 const Handle(Graphic3d_TextureParams)& theParams)
337 const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
338 if (aParams.IsNull())
343 GLint aMatrixMode = GL_TEXTURE;
344 glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
346 // setup texture matrix
347 glMatrixMode (GL_TEXTURE);
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);
355 // setup generation of texture coordinates
356 switch (aParams->GenMode())
358 case Graphic3d_TOTM_OBJECT:
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)
364 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
365 glTexGenfv (GL_T, GL_OBJECT_PLANE, aParams->GenPlaneT().GetData());
369 case Graphic3d_TOTM_SPHERE:
371 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
372 if (theTexture->GetTarget() != GL_TEXTURE_1D)
374 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
378 case Graphic3d_TOTM_EYE:
380 glMatrixMode (GL_MODELVIEW);
384 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
385 glTexGenfv (GL_S, GL_EYE_PLANE, aParams->GenPlaneS().GetData());
387 if (theTexture->GetTarget() != GL_TEXTURE_1D)
389 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
390 glTexGenfv (GL_T, GL_EYE_PLANE, aParams->GenPlaneT().GetData());
395 case Graphic3d_TOTM_SPRITE:
397 if (GetGlContext()->core20 != NULL)
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);
406 case Graphic3d_TOTM_MANUAL:
411 if (aParams->GenMode() != Graphic3d_TOTM_SPRITE)
413 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aParams->IsModulate() ? GL_MODULATE : GL_DECAL);
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())
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);
431 GLenum aFilterMin = aFilter;
432 if (theTexture->HasMipmaps())
434 aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
435 if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
437 aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
439 else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
441 aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
444 if (myGlContext->extAnis)
446 // setup degree of anisotropy filter
447 const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
448 switch (aParams->AnisoFilter())
450 case Graphic3d_LOTA_QUALITY:
452 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aMaxDegree);
455 case Graphic3d_LOTA_MIDDLE:
458 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2));
461 case Graphic3d_LOTA_FAST:
463 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2);
466 case Graphic3d_LOTA_OFF:
469 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
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);
484 switch (theTexture->GetTarget())
488 if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
490 glEnable (GL_TEXTURE_GEN_S);
492 glEnable (GL_TEXTURE_1D);
497 if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
499 glEnable (GL_TEXTURE_GEN_S);
500 glEnable (GL_TEXTURE_GEN_T);
502 glEnable (GL_TEXTURE_2D);
508 glMatrixMode (aMatrixMode); // turn back active matrix
509 theTexture->SetParams (aParams);
512 // =======================================================================
513 // function : EnableTexture
515 // =======================================================================
516 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)& theTexture,
517 const Handle(Graphic3d_TextureParams)& theParams)
519 if (theTexture.IsNull() || !theTexture->IsValid())
521 return DisableTexture();
524 if (myTextureBound == theTexture
525 && (theParams.IsNull() || theParams == theTexture->GetParams()))
528 return myTextureBound;
531 Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
532 myTextureBound = theTexture;
533 myTextureBound->Bind (myGlContext);
534 setTextureParams (myTextureBound, theParams);
539 // =======================================================================
542 // =======================================================================
543 void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
544 const Aspect_CLayer2d& theCUnderLayer,
545 const Aspect_CLayer2d& theCOverLayer)
552 // release pending GL resources
553 Handle(OpenGl_Context) aGlCtx = GetGlContext();
554 aGlCtx->ReleaseDelayed();
556 // fetch OpenGl context state
557 aGlCtx->FetchState();
559 Tint toSwap = (aGlCtx->IsRender()); // swap buffers
560 GLint aViewPortBack[4];
561 OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
562 if (aFrameBuffer != NULL)
564 glGetIntegerv (GL_VIEWPORT, aViewPortBack);
565 aFrameBuffer->SetupViewport (aGlCtx);
566 aFrameBuffer->BindBuffer (aGlCtx);
567 toSwap = 0; // no need to swap buffers
571 if (!theCView.IsRaytracing || myComputeInitStatus == OpenGl_CLIS_FAIL)
574 Redraw1 (theCView, theCUnderLayer, theCOverLayer, toSwap);
575 if (aFrameBuffer == NULL || !myTransientDrawToFront)
577 RedrawImmediatMode();
580 theCView.WasRedrawnGL = Standard_True;
585 int aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
586 int aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
588 Raytrace (theCView, aSizeX, aSizeY, toSwap);
590 theCView.WasRedrawnGL = Standard_False;
594 if (aFrameBuffer != NULL)
596 aFrameBuffer->UnbindBuffer (aGlCtx);
597 // move back original viewport
598 glViewport (aViewPortBack[0], aViewPortBack[1], aViewPortBack[2], aViewPortBack[3]);
601 #if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE)
602 if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
605 glGetIntegerv (GL_VIEWPORT, params);
606 int nWidth = params[2] & ~0x7;
607 int nHeight = params[3] & ~0x7;
609 const int nBitsPerPixel = 24;
610 GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
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);
619 // reset render mode state
620 aGlCtx->FetchState();