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