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