0023428: Extend OpenGl_Context to use Geometry Shaders extension
[occt.git] / src / OpenGl / OpenGl_Workspace_5.cxx
CommitLineData
b311480e 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
2166f0fa 20
5f8b738e 21#include <OpenGl_GlCore11.hxx>
22
2166f0fa
SK
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
498ce577 30#ifdef HAVE_CONFIG_H
31# include <config.h>
32#endif
33
2166f0fa
SK
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
2166f0fa 44#include <OpenGl_TextureBox.hxx>
2166f0fa 45#include <Aspect_PolygonOffsetMode.hxx>
2166f0fa
SK
46#include <OpenGl_View.hxx>
47
48/*----------------------------------------------------------------------*/
49
50static 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
72void 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
395const 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
404const 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
413const 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
422const 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
431const 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
453const 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
479const 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
505const 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
17f65eb2 601const OpenGl_AspectMarker* OpenGl_Workspace::AspectMarker (const Standard_Boolean theToApply)
2166f0fa 602{
17f65eb2 603 if (theToApply && (AspectMarker_set != AspectMarker_applied))
2166f0fa 604 {
17f65eb2 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 }
2166f0fa
SK
612 AspectMarker_applied = AspectMarker_set;
613 }
614 return AspectMarker_set;
615}
616
617/*----------------------------------------------------------------------*/
618
619const 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}