OCC22108 Cutting plane unpredictable behaviour in V3d_View
[occt.git] / src / OpenGl / OpenGl_view.cxx
1 /***********************************************************************
2
3 FONCTION :
4 ----------
5 File OpenGl_view :
6
7
8 REMARQUES:
9 ---------- 
10
11 An implementation of the PHIGS viewing pipeline
12
13 This module provides services for setting view representations and view
14 indices, viewport management, coordinate conversion routines and help
15 functions.
16
17 The corresponding header file is telem_view.h
18
19
20 HISTORIQUE DES MODIFICATIONS   :
21 --------------------------------
22 xx-xx-xx : xxx ; Creation.
23 11-03-96 : FMN ; Correction warning compilation
24 20-03-96 : CAL ; Modif de TelClearViews
25 appel a call_tox_getscreen pour effacer tout
26 meme apres un resize
27 01-04-96 : CAL ; Integration MINSK portage WNT
28 22-04-96 : FMN ; Suppression prototype inutile.
29 25-06-96 : FMN ; Suppression utilisation de glScissor.
30 28-06-96 : CAL ; Simplification de TelClearViews
31 02-07-96 : FMN ; Suppression WSWSHeight et WSWSWidth
32 Suppression de TelSetWSWindow
33 Suppression glViewport inutile
34 03-07-96 : FMN ; A une workstation correspond une vue.
35 12-07-96 : FMN ; Correction calcul matrice orientatione.
36 17-07-96 : FMN ; Ajout clear pour le zbuffer.
37 21-10-96 : FMN ; Suppression LMC_COLOR fait dans OpenGl_execstruct.c
38 24-01-97 : CAL ; Suppression code inutile (DEBUG_ONLY)
39 30-06-97 : FMN ; Suppression OpenGl_telem_light.h
40 27-08-97 : FMN ; Ajout glDepthMask avant le clear (PRO8939) 
41 09-12-97 : FMN ; Prise en compte environnement mapping. 
42 03-03-98 : FMN ; Suppression variable externe TglWhetherPerspective 
43 13-03-98 : FMN ; Suppression variable WSNeedsClear
44 10-04-98 : CAL ; Suppression du calcul de inverse_matrix
45 30-04-98 : FMN ; Suppression variable externe TglUpdateView0
46 24-11-98 : FMN ; PRO16215: Suppression test sur le GL_MAX_CLIP_PLANES 
47 Si OpenGL n'a pas de plans de clipping on ne le simule pas.
48 24-11-98 : FMN ; Correction sur la gestion de la perspective (cf Programming Guide)
49 - Suppression du test (prp between front and back planes)
50 - Suppression matrice perspective (modify the next two cells to change clipping policy)
51 Ces modifs sont necessaires pour pouvoir mettre le prp entre le Front et Back plane
52
53 ************************************************************************/
54
55 #define BUC60920        /* GG 010601
56 Change the z buffer comparaison for minimizing
57 unavailable or unviewable drawing of pixels in the same plane
58 */
59
60 #define BUC61044       /* 25/10/01 SAV ; added functionality to control gl depth testing
61 from higher API */
62
63 #define OCC1188         /* SAV 23/12/02 TelClearBackground() draws background texture
64 if any was defined
65 */
66
67
68 /*----------------------------------------------------------------------*/
69 /*
70 * Includes
71 */ 
72
73 #include <OpenGl_tgl_all.hxx>
74
75 #include <stddef.h>
76 #include <stdio.h>
77 #include <string.h>
78 #include <stdlib.h>
79
80 #include <OpenGl_cmn_varargs.hxx>
81 #include <OpenGl_telem.hxx>
82 #include <OpenGl_telem_util.hxx>
83 #include <OpenGl_telem_attri.hxx>
84 #include <OpenGl_telem_view.hxx>
85 #include <OpenGl_tsm.hxx>
86 #include <OpenGl_tsm_ws.hxx>
87 #include <OpenGl_txgl.hxx>
88 #include <OpenGl_Memory.hxx>
89 #include <Standard_TypeDef.hxx>
90
91 /*----------------------------------------------------------------------*/
92 /*
93 * Variable globales
94 */
95
96 EXPORT extern GLboolean env_walkthrow; /* definit dans OpenGl_togl_begin.c */
97 /* OCC18942: The new perspective projection matrix is off by default */
98 EXPORT extern GLboolean env_sym_perspective; /* defined in OpenGl_togl_begin.c */
99
100 /*----------------------------------------------------------------------*/
101 /*
102 * Constantes
103 */ 
104
105 #define NO_TRACE_MAT    
106 #define NO_TRACE_MATRIX 
107 #define NO_PRINT
108
109 #define ENVTEX
110
111
112 /*----------------------------------------------------------------------*/
113 /*
114 * Prototypes
115 */
116
117 #ifdef DEB
118 static void pr_matrix( Tmatrix3 );
119 #endif
120
121
122 /*----------------------------------------------------------------------*/
123 /*
124 * Type definitions
125 */
126
127 struct TEL_VIEW_DATA
128 {
129   TEL_VIEW_REP    vrep;
130 #ifdef CAL_100498
131   Tmatrix3        inverse_matrix;/* accelerates UVN2XYZ conversion */
132 #endif
133   IMPLEMENT_MEMORY_OPERATORS
134 };
135 typedef TEL_VIEW_DATA *tel_view_data;   /* Internal data stored for every view rep */
136
137 /*----------------------------------------------------------------------*/
138 /*
139 * Variables statiques
140 */
141
142 static void set_clipplanes( tel_view_rep );      /* front & back clip planes */
143 static void set_userclipplanes( tel_view_rep );  /* user-defined clipping planes */
144
145 #ifdef CAL_100498
146 static  void  TelEvalInverseMatrix( Tfloat*, Tfloat*, Tfloat*, /*vrp,vpn,vup*/
147                                     Tfloat, Tmatrix3 );        /*vpd,inverse*/
148 #endif
149 static  Tmatrix3  ident = {
150   { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
151   { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
152   { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
153   { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 }
154 };
155
156 /*----------------------------------------------------------------------*/
157 /*+
158 Qsearch number comparison routine
159
160 Compares view ids during sorting of the list of defined views
161 for a workstation
162 +*/
163
164 /*----------------------------------------------------------------------*/
165 /*+
166 Evaluate View Mapping Matrix
167
168 This routine computes the mapping matrix based on the Window and Viewport
169 limits, Projection type and View plane, Front plane and Back plane
170 distances.
171 +*/
172
173 static  void
174 EvalViewMappingMatrix( tel_view_mapping mapping /* View Mapping */,
175                        Tint *error_ind          /* Out: Error Indicator */,
176                        Tmatrix3 mat             /* Out: Mapping Matrix * */,
177                        Tint     flag,
178                        Tfloat   cx,
179                        Tfloat   cy,
180                        Tint     clip_flag,
181                        Tlimit3  *clip_limit
182                       )
183 {
184   Tfloat    gx, gy, xsf, ysf, zsf;
185   Tfloat    fpd, bpd;
186
187   /* OCC18942 */
188   Tfloat    n, f, r, l, t, b, Zprp, dx, dy, VPD;
189
190   /* FSXXX */
191   /* GLint gdtmp; */
192   Tlimit3   vp = { ( float )-1.0, ( float )1.0, ( float )-1.0, ( float )1.0, ( float )1.0, ( float )-1.0 };
193   Tmatrix3  pmat = { { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
194   { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
195   { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
196   { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 } };
197   Tmatrix3  mmat = { { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
198   { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
199   { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
200   { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 } };
201
202   fpd = mapping->fpd;
203   bpd = mapping->bpd;
204
205   /* invalid window */
206   if( mapping->window.xmin >= mapping->window.xmax ||
207     mapping->window.ymin >= mapping->window.ymax )
208   {
209     *error_ind = 1;    
210     return;
211   }
212
213   /* invalid viewport */
214   if( mapping->viewport.xmin >= mapping->viewport.xmax ||
215     mapping->viewport.ymin >= mapping->viewport.ymax ||
216     mapping->viewport.zmin >= mapping->viewport.zmax )
217   {
218     *error_ind = 2;   
219     return;
220   }
221
222   /* invalid back/front plane distances */
223   if( mapping->bpd >= mapping->fpd )
224   {
225     *error_ind = 3;   
226     return;
227   }
228
229   /* prp between front and back planes */
230   if (!env_walkthrow)
231   {
232     if( mapping->prp[2] < mapping->fpd &&
233       mapping->prp[2] > mapping->bpd )
234     {
235       *error_ind = 4;   
236       return;
237     } 
238   }
239
240   if( mapping->prp[2] == mapping->vpd )
241   {
242     *error_ind = 5;   /* prp on view plane */
243     return;
244   }
245
246   if( mapping->viewport.xmin < 0 ||
247     mapping->viewport.xmax > 1 ||
248     mapping->viewport.ymin < 0 ||
249     mapping->viewport.ymax > 1 ||
250     mapping->viewport.zmin < 0 ||
251     mapping->viewport.zmax > 1 )
252   {
253     *error_ind = 6;   /* viewport limits outside NPC space */
254     return;
255   }
256
257   *error_ind = 0;
258
259   /* OCC18942: Moved here while debugging perspective projection matrix */
260   /* centers */
261   if( flag == 0 )
262   {
263     cx = mapping->window.xmin + mapping->window.xmax, cx /= ( float )2.0;
264     cy = mapping->window.ymin + mapping->window.ymax, cy /= ( float )2.0;
265   }
266
267   gx = (cx - mapping->prp[0]) / (mapping->vpd - mapping->prp[2]);
268   gy = (cy - mapping->prp[1]) / (mapping->vpd - mapping->prp[2]);
269
270 #ifdef PRINT
271   printf("EvalViewMappingMatrix \n");
272   printf("prp %f %f %f \n", mapping->prp[0], mapping->prp[1], mapping->prp[2]);
273   printf("vpd fpd bpd %f %f %f \n", mapping->vpd, mapping->fpd, mapping->bpd);
274   printf("window limit %f %f %f %f\n", mapping->window.xmin, mapping->window.xmax, 
275     mapping->window.ymin, mapping->window.ymax);
276   printf("viewport limit %f %f %f %f\n", mapping->viewport.xmin, mapping->viewport.xmax, 
277     mapping->viewport.ymin, mapping->viewport.ymax);
278 #endif
279
280   /* projection matrix */
281   if( mapping->proj == TelParallel )
282   {
283
284     pmat[2][0] = -gx; pmat[3][0] = mapping->vpd*gx;
285     pmat[2][1] = -gy; pmat[3][1] = mapping->vpd*gy;
286   }
287   else if ( !env_sym_perspective )/* TelPerspective */
288   {
289     pmat[0][0] = pmat[1][1] = mapping->prp[2] - mapping->vpd;
290     pmat[2][0] = -gx; 
291     pmat[2][1] = -gy; 
292     pmat[2][3] = ( float )-1.0;
293     pmat[3][0] = mapping->vpd * gx; 
294     pmat[3][1] = mapping->vpd * gy; 
295     pmat[3][3] = mapping->prp[2];
296
297     /* modify the next two cells to change clipping policy */
298     if (!env_walkthrow)
299     {
300       pmat[2][2] = mapping->prp[2] - ( fpd + bpd );
301       pmat[3][2] = fpd * bpd; 
302     }
303   }
304   /* OCC18942: New approach to calculation of mapping (projection) matrix */
305   else 
306   {
307     dx = mapping->window.xmax - mapping->window.xmin;
308     dy = mapping->window.ymax - mapping->window.ymin;
309     Zprp = mapping->prp[2];
310     VPD = Zprp - mapping->vpd;
311
312     /* 
313     Calculate canonical perspective projection parameters as if we were about 
314     to use glFrustum() to create symmetric perspective frustum.
315
316     After the view orientation matrix is applied, the coordinate system origin is located 
317     at the VRP and oriented properly. However, the viewplane has width = dx and height = dy 
318     and its center (cx, cy, VPD) is not always located at the view Z axis.
319     The canonical perspective projection matrix assumes the eye is located at (0, 0, 0).
320     Thus the old approach resulted in a non-symmetric perspective, 
321     as X and Y coordinates of the projection reference point (PRP) were not updated
322     when cx and cy changed. Moreover, such "static" perspective had some other disadvantages,
323     such as non-realistic panning, i.e. instead of moving the eye (or camera) over the model
324     a sort of "frame" moved over the static perspective projection picture, 
325     exposing a part of this static picture to the user.
326
327     In order to make the perspective symmetric, we need to translate 
328     the coordinate system to PRP before projection.
329     Thus we translate X, Y and Z co-ordinates by -cx, -cy and -Zprp respectively.
330
331     NOTE: mat[i][j] means j-th element of i-th column, as OpenGL accepts the matrices
332     in column-major order, while in C two-dimensional arrays are stored in memory
333     in row-major order!
334
335     VPD is used below instead of near clipping plane dispance (n) in order to simplify 
336     calculation of l and r values. If we did not use VPD in the matrix calculation, we would have to 
337     project 0.5 * dx, -0.5 * dx, 0.5 * dy and - 0.5 * dy onto the near clipping plane 
338     to calculate these values.
339
340     Pending issues:
341     1. It is still necessary to find a way to calculate the perspective projection matrix 
342     for TPM_WALKTHROUGH projection model. This projection model is not supported yet 
343     by the new code.
344     */
345     r = .5f * dx;
346     l = -r;
347     t = .5f * dy;
348     b = -t;
349     n = Zprp - fpd; f = Zprp - bpd;
350
351     mat[0][0] = 2.f * VPD / (r - l);
352     mat[1][1] = 2.f * VPD / (t - b);
353     mat[2][0] = (r + l) / (r - l);
354     mat[2][1] = (t + b) / (t - b);
355     mat[2][2] = - (f + n) / (f - n);
356     mat[2][3] = -1.f;
357     /* 
358     The last column takes into account translation along X, Y and Z axis
359     before projecting. This can be considered as a result of right-multiplying the canonical 
360     perspective projection matrix P by a translation matrix T 
361     (it differs form the canonical matrix by the last column only):
362     | 1 0 0  -cx  |
363     | 0 1 0  -cy  |
364     mat = P * T, where T = | 0 0 1 -Zprp |
365     | 0 0 0   1   |
366     */
367     mat[3][0] = -mat[2][0] * Zprp - mat[0][0] * cx;
368     mat[3][1] = -mat[2][1] * Zprp - mat[1][1] * cy;
369     mat[3][2] = -2.f * f * n / (f - n) - mat[2][2] * Zprp;
370     mat[3][3] = Zprp;
371
372 #ifdef PRINT
373     printf("r l t b n f: %f %f %f %f %f %f \n", r,l,t,b,n,f);
374     printf( "mapping_matrix (new code):\n" );
375     pr_matrix(mat);
376 #endif
377
378     /* return here, as further calculations are related to the old approach */
379     return;
380   }
381
382   /* scale factors */
383   xsf = (vp.xmax - vp.xmin) / (mapping->window.xmax - mapping->window.xmin);
384   ysf = (vp.ymax - vp.ymin) / (mapping->window.ymax - mapping->window.ymin);
385   zsf = (vp.zmax - vp.zmin) / (fpd - bpd);
386
387   /* map matrix */
388   mmat[0][0] = xsf, mmat[1][1] = ysf, mmat[2][2] = zsf;
389   mmat[3][0] = vp.xmin - xsf*mapping->window.xmin;
390   mmat[3][1] = vp.ymin - ysf*mapping->window.ymin;
391   mmat[3][2] = vp.zmin - zsf*bpd;
392
393   /* multiply to obtain mapping matrix */
394   TelMultiplymat3( mat, pmat, mmat );
395
396 #ifdef PRINT
397   printf( "mapping_matrix :\n" );
398   pr_matrix(mat);
399 #endif
400 }
401
402 /*----------------------------------------------------------------------*/
403 /*+
404 Set View Representation
405
406 This routine defines a view representation for a workstation.
407
408 The representation of the view is stored in a storage table.
409 An entry is made into the list of defined views for the workstation.
410 If the view id being defined already exists, its representation gets
411 modified, else a new representation is created.
412 An inverse transformation matrix is computed and stored in the internal
413 data for the view to accelerate UVN2XYZ conversions. To be able to compute
414 this matrix, it requires some extra information about the view orientation,
415 view plane distance and viewport limits.
416 +*/
417
418 TStatus
419 TelSetViewRepresentation( Tint  Wsid /* Workstation id*/,
420                           Tint  Vid  /* View id */,
421                           tel_view_rep vrep /* view repesentation */
422                          )
423 {
424   CMN_KEY_DATA    key;
425   tel_view_data   vptr;
426
427   if( Vid == 0 )
428     return TFailure; /* attempt to modify default view */
429
430   /* Mise a jour de l'update_mode */
431   key.ldata = TNotDone;
432   TsmSetWSAttri( Wsid, WSUpdateState, &key );
433
434   TsmGetWSAttri( Wsid, WSViews, &key );
435   vptr = (tel_view_data)(key.pdata) ; /* Obtain defined view data*/
436
437   if( !vptr )  /* no view defined yet */
438   {                 /* allocate */
439     //cmn_memreserve(vptr, 1, 0 );
440     vptr = new TEL_VIEW_DATA();
441     if( !vptr ) return TFailure;
442
443     key.pdata = vptr;
444     TsmSetWSAttri( Wsid, WSViews, &key ); /* Set defined view data*/
445   }
446
447   /* copy view definition to storage table record */
448   /* NOTE: Use the matrices already calculated and stored in vrep */
449   vptr->vrep = *vrep; 
450
451 #ifdef CAL_100498
452   /* compute inverse transformation matrix */
453   TelEvalInverseMatrix( vrep->extra.vrp, vrep->extra.vpn, vrep->extra.vup,
454     vrep->extra.map.vpd, vptr->inverse_matrix );
455 #endif
456 #ifdef TRACE_MAT
457   printf( "\nTelSetViewRepresentation WS : %d, view : %d\n", Wsid, Vid );
458   printf( "orientation_matrix :\n" );
459   pr_matrix( vptr->vrep.orientation_matrix );
460   printf( "mapping_matrix :\n" );
461   pr_matrix( vptr->vrep.mapping_matrix );
462 #endif
463   return  TSuccess;
464 }
465
466
467 /*----------------------------------------------------------------------*/
468 TStatus
469 TelGetViewRepresentation( Tint  Wsid /* Workstation id*/,
470                           Tint  Vid  /* View id */,
471                           tel_view_rep vrep /* view representation */
472                          )
473 {
474   CMN_KEY_DATA    key;
475   tel_view_data   vptr;
476
477   if( Vid == 0 )
478   {
479     matcpy( vrep->orientation_matrix, ident );
480     matcpy( vrep->mapping_matrix, ident );
481     vrep->clip_limit.xmin = vrep->clip_limit.ymin = 
482       vrep->clip_limit.zmin = ( float )0.0;
483     vrep->clip_limit.xmax = vrep->clip_limit.ymax =
484       vrep->clip_limit.zmax = ( float )1.0;
485     vrep->clip_xy = TOff;
486     vrep->clip_back = vrep->clip_front = TOn;
487     vrep->shield_indicator = TOn;
488     vrep->shield_colour.rgb[0] = vrep->shield_colour.rgb[1] =
489       vrep->shield_colour.rgb[2] = ( float )0.0;
490     vrep->border_indicator = TOff; /* non utilise */
491     vrep->border_colour.rgb[0] = vrep->border_colour.rgb[1] =
492       vrep->border_colour.rgb[2] = ( float )0.0;
493     vrep->active_status = TOn;
494     vrep->extra.vrp[0] = vrep->extra.vrp[1] = vrep->extra.vrp[2] = ( float )0.0;
495     vrep->extra.vpn[0] = ( float )0.0,
496       vrep->extra.vpn[1] = ( float )0.0,
497       vrep->extra.vpn[2] = ( float )1.0;
498     vrep->extra.vup[0] = ( float )0.0,
499       vrep->extra.vup[1] = ( float )1.0,
500       vrep->extra.vup[2] = ( float )0.0;
501     vrep->extra.map.vpd = ( float )0.0,
502       vrep->extra.map.fpd = ( float )0.0,
503       vrep->extra.map.bpd = ( float )-1.0;
504     vrep->extra.map.window.xmin = vrep->extra.map.window.ymin = ( float )0.0;
505     vrep->extra.map.window.xmax = vrep->extra.map.window.ymax = ( float )1.0;
506     vrep->extra.map.viewport.xmin = vrep->extra.map.viewport.ymin =
507       vrep->extra.map.viewport.zmin = ( float )0.0;
508     vrep->extra.map.viewport.xmax = vrep->extra.map.viewport.ymax =
509       vrep->extra.map.viewport.zmax = ( float )1.0;
510     vrep->clipping_planes.Clear();
511     return TSuccess;
512   }
513
514   if(TsmGetWSAttri( Wsid, WSViews, &key ) != TSuccess) {
515     return TFailure;
516   }
517   vptr = (tel_view_data)key.pdata ; /* Obtain defined view data*/
518   if( !vptr ) return TFailure; /* no view defined yet */ 
519   *vrep = vptr->vrep; /* copy view definition */
520
521   return  TSuccess;
522 }
523
524 /*----------------------------------------------------------------------*/
525 /*+
526 Evaluate View Orientation Matrix
527
528 This routine computes the orientation matrix based on the View Reference
529 Point, View Plane Normal and the View Up Vector.
530 +*/
531
532 void
533 TelEvalViewOrientationMatrix( Tfloat *vrp    /* View Reference Point */,
534                               Tfloat *vpn    /* View Plane Normal */,
535                               Tfloat *vup    /* View Up Vector */,
536                               Tfloat *asf    /* Axial Scale Factors */,
537                               Tint *error_ind/* Out: Error indicator */,
538                               Tmatrix3  rmat  /* Out: Orientation Matrix  */
539                              )
540 {
541   Tfloat  u[3], v[3], n[3], f;
542
543   /* view plane normal of zero length */
544   if( vecmag(vpn) == 0.0 )
545   {
546     *error_ind = 1;   
547     return;
548   }
549
550   /* view up vector of zero length */
551   if( vecmag(vup) == 0.0 )
552   {
553     *error_ind = 2;    
554     return;
555   }
556
557   /* view up vector parallel to view plane normal */
558   vecang(vup, vpn, f);
559   if( f == 0.0 )
560   {
561     *error_ind = 3;    
562     return;
563   }
564
565   *error_ind = 0;
566
567   veccpy(n, vpn);
568   veccpy(v, vup);
569   vecnrm(n);  
570
571   veccrs(u,v,n);      /* up vector cross plane normal gives U axis */
572   vecnrm(u);
573
574   veccrs(v,n,u);      /* plane normal cross U axis gives modified up vector */
575   vecnrm(v); /* redundant ? */
576
577   /* rotate to align along u, v, n */
578   rmat[0][0] = ( float )u[0] * asf[0],
579     rmat[0][1] = ( float )v[0] * asf[0],
580     rmat[0][2] = ( float )n[0] * asf[0],
581     rmat[0][3] = ( float )0.0;
582
583   rmat[1][0] = ( float )u[1] * asf[1],
584     rmat[1][1] = ( float )v[1] * asf[1],
585     rmat[1][2] = ( float )n[1] * asf[1],
586     rmat[1][3] = ( float )0.0;
587
588   rmat[2][0] = ( float )u[2] * asf[2],
589     rmat[2][1] = ( float )v[2] * asf[2],
590     rmat[2][2] = ( float )n[2] * asf[2],
591     rmat[2][3] = ( float )0.0;
592
593   /* translate to centre at vrp */
594
595   rmat[3][0] = - ( float ) (u[0]*vrp[0] + u[1]*vrp[1] + u[2]*vrp[2]);
596   rmat[3][1] = - ( float ) (v[0]*vrp[0] + v[1]*vrp[1] + v[2]*vrp[2]);
597   rmat[3][2] = - ( float ) (n[0]*vrp[0] + n[1]*vrp[1] + n[2]*vrp[2]);
598   rmat[3][3] = ( float )1.0;
599
600 #ifdef PRINT
601   printf("TelEvalViewOrientationMatrix \n");
602   printf("view_ref_pt %f %f %f \n", vrp[0], vrp[1], vrp[2]);
603   printf("view_up_vec %f %f %f \n", vup[0], vup[1], vup[2]);
604   printf("view_plane_normal %f %f %f \n", vpn[0], vpn[1], vpn[2]);
605   pr_matrix(rmat);
606 #endif
607
608   return;
609 }
610 /*----------------------------------------------------------------------*/
611
612 void
613 TelEvalViewMappingMatrix( tel_view_mapping mapping /* View Mapping */,
614                           Tint *error_ind          /* Out: Error Indicator */,
615                           Tmatrix3 mat             /* Out: Mapping Matrix */
616                          )
617 {
618   EvalViewMappingMatrix( mapping, error_ind, mat, 0, ( float )0.0, ( float )0.0, 0, 0 );
619 }
620
621 /*----------------------------------------------------------------------*/
622
623 void
624 TelEvalViewMappingMatrixPick( tel_view_mapping mapping /* View Mapping */,
625                               Tint *error_ind          /* Out: Error Indicator */,
626                               Tmatrix3 mat             /* Out: Mapping Matrix */,
627                               Tfloat   cx,
628                               Tfloat   cy
629                              )
630 {
631   EvalViewMappingMatrix( mapping, error_ind, mat, 1, cx, cy, 0, 0 );
632 }
633
634 /*----------------------------------------------------------------------*/
635 /*+
636 Evalute inverse transformation matrix.
637
638 This routine computes a matrix required to convert UVN coordinates to XYZ
639 coordinates. It is called every time a View Representation is created or
640 modified, and the inverse matrix is stored along with the internal data
641 for the view representation.
642 +*/
643
644 #ifdef CAL_100498
645 static  void
646 TelEvalInverseMatrix( Tfloat *vrp    /* View Reference Point */,
647                       Tfloat *vpn    /* View Plane Normal */,
648                       Tfloat *vup    /* View Up Vector */,
649                       Tfloat vpd     /* View Plane Distance */,
650                       Tmatrix3 mat   /* Out: Inverse Transformation Matrix */
651                      )
652 {
653   Tfloat  u[3], v[3], n[3], p[3], t[3];
654   Tfloat  dist = ( float )0.0;
655
656   veccpy(n, vpn);            /* compute UVN orientation */
657   veccpy(v, vup);
658   veccpy(p, vrp);
659
660   veccrs(u,v,n);
661   vecnrm(u);
662
663   veccrs(v,n,u);
664   vecnrm(v);
665
666   dist = vpd;
667   veccpy(t,n);
668   vecscl(dist,t);
669   vecadd(t,t,p);           /* translation vector */
670
671   veccpy(mat[0],u);
672   veccpy(mat[1],v);
673   veccpy(mat[2],n);
674   veccpy(mat[3],t);
675
676   mat[0][3] = mat[1][3] = mat[2][3] = ( float )0.0, mat[3][3] = ( float )1.0;
677
678   return;
679 }
680 #endif
681
682 #ifdef CAL_100498
683 /*----------------------------------------------------------------------*/
684 /*+
685 Convert Coordinates utility routine
686
687 This routine converts coordinates from UVN space to XYZ space and
688 vice versa. For UVN2XYZ, the inverse transformation matrix is used and for
689 XYZ2UVN, the orientation matrix is used.
690 +*/
691
692 TStatus
693 TelConvertCoord( Tint  Wsid        /* Workstation id */,
694                  Tint  Vid         /* View id */,
695                  TelCoordType type /* Conversion type (UVN2XYZ or XYZ2UVN) */,
696                  Tfloat *uvn       /* UVN coords if type is UVN2XYZ else Out */,
697                  Tfloat *xyz       /* XYZ coords if type is XYZ2UVN else Out */
698                 )
699 {
700   CMN_KEY_DATA    key;
701   tel_view_data   vptr;
702   register  Tint  i;
703
704   Tfloat  pt[4], tpt[4];
705
706   if( Vid == 0 )
707   {                            /* default view */
708     switch( type )
709     {
710     case UVN2XYZ:
711       veccpy(xyz,uvn);
712       break;
713     case XYZ2UVN:
714       veccpy(uvn,xyz);
715       break;
716     }
717     return TSuccess;
718   }
719
720   TsmGetWSAttri( Wsid, WSViews, &key );
721   vptr = key.pdata ; /* Obtain defined view data*/
722   if( !vptr ) return TFailure; /* no view defined yet */ 
723
724   switch( type )
725   {
726   case UVN2XYZ:
727     veccpy(pt,uvn);
728     pt[3] = ( float )1.0;
729     TelTranpt3( tpt, pt, vptr->inverse_matrix );
730     veccpy(xyz,tpt);
731     break;
732
733   case XYZ2UVN:
734     veccpy(pt,xyz);
735     pt[3] = ( float )1.0;
736     TelTranpt3( tpt, pt, vptr->vrep.orientation_matrix );
737     veccpy(uvn,tpt);
738     break;
739   }
740
741   return TSuccess;
742 }
743 #endif
744
745 /*----------------------------------------------------------------------*/
746 /*+
747 Print Matrix
748
749 Debug tool
750 +*/
751
752 #ifdef DEB
753 void
754 pr_matrix( Tmatrix3 mat )
755 {
756   printf( "%f %f %f %f\n", mat[0][0], mat[0][1], mat[0][2], mat[0][3] );
757   printf( "%f %f %f %f\n", mat[1][0], mat[1][1], mat[1][2], mat[1][3] );
758   printf( "%f %f %f %f\n", mat[2][0], mat[2][1], mat[2][2], mat[2][3] );
759   printf( "%f %f %f %f\n", mat[3][0], mat[3][1], mat[3][2], mat[3][3] );
760   printf( "\n" );
761   return;
762 }
763 #endif
764
765 /*----------------------------------------------------------------------*/
766 /*+
767 Set View Index
768
769 This routine activates the view representation which has been defined
770 previously.
771 +*/
772
773 TStatus
774 TelSetViewIndex( Tint  Wsid /* Workstation id */,
775                  Tint  Vid  /* View id */ )
776 {
777   CMN_KEY_DATA    key;
778   tel_view_data   vptr;
779
780   if( Vid == 0 )
781   {                    /* default view */
782     GLint mm;
783     glGetIntegerv(GL_MATRIX_MODE, &mm);
784 #ifdef TRACE_MATRIX
785     printf("OpenGl_view.c::TelSetViewIndex::glMatrixMode(GL_PROJECTION) \n"); 
786 #endif
787     glMatrixMode(GL_PROJECTION);
788     glLoadIdentity();
789     glOrtho( -0.5,  0.5,  -0.5,  0.5,  -0.5,  0.5 );
790     glMatrixMode(mm);
791     return TSuccess;
792   }
793
794   TsmGetWSAttri( Wsid, WSViews, &key );
795   vptr = (tel_view_data)key.pdata ; /* Obtain defined view data*/
796   if( !vptr ) return TFailure; /* no view defined yet */ 
797
798  
799 #ifdef TRACE_MATRIX
800   printf("OpenGl_view.c::TelSetViewIndex::glMatrixMode(GL_MODELVIEW) \n"); 
801 #endif
802   if(vptr->vrep.extra.scaleFactors[0] != 1. || 
803     vptr->vrep.extra.scaleFactors[1] != 1. ||
804     vptr->vrep.extra.scaleFactors[2] != 1.)
805     glEnable(GL_NORMALIZE);           /* if the view is scaled normal vectors are scaled to unit length for correct displaying of shaded objects*/
806   else if(glIsEnabled(GL_NORMALIZE))  
807     glDisable(GL_NORMALIZE);
808   glMatrixMode(GL_MODELVIEW);
809   set_clipplanes( &(vptr->vrep) );
810   
811
812   glLoadMatrixf((GLfloat *) vptr->vrep.orientation_matrix );
813   set_userclipplanes( &(vptr->vrep) ); /* set clipping planes defined by user */
814
815 #ifdef ENVTEX
816   /*
817   * Ajout translation necessaire pour l'environnement mapping
818   */
819   {
820     GLfloat dep;  
821
822     TsmGetWSAttri(Wsid, WSSurfaceDetail, &key);
823     /* TOD_ENVIRONMENT ou TOD_ALL */
824     if (key.ldata == 1 || key.ldata == 2)
825     {
826       /*          dep = vptr->vrep.extra.map.fpd * 0.5F; */
827       dep = (vptr->vrep.extra.map.fpd + vptr->vrep.extra.map.bpd) * 0.5F; /* OCC280: FitAll work incorrect for perspective view if the SurfaceDetail mode is V3d_TEX_ENVIRONMENT or V3d_TEX_ALL */
828       glTranslatef(-dep*vptr->vrep.extra.vpn[0],
829         -dep*vptr->vrep.extra.vpn[1],
830         -dep*vptr->vrep.extra.vpn[2]); 
831 #ifdef PRINT
832       printf("glTranslatef: %f %f %f \n", 
833         -dep*vptr->vrep.extra.vpn[0],
834         -dep*vptr->vrep.extra.vpn[1],
835         -dep*vptr->vrep.extra.vpn[2]);
836 #endif
837     }
838   }
839 #endif
840
841 #ifdef TRACE_MATRIX
842   printf("OpenGl_view.c::TelSetViewIndex::glMatrixMode(GL_PROJECTION) \n"); 
843 #endif
844   glMatrixMode(GL_PROJECTION);
845   glLoadMatrixf((GLfloat *) vptr->vrep.mapping_matrix );
846
847 #ifdef TRACE_MAT
848   printf( "\nTelSetViewIndex WS : %d, view : %d", Wsid, Vid );
849   printf( "orientation_matrix :\n" );
850   pr_matrix( vptr->vrep.orientation_matrix );
851   printf( "mapping_matrix :\n" );
852   pr_matrix( vptr->vrep.mapping_matrix );
853 #endif
854
855   return vptr->vrep.active_status == TOn ? TSuccess : TFailure;
856 }
857
858
859 /*----------------------------------------------------------------------*/
860 /*+
861 Set View Projection
862
863 This routine activates the Projection matrix for a previously defined
864 view representation. It is meant to be used exclusively to restore the
865 Projection transformation at the end of an ExecuteStructure element
866 traversal. The restoration of the Viewing matrix is done by a GL popmatrix
867 call.
868 +*/
869
870 TStatus
871 TelSetViewProjection( Tint  Wsid /* Workstation id */,
872                       Tint  Vid  /* View id */ )
873 {
874   CMN_KEY_DATA    key;
875   tel_view_data   vptr;
876
877   if( Vid == 0 )
878   {                    /* default view */
879     GLint mm;
880     glGetIntegerv(GL_MATRIX_MODE, &mm);
881 #ifdef TRACE_MATRIX
882     printf("OpenGl_view.c::TelSetViewProjection::glMatrixMode(GL_PROJECTION) \n"); 
883 #endif
884     glMatrixMode(GL_PROJECTION);
885     glLoadIdentity();
886     glOrtho( 0,  1,  0,  1,  0,  1 );
887     glMatrixMode(mm);
888
889
890     return TSuccess;
891   }
892
893   TsmGetWSAttri( Wsid, WSViews, &key );
894   vptr = (tel_view_data)key.pdata ; /* Obtain defined view data*/
895   if( !vptr ) return TFailure; /* no view defined yet */ 
896
897   set_clipplanes( &(vptr->vrep) );
898   set_userclipplanes( &(vptr->vrep) );
899
900 #ifdef TRACE_MATRIX
901   printf("OpenGl_view.c::TelSetViewProjection::glMatrixMode(GL_PROJECTION) \n"); 
902 #endif
903   glMatrixMode(GL_PROJECTION);
904   glLoadMatrixf((GLfloat *) vptr->vrep.mapping_matrix );
905  
906   return vptr->vrep.active_status == TOn ? TSuccess : TFailure;
907 }
908
909 /*----------------------------------------------------------------------*/
910 /*+
911 Clear all active views in a workstation
912
913 This routine clears all the viewports, draws the viewport borders and
914 sets the viewport background if the corresponding indicators are on.
915 It also clears view 0 (default view), if the workstation state demands it.
916 +*/
917
918 void
919 TelClearViews( Tint  Wsid /* Workstation id */ )
920 {
921   CMN_KEY_DATA    key;
922   tel_view_data   vptr;
923
924   TelResetMaterial();
925
926   TsmGetWSAttri( Wsid, WSViews, &key );
927   vptr = (tel_view_data)key.pdata ; /* Obtain defined view data*/
928   if( !vptr ) return; /* no view defined yet */ 
929
930   if( vptr->vrep.active_status == TOn )  /* for each active view only */
931   {
932     if( vptr->vrep.shield_indicator == TOn ) TelClearBackground( Wsid );
933   }
934
935   return;
936 }
937
938 /*----------------------------------------------------------------------*/
939 /* Function for printing view information */
940
941 TStatus
942 TelPrintViewRepresentation( Tint  Wsid /* Workstation id*/,
943                             Tint  Vid  /* View id */
944                            )
945 {
946   CMN_KEY_DATA    key;
947   tel_view_data   vptr;
948
949   printf( "\n\tPrint : Workstation %d View %d", Wsid, Vid );
950
951   if( Vid == 0 )
952     return TSuccess;
953
954   TsmGetWSAttri( Wsid, WSViews, &key );
955   vptr = (tel_view_data)key.pdata ; /* Obtain defined view data*/
956   if( !vptr ) return TFailure; /* no view defined yet */ 
957
958   /* Print the information */
959   printf( "\n\tshield indicator : %s",
960     vptr->vrep.shield_indicator == TOn ? "ON" : "OFF" );
961   printf( "\n\tshield_colour r = %f, g = %f, b = %f",
962     vptr->vrep.shield_colour.rgb[0],
963     vptr->vrep.shield_colour.rgb[1],
964     vptr->vrep.shield_colour.rgb[2] );
965   printf( "\n\tactive_status : %s",
966     vptr->vrep.active_status == TOn ? "ON":"OFF");
967   printf( "\n\tVRP : %f %f %f", vptr->vrep.extra.vrp[0],
968     vptr->vrep.extra.vrp[1],
969     vptr->vrep.extra.vrp[2] );
970   printf( "\n\tVPN : %f %f %f", vptr->vrep.extra.vpn[0],
971     vptr->vrep.extra.vpn[1],
972     vptr->vrep.extra.vpn[2] );
973   printf( "\n\tVUP : %f %f %f", vptr->vrep.extra.vup[0],
974     vptr->vrep.extra.vup[1],
975     vptr->vrep.extra.vup[2] );
976   printf( "\n\tPRP : %f %f %f", vptr->vrep.extra.map.prp[0],
977     vptr->vrep.extra.map.prp[1],
978     vptr->vrep.extra.map.prp[2] );
979   printf( "\n\tWindow Limits xmin xmax ymin ymax :\n\t\t%f %f %f %f",
980     vptr->vrep.extra.map.window.xmin,
981     vptr->vrep.extra.map.window.xmax,
982     vptr->vrep.extra.map.window.ymin,
983     vptr->vrep.extra.map.window.ymax );
984   printf( "\n\tViewport Limits xmin xmax ymin ymax zmin zmax :\n\t\t%f %f %f %f %f %f", vptr->vrep.extra.map.viewport.xmin,
985     vptr->vrep.extra.map.viewport.xmax,
986     vptr->vrep.extra.map.viewport.ymin,
987     vptr->vrep.extra.map.viewport.ymax,
988     vptr->vrep.extra.map.viewport.zmin,
989     vptr->vrep.extra.map.viewport.zmax );
990   printf( "\n\tProjection type : %s",
991     vptr->vrep.extra.map.proj == TelParallel
992     ? "PARALLEL" : "PERSPECTIVE" );
993   printf( "\n\tVPD FPD BPD : %f %f %f\n", vptr->vrep.extra.map.vpd,
994     vptr->vrep.extra.map.fpd,
995     vptr->vrep.extra.map.bpd );
996   return  TSuccess;
997 }
998
999
1000 /*----------------------------------------------------------------------*/
1001
1002 #define FRONT_CLIPPING_PLANE (GL_CLIP_PLANE0 + 0)
1003 #define BACK_CLIPPING_PLANE  (GL_CLIP_PLANE0 + 1)
1004 /*
1005
1006 While drawing after a clipplane has been defined and enabled, each vertex
1007 is transformed to eye-coordinates, where it is dotted with the transformed
1008 clipping plane equation.  Eye-coordinate vertexes whose dot product with
1009 the transformed clipping plane equation is positive or zero are in, and
1010 require no clipping.  Those eye-coordinate vertexes whose dot product is
1011 negative are clipped.  Because clipplane clipping is done in eye-
1012 coordinates, changes to the projection matrix have no effect on its
1013 operation.
1014
1015 A point and a normal are converted to a plane equation in the following
1016 manner:
1017
1018 point = [Px,Py,Pz]
1019
1020 normal = |Nx|
1021 |Ny|
1022 |Nz|
1023
1024 plane equation = |A|
1025 |B|
1026 |C|
1027 |D|
1028 A = Nx
1029 B = Ny
1030 C = Nz
1031 D = -[Px,Py,Pz] dot |Nx|
1032 |Ny|
1033 |Nz|
1034
1035 */
1036
1037 /*----------------------------------------------------------------------*/
1038
1039 static void
1040 set_clipplanes( tel_view_rep vrep )
1041 {
1042   GLdouble arr[4];
1043   Tfloat front, back;
1044   GLfloat mat[4][4];
1045 #ifdef TRACE_MATRIX
1046   printf("OpenGl_view.c::set_clipplanes::glMatrixMode(GL_MODELVIEW) \n"); 
1047 #endif
1048   glMatrixMode( GL_MODELVIEW );
1049   glGetFloatv( GL_MODELVIEW_MATRIX,(GLfloat *) mat );
1050   glLoadIdentity();
1051
1052   if( vrep->clip_limit.zmin < 0.0 ||
1053     vrep->clip_limit.zmin > 1.0 ||
1054     vrep->clip_back == TOff )
1055     glDisable( BACK_CLIPPING_PLANE );
1056   else
1057   {
1058     /* cf Opengl_togl_cliplimit */
1059     back = (vrep->extra.map.fpd - vrep->extra.map.bpd) *
1060       vrep->clip_limit.zmin + vrep->extra.map.bpd;
1061     arr[0] = 0.0;  /* Nx */
1062     arr[1] = 0.0;  /* Ny */
1063     arr[2] = 1.0;  /* Nz */
1064     arr[3] = -( (GLdouble) (back) * arr[2] ); /* P dot N */
1065     glClipPlane( BACK_CLIPPING_PLANE, arr );
1066     glEnable( BACK_CLIPPING_PLANE );
1067   }
1068
1069   if( vrep->clip_limit.zmax < 0.0 ||
1070     vrep->clip_limit.zmax > 1.0 ||
1071     vrep->clip_front == TOff )
1072     glDisable( FRONT_CLIPPING_PLANE );
1073   else
1074   {
1075     /* cf Opengl_togl_cliplimit */
1076     front = (vrep->extra.map.fpd - vrep->extra.map.bpd) *
1077       vrep->clip_limit.zmax + vrep->extra.map.bpd;
1078     arr[0] = 0.0;  /* Nx */
1079     arr[1] = 0.0;  /* Ny */
1080     arr[2] = -1.0; /* Nz */
1081     arr[3] = -( (GLdouble) (front) * arr[2] ); /* P dot N */
1082     glClipPlane( FRONT_CLIPPING_PLANE, arr );
1083     glEnable( FRONT_CLIPPING_PLANE );
1084   }
1085
1086   glLoadMatrixf( (GLfloat *) mat );
1087 }
1088
1089 static void
1090 set_userclipplanes( tel_view_rep vrep )
1091 {
1092   int j,planeid;
1093   CALL_DEF_PLANE* plane;
1094
1095 #ifdef TRACE_MATRIX
1096   printf("OpenGl_view.c::set_userclipplanes::glMatrixMode(GL_MODELVIEW) \n"); 
1097 #endif
1098
1099   
1100   NCollection_List<CALL_DEF_PLANE>::Iterator planeIter(vrep->clipping_planes);
1101   
1102   // go through all of planes in the list & preview them
1103   for( j=0 ; planeIter.More(); planeIter.Next(), j++ ) 
1104   {
1105     plane = const_cast<CALL_DEF_PLANE*>(&planeIter.Value());
1106     
1107     if( plane->PlaneId > 0 ) 
1108     {
1109       planeid = GL_CLIP_PLANE2 + j;
1110
1111       if( plane->Active ) 
1112       {
1113           // Activates new clip planes
1114           GLdouble equation[4];
1115           equation[0] = plane->CoefA;
1116           equation[1] = plane->CoefB;
1117           equation[2] = plane->CoefC;
1118           equation[3] = plane->CoefD;
1119           
1120           glClipPlane( planeid , equation );     
1121           if( !glIsEnabled( planeid ) ) glEnable( planeid );     
1122       } 
1123       else 
1124       {
1125         if( glIsEnabled( planeid ) ) glDisable( planeid );     
1126       }
1127     }
1128   }   //for( ; planeIter.More(); planeIter.Next() ) 
1129
1130   // Disable the remainder Clip planes
1131
1132   for( j=vrep->clipping_planes.Size(); j < call_facilities_list.MaxPlanes; j++ )
1133   {
1134     planeid = GL_CLIP_PLANE2 + j; 
1135
1136     if( glIsEnabled( planeid ) ) 
1137       glDisable( planeid );
1138    }
1139
1140   
1141 }
1142
1143 /*----------------------------------------------------------------------*/
1144
1145 TStatus
1146 Tel2Dto3D( Tint ws, Tint vid, Tint x, Tint y,
1147           Tfloat *x1, Tfloat *y1, Tfloat *z1,
1148           Tfloat *x2, Tfloat *y2, Tfloat *z2 )
1149           /* x is from bottom */
1150           /* y is from top */
1151 {
1152   CMN_KEY_DATA key;
1153   TEL_VIEW_REP vrep;
1154   Tint         w, h;
1155   GLint        viewp[4];
1156   GLdouble xx1, yy1, zz1, xx2, yy2, zz2;
1157
1158   TsmGetWSAttri( ws, WSWidth, &key );
1159   w = key.ldata;
1160   TsmGetWSAttri( ws, WSHeight, &key );
1161   h = key.ldata;
1162   y = key.ldata - y;
1163
1164   /* FSXXX */
1165   printf("WARNING: Tel2Dto3D non verifie\n");
1166
1167   TelGetViewRepresentation( ws, vid, &vrep );
1168
1169   viewp[0] = 0;     viewp[2] = w;
1170   viewp[1] = 0;     viewp[3] = h;
1171
1172
1173   /* OGLXXX XXX I think this is backwards */
1174   gluProject((GLdouble) x, (GLdouble) y, 0.0,
1175     (GLdouble *) vrep.orientation_matrix,
1176     (GLdouble *) vrep.mapping_matrix,
1177     viewp, &xx1, &yy1, &zz1);
1178   gluProject((GLdouble) x, (GLdouble) y, 1.0,
1179     (GLdouble *) vrep.orientation_matrix,
1180     (GLdouble *) vrep.mapping_matrix,
1181     viewp, &xx2, &yy2, &zz2);
1182
1183   *x1 = (float) xx1; *y1 =  (float) yy1; *z1 =  (float) zz1;
1184   *x2 = (float) xx2; *y2 =  (float) yy2; *z2 =  (float) zz2;
1185
1186   return TSuccess;
1187
1188 }
1189
1190 /*----------------------------------------------------------------------*/
1191
1192 TStatus
1193 TelDeleteViewsForWS( Tint wsid )
1194 {
1195   CMN_KEY_DATA key;
1196   tel_view_data vptr;
1197
1198   TsmGetWSAttri( wsid, WSViews, &key );
1199   vptr = (tel_view_data)key.pdata ; /* Obtain defined view data*/
1200
1201   if( !vptr ) return TSuccess;
1202   delete vptr;
1203
1204   return TSuccess;
1205 }
1206
1207 /*----------------------------------------------------------------------*/
1208
1209 void
1210 TelClearBackground( Tint  Wsid /* Workstation id */ )
1211 {
1212   CMN_KEY_DATA key;
1213   Tfloat *rgb;
1214   Tint   zbuffer;
1215 #ifdef BUC61044
1216   Tint   dTest;
1217 #endif
1218 #ifdef OCC1188
1219   tsm_bg_texture texture;
1220 #endif  
1221   tsm_bg_gradient gradient;
1222
1223
1224   TsmGetWSAttri (Wsid, WSBackground, &key);
1225   rgb = (Tfloat *)key.pdata;
1226
1227 #ifdef OCC1188
1228   TsmGetWSAttri (Wsid, WSBgTexture, &key);
1229   texture = (tsm_bg_texture)key.pdata;
1230 #endif
1231   TsmGetWSAttri (Wsid, WSZbuffer, &key);
1232   zbuffer = key.ldata;
1233
1234   TsmGetWSAttri (Wsid, WSBgGradient, &key);
1235   gradient = (tsm_bg_gradient)key.pdata;
1236   
1237   /* GL_DITHER on/off pour le background */
1238   if (TxglGetBackDither ())
1239     glEnable (GL_DITHER);
1240   else
1241     glDisable (GL_DITHER);
1242
1243   if (zbuffer)
1244   {
1245 #ifdef BUC60920 
1246     glDepthFunc(GL_LEQUAL);
1247 #else
1248     glDepthFunc(GL_LESS);
1249 #endif
1250     glDepthMask(GL_TRUE);
1251
1252 #ifdef BUC61044
1253     /* getting depth testing flag */
1254     TsmGetWSAttri( Wsid, WSDepthTest, &key );
1255     dTest = key.ldata;
1256     /* SAV checking if depth test was depricated somewhere outside */
1257     if ( dTest == TOn ) 
1258       glEnable(GL_DEPTH_TEST);
1259     else
1260       glDisable(GL_DEPTH_TEST);
1261 #else
1262     glEnable(GL_DEPTH_TEST);
1263 #endif
1264
1265     glClearDepth(1.0);
1266     glClearColor (rgb[0], rgb[1], rgb[2], ( float )0.0);
1267     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
1268   }
1269   else
1270   {
1271     glDisable(GL_DEPTH_TEST);
1272     glClearColor (rgb[0], rgb[1], rgb[2], ( float )0.0);
1273     glClear (GL_COLOR_BUFFER_BIT);
1274   }
1275 #ifdef OCC1188
1276   glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
1277   /* drawing bg image if any */
1278   if ( texture->texId != 0 ) {
1279     GLint width, height; /* window dimensions*/
1280     GLfloat x_center, y_center; /* window center */
1281     GLfloat x_offset, y_offset; /* half of the texture size */
1282     GLfloat texX_range = 1.0;
1283     /* texture <s> coordinate */
1284     GLfloat texY_range = 1.0; /* texture <t> coordinate */
1285
1286     TsmGetWSAttri( Wsid, WSWidth, &key );
1287     width = key.ldata;
1288     x_center = (GLfloat)( width / 2. );
1289     TsmGetWSAttri( Wsid, WSHeight, &key );
1290     height = key.ldata;
1291     y_center = (GLfloat)( height / 2. );
1292
1293     x_offset = (GLfloat)( texture->width / 2. ); /* style = center */
1294     y_offset = (GLfloat)( texture->height / 2. ); /* style = center */
1295     if ( texture->style != 0 ) { /* stretch or tile */
1296       x_offset = x_center;
1297       y_offset = y_center;
1298       if ( texture->style == 1 ) { /* tile */
1299         texX_range = (float)( width / texture->width );
1300         if ( texX_range < 1.0 )
1301           texX_range = 1.0;
1302         texY_range = (float)( height / texture->height );
1303         if ( texY_range < 1.0 )
1304           texY_range = 1.0;
1305       }
1306     }
1307     /* drawing background texture */
1308     glMatrixMode( GL_PROJECTION );
1309     glPushMatrix();
1310     glLoadIdentity();
1311     gluOrtho2D( 0.0, (GLdouble)width, 0.0, (GLdouble)height );
1312     glMatrixMode( GL_MODELVIEW );
1313     glPushMatrix();
1314     glLoadIdentity();
1315     glEnable( GL_TEXTURE_2D );
1316     glBindTexture( GL_TEXTURE_2D, texture->texId );
1317     glDisable( GL_DEPTH_TEST );
1318
1319     glDisable( GL_BLEND );
1320     glColor3f( rgb[0], rgb[1], rgb[2] );
1321     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1322     glBegin( GL_QUADS );
1323     glTexCoord2f(0.0f, 0.0f);glVertex2f( x_center - x_offset, y_center - y_offset );
1324     glTexCoord2f(texX_range, 0.0f);glVertex2f( x_center + x_offset, y_center - y_offset );
1325     glTexCoord2f(texX_range, texY_range);glVertex2f( x_center + x_offset, y_center + y_offset );
1326     glTexCoord2f(0.0f, texY_range);glVertex2f( x_center - x_offset, y_center + y_offset );
1327     glEnd();
1328     if ( zbuffer )
1329       glEnable( GL_DEPTH_TEST );
1330     glDisable( GL_TEXTURE_2D );
1331     glPopMatrix(); /*modelview*/
1332     glMatrixMode( GL_PROJECTION );
1333     glPopMatrix(); /*projection*/
1334     glMatrixMode( GL_MODELVIEW );
1335   }  
1336   else if( gradient->type > 0 )
1337   {
1338
1339     Tfloat* corner1 = 0;/* -1,-1*/
1340     Tfloat* corner2 = 0;/*  1,-1*/
1341     Tfloat* corner3 = 0;/*  1, 1*/
1342     Tfloat* corner4 = 0;/* -1, 1*/
1343     Tfloat* dcorner1 = (Tfloat*)malloc(3*sizeof(Tfloat));
1344     Tfloat* dcorner2 = (Tfloat*)malloc(3*sizeof(Tfloat));
1345
1346     int upset[3] = {0} ;
1347
1348     switch( gradient->type )
1349     {
1350       case 1:
1351        corner1 = gradient->color2.rgb;
1352        corner2 = gradient->color2.rgb;
1353        corner3 = gradient->color1.rgb;
1354        corner4 = gradient->color1.rgb;
1355        break;
1356       case 2:    
1357        corner1 = gradient->color2.rgb;
1358        corner2 = gradient->color1.rgb;
1359        corner3 = gradient->color1.rgb;
1360        corner4 = gradient->color2.rgb;
1361        break;
1362       case 3:
1363        corner2 = gradient->color2.rgb;
1364        corner4 = gradient->color1.rgb;        
1365        dcorner1 [0] = dcorner2[0] = (corner2[0] + corner4[0]) / 2.0;
1366        dcorner1 [1] = dcorner2[1] = (corner2[1] + corner4[1]) / 2.0;
1367        dcorner1 [2] = dcorner2[2] = (corner2[2] + corner4[2]) / 2.0;   
1368        corner1 = dcorner1;
1369        corner3 = dcorner2;  
1370        break;
1371       case 4:  
1372        corner1 = gradient->color2.rgb;  
1373        corner3 = gradient->color1.rgb;       
1374        dcorner1 [0] = dcorner2[0] = (corner1[0] + corner3[0]) / 2.0;
1375        dcorner1 [1] = dcorner2[1] = (corner1[1] + corner3[1]) / 2.0;
1376        dcorner1 [2] = dcorner2[2] = (corner1[2] + corner3[2]) / 2.0;   
1377        corner2 = dcorner1;
1378        corner4 = dcorner2;  
1379        break;
1380       case 5:
1381        corner1 = gradient->color1.rgb;
1382        corner2 = gradient->color2.rgb;
1383        corner3 = gradient->color2.rgb;
1384        corner4 = gradient->color2.rgb;
1385        break;
1386       case 6:
1387        corner1 = gradient->color2.rgb;
1388        corner2 = gradient->color1.rgb;
1389        corner3 = gradient->color2.rgb;
1390        corner4 = gradient->color2.rgb;
1391        break;
1392       case 7:
1393        corner1 = gradient->color2.rgb;
1394        corner2 = gradient->color2.rgb;
1395        corner3 = gradient->color1.rgb;
1396        corner4 = gradient->color2.rgb;
1397        break;
1398       case 8:
1399        corner1 = gradient->color2.rgb;
1400        corner2 = gradient->color2.rgb;
1401        corner3 = gradient->color2.rgb;
1402        corner4 = gradient->color1.rgb;
1403        break;
1404       default:
1405        printf("gradient background type not right\n");
1406
1407     }    
1408     glMatrixMode( GL_PROJECTION );
1409     glPushMatrix();
1410     glLoadIdentity();
1411     glMatrixMode( GL_MODELVIEW );
1412     glPushMatrix();
1413     glLoadIdentity();
1414
1415     if ( glIsEnabled( GL_DEPTH_TEST) )
1416     {
1417       upset[0] = 1;
1418       glDisable( GL_DEPTH_TEST );
1419     }
1420     if ( glIsEnabled( GL_LIGHTING ) )
1421     {
1422       upset[1] = 1;
1423       glDisable( GL_LIGHTING );
1424     }
1425     if ( !glIsEnabled( GL_SMOOTH ) )
1426     {
1427       upset[2] = 1; 
1428       glShadeModel( GL_SMOOTH ) ;
1429     }    
1430
1431     if( gradient->type <= 5 || gradient->type == 7 )
1432     {
1433       glBegin(GL_TRIANGLES);
1434         glColor3f(corner1[0],corner1[1],corner1[2]);
1435         glVertex2f(-1.,-1.);
1436         glColor3f(corner2[0],corner2[1],corner2[2]);
1437         glVertex2f( 1.,-1.);
1438         glColor3f(corner3[0],corner3[1],corner3[2]);
1439         glVertex2f( 1., 1.);          
1440       glEnd(); 
1441       glBegin(GL_TRIANGLES);
1442         glColor3f(corner1[0],corner1[1],corner1[2]);
1443         glVertex2f(-1.,-1.);
1444         glColor3f(corner3[0],corner3[1],corner3[2]);
1445         glVertex2f( 1., 1.);
1446         glColor3f(corner4[0],corner4[1],corner4[2]);
1447         glVertex2f(-1., 1.);          
1448       glEnd();
1449     }         
1450     else if( gradient->type == 6 || gradient->type == 8 )
1451     {
1452       glBegin(GL_TRIANGLES);
1453         glColor3f(corner1[0],corner1[1],corner1[2]);
1454         glVertex2f(-1.,-1.);
1455         glColor3f(corner2[0],corner2[1],corner2[2]);
1456         glVertex2f( 1.,-1.);
1457         glColor3f(corner4[0],corner4[1],corner4[2]);
1458         glVertex2f(-1., 1.);          
1459       glEnd(); 
1460       glBegin(GL_TRIANGLES);
1461         glColor3f(corner2[0],corner2[1],corner2[2]);
1462         glVertex2f( 1.,-1.);
1463         glColor3f(corner3[0],corner3[1],corner3[2]);
1464         glVertex2f( 1., 1.);
1465         glColor3f(corner4[0],corner4[1],corner4[2]);
1466         glVertex2f(-1., 1.);          
1467       glEnd(); 
1468
1469     }    
1470
1471     if ( upset[0] )
1472       glEnable( GL_DEPTH_TEST );   
1473
1474     if ( upset[1] )
1475       glEnable( GL_LIGHTING ); 
1476
1477     if ( upset[2] )
1478       glShadeModel( GL_FLAT );      
1479  
1480     if ( zbuffer )
1481       glEnable( GL_DEPTH_TEST );
1482     glPopMatrix();
1483     glMatrixMode( GL_PROJECTION );
1484     glPopMatrix();
1485     glMatrixMode( GL_MODELVIEW );
1486
1487     free(dcorner1);
1488     free(dcorner2);
1489     dcorner1 = 0;
1490     dcorner2 = 0;
1491
1492   } 
1493
1494 #endif /* OCC1188*/
1495
1496   glPopAttrib();
1497
1498   /* GL_DITHER on/off pour le trace */
1499   if (TxglGetDither ())
1500     glEnable (GL_DITHER);
1501   else
1502     glDisable (GL_DITHER);
1503
1504
1505 }
1506 /*----------------------------------------------------------------------*/