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