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