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