0024001: Stereographic rendering support
[occt.git] / src / OpenGl / OpenGl_Workspace_5.cxx
1 // Created on: 2011-08-05
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_GlCore11.hxx>
17
18 #include <OpenGl_Workspace.hxx>
19
20 #include <OpenGl_AspectLine.hxx>
21 #include <OpenGl_AspectFace.hxx>
22 #include <OpenGl_AspectMarker.hxx>
23 #include <OpenGl_AspectText.hxx>
24 #include <OpenGl_Context.hxx>
25 #include <OpenGl_ShaderManager.hxx>
26 #include <OpenGl_telem_util.hxx>
27
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31
32 /* OCC22218 NOTE: project dependency on gl2ps is specified by macro */
33 #ifdef HAVE_GL2PS
34   #include <gl2ps.h>
35   /* OCC22216 NOTE: linker dependency can be switched off by undefining macro.
36      Pragma comment for gl2ps.lib is defined only here. */
37   #ifdef _MSC_VER
38   #pragma comment( lib, "gl2ps.lib" )
39   #endif
40 #endif
41
42 #include <Aspect_PolygonOffsetMode.hxx>
43 #include <OpenGl_View.hxx>
44
45 /*----------------------------------------------------------------------*/
46
47 static void TelUpdatePolygonOffsets( const TEL_POFFSET_PARAM *pdata )
48 {
49   if ( ( pdata->mode & Aspect_POM_Fill ) == Aspect_POM_Fill )
50     glEnable ( GL_POLYGON_OFFSET_FILL );
51   else
52     glDisable ( GL_POLYGON_OFFSET_FILL );
53
54   if ( ( pdata->mode & Aspect_POM_Line ) == Aspect_POM_Line )
55     glEnable ( GL_POLYGON_OFFSET_LINE );
56   else
57     glDisable( GL_POLYGON_OFFSET_LINE );
58
59   if ( ( pdata->mode & Aspect_POM_Point ) == Aspect_POM_Point )
60     glEnable ( GL_POLYGON_OFFSET_POINT );
61   else
62     glDisable( GL_POLYGON_OFFSET_POINT );
63
64   glPolygonOffset( pdata->factor, pdata->units );
65 }
66
67 /*----------------------------------------------------------------------*/
68
69 void OpenGl_Workspace::updateMaterial (const int theFlag)
70 {
71   // Case of hidden line
72   if (AspectFace_set->InteriorStyle() == Aspect_IS_HIDDENLINE)
73   {
74     myAspectFaceHl = *AspectFace_set; // copy all values including line edge aspect
75     myAspectFaceHl.ChangeIntFront().matcol     = BackgroundColor();
76     myAspectFaceHl.ChangeIntFront().color_mask = 0;
77     myAspectFaceHl.ChangeIntFront().color_mask = 0;
78
79     AspectFace_set = &myAspectFaceHl;
80     return;
81   }
82
83   const OPENGL_SURF_PROP* aProps = &AspectFace_set->IntFront();
84   GLenum aFace = GL_FRONT_AND_BACK;
85   if (theFlag == TEL_BACK_MATERIAL)
86   {
87     aFace  = GL_BACK;
88     aProps = &AspectFace_set->IntBack();
89   }
90   else if (AspectFace_set->DistinguishingMode() == TOn
91         && !(NamedStatus & OPENGL_NS_RESMAT))
92   {
93     aFace = GL_FRONT;
94   }
95
96   myMatTmp.Init (*aProps);
97
98   // handling transparency
99   if (NamedStatus & OPENGL_NS_2NDPASSDO)
100   {
101     // second pass
102     myMatTmp.Diffuse.a() = aProps->env_reflexion;
103   }
104   else
105   {
106     if (aProps->env_reflexion != 0.0f)
107     {
108       // if the material reflects the environment scene, the second pass is needed
109       NamedStatus |= OPENGL_NS_2NDPASSNEED;
110     }
111
112     if (myUseTransparency && aProps->trans != 1.0f)
113     {
114       // render transparent
115       myMatTmp.Diffuse.a() = aProps->trans;
116       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
117       glEnable    (GL_BLEND);
118       glDepthMask (GL_FALSE);
119     }
120     else
121     {
122       // render opaque
123       if ((NamedStatus & OPENGL_NS_ANTIALIASING) == 0)
124       {
125         glBlendFunc (GL_ONE, GL_ZERO);
126         glDisable   (GL_BLEND);
127       }
128       glDepthMask (GL_TRUE);
129     }
130   }
131
132   // do not update material properties in case of zero reflection mode,
133   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
134   if (aProps->color_mask == 0)
135   {
136     return;
137   }
138
139   // reset material
140   if (NamedStatus & OPENGL_NS_RESMAT)
141   {
142     glMaterialfv (aFace, GL_AMBIENT,   myMatTmp.Ambient.GetData());
143     glMaterialfv (aFace, GL_DIFFUSE,   myMatTmp.Diffuse.GetData());
144     glMaterialfv (aFace, GL_SPECULAR,  myMatTmp.Specular.GetData());
145     glMaterialfv (aFace, GL_EMISSION,  myMatTmp.Emission.GetData());
146     glMaterialf  (aFace, GL_SHININESS, myMatTmp.Shine());
147
148     if (theFlag == TEL_FRONT_MATERIAL)
149     {
150       myMatFront = myMatTmp;
151       myMatBack  = myMatTmp;
152     }
153     else
154     {
155       myMatBack = myMatTmp;
156     }
157
158     NamedStatus &= ~OPENGL_NS_RESMAT;
159     return;
160   }
161
162   // reduce updates
163   OpenGl_Material& anOld = (theFlag == TEL_FRONT_MATERIAL)
164                          ? myMatFront
165                          : myMatBack;
166
167   if (myMatTmp.Ambient.r() != anOld.Ambient.r()
168    || myMatTmp.Ambient.g() != anOld.Ambient.g()
169    || myMatTmp.Ambient.b() != anOld.Ambient.b())
170   {
171     glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData());
172   }
173   if (myMatTmp.Diffuse.r() != anOld.Diffuse.r()
174    || myMatTmp.Diffuse.g() != anOld.Diffuse.g()
175    || myMatTmp.Diffuse.b() != anOld.Diffuse.b()
176    || fabs (myMatTmp.Diffuse.a() - anOld.Diffuse.a()) > 0.01f)
177   {
178     glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData());
179   }
180   if (myMatTmp.Specular.r() != anOld.Specular.r()
181    || myMatTmp.Specular.g() != anOld.Specular.g()
182    || myMatTmp.Specular.b() != anOld.Specular.b())
183   {
184     glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData());
185   }
186   if (myMatTmp.Emission.r() != anOld.Emission.r()
187    || myMatTmp.Emission.g() != anOld.Emission.g()
188    || myMatTmp.Emission.b() != anOld.Emission.b())
189   {
190     glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData());
191   }
192   if (myMatTmp.Shine() != anOld.Shine())
193   {
194     glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine());
195   }
196   anOld = myMatTmp;
197   if (aFace == GL_FRONT_AND_BACK)
198   {
199     myMatBack = myMatTmp;
200   }
201 }
202
203 /*----------------------------------------------------------------------*/
204
205 const OpenGl_AspectLine * OpenGl_Workspace::SetAspectLine(const OpenGl_AspectLine *AnAspect)
206 {
207   const OpenGl_AspectLine *AspectLine_old = AspectLine_set;
208   AspectLine_set = AnAspect;
209   return AspectLine_old;
210 }
211
212 /*----------------------------------------------------------------------*/
213
214 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace(const OpenGl_AspectFace *AnAspect)
215 {
216   const OpenGl_AspectFace *AspectFace_old = AspectFace_set;
217   AspectFace_set = AnAspect;
218   return AspectFace_old;
219 }
220
221 /*----------------------------------------------------------------------*/
222
223 const OpenGl_AspectMarker * OpenGl_Workspace::SetAspectMarker(const OpenGl_AspectMarker *AnAspect)
224 {
225   const OpenGl_AspectMarker *AspectMarker_old = AspectMarker_set;
226   AspectMarker_set = AnAspect;
227   return AspectMarker_old;
228 }
229
230 /*----------------------------------------------------------------------*/
231
232 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText(const OpenGl_AspectText *AnAspect)
233 {
234   const OpenGl_AspectText *AspectText_old = AspectText_set;
235   AspectText_set = AnAspect;
236   return AspectText_old;
237 }
238
239 /*----------------------------------------------------------------------*/
240
241 const OpenGl_Matrix * OpenGl_Workspace::SetViewMatrix (const OpenGl_Matrix *AMatrix)
242 {
243   const OpenGl_Matrix *ViewMatrix_old = ViewMatrix_applied;
244   ViewMatrix_applied = AMatrix;
245
246   // Update model-view matrix with new view matrix
247   UpdateModelViewMatrix();
248
249   return ViewMatrix_old;
250 }
251
252 /*----------------------------------------------------------------------*/
253
254 const OpenGl_Matrix * OpenGl_Workspace::SetStructureMatrix (const OpenGl_Matrix *AMatrix, bool aRevert)
255 {
256   const OpenGl_Matrix *StructureMatrix_old = StructureMatrix_applied;
257   StructureMatrix_applied = AMatrix;
258
259   OpenGl_Matrix lmat;
260   OpenGl_Transposemat3( &lmat, AMatrix );
261
262   // Update model-view matrix with new structure matrix
263   UpdateModelViewMatrix();
264
265   if (!myGlContext->ShaderManager()->IsEmpty())
266   {
267     if (aRevert)
268     {
269       myGlContext->ShaderManager()->RevertModelWorldStateTo (&lmat.mat);
270     }
271     else
272     {
273       myGlContext->ShaderManager()->UpdateModelWorldStateTo (&lmat.mat);
274     }
275   }
276
277   return StructureMatrix_old;
278 }
279
280 /*----------------------------------------------------------------------*/
281
282 const void OpenGl_Workspace::UpdateModelViewMatrix()
283 {
284   OpenGl_Matrix aStructureMatT;
285   OpenGl_Transposemat3( &aStructureMatT, StructureMatrix_applied);
286
287   glMatrixMode (GL_MODELVIEW);
288   OpenGl_Multiplymat3 (&myModelViewMatrix, &aStructureMatT, ViewMatrix_applied);
289   glLoadMatrixf ((const GLfloat* )&myModelViewMatrix.mat);
290 }
291
292 /*----------------------------------------------------------------------*/
293
294 const OpenGl_AspectLine * OpenGl_Workspace::AspectLine(const Standard_Boolean WithApply)
295 {
296   if ( WithApply && (AspectLine_set != AspectLine_applied) )
297   {
298     glColor3fv(AspectLine_set->Color().rgb);
299
300     if ( !AspectLine_applied || (AspectLine_set->Type() != AspectLine_applied->Type() ) )
301     {
302       myDisplay->SetTypeOfLine(AspectLine_set->Type());
303     }
304
305     if ( !AspectLine_applied || ( AspectLine_set->Width() != AspectLine_applied->Width() ) )
306     {
307       glLineWidth( (GLfloat)AspectLine_set->Width() );
308 #ifdef HAVE_GL2PS
309       gl2psLineWidth( (GLfloat)AspectLine_set->Width() );
310 #endif
311     }
312
313     AspectLine_applied = AspectLine_set;
314   }
315   return AspectLine_set;
316 }
317
318 /*----------------------------------------------------------------------*/
319
320 const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean theToApply)
321 {
322   if (!theToApply)
323   {
324     return AspectFace_set;
325   }
326
327   if (!ActiveView()->Backfacing())
328   {
329     // manage back face culling mode, disable culling when clipping is enabled
330     TelCullMode aCullingMode = (myGlContext->Clipping().IsClippingOrCappingOn()
331                              || AspectFace_set->InteriorStyle() == Aspect_IS_HATCH)
332                              ? TelCullNone
333                              : (TelCullMode )AspectFace_set->CullingMode();
334     if (aCullingMode != TelCullNone
335      && myUseTransparency && !(NamedStatus & OPENGL_NS_2NDPASSDO))
336     {
337       // disable culling in case of translucent shading aspect
338       if (AspectFace_set->IntFront().trans != 1.0f)
339       {
340         aCullingMode = TelCullNone;
341       }
342     }
343     if (myCullingMode != aCullingMode)
344     {
345       myCullingMode = aCullingMode;
346       switch (myCullingMode)
347       {
348         case TelCullNone:
349         case TelCullUndefined:
350         {
351           glDisable (GL_CULL_FACE);
352           break;
353         }
354         case TelCullFront:
355         {
356           glCullFace (GL_FRONT);
357           glEnable (GL_CULL_FACE);
358           break;
359         }
360         case TelCullBack:
361         {
362           glCullFace (GL_BACK);
363           glEnable (GL_CULL_FACE);
364           break;
365         }
366       }
367     }
368   }
369
370   if (AspectFace_set == AspectFace_applied)
371   {
372     return AspectFace_set;
373   }
374
375   const Aspect_InteriorStyle anIntstyle = AspectFace_set->InteriorStyle();
376   if (AspectFace_applied == NULL || AspectFace_applied->InteriorStyle() != anIntstyle)
377   {
378     switch (anIntstyle)
379     {
380       case Aspect_IS_EMPTY:
381       case Aspect_IS_HOLLOW:
382       {
383         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
384         break;
385       }
386       case Aspect_IS_HATCH:
387       {
388         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
389         myDisplay->SetTypeOfHatch (AspectFace_applied != NULL ? AspectFace_applied->Hatch() : TEL_HS_SOLID);
390         break;
391       }
392       case Aspect_IS_SOLID:
393       case Aspect_IS_HIDDENLINE:
394       {
395         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
396         glDisable (GL_POLYGON_STIPPLE);
397         break;
398       }
399       case Aspect_IS_POINT:
400       {
401         glPolygonMode (GL_FRONT_AND_BACK, GL_POINT);
402         break;
403       }
404     }
405   }
406
407   if (anIntstyle == Aspect_IS_HATCH)
408   {
409     const Tint hatchstyle = AspectFace_set->Hatch();
410     if (AspectFace_applied == NULL || AspectFace_applied->Hatch() != hatchstyle)
411     {
412       myDisplay->SetTypeOfHatch(hatchstyle);
413     }
414   }
415
416   // Aspect_POM_None means: do not change current settings
417   if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None)
418   {
419     if (PolygonOffset_applied         == NULL
420      || PolygonOffset_applied->mode   != AspectFace_set->PolygonOffset().mode
421      || PolygonOffset_applied->factor != AspectFace_set->PolygonOffset().factor
422      || PolygonOffset_applied->units  != AspectFace_set->PolygonOffset().units)
423     {
424       PolygonOffset_applied = &AspectFace_set->PolygonOffset();
425       TelUpdatePolygonOffsets (PolygonOffset_applied);
426     }
427   }
428
429   updateMaterial (TEL_FRONT_MATERIAL);
430   if (AspectFace_set->DistinguishingMode() == TOn)
431   {
432     updateMaterial (TEL_BACK_MATERIAL);
433   }
434
435   if ((NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
436   {
437     if (AspectFace_set->DoTextureMap())
438     {
439       EnableTexture (AspectFace_set->TextureRes (this),
440                      AspectFace_set->TextureParams());
441     }
442     else
443     {
444       DisableTexture();
445     }
446   }
447
448   AspectFace_applied = AspectFace_set;
449   return AspectFace_set;
450 }
451
452 /*----------------------------------------------------------------------*/
453
454 const OpenGl_AspectMarker* OpenGl_Workspace::AspectMarker (const Standard_Boolean theToApply)
455 {
456   if (theToApply && (AspectMarker_set != AspectMarker_applied))
457   {
458     if (!AspectMarker_applied || (AspectMarker_set->Scale() != AspectMarker_applied->Scale()))
459     {
460       glPointSize (AspectMarker_set->Scale());
461     #ifdef HAVE_GL2PS
462       gl2psPointSize (AspectMarker_set->Scale());
463     #endif
464     }
465     AspectMarker_applied = AspectMarker_set;
466   }
467   return AspectMarker_set;
468 }
469
470 /*----------------------------------------------------------------------*/
471
472 const OpenGl_AspectText* OpenGl_Workspace::AspectText (const Standard_Boolean theWithApply)
473 {
474   if (theWithApply)
475   {
476     AspectText_applied = AspectText_set;
477     TextParam_applied  = TextParam_set;
478   }
479
480   return AspectText_set;
481 }