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