0024250: TKOpenGl - per-pixel lighting using GLSL program (Phong shading)
[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 void OpenGl_View::DrawBackground (const Handle(OpenGl_Workspace) &AWorkspace)
640 {
641   /////////////////////////////////////////////////////////////////////////////
642   // Step 1: Prepare for redraw
643
644   // Render background
645   if ( (AWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) == 0 &&
646     ( myBgTexture.TexId != 0 || myBgGradient.type != Aspect_GFM_NONE ) )
647   {
648     const Standard_Integer aViewWidth = AWorkspace->Width();
649     const Standard_Integer aViewHeight = AWorkspace->Height();
650
651     glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
652
653     glMatrixMode( GL_PROJECTION );
654     glPushMatrix();
655     glLoadIdentity();
656     glMatrixMode( GL_MODELVIEW );
657     glPushMatrix();
658     glLoadIdentity();
659
660     if ( glIsEnabled( GL_DEPTH_TEST ) )
661       glDisable( GL_DEPTH_TEST ); //push GL_ENABLE_BIT
662
663     // drawing bg gradient if:
664     // - gradient fill type is not Aspect_GFM_NONE and
665     // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode
666     if ( ( myBgGradient.type != Aspect_GFM_NONE ) &&
667       ( myBgTexture.TexId == 0 || myBgTexture.Style == Aspect_FM_CENTERED ||
668       myBgTexture.Style == Aspect_FM_NONE ) )
669     {
670       Tfloat* corner1 = 0;/* -1,-1*/
671       Tfloat* corner2 = 0;/*  1,-1*/
672       Tfloat* corner3 = 0;/*  1, 1*/
673       Tfloat* corner4 = 0;/* -1, 1*/
674       Tfloat dcorner1[3];
675       Tfloat dcorner2[3];
676
677       switch( myBgGradient.type )
678       {
679       case Aspect_GFM_HOR:
680         corner1 = myBgGradient.color1.rgb;
681         corner2 = myBgGradient.color2.rgb;
682         corner3 = myBgGradient.color2.rgb;
683         corner4 = myBgGradient.color1.rgb;
684         break;
685       case Aspect_GFM_VER:
686         corner1 = myBgGradient.color2.rgb;
687         corner2 = myBgGradient.color2.rgb;
688         corner3 = myBgGradient.color1.rgb;
689         corner4 = myBgGradient.color1.rgb;
690         break;
691       case Aspect_GFM_DIAG1:
692         corner2 = myBgGradient.color2.rgb;
693         corner4 = myBgGradient.color1.rgb;
694         dcorner1 [0] = dcorner2[0] = 0.5F * (corner2[0] + corner4[0]);
695         dcorner1 [1] = dcorner2[1] = 0.5F * (corner2[1] + corner4[1]);
696         dcorner1 [2] = dcorner2[2] = 0.5F * (corner2[2] + corner4[2]);
697         corner1 = dcorner1;
698         corner3 = dcorner2;
699         break;
700       case Aspect_GFM_DIAG2:
701         corner1 = myBgGradient.color2.rgb;
702         corner3 = myBgGradient.color1.rgb;
703         dcorner1 [0] = dcorner2[0] = 0.5F * (corner1[0] + corner3[0]);
704         dcorner1 [1] = dcorner2[1] = 0.5F * (corner1[1] + corner3[1]);
705         dcorner1 [2] = dcorner2[2] = 0.5F * (corner1[2] + corner3[2]);
706         corner2 = dcorner1;
707         corner4 = dcorner2;
708         break;
709       case Aspect_GFM_CORNER1:
710         corner1 = myBgGradient.color2.rgb;
711         corner2 = myBgGradient.color2.rgb;
712         corner3 = myBgGradient.color2.rgb;
713         corner4 = myBgGradient.color1.rgb;
714         break;
715       case Aspect_GFM_CORNER2:
716         corner1 = myBgGradient.color2.rgb;
717         corner2 = myBgGradient.color2.rgb;
718         corner3 = myBgGradient.color1.rgb;
719         corner4 = myBgGradient.color2.rgb;
720         break;
721       case Aspect_GFM_CORNER3:
722         corner1 = myBgGradient.color2.rgb;
723         corner2 = myBgGradient.color1.rgb;
724         corner3 = myBgGradient.color2.rgb;
725         corner4 = myBgGradient.color2.rgb;
726         break;
727       case Aspect_GFM_CORNER4:
728         corner1 = myBgGradient.color1.rgb;
729         corner2 = myBgGradient.color2.rgb;
730         corner3 = myBgGradient.color2.rgb;
731         corner4 = myBgGradient.color2.rgb;
732         break;
733       default:
734         //printf("gradient background type not right\n");
735         break;
736       }
737
738       // Save GL parameters
739       glDisable( GL_LIGHTING ); //push GL_ENABLE_BIT
740
741       GLint curSM;
742       glGetIntegerv( GL_SHADE_MODEL, &curSM );
743       if ( curSM != GL_SMOOTH )
744         glShadeModel( GL_SMOOTH ); //push GL_LIGHTING_BIT
745
746       glBegin(GL_TRIANGLE_FAN);
747       if( myBgGradient.type != Aspect_GFM_CORNER1 && myBgGradient.type != Aspect_GFM_CORNER3 )
748       {
749         glColor3f(corner1[0],corner1[1],corner1[2]); glVertex2f(-1.,-1.);
750         glColor3f(corner2[0],corner2[1],corner2[2]); glVertex2f( 1.,-1.);
751         glColor3f(corner3[0],corner3[1],corner3[2]); glVertex2f( 1., 1.);
752         glColor3f(corner4[0],corner4[1],corner4[2]); glVertex2f(-1., 1.);
753       }
754       else //if ( myBgGradient.type == Aspect_GFM_CORNER1 || myBgGradient.type == Aspect_GFM_CORNER3 )
755       {
756         glColor3f(corner2[0],corner2[1],corner2[2]); glVertex2f( 1.,-1.);
757         glColor3f(corner3[0],corner3[1],corner3[2]); glVertex2f( 1., 1.);
758         glColor3f(corner4[0],corner4[1],corner4[2]); glVertex2f(-1., 1.);
759         glColor3f(corner1[0],corner1[1],corner1[2]); glVertex2f(-1.,-1.);
760       }
761       glEnd();
762
763       // Restore GL parameters
764       if ( curSM != GL_SMOOTH )
765         glShadeModel( curSM );
766     }
767     // drawing bg image if:
768     // - it is defined and
769     // - fill type is not Aspect_FM_NONE
770     if ( myBgTexture.TexId != 0 && myBgTexture.Style != Aspect_FM_NONE )
771     {
772       GLfloat texX_range = 1.F; // texture <s> coordinate
773       GLfloat texY_range = 1.F; // texture <t> coordinate
774
775       // Set up for stretching or tiling
776       GLfloat x_offset, y_offset;
777       if ( myBgTexture.Style == Aspect_FM_CENTERED )
778       {
779         x_offset = (GLfloat)myBgTexture.Width / (GLfloat)aViewWidth;
780         y_offset = (GLfloat)myBgTexture.Height / (GLfloat)aViewHeight;
781       }
782       else
783       {
784         x_offset = 1.F;
785         y_offset = 1.F;
786         if ( myBgTexture.Style == Aspect_FM_TILED )
787         {
788           texX_range = (GLfloat)aViewWidth / (GLfloat)myBgTexture.Width;
789           texY_range = (GLfloat)aViewHeight / (GLfloat)myBgTexture.Height;
790         }
791       }
792
793       // OCCT issue 0023000: Improve the way the gradient and textured
794       // background is managed in 3d viewer (note 0020339)
795       // Setting this coefficient to -1.F allows to tile textures relatively
796       // to the top-left corner of the view (value 1.F corresponds to the
797       // initial behaviour - tiling from the bottom-left corner)
798       GLfloat aCoef = -1.F;
799
800       glEnable( GL_TEXTURE_2D ); //push GL_ENABLE_BIT
801       glBindTexture( GL_TEXTURE_2D, myBgTexture.TexId ); //push GL_TEXTURE_BIT
802
803       glDisable( GL_BLEND ); //push GL_ENABLE_BIT
804
805       glColor3fv( AWorkspace->BackgroundColor().rgb );
806       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); //push GL_TEXTURE_BIT
807
808       // Note that texture is mapped using GL_REPEAT wrapping mode so integer part
809       // is simply ignored, and negative multiplier is here for convenience only
810       // and does not result e.g. in texture mirroring
811       glBegin( GL_QUADS );
812       glTexCoord2f(0.F, 0.F); glVertex2f( -x_offset, -aCoef * y_offset );
813       glTexCoord2f(texX_range, 0.F); glVertex2f( x_offset, -aCoef * y_offset );
814       glTexCoord2f(texX_range, aCoef * texY_range); glVertex2f( x_offset, aCoef * y_offset );
815       glTexCoord2f(0.F, aCoef * texY_range); glVertex2f( -x_offset, aCoef * y_offset );
816       glEnd();
817     }
818
819     glPopMatrix();
820     glMatrixMode( GL_PROJECTION );
821     glPopMatrix();
822     glMatrixMode( GL_MODELVIEW );
823
824     glPopAttrib(); //GL_ENABLE_BIT | GL_TEXTURE_BIT
825
826     if ( AWorkspace->UseZBuffer() )
827       glEnable( GL_DEPTH_TEST );
828
829     /* GL_DITHER on/off pour le trace */
830     if (AWorkspace->Dither())
831       glEnable (GL_DITHER);
832     else
833       glDisable (GL_DITHER);
834   }
835 }
836
837 /*----------------------------------------------------------------------*/
838
839 //call_func_redraw_all_structs_proc
840 void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
841                           const Handle(OpenGl_Workspace) &AWorkspace,
842                           const Graphic3d_CView& ACView,
843                           const Aspect_CLayer2d& ACUnderLayer,
844                           const Aspect_CLayer2d& ACOverLayer)
845 {
846   // Store and disable current clipping planes
847   const Handle(OpenGl_Context)& aContext = AWorkspace->GetGlContext();
848   const Standard_Integer aMaxClipPlanes = aContext->MaxClipPlanes();
849   const GLenum lastid = GL_CLIP_PLANE0 + aMaxClipPlanes;
850   OPENGL_CLIP_PLANE *oldPlanes = new OPENGL_CLIP_PLANE[aMaxClipPlanes];
851   OPENGL_CLIP_PLANE *ptrPlane = oldPlanes;
852   GLenum planeid = GL_CLIP_PLANE0;
853   for ( ; planeid < lastid; planeid++, ptrPlane++ )
854   {
855     glGetClipPlane( planeid, ptrPlane->Equation );
856     if ( ptrPlane->isEnabled )
857     {
858       glDisable( planeid );
859       ptrPlane->isEnabled = GL_TRUE;
860     }
861     else
862     {
863       ptrPlane->isEnabled = GL_FALSE;
864     }
865   }
866
867   // Set OCCT state uniform variables
868   const Handle(OpenGl_ShaderManager) aManager = aContext->ShaderManager();
869   if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
870   {
871     aManager->UpdateLightSourceStateTo (&myLights);
872     myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
873   }
874   if (StateInfo (myCurrViewMappingState, aManager->ProjectionState().Index()) != myLastViewMappingState)
875   {
876     aManager->UpdateProjectionStateTo (myMappingMatrix);
877     myLastViewMappingState = StateInfo (myCurrViewMappingState, aManager->ProjectionState().Index());
878   }
879   if (StateInfo (myCurrOrientationState, aManager->WorldViewState().Index()) != myLastOrientationState)
880   {
881     aManager->UpdateWorldViewStateTo (myOrientationMatrix);
882     myLastOrientationState = StateInfo (myCurrOrientationState, aManager->WorldViewState().Index());
883   }
884   if (aManager->ModelWorldState().Index() == 0)
885   {
886     Tmatrix3 aModelWorldState = { { 1.f, 0.f, 0.f, 0.f },
887                                   { 0.f, 1.f, 0.f, 0.f },
888                                   { 0.f, 0.f, 1.f, 0.f },
889                                   { 0.f, 0.f, 0.f, 1.f } };
890     
891     aManager->UpdateModelWorldStateTo (aModelWorldState);
892   }
893
894   /////////////////////////////////////////////////////////////////////////////
895   // Step 1: Prepare for redraw
896
897   // Render background
898   DrawBackground (AWorkspace);
899
900   // Switch off lighting by default
901   glDisable(GL_LIGHTING);
902
903   /////////////////////////////////////////////////////////////////////////////
904   // Step 2: Draw underlayer
905   RedrawLayer2d (thePrintContext, ACView, ACUnderLayer);
906
907   /////////////////////////////////////////////////////////////////////////////
908   // Step 3: Redraw main plane
909
910   // Setup face culling
911   GLboolean isCullFace = GL_FALSE;
912   if ( myBackfacing )
913   {
914     isCullFace = glIsEnabled( GL_CULL_FACE );
915     if ( myBackfacing < 0 )
916     {
917       glEnable( GL_CULL_FACE );
918       glCullFace( GL_BACK );
919     }
920         else
921       glDisable( GL_CULL_FACE );
922   }
923
924   //TsmPushAttri(); /* save previous graphics context */
925
926   // if the view is scaled normal vectors are scaled to unit length for correct displaying of shaded objects
927   if(myExtra.scaleFactors[0] != 1.F ||
928      myExtra.scaleFactors[1] != 1.F ||
929      myExtra.scaleFactors[2] != 1.F)
930     glEnable(GL_NORMALIZE);
931   else if(glIsEnabled(GL_NORMALIZE))
932     glDisable(GL_NORMALIZE);
933
934   // Apply View Projection
935   // This routine activates the Projection matrix for a view.
936
937   glMatrixMode( GL_PROJECTION );
938
939 #ifdef _WIN32
940   // add printing scale/tiling transformation
941   if (!thePrintContext.IsNull())
942   {
943     thePrintContext->LoadProjTransformation();
944   }
945   else
946 #endif
947     glLoadIdentity();
948
949   glMultMatrixf( (const GLfloat *) myMappingMatrix );
950
951   // Add translation necessary for the environnement mapping
952   if (mySurfaceDetail != Visual3d_TOD_NONE)
953   {
954     // OCC280: FitAll work incorrect for perspective view if the SurfaceDetail mode is V3d_TEX_ENVIRONMENT or V3d_TEX_ALL
955     // const GLfloat dep = vptr->vrep.extra.map.fpd * 0.5F;
956     const GLfloat dep = (myExtra.map.fpd + myExtra.map.bpd) * 0.5F;
957     glTranslatef(-dep*myExtra.vpn[0],-dep*myExtra.vpn[1],-dep*myExtra.vpn[2]);
958   }
959
960   // Apply matrix
961   AWorkspace->SetViewMatrix((const OpenGl_Matrix *)myOrientationMatrix);
962
963 /*
964 While drawing after a clipplane has been defined and enabled, each vertex
965 is transformed to eye-coordinates, where it is dotted with the transformed
966 clipping plane equation.  Eye-coordinate vertexes whose dot product with
967 the transformed clipping plane equation is positive or zero are in, and
968 require no clipping.  Those eye-coordinate vertexes whose dot product is
969 negative are clipped.  Because clipplane clipping is done in eye-
970 coordinates, changes to the projection matrix have no effect on its
971 operation.
972
973 A point and a normal are converted to a plane equation in the following manner:
974
975 point = [Px,Py,Pz]
976
977 normal = |Nx|
978 |Ny|
979 |Nz|
980
981 plane equation = |A|
982 |B|
983 |C|
984 |D|
985 A = Nx
986 B = Ny
987 C = Nz
988 D = -[Px,Py,Pz] dot |Nx|
989 |Ny|
990 |Nz|
991
992 */
993
994   // Apply Fog
995   if ( myFog.IsOn )
996   {
997     const GLfloat ramp = myExtra.map.fpd - myExtra.map.bpd;
998     const GLfloat fog_start = myFog.Front * ramp - myExtra.map.fpd;
999     const GLfloat fog_end   = myFog.Back  * ramp - myExtra.map.fpd;
1000
1001     glFogi(GL_FOG_MODE, GL_LINEAR);
1002     glFogf(GL_FOG_START, fog_start);
1003     glFogf(GL_FOG_END, fog_end);
1004     glFogfv(GL_FOG_COLOR, myFog.Color.rgb);
1005     glEnable(GL_FOG);
1006   }
1007   else
1008     glDisable(GL_FOG);
1009
1010   // Apply Lights
1011   {
1012     int i;
1013
1014     // Switch off all lights
1015     for (i = GL_LIGHT0; i <= GL_LIGHT7; i++)
1016       glDisable(i);
1017     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, default_amb);
1018
1019     /* set les lights */
1020     int gl_lid = GL_LIGHT0;
1021     OpenGl_ListOfLight::Iterator itl(myLights);
1022     for (; itl.More(); itl.Next())
1023     {
1024       const OpenGl_Light &alight = itl.Value();
1025       bind_light(&alight, &gl_lid);
1026     }
1027
1028     if (gl_lid != GL_LIGHT0) glEnable(GL_LIGHTING);
1029   }
1030
1031   // Apply InteriorShadingMethod
1032   glShadeModel( myIntShadingMethod == TEL_SM_FLAT ? GL_FLAT : GL_SMOOTH );
1033
1034   // Apply clipping planes
1035   {
1036     if (myZClip.Back.IsOn || myZClip.Front.IsOn)
1037     {
1038       const GLdouble ramp = myExtra.map.fpd - myExtra.map.bpd;
1039
1040       Handle(Graphic3d_ClipPlane) aPlaneBack;
1041       Handle(Graphic3d_ClipPlane) aPlaneFront;
1042
1043       if (myZClip.Back.IsOn)
1044       {
1045         const GLdouble back = ramp * myZClip.Back.Limit + myExtra.map.bpd;
1046         const Graphic3d_ClipPlane::Equation aBackEquation (0.0, 0.0, 1.0, -back);
1047         aPlaneBack = new Graphic3d_ClipPlane (aBackEquation);
1048       }
1049
1050       if (myZClip.Front.IsOn)
1051       {
1052         const GLdouble front = ramp * myZClip.Front.Limit + myExtra.map.bpd;
1053         const Graphic3d_ClipPlane::Equation aFrontEquation (0.0, 0.0, -1.0, front);
1054         aPlaneFront = new Graphic3d_ClipPlane (aFrontEquation);
1055       }
1056
1057       // do some "memory allocation"-wise optimization
1058       if (!aPlaneBack.IsNull() || !aPlaneFront.IsNull())
1059       {
1060         Graphic3d_SetOfHClipPlane aSlicingPlanes;
1061         if (!aPlaneBack.IsNull())
1062         {
1063           aSlicingPlanes.Add (aPlaneBack);
1064         }
1065
1066         if (!aPlaneFront.IsNull())
1067         {
1068           aSlicingPlanes.Add (aPlaneFront);
1069         }
1070
1071         // add planes at loaded view matrix state
1072         aContext->ChangeClipping().AddView (aSlicingPlanes, AWorkspace);
1073       }
1074     }
1075
1076     // Apply user clipping planes
1077     if (!myClipPlanes.IsEmpty())
1078     {
1079       Graphic3d_SetOfHClipPlane aUserPlanes;
1080       Graphic3d_SetOfHClipPlane::Iterator aClippingIt (myClipPlanes);
1081       for (; aClippingIt.More(); aClippingIt.Next())
1082       {
1083         const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
1084         if (aClipPlane->IsOn())
1085         {
1086           aUserPlanes.Add (aClipPlane);
1087         }
1088       }
1089
1090       if (!aUserPlanes.IsEmpty())
1091       {
1092         // add planes at actual matrix state.
1093         aContext->ChangeClipping().AddWorld (aUserPlanes);
1094       }
1095     }
1096     
1097     if (!aManager->IsEmpty())
1098     {
1099       aManager->UpdateClippingState();
1100     }
1101   }
1102
1103   // Apply AntiAliasing
1104   {
1105     if (myAntiAliasing)
1106       AWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING;
1107         else
1108       AWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING;
1109   }
1110
1111   // Clear status bitfields
1112   AWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
1113
1114   // Added PCT for handling of textures
1115   switch (mySurfaceDetail)
1116   {
1117     case Visual3d_TOD_NONE:
1118       AWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1119       AWorkspace->DisableTexture();
1120       // Render the view
1121       RenderStructs(AWorkspace);
1122       break;
1123
1124     case Visual3d_TOD_ENVIRONMENT:
1125       AWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1126       AWorkspace->EnableTexture (myTextureEnv);
1127       // Render the view
1128       RenderStructs(AWorkspace);
1129       AWorkspace->DisableTexture();
1130       break;
1131
1132     case Visual3d_TOD_ALL:
1133       // First pass
1134       AWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX;
1135       // Render the view
1136       RenderStructs(AWorkspace);
1137       AWorkspace->DisableTexture();
1138
1139       // Second pass
1140       if (AWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
1141       {
1142         AWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
1143         AWorkspace->EnableTexture (myTextureEnv);
1144
1145         /* sauvegarde de quelques parametres OpenGL */
1146         GLint blend_dst, blend_src;
1147         GLint zbuff_f;
1148         GLboolean zbuff_w;
1149         glGetBooleanv(GL_DEPTH_WRITEMASK, &zbuff_w);
1150         glGetIntegerv(GL_DEPTH_FUNC, &zbuff_f);
1151         glGetIntegerv(GL_BLEND_DST, &blend_dst);
1152         glGetIntegerv(GL_BLEND_SRC, &blend_src);
1153         GLboolean zbuff_state = glIsEnabled(GL_DEPTH_TEST);
1154         GLboolean blend_state = glIsEnabled(GL_BLEND);
1155
1156         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1157         glEnable(GL_BLEND);
1158
1159         glDepthFunc(GL_EQUAL);
1160         glDepthMask(GL_FALSE);
1161         glEnable(GL_DEPTH_TEST);
1162
1163         AWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1164
1165         // Render the view
1166         RenderStructs(AWorkspace);
1167         AWorkspace->DisableTexture();
1168
1169         /* restauration des parametres OpenGL */
1170         glBlendFunc(blend_src, blend_dst);
1171         if (!blend_state) glDisable(GL_BLEND);
1172
1173         glDepthFunc(zbuff_f);
1174         glDepthMask(zbuff_w);
1175         if (!zbuff_state) glDisable(GL_DEPTH_FUNC);
1176       }
1177       break;
1178   }
1179
1180   // Resetting GL parameters according to the default aspects
1181   // in order to synchronize GL state with the graphic driver state
1182   // before drawing auxiliary stuff (trihedrons, overlayer)
1183   // and invoking optional callbacks
1184   AWorkspace->ResetAppliedAspect();
1185
1186   aContext->ChangeClipping().RemoveAll();
1187
1188   if (!aManager->IsEmpty())
1189   {
1190     aManager->ResetMaterialStates();
1191     aManager->RevertClippingState();
1192
1193     // We need to disable (unbind) all shaders programs to ensure
1194     // that all objects without specified aspect will be drawn
1195     // correctly (such as background)
1196     OpenGl_ShaderProgram::Unbind (aContext);
1197   }
1198
1199   // display global trihedron
1200   if (myTrihedron != NULL)
1201   {
1202     myTrihedron->Render (AWorkspace);
1203   }
1204   if (myGraduatedTrihedron != NULL)
1205   {
1206     myGraduatedTrihedron->Render (AWorkspace);
1207   }
1208
1209   // Restore face culling
1210   if ( myBackfacing )
1211   {
1212     if ( isCullFace )
1213     {
1214       glEnable   ( GL_CULL_FACE );
1215       glCullFace ( GL_BACK      );
1216     }
1217     else
1218       glDisable ( GL_CULL_FACE );
1219   }
1220
1221   /////////////////////////////////////////////////////////////////////////////
1222   // Step 6: Draw overlayer
1223   const int aMode = 0;
1224   AWorkspace->DisplayCallback (ACView, (aMode | OCC_PRE_OVERLAY));
1225
1226   RedrawLayer2d (thePrintContext, ACView, ACOverLayer);
1227
1228   AWorkspace->DisplayCallback (ACView, aMode);
1229
1230   // Restore clipping planes
1231   for ( ptrPlane = oldPlanes, planeid = GL_CLIP_PLANE0; planeid < lastid; planeid++, ptrPlane++ )
1232   {
1233     glClipPlane( planeid, ptrPlane->Equation );
1234     if ( ptrPlane->isEnabled )
1235       glEnable( planeid );
1236     else
1237       glDisable( planeid );
1238   }
1239   delete[] oldPlanes;
1240 }
1241
1242 /*----------------------------------------------------------------------*/
1243
1244 //ExecuteViewDisplay
1245 void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace)
1246 {
1247   if ( myZLayers.NbStructures() <= 0 )
1248     return;
1249
1250   glPushAttrib ( GL_DEPTH_BUFFER_BIT );
1251
1252   //TsmPushAttri(); /* save previous graphics context */
1253
1254   if ( (AWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
1255   {
1256     const int antiAliasingMode = AWorkspace->GetDisplay()->AntiAliasingMode();
1257
1258     if ( !myAntiAliasing )
1259     {
1260       glDisable(GL_POINT_SMOOTH);
1261       glDisable(GL_LINE_SMOOTH);
1262       if( antiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
1263       glBlendFunc (GL_ONE, GL_ZERO);
1264       glDisable (GL_BLEND);
1265     }
1266     else
1267     {
1268       glEnable(GL_POINT_SMOOTH);
1269       glEnable(GL_LINE_SMOOTH);
1270       if( antiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
1271       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1272       glEnable (GL_BLEND);
1273     }
1274   }
1275
1276   myZLayers.Render (AWorkspace);
1277
1278   //TsmPopAttri(); /* restore previous graphics context; before update lights */
1279   glPopAttrib();
1280 }
1281
1282 /*----------------------------------------------------------------------*/
1283
1284 //call_togl_redraw_layer2d
1285 void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintContext,
1286                                  const Graphic3d_CView&               ACView,
1287                                  const Aspect_CLayer2d&               ACLayer)
1288 {
1289   if (&ACLayer == NULL
1290    || ACLayer.ptrLayer == NULL
1291    || ACLayer.ptrLayer->listIndex == 0) return;
1292
1293   GLsizei dispWidth  = (GLsizei )ACLayer.viewport[0];
1294   GLsizei dispHeight = (GLsizei )ACLayer.viewport[1];
1295
1296   glMatrixMode( GL_MODELVIEW );
1297   glPushMatrix ();
1298   glLoadIdentity ();
1299
1300   glMatrixMode (GL_PROJECTION);
1301   glPushMatrix ();
1302   glLoadIdentity ();
1303
1304   if (!ACLayer.sizeDependent)
1305     glViewport (0, 0, dispWidth, dispHeight);
1306
1307   float left = ACLayer.ortho[0];
1308   float right = ACLayer.ortho[1];
1309   float bottom = ACLayer.ortho[2];
1310   float top = ACLayer.ortho[3];
1311
1312   int attach = ACLayer.attach;
1313
1314   float ratio;
1315   if (!ACLayer.sizeDependent)
1316     ratio = (float) dispWidth/dispHeight;
1317   else
1318     ratio = ACView.DefWindow.dx/ACView.DefWindow.dy;
1319
1320   float delta;
1321   if (ratio >= 1.0) {
1322     delta = (float )((top - bottom)/2.0);
1323     switch (attach) {
1324       case 0: /* Aspect_TOC_BOTTOM_LEFT */
1325         top = bottom + 2*delta/ratio;
1326         break;
1327       case 1: /* Aspect_TOC_BOTTOM_RIGHT */
1328         top = bottom + 2*delta/ratio;
1329         break;
1330       case 2: /* Aspect_TOC_TOP_LEFT */
1331         bottom = top - 2*delta/ratio;
1332         break;
1333       case 3: /* Aspect_TOC_TOP_RIGHT */
1334         bottom = top - 2*delta/ratio;
1335         break;
1336     }
1337   }
1338   else {
1339     delta = (float )((right - left)/2.0);
1340     switch (attach) {
1341       case 0: /* Aspect_TOC_BOTTOM_LEFT */
1342         right = left + 2*delta*ratio;
1343         break;
1344       case 1: /* Aspect_TOC_BOTTOM_RIGHT */
1345         left = right - 2*delta*ratio;
1346         break;
1347       case 2: /* Aspect_TOC_TOP_LEFT */
1348         right = left + 2*delta*ratio;
1349         break;
1350       case 3: /* Aspect_TOC_TOP_RIGHT */
1351         left = right - 2*delta*ratio;
1352         break;
1353     }
1354   }
1355
1356 #ifdef _WIN32
1357   // Check printer context that exists only for print operation
1358   if (!thePrintContext.IsNull())
1359   {
1360     // additional transformation matrix could be applied to
1361     // render only those parts of viewport that will be
1362     // passed to a printer as a current "frame" to provide
1363     // tiling; scaling of graphics by matrix helps render a
1364     // part of a view (frame) in same viewport, but with higher
1365     // resolution
1366     thePrintContext->LoadProjTransformation();
1367
1368     // printing operation also assumes other viewport dimension
1369     // to comply with transformation matrix or graphics scaling
1370     // factors for tiling for layer redraw
1371     GLsizei anViewportX = 0;
1372     GLsizei anViewportY = 0;
1373     thePrintContext->GetLayerViewport (anViewportX, anViewportY);
1374     if (anViewportX != 0 && anViewportY != 0)
1375       glViewport (0, 0, anViewportX, anViewportY);
1376   }
1377 #endif
1378
1379   glOrtho (left, right, bottom, top, -1.0, 1.0);
1380
1381   glPushAttrib (
1382     GL_LIGHTING_BIT | GL_LINE_BIT | GL_POLYGON_BIT |
1383     GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT );
1384
1385   glDisable (GL_DEPTH_TEST);
1386   glDisable (GL_TEXTURE_1D);
1387   glDisable (GL_TEXTURE_2D);
1388   glDisable (GL_LIGHTING);
1389
1390   // TODO: Obsolete code, the display list is always empty now, to be removed
1391   glCallList (ACLayer.ptrLayer->listIndex);
1392
1393   //calling dynamic render of LayerItems
1394   if ( ACLayer.ptrLayer->layerData )
1395   {
1396     InitLayerProp (ACLayer.ptrLayer->listIndex);
1397     ((Visual3d_Layer*)ACLayer.ptrLayer->layerData)->RenderLayerItems();
1398     InitLayerProp (0);
1399   }
1400
1401   glPopAttrib ();
1402
1403   glMatrixMode (GL_PROJECTION);
1404   glPopMatrix ();
1405
1406   glMatrixMode( GL_MODELVIEW );
1407   glPopMatrix ();
1408
1409   if (!ACLayer.sizeDependent)
1410     glViewport (0, 0, (GLsizei) ACView.DefWindow.dx, (GLsizei) ACView.DefWindow.dy);
1411
1412   glFlush ();
1413 }
1414
1415 /*----------------------------------------------------------------------*/
1416
1417 //call_togl_create_bg_texture
1418 void OpenGl_View::CreateBackgroundTexture (const Standard_CString  theFilePath,
1419                                            const Aspect_FillMethod theFillStyle)
1420 {
1421   if (myBgTexture.TexId != 0)
1422   {
1423     // delete existing texture
1424     glDeleteTextures (1, (GLuint* )&(myBgTexture.TexId));
1425     myBgTexture.TexId = 0;
1426   }
1427
1428   // load image from file
1429   Image_AlienPixMap anImageLoaded;
1430   if (!anImageLoaded.Load (theFilePath))
1431   {
1432     return;
1433   }
1434
1435   Image_PixMap anImage;
1436   if (anImageLoaded.RowExtraBytes() == 0 &&
1437       (anImageLoaded.Format() == Image_PixMap::ImgRGB
1438     || anImageLoaded.Format() == Image_PixMap::ImgRGB32
1439     || anImageLoaded.Format() == Image_PixMap::ImgRGBA))
1440   {
1441     anImage.InitWrapper (anImageLoaded.Format(), anImageLoaded.ChangeData(),
1442                          anImageLoaded.SizeX(), anImageLoaded.SizeY(), anImageLoaded.SizeRowBytes());
1443   }
1444   else
1445   {
1446     // convert image to RGB format
1447     if (!anImage.InitTrash (Image_PixMap::ImgRGB, anImageLoaded.SizeX(), anImageLoaded.SizeY()))
1448     {
1449       return;
1450     }
1451
1452     anImage.SetTopDown (false);
1453     Image_PixMapData<Image_ColorRGB>& aDataNew = anImage.EditData<Image_ColorRGB>();
1454     Quantity_Color aSrcColor;
1455     for (Standard_Size aRow = 0; aRow < anImage.SizeY(); ++aRow)
1456     {
1457       for (Standard_Size aCol = 0; aCol < anImage.SizeX(); ++aCol)
1458       {
1459         aSrcColor = anImageLoaded.PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow);
1460         Image_ColorRGB& aColor = aDataNew.ChangeValue (aRow, aCol);
1461         aColor.r() = Standard_Byte(255.0 * aSrcColor.Red());
1462         aColor.g() = Standard_Byte(255.0 * aSrcColor.Green());
1463         aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue());
1464       }
1465     }
1466     anImageLoaded.Clear();
1467   }
1468
1469   // create MipMapped texture
1470   glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
1471
1472   GLuint aTextureId = 0;
1473   glGenTextures (1, &aTextureId);
1474   glBindTexture (GL_TEXTURE_2D, aTextureId);
1475
1476   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_REPEAT);
1477   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_REPEAT);
1478   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1479   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1480
1481   const GLenum aDataFormat = (anImage.Format() == Image_PixMap::ImgRGB) ? GL_RGB : GL_RGBA;
1482   gluBuild2DMipmaps (GL_TEXTURE_2D, 3/*4*/,
1483                      GLint(anImage.SizeX()), GLint(anImage.SizeY()),
1484                      aDataFormat, GL_UNSIGNED_BYTE, anImage.Data());
1485
1486   myBgTexture.TexId  = aTextureId;
1487   myBgTexture.Width  = (Standard_Integer )anImage.SizeX();
1488   myBgTexture.Height = (Standard_Integer )anImage.SizeY();
1489   myBgTexture.Style  = theFillStyle;
1490 }
1491
1492 /*----------------------------------------------------------------------*/
1493
1494 //call_togl_set_bg_texture_style
1495 void OpenGl_View::SetBackgroundTextureStyle (const Aspect_FillMethod AFillStyle)
1496 {
1497   myBgTexture.Style = AFillStyle;
1498 }
1499
1500 /*----------------------------------------------------------------------*/
1501
1502 //call_togl_gradient_background
1503 void OpenGl_View::SetBackgroundGradient (const Quantity_Color& AColor1,
1504                                         const Quantity_Color& AColor2,
1505                                         const Aspect_GradientFillMethod AType)
1506 {
1507   Standard_Real R,G,B;
1508   AColor1.Values( R, G, B, Quantity_TOC_RGB );
1509   myBgGradient.color1.rgb[0] = ( Tfloat )R;
1510   myBgGradient.color1.rgb[1] = ( Tfloat )G;
1511   myBgGradient.color1.rgb[2] = ( Tfloat )B;
1512   myBgGradient.color1.rgb[3] = 0.F;
1513
1514   AColor2.Values( R, G, B, Quantity_TOC_RGB );
1515   myBgGradient.color2.rgb[0] = ( Tfloat )R;
1516   myBgGradient.color2.rgb[1] = ( Tfloat )G;
1517   myBgGradient.color2.rgb[2] = ( Tfloat )B;
1518   myBgGradient.color2.rgb[3] = 0.F;
1519
1520   myBgGradient.type = AType;
1521 }
1522
1523 /*----------------------------------------------------------------------*/
1524
1525 //call_togl_set_gradient_type
1526 void OpenGl_View::SetBackgroundGradientType (const Aspect_GradientFillMethod AType)
1527 {
1528   myBgGradient.type = AType;
1529 }
1530
1531 //=======================================================================
1532 //function : AddZLayer
1533 //purpose  :
1534 //=======================================================================
1535
1536 void OpenGl_View::AddZLayer (const Standard_Integer theLayerId)
1537 {
1538   myZLayers.AddLayer (theLayerId);
1539 }
1540
1541 //=======================================================================
1542 //function : RemoveZLayer
1543 //purpose  :
1544 //=======================================================================
1545
1546 void OpenGl_View::RemoveZLayer (const Standard_Integer theLayerId)
1547 {
1548   myZLayers.RemoveLayer (theLayerId);
1549 }
1550
1551 //=======================================================================
1552 //function : DisplayStructure
1553 //purpose  :
1554 //=======================================================================
1555
1556 void OpenGl_View::DisplayStructure (const OpenGl_Structure *theStructure,
1557                                     const Standard_Integer  thePriority)
1558 {
1559   Standard_Integer aZLayer = theStructure->GetZLayer ();
1560   myZLayers.AddStructure (theStructure, aZLayer, thePriority);
1561 }
1562
1563 //=======================================================================
1564 //function : EraseStructure
1565 //purpose  :
1566 //=======================================================================
1567
1568 void OpenGl_View::EraseStructure (const OpenGl_Structure *theStructure)
1569 {
1570   Standard_Integer aZLayer = theStructure->GetZLayer ();
1571   myZLayers.RemoveStructure (theStructure, aZLayer);
1572 }
1573
1574 //=======================================================================
1575 //function : ChangeZLayer
1576 //purpose  :
1577 //=======================================================================
1578
1579 void OpenGl_View::ChangeZLayer (const OpenGl_Structure *theStructure,
1580                                 const Standard_Integer  theNewLayerId)
1581 {
1582   Standard_Integer anOldLayer = theStructure->GetZLayer ();
1583   myZLayers.ChangeLayer (theStructure, anOldLayer, theNewLayerId);
1584 }