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