1 /*   EXTRAITS DE LA LICENCE
2 	Copyright CEA, contributeurs : Luc BILLARD et Damien
3 	CALISTE, laboratoire L_Sim, (2001-2005)
4 
5 	Adresse mèl :
6 	BILLARD, non joignable par mèl ;
7 	CALISTE, damien P caliste AT cea P fr.
8 
9 	Ce logiciel est un programme informatique servant à visualiser des
10 	structures atomiques dans un rendu pseudo-3D.
11 
12 	Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 	respectant les principes de diffusion des logiciels libres. Vous pouvez
14 	utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 	sur le site "http://www.cecill.info".
17 
18 	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 	pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22 
23 /*   LICENCE SUM UP
24 	Copyright CEA, contributors : Luc BILLARD et Damien
25 	CALISTE, laboratoire L_Sim, (2001-2005)
26 
27 	E-mail address:
28 	BILLARD, not reachable any more ;
29 	CALISTE, damien P caliste AT cea P fr.
30 
31 	This software is a computer program whose purpose is to visualize atomic
32 	configurations in 3D.
33 
34 	This software is governed by the CeCILL  license under French law and
35 	abiding by the rules of distribution of free software.  You can  use,
36 	modify and/ or redistribute the software under the terms of the CeCILL
37 	license as circulated by CEA, CNRS and INRIA at the following URL
38 	"http://www.cecill.info".
39 
40 	The fact that you are presently reading this means that you have had
41 	knowledge of the CeCILL license and that you accept its terms. You can
42 	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44 
45 #include <GL/gl.h>
46 #include <GL/glu.h>
47 
48 #include <math.h>
49 
50 #include <visu_tools.h>
51 #include <visu_configFile.h>
52 #include <visu_data.h>
53 #include <iface_animatable.h>
54 #include <coreTools/toolMatrix.h>
55 
56 
57 #include "view.h"
58 
59 /**
60  * SECTION:view
61  * @short_description: Defines all necessary informations for the
62  * rendering of a view.
63  *
64  * <para>The #VisuGlView stores two basic informations: one for the
65  * position and orientation of the camera (#VisuGlCamera) and one last for the
66  * definition of the viewing window (#VisuGlWindow, including volumic
67  * informations).</para>
68  *
69  * <para>One resource is used by this part, defining the precision
70  * desired by the user when drawing OpenGL objects. This precision can
71  * be changed using visu_gl_view_setPrecision() and all V_Sim part
72  * drawing something should use visu_gl_view_getDetailLevel() to
73  * know the size of the vertices to be drawn depending on this
74  * precision and the level of zoom.</para>
75  *
76  * <para>The rendering is done in an OpenGl viewport whose size is
77  * given by the bounding box (plus 10%). The camera can be positionned
78  * with three angles (theta, phi and omega) and has a zoom factor
79  * (gross) and a perspective value (d_red). The angle theta is around
80  * the z axis (box coordinates), phi is around the new x axis (after
81  * the theta rotation) and omega is a rotation around the axis which
82  * goes from the observer to the center of the bounding box. By
83  * default the camera looks at the center of the bounding box but this
84  * can be changed with the Xs and Ys parameters. These values are
85  * stored and are readable through the #VisuGlCamera structure. They
86  * must be changed with the following methods to ensure propery
87  * signals are correctly emitted:
88  * visu_gl_view_setThetaPhiOmega(), visu_gl_view_setGross(),
89  * visu_gl_view_setPersp() and visu_gl_view_setXsYs().</para>
90  */
91 
92 /**
93  * VisuGlCamera:
94  * @d_red: a factor for perspective from 1. to inifnity. With one, the nose of
95  *         the observer is completly set on the rendered object, and the size
96  *         of the observer is neglectible compared to the size of the object.
97  * @theta: the theta angle in spherical coordinates of the position of the observer ;
98  * @phi: the phi angle in spherical coordinates of the position of the observer ;
99  * @omega: rotation of the observer on itself ;
100  * @xs: a value for translation of the viewport on x axis ;
101  * @ys: a value for translation of the viewport on y axis ;
102  * @gross: a value of zoom ;
103  * @length0: a length reference to adimension all values, by default,
104  * this is the longest diagonal of the current box (without
105  * duplication) ;
106  * @up: (in) (array fixed-size=3): the current up vector.
107  * @upAxis: which axis define the north pole.
108  * @centre: (in) (array fixed-size=3): position of the eye look at ;
109  * @eye: (in) (array fixed-size=3): position of the eye.
110  * @unit: the unit of @length0.
111  *
112  * Values to define the position of the observer.
113  */
114 
115 /**
116  * VisuGlWindow:
117  * @extens: additional length to add to length0 to obtain the global
118  * viewable area.
119  * @unit: the #ToolUnits of @extens.
120  * @width : the width of the window ;
121  * @height : the height of the window ;
122  * @near : the beginning of the viewport on z axis (z for observer) ;
123  * @far : the end of the viewport on z axis (z for observer) ;
124  * @left : the left of the viewport on x axis ;
125  * @right : the right of the viewport on x axis ;
126  * @bottom : the bottom of the viewport on y axis ;
127  * @top : the top of the viewport on y axis ;
128  *
129  * Values to describe the window where the render is done.
130  */
131 
132 /* Global value used as default when creating a new VisuGlView. */
133 static float anglesDefault[3] = {40., -50., 0.};
134 static float translatDefault[2] = {0.5, 0.5};
135 static float grossDefault = 1.;
136 static float perspDefault = 5.;
137 
138 /* Local methods. */
139 static VisuGlCamera* camera_copy(VisuGlCamera *camera);
140 
141 /**
142  * visu_gl_camera_get_type:
143  *
144  * Create and retrieve a #GType for a #VisuGlCamera object.
145  *
146  * Since: 3.7
147  *
148  * Returns: a new type for #VisuGlCamera structures.
149  */
visu_gl_camera_get_type(void)150 GType visu_gl_camera_get_type(void)
151 {
152   static GType g_define_type_id = 0;
153 
154   if (g_define_type_id == 0)
155     g_define_type_id =
156       g_boxed_type_register_static("VisuGlCamera",
157                                    (GBoxedCopyFunc)camera_copy,
158                                    (GBoxedFreeFunc)g_free);
159   return g_define_type_id;
160 }
161 /**
162  * visu_gl_camera_copy:
163  * @to: a location to copy values to
164  * @from: a #VisuGlCamera to copy values from
165  *
166  * Do a deep copy of @from to @to.
167  *
168  * Since: 3.7
169  **/
visu_gl_camera_copy(VisuGlCamera * to,const VisuGlCamera * from)170 void visu_gl_camera_copy(VisuGlCamera *to, const VisuGlCamera *from)
171 {
172   to->theta     = from->theta;
173   to->phi       = from->phi;
174   to->omega     = from->omega;
175   to->xs        = from->xs;
176   to->ys        = from->ys;
177   to->gross     = from->gross;
178   to->d_red     = from->d_red;
179   to->length0   = from->length0;
180   to->unit      = from->unit;
181   to->upAxis    = from->upAxis;
182   to->centre[0] = from->centre[0];
183   to->centre[1] = from->centre[1];
184   to->centre[2] = from->centre[2];
185   to->up[0]     = from->up[0];
186   to->up[1]     = from->up[1];
187   to->up[2]     = from->up[2];
188   to->eye[0]    = from->eye[0];
189   to->eye[1]    = from->eye[1];
190   to->eye[2]    = from->eye[2];
191 }
camera_copy(VisuGlCamera * camera)192 static VisuGlCamera* camera_copy(VisuGlCamera *camera)
193 {
194   VisuGlCamera *out;
195 
196   out = g_malloc(sizeof(VisuGlCamera));
197   visu_gl_camera_copy(out, camera);
198   return out;
199 }
200 
201 /**
202  * visu_gl_camera_setThetaPhiOmega:
203  * @camera: a valid #VisuGlCamera object ;
204  * @valueTheta: a floatinf point value in degrees ;
205  * @valuePhi: a floating point value in degrees ;
206  * @valueOmega: a floating point value in degrees ;
207  * @mask: to specified what values will be changed.
208  *
209  * Change the orientation of the camera to the specified angles.
210  *
211  * Returns: a mask of changed values.
212  */
visu_gl_camera_setThetaPhiOmega(VisuGlCamera * camera,float valueTheta,float valuePhi,float valueOmega,int mask)213 int visu_gl_camera_setThetaPhiOmega(VisuGlCamera *camera, float valueTheta,
214                                          float valuePhi, float valueOmega, int mask)
215 {
216   float valT, valP, valO;
217   int diff;
218 
219   g_return_val_if_fail(camera, FALSE);
220 
221   diff = 0;
222   if (mask & VISU_GL_CAMERA_THETA)
223     {
224       valT = valueTheta;
225       while (valT < -180.)
226 	valT += 360.;
227       while (valT > 180.)
228 	valT -= 360.;
229 
230       if (camera->theta != valT)
231 	{
232 	  diff += VISU_GL_CAMERA_THETA;
233 	  camera->theta = valT;
234 	}
235     }
236   if (mask & VISU_GL_CAMERA_PHI)
237     {
238       valP = valuePhi;
239       while (valP < -180.)
240 	valP += 360.;
241       while (valP > 180.)
242 	valP -= 360.;
243 
244       if (camera->phi != valP)
245 	{
246 	  diff += VISU_GL_CAMERA_PHI;
247 	  camera->phi = valP;
248 	}
249     }
250   if (mask & VISU_GL_CAMERA_OMEGA)
251     {
252       valO = valueOmega;
253       while (valO < -180.)
254 	valO += 360.;
255       while (valO > 180.)
256 	valO -= 360.;
257 
258       if (camera->omega != valO)
259 	{
260 	  diff += VISU_GL_CAMERA_OMEGA;
261 	  camera->omega = valO;
262 	}
263     }
264   return diff;
265 }
266 
267 /**
268  * visu_gl_camera_setXsYs:
269  * @camera: a valid #VisuGlCamera object ;
270  * @valueX: a floatinf point value in the bounding box scale
271  *          (1 is the size of the bounding box) ;
272  * @valueY: a floating point value in bounding box scale ;
273  * @mask: to specified what values will be changed.
274  *
275  * Change the point where the camera is pointed to.
276  *
277  * Returns: a mask of changed values.
278  */
visu_gl_camera_setXsYs(VisuGlCamera * camera,float valueX,float valueY,int mask)279 int visu_gl_camera_setXsYs(VisuGlCamera *camera,
280                            float valueX, float valueY, int mask)
281 {
282   int diff;
283 
284   g_return_val_if_fail(camera, FALSE);
285 
286   diff = 0;
287   if (mask & VISU_GL_CAMERA_XS)
288     {
289       valueX = CLAMP(valueX, -3., 3.);
290 
291       if (camera->xs != valueX)
292 	{
293           diff += VISU_GL_CAMERA_XS;
294 	  camera->xs = valueX;
295 	}
296     }
297   if (mask & VISU_GL_CAMERA_YS)
298     {
299       valueY = CLAMP(valueY, -3., 3.);
300 
301       if (camera->ys != valueY)
302 	{
303           diff += VISU_GL_CAMERA_YS;
304 	  camera->ys = valueY;
305 	}
306     }
307   return diff;
308 
309 /*   g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLXsYs_signal_id, */
310 /* 		 0 , NULL); */
311 
312 /*   project(view); */
313 
314   /* Change the eyes position. */
315 /*   O[0] = view->camera->centre[0] + view->box->dxxs2; */
316 /*   O[1] = view->camera->centre[1] + view->box->dyys2; */
317 /*   O[2] = view->camera->centre[2] + view->box->dzzs2; */
318 /*   z = visu_gl_view_getZCoordinate(view, O); */
319 /*   DBG_fprintf(stderr, "OpenGL View: new window coordinates (%f;%f;%f).\n", */
320 /* 	      0.5f * view->window->width, 0.5f * view->window->height, z); */
321 /*   visu_gl_view_getRealCoordinates(view, view->camera->centre, */
322 /* 				0.5f * view->window->width, */
323 /* 				0.5f * view->window->height, z, FALSE); */
324 /*   modelize(view); */
325 }
326 
327 /**
328  * visu_gl_camera_setGross:
329  * @camera: a valid #VisuGlCamera object ;
330  * @value: a positive floating point value.
331  *
332  * Change the value of the camera zoom value. If the value is higher than 10
333  * it is set to 10 and if the value is negative it is set to 0.001.
334  *
335  * Returns: TRUE if value is actually changed.
336  */
visu_gl_camera_setGross(VisuGlCamera * camera,float value)337 gboolean visu_gl_camera_setGross(VisuGlCamera *camera, float value)
338 {
339   float val;
340 
341   g_return_val_if_fail(camera, FALSE);
342 
343   val = value;
344   if (val < 0.02)
345     val = 0.02;
346   else if (val > 999.)
347     val = 999.;
348 
349   if (camera->gross == val)
350     return FALSE;
351 
352   camera->gross = val;
353 /*   g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLGross_signal_id, */
354 /* 		 0 , NULL); */
355 /*   project(view); */
356 
357 /*   g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLFacetteChanged_signal_id, */
358 /* 		 0 , NULL); */
359   return TRUE;
360 }
361 
362 /**
363  * visu_gl_camera_setPersp:
364  * @camera: a valid #VisuGlCamera object ;
365  * @value: a floating point value greater than 1.1.
366  *
367  * Change the value of the camera perspective value and put it in
368  * bounds if needed.
369  *
370  * Returns: TRUE if value is actually changed.
371  */
visu_gl_camera_setPersp(VisuGlCamera * camera,float value)372 gboolean visu_gl_camera_setPersp(VisuGlCamera *camera, float value)
373 {
374   g_return_val_if_fail(camera, FALSE);
375 
376   DBG_fprintf(stderr, "Visu GlCamera: set persp to %g (%g).\n", value, camera->d_red);
377   value = CLAMP(value, 1.1f, 100.f);
378   if (camera->d_red == value)
379     return FALSE;
380 
381   camera->d_red = value;
382 
383 /*   project(view); */
384 /*   modelize(view); */
385   return TRUE;
386 }
387 /**
388  * visu_gl_window_setViewport:
389  * @window: a valid #VisuGlWindow object ;
390  * @width: the new horizontal size ;
391  * @height: the new vertical size.
392  *
393  * It changes the size of the OpenGl area and reccompute the OpenGL viewport.
394  *
395  * Returns: TRUE the size of @window is actually changed.
396  */
visu_gl_window_setViewport(VisuGlWindow * window,guint width,guint height)397 gboolean visu_gl_window_setViewport(VisuGlWindow *window, guint width, guint height)
398 {
399   DBG_fprintf(stderr, "OpenGL Window: set viewport size (%dx%d) for window %p.\n",
400 	      width, height, (gpointer)window);
401 
402   g_return_val_if_fail(window, FALSE);
403 
404   if (window->width == width && window->height == height)
405     return FALSE;
406 
407   DBG_fprintf(stderr, " | old values were %dx%d.\n", window->width,
408 	      window->height);
409   window->width = width;
410   window->height = height;
411   glViewport(0, 0, window->width, window->height);
412   return TRUE;
413 }
414 /**
415  * visu_gl_window_setAddLength:
416  * @window: a #VisuGlWindow object.
417  * @value: a float value (positive).
418  * @unit: the unit of @value.
419  *
420  * The viewable area is defined by the #VisuGlCamera size, as set by
421  * visu_gl_camera_setRefLength() and by additional space setup by this routine.
422  *
423  * Since: 3.7
424  *
425  * Returns: TRUE if the value is indeed changed.
426  **/
visu_gl_window_setAddLength(VisuGlWindow * window,float value,ToolUnits unit)427 gboolean visu_gl_window_setAddLength(VisuGlWindow *window, float value, ToolUnits unit)
428 {
429   DBG_fprintf(stderr, "OpenGL Window: set additional length (%f) for window %p.\n",
430 	      value, (gpointer)window);
431 
432   g_return_val_if_fail(window, FALSE);
433 
434   if (window->extens == value && window->unit == unit)
435     return FALSE;
436 
437   window->extens = value;
438   window->unit   = unit;
439   return TRUE;
440 }
441 /**
442  * visu_gl_window_getAddLength:
443  * @window: a #VisuGlWindow object.
444  * @unit: (allow-none): a location for the unit of the returned value.
445  *
446  * The viewable area is defined by the #VisuGlCamera size, as set by
447  * visu_gl_camera_setRefLength() and by additional space setup by
448  * visu_gl_window_setAddLength().
449  *
450  * Since: 3.7
451  *
452  * Returns: the additional length to be added to the camera object
453  * size to obtain the full viewable area.
454  **/
visu_gl_window_getAddLength(VisuGlWindow * window,ToolUnits * unit)455 float visu_gl_window_getAddLength(VisuGlWindow *window, ToolUnits *unit)
456 {
457   g_return_val_if_fail(window, FALSE);
458 
459   DBG_fprintf(stderr, "OpenGL Window: get additional length (%f) for window %p.\n",
460 	      window->extens, (gpointer)window);
461   if (unit)
462     *unit = window->unit;
463   return window->extens;
464 }
465 
466 /**
467  * visu_gl_camera_setUpAxis:
468  * @camera: a #VisuGlCamera object.
469  * @upAxis: a direction.
470  *
471  * In constraint observation mode, the "north" direction is a singular
472  * one. Define this direction with this routine.
473  *
474  * Since: 3.6
475  */
visu_gl_camera_setUpAxis(VisuGlCamera * camera,ToolXyzDir upAxis)476 void visu_gl_camera_setUpAxis(VisuGlCamera *camera, ToolXyzDir upAxis)
477 {
478   g_return_if_fail(camera);
479 
480   camera->upAxis = upAxis;
481 }
482 
483 /**
484  * visu_gl_camera_setRefLength:
485  * @camera: a #VisuGlCamera object.
486  * @value: a new length.
487  * @unit: its measurement unit.
488  *
489  * Change the reference value that is used for the zoom.
490  *
491  * Since: 3.6
492  *
493  * Returns: TRUE if the value is indeed changed.
494  */
visu_gl_camera_setRefLength(VisuGlCamera * camera,float value,ToolUnits unit)495 gboolean visu_gl_camera_setRefLength(VisuGlCamera *camera, float value, ToolUnits unit)
496 {
497   g_return_val_if_fail(camera, FALSE);
498 
499   DBG_fprintf(stderr, "Visu GlCamera: set ref length to %g %d (prev was %g %d)\n",
500               value, unit, camera->length0, camera->unit);
501 
502   if (camera->length0 == value && camera->unit == unit)
503     return FALSE;
504 
505   camera->length0 = value;
506   camera->unit    = unit;
507   return TRUE;
508 }
509 /**
510  * visu_gl_camera_getRefLength:
511  * @camera: a #VisuGlCamera object.
512  * @unit: a location for unit value (can be NULL).
513  *
514  * The zoom is define from a reference length in given unit. If @unit
515  * is provided, the corresponding unit will be set.
516  *
517  * Since: 3.6
518  *
519  * Returns: the current reference length.
520  */
visu_gl_camera_getRefLength(VisuGlCamera * camera,ToolUnits * unit)521 float visu_gl_camera_getRefLength(VisuGlCamera *camera, ToolUnits *unit)
522 {
523   g_return_val_if_fail(camera, -1.f);
524 
525   if (unit)
526     *unit = camera->unit;
527   return camera->length0;
528 }
529 
530 /**
531  * visu_gl_camera_modelize:
532  * @camera: a #VisuGlCamera object.
533  *
534  * Set-up the orientation matrix, depending on the camera definition.
535  */
visu_gl_camera_modelize(VisuGlCamera * camera)536 static void visu_gl_camera_modelize(VisuGlCamera *camera)
537 {
538   double theta_rad, d_red;
539   double phi_rad;
540   double sth, cth, sph, cph, com, som;
541   double distance;
542   int permut[3][3] = {{1,2,0}, {2,0,1}, {0,1,2}};
543 
544   g_return_if_fail(camera);
545 
546   DBG_fprintf(stderr, "OpenGL Camera: modelize view.\n");
547   DBG_fprintf(stderr, "OpenGL Camera: using ref length %g.\n",
548 	      camera->length0);
549 
550   if (camera->d_red > 100.)
551     d_red = 100.;
552   else
553     d_red = camera->d_red;
554   theta_rad = camera->theta * TOOL_PI180;
555   phi_rad   = camera->phi   * TOOL_PI180;
556 
557   distance = d_red * camera->length0;
558 
559   sth = sin(theta_rad);
560   cth = cos(theta_rad);
561   sph = sin(phi_rad);
562   cph = cos(phi_rad);
563   com = cos(camera->omega * TOOL_PI180);
564   som = sin(camera->omega * TOOL_PI180);
565 
566   /* La matrice de rotation est la suivante pour passer
567      des coordonnées transformées aux coordonnées de l'écran :
568      /cph.cth -sph cph.sth\
569      |sph.cth  cph sph.sth| (for z as north axis)
570      \   -sth   0      cth/
571 
572      / cph -sph.sth sph.cth\
573      |  0       cth     sth| (for y as north axis)
574      \-sph -sth.cph cph.cth/
575      Ainsi la caméra qui est situé en (0,0,Distance) dans le repère transformé
576      devient dans le repère de l'écran : */
577   camera->eye[permut[camera->upAxis][0]] = distance*sth*cph;
578   camera->eye[permut[camera->upAxis][1]] = distance*sth*sph;
579   camera->eye[permut[camera->upAxis][2]] = distance*cth;
580 
581   /* Vecteur donnant la direction verticale.
582      Dans le repère transformé il est (-1,0,0). */
583   camera->up[permut[camera->upAxis][0]] = -cth*cph*com + sph*som;
584   camera->up[permut[camera->upAxis][1]] = -cth*sph*com - cph*som;
585   camera->up[permut[camera->upAxis][2]] = sth*com;
586 
587   DBG_fprintf(stderr, "Visu GlView: modelize with:\n");
588   DBG_fprintf(stderr, " | %g %g %g  %g %g %g  %g %g %g\n",
589               camera->eye[0], camera->eye[1], camera->eye[2],
590               camera->centre[0], camera->centre[1], camera->centre[2],
591               camera->up[0], camera->up[1], camera->up[2]);
592   glMatrixMode(GL_MODELVIEW);
593   glLoadIdentity();
594   gluLookAt(camera->eye[0], camera->eye[1], camera->eye[2],
595 	    camera->centre[0], camera->centre[1], camera->centre[2],
596 	    camera->up[0], camera->up[1], camera->up[2]);
597 }
598 
599 /**
600  * visu_gl_window_project:
601  * @window: definition of the screen.
602  * @camera: position of the camera.
603  *
604  * This method is used to set the projection and the OpenGL viewport.
605  */
visu_gl_window_project(VisuGlWindow * window,const VisuGlCamera * camera)606 static void visu_gl_window_project(VisuGlWindow *window, const VisuGlCamera *camera)
607 {
608   double x, y, xmin, xmax, ymin, ymax, fact, rap;
609   double rap_win, d_red;
610 
611   g_return_if_fail(camera && window);
612   DBG_fprintf(stderr, "OpenGL View: project view (%d, %d).\n", camera->unit, window->unit);
613   DBG_fprintf(stderr, " | %g %g.\n", camera->length0, window->extens);
614 
615   if (camera->length0 <= 0. || camera->unit != window->unit)
616     return;
617 
618   if (camera->d_red > 100.)
619     d_red = 100.;
620   else
621     d_red = camera->d_red;
622 
623   fact = d_red * camera->length0;
624   window->near = MAX(0.01, fact - window->extens);
625   window->far  = fact + window->extens;
626 
627   fact = window->near / camera->gross / d_red;
628   rap = 2. * window->near / (d_red - 1.);
629   x = (0.5 - camera->xs) * rap;
630   xmin = x - fact;
631   xmax = x + fact;
632   y = (0.5 - camera->ys) * rap;
633   ymin = y - fact;
634   ymax = y + fact;
635   window->left   = xmin;
636   window->bottom = ymin;
637 
638   rap_win = (1.0*window->height)/window->width;
639   if ( 1. > rap_win )
640     {
641       window->top   = ymax;
642       fact          = (ymax - ymin) / rap_win;
643       window->left  = 0.5 * (xmin + xmax - fact);
644       window->right = 0.5 * (xmin + xmax + fact);
645     }
646   else if ( 1. < rap_win )
647     {
648       window->right  = xmax;
649       fact           = (xmax - xmin) * rap_win;
650       window->bottom = 0.5 * (ymin + ymax - fact);
651       window->top    = 0.5 * (ymin + ymax + fact);
652     }
653   else
654     {
655       window->right  = xmax;
656       window->top    = ymax;
657     }
658 
659   DBG_fprintf(stderr, "Visu GlView: project:\n");
660   DBG_fprintf(stderr, " | %g %g  %g %g  %g %g\n",
661               window->left, window->right, window->bottom,
662               window->top, window->near, window->far);
663   glMatrixMode(GL_PROJECTION);
664   glLoadIdentity();
665   if (d_red == 100.)
666     glOrtho(window->left, window->right, window->bottom,
667 	    window->top, window->near, window->far);
668   else
669     glFrustum(window->left, window->right, window->bottom,
670 	      window->top, window->near, window->far);
671   glMatrixMode(GL_MODELVIEW);
672 }
673 
674 /***************************/
675 /* The #VisuGlView object. */
676 /***************************/
677 enum {
678   CHANGED_SIGNAL,
679   WIDTH_HEIGHT_CHANGED_SIGNAL,
680   REF_LENGTH_CHANGED_SIGNAL,
681   FACETTES_CHANGED_SIGNAL,
682   LAST_SIGNAL
683 };
684 static guint _signals[LAST_SIGNAL] = { 0 };
685 enum
686   {
687     PROP_0,
688     THETA_PROP,
689     PHI_PROP,
690     OMEGA_PROP,
691     XS_PROP,
692     YS_PROP,
693     GROSS_PROP,
694     PERSP_PROP,
695     PRECISION_PROP,
696     N_PROP,
697     ADJUST_PROP,
698     BOX_PROP
699   };
700 static GParamSpec *properties[N_PROP];
701 
702 struct _VisuGlViewPrivate
703 {
704   VisuBox *box;
705   gulong box_signal, unit_signal, bc_signal;
706 
707   gboolean adjust;
708   float precision;
709 
710   VisuAnimation *theta_anim, *phi_anim, *gross_anim, *persp_anim;
711   GHashTable *animations;
712 
713   gboolean dispose_has_run;
714 };
715 
716 /* This is a positive float that enable to increase or
717    decrease the rendering load by modifying the
718    number of facettes. */
719 #define FLAG_PARAMETER_OPENGL_DETAILS   "opengl_details"
720 #define DESC_PARAMETER_OPENGL_DETAILS   "Give a value to the quality of rendering (100 is normal) ; positive integer"
721 static float _defaultDetails = 100.f;
722 static void exportParametersVisuGlView(GString *data,
723                                        VisuData *dataObj);
724 
725 #define FLAG_RESOURCE_OPENGL_ANGLES "opengl_theta_phi_omega"
726 #define DESC_RESOURCE_OPENGL_ANGLES "3 real values (degrees) for user orientation with respect to sample"
727 
728 #define FLAG_RESOURCE_OPENGL_TRANSLAT "opengl_xs_ys"
729 #define DESC_RESOURCE_OPENGL_TRANSLAT "2 real values for image position with respect to [0.0, 1.0]x[0.0, 1.0] window"
730 
731 #define FLAG_RESOURCE_OPENGL_GROSS "opengl_gross"
732 #define DESC_RESOURCE_OPENGL_GROSS "gross factor (must be real > 0.0)"
733 
734 #define FLAG_RESOURCE_OPENGL_PERSP "opengl_d_red"
735 #define DESC_RESOURCE_OPENGL_PERSP "reduced perspective distance (must be real > 1.0)"
736 
737 #define FLAG_PARAMETER_AUTO_ADJUST "config_autoAdjustCamera"
738 #define DESC_PARAMETER_AUTO_ADJUST "Auto adjust zoom capability for the box to be full size at zoom level 1 ; boolean 0 or 1"
739 static gboolean autoAdjustDefault = TRUE;
740 
741 static void exportResourcesVisuGlView(GString *data, VisuData *dataObj);
742 
743 static void visu_gl_view_dispose     (GObject* obj);
744 static void visu_gl_view_finalize    (GObject* obj);
745 static void visu_gl_view_get_property(GObject* obj, guint property_id,
746                                       GValue *value, GParamSpec *pspec);
747 static void visu_gl_view_set_property(GObject* obj, guint property_id,
748                                       const GValue *value, GParamSpec *pspec);
749 static void visu_boxed_interface_init(VisuBoxedInterface *iface);
750 static void visu_animatable_interface_init(VisuAnimatableInterface *iface);
751 
752 /* Callbacks. */
753 static void onSizeChanged(VisuBox *box, gfloat extens, gpointer data);
754 static void onUnitChanged(VisuBox *box, gfloat fact, gpointer data);
755 static void onBoundaryChanged(VisuBox *box, GParamSpec *pspec, gpointer data);
756 static void onEntryAngles(VisuGlView *view, VisuConfigFileEntry *entry, VisuConfigFile *obj);
757 static void onEntryTrans(VisuGlView *view, VisuConfigFileEntry *entry, VisuConfigFile *obj);
758 static void onEntryGross(VisuGlView *view, VisuConfigFileEntry *entry, VisuConfigFile *obj);
759 static void onEntryPersp(VisuGlView *view, VisuConfigFileEntry *entry, VisuConfigFile *obj);
760 static void onEntryPrecision(VisuGlView *view, VisuConfigFileEntry *entry, VisuConfigFile *obj);
761 
762 /* Local methods. */
763 static void _setBoundary(VisuGlView *view, VisuBox *box);
764 static VisuBox* _getBox(VisuBoxed *boxed);
765 static gboolean _setBox(VisuBoxed *boxed, VisuBox* box);
766 static VisuAnimation* _getAnimation(const VisuAnimatable *animatable, const gchar *prop);
767 
G_DEFINE_TYPE_WITH_CODE(VisuGlView,visu_gl_view,VISU_TYPE_OBJECT,G_ADD_PRIVATE (VisuGlView)G_IMPLEMENT_INTERFACE (VISU_TYPE_BOXED,visu_boxed_interface_init)G_IMPLEMENT_INTERFACE (VISU_TYPE_ANIMATABLE,visu_animatable_interface_init))768 G_DEFINE_TYPE_WITH_CODE(VisuGlView, visu_gl_view, VISU_TYPE_OBJECT,
769                         G_ADD_PRIVATE(VisuGlView)
770                         G_IMPLEMENT_INTERFACE(VISU_TYPE_BOXED,
771                                               visu_boxed_interface_init)
772                         G_IMPLEMENT_INTERFACE(VISU_TYPE_ANIMATABLE,
773                                               visu_animatable_interface_init))
774 
775 static void visu_gl_view_class_init(VisuGlViewClass *klass)
776 {
777   float rg[2] = {-G_MAXFLOAT, G_MAXFLOAT};
778   float rgGross[2] = {0.02f, 999.f};
779   float rgPersp[2] = {1.1f, 100.f};
780   float rgDetails[2] = {0.f, 500.f};
781   VisuConfigFileEntry *resourceEntry;
782 
783   DBG_fprintf(stderr, "Visu GlView: creating the class of the object.\n");
784   /* Connect the overloading methods. */
785   G_OBJECT_CLASS(klass)->dispose      = visu_gl_view_dispose;
786   G_OBJECT_CLASS(klass)->finalize     = visu_gl_view_finalize;
787   G_OBJECT_CLASS(klass)->set_property = visu_gl_view_set_property;
788   G_OBJECT_CLASS(klass)->get_property = visu_gl_view_get_property;
789 
790   DBG_fprintf(stderr, "                - adding new signals ;\n");
791   /**
792    * VisuGlView::changed:
793    * @view: the object which emits the signal ;
794    *
795    * Gets emitted when the view is changed.
796    *
797    * Since: 3.8
798    */
799   _signals[CHANGED_SIGNAL] =
800     g_signal_new("changed", G_TYPE_FROM_CLASS (klass),
801                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
802                  0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
803                  G_TYPE_NONE, 0);
804 
805   /**
806    * VisuGlView::WidthHeightChanged:
807    * @view: the object which received the signal ;
808    *
809    * Gets emitted when the viewing frame has been changed.
810    *
811    * Since: 3.2
812    */
813   _signals[WIDTH_HEIGHT_CHANGED_SIGNAL] =
814     g_signal_new("WidthHeightChanged", G_TYPE_FROM_CLASS (klass),
815                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
816                  0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
817                  G_TYPE_NONE, 0);
818   /**
819    * VisuGlView::RefLengthChanged:
820    * @view: the object which received the signal ;
821    *
822    * Gets emitted when the reference length of the camera has been changed.
823    *
824    * Since: 3.7
825    */
826   _signals[REF_LENGTH_CHANGED_SIGNAL] =
827     g_signal_new("RefLengthChanged", G_TYPE_FROM_CLASS (klass),
828                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
829                  0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
830                  G_TYPE_NONE, 0);
831   /**
832    * VisuGlView::DetailLevelChanged:
833    * @view: the object which received the signal ;
834    *
835    * Gets emitted when precision of the drawn object has been changed.
836    *
837    * Since: 3.2
838    */
839   _signals[FACETTES_CHANGED_SIGNAL] =
840     g_signal_new("DetailLevelChanged", G_TYPE_FROM_CLASS (klass),
841                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
842                  0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
843                  G_TYPE_NONE, 0);
844 
845   /**
846    * VisuGlView::theta:
847    *
848    * The theta angle of the camera.
849    *
850    * Since: 3.8
851    */
852   properties[THETA_PROP] = g_param_spec_double("theta", "Theta", "theta angle",
853                                                -360., 360., 90., G_PARAM_READWRITE);
854   /**
855    * VisuGlView::phi:
856    *
857    * The phi angle of the camera.
858    *
859    * Since: 3.8
860    */
861   properties[PHI_PROP] = g_param_spec_double("phi", "Phi", "phi angle",
862                                             -360., 360., 0., G_PARAM_READWRITE);
863   /**
864    * VisuGlView::omega:
865    *
866    * The omega angle of the camera.
867    *
868    * Since: 3.8
869    */
870   properties[OMEGA_PROP] = g_param_spec_double("omega", "Omega", "omega angle",
871                                               -360., 360., 0., G_PARAM_READWRITE);
872   /**
873    * VisuGlView::trans-x:
874    *
875    * The translation of the object along the window x axis.
876    *
877    * Since: 3.8
878    */
879   properties[XS_PROP] = g_param_spec_double("trans-x", "X translation", "translation along x",
880                                            -3., +3., 0.5, G_PARAM_READWRITE);
881   /**
882    * VisuGlView::trans-y:
883    *
884    * The translation of the object along the window y axis.
885    *
886    * Since: 3.8
887    */
888   properties[YS_PROP] = g_param_spec_double("trans-y", "Y translation", "translation along y",
889                                            -3., +3., 0.5, G_PARAM_READWRITE);
890   /**
891    * VisuGlView::zoom:
892    *
893    * The magnification of the camera.
894    *
895    * Since: 3.8
896    */
897   properties[GROSS_PROP] = g_param_spec_double("zoom", "Zoom", "zoom level",
898                                               .02, 999., 1., G_PARAM_READWRITE);
899   /**
900    * VisuGlView::perspective:
901    *
902    * The perspective of the camera.
903    *
904    * Since: 3.8
905    */
906   properties[PERSP_PROP] = g_param_spec_double("perspective", "Perspective",
907                                               "perspective level",
908                                               1.1, 100., 5., G_PARAM_READWRITE);
909   /**
910    * VisuGlView::precision:
911    *
912    * The accuracy of the rendering.
913    *
914    * Since: 3.8
915    */
916   properties[PRECISION_PROP] = g_param_spec_float("precision", "Precision",
917                                                   "precision level",
918                                                   0.f, 10.f, 1.f, G_PARAM_READWRITE);
919 
920   g_object_class_install_properties(G_OBJECT_CLASS(klass), N_PROP, properties);
921 
922   g_object_class_override_property(G_OBJECT_CLASS(klass), ADJUST_PROP, "auto-adjust");
923   g_object_class_override_property(G_OBJECT_CLASS(klass), BOX_PROP, "box");
924 
925   DBG_fprintf(stderr, "                - adding resources ;\n");
926   /* Parameters */
927   resourceEntry = visu_config_file_addFloatArrayEntry(VISU_CONFIG_FILE_PARAMETER,
928                                                       FLAG_PARAMETER_OPENGL_DETAILS,
929                                                       DESC_PARAMETER_OPENGL_DETAILS,
930                                                       1, &_defaultDetails, rgDetails, FALSE);
931   resourceEntry = visu_config_file_addBooleanEntry(VISU_CONFIG_FILE_PARAMETER,
932                                                    FLAG_PARAMETER_AUTO_ADJUST,
933                                                    DESC_PARAMETER_AUTO_ADJUST,
934                                                    &autoAdjustDefault, FALSE);
935   visu_config_file_entry_setVersion(resourceEntry, 3.6f);
936   visu_config_file_addExportFunction(VISU_CONFIG_FILE_PARAMETER,
937                                      exportParametersVisuGlView);
938 
939   /* Resources */
940   resourceEntry = visu_config_file_addFloatArrayEntry(VISU_CONFIG_FILE_RESOURCE,
941                                                       FLAG_RESOURCE_OPENGL_ANGLES,
942                                                       DESC_RESOURCE_OPENGL_ANGLES,
943                                                       3, anglesDefault, rg, FALSE);
944   visu_config_file_entry_setVersion(resourceEntry, 3.1f);
945   resourceEntry = visu_config_file_addFloatArrayEntry(VISU_CONFIG_FILE_RESOURCE,
946                                                       FLAG_RESOURCE_OPENGL_TRANSLAT,
947                                                       DESC_RESOURCE_OPENGL_TRANSLAT,
948                                                       2, translatDefault, rg, FALSE);
949   resourceEntry = visu_config_file_addFloatArrayEntry(VISU_CONFIG_FILE_RESOURCE,
950                                                       FLAG_RESOURCE_OPENGL_GROSS,
951                                                       DESC_RESOURCE_OPENGL_GROSS,
952                                                       1, &grossDefault, rgGross, FALSE);
953   resourceEntry = visu_config_file_addFloatArrayEntry(VISU_CONFIG_FILE_RESOURCE,
954                                                       FLAG_RESOURCE_OPENGL_PERSP,
955                                                       DESC_RESOURCE_OPENGL_PERSP,
956                                                       1, &perspDefault, rgPersp, FALSE);
957   visu_config_file_addExportFunction(VISU_CONFIG_FILE_RESOURCE,
958                                      exportResourcesVisuGlView);
959 }
visu_boxed_interface_init(VisuBoxedInterface * iface)960 static void visu_boxed_interface_init(VisuBoxedInterface *iface)
961 {
962   iface->get_box = _getBox;
963   iface->set_box = _setBox;
964 }
visu_animatable_interface_init(VisuAnimatableInterface * iface)965 static void visu_animatable_interface_init(VisuAnimatableInterface *iface)
966 {
967   iface->get_animation = _getAnimation;
968 }
969 
visu_gl_view_init(VisuGlView * view)970 static void visu_gl_view_init(VisuGlView *view)
971 {
972   DBG_fprintf(stderr, "Visu GlView: initializing a new object (%p).\n",
973 	      (gpointer)view);
974 
975   view->priv = visu_gl_view_get_instance_private(view);
976   view->priv->dispose_has_run = FALSE;
977 
978   view->priv->box             = (VisuBox*)0;
979   view->priv->box_signal      = 0;
980   view->priv->unit_signal     = 0;
981   view->priv->bc_signal       = 0;
982   view->priv->adjust          = autoAdjustDefault;
983   view->priv->precision       = _defaultDetails / 100.f;
984   view->priv->animations      = g_hash_table_new(g_str_hash, g_str_equal);
985   view->priv->theta_anim      = visu_animation_new(G_OBJECT(view), "theta");
986   g_hash_table_insert(view->priv->animations, "theta", view->priv->theta_anim);
987   view->priv->phi_anim        = visu_animation_new(G_OBJECT(view), "phi");
988   g_hash_table_insert(view->priv->animations, "phi", view->priv->phi_anim);
989   view->priv->gross_anim      = visu_animation_new(G_OBJECT(view), "zoom");
990   g_hash_table_insert(view->priv->animations, "zoom", view->priv->gross_anim);
991   view->priv->persp_anim      = visu_animation_new(G_OBJECT(view), "perspective");
992   g_hash_table_insert(view->priv->animations, "perspective", view->priv->persp_anim);
993 
994   view->window.extens = 0.;
995   view->window.width  = 0;
996   view->window.height = 0;
997   view->window.near   = 0.;
998   view->window.far    = 0.;
999   view->window.unit   = TOOL_UNITS_UNDEFINED;
1000 
1001   view->camera.theta   = anglesDefault[0];
1002   view->camera.phi     = anglesDefault[1];
1003   view->camera.omega   = anglesDefault[2];
1004   view->camera.xs      = translatDefault[0];
1005   view->camera.ys      = translatDefault[1];
1006   view->camera.gross   = grossDefault;
1007   view->camera.d_red   = perspDefault;
1008   view->camera.length0 = -1.;
1009   view->camera.unit    = TOOL_UNITS_UNDEFINED;
1010   view->camera.upAxis  = TOOL_XYZ_Z;
1011   view->camera.centre[0] = 0.f;
1012   view->camera.centre[1] = 0.f;
1013   view->camera.centre[2] = 0.f;
1014 
1015   DBG_fprintf(stderr, " | theta = %g\n", view->camera.theta);
1016   DBG_fprintf(stderr, " | phi   = %g\n", view->camera.phi);
1017   DBG_fprintf(stderr, " | omega = %g\n", view->camera.omega);
1018   DBG_fprintf(stderr, " | dx-dy = %g %g\n", view->camera.xs, view->camera.ys);
1019   DBG_fprintf(stderr, " | gross = %g\n", view->camera.gross);
1020   DBG_fprintf(stderr, " | persp = %g\n", view->camera.d_red);
1021   DBG_fprintf(stderr, " | width x height = %d x %d\n", view->window.width, view->window.height);
1022 
1023   g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_OPENGL_ANGLES,
1024                           G_CALLBACK(onEntryAngles), (gpointer)view, G_CONNECT_SWAPPED);
1025   g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_OPENGL_TRANSLAT,
1026                           G_CALLBACK(onEntryTrans), (gpointer)view, G_CONNECT_SWAPPED);
1027   g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_OPENGL_GROSS,
1028                           G_CALLBACK(onEntryGross), (gpointer)view, G_CONNECT_SWAPPED);
1029   g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCE_OPENGL_PERSP,
1030                           G_CALLBACK(onEntryPersp), (gpointer)view, G_CONNECT_SWAPPED);
1031   g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_PARAMETER_OPENGL_DETAILS,
1032                           G_CALLBACK(onEntryPrecision), (gpointer)view, G_CONNECT_SWAPPED);
1033 }
1034 /* This method can be called several times.
1035    It should unref all of its reference to
1036    GObjects. */
visu_gl_view_dispose(GObject * obj)1037 static void visu_gl_view_dispose(GObject* obj)
1038 {
1039   VisuGlView *view;
1040 
1041   DBG_fprintf(stderr, "Visu GlView: dispose object %p.\n", (gpointer)obj);
1042 
1043   view = VISU_GL_VIEW(obj);
1044   if (view->priv->dispose_has_run)
1045     return;
1046   view->priv->dispose_has_run = TRUE;
1047 
1048   _setBox(VISU_BOXED(view), (VisuBox*)0);
1049   g_object_unref(view->priv->theta_anim);
1050   g_object_unref(view->priv->phi_anim);
1051   g_object_unref(view->priv->gross_anim);
1052   g_object_unref(view->priv->persp_anim);
1053 
1054   /* Chain up to the parent class */
1055   G_OBJECT_CLASS(visu_gl_view_parent_class)->dispose(obj);
1056 }
1057 /* This method is called once only. */
visu_gl_view_finalize(GObject * obj)1058 static void visu_gl_view_finalize(GObject* obj)
1059 {
1060   g_return_if_fail(obj);
1061 
1062   DBG_fprintf(stderr, "Visu GlView: finalize object %p.\n", (gpointer)obj);
1063   g_hash_table_destroy(VISU_GL_VIEW(obj)->priv->animations);
1064 
1065   /* Chain up to the parent class */
1066   DBG_fprintf(stderr, "Visu GlView: chain to parent.\n");
1067   G_OBJECT_CLASS(visu_gl_view_parent_class)->finalize(obj);
1068   DBG_fprintf(stderr, "Visu GlView: freeing ... OK.\n");
1069 }
visu_gl_view_get_property(GObject * obj,guint property_id,GValue * value,GParamSpec * pspec)1070 static void visu_gl_view_get_property(GObject* obj, guint property_id,
1071                                       GValue *value, GParamSpec *pspec)
1072 {
1073   VisuGlView *self = VISU_GL_VIEW(obj);
1074 
1075   DBG_fprintf(stderr, "Visu GlView: get property '%s' -> ",
1076 	      g_param_spec_get_name(pspec));
1077   switch (property_id)
1078     {
1079     case THETA_PROP:
1080       if (visu_animation_isRunning(self->priv->theta_anim))
1081         visu_animation_getTo(self->priv->theta_anim, value);
1082       else
1083         g_value_set_double(value, self->camera.theta);
1084       DBG_fprintf(stderr, "%g.\n", self->camera.theta);
1085       break;
1086     case PHI_PROP:
1087       if (visu_animation_isRunning(self->priv->phi_anim))
1088         visu_animation_getTo(self->priv->phi_anim, value);
1089       else
1090         g_value_set_double(value, self->camera.phi);
1091       DBG_fprintf(stderr, "%g.\n", self->camera.phi);
1092       break;
1093     case OMEGA_PROP:
1094       g_value_set_double(value, self->camera.omega);
1095       DBG_fprintf(stderr, "%g.\n", self->camera.omega);
1096       break;
1097     case XS_PROP:
1098       g_value_set_double(value, self->camera.xs);
1099       DBG_fprintf(stderr, "%g.\n", self->camera.xs);
1100       break;
1101     case YS_PROP:
1102       g_value_set_double(value, self->camera.ys);
1103       DBG_fprintf(stderr, "%g.\n", self->camera.ys);
1104       break;
1105     case GROSS_PROP:
1106       if (visu_animation_isRunning(self->priv->gross_anim))
1107         visu_animation_getTo(self->priv->gross_anim, value);
1108       else
1109         g_value_set_double(value, self->camera.gross);
1110       DBG_fprintf(stderr, "%g.\n", self->camera.gross);
1111       break;
1112     case PERSP_PROP:
1113       if (visu_animation_isRunning(self->priv->persp_anim))
1114         visu_animation_getTo(self->priv->persp_anim, value);
1115       else
1116         g_value_set_double(value, self->camera.d_red);
1117       DBG_fprintf(stderr, "%g.\n", self->camera.d_red);
1118       break;
1119     case ADJUST_PROP:
1120       g_value_set_boolean(value, self->priv->adjust);
1121       DBG_fprintf(stderr, "%d.\n", self->priv->adjust);
1122       break;
1123     case PRECISION_PROP:
1124       DBG_fprintf(stderr, "%g.\n", self->priv->precision);
1125       g_value_set_float(value, self->priv->precision);
1126       break;
1127     case BOX_PROP:
1128       DBG_fprintf(stderr, "%p.\n", (gpointer)self->priv->box);
1129       g_value_set_object(value, self->priv->box);
1130       break;
1131     default:
1132       /* We don't have any other property... */
1133       G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
1134       break;
1135     }
1136 }
visu_gl_view_set_property(GObject * obj,guint property_id,const GValue * value,GParamSpec * pspec)1137 static void visu_gl_view_set_property(GObject* obj, guint property_id,
1138                                       const GValue *value, GParamSpec *pspec)
1139 {
1140   VisuGlView *self = VISU_GL_VIEW(obj);
1141 
1142   DBG_fprintf(stderr, "Visu GlView: set property '%s' -> ",
1143 	      g_param_spec_get_name(pspec));
1144   switch (property_id)
1145     {
1146     case THETA_PROP:
1147       DBG_fprintf(stderr, "%g.\n", g_value_get_double(value));
1148       if (!visu_animatable_animateDouble(VISU_ANIMATABLE(self), self->priv->theta_anim,
1149                                          g_value_get_double(value),
1150                                          200, FALSE, VISU_ANIMATION_QUAD))
1151         visu_gl_view_setThetaPhiOmega(self, g_value_get_double(value),
1152                                       0., 0., VISU_GL_CAMERA_THETA);
1153       break;
1154     case PHI_PROP:
1155       DBG_fprintf(stderr, "%g.\n", g_value_get_double(value));
1156       if (!visu_animatable_animateDouble(VISU_ANIMATABLE(self), self->priv->phi_anim,
1157                                          g_value_get_double(value),
1158                                          200, FALSE, VISU_ANIMATION_QUAD))
1159         visu_gl_view_setThetaPhiOmega(self, 0., g_value_get_double(value),
1160                                       0., VISU_GL_CAMERA_PHI);
1161       break;
1162     case OMEGA_PROP:
1163       visu_gl_view_setThetaPhiOmega(self, 0., 0., g_value_get_double(value),
1164                                     VISU_GL_CAMERA_OMEGA);
1165       DBG_fprintf(stderr, "%g.\n", self->camera.omega);
1166       break;
1167     case XS_PROP:
1168       visu_gl_view_setXsYs(self, g_value_get_double(value), 0.,
1169                            VISU_GL_CAMERA_XS);
1170       DBG_fprintf(stderr, "%g.\n", self->camera.xs);
1171       break;
1172     case YS_PROP:
1173       visu_gl_view_setXsYs(self, 0., g_value_get_double(value),
1174                            VISU_GL_CAMERA_YS);
1175       DBG_fprintf(stderr, "%g.\n", self->camera.ys);
1176       break;
1177     case GROSS_PROP:
1178       DBG_fprintf(stderr, "%g.\n", g_value_get_double(value));
1179       if (!visu_animatable_animateDouble(VISU_ANIMATABLE(self), self->priv->gross_anim,
1180                                          g_value_get_double(value),
1181                                          200, FALSE, VISU_ANIMATION_QUAD))
1182         visu_gl_view_setGross(self, g_value_get_double(value));
1183       break;
1184     case PERSP_PROP:
1185       DBG_fprintf(stderr, "%g.\n", g_value_get_double(value));
1186       if (!visu_animatable_animateDouble(VISU_ANIMATABLE(self), self->priv->persp_anim,
1187                                          g_value_get_double(value),
1188                                          200, FALSE, VISU_ANIMATION_QUAD))
1189         visu_gl_view_setPersp(self, g_value_get_double(value));
1190       break;
1191     case ADJUST_PROP:
1192       self->priv->adjust = g_value_get_boolean(value);
1193       autoAdjustDefault = g_value_get_boolean(value);
1194       DBG_fprintf(stderr, "%d.\n", self->priv->adjust);
1195       break;
1196     case PRECISION_PROP:
1197       DBG_fprintf(stderr, "%g.\n", g_value_get_float(value));
1198       visu_gl_view_setPrecision(self, g_value_get_float(value));
1199       break;
1200     case BOX_PROP:
1201       DBG_fprintf(stderr, "%p.\n", g_value_get_object(value));
1202       _setBox(VISU_BOXED(obj), VISU_BOX(g_value_get_object(value)));
1203       break;
1204     default:
1205       /* We don't have any other property... */
1206       G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
1207       break;
1208     }
1209 }
1210 
1211 /**
1212  * visu_gl_view_new:
1213  *
1214  * Create a new #VisuGlView object with default values.
1215  *
1216  * Returns: (transfer full): the newly created object.
1217  */
visu_gl_view_new(void)1218 VisuGlView* visu_gl_view_new(void)
1219 {
1220   VisuGlView *view;
1221 
1222   view = VISU_GL_VIEW(g_object_new(VISU_TYPE_GL_VIEW, NULL));
1223   return view;
1224 }
1225 
1226 /**
1227  * visu_gl_view_new_withSize:
1228  * @w: the width ;
1229  * @h: the height.
1230  *
1231  * Create a new #VisuGlView object with default values and the given
1232  * window size.
1233  *
1234  * Since: 3.7
1235  *
1236  * Returns: (transfer full): the newly created object.
1237  */
visu_gl_view_new_withSize(guint w,guint h)1238 VisuGlView* visu_gl_view_new_withSize(guint w, guint h)
1239 {
1240   VisuGlView *view;
1241 
1242   view = VISU_GL_VIEW(g_object_new(VISU_TYPE_GL_VIEW, NULL));
1243   visu_gl_window_setViewport(&view->window, w, h);
1244 
1245   return view;
1246 }
1247 
1248 /**
1249  * visu_gl_view_initContext:
1250  * @view: a #VisuGlView object.
1251  *
1252  * Modelize and project the view. Should be called when used in a new
1253  * OpenGL context.
1254  *
1255  * Since: 3.8
1256  **/
visu_gl_view_initContext(VisuGlView * view)1257 void visu_gl_view_initContext(VisuGlView *view)
1258 {
1259   g_return_if_fail(VISU_IS_GL_VIEW(view));
1260 
1261   visu_gl_camera_modelize(&view->camera);
1262   visu_gl_window_project(&view->window, &view->camera);
1263 }
1264 
_setBox(VisuBoxed * self,VisuBox * box)1265 static gboolean _setBox(VisuBoxed *self, VisuBox *box)
1266 {
1267   VisuGlView *view;
1268   float fact;
1269 
1270   g_return_val_if_fail(VISU_IS_GL_VIEW(self), FALSE);
1271   view = VISU_GL_VIEW(self);
1272 
1273   DBG_fprintf(stderr, "OpenGL View: set box %p.\n", (gpointer)box);
1274 
1275   if (box == view->priv->box)
1276     return FALSE;
1277 
1278   if (view->priv->box)
1279     {
1280       g_signal_handler_disconnect(G_OBJECT(view->priv->box), view->priv->box_signal);
1281       g_signal_handler_disconnect(G_OBJECT(view->priv->box), view->priv->unit_signal);
1282       g_signal_handler_disconnect(G_OBJECT(view->priv->box), view->priv->bc_signal);
1283       g_object_unref(view->priv->box);
1284     }
1285   if (box)
1286     {
1287       g_object_ref(box);
1288       view->priv->box_signal =
1289         g_signal_connect(G_OBJECT(box), "SizeChanged",
1290                          G_CALLBACK(onSizeChanged), (gpointer)view);
1291       view->priv->unit_signal =
1292 	g_signal_connect(G_OBJECT(box), "UnitChanged",
1293 			 G_CALLBACK(onUnitChanged), (gpointer)view);
1294       view->priv->bc_signal =
1295 	g_signal_connect(G_OBJECT(box), "notify::boundary",
1296 			 G_CALLBACK(onBoundaryChanged), (gpointer)view);
1297 
1298       /* Update lengths. */
1299       if (view->priv->adjust || view->camera.length0 <= 0.f)
1300         visu_gl_view_setRefLength(view,
1301                                   visu_box_getGlobalSize(box, FALSE),
1302                                   visu_box_getUnit(box));
1303       else
1304         {
1305           fact = 1.;
1306           if (view->camera.unit != TOOL_UNITS_UNDEFINED &&
1307               visu_box_getUnit(box) != TOOL_UNITS_UNDEFINED)
1308             fact = tool_physic_getUnitValueInMeter(view->camera.unit) /
1309               tool_physic_getUnitValueInMeter(visu_box_getUnit(box));
1310           DBG_fprintf(stderr, "Visu GlView: ref length factor %g (%d %d).\n",
1311                       fact, view->camera.unit, visu_box_getUnit(box));
1312           visu_gl_view_setRefLength(view,
1313                                     view->camera.length0 * fact,
1314                                     visu_box_getUnit(box));
1315         }
1316       visu_gl_view_setObjectRadius(view,
1317                                    visu_box_getGlobalSize(box, TRUE),
1318                                    visu_box_getUnit(box));
1319       /* Update camera. */
1320       _setBoundary(view, box);
1321     }
1322   else
1323     {
1324       view->priv->box_signal = 0;
1325       view->priv->unit_signal = 0;
1326       view->priv->bc_signal = 0;
1327     }
1328   view->priv->box = box;
1329 
1330   return TRUE;
1331 }
onSizeChanged(VisuBox * box,gfloat extens,gpointer data)1332 static void onSizeChanged(VisuBox *box, gfloat extens, gpointer data)
1333 {
1334   VisuGlView *view = VISU_GL_VIEW(data);
1335 
1336   DBG_fprintf(stderr, "Visu GlView: caught 'SizeChanged'.\n");
1337   visu_gl_view_setObjectRadius(view, extens, visu_box_getUnit(box));
1338   DBG_fprintf(stderr, "Visu GlView: done 'SizeChanged'.\n");
1339 }
onUnitChanged(VisuBox * box,gfloat fact,gpointer data)1340 static void onUnitChanged(VisuBox *box, gfloat fact, gpointer data)
1341 {
1342   VisuGlView *view = VISU_GL_VIEW(data);
1343   ToolUnits unit;
1344 
1345   DBG_fprintf(stderr, "Visu GlView: caught 'UnitChanged'.\n");
1346   unit = visu_box_getUnit(box);
1347   if (view->camera.unit != TOOL_UNITS_UNDEFINED && unit != TOOL_UNITS_UNDEFINED)
1348     fact = tool_physic_getUnitValueInMeter(view->camera.unit) /
1349       tool_physic_getUnitValueInMeter(unit);
1350   visu_gl_view_setRefLength(view, view->camera.length0 * fact, unit);
1351   /* Box size changed will be emitted after, so the object radius will
1352      be updated automatically, except for undefined units. */
1353   if (view->window.unit == TOOL_UNITS_UNDEFINED || unit == TOOL_UNITS_UNDEFINED)
1354     visu_gl_window_setAddLength(&view->window, view->window.extens, unit);
1355   DBG_fprintf(stderr, "Visu GlView: done 'UnitChanged'.\n");
1356 }
onBoundaryChanged(VisuBox * box,GParamSpec * pspec _U_,gpointer data)1357 static void onBoundaryChanged(VisuBox *box, GParamSpec *pspec _U_, gpointer data)
1358 {
1359   _setBoundary(VISU_GL_VIEW(data), box);
1360 }
_setBoundary(VisuGlView * view,VisuBox * box)1361 static void _setBoundary(VisuGlView *view, VisuBox *box)
1362 {
1363   switch (visu_box_getBoundary(box))
1364     {
1365     case (VISU_BOX_PERIODIC):
1366     case (VISU_BOX_FREE):
1367     case (VISU_BOX_WIRE_X):
1368     case (VISU_BOX_WIRE_Y):
1369     case (VISU_BOX_WIRE_Z):
1370     case (VISU_BOX_SURFACE_XY):
1371       visu_gl_camera_setUpAxis(&view->camera, TOOL_XYZ_Z);
1372       break;
1373     case (VISU_BOX_SURFACE_YZ):
1374       visu_gl_camera_setUpAxis(&view->camera, TOOL_XYZ_X);
1375       break;
1376     case (VISU_BOX_SURFACE_ZX):
1377       visu_gl_camera_setUpAxis(&view->camera, TOOL_XYZ_Y);
1378       break;
1379     }
1380   visu_gl_camera_modelize(&view->camera);
1381   g_signal_emit(view, _signals[CHANGED_SIGNAL], 0);
1382 }
_getBox(VisuBoxed * boxed)1383 static VisuBox* _getBox(VisuBoxed *boxed)
1384 {
1385   g_return_val_if_fail(VISU_IS_GL_VIEW(boxed), (VisuBox*)0);
1386 
1387   return VISU_GL_VIEW(boxed)->priv->box;
1388 }
_getAnimation(const VisuAnimatable * animatable,const gchar * prop)1389 static VisuAnimation* _getAnimation(const VisuAnimatable *animatable,
1390                                     const gchar *prop)
1391 {
1392   g_return_val_if_fail(VISU_IS_GL_VIEW(animatable), (VisuAnimation*)0);
1393 
1394   return g_hash_table_lookup(VISU_GL_VIEW(animatable)->priv->animations, prop);
1395 }
1396 
1397 /**
1398  * visu_gl_view_getDetailLevel:
1399  * @view: a valid #VisuGlView object ;
1400  * @dimension: the size of the object which asks for its number of facettes.
1401  *
1402  * This is a function to get the number of "facettes" advised
1403  * by the server (according to its policy on rendering)
1404  * to draw an object according to a given dimension.
1405  *
1406  * Returns: the number of facettes the object should used.
1407  */
visu_gl_view_getDetailLevel(const VisuGlView * view,float dimension)1408 gint visu_gl_view_getDetailLevel(const VisuGlView *view, float dimension)
1409 {
1410   gint rsize;
1411   gint nlat;
1412 #define NLAT_MIN 12
1413 #define NLAT_MAX 50
1414 #define RSIZE_MIN  10
1415 #define RSIZE_MAX 250
1416 
1417 #define NLAT_V_MIN 0
1418 #define NLAT_V_MAX (NLAT_MIN)
1419 #define RSIZE_V_MIN  0
1420 #define RSIZE_V_MAX (RSIZE_MIN)
1421 
1422 #define NLAT_MINI 3
1423 #define NLAT_MAXI 100
1424 
1425   static float fac = -1.0f, fac_v = -1.0f;
1426 
1427   g_return_val_if_fail(VISU_IS_GL_VIEW(view), 0);
1428 
1429   DBG_fprintf(stderr, "Visu GlView: get GL details for window %dx%d.\n",
1430               view->window.width, view->window.height);
1431   DBG_fprintf(stderr, " | gross = %g.\n", view->camera.gross);
1432   DBG_fprintf(stderr, " | persp = %g.\n", view->camera.d_red);
1433   DBG_fprintf(stderr, " | lgth0 = %g.\n", view->camera.length0);
1434 
1435   /* calculate once fac and fac_v!... */
1436   if(fac < 0.0f) {
1437     fac = ((float)(NLAT_MAX - NLAT_MIN))/(RSIZE_MAX - RSIZE_MIN);
1438     fac_v = ((float)(NLAT_V_MAX - NLAT_V_MIN))/(RSIZE_V_MAX - RSIZE_V_MIN);
1439   }
1440 
1441   rsize = (int)((float)MIN(view->window.width, view->window.height) *
1442 		(0.5 * dimension / view->camera.length0 * view->camera.gross *
1443 		 view->camera.d_red / (view->camera.d_red - 1.)));
1444 
1445   if(rsize < RSIZE_MIN) {
1446     nlat = (int)(NLAT_V_MIN + fac_v * (rsize - RSIZE_V_MIN));
1447     if(nlat < NLAT_MINI) nlat = NLAT_MINI;
1448   }
1449   else if(rsize > RSIZE_MAX) {
1450     nlat = NLAT_MAX;
1451   }
1452   else {
1453     nlat = (int)(NLAT_MIN + fac * (rsize - RSIZE_MIN));
1454   }
1455 
1456   nlat = (int)((float)nlat * view->priv->precision);
1457   nlat = CLAMP(nlat, NLAT_MINI, NLAT_MAXI);
1458 
1459   DBG_fprintf(stderr, " | nlat  = %d.\n", nlat);
1460   return nlat;
1461 }
1462 /**
1463  * visu_gl_view_setPrecision:
1464  * @view: a #VisuGlView object.
1465  * @value: a positive value (1. is normal precision).
1466  *
1467  * This function change the value of the parameter precisionOfRendering. It
1468  * changes the number of facettes advised for every objects. It allows to
1469  * increase or decrease the number of polygons drawn and thus acts on the
1470  * speed of rendering.
1471  *
1472  * Returns: TRUE if value is actually changed.
1473  */
visu_gl_view_setPrecision(VisuGlView * view,float value)1474 gboolean visu_gl_view_setPrecision(VisuGlView *view, float value)
1475 {
1476   g_return_val_if_fail(VISU_IS_GL_VIEW(view), FALSE);
1477 
1478   if (value <= 0. || value == view->priv->precision)
1479     return FALSE;
1480 
1481   view->priv->precision = value;
1482   _defaultDetails = value * 100.f;
1483   g_object_notify_by_pspec(G_OBJECT(view), properties[PRECISION_PROP]);
1484   g_signal_emit(G_OBJECT(view), _signals[FACETTES_CHANGED_SIGNAL], 0);
1485 
1486   return TRUE;
1487 }
1488 /**
1489  * visu_gl_view_getPrecision:
1490  * @view: a #VisuGlView object.
1491  *
1492  * This function retrieve the value of the parameter precisionOfRendering.
1493  *
1494  * Returns: the actual precision.
1495  */
visu_gl_view_getPrecision(const VisuGlView * view)1496 float visu_gl_view_getPrecision(const VisuGlView *view)
1497 {
1498   g_return_val_if_fail(VISU_IS_GL_VIEW(view), 1.f);
1499 
1500   return view->priv->precision;
1501 }
1502 /**
1503  * visu_gl_window_getFileUnitPerPixel:
1504  * @window: a valid #VisuGlWindow object.
1505  *
1506  * This method is used to know the ratio of a pixel with the unit of the file.
1507  * WARNING : this method is valid only when the camera is position at infinity.
1508  *
1509  * Returns: how much of a unit of file is in a pixel.
1510  */
visu_gl_window_getFileUnitPerPixel(VisuGlWindow * window)1511 float visu_gl_window_getFileUnitPerPixel(VisuGlWindow *window)
1512 {
1513   float deltaH, deltaV;
1514 
1515   g_return_val_if_fail(window, 0.);
1516 
1517   deltaH = window->right - window->left;
1518   deltaV = window->top - window->bottom;
1519   if (deltaH < deltaV)
1520     return deltaH / (float)window->width;
1521   else
1522     return deltaV / (float)window->height;
1523 }
1524 /**
1525  * visu_gl_camera_getScreenAxes:
1526  * @camera: a valid #VisuGlCamera.
1527  * @xAxis: (in) (array fixed-size=3): three float values representing x axis ;
1528  * @yAxis: (in) (array fixed-size=3): three float values representing y axis.
1529  *
1530  * This method is used to get the coordinates in box frame of x axis and y axis
1531  * of the current camera view.
1532  */
visu_gl_camera_getScreenAxes(VisuGlCamera * camera,float xAxis[3],float yAxis[3])1533 void visu_gl_camera_getScreenAxes(VisuGlCamera *camera, float xAxis[3], float yAxis[3])
1534 {
1535   double cth, sth, cph, sph, com, som;
1536   float matPhi[3][3], matTheta[3][3], matOmega[3][3];
1537   float matRes[3][3], matRes2[3][3];
1538   float axis[3];
1539 
1540   g_return_if_fail(camera);
1541 
1542   cth = cos(camera->theta * TOOL_PI180);
1543   sth = sin(camera->theta * TOOL_PI180);
1544   cph = cos(camera->phi * TOOL_PI180);
1545   sph = sin(camera->phi * TOOL_PI180);
1546   com = cos(camera->omega * TOOL_PI180);
1547   som = sin(camera->omega * TOOL_PI180);
1548 
1549   matPhi[0][0] = cph;
1550   matPhi[1][0] = sph;
1551   matPhi[2][0] = 0.;
1552   matPhi[0][1] = -sph;
1553   matPhi[1][1] = cph;
1554   matPhi[2][1] = 0.;
1555   matPhi[0][2] = 0.;
1556   matPhi[1][2] = 0.;
1557   matPhi[2][2] = 1.;
1558 
1559   matTheta[0][0] = cth;
1560   matTheta[1][0] = 0.;
1561   matTheta[2][0] = -sth;
1562   matTheta[0][1] = 0.;
1563   matTheta[1][1] = 1.;
1564   matTheta[2][1] = 0.;
1565   matTheta[0][2] = sth;
1566   matTheta[1][2] = 0.;
1567   matTheta[2][2] = cth;
1568 
1569   matOmega[0][0] = com;
1570   matOmega[1][0] = som;
1571   matOmega[2][0] = 0.;
1572   matOmega[0][1] = -som;
1573   matOmega[1][1] = com;
1574   matOmega[2][1] = 0.;
1575   matOmega[0][2] = 0.;
1576   matOmega[1][2] = 0.;
1577   matOmega[2][2] = 1.;
1578 
1579   tool_matrix_productMatrix(matRes, matTheta, matOmega);
1580   tool_matrix_productMatrix(matRes2, matPhi, matRes);
1581 
1582   axis[0] = 0.;
1583   axis[1] = 1.;
1584   axis[2] = 0.;
1585   tool_matrix_productVector(xAxis, matRes2, axis);
1586 
1587   axis[0] = -1.;
1588   axis[1] = 0.;
1589   axis[2] = 0.;
1590   tool_matrix_productVector(yAxis, matRes2, axis);
1591 }
1592 /**
1593  * visu_gl_view_getZCoordinate:
1594  * @view: a #VisuGlView object.
1595  * @xyz: a cartesian point.
1596  *
1597  * Use this routine to know the Z value of a real point defined by
1598  * @xyz in caretsian coordinates.
1599  */
visu_gl_view_getZCoordinate(VisuGlView * view,float xyz[3])1600 float visu_gl_view_getZCoordinate(VisuGlView *view, float xyz[3])
1601 {
1602   GLdouble model[16], project[16];
1603   GLint viewport[4];
1604   GLdouble xyzGL[3], winGL[3];
1605 
1606   g_return_val_if_fail(view, 0.5f);
1607 
1608   glGetDoublev(GL_MODELVIEW_MATRIX, model);
1609   glGetDoublev(GL_PROJECTION_MATRIX, project);
1610   glGetIntegerv(GL_VIEWPORT, viewport);
1611 
1612   xyzGL[0] = (GLdouble)xyz[0];
1613   xyzGL[1] = (GLdouble)xyz[1];
1614   xyzGL[2] = (GLdouble)xyz[2];
1615   gluProject(xyzGL[0], xyzGL[1], xyzGL[2], model, project, viewport,
1616 	     winGL, winGL + 1, winGL + 2);
1617   DBG_fprintf(stderr, "OpenGL View: get z coordinates from %gx%gx%g: %g.\n",
1618 	      xyz[0], xyz[1], xyz[2], (float)winGL[2]);
1619   DBG_fprintf(stderr, " | win coords: %gx%g\n",
1620 	      (float)winGL[0], (float)winGL[1]);
1621   return (float)winGL[2];
1622 }
1623 /**
1624  * visu_gl_view_getRealCoordinates:
1625  * @view: a #VisuGlView object.
1626  * @xyz: a location to store the result.
1627  * @winx: position on X axis of screen.
1628  * @winy: position on Y axis of screen.
1629  * @winz: height before projection on screen.
1630  *
1631  * Use this routine to get the cartesian coordinates in real space of
1632  * a point located at @winx and @winy on screen.
1633  */
visu_gl_view_getRealCoordinates(VisuGlView * view,float xyz[3],float winx,float winy,float winz)1634 void visu_gl_view_getRealCoordinates(VisuGlView *view, float xyz[3],
1635 				   float winx, float winy, float winz)
1636 {
1637   GLdouble model[16], project[16];
1638   GLint viewport[4];
1639   GLdouble xyzGL[3], winGL[3];
1640 
1641   g_return_if_fail(view);
1642 
1643   glGetDoublev(GL_MODELVIEW_MATRIX, model);
1644   glGetDoublev(GL_PROJECTION_MATRIX, project);
1645   glGetIntegerv(GL_VIEWPORT, viewport);
1646 
1647   winGL[0] = (GLdouble)winx;
1648   winGL[1] = (GLdouble)(view->window.height - winy);
1649   winGL[2] = (GLdouble)winz;
1650   gluUnProject(winGL[0], winGL[1], winGL[2], model, project, viewport,
1651 	       xyzGL, xyzGL + 1, xyzGL + 2);
1652   xyz[0] = (float)xyzGL[0];
1653   xyz[1] = (float)xyzGL[1];
1654   xyz[2] = (float)xyzGL[2];
1655   DBG_fprintf(stderr, "OpenGL View: get real coordinates from %gx%gx%g: %gx%gx%g.\n",
1656 	      winx, winy, winz, xyz[0], xyz[1], xyz[2]);
1657 }
1658 
1659 /**
1660  * visu_gl_view_alignToAxis:
1661  * @view: a #VisuGlView object.
1662  * @axis: an axis.
1663  *
1664  * Rotate the view to align it with the given box axis.
1665  *
1666  * Since: 3.8
1667  **/
visu_gl_view_alignToAxis(VisuGlView * view,ToolXyzDir axis)1668 void visu_gl_view_alignToAxis(VisuGlView *view, ToolXyzDir axis)
1669 {
1670   float red[3], xyz[3], xyz_[3], sph[3];
1671   int permut[3][3] = {{1,2,0}, {2,0,1}, {0,1,2}};
1672 
1673   g_return_if_fail(VISU_IS_GL_VIEW(view));
1674 
1675   if (!view->priv->box)
1676     return;
1677 
1678   red[0] = (axis == TOOL_XYZ_X) ? 1.f : 0.f;
1679   red[1] = (axis == TOOL_XYZ_Y) ? 1.f : 0.f;
1680   red[2] = (axis == TOOL_XYZ_Z) ? 1.f : 0.f;
1681   visu_box_convertBoxCoordinatestoXYZ(view->priv->box, xyz, red);
1682   xyz_[0] = xyz[permut[view->camera.upAxis][0]];
1683   xyz_[1] = xyz[permut[view->camera.upAxis][1]];
1684   xyz_[2] = xyz[permut[view->camera.upAxis][2]];
1685   tool_matrix_cartesianToSpherical(sph, xyz_);
1686 
1687   g_object_set(view, "theta", sph[TOOL_MATRIX_SPHERICAL_THETA],
1688                "phi", sph[TOOL_MATRIX_SPHERICAL_PHI], NULL);
1689 }
1690 
1691 /**
1692  * visu_gl_view_setThetaPhiOmega:
1693  * @view: a #VisuGlView object ;
1694  * @valueTheta: a floatinf point value in degrees ;
1695  * @valuePhi: a floating point value in degrees ;
1696  * @valueOmega: a floating point value in degrees ;
1697  * @mask: to specified what values will be changed.
1698  *
1699  * This method is used to change the camera orientation for the given @view.
1700  * If necessary, this method will emit the 'ThetaPhiOmegaChanged' signal.
1701  *
1702  * Returns: TRUE if value is actually changed.
1703  */
1704 
visu_gl_view_setThetaPhiOmega(VisuGlView * view,float valueTheta,float valuePhi,float valueOmega,int mask)1705 gboolean visu_gl_view_setThetaPhiOmega(VisuGlView *view, float valueTheta,
1706                                        float valuePhi, float valueOmega, int mask)
1707 {
1708   int res;
1709 
1710   g_return_val_if_fail(VISU_IS_GL_VIEW(view), FALSE);
1711 
1712   DBG_fprintf(stderr, "OpenGL View: changing theta / phi / omega (%d).\n", mask);
1713   DBG_fprintf(stderr, "OpenGL View: to %g / %g / %g.\n",
1714               valueTheta, valuePhi, valueOmega);
1715   res = visu_gl_camera_setThetaPhiOmega(&view->camera,
1716                                         valueTheta, valuePhi, valueOmega, mask);
1717   DBG_fprintf(stderr, "OpenGL View: to %g / %g / %g.\n",
1718               view->camera.theta, view->camera.phi, view->camera.omega);
1719   if (res & VISU_GL_CAMERA_THETA)
1720     g_object_notify_by_pspec(G_OBJECT(view), properties[THETA_PROP]);
1721   if (res & VISU_GL_CAMERA_PHI)
1722     g_object_notify_by_pspec(G_OBJECT(view), properties[PHI_PROP]);
1723   if (res & VISU_GL_CAMERA_OMEGA)
1724     g_object_notify_by_pspec(G_OBJECT(view), properties[OMEGA_PROP]);
1725   if (res)
1726     {
1727       anglesDefault[0] = view->camera.theta;
1728       anglesDefault[1] = view->camera.phi;
1729       anglesDefault[2] = view->camera.omega;
1730       visu_gl_camera_modelize(&view->camera);
1731       g_signal_emit(view, _signals[CHANGED_SIGNAL], 0);
1732     }
1733 
1734   return (res > 0);
1735 }
1736 /**
1737  * visu_gl_view_setXsYs:
1738  * @view: a #VisuGlView object ;
1739  * @valueX: a floatinf point value in the bounding box scale
1740  *          (1 is the size of the bounding box) ;
1741  * @valueY: a floating point value in bounding box scale ;
1742  * @mask: to specified what values will be changed.
1743  *
1744  * This method is used to change the camera position for the given @view.
1745  * If necessary, this method will emit the 'XsYsChanged' signal.
1746  *
1747  * Returns: TRUE if value is actually changed.
1748  */
visu_gl_view_setXsYs(VisuGlView * view,float valueX,float valueY,int mask)1749 gboolean visu_gl_view_setXsYs(VisuGlView *view,
1750                               float valueX, float valueY, int mask)
1751 {
1752   int res;
1753 
1754   g_return_val_if_fail(VISU_IS_GL_VIEW(view), FALSE);
1755 
1756   res = visu_gl_camera_setXsYs(&view->camera, valueX, valueY, mask);
1757   if (res & VISU_GL_CAMERA_XS)
1758     g_object_notify_by_pspec(G_OBJECT(view), properties[XS_PROP]);
1759   if (res & VISU_GL_CAMERA_YS)
1760     g_object_notify_by_pspec(G_OBJECT(view), properties[YS_PROP]);
1761   if (res)
1762     {
1763       translatDefault[0] = view->camera.xs;
1764       translatDefault[1] = view->camera.ys;
1765       visu_gl_window_project(&view->window, &view->camera);
1766       g_signal_emit(view, _signals[CHANGED_SIGNAL], 0);
1767     }
1768 
1769   return (res > 0);
1770 }
1771 
1772 /**
1773  * visu_gl_view_setGross:
1774  * @view: a #VisuGlView object ;
1775  * @value: a positive floating point value.
1776  *
1777  * This method is used to change the camera zoom for the given @view.
1778  * If necessary, this method will emit the 'GrossChanged' signal and
1779  * the 'FacetteChangedChanged' signal.
1780  *
1781  * Returns: TRUE if value is actually changed.
1782  */
visu_gl_view_setGross(VisuGlView * view,float value)1783 gboolean visu_gl_view_setGross(VisuGlView *view, float value)
1784 {
1785   gboolean res;
1786 
1787   g_return_val_if_fail(VISU_IS_GL_VIEW(view), FALSE);
1788 
1789   res = visu_gl_camera_setGross(&view->camera, value);
1790   if (res)
1791     {
1792       grossDefault = view->camera.gross;
1793 
1794       g_object_notify_by_pspec(G_OBJECT(view), properties[GROSS_PROP]);
1795       g_signal_emit(view, _signals[FACETTES_CHANGED_SIGNAL],
1796 		    0, NULL);
1797 
1798       visu_gl_window_project(&view->window, &view->camera);
1799       g_signal_emit(view, _signals[CHANGED_SIGNAL], 0);
1800     }
1801   return res;
1802 }
1803 
1804 /**
1805  * visu_gl_view_setPersp:
1806  * @view: a #VisuGlView object ;
1807  * @value: a positive floating point value (> 1.1).
1808  *
1809  * This method is used to change the camera perspective for the given @view.
1810  * If necessary, this method will emit the 'PerspChanged' signal and
1811  * the 'FacetteChangedChanged' signal.
1812  *
1813  * Returns: TRUE if value is actually changed.
1814  */
visu_gl_view_setPersp(VisuGlView * view,float value)1815 gboolean visu_gl_view_setPersp(VisuGlView *view, float value)
1816 {
1817   gboolean res;
1818 
1819   g_return_val_if_fail(VISU_IS_GL_VIEW(view), FALSE);
1820 
1821   res = visu_gl_camera_setPersp(&view->camera, value);
1822   if (res)
1823     {
1824       perspDefault = view->camera.d_red;
1825 
1826       DBG_fprintf(stderr, "Visu GlView: emitting signals on persp changed.\n");
1827       g_object_notify_by_pspec(G_OBJECT(view), properties[PERSP_PROP]);
1828       g_signal_emit(view, _signals[FACETTES_CHANGED_SIGNAL],
1829 		    0, NULL);
1830 
1831       visu_gl_camera_modelize(&view->camera);
1832       visu_gl_window_project(&view->window, &view->camera);
1833       g_signal_emit(view, _signals[CHANGED_SIGNAL], 0);
1834     }
1835 
1836   return res;
1837 }
1838 
1839 /**
1840  * visu_gl_view_setViewport:
1841  * @view: a #VisuGlView object ;
1842  * @width: the new horizontal size ;
1843  * @height: the new vertical size.
1844  *
1845  * It changes the size of the OpenGl area and reccompute the OpenGL viewport.
1846  * Warning : it doesn't change the size of the window.
1847  *
1848  * Returns: TRUE if value is actually changed.
1849  */
visu_gl_view_setViewport(VisuGlView * view,guint width,guint height)1850 gboolean visu_gl_view_setViewport(VisuGlView *view, guint width, guint height)
1851 {
1852   gboolean res;
1853 
1854   g_return_val_if_fail(VISU_IS_GL_VIEW(view), FALSE);
1855 
1856   res = visu_gl_window_setViewport(&view->window, width, height);
1857   if (res)
1858     {
1859       g_signal_emit(view, _signals[WIDTH_HEIGHT_CHANGED_SIGNAL],
1860 		    0, NULL);
1861       g_signal_emit(view, _signals[FACETTES_CHANGED_SIGNAL],
1862 		    0, NULL);
1863 
1864       visu_gl_window_project(&view->window, &view->camera);
1865       g_signal_emit(view, _signals[CHANGED_SIGNAL], 0);
1866     }
1867 
1868   return res;
1869 }
1870 /**
1871  * visu_gl_view_setRefLength:
1872  * @view: a #VisuGlView object ;
1873  * @lg: the new value.
1874  * @units: the unit to read @lg with.
1875  *
1876  * This method is used to change the camera reference length for the given @view.
1877  * If necessary, this method will modelize and emit the 'RefLengthChanged' signal.
1878  *
1879  * Returns: TRUE if value is actually changed.
1880  */
visu_gl_view_setRefLength(VisuGlView * view,float lg,ToolUnits units)1881 gboolean visu_gl_view_setRefLength(VisuGlView *view, float lg, ToolUnits units)
1882 {
1883   gboolean res;
1884 
1885   g_return_val_if_fail(VISU_IS_GL_VIEW(view), FALSE);
1886 
1887   res = visu_gl_camera_setRefLength(&view->camera, lg, units);
1888   if (res)
1889     {
1890       g_signal_emit(view, _signals[REF_LENGTH_CHANGED_SIGNAL],
1891                     0, NULL);
1892       g_signal_emit(view, _signals[FACETTES_CHANGED_SIGNAL],
1893 		    0, NULL);
1894       visu_gl_camera_modelize(&view->camera);
1895       g_signal_emit(view, _signals[CHANGED_SIGNAL], 0);
1896     }
1897 
1898   return res;
1899 }
1900 /**
1901  * visu_gl_view_setObjectRadius:
1902  * @view: a #VisuGlView object ;
1903  * @lg: the new value.
1904  * @units: the unit to read @lg with.
1905  *
1906  * This method is used to change the window frustum for the given @view.
1907  * If necessary, this method will project and emit the
1908  * 'NearFarChanged' signal.
1909  *
1910  * Since: 3.7
1911  *
1912  * Returns: TRUE if value is actually changed.
1913  */
visu_gl_view_setObjectRadius(VisuGlView * view,float lg,ToolUnits units)1914 gboolean visu_gl_view_setObjectRadius(VisuGlView *view, float lg, ToolUnits units)
1915 {
1916   gboolean res;
1917 
1918   g_return_val_if_fail(VISU_IS_GL_VIEW(view), FALSE);
1919 
1920   res = visu_gl_window_setAddLength(&view->window, lg, units);
1921   if (res)
1922     {
1923       visu_gl_window_project(&view->window, &view->camera);
1924       g_signal_emit(view, _signals[CHANGED_SIGNAL], 0);
1925     }
1926 
1927   return res;
1928 }
1929 
1930 /**
1931  * visu_gl_view_rotateBox:
1932  * @view: a valid #VisuGlView object ;
1933  * @dTheta: a float value ;
1934  * @dPhi: a float value ;
1935  * @angles: (out) (array fixed-size=2): a storing area two floats.
1936  *
1937  * This methods rotates the camera of the given @view of (@dTheta, @dPhi) and
1938  * put new theta and phi angles in @angles, first being theta and second phi.
1939  */
visu_gl_view_rotateBox(VisuGlView * view,float dTheta,float dPhi,float angles[2])1940 void visu_gl_view_rotateBox(VisuGlView *view, float dTheta, float dPhi, float angles[2])
1941 {
1942   GValue val = G_VALUE_INIT;
1943 
1944   g_return_if_fail(view && angles);
1945 
1946   g_value_init(&val, G_TYPE_DOUBLE);
1947   if (visu_animation_isRunning(view->priv->theta_anim))
1948     {
1949       visu_animation_getTo(view->priv->theta_anim, &val);
1950       angles[0] = g_value_get_double(&val) + dTheta;
1951     }
1952   else
1953     angles[0] = view->camera.theta + dTheta;
1954   if (visu_animation_isRunning(view->priv->phi_anim))
1955     {
1956       visu_animation_getTo(view->priv->phi_anim, &val);
1957       angles[1] = g_value_get_double(&val) + dPhi;
1958     }
1959   else
1960     angles[1] = view->camera.phi + dPhi;
1961 }
1962 /**
1963  * visu_gl_view_rotateCamera:
1964  * @view: a valid #VisuGlView object ;
1965  * @dTheta: a float value ;
1966  * @dPhi: a float value ;
1967  * @angles: (out) (array fixed-size=3): a storing area three floats.
1968  *
1969  * This methods rotates the camera of the given @view of (@dTheta, @dPhi).
1970  * @dTheta is taken as displacement along camera x axis and dPhi along camera y axis.
1971  * Then, computations are done to obtain new theta, phi and omega values. They are
1972  * put in @angles, first being theta, second phi and third omega.
1973  */
visu_gl_view_rotateCamera(VisuGlView * view,float dTheta,float dPhi,float angles[3])1974 void visu_gl_view_rotateCamera(VisuGlView *view, float dTheta, float dPhi, float angles[3])
1975 {
1976   double cth, sth, cph, sph, com, som;
1977   double cdth, sdth, cdph, sdph;
1978   double Theta, Phi, Omega;
1979   #define RADTODEG 57.29577951
1980   float MinRprime[3], MinR[3];
1981   float Mspherical[3];
1982   float matPhi[3][3], matTheta[3][3], matOmega[3][3], matdPhi[3][3], matdTheta[3][3];
1983   float matPhiPrime[3][3], matThetaPrime[3][3];
1984   float matRprime2R[3][3];
1985   float matRes[3][3], matRes2[3][3];
1986 
1987   g_return_if_fail(view && angles);
1988 
1989   cth = cos(view->camera.theta * TOOL_PI180);
1990   sth = sin(view->camera.theta * TOOL_PI180);
1991   cph = cos(view->camera.phi * TOOL_PI180);
1992   sph = sin(view->camera.phi * TOOL_PI180);
1993   com = cos(view->camera.omega * TOOL_PI180);
1994   som = sin(view->camera.omega * TOOL_PI180);
1995 
1996   cdth = cos(dTheta * TOOL_PI180);
1997   sdth = sin(dTheta * TOOL_PI180);
1998   cdph = cos(dPhi * TOOL_PI180);
1999   sdph = sin(dPhi * TOOL_PI180);
2000 
2001 
2002   matPhi[0][0] = cph;
2003   matPhi[1][0] = sph;
2004   matPhi[2][0] = 0.;
2005   matPhi[0][1] = -sph;
2006   matPhi[1][1] = cph;
2007   matPhi[2][1] = 0.;
2008   matPhi[0][2] = 0.;
2009   matPhi[1][2] = 0.;
2010   matPhi[2][2] = 1.;
2011 
2012   matTheta[0][0] = cth;
2013   matTheta[1][0] = 0.;
2014   matTheta[2][0] = -sth;
2015   matTheta[0][1] = 0.;
2016   matTheta[1][1] = 1.;
2017   matTheta[2][1] = 0.;
2018   matTheta[0][2] = sth;
2019   matTheta[1][2] = 0.;
2020   matTheta[2][2] = cth;
2021 
2022   matOmega[0][0] = com;
2023   matOmega[1][0] = som;
2024   matOmega[2][0] = 0.;
2025   matOmega[0][1] = -som;
2026   matOmega[1][1] = com;
2027   matOmega[2][1] = 0.;
2028   matOmega[0][2] = 0.;
2029   matOmega[1][2] = 0.;
2030   matOmega[2][2] = 1.;
2031 
2032   matdPhi[0][0] = 1.;
2033   matdPhi[1][0] = 0.;
2034   matdPhi[2][0] = 0.;
2035   matdPhi[0][1] = 0.;
2036   matdPhi[1][1] = cdph;
2037   matdPhi[2][1] = -sdph;
2038   matdPhi[0][2] = 0.;
2039   matdPhi[1][2] = sdph;
2040   matdPhi[2][2] = cdph;
2041 
2042   matdTheta[0][0] = cdth;
2043   matdTheta[1][0] = 0.;
2044   matdTheta[2][0] = -sdth;
2045   matdTheta[0][1] = 0.;
2046   matdTheta[1][1] = 1.;
2047   matdTheta[2][1] = 0.;
2048   matdTheta[0][2] = sdth;
2049   matdTheta[1][2] = 0.;
2050   matdTheta[2][2] = cdth;
2051 
2052   tool_matrix_productMatrix(matRes, matdPhi, matdTheta);
2053   tool_matrix_productMatrix(matRes2, matOmega, matRes);
2054   tool_matrix_productMatrix(matRes, matTheta, matRes2);
2055   tool_matrix_productMatrix(matRprime2R, matPhi, matRes);
2056 
2057   MinRprime[0] = 0.;
2058   MinRprime[1] = 0.;
2059   MinRprime[2] = 1.;
2060   tool_matrix_productVector(MinR, matRprime2R, MinRprime);
2061 /*   fprintf(stderr, "M : %f %f %f -> %f\n", MinR[0], MinR[1], MinR[2], */
2062 /* 	  MinR[0]*MinR[0] + MinR[1]*MinR[1] + MinR[2]*MinR[2]); */
2063 
2064 /*   cartesian_to_spherical(Mspherical, MinR); */
2065   Mspherical[0] = sqrt(MinR[0]*MinR[0] + MinR[1]*MinR[1] + MinR[2]*MinR[2]);
2066   if (MinR[1] == 0 && MinR[0] == 0)
2067     {
2068       Mspherical[1] = (MinR[2] > 0.)?0.:180.;
2069       Mspherical[2] = view->camera.phi;
2070     }
2071   else
2072     {
2073       Mspherical[1] = acos(MinR[2] / Mspherical[0]) * RADTODEG;
2074       if (MinR[0] == 0.)
2075 	Mspherical[2] = (MinR[1] > 0.)?90.:-90.;
2076       else
2077 	{
2078 	  Mspherical[2] = atan(MinR[1] / MinR[0]) * RADTODEG;
2079 	  if (MinR[0] < 0.)
2080 	    Mspherical[2] += 180.;
2081 	}
2082     }
2083 /*   fprintf(stderr, "avant %f %f\n", Mspherical[1], Mspherical[2]); */
2084   while (Mspherical[1] - view->camera.theta < -90.)
2085     Mspherical[1] += 360.;
2086   while (Mspherical[1] - view->camera.theta > 90.)
2087     Mspherical[1] -= 360.;
2088   while (Mspherical[2] - view->camera.phi < -90.)
2089     Mspherical[2] += 360.;
2090   while (Mspherical[2] - view->camera.phi > 90.)
2091     Mspherical[2] -= 360.;
2092 /*   fprintf(stderr, "après %f %f\n", Mspherical[1], Mspherical[2]); */
2093 
2094   Theta = Mspherical[1];
2095   Phi = Mspherical[2];
2096 
2097 /*   fprintf(stderr, "%f %f, %f %f\n", view->camera.theta, view->camera.phi, Theta, Phi); */
2098 /*   fprintf(stderr, "%f %f, %f %f\n", dTheta, dPhi, Theta - view->camera.theta, Phi -  view->camera.phi); */
2099 
2100   cth = cos(Theta * TOOL_PI180);
2101   sth = sin(Theta * TOOL_PI180);
2102   cph = cos(Phi * TOOL_PI180);
2103   sph = sin(Phi * TOOL_PI180);
2104 
2105   matPhiPrime[0][0] = cph;
2106   matPhiPrime[1][0] = -sph;
2107   matPhiPrime[2][0] = 0.;
2108   matPhiPrime[0][1] = sph;
2109   matPhiPrime[1][1] = cph;
2110   matPhiPrime[2][1] = 0.;
2111   matPhiPrime[0][2] = 0.;
2112   matPhiPrime[1][2] = 0.;
2113   matPhiPrime[2][2] = 1.;
2114 
2115   matThetaPrime[0][0] = cth;
2116   matThetaPrime[1][0] = 0.;
2117   matThetaPrime[2][0] = sth;
2118   matThetaPrime[0][1] = 0.;
2119   matThetaPrime[1][1] = 1.;
2120   matThetaPrime[2][1] = 0.;
2121   matThetaPrime[0][2] = -sth;
2122   matThetaPrime[1][2] = 0.;
2123   matThetaPrime[2][2] = cth;
2124 
2125   tool_matrix_productMatrix(matRes2, matPhiPrime, matRprime2R);
2126   tool_matrix_productMatrix(matRes, matThetaPrime, matRes2);
2127 
2128   MinRprime[0] = 0.;
2129   MinRprime[1] = 1.;
2130   MinRprime[2] = 0.;
2131   tool_matrix_productVector(MinR, matRes, MinRprime);
2132 /*   fprintf(stderr, "vect u : %f %f %f -> %f\n", MinR[0], MinR[1], MinR[2], */
2133 /* 	  MinR[0]*MinR[0] + MinR[1]*MinR[1] + MinR[2]*MinR[2]); */
2134   Omega = acos(CLAMP(MinR[1], -1.f, 1.f)) * RADTODEG;
2135   if (MinR[0] > 0.)
2136     Omega = -Omega;
2137   while (Omega - view->camera.omega < -90.)
2138     Omega += 360.;
2139   while (Omega - view->camera.omega > 90.)
2140     Omega -= 360.;
2141 
2142   /*   fprintf(stderr, "Theta phi omega : %f %f %f\n", Theta, Phi, Omega); */
2143   angles[0] = Theta;
2144   angles[1] = Phi;
2145   angles[2] = Omega;
2146 }
2147 
2148 /***************************/
2149 /* Dealing with resources. */
2150 /***************************/
exportParametersVisuGlView(GString * data,VisuData * dataObj _U_)2151 static void exportParametersVisuGlView(GString *data, VisuData *dataObj _U_)
2152 {
2153   g_string_append_printf(data, "# %s\n", DESC_PARAMETER_OPENGL_DETAILS);
2154   g_string_append_printf(data, "%s: %d\n\n", FLAG_PARAMETER_OPENGL_DETAILS,
2155                          (int)(_defaultDetails));
2156 
2157   g_string_append_printf(data, "# %s\n", DESC_PARAMETER_AUTO_ADJUST);
2158   g_string_append_printf(data, "%s: %d\n\n", FLAG_PARAMETER_AUTO_ADJUST, autoAdjustDefault);
2159 }
onEntryPrecision(VisuGlView * view,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)2160 static void onEntryPrecision(VisuGlView *view, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
2161 {
2162   visu_gl_view_setPrecision(view, _defaultDetails / 100.f);
2163 }
onEntryAngles(VisuGlView * view,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)2164 static void onEntryAngles(VisuGlView *view, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
2165 {
2166   visu_gl_view_setThetaPhiOmega
2167     (view, anglesDefault[0], anglesDefault[1], anglesDefault[2],
2168      VISU_GL_CAMERA_THETA | VISU_GL_CAMERA_PHI | VISU_GL_CAMERA_OMEGA);
2169 }
onEntryTrans(VisuGlView * view,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)2170 static void onEntryTrans(VisuGlView *view, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
2171 {
2172   visu_gl_view_setXsYs(view, translatDefault[0], translatDefault[1],
2173                        VISU_GL_CAMERA_XS | VISU_GL_CAMERA_YS);
2174 }
onEntryGross(VisuGlView * view,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)2175 static void onEntryGross(VisuGlView *view, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
2176 {
2177   visu_gl_view_setGross(view, grossDefault);
2178 }
onEntryPersp(VisuGlView * view,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)2179 static void onEntryPersp(VisuGlView *view, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
2180 {
2181   visu_gl_view_setPersp(view, perspDefault);
2182 }
exportResourcesVisuGlView(GString * data,VisuData * dataObj _U_)2183 static void exportResourcesVisuGlView(GString *data, VisuData *dataObj _U_)
2184 {
2185   visu_config_file_exportComment(data, DESC_RESOURCE_OPENGL_ANGLES);
2186   visu_config_file_exportEntry(data, FLAG_RESOURCE_OPENGL_ANGLES, NULL,
2187                                "%9.3f %9.3f %9.3f",
2188                                anglesDefault[0], anglesDefault[1], anglesDefault[2]);
2189 
2190   visu_config_file_exportComment(data, DESC_RESOURCE_OPENGL_TRANSLAT);
2191   visu_config_file_exportEntry(data, FLAG_RESOURCE_OPENGL_TRANSLAT, NULL,
2192                                "%9.3f %9.3f",
2193                                translatDefault[0], translatDefault[1]);
2194 
2195   visu_config_file_exportComment(data, DESC_RESOURCE_OPENGL_GROSS);
2196   visu_config_file_exportEntry(data, FLAG_RESOURCE_OPENGL_GROSS, NULL,
2197                                "%9.3f", grossDefault);
2198 
2199   visu_config_file_exportComment(data, DESC_RESOURCE_OPENGL_PERSP);
2200   visu_config_file_exportEntry(data, FLAG_RESOURCE_OPENGL_PERSP, NULL,
2201                                "%9.3f", perspDefault);
2202 
2203   visu_config_file_exportComment(data, "");
2204 }
2205 
2206