1 /*************************************************/
2 /* Compute a preview image and preview wireframe */
3 /*************************************************/
4
5 #include "config.h"
6
7 #include <gtk/gtk.h>
8
9 #include <libgimp/gimp.h>
10 #include <libgimp/gimpui.h>
11
12 #include "map-object-main.h"
13 #include "map-object-ui.h"
14 #include "map-object-image.h"
15 #include "map-object-apply.h"
16 #include "map-object-shade.h"
17 #include "map-object-preview.h"
18
19
20 gdouble mat[3][4];
21 gint lightx, lighty;
22
23 /* Protos */
24 /* ====== */
25
26 static void compute_preview (gint x,
27 gint y,
28 gint w,
29 gint h,
30 gint pw,
31 gint ph);
32 static void draw_light_marker (cairo_t *cr,
33 gint xpos,
34 gint ypos);
35 static void draw_line (cairo_t *cr,
36 gint startx,
37 gint starty,
38 gint pw,
39 gint ph,
40 gdouble cx1,
41 gdouble cy1,
42 gdouble cx2,
43 gdouble cy2,
44 GimpVector3 a,
45 GimpVector3 b);
46 static void draw_wireframe (cairo_t *cr,
47 gint startx,
48 gint starty,
49 gint pw,
50 gint ph);
51 static void draw_preview_wireframe (cairo_t *cr);
52 static void draw_wireframe_plane (cairo_t *cr,
53 gint startx,
54 gint starty,
55 gint pw,
56 gint ph);
57 static void draw_wireframe_sphere (cairo_t *cr,
58 gint startx,
59 gint starty,
60 gint pw,
61 gint ph);
62 static void draw_wireframe_box (cairo_t *cr,
63 gint startx,
64 gint starty,
65 gint pw,
66 gint ph);
67 static void draw_wireframe_cylinder (cairo_t *cr,
68 gint startx,
69 gint starty,
70 gint pw,
71 gint ph);
72
73 /**************************************************************/
74 /* Computes a preview of the rectangle starting at (x,y) with */
75 /* dimensions (w,h), placing the result in preview_RGB_data. */
76 /**************************************************************/
77
78 static void
compute_preview(gint x,gint y,gint w,gint h,gint pw,gint ph)79 compute_preview (gint x,
80 gint y,
81 gint w,
82 gint h,
83 gint pw,
84 gint ph)
85 {
86 gdouble xpostab[PREVIEW_WIDTH];
87 gdouble ypostab[PREVIEW_HEIGHT];
88 gdouble realw;
89 gdouble realh;
90 GimpVector3 p1, p2;
91 GimpRGB color;
92 GimpRGB lightcheck, darkcheck;
93 gint xcnt, ycnt, f1, f2;
94 guchar r, g, b;
95 glong index = 0;
96
97 init_compute ();
98
99 if (! preview_surface)
100 return;
101
102 p1 = int_to_pos (x, y);
103 p2 = int_to_pos (x + w, y + h);
104
105 /* First, compute the linear mapping (x,y,x+w,y+h) to (0,0,pw,ph) */
106 /* ============================================================== */
107
108 realw = (p2.x - p1.x);
109 realh = (p2.y - p1.y);
110
111 for (xcnt = 0; xcnt < pw; xcnt++)
112 xpostab[xcnt] = p1.x + realw * ((gdouble) xcnt / (gdouble) pw);
113
114 for (ycnt = 0; ycnt < ph; ycnt++)
115 ypostab[ycnt] = p1.y + realh * ((gdouble) ycnt / (gdouble) ph);
116
117 /* Compute preview using the offset tables */
118 /* ======================================= */
119
120 if (mapvals.transparent_background == TRUE)
121 {
122 gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0);
123 }
124 else
125 {
126 gimp_context_get_background (&background);
127 gimp_rgb_set_alpha (&background, 1.0);
128 }
129
130 gimp_rgba_set (&lightcheck,
131 GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, 1.0);
132 gimp_rgba_set (&darkcheck,
133 GIMP_CHECK_DARK, GIMP_CHECK_DARK, GIMP_CHECK_DARK, 1.0);
134 gimp_vector3_set (&p2, -1.0, -1.0, 0.0);
135
136 cairo_surface_flush (preview_surface);
137
138 for (ycnt = 0; ycnt < ph; ycnt++)
139 {
140 index = ycnt * preview_rgb_stride;
141 for (xcnt = 0; xcnt < pw; xcnt++)
142 {
143 p1.x = xpostab[xcnt];
144 p1.y = ypostab[ycnt];
145
146 p2 = p1;
147 color = (* get_ray_color) (&p1);
148
149 if (color.a < 1.0)
150 {
151 f1 = ((xcnt % 32) < 16);
152 f2 = ((ycnt % 32) < 16);
153 f1 = f1 ^ f2;
154
155 if (f1)
156 {
157 if (color.a == 0.0)
158 color = lightcheck;
159 else
160 gimp_rgb_composite (&color, &lightcheck,
161 GIMP_RGB_COMPOSITE_BEHIND);
162 }
163 else
164 {
165 if (color.a == 0.0)
166 color = darkcheck;
167 else
168 gimp_rgb_composite (&color, &darkcheck,
169 GIMP_RGB_COMPOSITE_BEHIND);
170 }
171 }
172
173 gimp_rgb_get_uchar (&color, &r, &g, &b);
174 GIMP_CAIRO_RGB24_SET_PIXEL((preview_rgb_data + index), r, g, b);
175 index += 4;
176 }
177 }
178 cairo_surface_mark_dirty (preview_surface);
179 }
180
181 /*************************************************/
182 /* Check if the given position is within the */
183 /* light marker. Return TRUE if so, FALSE if not */
184 /*************************************************/
185
186 gint
check_light_hit(gint xpos,gint ypos)187 check_light_hit (gint xpos,
188 gint ypos)
189 {
190 gdouble dx, dy, r;
191
192 if (mapvals.lightsource.type == POINT_LIGHT)
193 {
194 dx = (gdouble) lightx - xpos;
195 dy = (gdouble) lighty - ypos;
196 r = sqrt (dx * dx + dy * dy) + 0.5;
197
198 if ((gint) r > 7)
199 return FALSE;
200 else
201 return TRUE;
202 }
203
204 return FALSE;
205 }
206
207 /****************************************/
208 /* Draw a marker to show light position */
209 /****************************************/
210
211 static void
draw_light_marker(cairo_t * cr,gint xpos,gint ypos)212 draw_light_marker (cairo_t *cr,
213 gint xpos,
214 gint ypos)
215 {
216 GdkColor color;
217
218 if (mapvals.lightsource.type != POINT_LIGHT)
219 return;
220
221 cairo_set_line_width (cr, 1.0);
222
223 color.red = 0x0;
224 color.green = 0x4000;
225 color.blue = 0xFFFF;
226 gdk_cairo_set_source_color (cr, &color);
227
228 lightx = xpos;
229 lighty = ypos;
230
231 cairo_arc (cr, lightx, lighty, 7, 0, 2 * G_PI);
232 cairo_fill (cr);
233 }
234
235 static void
draw_lights(cairo_t * cr,gint startx,gint starty,gint pw,gint ph)236 draw_lights (cairo_t *cr,
237 gint startx,
238 gint starty,
239 gint pw,
240 gint ph)
241 {
242 gdouble dxpos, dypos;
243 gint xpos, ypos;
244
245 gimp_vector_3d_to_2d (startx, starty, pw, ph,
246 &dxpos, &dypos, &mapvals.viewpoint,
247 &mapvals.lightsource.position);
248 xpos = RINT (dxpos);
249 ypos = RINT (dypos);
250
251 if (xpos >= 0 && xpos <= PREVIEW_WIDTH &&
252 ypos >= 0 && ypos <= PREVIEW_HEIGHT)
253 {
254 draw_light_marker (cr, xpos, ypos);
255 }
256 }
257
258 /*************************************************/
259 /* Update light position given new screen coords */
260 /*************************************************/
261
262 void
update_light(gint xpos,gint ypos)263 update_light (gint xpos,
264 gint ypos)
265 {
266 gint startx, starty, pw, ph;
267
268 pw = PREVIEW_WIDTH * mapvals.zoom;
269 ph = PREVIEW_HEIGHT * mapvals.zoom;
270 startx = (PREVIEW_WIDTH - pw) / 2;
271 starty = (PREVIEW_HEIGHT - ph) / 2;
272
273 gimp_vector_2d_to_3d (startx, starty, pw, ph, xpos, ypos,
274 &mapvals.viewpoint, &mapvals.lightsource.position);
275
276 gtk_widget_queue_draw (previewarea);
277 }
278
279 /**************************/
280 /* Compute preview image. */
281 /**************************/
282
283 void
compute_preview_image(void)284 compute_preview_image (void)
285 {
286 GdkDisplay *display = gtk_widget_get_display (previewarea);
287 GdkCursor *cursor;
288 gint pw, ph;
289
290 pw = PREVIEW_WIDTH * mapvals.zoom;
291 ph = PREVIEW_HEIGHT * mapvals.zoom;
292
293 cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
294 gdk_window_set_cursor (gtk_widget_get_window (previewarea), cursor);
295 gdk_cursor_unref (cursor);
296
297 compute_preview (0, 0, width - 1, height - 1, pw, ph);
298
299 cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
300 gdk_window_set_cursor(gtk_widget_get_window (previewarea), cursor);
301 gdk_cursor_unref (cursor);
302 }
303
304 gboolean
preview_expose(GtkWidget * widget,GdkEventExpose * eevent)305 preview_expose (GtkWidget *widget,
306 GdkEventExpose *eevent)
307 {
308 gint startx, starty, pw, ph;
309 cairo_t *cr;
310
311 cr = gdk_cairo_create (eevent->window);
312
313 pw = PREVIEW_WIDTH * mapvals.zoom;
314 ph = PREVIEW_HEIGHT * mapvals.zoom;
315 startx = (PREVIEW_WIDTH - pw) / 2;
316 starty = (PREVIEW_HEIGHT - ph) / 2;
317
318 cairo_set_source_surface (cr, preview_surface, startx, starty);
319 cairo_rectangle (cr, startx, starty, pw, ph);
320 cairo_clip (cr);
321
322 cairo_paint (cr);
323
324 cairo_reset_clip (cr);
325
326 if (mapvals.showgrid)
327 draw_preview_wireframe (cr);
328
329 cairo_reset_clip (cr);
330 draw_lights (cr, startx, starty, pw, ph);
331
332 cairo_destroy (cr);
333
334 return FALSE;
335 }
336
337 /**************************/
338 /* Draw preview wireframe */
339 /**************************/
340
341 void
draw_preview_wireframe(cairo_t * cr)342 draw_preview_wireframe (cairo_t *cr)
343 {
344 gint startx, starty, pw, ph;
345
346 pw = PREVIEW_WIDTH * mapvals.zoom;
347 ph = PREVIEW_HEIGHT * mapvals.zoom;
348 startx = (PREVIEW_WIDTH - pw) / 2;
349 starty = (PREVIEW_HEIGHT - ph) / 2;
350
351 draw_wireframe (cr, startx, starty, pw, ph);
352 }
353
354 /****************************/
355 /* Draw a wireframe preview */
356 /****************************/
357
358 void
draw_wireframe(cairo_t * cr,gint startx,gint starty,gint pw,gint ph)359 draw_wireframe (cairo_t *cr,
360 gint startx,
361 gint starty,
362 gint pw,
363 gint ph)
364 {
365 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
366 switch (mapvals.maptype)
367 {
368 case MAP_PLANE:
369 draw_wireframe_plane (cr, startx, starty, pw, ph);
370 break;
371 case MAP_SPHERE:
372 draw_wireframe_sphere (cr, startx, starty, pw, ph);
373 break;
374 case MAP_BOX:
375 draw_wireframe_box (cr, startx, starty, pw, ph);
376 break;
377 case MAP_CYLINDER:
378 draw_wireframe_cylinder (cr, startx, starty, pw, ph);
379 break;
380 }
381 }
382
383 static void
draw_wireframe_plane(cairo_t * cr,gint startx,gint starty,gint pw,gint ph)384 draw_wireframe_plane (cairo_t *cr,
385 gint startx,
386 gint starty,
387 gint pw,
388 gint ph)
389 {
390 GimpVector3 v1, v2, a, b, c, d, dir1, dir2;
391 gint cnt;
392 gdouble x1, y1, x2, y2, fac;
393
394 cairo_rectangle (cr, startx, starty, pw, ph);
395 cairo_clip (cr);
396
397 /* Find rotated box corners */
398 /* ======================== */
399
400 gimp_vector3_set (&v1, 0.5, 0.0, 0.0);
401 gimp_vector3_set (&v2, 0.0, 0.5, 0.0);
402
403 gimp_vector3_rotate (&v1,
404 gimp_deg_to_rad (mapvals.alpha),
405 gimp_deg_to_rad (mapvals.beta),
406 gimp_deg_to_rad (mapvals.gamma));
407
408 gimp_vector3_rotate (&v2,
409 gimp_deg_to_rad (mapvals.alpha),
410 gimp_deg_to_rad (mapvals.beta),
411 gimp_deg_to_rad (mapvals.gamma));
412
413 dir1 = v1; gimp_vector3_normalize (&dir1);
414 dir2 = v2; gimp_vector3_normalize (&dir2);
415
416 fac = 1.0 / (gdouble) WIRESIZE;
417
418 gimp_vector3_mul (&dir1, fac);
419 gimp_vector3_mul (&dir2, fac);
420
421 gimp_vector3_add (&a, &mapvals.position, &v1);
422 gimp_vector3_sub (&b, &a, &v2);
423 gimp_vector3_add (&a, &a, &v2);
424 gimp_vector3_sub (&d, &mapvals.position, &v1);
425 gimp_vector3_sub (&d, &d, &v2);
426
427 c = b;
428
429 for (cnt = 0; cnt <= WIRESIZE; cnt++)
430 {
431 gimp_vector_3d_to_2d (startx, starty, pw, ph,
432 &x1, &y1, &mapvals.viewpoint, &a);
433 gimp_vector_3d_to_2d (startx, starty, pw, ph,
434 &x2, &y2, &mapvals.viewpoint, &b);
435
436 cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5);
437 cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5);
438
439 gimp_vector_3d_to_2d (startx, starty, pw, ph,
440 &x1, &y1, &mapvals.viewpoint, &c);
441 gimp_vector_3d_to_2d (startx, starty, pw, ph,
442 &x2, &y2, &mapvals.viewpoint, &d);
443
444 cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5);
445 cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5);
446
447 gimp_vector3_sub (&a, &a, &dir1);
448 gimp_vector3_sub (&b, &b, &dir1);
449 gimp_vector3_add (&c, &c, &dir2);
450 gimp_vector3_add (&d, &d, &dir2);
451 }
452
453 cairo_set_line_width (cr, 3.0);
454 cairo_stroke_preserve (cr);
455 cairo_set_line_width (cr, 1.0);
456 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
457 cairo_stroke (cr);
458 }
459
460 static void
draw_wireframe_sphere(cairo_t * cr,gint startx,gint starty,gint pw,gint ph)461 draw_wireframe_sphere (cairo_t *cr,
462 gint startx,
463 gint starty,
464 gint pw,
465 gint ph)
466 {
467 GimpVector3 p[2 * (WIRESIZE + 5)];
468 gint cnt, cnt2;
469 gdouble x1, y1, x2, y2, twopifac;
470
471 cairo_rectangle (cr, startx, starty, pw, ph);
472 cairo_clip (cr);
473
474 /* Compute wireframe points */
475 /* ======================== */
476
477 twopifac = (2.0 * G_PI) / WIRESIZE;
478
479 for (cnt = 0; cnt < WIRESIZE; cnt++)
480 {
481 p[cnt].x = mapvals.radius * cos ((gdouble) cnt * twopifac);
482 p[cnt].y = 0.0;
483 p[cnt].z = mapvals.radius * sin ((gdouble) cnt * twopifac);
484 gimp_vector3_rotate (&p[cnt],
485 gimp_deg_to_rad (mapvals.alpha),
486 gimp_deg_to_rad (mapvals.beta),
487 gimp_deg_to_rad (mapvals.gamma));
488 gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position);
489 }
490
491 p[cnt] = p[0];
492
493 for (cnt = WIRESIZE + 1; cnt < 2 * WIRESIZE + 1; cnt++)
494 {
495 p[cnt].x = mapvals.radius * cos ((gdouble) (cnt-(WIRESIZE+1))*twopifac);
496 p[cnt].y = mapvals.radius * sin ((gdouble) (cnt-(WIRESIZE+1))*twopifac);
497 p[cnt].z = 0.0;
498 gimp_vector3_rotate (&p[cnt],
499 gimp_deg_to_rad (mapvals.alpha),
500 gimp_deg_to_rad (mapvals.beta),
501 gimp_deg_to_rad (mapvals.gamma));
502 gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position);
503 }
504
505 p[cnt] = p[WIRESIZE+1];
506 cnt++;
507 cnt2 = cnt;
508
509 /* Find rotated axis */
510 /* ================= */
511
512 gimp_vector3_set (&p[cnt], 0.0, -0.35, 0.0);
513 gimp_vector3_rotate (&p[cnt],
514 gimp_deg_to_rad (mapvals.alpha),
515 gimp_deg_to_rad (mapvals.beta),
516 gimp_deg_to_rad (mapvals.gamma));
517 p[cnt+1] = mapvals.position;
518
519 gimp_vector3_set (&p[cnt+2], 0.0, 0.0, -0.35);
520 gimp_vector3_rotate (&p[cnt+2],
521 gimp_deg_to_rad (mapvals.alpha),
522 gimp_deg_to_rad (mapvals.beta),
523 gimp_deg_to_rad (mapvals.gamma));
524 p[cnt+3] = mapvals.position;
525
526 p[cnt + 4] = p[cnt];
527 gimp_vector3_mul (&p[cnt + 4], -1.0);
528 p[cnt + 5] = p[cnt + 1];
529
530 gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position);
531 gimp_vector3_add (&p[cnt + 2], &p[cnt + 2], &mapvals.position);
532 gimp_vector3_add (&p[cnt + 4], &p[cnt + 4], &mapvals.position);
533
534 /* Draw the circles (equator and zero meridian) */
535 /* ============================================ */
536
537 for (cnt = 0; cnt < cnt2 - 1; cnt++)
538 {
539 if (p[cnt].z > mapvals.position.z && p[cnt + 1].z > mapvals.position.z)
540 {
541 gimp_vector_3d_to_2d (startx, starty, pw, ph,
542 &x1, &y1, &mapvals.viewpoint, &p[cnt]);
543 gimp_vector_3d_to_2d (startx, starty, pw, ph,
544 &x2, &y2, &mapvals.viewpoint, &p[cnt + 1]);
545
546 cairo_move_to (cr, (gint) (x1 + 0.5) + 0.5, (gint) (y1 + 0.5) + 0.5);
547 cairo_line_to (cr, (gint) (x2 + 0.5) + 0.5, (gint) (y2 + 0.5) + 0.5);
548 }
549 }
550
551 /* Draw the axis (pole to pole and center to zero meridian) */
552 /* ======================================================== */
553
554 for (cnt = 0; cnt < 3; cnt++)
555 {
556 gimp_vector_3d_to_2d (startx, starty, pw, ph,
557 &x1, &y1, &mapvals.viewpoint, &p[cnt2]);
558 gimp_vector_3d_to_2d (startx, starty, pw, ph,
559 &x2, &y2, &mapvals.viewpoint, &p[cnt2 + 1]);
560
561 cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5);
562 cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5);
563
564 cnt2 += 2;
565 }
566
567 cairo_set_line_width (cr, 3.0);
568 cairo_stroke_preserve (cr);
569 cairo_set_line_width (cr, 1.0);
570 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
571 cairo_stroke (cr);
572 }
573
574 static void
draw_line(cairo_t * cr,gint startx,gint starty,gint pw,gint ph,gdouble cx1,gdouble cy1,gdouble cx2,gdouble cy2,GimpVector3 a,GimpVector3 b)575 draw_line (cairo_t *cr,
576 gint startx,
577 gint starty,
578 gint pw,
579 gint ph,
580 gdouble cx1,
581 gdouble cy1,
582 gdouble cx2,
583 gdouble cy2,
584 GimpVector3 a,
585 GimpVector3 b)
586 {
587 gdouble x1, y1, x2, y2;
588
589 gimp_vector_3d_to_2d (startx, starty, pw, ph,
590 &x1, &y1, &mapvals.viewpoint, &a);
591 gimp_vector_3d_to_2d (startx, starty, pw, ph,
592 &x2, &y2, &mapvals.viewpoint, &b);
593
594 cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5);
595 cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5);
596 }
597
598 static void
draw_wireframe_box(cairo_t * cr,gint startx,gint starty,gint pw,gint ph)599 draw_wireframe_box (cairo_t *cr,
600 gint startx,
601 gint starty,
602 gint pw,
603 gint ph)
604 {
605 GimpVector3 p[8], tmp, scale;
606 gint i;
607 gdouble cx1, cy1, cx2, cy2;
608
609 cairo_rectangle (cr, startx, starty, pw, ph);
610 cairo_clip (cr);
611
612 /* Compute wireframe points */
613 /* ======================== */
614
615 init_compute ();
616
617 scale = mapvals.scale;
618 gimp_vector3_mul (&scale, 0.5);
619
620 gimp_vector3_set (&p[0], -scale.x, -scale.y, scale.z);
621 gimp_vector3_set (&p[1], scale.x, -scale.y, scale.z);
622 gimp_vector3_set (&p[2], scale.x, scale.y, scale.z);
623 gimp_vector3_set (&p[3], -scale.x, scale.y, scale.z);
624
625 gimp_vector3_set (&p[4], -scale.x, -scale.y, -scale.z);
626 gimp_vector3_set (&p[5], scale.x, -scale.y, -scale.z);
627 gimp_vector3_set (&p[6], scale.x, scale.y, -scale.z);
628 gimp_vector3_set (&p[7], -scale.x, scale.y, -scale.z);
629
630 /* Rotate and translate points */
631 /* =========================== */
632
633 for (i = 0; i < 8; i++)
634 {
635 vecmulmat (&tmp, &p[i], rotmat);
636 gimp_vector3_add (&p[i], &tmp, &mapvals.position);
637 }
638
639 /* Draw the box */
640 /* ============ */
641
642 cx1 = (gdouble) startx;
643 cy1 = (gdouble) starty;
644 cx2 = cx1 + (gdouble) pw;
645 cy2 = cy1 + (gdouble) ph;
646
647 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[0],p[1]);
648 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[1],p[2]);
649 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[2],p[3]);
650 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[3],p[0]);
651
652 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[4],p[5]);
653 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[5],p[6]);
654 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[6],p[7]);
655 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[7],p[4]);
656
657 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[0],p[4]);
658 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[1],p[5]);
659 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[2],p[6]);
660 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[3],p[7]);
661
662 cairo_set_line_width (cr, 3.0);
663 cairo_stroke_preserve (cr);
664 cairo_set_line_width (cr, 1.0);
665 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
666 cairo_stroke (cr);
667 }
668
669 static void
draw_wireframe_cylinder(cairo_t * cr,gint startx,gint starty,gint pw,gint ph)670 draw_wireframe_cylinder (cairo_t *cr,
671 gint startx,
672 gint starty,
673 gint pw,
674 gint ph)
675 {
676 GimpVector3 p[2*8], a, axis, scale;
677 gint i;
678 gdouble cx1, cy1, cx2, cy2;
679 gfloat m[16], l, angle;
680
681 cairo_rectangle (cr, startx, starty, pw, ph);
682 cairo_clip (cr);
683
684 /* Compute wireframe points */
685 /* ======================== */
686
687 init_compute ();
688
689 scale = mapvals.scale;
690 gimp_vector3_mul (&scale, 0.5);
691
692 l = mapvals.cylinder_length / 2.0;
693 angle = 0;
694
695 gimp_vector3_set (&axis, 0.0, 1.0, 0.0);
696
697 for (i = 0; i < 8; i++)
698 {
699 rotatemat (angle, &axis, m);
700
701 gimp_vector3_set (&a, mapvals.cylinder_radius, 0.0, 0.0);
702
703 vecmulmat (&p[i], &a, m);
704
705 p[i+8] = p[i];
706
707 p[i].y += l;
708 p[i+8].y -= l;
709
710 angle += 360.0 / 8.0;
711 }
712
713 /* Rotate and translate points */
714 /* =========================== */
715
716 for (i = 0; i < 16; i++)
717 {
718 vecmulmat (&a, &p[i], rotmat);
719 gimp_vector3_add (&p[i], &a, &mapvals.position);
720 }
721
722 /* Draw the box */
723 /* ============ */
724
725 cx1 = (gdouble) startx;
726 cy1 = (gdouble) starty;
727 cx2 = cx1 + (gdouble) pw;
728 cy2 = cy1 + (gdouble) ph;
729
730 for (i = 0; i < 7; i++)
731 {
732 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i],p[i+1]);
733 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i+8],p[i+9]);
734 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i],p[i+8]);
735 }
736
737 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[7],p[0]);
738 draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[15],p[8]);
739
740 cairo_set_line_width (cr, 3.0);
741 cairo_stroke_preserve (cr);
742 cairo_set_line_width (cr, 1.0);
743 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
744 cairo_stroke (cr);
745 }
746