1 /******************************************************/
2 /* Apply mapping and shading on the whole input image */
3 /******************************************************/
4
5 #include "config.h"
6
7 #include <string.h>
8
9 #include <gtk/gtk.h>
10
11 #include <libgimp/gimp.h>
12 #include <libgimp/gimpui.h>
13
14 #include "map-object-main.h"
15 #include "map-object-image.h"
16 #include "map-object-shade.h"
17 #include "map-object-apply.h"
18
19 #include "libgimp/stdplugins-intl.h"
20
21
22 /*************/
23 /* Main loop */
24 /*************/
25
26 gdouble imat[4][4];
27 gfloat rotmat[16];
28 static gfloat a[16], b[16];
29
30 void
init_compute(void)31 init_compute (void)
32 {
33 gint i;
34
35 switch (mapvals.maptype)
36 {
37 case MAP_SPHERE:
38
39 /* Rotate the equator/northpole axis */
40 /* ================================= */
41
42 gimp_vector3_set (&mapvals.firstaxis, 0.0, 0.0, -1.0);
43 gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
44
45 gimp_vector3_rotate (&mapvals.firstaxis,
46 gimp_deg_to_rad (mapvals.alpha),
47 gimp_deg_to_rad (mapvals.beta),
48 gimp_deg_to_rad (mapvals.gamma));
49 gimp_vector3_rotate (&mapvals.secondaxis,
50 gimp_deg_to_rad (mapvals.alpha),
51 gimp_deg_to_rad (mapvals.beta),
52 gimp_deg_to_rad (mapvals.gamma));
53
54 /* Compute the 2D bounding box of the sphere spanned by the axis */
55 /* ============================================================= */
56
57 compute_bounding_box ();
58
59 get_ray_color = get_ray_color_sphere;
60
61 break;
62
63 case MAP_PLANE:
64
65 /* Rotate the plane axis */
66 /* ===================== */
67
68 gimp_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0);
69 gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
70 gimp_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0);
71
72 gimp_vector3_rotate (&mapvals.firstaxis,
73 gimp_deg_to_rad (mapvals.alpha),
74 gimp_deg_to_rad (mapvals.beta),
75 gimp_deg_to_rad (mapvals.gamma));
76 gimp_vector3_rotate (&mapvals.secondaxis,
77 gimp_deg_to_rad (mapvals.alpha),
78 gimp_deg_to_rad (mapvals.beta),
79 gimp_deg_to_rad (mapvals.gamma));
80
81 mapvals.normal = gimp_vector3_cross_product (&mapvals.firstaxis,
82 &mapvals.secondaxis);
83
84 if (mapvals.normal.z < 0.0)
85 gimp_vector3_mul (&mapvals.normal, -1.0);
86
87 /* Initialize intersection matrix */
88 /* ============================== */
89
90 imat[0][1] = -mapvals.firstaxis.x;
91 imat[1][1] = -mapvals.firstaxis.y;
92 imat[2][1] = -mapvals.firstaxis.z;
93
94 imat[0][2] = -mapvals.secondaxis.x;
95 imat[1][2] = -mapvals.secondaxis.y;
96 imat[2][2] = -mapvals.secondaxis.z;
97
98 imat[0][3] = mapvals.position.x - mapvals.viewpoint.x;
99 imat[1][3] = mapvals.position.y - mapvals.viewpoint.y;
100 imat[2][3] = mapvals.position.z - mapvals.viewpoint.z;
101
102 get_ray_color = get_ray_color_plane;
103
104 break;
105
106 case MAP_BOX:
107 get_ray_color = get_ray_color_box;
108
109 gimp_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0);
110 gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
111 gimp_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0);
112
113 ident_mat (rotmat);
114
115 rotatemat (mapvals.alpha, &mapvals.firstaxis, a);
116
117 matmul (a, rotmat, b);
118
119 memcpy (rotmat, b, sizeof (gfloat) * 16);
120
121 rotatemat (mapvals.beta, &mapvals.secondaxis, a);
122 matmul (a, rotmat, b);
123
124 memcpy (rotmat, b, sizeof (gfloat) * 16);
125
126 rotatemat (mapvals.gamma, &mapvals.normal, a);
127 matmul (a, rotmat, b);
128
129 memcpy (rotmat, b, sizeof (gfloat) * 16);
130
131 /* Set up pixel regions for the box face images */
132 /* ============================================ */
133
134 for (i = 0; i < 6; i++)
135 {
136 box_drawable_ids[i] = mapvals.boxmap_id[i];
137
138 box_buffers[i] = gimp_drawable_get_buffer (box_drawable_ids[i]);
139 }
140
141 break;
142
143 case MAP_CYLINDER:
144 get_ray_color = get_ray_color_cylinder;
145
146 gimp_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0);
147 gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
148 gimp_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0);
149
150 ident_mat (rotmat);
151
152 rotatemat (mapvals.alpha, &mapvals.firstaxis, a);
153
154 matmul (a, rotmat, b);
155
156 memcpy (rotmat, b, sizeof (gfloat) * 16);
157
158 rotatemat (mapvals.beta, &mapvals.secondaxis, a);
159 matmul (a, rotmat, b);
160
161 memcpy (rotmat, b, sizeof (gfloat) * 16);
162
163 rotatemat (mapvals.gamma, &mapvals.normal, a);
164 matmul (a, rotmat, b);
165
166 memcpy (rotmat, b, sizeof (gfloat) * 16);
167
168 /* Set up pixel regions for the cylinder cap images */
169 /* ================================================ */
170
171 for (i = 0; i < 2; i++)
172 {
173 cylinder_drawable_ids[i] = mapvals.cylindermap_id[i];
174
175 cylinder_buffers[i] = gimp_drawable_get_buffer (cylinder_drawable_ids[i]);
176 }
177 break;
178 }
179
180 max_depth = (gint) mapvals.maxdepth;
181 }
182
183 static void
render(gdouble x,gdouble y,GimpRGB * col,gpointer data)184 render (gdouble x,
185 gdouble y,
186 GimpRGB *col,
187 gpointer data)
188 {
189 GimpVector3 pos;
190
191 pos.x = x / (gdouble) width;
192 pos.y = y / (gdouble) height;
193 pos.z = 0.0;
194
195 *col = get_ray_color (&pos);
196 }
197
198 static void
show_progress(gint min,gint max,gint curr,gpointer data)199 show_progress (gint min,
200 gint max,
201 gint curr,
202 gpointer data)
203 {
204 gimp_progress_update ((gdouble) curr / (gdouble) max);
205 }
206
207 /**************************************************/
208 /* Performs map-to-sphere on the whole input image */
209 /* and updates or creates a new GIMP image. */
210 /**************************************************/
211
212 void
compute_image(void)213 compute_image (void)
214 {
215 gint xcount, ycount;
216 GimpRGB color;
217 glong progress_counter = 0;
218 GimpVector3 p;
219 gint32 new_image_id = -1;
220 gint32 new_layer_id = -1;
221 gboolean insert_layer = FALSE;
222
223 init_compute ();
224
225 if (mapvals.create_new_image)
226 {
227 new_image_id = gimp_image_new (width, height, GIMP_RGB);
228 }
229 else
230 {
231 new_image_id = image_id;
232 }
233
234 gimp_image_undo_group_start (new_image_id);
235
236 if (mapvals.create_new_image ||
237 mapvals.create_new_layer ||
238 (mapvals.transparent_background &&
239 ! gimp_drawable_has_alpha (output_drawable_id)))
240 {
241 gchar *layername[] = {_("Map to plane"),
242 _("Map to sphere"),
243 _("Map to box"),
244 _("Map to cylinder"),
245 _("Background")};
246
247 new_layer_id = gimp_layer_new (new_image_id,
248 layername[mapvals.create_new_image ? 4 :
249 mapvals.maptype],
250 width, height,
251 mapvals.transparent_background ?
252 GIMP_RGBA_IMAGE :
253 GIMP_RGB_IMAGE,
254 100.0,
255 gimp_image_get_default_new_layer_mode (new_image_id));
256
257 insert_layer = TRUE;
258 output_drawable_id = new_layer_id;
259 }
260
261 dest_buffer = gimp_drawable_get_shadow_buffer (output_drawable_id);
262
263 switch (mapvals.maptype)
264 {
265 case MAP_PLANE:
266 gimp_progress_init (_("Map to plane"));
267 break;
268 case MAP_SPHERE:
269 gimp_progress_init (_("Map to sphere"));
270 break;
271 case MAP_BOX:
272 gimp_progress_init (_("Map to box"));
273 break;
274 case MAP_CYLINDER:
275 gimp_progress_init (_("Map to cylinder"));
276 break;
277 }
278
279 if (! mapvals.antialiasing)
280 {
281 for (ycount = 0; ycount < height; ycount++)
282 {
283 for (xcount = 0; xcount < width; xcount++)
284 {
285 p = int_to_pos (xcount, ycount);
286 color = (* get_ray_color) (&p);
287 poke (xcount, ycount, &color, NULL);
288
289 progress_counter++;
290 }
291
292 gimp_progress_update ((gdouble) progress_counter /
293 (gdouble) maxcounter);
294 }
295 }
296 else
297 {
298 gimp_adaptive_supersample_area (0, 0,
299 width - 1, height - 1,
300 max_depth,
301 mapvals.pixelthreshold,
302 render,
303 NULL,
304 poke,
305 NULL,
306 show_progress,
307 NULL);
308 }
309
310 gimp_progress_update (1.0);
311
312 g_object_unref (source_buffer);
313 g_object_unref (dest_buffer);
314
315 if (insert_layer)
316 gimp_image_insert_layer (new_image_id, new_layer_id, -1, 0);
317
318 gimp_drawable_merge_shadow (output_drawable_id, TRUE);
319 gimp_drawable_update (output_drawable_id, 0, 0, width, height);
320
321 if (new_image_id != image_id)
322 {
323 gimp_display_new (new_image_id);
324 gimp_displays_flush ();
325 }
326
327 gimp_image_undo_group_end (new_image_id);
328 }
329