0024228: TKOpenGL - destroy GL context at view close
[occt.git] / src / OpenGl / OpenGl_Workspace_5.cxx
1 // Created on: 2011-08-05
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 #include <OpenGl_GlCore11.hxx>
22
23 #include <OpenGl_Workspace.hxx>
24
25 #include <OpenGl_AspectLine.hxx>
26 #include <OpenGl_AspectFace.hxx>
27 #include <OpenGl_AspectMarker.hxx>
28 #include <OpenGl_AspectText.hxx>
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 /* OCC22218 NOTE: project dependency on gl2ps is specified by macro */
35 #ifdef HAVE_GL2PS
36   #include <gl2ps.h>
37   /* OCC22216 NOTE: linker dependency can be switched off by undefining macro.
38      Pragma comment for gl2ps.lib is defined only here. */
39   #ifdef _MSC_VER
40   #pragma comment( lib, "gl2ps.lib" )
41   #endif
42 #endif
43
44 #include <Aspect_PolygonOffsetMode.hxx>
45 #include <OpenGl_View.hxx>
46
47 /*----------------------------------------------------------------------*/
48
49 static void TelUpdatePolygonOffsets( const TEL_POFFSET_PARAM *pdata )
50 {
51   if ( ( pdata->mode & Aspect_POM_Fill ) == Aspect_POM_Fill )
52     glEnable ( GL_POLYGON_OFFSET_FILL );
53   else
54     glDisable ( GL_POLYGON_OFFSET_FILL );
55
56   if ( ( pdata->mode & Aspect_POM_Line ) == Aspect_POM_Line )
57     glEnable ( GL_POLYGON_OFFSET_LINE );
58   else
59     glDisable( GL_POLYGON_OFFSET_LINE );
60
61   if ( ( pdata->mode & Aspect_POM_Point ) == Aspect_POM_Point )
62     glEnable ( GL_POLYGON_OFFSET_POINT );
63   else
64     glDisable( GL_POLYGON_OFFSET_POINT );
65
66   glPolygonOffset( pdata->factor, pdata->units );
67 }
68
69 /*----------------------------------------------------------------------*/
70
71 void OpenGl_Workspace::UpdateMaterial( const int flag )
72 {
73   // Case of hidden line
74   if (AspectFace_set->InteriorStyle() == Aspect_IS_HIDDENLINE)
75   {
76     myAspectFaceHl = *AspectFace_set; // copy all values including line edge aspect
77     myAspectFaceHl.ChangeIntFront().matcol     = BackgroundColor();
78     myAspectFaceHl.ChangeIntFront().color_mask = 0;
79     myAspectFaceHl.ChangeIntFront().color_mask = 0;
80
81     AspectFace_set = &myAspectFaceHl;
82     return;
83   }
84
85   const OPENGL_SURF_PROP *prop = NULL;
86   GLenum face = 0;
87   if ( flag == TEL_FRONT_MATERIAL )
88   {
89     prop = &AspectFace_set->IntFront();
90     face = GL_FRONT_AND_BACK;
91   }
92   else
93   {
94     prop = &AspectFace_set->IntBack();
95     face = GL_BACK;
96   }
97
98   // Handling transparency
99   if ( (NamedStatus & OPENGL_NS_2NDPASSDO) == 0 )
100   {
101     if ( myUseTransparency && prop->trans != 1.0F )
102     {
103       // Render transparent
104       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
105       glEnable (GL_BLEND);
106       glDepthMask (GL_FALSE);
107     }
108     else
109     {
110       // Render opaque
111       if ( (NamedStatus & OPENGL_NS_ANTIALIASING) == 0 )
112       {
113         glBlendFunc (GL_ONE, GL_ZERO);
114         glDisable (GL_BLEND);
115       }
116       glDepthMask (GL_TRUE);
117     }
118   }
119
120   // Obtaining reflection mode flags to update GL material properties
121   const unsigned int aReflectionMode = prop->color_mask;
122
123   // Do not update material properties in case of zero reflection mode, 
124   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray()
125   // anyway.
126   if ( !aReflectionMode ) return;
127
128   static float  mAmb[4];
129   static float  mDiff[4];
130   static float  mSpec[4];
131   static float  mEmsv[4];
132   static float  mShin;
133
134   static const float defspeccol[4] = { 1.F, 1.F, 1.F, 1.F };
135
136   // Reset material
137   if ( NamedStatus & OPENGL_NS_RESMAT )
138   {
139     // Ambient component
140     if( aReflectionMode & OPENGL_AMBIENT_MASK )
141     {
142       const float *c = prop->isphysic? prop->ambcol.rgb : prop->matcol.rgb;
143
144       mAmb[0] = prop->amb * c[0];
145       mAmb[1] = prop->amb * c[1];
146       mAmb[2] = prop->amb * c[2];
147     }
148     else
149     {
150       mAmb[0] = 0.F;
151       mAmb[1] = 0.F;
152       mAmb[2] = 0.F;
153     }
154     mAmb[3] = 1.F;
155
156     // Diffusion component
157     if( aReflectionMode & OPENGL_DIFFUSE_MASK )
158     {
159       const float *c = prop->isphysic? prop->difcol.rgb : prop->matcol.rgb;
160
161       mDiff[0] = prop->diff * c[0];
162       mDiff[1] = prop->diff * c[1];
163       mDiff[2] = prop->diff * c[2];
164     }
165     else
166     {
167       mDiff[0] = 0.F;
168       mDiff[1] = 0.F;
169       mDiff[2] = 0.F;
170     }
171     mDiff[3] = 1.F;
172
173     if (NamedStatus & OPENGL_NS_2NDPASSDO)
174     {
175       mDiff[3] = prop->env_reflexion;
176     }
177     else
178     {
179       if (myUseTransparency) mDiff[3] = prop->trans;
180       // If the material reflects the environment scene, the second pass is needed
181       if (prop->env_reflexion != 0.0) NamedStatus |= OPENGL_NS_2NDPASSNEED;
182     }
183
184     // Specular component
185     if( aReflectionMode & OPENGL_SPECULAR_MASK )
186     {
187       const float *c = prop->isphysic? prop->speccol.rgb : defspeccol;
188
189       mSpec[0] = prop->spec * c[0];
190       mSpec[1] = prop->spec * c[1];
191       mSpec[2] = prop->spec * c[2];
192     }
193     else {
194       mSpec[0] = 0.F;
195       mSpec[1] = 0.F;
196       mSpec[2] = 0.F;
197     }
198     mSpec[3] = 1.F;
199
200     // Emissive component
201     if( aReflectionMode & OPENGL_EMISSIVE_MASK )
202     {
203       const float *c = prop->isphysic? prop->emscol.rgb : prop->matcol.rgb;
204
205       mEmsv[0] = prop->emsv * c[0];
206       mEmsv[1] = prop->emsv * c[1];
207       mEmsv[2] = prop->emsv * c[2];
208     }
209     else {
210       mEmsv[0] = 0.F;
211       mEmsv[1] = 0.F;
212       mEmsv[2] = 0.F;
213     }
214     mEmsv[3] = 1.F;
215
216     /* Coeficient de brillance */
217     mShin = prop->shine;
218
219     glMaterialfv(face, GL_AMBIENT, mAmb );
220     glMaterialfv(face, GL_DIFFUSE, mDiff );
221     glMaterialfv(face, GL_SPECULAR, mSpec);
222     glMaterialfv(face, GL_EMISSION, mEmsv);
223     glMaterialf(face, GL_SHININESS, mShin);
224
225     NamedStatus &= ~OPENGL_NS_RESMAT;
226   }
227
228   // Set Material Optimize
229   else
230   {
231     // Ambient component
232     if( aReflectionMode & OPENGL_AMBIENT_MASK )
233     {
234       const float *c = prop->isphysic? prop->ambcol.rgb : prop->matcol.rgb;
235
236       if (mAmb[0] != prop->amb * c[0] ||
237           mAmb[1] != prop->amb * c[1] ||
238           mAmb[2] != prop->amb * c[2] )
239       {
240         mAmb[0] = prop->amb * c[0];
241         mAmb[1] = prop->amb * c[1];
242         mAmb[2] = prop->amb * c[2];
243         mAmb[3] = 1.F;
244
245         glMaterialfv(face, GL_AMBIENT, mAmb);
246       }
247     }
248     else
249     {
250       if ( mAmb[0] != 0.F || mAmb[1] != 0.F || mAmb[2] != 0.F )
251       {
252         mAmb[0] = 0.F;
253         mAmb[1] = 0.F;
254         mAmb[2] = 0.F;
255         mAmb[3] = 1.F;
256
257         glMaterialfv(face, GL_AMBIENT, mAmb);
258       }
259     }
260
261     // Diffusion component
262     if( aReflectionMode & OPENGL_DIFFUSE_MASK )
263     {
264       const float *c = prop->isphysic? prop->difcol.rgb : prop->matcol.rgb;
265
266       if (mDiff[0] != prop->diff * c[0] ||
267           mDiff[1] != prop->diff * c[1] ||
268           mDiff[2] != prop->diff * c[2] ||
269           mDiff[3] != ((NamedStatus & OPENGL_NS_2NDPASSDO)? prop->env_reflexion : (myUseTransparency? prop->trans : 1.0F)))
270       {
271         mDiff[0] = prop->diff * c[0];
272         mDiff[1] = prop->diff * c[1];
273         mDiff[2] = prop->diff * c[2];
274         mDiff[3] = 1.F;
275
276         if (NamedStatus & OPENGL_NS_2NDPASSDO)
277         {
278           mDiff[3] = prop->env_reflexion;
279         }
280         else
281         {
282           if (myUseTransparency) mDiff[3] = prop->trans;
283           // If the material reflects the environment scene, the second pass is needed
284           if (prop->env_reflexion != 0.0) NamedStatus |= OPENGL_NS_2NDPASSNEED;
285         }
286
287         glMaterialfv(face, GL_DIFFUSE, mDiff );
288       }
289     }
290     else
291     {
292       Tfloat newDiff3 = 1.F;
293
294       if (NamedStatus & OPENGL_NS_2NDPASSDO)
295       {
296         newDiff3 = prop->env_reflexion;
297       }
298       else
299       {
300         if (myUseTransparency) newDiff3 = prop->trans;
301         // If the material reflects the environment scene, the second pass is needed
302         if (prop->env_reflexion != 0.0) NamedStatus |= OPENGL_NS_2NDPASSNEED;
303       }
304
305       /* OCC19915: Even if diffuse reflectance is disabled,
306       still trying to update the current transparency if it
307       differs from the previous value  */
308       if ( mDiff[0] != 0.F || mDiff[1] != 0.F || mDiff[2] != 0.F || fabs(mDiff[3] - newDiff3) > 0.01F )
309       {
310         mDiff[0] = 0.F;
311         mDiff[1] = 0.F;
312         mDiff[2] = 0.F;
313         mDiff[3] = newDiff3;
314
315         glMaterialfv(face, GL_DIFFUSE, mDiff);
316       }
317     }
318
319     // Specular component
320     if( aReflectionMode & OPENGL_SPECULAR_MASK )
321     {
322       const float *c = prop->isphysic? prop->speccol.rgb : defspeccol;
323
324       if (mSpec[0] != prop->spec * c[0] ||
325           mSpec[1] != prop->spec * c[1] ||
326           mSpec[2] != prop->spec * c[2])
327       {
328         mSpec[0] = prop->spec * c[0];
329         mSpec[1] = prop->spec * c[1];
330         mSpec[2] = prop->spec * c[2];
331         mSpec[3] = 1.F;
332
333         glMaterialfv(face, GL_SPECULAR, mSpec);
334       }
335     }
336     else
337     {
338       if ( mSpec[0] != 0.F || mSpec[1] != 0.F || mSpec[2] != 0.F )
339       {
340         mSpec[0] = 0.F;
341         mSpec[1] = 0.F;
342         mSpec[2] = 0.F;
343         mSpec[3] = 1.F;
344
345         glMaterialfv(face, GL_SPECULAR, mSpec);
346       }
347     }
348
349     // Emissive component
350     if( aReflectionMode & OPENGL_EMISSIVE_MASK )
351     {
352       const float *c = prop->isphysic? prop->emscol.rgb : prop->matcol.rgb;
353
354       if (mEmsv[0] != prop->emsv * c[0] ||
355           mEmsv[1] != prop->emsv * c[1] ||
356           mEmsv[2] != prop->emsv * c[2])
357       {
358         mEmsv[0] = prop->emsv * c[0];
359         mEmsv[1] = prop->emsv * c[1];
360         mEmsv[2] = prop->emsv * c[2];
361         mEmsv[3] = 1.F;
362
363         glMaterialfv(face, GL_EMISSION, mEmsv);
364       }
365     }
366     else
367     {
368       if ( mEmsv[0] != 0.F || mEmsv[1] != 0.F || mEmsv[2] != 0.F )
369       {
370         mEmsv[0] = 0.F;
371         mEmsv[1] = 0.F;
372         mEmsv[2] = 0.F;
373         mEmsv[3] = 1.F;
374
375         glMaterialfv(face, GL_EMISSION, mEmsv);
376       }
377     }
378
379     // Shining coefficient
380     if( mShin != prop->shine )
381     {
382       mShin = prop->shine;
383       glMaterialf(face, GL_SHININESS, mShin);
384     }
385   }
386 }
387
388 /*----------------------------------------------------------------------*/
389
390 const OpenGl_AspectLine * OpenGl_Workspace::SetAspectLine(const OpenGl_AspectLine *AnAspect)
391 {
392   const OpenGl_AspectLine *AspectLine_old = AspectLine_set;
393   AspectLine_set = AnAspect;
394   return AspectLine_old;
395 }
396
397 /*----------------------------------------------------------------------*/
398
399 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace(const OpenGl_AspectFace *AnAspect)
400 {
401   const OpenGl_AspectFace *AspectFace_old = AspectFace_set;
402   AspectFace_set = AnAspect;
403   return AspectFace_old;
404 }
405
406 /*----------------------------------------------------------------------*/
407
408 const OpenGl_AspectMarker * OpenGl_Workspace::SetAspectMarker(const OpenGl_AspectMarker *AnAspect)
409 {
410   const OpenGl_AspectMarker *AspectMarker_old = AspectMarker_set;
411   AspectMarker_set = AnAspect;
412   return AspectMarker_old;
413 }
414
415 /*----------------------------------------------------------------------*/
416
417 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText(const OpenGl_AspectText *AnAspect)
418 {
419   const OpenGl_AspectText *AspectText_old = AspectText_set;
420   AspectText_set = AnAspect;
421   return AspectText_old;
422 }
423
424 /*----------------------------------------------------------------------*/
425
426 const OpenGl_Matrix * OpenGl_Workspace::SetViewMatrix(const OpenGl_Matrix *AMatrix)
427 {
428   const OpenGl_Matrix *ViewMatrix_old = ViewMatrix_applied;
429   ViewMatrix_applied = AMatrix;
430
431   OpenGl_Matrix lmat;
432   OpenGl_Transposemat3( &lmat, StructureMatrix_applied );
433
434   glMatrixMode (GL_MODELVIEW);
435   OpenGl_Matrix rmat;
436   OpenGl_Multiplymat3 (&rmat, &lmat, ViewMatrix_applied);
437   glLoadMatrixf ((const GLfloat* )rmat.mat);
438
439   return ViewMatrix_old;
440 }
441
442 /*----------------------------------------------------------------------*/
443
444 const OpenGl_Matrix * OpenGl_Workspace::SetStructureMatrix(const OpenGl_Matrix *AMatrix)
445 {
446   const OpenGl_Matrix *StructureMatrix_old = StructureMatrix_applied;
447   StructureMatrix_applied = AMatrix;
448
449   OpenGl_Matrix lmat;
450   OpenGl_Transposemat3( &lmat, AMatrix );
451
452   glMatrixMode (GL_MODELVIEW);
453   OpenGl_Matrix rmat;
454   OpenGl_Multiplymat3 (&rmat, &lmat, ViewMatrix_applied);
455   glLoadMatrixf ((const GLfloat* )rmat.mat);
456
457   return StructureMatrix_old;
458 }
459
460 /*----------------------------------------------------------------------*/
461
462 const OpenGl_AspectLine * OpenGl_Workspace::AspectLine(const Standard_Boolean WithApply)
463 {
464   if ( WithApply && (AspectLine_set != AspectLine_applied) )
465   {
466     glColor3fv(AspectLine_set->Color().rgb);
467
468     if ( !AspectLine_applied || (AspectLine_set->Type() != AspectLine_applied->Type() ) )
469     {
470       myDisplay->SetTypeOfLine(AspectLine_set->Type());
471     }
472
473     if ( !AspectLine_applied || ( AspectLine_set->Width() != AspectLine_applied->Width() ) )
474     {
475       glLineWidth( (GLfloat)AspectLine_set->Width() );
476 #ifdef HAVE_GL2PS
477       gl2psLineWidth( (GLfloat)AspectLine_set->Width() );
478 #endif
479     }
480
481     AspectLine_applied = AspectLine_set;
482   }
483   return AspectLine_set;
484 }
485
486 /*----------------------------------------------------------------------*/
487
488 const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean theToApply)
489 {
490   if (!theToApply || (AspectFace_set == AspectFace_applied))
491   {
492     return AspectFace_set;
493   }
494
495   const Aspect_InteriorStyle anIntstyle = AspectFace_set->InteriorStyle();
496   if (AspectFace_applied == NULL || AspectFace_applied->InteriorStyle() != anIntstyle)
497   {
498     switch (anIntstyle)
499     {
500       case Aspect_IS_EMPTY:
501       case Aspect_IS_HOLLOW:
502       {
503         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
504         break;
505       }
506       case Aspect_IS_HATCH:
507       {
508         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
509         myDisplay->SetTypeOfHatch (AspectFace_applied != NULL ? AspectFace_applied->Hatch() : TEL_HS_SOLID);
510         break;
511       }
512       case Aspect_IS_SOLID:
513       case Aspect_IS_HIDDENLINE:
514       {
515         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
516         glDisable (GL_POLYGON_STIPPLE);
517         break;
518       }
519       case Aspect_IS_POINT: //szvgl - no corresponding enumeration item Aspect_IS_POINT // = 5
520       {
521         glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);
522         break;
523       }
524     }
525   }
526
527   if (anIntstyle == Aspect_IS_HATCH)
528   {
529     const Tint hatchstyle = AspectFace_set->Hatch();
530     if (AspectFace_applied == NULL || AspectFace_applied->Hatch() != hatchstyle)
531     {
532       myDisplay->SetTypeOfHatch(hatchstyle);
533     }
534   }
535
536   if (!ActiveView()->Backfacing())
537   {
538     const Tint aCullingMode = AspectFace_set->CullingMode();
539     if (AspectFace_applied == NULL || AspectFace_applied->CullingMode() != aCullingMode)
540     {
541       switch ((TelCullMode )aCullingMode)
542       {
543         case TelCullNone:
544         {
545           glDisable (GL_CULL_FACE);
546           break;
547         }
548         case TelCullFront:
549         {
550           glCullFace (GL_FRONT);
551           glEnable (GL_CULL_FACE);
552           break;
553         }
554         case TelCullBack:
555         {
556           glCullFace (GL_BACK);
557           glEnable (GL_CULL_FACE);
558           break;
559         }
560       }
561     }
562   }
563
564   // Aspect_POM_None means: do not change current settings
565   if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None)
566   {
567     if (PolygonOffset_applied         == NULL
568      || PolygonOffset_applied->mode   != AspectFace_set->PolygonOffset().mode
569      || PolygonOffset_applied->factor != AspectFace_set->PolygonOffset().factor
570      || PolygonOffset_applied->units  != AspectFace_set->PolygonOffset().units)
571     {
572       PolygonOffset_applied = &AspectFace_set->PolygonOffset();
573       TelUpdatePolygonOffsets (PolygonOffset_applied);
574     }
575   }
576
577   UpdateMaterial (TEL_FRONT_MATERIAL);
578   if (AspectFace_set->DistinguishingMode() == TOn)
579   {
580     UpdateMaterial (TEL_BACK_MATERIAL);
581   }
582
583   if ((NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
584   {
585     if (AspectFace_set->DoTextureMap())
586     {
587       EnableTexture (AspectFace_set->TextureRes (this),
588                      AspectFace_set->TextureParams());
589     }
590     else
591     {
592       DisableTexture();
593     }
594   }
595
596   AspectFace_applied = AspectFace_set;
597   return AspectFace_set;
598 }
599
600 /*----------------------------------------------------------------------*/
601
602 const OpenGl_AspectMarker* OpenGl_Workspace::AspectMarker (const Standard_Boolean theToApply)
603 {
604   if (theToApply && (AspectMarker_set != AspectMarker_applied))
605   {
606     if (!AspectMarker_applied || (AspectMarker_set->Scale() != AspectMarker_applied->Scale()))
607     {
608       glPointSize (AspectMarker_set->Scale());
609     #ifdef HAVE_GL2PS
610       gl2psPointSize (AspectMarker_set->Scale());
611     #endif
612     }
613     AspectMarker_applied = AspectMarker_set;
614   }
615   return AspectMarker_set;
616 }
617
618 /*----------------------------------------------------------------------*/
619
620 const OpenGl_AspectText* OpenGl_Workspace::AspectText (const Standard_Boolean theWithApply)
621 {
622   if (theWithApply)
623   {
624     AspectText_applied = AspectText_set;
625     TextParam_applied  = TextParam_set;
626   }
627
628   return AspectText_set;
629 }