0024428: Implementation of LGPL license
[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 || (AspectFace_set == AspectFace_applied))
323   {
324     return AspectFace_set;
325   }
326
327   const Aspect_InteriorStyle anIntstyle = AspectFace_set->InteriorStyle();
328   if (AspectFace_applied == NULL || AspectFace_applied->InteriorStyle() != anIntstyle)
329   {
330     switch (anIntstyle)
331     {
332       case Aspect_IS_EMPTY:
333       case Aspect_IS_HOLLOW:
334       {
335         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
336         break;
337       }
338       case Aspect_IS_HATCH:
339       {
340         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
341         myDisplay->SetTypeOfHatch (AspectFace_applied != NULL ? AspectFace_applied->Hatch() : TEL_HS_SOLID);
342         break;
343       }
344       case Aspect_IS_SOLID:
345       case Aspect_IS_HIDDENLINE:
346       {
347         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
348         glDisable (GL_POLYGON_STIPPLE);
349         break;
350       }
351       case Aspect_IS_POINT:
352       {
353         glPolygonMode (GL_FRONT_AND_BACK, GL_POINT);
354         break;
355       }
356     }
357   }
358
359   if (anIntstyle == Aspect_IS_HATCH)
360   {
361     const Tint hatchstyle = AspectFace_set->Hatch();
362     if (AspectFace_applied == NULL || AspectFace_applied->Hatch() != hatchstyle)
363     {
364       myDisplay->SetTypeOfHatch(hatchstyle);
365     }
366   }
367
368   if (!ActiveView()->Backfacing())
369   {
370     const Tint aCullingMode = AspectFace_set->CullingMode();
371     if (AspectFace_applied == NULL || AspectFace_applied->CullingMode() != aCullingMode)
372     {
373       switch ((TelCullMode )aCullingMode)
374       {
375         case TelCullNone:
376         {
377           glDisable (GL_CULL_FACE);
378           break;
379         }
380         case TelCullFront:
381         {
382           glCullFace (GL_FRONT);
383           glEnable (GL_CULL_FACE);
384           break;
385         }
386         case TelCullBack:
387         {
388           glCullFace (GL_BACK);
389           glEnable (GL_CULL_FACE);
390           break;
391         }
392       }
393     }
394   }
395
396   // Aspect_POM_None means: do not change current settings
397   if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None)
398   {
399     if (PolygonOffset_applied         == NULL
400      || PolygonOffset_applied->mode   != AspectFace_set->PolygonOffset().mode
401      || PolygonOffset_applied->factor != AspectFace_set->PolygonOffset().factor
402      || PolygonOffset_applied->units  != AspectFace_set->PolygonOffset().units)
403     {
404       PolygonOffset_applied = &AspectFace_set->PolygonOffset();
405       TelUpdatePolygonOffsets (PolygonOffset_applied);
406     }
407   }
408
409   updateMaterial (TEL_FRONT_MATERIAL);
410   if (AspectFace_set->DistinguishingMode() == TOn)
411   {
412     updateMaterial (TEL_BACK_MATERIAL);
413   }
414
415   if ((NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
416   {
417     if (AspectFace_set->DoTextureMap())
418     {
419       EnableTexture (AspectFace_set->TextureRes (this),
420                      AspectFace_set->TextureParams());
421     }
422     else
423     {
424       DisableTexture();
425     }
426   }
427
428   AspectFace_applied = AspectFace_set;
429   return AspectFace_set;
430 }
431
432 /*----------------------------------------------------------------------*/
433
434 const OpenGl_AspectMarker* OpenGl_Workspace::AspectMarker (const Standard_Boolean theToApply)
435 {
436   if (theToApply && (AspectMarker_set != AspectMarker_applied))
437   {
438     if (!AspectMarker_applied || (AspectMarker_set->Scale() != AspectMarker_applied->Scale()))
439     {
440       glPointSize (AspectMarker_set->Scale());
441     #ifdef HAVE_GL2PS
442       gl2psPointSize (AspectMarker_set->Scale());
443     #endif
444     }
445     AspectMarker_applied = AspectMarker_set;
446   }
447   return AspectMarker_set;
448 }
449
450 /*----------------------------------------------------------------------*/
451
452 const OpenGl_AspectText* OpenGl_Workspace::AspectText (const Standard_Boolean theWithApply)
453 {
454   if (theWithApply)
455   {
456     AspectText_applied = AspectText_set;
457     TextParam_applied  = TextParam_set;
458   }
459
460   return AspectText_set;
461 }