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