1 /* camera.c - Managing the Povray camera in preview mode, from OpenGL settings
2 *
3 * Copyright (C) 2003 Patrice St-Gelais
4 * patrstg@users.sourceforge.net
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include <GL/gl.h>
22 #include <GL/glu.h>
23 #include <gtk/gtk.h>
24 #include <locale.h>
25
26 #include "gl_preview.h"
27
28 /* These variables are now defined in globals.h and the RC file
29
30 #define DISTANCE_INIT 2.5
31 #define DEFAULT_ANGLE 55 // Povray standard (width), translates to ~38 in GL standard (height)
32 // #define DEFAULT_ROT_Y 180
33 #define DEFAULT_ROT_Y 0
34 // #define DEFAULT_ROT_X 140
35 #define DEFAULT_ROT_X 50
36 #define ASPECT_RATIO 1.3333333333
37
38 */
39
40 extern gint DEFAULT_ANGLE[], DEFAULT_ROT_X[], DEFAULT_ROT_Y[];
41 extern gfloat DISTANCE_INIT[], ASPECT_RATIO[], RIGHT_LEFT_DISPL[], HEIGHT[];
42
43 // Camera_def is the default camera, from which others are reset
44 // Camera[NBCAMERAS] is used for keeping the current parameters between each new document
45
46 camera_struct camera_def = {FALSE, 0, 0, 0.0, 0.0, 0.0, 0, 0.0} ;
47
48 camera_struct cameras[NBCAMERAS] ;
49
50 /*************************************************************************************************/
51 // Camera management
52
53 // How it works (2003-10-12)
54 // 1. The preview settings (translation and rotation of the HF) are translated
55 // into Povray camera parameters (rotation of the camera around the HF,
56 // negative translation). Povray lights are not rotated nor translated, as of v. 0.12.
57 // 2. Each document has 5 cameras.
58 // 3. Each camera can be reset to default values (in "camera_def").
59 // 4. The 5 cameras of a newly created document are copied from the last active document.
60 // 5. The 5 cameras of the last active document are saved in a the geomorph_session file
61 //
62 // camera1, camera2... camera5 are used as buffers for "transmitting" the cameras settings
63 // between the current document and the newly created ones
64 // ==> each time we activate a document, its cameras must be copied into these buffers
65
copy_camera(camera_struct * camera_out,camera_struct * camera_in)66 void copy_camera (camera_struct *camera_out, camera_struct *camera_in) {
67 memcpy(camera_out, camera_in, sizeof(camera_struct));
68 }
69
init_default_camera()70 void init_default_camera ( ) {
71 if (camera_def.init)
72 return;
73 camera_def.init = TRUE;
74 camera_def.rot_x = DEFAULT_ROT_X[0];
75 camera_def.rot_y = DEFAULT_ROT_Y[0];
76 camera_def.distance = DISTANCE_INIT[0];
77 camera_def.translate_x = RIGHT_LEFT_DISPL[0];
78 camera_def.translate_y = HEIGHT[0];
79 camera_def.angle_w = DEFAULT_ANGLE[0];
80 camera_def.aspect_ratio = ASPECT_RATIO[0];
81 }
82
init_cameras()83 void init_cameras ( ) {
84 // Method initializing the camera buffers (array of NBCAMERAS cameras)
85 // with the default camera
86 gint i;
87 for (i=0; i<NBCAMERAS; i++) {
88 // Old way: initialize cameras from the default one
89 // copy_camera (&cameras[i],&camera_def);
90 // Now we can have default values for all the 5 cameras
91 cameras[i].init = TRUE;
92 cameras[i].rot_x = DEFAULT_ROT_X[i];
93 cameras[i].rot_y = DEFAULT_ROT_Y[i];
94 cameras[i].distance = DISTANCE_INIT[i];
95 cameras[i].translate_x = RIGHT_LEFT_DISPL[i];
96 cameras[i].translate_y = HEIGHT[i];
97 cameras[i].angle_w = DEFAULT_ANGLE[i];
98 cameras[i].aspect_ratio = ASPECT_RATIO[i];
99 }
100 }
101
print_default_camera()102 void print_default_camera () {
103
104 printf("DEFAULT CAMERA:\nINIT: %d;\nROT_X: %d;\nROT_Y: %d;\nDISTANCE: %5.3f;\n", camera_def.init, camera_def.rot_x, camera_def.rot_y, camera_def.distance);
105 printf("TRANSLATE_X: %5.3f;\nTRANSLATE_Y: %5.3f;\nANGLE_W: %d;\nASPECT_RATIO: %5.3f;\n", camera_def.translate_x, camera_def.translate_y, camera_def.angle_w, camera_def.aspect_ratio);
106
107 printf("DEFAULT_VALUES: \nROT_X: %d;\nROT_Y: %d;\nDISTANCE: %5.3f;\nANGLE_W: %d;\nASPECT_RATIO: %5.3f;\n", DEFAULT_ROT_X[0], DEFAULT_ROT_Y[0], DISTANCE_INIT[0], DEFAULT_ANGLE[0], ASPECT_RATIO[0]);
108 }
109
gl_save_camera_inc(camera_struct * camera)110 void gl_save_camera_inc (camera_struct * camera) {
111 // Public method
112 // Save the current camera parameters in "camera.inc" in the current directory
113
114 FILE *fin;
115 gchar *loc, *tmp, *msg_buf;
116 if (!(fin=fopen("camera.inc","wb"))) {
117 msg_buf = (gchar *) x_malloc(sizeof(gchar) + strlen("camera.inc") + strlen(_("Not able to open '%s' file for writing"))+5 , "const gchar (msg_buf - open file for writing)");
118 sprintf(msg_buf,_("Not able to open '%s' file for writing"),"camera.inc");
119 my_msg(msg_buf,WARNING);
120 }
121 else {
122 tmp = setlocale(LC_NUMERIC,NULL); // Povray uses "." as decimal separator instead of ","
123 loc = (gchar *) malloc(strlen(tmp)+1);
124 strcpy(loc,tmp);
125 setlocale(LC_NUMERIC,"C");
126 fprintf(fin,"#declare gl_angle = %d;\n",camera->angle_w);
127 fprintf(fin,"#declare aspect_ratio = %10.7f;\n",camera->aspect_ratio);
128 fprintf(fin,"#declare tr_x = %10.7f;\n",-camera->translate_x/2.0);
129 fprintf(fin,"#declare tr_y = %10.7f;\n",-camera->translate_y/2.0);
130 fprintf(fin,"#declare tr_z = %10.7f;\n", -(1.35+(camera->distance-2.5)/2.0));
131 fprintf(fin,"#declare rot_x = %d;\n",camera->rot_x);
132 fprintf(fin,"#declare rot_y = %d;\n",camera->rot_y);
133 fprintf(fin,"#declare rot_z = 0;\n");
134 setlocale(LC_NUMERIC,loc);
135 free(loc);
136 fclose(fin);
137 }
138 }
139
set_perspective(camera_struct * camera)140 void set_perspective (camera_struct *camera) {
141
142 // Set perspective
143 gfloat angle;
144
145 glMatrixMode(GL_PROJECTION);
146 glLoadIdentity();
147 // camera->angle_w is in the Povray standard (horizontal)
148 // gluPerspective() takes a vertical angle
149 angle = atanf( tanf(((gfloat) camera->angle_w)*PI/360.0)/camera->aspect_ratio);
150 gluPerspective(angle*360.0/PI,camera->aspect_ratio,0.1,20.0);
151
152 glMatrixMode(GL_MODELVIEW);
153 }
154
set_camera(gpointer glp,camera_struct * camera)155 void set_camera (gpointer glp, camera_struct *camera) {
156 gl_preview_struct *gl_preview = (gl_preview_struct *) glp;
157 gtk_adjustment_set_value(
158 GTK_ADJUSTMENT(gl_preview->adj_rot_y), camera->rot_y);
159 gtk_adjustment_set_value(
160 GTK_ADJUSTMENT(gl_preview->adj_rot_x), camera->rot_x);
161 gtk_adjustment_set_value(
162 GTK_ADJUSTMENT(gl_preview->adj_distance), camera->distance);
163 gtk_adjustment_set_value(
164 GTK_ADJUSTMENT(gl_preview->adj_translate_x), camera->translate_x);
165 gtk_adjustment_set_value(
166 GTK_ADJUSTMENT(gl_preview->adj_translate_y), camera->translate_y);
167 gtk_adjustment_set_value(
168 GTK_ADJUSTMENT(gl_preview->adj_angle_w), camera->angle_w);
169 set_perspective (camera);
170 gtk_widget_queue_draw(GTK_WIDGET(gl_preview->gl_area));
171 }
172
set_camera_callb(GtkWidget * wdg,gpointer data)173 void set_camera_callb (GtkWidget *wdg, gpointer data) {
174 // Sets the camera from the label of a radio button
175 gchar *txt;
176 gl_preview_struct *gl_preview = (gl_preview_struct *) data;
177
178 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
179 return;
180 gtk_label_get(GTK_LABEL(GTK_BIN(wdg)->child), &txt);
181
182 gl_preview->current_camera_id = atoi(txt);
183 if ( (gl_preview->current_camera_id<1) || (gl_preview->current_camera_id>NBCAMERAS))
184 gl_preview->current_camera_id = 1;
185
186 gl_preview->current_camera_id--; // current_camera_id is a C index
187
188 set_camera (gl_preview, gl_preview->cameras[gl_preview->current_camera_id]);
189 }
190
191