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