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