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