6a1813eabba2daf814d4074123b391e331ab50cc
[occt.git] / src / OpenGl / OpenGl_View_2.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include <OpenGl_GlCore11.hxx>
25 #include <OpenGl_tgl_funcs.hxx>
26 #include <OpenGl_TextureBox.hxx>
27
28 #include <AlienImage.hxx>
29 #include <Image_Image.hxx>
30 #include <Visual3d_Layer.hxx>
31
32 #include <OpenGl_AspectLine.hxx>
33 #include <OpenGl_Display.hxx>
34 #include <OpenGl_Workspace.hxx>
35 #include <OpenGl_View.hxx>
36 #include <OpenGl_Trihedron.hxx>
37 #include <OpenGl_GraduatedTrihedron.hxx>
38 #include <OpenGl_PrinterContext.hxx>
39 #include <OpenGl_Structure.hxx>
40
41 #include <GL/glu.h> // gluBuild2DMipmaps()
42
43 #define EPSI 0.0001
44
45 static const GLfloat default_amb[4] = { 0.F, 0.F, 0.F, 1.F };
46 static const GLfloat default_sptdir[3] = { 0.F, 0.F, -1.F };
47 static const GLfloat default_sptexpo = 0.F;
48 static const GLfloat default_sptcutoff = 180.F;
49
50 extern void InitLayerProp (const int AListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx
51
52 /*----------------------------------------------------------------------*/
53
54 struct OPENGL_CLIP_PLANE
55 {
56   GLboolean isEnabled;
57   GLdouble Equation[4];
58   DEFINE_STANDARD_ALLOC
59 };
60
61 /*----------------------------------------------------------------------*/
62 /*
63 * Fonctions privees
64 */
65
66 /*-----------------------------------------------------------------*/
67 /*
68 *  Set des lumieres
69 */
70 static void bind_light(const OpenGl_Light *lptr, int *gl_lid)
71 {
72   // Only 8 lights in OpenGL...
73   if (*gl_lid > GL_LIGHT7) return;
74
75   // the light is a headlight ?
76   GLint cur_matrix;
77   if (lptr->HeadLight)
78   {
79     glGetIntegerv(GL_MATRIX_MODE, &cur_matrix);
80     glMatrixMode(GL_MODELVIEW);
81     glPushMatrix();
82     glLoadIdentity();
83   }
84
85   GLfloat data_amb[4];
86   GLfloat data_diffu[4];
87   GLfloat data_pos[4];
88   GLfloat data_sptdir[3];
89   GLfloat data_sptexpo;
90   GLfloat data_sptcutoff;
91   GLfloat data_constantattenuation;
92   GLfloat data_linearattenuation;
93
94   /* set la light en fonction de son type */
95   switch (lptr->type)
96   {
97   case TLightAmbient:
98     data_amb[0] = lptr->col.rgb[0];
99     data_amb[1] = lptr->col.rgb[1];
100     data_amb[2] = lptr->col.rgb[2];
101     data_amb[3] = 1.0;
102
103     /*------------------------- Ambient ---------------------------*/
104     /*
105     * The GL_AMBIENT parameter refers to RGBA intensity of the ambient
106     * light.
107     */
108     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, data_amb); 
109     break;
110
111
112   case TLightDirectional:
113     data_diffu[0] = lptr->col.rgb[0];
114     data_diffu[1] = lptr->col.rgb[1];
115     data_diffu[2] = lptr->col.rgb[2];
116     data_diffu[3] = 1.0;
117
118     /*------------------------- Direction ---------------------------*/
119     /* From Open GL Programming Rev 1 Guide Chapt 6 :
120     Lighting The Mathematics of Lighting ( p 168 )
121
122     Directional Light Source ( Infinite ) :
123     if the last parameter of GL_POSITION , w , is zero, the
124     corresponding light source is a Directional one.
125
126     GL_SPOT_CUTOFF a 180 signifie que ce n'est pas un spot.
127     To create a realistic effect,  set the GL_SPECULAR parameter 
128     to the same value as the GL_DIFFUSE.
129     */
130
131     data_pos[0] = -lptr->dir[0];
132     data_pos[1] = -lptr->dir[1];
133     data_pos[2] = -lptr->dir[2];
134     data_pos[3] = 0.0;
135
136     glLightfv(*gl_lid, GL_AMBIENT, default_amb);
137     glLightfv(*gl_lid, GL_DIFFUSE, data_diffu);
138     glLightfv(*gl_lid, GL_SPECULAR, data_diffu);
139
140     glLightfv(*gl_lid, GL_POSITION, data_pos);
141     glLightfv(*gl_lid, GL_SPOT_DIRECTION, default_sptdir);
142     glLightf(*gl_lid, GL_SPOT_EXPONENT, default_sptexpo);
143     glLightf(*gl_lid, GL_SPOT_CUTOFF, default_sptcutoff);
144     break;
145
146
147   case TLightPositional:
148     data_diffu[0] = lptr->col.rgb[0];
149     data_diffu[1] = lptr->col.rgb[1];
150     data_diffu[2] = lptr->col.rgb[2];
151     data_diffu[3] = 1.0;
152
153     /*------------------------- Position -----------------------------*/
154     /* From Open GL Programming Rev 1 Guide Chapt 6 :
155     Lighting The Mathematics of Lighting ( p 168 )
156     Positional Light Source :
157     if the last parameter of GL_POSITION , w , is nonzero,
158     the corresponding light source is a Positional one.
159
160     GL_SPOT_CUTOFF a 180 signifie que ce n'est pas un spot.
161
162     To create a realistic effect,  set the GL_SPECULAR parameter 
163     to the same value as the GL_DIFFUSE.
164     */
165
166     data_pos[0] = lptr->pos[0];
167     data_pos[1] = lptr->pos[1];
168     data_pos[2] = lptr->pos[2];
169     data_pos[3] = 1.0;
170
171     data_constantattenuation = lptr->atten[0];
172     data_linearattenuation = lptr->atten[1];
173
174     glLightfv(*gl_lid, GL_AMBIENT, default_amb);
175     glLightfv(*gl_lid, GL_DIFFUSE, data_diffu);
176     glLightfv(*gl_lid, GL_SPECULAR, data_diffu);
177
178     glLightfv(*gl_lid, GL_POSITION, data_pos);
179     glLightfv(*gl_lid, GL_SPOT_DIRECTION, default_sptdir);
180     glLightf(*gl_lid, GL_SPOT_EXPONENT, default_sptexpo);
181     glLightf(*gl_lid, GL_SPOT_CUTOFF, default_sptcutoff);
182     glLightf(*gl_lid, GL_CONSTANT_ATTENUATION, data_constantattenuation);
183     glLightf(*gl_lid, GL_LINEAR_ATTENUATION, data_linearattenuation);
184     glLightf(*gl_lid, GL_QUADRATIC_ATTENUATION, 0.0); 
185     break;
186
187
188   case TLightSpot:
189     data_diffu[0] = lptr->col.rgb[0];
190     data_diffu[1] = lptr->col.rgb[1];
191     data_diffu[2] = lptr->col.rgb[2];
192     data_diffu[3] = 1.0;
193
194     data_pos[0] = lptr->pos[0];
195     data_pos[1] = lptr->pos[1];
196     data_pos[2] = lptr->pos[2];
197     data_pos[3] = 1.0;
198
199     data_sptdir[0] = lptr->dir[0];
200     data_sptdir[1] = lptr->dir[1];
201     data_sptdir[2] = lptr->dir[2];
202
203     data_sptexpo = ( float )lptr->shine * 128.0F;
204     data_sptcutoff = ( float )(lptr->angle * 180.0F)/( float )M_PI;
205
206     data_constantattenuation = lptr->atten[0];
207     data_linearattenuation = lptr->atten[1];
208
209     glLightfv(*gl_lid, GL_AMBIENT, default_amb);
210     glLightfv(*gl_lid, GL_DIFFUSE, data_diffu);
211     glLightfv(*gl_lid, GL_SPECULAR, data_diffu);   
212
213     glLightfv(*gl_lid, GL_POSITION, data_pos);      
214     glLightfv(*gl_lid, GL_SPOT_DIRECTION, data_sptdir);
215     glLightf(*gl_lid, GL_SPOT_EXPONENT, data_sptexpo);
216     glLightf(*gl_lid, GL_SPOT_CUTOFF, data_sptcutoff);
217     glLightf(*gl_lid, GL_CONSTANT_ATTENUATION, data_constantattenuation);
218     glLightf(*gl_lid, GL_LINEAR_ATTENUATION, data_linearattenuation);
219     glLightf(*gl_lid, GL_QUADRATIC_ATTENUATION, 0.0); 
220     break;
221   }
222
223   if (lptr->type != TLightAmbient) 
224   {  
225     glEnable(*gl_lid);
226     (*gl_lid)++;
227   }
228
229   /* si la light etait une headlight alors restaure la matrice precedente */
230   if (lptr->HeadLight)
231   {
232     glPopMatrix();
233     glMatrixMode(cur_matrix);
234   }
235 }
236
237 /*----------------------------------------------------------------------*/
238 /*
239 * Prototypes
240 */
241
242 static void call_util_apply_trans2( float ix, float iy, float iz, matrix3 mat,
243                                    float *ox, float *oy, float *oz );
244 static void call_util_mat_mul( matrix3 mat_a, matrix3 mat_b, matrix3 mat_c);
245
246 /*----------------------------------------------------------------------*/
247 /*
248 * Fonctions externes
249 */
250
251 /*
252 *  Evaluates orientation matrix.
253 */
254 /* OCC18942: obsolete in OCCT6.3, might be removed in further versions! */
255 void call_func_eval_ori_matrix3 (const point3* vrp,        // view reference point
256                                  const vec3*   vpn,        // view plane normal
257                                  const vec3*   vup,        // view up vector
258                                  int*          err_ind, 
259                                  float         mout[4][4]) // OUT view orientation matrix
260 {
261
262   /* Translate to VRP then change the basis.
263   * The old basis is: e1 = < 1, 0, 0>, e2 = < 0, 1, 0>, e3 = < 0, 0, 1>.
264   * The new basis is: ("x" means cross product)
265   *  e3' = VPN / |VPN|
266   *  e1' = VUP x VPN / |VUP x VPN|
267   *  e2' = e3' x e1'
268   * Therefore the transform from old to new is x' = TAx, where:
269   *
270   *       | e1'x e2'x e3'x 0 |         |   1      0      0      0 |
271   *   A = | e1'y e2'y e3'y 0 |,    T = |   0      1      0      0 |
272   *       | e1'z e2'z e3'z 0 |         |   0      0      1      0 |
273   *       |  0    0    0   1 |         | -vrp.x -vrp.y -vrp.z   1 |
274   *
275   */
276
277   /*
278   * These ei's are really ei primes.
279   */
280   register float      (*m)[4][4];
281   point3      e1, e2, e3, e4;
282   double      s, v;
283
284   /*
285   * e1' = VUP x VPN / |VUP x VPN|, but do the division later.
286   */
287   e1.x = vup->delta_y * vpn->delta_z - vup->delta_z * vpn->delta_y;
288   e1.y = vup->delta_z * vpn->delta_x - vup->delta_x * vpn->delta_z;
289   e1.z = vup->delta_x * vpn->delta_y - vup->delta_y * vpn->delta_x;
290   s = sqrt( e1.x * e1.x + e1.y * e1.y + e1.z * e1.z);
291   e3.x = vpn->delta_x;
292   e3.y = vpn->delta_y;
293   e3.z = vpn->delta_z;
294   v = sqrt( e3.x * e3.x + e3.y * e3.y + e3.z * e3.z);
295   /*
296   * Check for vup and vpn colinear (zero dot product).
297   */
298   if ((s > -EPSI) && (s < EPSI))
299     *err_ind = 2;
300   else
301     /*
302     * Check for a normal vector not null.
303     */
304     if ((v > -EPSI) && (v < EPSI))
305       *err_ind = 3;
306     else {
307       /*
308       * Normalize e1
309       */
310       e1.x /= ( float )s;
311       e1.y /= ( float )s;
312       e1.z /= ( float )s;
313       /*
314       * e3 = VPN / |VPN|
315       */
316       e3.x /= ( float )v;
317       e3.y /= ( float )v;
318       e3.z /= ( float )v;
319       /*
320       * e2 = e3 x e1
321       */
322       e2.x = e3.y * e1.z - e3.z * e1.y;
323       e2.y = e3.z * e1.x - e3.x * e1.z;
324       e2.z = e3.x * e1.y - e3.y * e1.x;
325       /*
326       * Add the translation
327       */
328       e4.x = -( e1.x * vrp->x + e1.y * vrp->y + e1.z * vrp->z);
329       e4.y = -( e2.x * vrp->x + e2.y * vrp->y + e2.z * vrp->z);
330       e4.z = -( e3.x * vrp->x + e3.y * vrp->y + e3.z * vrp->z);
331       /*
332       * Homogeneous entries
333       *
334       *  | e1.x  e2.x  e3.x  0.0 |   | 1  0  0  0 |
335       *  | e1.y  e2.y  e3.y  0.0 | * | 0  1  0  0 |
336       *  | e1.z  e2.z  e3.z  0.0 |   | a  b  1  c |
337       *  | e4.x  e4.y  e4.z  1.0 |   | 0  0  0  1 |
338       */
339
340       m = (float (*)[4][4])mout;
341
342       (*m)[0][0] = e1.x;
343       (*m)[0][1] = e2.x;
344       (*m)[0][2] = e3.x;
345       (*m)[0][3] = ( float )0.0;
346
347       (*m)[1][0] = e1.y;
348       (*m)[1][1] = e2.y;
349       (*m)[1][2] = e3.y;
350       (*m)[1][3] = ( float )0.0;
351
352       (*m)[2][0] = e1.z;
353       (*m)[2][1] = e2.z;
354       (*m)[2][2] = e3.z;
355       (*m)[2][3] = ( float )0.0;
356
357       (*m)[3][0] = e4.x;
358       (*m)[3][1] = e4.y;
359       (*m)[3][2] = e4.z;
360       (*m)[3][3] = ( float )1.0;
361
362       *err_ind = 0;
363     }
364 }
365
366 /*----------------------------------------------------------------------*/
367 /*
368 *  Evaluates mapping matrix.
369 */
370 /* OCC18942: obsolete in OCCT6.3, might be removed in further versions! */
371 void call_func_eval_map_matrix3(
372                                 view_map3 *Map, 
373                                 int *err_ind, 
374                                 matrix3 mat)
375 {
376   int i, j;
377   matrix3 Tpar, Spar;
378   matrix3 Tper, Sper;
379   matrix3 Shear;
380   matrix3 Scale;
381   matrix3 Tprp;
382   matrix3 aux_mat1, aux_mat2, aux_mat3;
383   point3 Prp;
384
385   *err_ind = 0;
386   for (i=0; i<4; i++)
387     for (j=0; j<4; j++)
388       Spar[i][j] = Sper[i][j] = aux_mat1[i][j] = aux_mat2[i][j] =
389       aux_mat3[i][j] = Tper[i][j] = Tpar[i][j] = Tprp[i][j] =
390       Shear[i][j] = Scale[i][j] = ( float )(i == j);
391
392   Prp.x = Map->proj_ref_point.x;
393   Prp.y = Map->proj_ref_point.y;
394   Prp.z = Map->proj_ref_point.z;
395
396   /*
397   * Type Parallele
398   */    
399   if (Map->proj_type == TYPE_PARAL)
400   {
401     float umid, vmid;
402     point3 temp;
403
404 #ifdef FMN
405     float    cx, cy, gx, gy, xsf, ysf, zsf;
406     float    fpd, bpd;
407     float    dopx, dopy, dopz;
408     matrix3  tmat = { { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
409     { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
410     { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
411     { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 } };
412     matrix3  smat = { { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
413     { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
414     { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
415     { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 } };
416     matrix3 shmat = { { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
417     { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
418     { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
419     { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 } };
420     matrix3 tshmat = { { ( float )1.0, ( float )0.0, ( float )0.0, ( float )0.0 },
421     { ( float )0.0, ( float )1.0, ( float )0.0, ( float )0.0 },
422     { ( float )0.0, ( float )0.0, ( float )1.0, ( float )0.0 },
423     { ( float )0.0, ( float )0.0, ( float )0.0, ( float )1.0 } };
424
425     /* centers */
426     cx = Map->win.x_min + Map->win.x_max, cx /= ( float )2.0;
427     cy = Map->win.y_min + Map->win.y_max, cy /= ( float )2.0;
428
429     gx = 2.0/ (Map->win.x_max - Map->win.x_min);
430     gy = 2.0/ (Map->win.y_max - Map->win.y_min);
431
432     tmat[0][3] = -cx;
433     tmat[1][3] = -cy;
434     tmat[2][3] = (Map->front_plane + Map->back_plane)/(Map->front_plane - Map->back_plane);
435
436     smat[0][0] = gx;
437     smat[1][1] = gy;
438     smat[2][2] = -2./(Map->front_plane - Map->back_plane);
439
440     /* scale factors */
441     dopx = cx - Prp.x;
442     dopy = cy - Prp.y;
443     dopz = - Prp.z;
444
445     /* map matrix */
446     shmat[0][2] = -(dopx/dopz);
447     shmat[1][2] = -(dopy/dopz);
448
449     /* multiply to obtain mapping matrix */
450     call_util_mat_mul( tmat, shmat, tshmat );
451     call_util_mat_mul( smat, tshmat, mat );
452
453     return;         
454 #endif
455
456     /* CAL */
457     Map->proj_vp.z_min = ( float )0.0;
458     Map->proj_vp.z_max = ( float )1.0;
459     /* CAL */
460
461     /* Shear matrix calculation */
462     umid = ( float )(Map->win.x_min+Map->win.x_max)/( float )2.0;
463     vmid = ( float )(Map->win.y_min+Map->win.y_max)/( float )2.0;
464     if(Prp.z == Map->view_plane){
465       /* Projection reference point is on the view plane */
466       *err_ind = 1;
467       return;
468     }
469     Shear[2][0] = ( float )(-1.0) * ((Prp.x-umid)/(Prp.z-Map->view_plane));
470     Shear[2][1] = ( float )(-1.0) * ((Prp.y-vmid)/(Prp.z-Map->view_plane));
471
472     /*
473     * Calculate the lower left coordinate of the view plane
474     * after the Shearing Transformation.
475     */
476     call_util_apply_trans2(Map->win.x_min, Map->win.y_min,
477       Map->view_plane, Shear, &(temp.x), &(temp.y), &(temp.z));
478
479     /* Translate the back plane to the origin */
480     Tpar[3][0] = ( float )(-1.0) * temp.x;
481     Tpar[3][1] = ( float )(-1.0) * temp.y;
482     Tpar[3][2] = ( float )(-1.0) * Map->back_plane;
483
484     call_util_mat_mul(Shear, Tpar, aux_mat1);
485
486     /* Calculation of Scaling transformation */
487     Spar[0][0] = ( float )1.0 / (Map->win.x_max - Map->win.x_min);
488     Spar[1][1] = ( float )1.0 / (Map->win.y_max - Map->win.y_min);
489     Spar[2][2] = ( float )1.0 / (Map->front_plane - Map->back_plane );
490     call_util_mat_mul (aux_mat1, Spar, aux_mat2);
491     /* Atlast we transformed view volume to NPC */
492
493     /* Translate and scale the view plane to projection view port */
494     if(Map->proj_vp.x_min < 0.0 || Map->proj_vp.y_min < 0.0 ||
495       Map->proj_vp.z_min < 0.0 || Map->proj_vp.x_max > 1.0 ||
496       Map->proj_vp.y_max > 1.0 || Map->proj_vp.z_max > 1.0 ||
497       Map->proj_vp.x_min > Map->proj_vp.x_max ||
498       Map->proj_vp.y_min > Map->proj_vp.y_max ||
499       Map->proj_vp.z_min > Map->proj_vp.z_max){
500         *err_ind = 1;
501         return;
502       }
503       for(i=0; i<4; i++)
504         for(j=0; j<4; j++)
505           aux_mat1[i][j] = (float)(i==j);
506       aux_mat1[0][0] = Map->proj_vp.x_max-Map->proj_vp.x_min;
507       aux_mat1[1][1] = Map->proj_vp.y_max-Map->proj_vp.y_min;
508       aux_mat1[2][2] = Map->proj_vp.z_max-Map->proj_vp.z_min;
509       aux_mat1[3][0] = Map->proj_vp.x_min;
510       aux_mat1[3][1] = Map->proj_vp.y_min;
511       aux_mat1[3][2] = Map->proj_vp.z_min;
512       call_util_mat_mul (aux_mat2, aux_mat1, mat);
513
514       return;         
515   } 
516
517   /*
518   * Type Perspective
519   */    
520   else if (Map->proj_type == TYPE_PERSPECT)
521   {
522     float umid, vmid;
523     float B, F, V;
524     float Zvmin;
525
526     /* CAL */
527     Map->proj_vp.z_min = ( float )0.0;
528     Map->proj_vp.z_max = ( float )1.0;
529     /* CAL */
530
531     B = Map->back_plane;
532     F = Map->front_plane;
533     V = Map->view_plane;
534
535     if(Prp.z == Map->view_plane){
536       /* Centre of Projection is on the view plane */
537       *err_ind = 1;
538       return;
539     }
540     if(Map->proj_vp.x_min < 0.0 || Map->proj_vp.y_min < 0.0 ||
541       Map->proj_vp.z_min < 0.0 || Map->proj_vp.x_max > 1.0 ||
542       Map->proj_vp.y_max > 1.0 || Map->proj_vp.z_max > 1.0 ||
543       Map->proj_vp.x_min > Map->proj_vp.x_max ||
544       Map->proj_vp.y_min > Map->proj_vp.y_max ||
545       Map->proj_vp.z_min > Map->proj_vp.z_max ||
546       F < B){
547         *err_ind = 1;
548         return;
549       }
550
551       /* This is the transformation to move VRC to Center Of Projection */
552       Tprp[3][0] = ( float )(-1.0)*Prp.x;
553       Tprp[3][1] = ( float )(-1.0)*Prp.y;
554       Tprp[3][2] = ( float )(-1.0)*Prp.z;
555
556       /* Calculation of Shear matrix */
557       umid = ( float )(Map->win.x_min+Map->win.x_max)/( float )2.0-Prp.x;
558       vmid = ( float )(Map->win.y_min+Map->win.y_max)/( float )2.0-Prp.y;
559       Shear[2][0] = ( float )(-1.0)*umid/(Map->view_plane-Prp.z);
560       Shear[2][1] = ( float )(-1.0)*vmid/(Map->view_plane-Prp.z);
561       call_util_mat_mul(Tprp, Shear, aux_mat3);
562
563       /* Scale the view volume to canonical view volume
564       * Centre of projection at origin.
565       * 0 <= N <= -1, -0.5 <= U <= 0.5, -0.5 <= V <= 0.5
566       */
567       Scale[0][0] =  (( float )(-1.0)*Prp.z+V)/
568         ((Map->win.x_max-Map->win.x_min)*(( float )(-1.0)*Prp.z+B));
569       Scale[1][1] =  (( float )(-1.0)*Prp.z+V)/
570         ((Map->win.y_max-Map->win.y_min)*(( float )(-1.0)*Prp.z+B));
571       Scale[2][2] =  ( float )(-1.0) / (( float )(-1.0)*Prp.z+B);
572
573       call_util_mat_mul(aux_mat3, Scale, aux_mat1);
574
575       /*
576       * Transform the Perspective view volume into
577       * Parallel view volume.
578       * Lower left coordinate: (-0.5,-0.5, -1)
579       * Upper right coordinate: (0.5, 0.5, 1.0)
580       */
581       Zvmin = ( float )(-1.0*(-1.0*Prp.z+F)/(-1.0*Prp.z+B));
582       aux_mat2[2][2] = ( float )1.0/(( float )1.0+Zvmin);
583       aux_mat2[2][3] = ( float )(-1.0);
584       aux_mat2[3][2] = ( float )(-1.0)*Zvmin*aux_mat2[2][2];
585       aux_mat2[3][3] = ( float )0.0;
586       call_util_mat_mul(aux_mat1, aux_mat2, Shear);
587
588       for(i=0; i<4; i++)
589         for(j=0; j<4; j++)
590           aux_mat1[i][j] = aux_mat2[i][j] = (float)(i==j);
591
592       /* Translate and scale the view plane to projection view port */
593       aux_mat2[0][0] = (Map->proj_vp.x_max-Map->proj_vp.x_min);
594       aux_mat2[1][1] = (Map->proj_vp.y_max-Map->proj_vp.y_min);
595       aux_mat2[2][2] = (Map->proj_vp.z_max-Map->proj_vp.z_min);
596       aux_mat2[3][0] = aux_mat2[0][0]/( float )2.0+Map->proj_vp.x_min;
597       aux_mat2[3][1] = aux_mat2[1][1]/( float )2.0+Map->proj_vp.y_min;
598       aux_mat2[3][2] = aux_mat2[2][2]+Map->proj_vp.z_min;
599       call_util_mat_mul (Shear, aux_mat2, mat);
600
601       return;
602   }
603   else
604     *err_ind = 1;
605 }
606
607 /*----------------------------------------------------------------------*/
608
609 static void
610 call_util_apply_trans2( float ix, float iy, float iz, matrix3 mat,
611                        float *ox, float *oy, float *oz )
612 {
613   float temp;
614   *ox = ix*mat[0][0]+iy*mat[1][0]+iz*mat[2][0]+mat[3][0];
615   *oy = ix*mat[0][1]+iy*mat[1][1]+iz*mat[2][1]+mat[3][1];
616   *oz = ix*mat[0][2]+iy*mat[1][2]+iz*mat[2][2]+mat[3][2];
617   temp = ix * mat[0][3]+iy * mat[1][3]+iz * mat[2][3]+mat[3][3];
618   *ox /= temp;
619   *oy /= temp;
620   *oz /= temp;
621 }
622
623 /*----------------------------------------------------------------------*/
624
625 static void
626 call_util_mat_mul( matrix3 mat_a, matrix3 mat_b, matrix3 mat_c)
627 {
628   int i, j, k;
629
630   for (i=0; i<4; i++)
631     for (j=0; j<4; j++)
632       for (mat_c[i][j] = ( float )0.0,k=0; k<4; k++)
633         mat_c[i][j] += mat_a[i][k] * mat_b[k][j];
634 }
635
636 /*----------------------------------------------------------------------*/
637
638 //call_func_redraw_all_structs_proc
639 void OpenGl_View::Render (const Handle(OpenGl_Workspace) &AWorkspace,
640                          const Graphic3d_CView& ACView,
641                          const Aspect_CLayer2d& ACUnderLayer,
642                          const Aspect_CLayer2d& ACOverLayer)
643 {
644   // Reset FLIST status after modification of myBackfacing
645   if (myResetFLIST)
646   {
647     AWorkspace->NamedStatus &= ~OPENGL_NS_FLIST;
648     myResetFLIST = Standard_False;
649   }
650
651   // Store and disable current clipping planes
652   GLint maxplanes;
653   glGetIntegerv(GL_MAX_CLIP_PLANES, &maxplanes);
654   const GLenum lastid = GL_CLIP_PLANE0 + maxplanes;
655   OPENGL_CLIP_PLANE *oldPlanes = new OPENGL_CLIP_PLANE[maxplanes];
656   OPENGL_CLIP_PLANE *ptrPlane = oldPlanes;
657   GLenum planeid = GL_CLIP_PLANE0;
658   for ( ; planeid < lastid; planeid++, ptrPlane++ )
659   {
660     glGetClipPlane( planeid, ptrPlane->Equation );
661     if ( ptrPlane->isEnabled )
662     {
663       glDisable( planeid );
664       ptrPlane->isEnabled = GL_TRUE;
665     }
666         else
667       ptrPlane->isEnabled = GL_FALSE;
668   }
669
670   /////////////////////////////////////////////////////////////////////////////
671   // Step 1: Prepare for redraw
672
673   // Render background
674   if ( (AWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) == 0 &&
675            ( myBgTexture.TexId != 0 || myBgGradient.type != Aspect_GFM_NONE ) )
676   {
677     const Standard_Integer aViewWidth = AWorkspace->Width();
678     const Standard_Integer aViewHeight = AWorkspace->Height();
679
680     glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
681
682     glMatrixMode( GL_PROJECTION );
683     glPushMatrix();
684     glLoadIdentity();
685     glMatrixMode( GL_MODELVIEW );
686     glPushMatrix();
687     glLoadIdentity();
688
689     if ( glIsEnabled( GL_DEPTH_TEST ) )
690       glDisable( GL_DEPTH_TEST ); //push GL_ENABLE_BIT
691
692     // drawing bg gradient if:
693     // - gradient fill type is not Aspect_GFM_NONE and
694     // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode
695     if ( ( myBgGradient.type != Aspect_GFM_NONE ) &&
696          ( myBgTexture.TexId == 0 || myBgTexture.Style == Aspect_FM_CENTERED ||
697            myBgTexture.Style == Aspect_FM_NONE ) )
698     {
699       Tfloat* corner1 = 0;/* -1,-1*/
700       Tfloat* corner2 = 0;/*  1,-1*/
701       Tfloat* corner3 = 0;/*  1, 1*/
702       Tfloat* corner4 = 0;/* -1, 1*/
703       Tfloat dcorner1[3];
704       Tfloat dcorner2[3];
705
706       switch( myBgGradient.type )
707       {
708         case Aspect_GFM_HOR:
709           corner1 = myBgGradient.color1.rgb;
710           corner2 = myBgGradient.color2.rgb;
711           corner3 = myBgGradient.color2.rgb;
712           corner4 = myBgGradient.color1.rgb;
713           break;
714         case Aspect_GFM_VER:
715           corner1 = myBgGradient.color2.rgb;
716           corner2 = myBgGradient.color2.rgb;
717           corner3 = myBgGradient.color1.rgb;
718           corner4 = myBgGradient.color1.rgb;
719           break;
720         case Aspect_GFM_DIAG1:
721           corner2 = myBgGradient.color2.rgb;
722           corner4 = myBgGradient.color1.rgb;        
723           dcorner1 [0] = dcorner2[0] = 0.5F * (corner2[0] + corner4[0]);
724           dcorner1 [1] = dcorner2[1] = 0.5F * (corner2[1] + corner4[1]);
725           dcorner1 [2] = dcorner2[2] = 0.5F * (corner2[2] + corner4[2]);
726           corner1 = dcorner1;
727           corner3 = dcorner2;  
728           break;
729         case Aspect_GFM_DIAG2:
730           corner1 = myBgGradient.color2.rgb;  
731           corner3 = myBgGradient.color1.rgb;       
732           dcorner1 [0] = dcorner2[0] = 0.5F * (corner1[0] + corner3[0]);
733           dcorner1 [1] = dcorner2[1] = 0.5F * (corner1[1] + corner3[1]);
734           dcorner1 [2] = dcorner2[2] = 0.5F * (corner1[2] + corner3[2]);
735           corner2 = dcorner1;
736           corner4 = dcorner2;  
737           break;
738         case Aspect_GFM_CORNER1:
739           corner1 = myBgGradient.color2.rgb;
740           corner2 = myBgGradient.color2.rgb;
741           corner3 = myBgGradient.color2.rgb;
742           corner4 = myBgGradient.color1.rgb;
743           break;
744         case Aspect_GFM_CORNER2:
745           corner1 = myBgGradient.color2.rgb;
746           corner2 = myBgGradient.color2.rgb;
747           corner3 = myBgGradient.color1.rgb;
748           corner4 = myBgGradient.color2.rgb;
749           break;
750         case Aspect_GFM_CORNER3:
751           corner1 = myBgGradient.color2.rgb;
752           corner2 = myBgGradient.color1.rgb;
753           corner3 = myBgGradient.color2.rgb;
754           corner4 = myBgGradient.color2.rgb;
755           break;
756         case Aspect_GFM_CORNER4:
757           corner1 = myBgGradient.color1.rgb;
758           corner2 = myBgGradient.color2.rgb;
759           corner3 = myBgGradient.color2.rgb;
760           corner4 = myBgGradient.color2.rgb;
761           break;
762         default:
763           //printf("gradient background type not right\n");
764          break;
765       }
766
767       // Save GL parameters
768       glDisable( GL_LIGHTING ); //push GL_ENABLE_BIT
769
770       GLint curSM;
771       glGetIntegerv( GL_SHADE_MODEL, &curSM );
772       if ( curSM != GL_SMOOTH )
773         glShadeModel( GL_SMOOTH ); //push GL_LIGHTING_BIT
774
775       glBegin(GL_TRIANGLE_FAN);
776       if( myBgGradient.type != Aspect_GFM_CORNER1 && myBgGradient.type != Aspect_GFM_CORNER3 )
777       {
778         glColor3f(corner1[0],corner1[1],corner1[2]); glVertex2f(-1.,-1.);
779         glColor3f(corner2[0],corner2[1],corner2[2]); glVertex2f( 1.,-1.);
780         glColor3f(corner3[0],corner3[1],corner3[2]); glVertex2f( 1., 1.);
781         glColor3f(corner4[0],corner4[1],corner4[2]); glVertex2f(-1., 1.);
782       }         
783       else //if ( myBgGradient.type == Aspect_GFM_CORNER1 || myBgGradient.type == Aspect_GFM_CORNER3 )
784       {
785         glColor3f(corner2[0],corner2[1],corner2[2]); glVertex2f( 1.,-1.);
786         glColor3f(corner3[0],corner3[1],corner3[2]); glVertex2f( 1., 1.);
787         glColor3f(corner4[0],corner4[1],corner4[2]); glVertex2f(-1., 1.);
788         glColor3f(corner1[0],corner1[1],corner1[2]); glVertex2f(-1.,-1.);
789       }
790       glEnd();
791
792       // Restore GL parameters
793       if ( curSM != GL_SMOOTH )
794         glShadeModel( curSM );
795     }
796     // drawing bg image if:
797     // - it is defined and
798     // - fill type is not Aspect_FM_NONE
799     if ( myBgTexture.TexId != 0 && myBgTexture.Style != Aspect_FM_NONE )
800     {
801       GLfloat texX_range = 1.F; // texture <s> coordinate
802       GLfloat texY_range = 1.F; // texture <t> coordinate
803
804           // Set up for stretching or tiling
805       GLfloat x_offset, y_offset;
806       if ( myBgTexture.Style == Aspect_FM_CENTERED )
807       {
808         x_offset = (GLfloat)myBgTexture.Width / (GLfloat)aViewWidth;
809         y_offset = (GLfloat)myBgTexture.Height / (GLfloat)aViewHeight;
810       }
811       else
812       {
813         x_offset = 1.F;
814         y_offset = 1.F;
815         if ( myBgTexture.Style == Aspect_FM_TILED )
816         {
817           texX_range = (GLfloat)aViewWidth / (GLfloat)myBgTexture.Width;
818           texY_range = (GLfloat)aViewHeight / (GLfloat)myBgTexture.Height;
819         }
820       }
821
822       glEnable( GL_TEXTURE_2D ); //push GL_ENABLE_BIT
823       glBindTexture( GL_TEXTURE_2D, myBgTexture.TexId ); //push GL_TEXTURE_BIT
824
825       glDisable( GL_BLEND ); //push GL_ENABLE_BIT
826
827       glColor3fv( AWorkspace->BackgroundColor().rgb );
828       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); //push GL_TEXTURE_BIT
829
830       glBegin( GL_QUADS );
831       glTexCoord2f(0.F, 0.F); glVertex2f( -x_offset, -y_offset );
832       glTexCoord2f(texX_range, 0.F); glVertex2f( x_offset, -y_offset );
833       glTexCoord2f(texX_range, texY_range); glVertex2f( x_offset, y_offset );
834       glTexCoord2f(0.F, texY_range); glVertex2f( -x_offset, y_offset );
835       glEnd();
836     }
837
838     glPopMatrix();
839     glMatrixMode( GL_PROJECTION );
840     glPopMatrix();
841     glMatrixMode( GL_MODELVIEW );
842
843     glPopAttrib(); //GL_ENABLE_BIT | GL_TEXTURE_BIT
844
845     if ( AWorkspace->UseZBuffer() )
846       glEnable( GL_DEPTH_TEST );
847
848     /* GL_DITHER on/off pour le trace */
849     if (AWorkspace->Dither())
850       glEnable (GL_DITHER);
851     else
852       glDisable (GL_DITHER);
853   }
854
855   // Switch off lighting by default
856   glDisable(GL_LIGHTING);
857
858   /////////////////////////////////////////////////////////////////////////////
859   // Step 2: Draw underlayer
860   RedrawLayer2d(AWorkspace, ACView, ACUnderLayer);
861
862   /////////////////////////////////////////////////////////////////////////////
863   // Step 3: Redraw main plane
864
865   // Setup face culling
866   GLboolean isCullFace = GL_FALSE;
867   if ( myBackfacing )
868   {
869     isCullFace = glIsEnabled( GL_CULL_FACE );
870     if ( myBackfacing < 0 )
871     {
872       glEnable( GL_CULL_FACE );
873       glCullFace( GL_BACK );
874     }
875         else
876       glDisable( GL_CULL_FACE );
877   }
878
879   //TsmPushAttri(); /* save previous graphics context */
880
881   // if the view is scaled normal vectors are scaled to unit length for correct displaying of shaded objects
882   if(myExtra.scaleFactors[0] != 1.F || 
883      myExtra.scaleFactors[1] != 1.F ||
884      myExtra.scaleFactors[2] != 1.F)
885     glEnable(GL_NORMALIZE);
886   else if(glIsEnabled(GL_NORMALIZE))  
887     glDisable(GL_NORMALIZE);
888
889   // Apply View Projection
890   // This routine activates the Projection matrix for a view.
891
892   glMatrixMode( GL_PROJECTION );
893
894 #ifdef WNT
895   // add printing scale/tiling transformation
896   OpenGl_PrinterContext* aPrinterContext = OpenGl_PrinterContext::GetPrinterContext(AWorkspace->GetGContext());
897
898   if (aPrinterContext)
899   {
900     GLfloat aProjMatrix[16];
901     aPrinterContext->GetProjTransformation(aProjMatrix);
902     glLoadMatrixf((GLfloat*) aProjMatrix);
903   }
904   else
905 #endif
906     glLoadIdentity();
907
908   glMultMatrixf( (const GLfloat *) myMappingMatrix );
909
910   // Add translation necessary for the environnement mapping
911   if (mySurfaceDetail != Visual3d_TOD_NONE)
912   {
913     // OCC280: FitAll work incorrect for perspective view if the SurfaceDetail mode is V3d_TEX_ENVIRONMENT or V3d_TEX_ALL
914     // const GLfloat dep = vptr->vrep.extra.map.fpd * 0.5F;
915     const GLfloat dep = (myExtra.map.fpd + myExtra.map.bpd) * 0.5F;
916     glTranslatef(-dep*myExtra.vpn[0],-dep*myExtra.vpn[1],-dep*myExtra.vpn[2]);
917   }
918
919   // Apply matrix
920   AWorkspace->SetViewMatrix((const OpenGl_Matrix *)myOrientationMatrix);
921
922 /*
923 While drawing after a clipplane has been defined and enabled, each vertex
924 is transformed to eye-coordinates, where it is dotted with the transformed
925 clipping plane equation.  Eye-coordinate vertexes whose dot product with
926 the transformed clipping plane equation is positive or zero are in, and
927 require no clipping.  Those eye-coordinate vertexes whose dot product is
928 negative are clipped.  Because clipplane clipping is done in eye-
929 coordinates, changes to the projection matrix have no effect on its
930 operation.
931
932 A point and a normal are converted to a plane equation in the following manner:
933
934 point = [Px,Py,Pz]
935
936 normal = |Nx|
937 |Ny|
938 |Nz|
939
940 plane equation = |A|
941 |B|
942 |C|
943 |D|
944 A = Nx
945 B = Ny
946 C = Nz
947 D = -[Px,Py,Pz] dot |Nx|
948 |Ny|
949 |Nz|
950
951 */
952
953   glPushAttrib( GL_FOG_BIT | GL_LIGHTING_BIT | GL_ENABLE_BIT );
954
955   // Apply Fog
956   if ( myFog.IsOn )
957   {
958     const GLfloat ramp = myExtra.map.fpd - myExtra.map.bpd;
959     const GLfloat fog_start = myFog.Front * ramp - myExtra.map.fpd;
960     const GLfloat fog_end   = myFog.Back  * ramp - myExtra.map.fpd;
961
962     glFogi(GL_FOG_MODE, GL_LINEAR);
963     glFogf(GL_FOG_START, fog_start);
964     glFogf(GL_FOG_END, fog_end);
965     glFogfv(GL_FOG_COLOR, myFog.Color.rgb);
966     glEnable(GL_FOG);
967   }
968   else
969     glDisable(GL_FOG);
970
971   // Apply Lights
972   {
973     int i;
974
975     // Switch off all lights
976     for (i = GL_LIGHT0; i <= GL_LIGHT7; i++)
977       glDisable(i);
978     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, default_amb);
979
980     /* set les lights */
981     int gl_lid = GL_LIGHT0;
982     OpenGl_ListOfLight::Iterator itl(myLights);
983     for (; itl.More(); itl.Next())
984     {
985       const OpenGl_Light &alight = itl.Value();
986       bind_light(&alight, &gl_lid);
987     }
988
989     if (gl_lid != GL_LIGHT0) glEnable(GL_LIGHTING);
990   }
991
992   // Apply InteriorShadingMethod
993   glShadeModel( myIntShadingMethod == TEL_SM_FLAT ? GL_FLAT : GL_SMOOTH );
994
995   // Apply clipping planes
996   {
997     // Define starting plane id
998     planeid = GL_CLIP_PLANE0;
999
1000     GLdouble equation[4];
1001
1002     if ( myZClip.Back.IsOn || myZClip.Front.IsOn )
1003     {
1004       // Apply front and back clipping planes
1005       GLfloat mat[4][4];
1006       glMatrixMode( GL_MODELVIEW );
1007       glGetFloatv( GL_MODELVIEW_MATRIX,(GLfloat *) mat );
1008       glLoadIdentity();
1009
1010       const GLdouble ramp = myExtra.map.fpd - myExtra.map.bpd;
1011
1012       if ( myZClip.Back.IsOn )
1013       {
1014         const GLdouble back = ramp * myZClip.Back.Limit + myExtra.map.bpd;
1015         equation[0] = 0.0;  /* Nx */
1016         equation[1] = 0.0;  /* Ny */
1017         equation[2] = 1.0;  /* Nz */
1018         equation[3] = -back; /* P dot N */
1019         glClipPlane( planeid, equation );
1020         glEnable( planeid );
1021         planeid++;
1022       }
1023
1024       if ( myZClip.Front.IsOn )
1025       {
1026         const GLdouble front = ramp * myZClip.Front.Limit + myExtra.map.bpd;
1027         equation[0] = 0.0;  /* Nx */
1028         equation[1] = 0.0;  /* Ny */
1029         equation[2] = -1.0; /* Nz */
1030         equation[3] = front; /* P dot N */
1031         glClipPlane( planeid, equation );
1032         glEnable( planeid );
1033         planeid++;
1034       }
1035
1036       glLoadMatrixf( (GLfloat *) mat );
1037     }
1038
1039     // Apply user clipping planes
1040     NCollection_List<OPENGL_CLIP_REP>::Iterator planeIter(myClippingPlanes);
1041     for ( ; planeIter.More(); planeIter.Next() )
1042     {
1043       glClipPlane( planeid, planeIter.Value().equation );
1044       glEnable( planeid );
1045       planeid++;
1046     }
1047   }
1048
1049   // Apply AntiAliasing
1050   {
1051     if (myAntiAliasing)
1052       AWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING;
1053         else
1054       AWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING;
1055   }
1056
1057   Standard_Boolean isAnimationListOpen = Standard_False;
1058
1059   // Request for update of animation mode?
1060   if ( (AWorkspace->NamedStatus & OPENGL_NS_UPDATEAM) != 0 )
1061   {
1062     // Request to rebuild display list
1063     myAnimationListReady = Standard_False;
1064     // Reset request for update of animation mode
1065     AWorkspace->NamedStatus &= ~OPENGL_NS_UPDATEAM;
1066   }
1067
1068   // Is in animation mode?
1069   if ( AWorkspace->NamedStatus & OPENGL_NS_ANIMATION )
1070   {
1071     // Is the animation list ready?
1072     if (myAnimationListReady)
1073     {
1074       // Execute the animation list
1075       glCallList(myAnimationListIndex);
1076     }
1077     else
1078     {
1079       // Update the animation list
1080       if ( AWorkspace->NamedStatus & OPENGL_NS_FLIST )
1081       {
1082         if (myAnimationListIndex == 0)
1083           myAnimationListIndex = glGenLists(1);
1084
1085         if (myAnimationListIndex != 0)
1086         {
1087           glNewList(myAnimationListIndex, GL_COMPILE_AND_EXECUTE);
1088           isAnimationListOpen = Standard_True;
1089         }
1090       }
1091       else
1092         AWorkspace->NamedStatus |= OPENGL_NS_FLIST;
1093     }
1094   }
1095   else
1096     myAnimationListReady = Standard_False;
1097
1098   if (!myAnimationListReady)
1099   {
1100     // Clear status bitfields
1101     AWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
1102
1103     // Added PCT for handling of textures
1104     switch (mySurfaceDetail)
1105     {
1106       case Visual3d_TOD_NONE:
1107         AWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1108         DisableTexture();
1109         // Render the view
1110         RenderStructs(AWorkspace);
1111         break;
1112
1113       case Visual3d_TOD_ENVIRONMENT:
1114         AWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1115         SetCurrentTexture(myTextureEnv);
1116         EnableTexture();
1117         // Render the view
1118         RenderStructs(AWorkspace);
1119         DisableTexture();
1120         break;
1121
1122       case Visual3d_TOD_ALL:
1123         // First pass
1124         AWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX;
1125         // Render the view
1126         RenderStructs(AWorkspace);
1127         DisableTexture();
1128
1129         // Second pass
1130         if (AWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
1131         {
1132           AWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
1133           SetCurrentTexture(myTextureEnv);
1134           EnableTexture();
1135
1136           /* sauvegarde de quelques parametres OpenGL */
1137           GLint blend_dst, blend_src;
1138           GLint zbuff_f;
1139           GLboolean zbuff_w;
1140           glGetBooleanv(GL_DEPTH_WRITEMASK, &zbuff_w);
1141           glGetIntegerv(GL_DEPTH_FUNC, &zbuff_f);
1142           glGetIntegerv(GL_BLEND_DST, &blend_dst); 
1143           glGetIntegerv(GL_BLEND_SRC, &blend_src);    
1144           GLboolean zbuff_state = glIsEnabled(GL_DEPTH_TEST);
1145           GLboolean blend_state = glIsEnabled(GL_BLEND);
1146
1147           glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
1148           glEnable(GL_BLEND);
1149
1150           glDepthFunc(GL_EQUAL);
1151           glDepthMask(GL_FALSE);
1152           glEnable(GL_DEPTH_TEST);
1153
1154           AWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1155
1156           // Render the view
1157           RenderStructs(AWorkspace);
1158           DisableTexture();
1159
1160           /* restauration des parametres OpenGL */
1161           glBlendFunc(blend_src, blend_dst);
1162           if (!blend_state) glDisable(GL_BLEND);
1163
1164           glDepthFunc(zbuff_f);
1165           glDepthMask(zbuff_w);
1166           if (!zbuff_state) glDisable(GL_DEPTH_FUNC);
1167         }
1168         break;
1169     }
1170
1171     if (isAnimationListOpen)
1172     {
1173       glEndList();
1174       myAnimationListReady = Standard_True;
1175     }
1176   }
1177
1178   /* restore previous graphics context; before update lights */
1179   //TsmPopAttri();
1180
1181   // Disable current clipping planes
1182   for ( planeid = GL_CLIP_PLANE0; planeid < lastid; planeid++ )
1183     glDisable( planeid );
1184
1185   /* affichage de Triedre Non Zoomable de la vue s'il existe */
1186   if (!myTrihedron.IsNull())
1187     myTrihedron->Render(AWorkspace);
1188   if (!myGraduatedTrihedron.IsNull())
1189     myGraduatedTrihedron->Render(AWorkspace);
1190
1191   // The applied aspects should be reset to make it possible to
1192   // update gl state and bring it into line with currently set
1193   // aspects by reapplying them. Reset should be done, because
1194   // the glPopAttrib() will return original gl state while the
1195   // internal TKOpenGl state stills unchanged.
1196   AWorkspace->ResetAppliedAspect();
1197   glPopAttrib(); // GL_FOG_BIT | GL_LIGHTING_BIT | GL_ENABLE_BIT
1198
1199   // Restore face culling
1200   if ( myBackfacing )
1201   {
1202     if ( isCullFace )
1203     {
1204       glEnable   ( GL_CULL_FACE );
1205       glCullFace ( GL_BACK      );
1206     }
1207     else
1208       glDisable ( GL_CULL_FACE );
1209   }
1210
1211   /////////////////////////////////////////////////////////////////////////////
1212   // Step 6: Draw overlayer
1213   const int aMode = 0;
1214   AWorkspace->DisplayCallback (ACView, (aMode | OCC_PRE_OVERLAY));
1215
1216   RedrawLayer2d(AWorkspace, ACView, ACOverLayer);
1217
1218   AWorkspace->DisplayCallback (ACView, aMode);
1219
1220   // Restore clipping planes
1221   for ( ptrPlane = oldPlanes, planeid = GL_CLIP_PLANE0; planeid < lastid; planeid++, ptrPlane++ )
1222   {
1223     glClipPlane( planeid, ptrPlane->Equation );
1224     if ( ptrPlane->isEnabled )
1225       glEnable( planeid );
1226     else
1227       glDisable( planeid );
1228   }
1229   delete[] oldPlanes;
1230 }
1231
1232 /*----------------------------------------------------------------------*/
1233
1234 //ExecuteViewDisplay
1235 void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace)
1236 {
1237   if ( myZLayers.NbStructures() <= 0 )
1238     return;
1239
1240   glPushAttrib ( GL_DEPTH_BUFFER_BIT );
1241
1242   const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine( Standard_True );
1243
1244   //TsmPushAttri(); /* save previous graphics context */
1245
1246   if ( (AWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
1247   {
1248     const int antiAliasingMode = AWorkspace->GetDisplay()->AntiAliasingMode();
1249
1250     if ( !myAntiAliasing )
1251     {
1252       glDisable(GL_POINT_SMOOTH);
1253       glDisable(GL_LINE_SMOOTH);
1254       if( antiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
1255       glBlendFunc (GL_ONE, GL_ZERO);
1256       glDisable (GL_BLEND);
1257     }
1258     else
1259     {
1260       glEnable(GL_POINT_SMOOTH);
1261       glEnable(GL_LINE_SMOOTH);
1262       if( antiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
1263       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
1264       glEnable (GL_BLEND);
1265     }
1266   }
1267
1268   myZLayers.Render (AWorkspace);
1269
1270   //TsmPopAttri(); /* restore previous graphics context; before update lights */
1271
1272   if ( AWorkspace->DegenerateModel > 1 )
1273   {
1274     glLineWidth ( aspect_line->Width() );
1275     if ( aspect_line->Type() != Aspect_TOL_SOLID ) glEnable ( GL_LINE_STIPPLE );
1276   }
1277
1278   glPopAttrib ();
1279 }
1280
1281 /*----------------------------------------------------------------------*/
1282
1283 //call_togl_redraw_layer2d
1284 void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_Workspace) &AWorkspace, const Graphic3d_CView& ACView, const Aspect_CLayer2d& ACLayer)
1285 {
1286   if (&ACLayer == NULL
1287    || ACLayer.ptrLayer == NULL
1288    || ACLayer.ptrLayer->listIndex == 0) return;
1289
1290   GLsizei dispWidth  = (GLsizei )ACLayer.viewport[0];
1291   GLsizei dispHeight = (GLsizei )ACLayer.viewport[1];
1292
1293   const GLboolean isl = glIsEnabled(GL_LIGHTING); /*OCC6247*/
1294   if (isl)
1295     glDisable(GL_LIGHTING); /*OCC6247*/
1296
1297   /*
1298   * On positionne la projection
1299   */
1300   glMatrixMode( GL_MODELVIEW );
1301   glPushMatrix ();
1302   glLoadIdentity ();
1303
1304   glMatrixMode (GL_PROJECTION);
1305   glPushMatrix ();
1306   glLoadIdentity ();
1307
1308   if (!ACLayer.sizeDependent)
1309     glViewport (0, 0, dispWidth, dispHeight);
1310
1311   float left = ACLayer.ortho[0];
1312   float right = ACLayer.ortho[1];
1313   float bottom = ACLayer.ortho[2];
1314   float top = ACLayer.ortho[3];
1315
1316   int attach = ACLayer.attach;
1317
1318   float ratio;
1319   if (!ACLayer.sizeDependent)
1320     ratio = (float) dispWidth/dispHeight;
1321   else
1322     ratio = ACView.DefWindow.dx/ACView.DefWindow.dy;
1323
1324   float delta;
1325   if (ratio >= 1.0) { /* fenetre horizontale */
1326     delta = (float )((top - bottom)/2.0);
1327     switch (attach) {
1328       case 0: /* Aspect_TOC_BOTTOM_LEFT */
1329         top = bottom + 2*delta/ratio;
1330         break;
1331       case 1: /* Aspect_TOC_BOTTOM_RIGHT */
1332         top = bottom + 2*delta/ratio;
1333         break;
1334       case 2: /* Aspect_TOC_TOP_LEFT */
1335         bottom = top - 2*delta/ratio;
1336         break;
1337       case 3: /* Aspect_TOC_TOP_RIGHT */
1338         bottom = top - 2*delta/ratio;
1339         break;
1340     }
1341   }
1342   else { /* fenetre verticale */
1343     delta = (float )((right - left)/2.0);
1344     switch (attach) {
1345       case 0: /* Aspect_TOC_BOTTOM_LEFT */
1346         right = left + 2*delta*ratio;
1347         break;
1348       case 1: /* Aspect_TOC_BOTTOM_RIGHT */
1349         left = right - 2*delta*ratio;
1350         break;
1351       case 2: /* Aspect_TOC_TOP_LEFT */
1352         right = left + 2*delta*ratio;
1353         break;
1354       case 3: /* Aspect_TOC_TOP_RIGHT */
1355         left = right - 2*delta*ratio;
1356         break;
1357     }
1358   }
1359
1360 #ifdef WNT
1361   // Check printer context that exists only for print operation
1362   OpenGl_PrinterContext* aPrinterContext = OpenGl_PrinterContext::GetPrinterContext (AWorkspace->GetGContext());
1363
1364   if (aPrinterContext)
1365   {
1366     // additional transformation matrix could be applied to
1367     // render only those parts of viewport that will be
1368     // passed to a printer as a current "frame" to provide
1369     // tiling; scaling of graphics by matrix helps render a
1370     // part of a view (frame) in same viewport, but with higher
1371     // resolution
1372     GLfloat aProjMatrix[16];
1373     aPrinterContext->GetProjTransformation (aProjMatrix);
1374     glLoadMatrixf ((GLfloat*) aProjMatrix);
1375
1376     // printing operation also assumes other viewport dimension
1377     // to comply with transformation matrix or graphics scaling
1378     // factors for tiling for layer redraw
1379     GLsizei anViewportX = 0;
1380     GLsizei anViewportY = 0;
1381     aPrinterContext->GetLayerViewport (anViewportX, anViewportY);
1382     if (anViewportX != 0 && anViewportY != 0)
1383       glViewport (0, 0, anViewportX, anViewportY);
1384   }
1385 #endif 
1386
1387   glOrtho (left, right, bottom, top, -1.0, 1.0);
1388
1389   /*
1390   * On trace la display-list associee au layer.
1391   */
1392   glPushAttrib (
1393     GL_LIGHTING_BIT | GL_LINE_BIT | GL_POLYGON_BIT |
1394     GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT );
1395   glDisable (GL_DEPTH_TEST);
1396   glCallList (ACLayer.ptrLayer->listIndex);
1397
1398   //calling dynamic render of LayerItems
1399   if ( ACLayer.ptrLayer->layerData )
1400   {
1401     InitLayerProp(ACLayer.ptrLayer->listIndex);
1402     ((Visual3d_Layer*)ACLayer.ptrLayer->layerData)->RenderLayerItems();
1403     InitLayerProp(0);
1404   }
1405
1406   glPopAttrib ();
1407
1408   /*
1409   * On retire la projection
1410   */
1411   glMatrixMode (GL_PROJECTION);
1412   glPopMatrix ();
1413
1414   glMatrixMode( GL_MODELVIEW );
1415   glPopMatrix ();
1416
1417   /*
1418   * Restauration du Viewport en cas de modification
1419   */
1420   if (!ACLayer.sizeDependent)
1421     glViewport (0, 0, (GLsizei) ACView.DefWindow.dx, (GLsizei) ACView.DefWindow.dy);
1422
1423   glFlush ();
1424
1425   if (isl)
1426     glEnable(GL_LIGHTING); /*OCC6247*/
1427 }
1428
1429 /*----------------------------------------------------------------------*/
1430
1431 //call_togl_create_bg_texture
1432 void OpenGl_View::CreateBackgroundTexture (const Standard_CString AFileName, const Aspect_FillMethod AFillStyle)
1433 {
1434   // Delete existing texture
1435   if ( myBgTexture.TexId != 0 )
1436   {
1437     glDeleteTextures( 1, (GLuint*)&(myBgTexture.TexId) );
1438     myBgTexture.TexId = 0;
1439   }
1440
1441   Standard_Integer width, height;
1442   Handle(Image_Image) image;
1443   if ( AlienImage::LoadImageFile( AFileName, image, width, height ) )
1444   {
1445     const int nbbytes = width * height * 3;
1446     GLubyte *data = new GLubyte[nbbytes];
1447     GLubyte *pdata = data;
1448     Standard_Integer i, j;
1449     for ( j = height - 1; j >= 0; j-- )
1450       for ( i = 0; i < width; i++ )
1451       {
1452         const Quantity_Color &color = image->PixelColor( i, j );
1453         *pdata++ = (GLubyte)( 255 * color.Red() );
1454         *pdata++ = (GLubyte)( 255 * color.Green() );
1455         *pdata++ = (GLubyte)( 255 * color.Blue() );
1456       }
1457
1458     GLuint texture = 0;
1459     glGenTextures( 1, &texture );
1460     glBindTexture( GL_TEXTURE_2D, texture );
1461
1462     /* Create MipMapped Texture */
1463     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1464     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1465     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1466     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1467
1468     gluBuild2DMipmaps( GL_TEXTURE_2D, 3/*4*/, width, height, GL_RGB, GL_UNSIGNED_BYTE, data );
1469
1470     delete[] data;
1471
1472     myBgTexture.TexId = texture;
1473     myBgTexture.Width = width;
1474     myBgTexture.Height = height;
1475     myBgTexture.Style = AFillStyle;
1476   }
1477 }
1478
1479 /*----------------------------------------------------------------------*/
1480
1481 //call_togl_set_bg_texture_style
1482 void OpenGl_View::SetBackgroundTextureStyle (const Aspect_FillMethod AFillStyle)
1483 {
1484   myBgTexture.Style = AFillStyle;
1485 }
1486
1487 /*----------------------------------------------------------------------*/
1488
1489 //call_togl_gradient_background
1490 void OpenGl_View::SetBackgroundGradient (const Quantity_Color& AColor1,
1491                                         const Quantity_Color& AColor2,
1492                                         const Aspect_GradientFillMethod AType)
1493 {
1494   Standard_Real R,G,B;
1495   AColor1.Values( R, G, B, Quantity_TOC_RGB );
1496   myBgGradient.color1.rgb[0] = ( Tfloat )R;
1497   myBgGradient.color1.rgb[1] = ( Tfloat )G;
1498   myBgGradient.color1.rgb[2] = ( Tfloat )B;
1499   myBgGradient.color1.rgb[3] = 0.F;
1500
1501   AColor2.Values( R, G, B, Quantity_TOC_RGB );
1502   myBgGradient.color2.rgb[0] = ( Tfloat )R;
1503   myBgGradient.color2.rgb[1] = ( Tfloat )G;
1504   myBgGradient.color2.rgb[2] = ( Tfloat )B;
1505   myBgGradient.color2.rgb[3] = 0.F;
1506
1507   myBgGradient.type = AType;
1508 }
1509
1510 /*----------------------------------------------------------------------*/
1511
1512 //call_togl_set_gradient_type
1513 void OpenGl_View::SetBackgroundGradientType (const Aspect_GradientFillMethod AType)
1514 {
1515   myBgGradient.type = AType;
1516 }
1517
1518 //=======================================================================
1519 //function : AddZLayer
1520 //purpose  : 
1521 //=======================================================================
1522
1523 void OpenGl_View::AddZLayer (const Standard_Integer theLayerId)
1524 {
1525   myZLayers.AddLayer (theLayerId);
1526 }
1527
1528 //=======================================================================
1529 //function : RemoveZLayer
1530 //purpose  : 
1531 //=======================================================================
1532
1533 void OpenGl_View::RemoveZLayer (const Standard_Integer theLayerId)
1534 {
1535   myZLayers.RemoveLayer (theLayerId);
1536 }
1537
1538 //=======================================================================
1539 //function : DisplayStructure
1540 //purpose  : 
1541 //=======================================================================
1542
1543 void OpenGl_View::DisplayStructure (const OpenGl_Structure *theStructure,
1544                                     const Standard_Integer  thePriority)
1545 {
1546   Standard_Integer aZLayer = theStructure->GetZLayer ();
1547   myZLayers.AddStructure (theStructure, aZLayer, thePriority);
1548 }
1549
1550 //=======================================================================
1551 //function : EraseStructure
1552 //purpose  : 
1553 //=======================================================================
1554
1555 void OpenGl_View::EraseStructure (const OpenGl_Structure *theStructure)
1556 {
1557   Standard_Integer aZLayer = theStructure->GetZLayer ();
1558   myZLayers.RemoveStructure (theStructure, aZLayer);
1559 }
1560
1561 //=======================================================================
1562 //function : ChangeZLayer
1563 //purpose  :
1564 //=======================================================================
1565
1566 void OpenGl_View::ChangeZLayer (const OpenGl_Structure *theStructure,
1567                                 const Standard_Integer  theNewLayerId)
1568 {
1569   Standard_Integer anOldLayer = theStructure->GetZLayer ();
1570   myZLayers.ChangeLayer (theStructure, anOldLayer, theNewLayerId);
1571 }