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