/*************************************************/ /* Compute a preview image and preview wireframe */ /*************************************************/ #include "config.h" #include #include #include #include "map-object-main.h" #include "map-object-ui.h" #include "map-object-image.h" #include "map-object-apply.h" #include "map-object-shade.h" #include "map-object-preview.h" line linetab[WIRESIZE*2+8]; gdouble mat[3][4]; gint lightx, lighty; BackBuffer backbuf = { 0, 0, 0, 0, NULL }; /* Protos */ /* ====== */ static void draw_light_marker (gint xpos, gint ypos); static void clear_light_marker (void); static gint draw_line (gint n, gint startx, gint starty, gint pw, gint ph, gdouble cx1, gdouble cy1, gdouble cx2, gdouble cy2, GimpVector3 a, GimpVector3 b); static void draw_wireframe_plane (gint startx, gint starty, gint pw, gint ph); static void draw_wireframe_sphere (gint startx, gint starty, gint pw, gint ph); static void draw_wireframe_box (gint startx, gint starty, gint pw, gint ph); static void draw_wireframe_cylinder (gint startx, gint starty, gint pw, gint ph); /*************************************************/ /* Quick and dirty (and slow) line clip routine. */ /* The function returns FALSE if the line isn't */ /* visible according to the limits given. */ /*************************************************/ static gboolean clip_line (gdouble *x1, gdouble *y1, gdouble *x2, gdouble *y2, gdouble minx, gdouble miny, gdouble maxx, gdouble maxy) { gdouble tmp; g_assert (x1 != NULL); g_assert (y1 != NULL); g_assert (x2 != NULL); g_assert (y2 != NULL); /* First, check if line is visible at all */ /* ====================================== */ if (*x1 < minx && *x2 < minx) return FALSE; if (*x1 > maxx && *x2 > maxx) return FALSE; if (*y1 < miny && *y2 < miny) return FALSE; if (*y1 > maxy && *y2 > maxy) return FALSE; /* Check for intersection with the four edges. Sort on x first. */ /* ============================================================ */ if (*x2 < *x1) { tmp = *x1; *x1 = *x2; *x2 = tmp; tmp = *y1; *y1 = *y2; *y2 = tmp; } if (*x1 < minx) { if (*y1 < *y2) *y1 = *y1 + (minx - *x1) * ((*y2 - *y1) / (*x2 - *x1)); else *y1 = *y1 - (minx - *x1) * ((*y1 - *y2) / (*x2 - *x1)); *x1 = minx; } if (*x2 > maxx) { if (*y1 < *y2) *y2 = *y2 - (*x2 - maxx) * ((*y2 - *y1) / (*x2 - *x1)); else *y2 = *y2 + (*x2 - maxx) * ((*y1 - *y2) / (*x2 - *x1)); *x2 = maxx; } if (*y1 < miny) { *x1 = *x1 + (miny - *y1) * ((*x2 - *x1) / (*y2 - *y1)); *y1 = miny; } if (*y2 < miny) { *x2 = *x2 - (miny - *y2) * ((*x2 - *x1) / (*y1 - *y2)); *y2 = miny; } if (*y1 > maxy) { *x1 = *x1 + (*y1 - maxy) * ((*x2 - *x1) / (*y1 - *y2)); *y1 = maxy; } if (*y2 > maxy) { *x2 = *x2 - (*y2 - maxy) * ((*x2 - *x1) / (*y2 - *y1)); *y2 = maxy; } return TRUE; } /**************************************************************/ /* Computes a preview of the rectangle starting at (x,y) with */ /* dimensions (w,h), placing the result in preview_RGB_data. */ /**************************************************************/ void compute_preview (gint x, gint y, gint w, gint h, gint pw, gint ph) { gdouble xpostab[PREVIEW_WIDTH]; gdouble ypostab[PREVIEW_HEIGHT]; gdouble realw; gdouble realh; GimpVector3 p1, p2; GimpRGB color; GimpRGB lightcheck, darkcheck; gint xcnt, ycnt, f1, f2; glong index = 0; init_compute (); p1 = int_to_pos (x, y); p2 = int_to_pos (x + w, y + h); /* First, compute the linear mapping (x,y,x+w,y+h) to (0,0,pw,ph) */ /* ============================================================== */ realw = (p2.x - p1.x); realh = (p2.y - p1.y); for (xcnt = 0; xcnt < pw; xcnt++) xpostab[xcnt] = p1.x + realw * ((gdouble) xcnt / (gdouble) pw); for (ycnt = 0; ycnt < ph; ycnt++) ypostab[ycnt] = p1.y + realh * ((gdouble) ycnt / (gdouble) ph); /* Compute preview using the offset tables */ /* ======================================= */ if (mapvals.transparent_background == TRUE) { gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0); } else { gimp_context_get_background (&background); gimp_rgb_set_alpha (&background, 1.0); } gimp_rgba_set (&lightcheck, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, 1.0); gimp_rgba_set (&darkcheck, GIMP_CHECK_DARK, GIMP_CHECK_DARK, GIMP_CHECK_DARK, 1.0); gimp_vector3_set (&p2, -1.0, -1.0, 0.0); for (ycnt = 0; ycnt < ph; ycnt++) { for (xcnt = 0; xcnt < pw; xcnt++) { p1.x = xpostab[xcnt]; p1.y = ypostab[ycnt]; p2 = p1; color = (* get_ray_color) (&p1); if (color.a < 1.0) { f1 = ((xcnt % 32) < 16); f2 = ((ycnt % 32) < 16); f1 = f1 ^ f2; if (f1) { if (color.a == 0.0) color = lightcheck; else gimp_rgb_composite (&color, &lightcheck, GIMP_RGB_COMPOSITE_BEHIND); } else { if (color.a == 0.0) color = darkcheck; else gimp_rgb_composite (&color, &darkcheck, GIMP_RGB_COMPOSITE_BEHIND); } } gimp_rgb_get_uchar (&color, preview_rgb_data + index, preview_rgb_data + index + 1, preview_rgb_data + index + 2); index += 3; } } } /*************************************************/ /* Check if the given position is within the */ /* light marker. Return TRUE if so, FALSE if not */ /*************************************************/ gint check_light_hit (gint xpos, gint ypos) { gdouble dx, dy, r; if (mapvals.lightsource.type == POINT_LIGHT) { dx = (gdouble) lightx - xpos; dy = (gdouble) lighty - ypos; r = sqrt (dx * dx + dy * dy) + 0.5; if ((gint) r > 7) return FALSE; else return TRUE; } return FALSE; } /****************************************/ /* Draw a marker to show light position */ /****************************************/ static void draw_light_marker (gint xpos, gint ypos) { GdkColor color; color.red = 0x0; color.green = 0x0; color.blue = 0x0; gdk_gc_set_rgb_bg_color (gc, &color); color.red = 0x0; color.green = 0x4000; color.blue = 0xFFFF; gdk_gc_set_rgb_fg_color (gc, &color); gdk_gc_set_function (gc, GDK_COPY); if (mapvals.lightsource.type == POINT_LIGHT) { lightx = xpos; lighty = ypos; /* Save background */ /* =============== */ backbuf.x = lightx - 7; backbuf.y = lighty - 7; backbuf.w = 14; backbuf.h = 14; /* X doesn't like images that's outside a window, make sure */ /* we get the backbuffer image from within the boundaries */ /* ======================================================== */ if (backbuf.x < 0) backbuf.x = 0; else if ((backbuf.x + backbuf.w) > PREVIEW_WIDTH) backbuf.w = (PREVIEW_WIDTH - backbuf.x); if (backbuf.y < 0) backbuf.y = 0; else if ((backbuf.y + backbuf.h) > PREVIEW_HEIGHT) backbuf.h = (PREVIEW_WIDTH - backbuf.y); backbuf.image = gdk_drawable_get_image (previewarea->window, backbuf.x, backbuf.y, backbuf.w, backbuf.h); gdk_draw_arc (previewarea->window, gc, TRUE, lightx - 7, lighty - 7, 14, 14, 0, 360 * 64); } } static void clear_light_marker (void) { /* Restore background if it has been saved */ /* ======================================= */ if (backbuf.image != NULL) { GdkColor color; color.red = 0x0; color.green = 0x0; color.blue = 0x0; gdk_gc_set_rgb_bg_color (gc, &color); color.red = 0xFFFF; color.green = 0xFFFF; color.blue = 0xFFFF; gdk_gc_set_rgb_fg_color (gc, &color); gdk_gc_set_function (gc, GDK_COPY); gdk_draw_image (previewarea->window, gc, backbuf.image, 0, 0, backbuf.x, backbuf.y, backbuf.w, backbuf.h); g_object_unref (backbuf.image); backbuf.image = NULL; } } static void draw_lights (gint startx, gint starty, gint pw, gint ph) { gdouble dxpos, dypos; gint xpos, ypos; clear_light_marker (); gimp_vector_3d_to_2d (startx, starty, pw, ph, &dxpos, &dypos, &mapvals.viewpoint, &mapvals.lightsource.position); xpos = RINT (dxpos); ypos = RINT (dypos); if (xpos >= 0 && xpos <= PREVIEW_WIDTH && ypos >= 0 && ypos <= PREVIEW_HEIGHT) draw_light_marker (xpos, ypos); } /*************************************************/ /* Update light position given new screen coords */ /*************************************************/ void update_light (gint xpos, gint ypos) { gint startx, starty, pw, ph; pw = PREVIEW_WIDTH * mapvals.zoom; ph = PREVIEW_HEIGHT * mapvals.zoom; startx = (PREVIEW_WIDTH - pw) / 2; starty = (PREVIEW_HEIGHT - ph) / 2; gimp_vector_2d_to_3d (startx, starty, pw, ph, xpos, ypos, &mapvals.viewpoint, &mapvals.lightsource.position); draw_lights (startx, starty,pw, ph); } /******************************************************************/ /* Draw preview image. if DoCompute is TRUE then recompute image. */ /******************************************************************/ void draw_preview_image (gint docompute) { gint startx, starty, pw, ph; GdkColor color; color.red = 0x0; color.green = 0x0; color.blue = 0x0; gdk_gc_set_rgb_bg_color (gc, &color); color.red = 0xFFFF; color.green = 0xFFFF; color.blue = 0xFFFF; gdk_gc_set_rgb_fg_color (gc, &color); gdk_gc_set_function (gc, GDK_COPY); linetab[0].x1 = -1; pw = PREVIEW_WIDTH * mapvals.zoom; ph = PREVIEW_HEIGHT * mapvals.zoom; startx = (PREVIEW_WIDTH - pw) / 2; starty = (PREVIEW_HEIGHT - ph) / 2; if (docompute == TRUE) { GdkDisplay *display = gtk_widget_get_display (previewarea); GdkCursor *cursor; cursor = gdk_cursor_new_for_display (display, GDK_WATCH); gdk_window_set_cursor (previewarea->window, cursor); gdk_cursor_unref (cursor); compute_preview (0, 0, width - 1, height - 1, pw, ph); cursor = gdk_cursor_new_for_display (display, GDK_HAND2); gdk_window_set_cursor(previewarea->window, cursor); gdk_cursor_unref (cursor); clear_light_marker (); } if (pw != PREVIEW_WIDTH || ph != PREVIEW_HEIGHT) gdk_window_clear (previewarea->window); gdk_draw_rgb_image (previewarea->window, gc, startx, starty, pw, ph, GDK_RGB_DITHER_MAX, preview_rgb_data, 3 * pw); draw_lights (startx, starty, pw, ph); } /**************************/ /* Draw preview wireframe */ /**************************/ void draw_preview_wireframe (void) { gint startx, starty, pw, ph; GdkColor color; color.red = 0x0; color.green = 0x0; color.blue = 0x0; gdk_gc_set_rgb_bg_color (gc, &color); color.red = 0xFFFF; color.green = 0xFFFF; color.blue = 0xFFFF; gdk_gc_set_rgb_fg_color (gc, &color); gdk_gc_set_function (gc, GDK_INVERT); pw = PREVIEW_WIDTH * mapvals.zoom; ph = PREVIEW_HEIGHT * mapvals.zoom; startx = (PREVIEW_WIDTH - pw) / 2; starty = (PREVIEW_HEIGHT - ph) / 2; clear_wireframe (); draw_wireframe (startx, starty, pw, ph); } /****************************/ /* Draw a wireframe preview */ /****************************/ void draw_wireframe (gint startx, gint starty, gint pw, gint ph) { switch (mapvals.maptype) { case MAP_PLANE: draw_wireframe_plane (startx, starty, pw, ph); break; case MAP_SPHERE: draw_wireframe_sphere (startx, starty, pw, ph); break; case MAP_BOX: draw_wireframe_box (startx, starty, pw, ph); break; case MAP_CYLINDER: draw_wireframe_cylinder (startx, starty, pw, ph); break; } } static void draw_wireframe_plane (gint startx, gint starty, gint pw, gint ph) { GimpVector3 v1, v2, a, b, c, d, dir1, dir2; gint cnt, n = 0; gdouble x1, y1, x2, y2, cx1, cy1, cx2, cy2, fac; /* Find rotated box corners */ /* ======================== */ gimp_vector3_set (&v1, 0.5, 0.0, 0.0); gimp_vector3_set (&v2, 0.0, 0.5, 0.0); gimp_vector3_rotate (&v1, gimp_deg_to_rad (mapvals.alpha), gimp_deg_to_rad (mapvals.beta), gimp_deg_to_rad (mapvals.gamma)); gimp_vector3_rotate (&v2, gimp_deg_to_rad (mapvals.alpha), gimp_deg_to_rad (mapvals.beta), gimp_deg_to_rad (mapvals.gamma)); dir1 = v1; gimp_vector3_normalize (&dir1); dir2 = v2; gimp_vector3_normalize (&dir2); fac = 1.0 / (gdouble) WIRESIZE; gimp_vector3_mul (&dir1, fac); gimp_vector3_mul (&dir2, fac); gimp_vector3_add (&a, &mapvals.position, &v1); gimp_vector3_sub (&b, &a, &v2); gimp_vector3_add (&a, &a, &v2); gimp_vector3_sub (&d, &mapvals.position, &v1); gimp_vector3_sub (&d, &d, &v2); c = b; cx1 = (gdouble) startx; cy1 = (gdouble) starty; cx2 = cx1 + (gdouble) pw; cy2 = cy1 + (gdouble) ph; for (cnt = 0; cnt <= WIRESIZE; cnt++) { gimp_vector_3d_to_2d (startx, starty, pw, ph, &x1, &y1, &mapvals.viewpoint, &a); gimp_vector_3d_to_2d (startx, starty, pw, ph, &x2, &y2, &mapvals.viewpoint, &b); if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE) { linetab[n].x1 = RINT (x1); linetab[n].y1 = RINT (y1); linetab[n].x2 = RINT (x2); linetab[n].y2 = RINT (y2); linetab[n].linewidth = 1; linetab[n].linestyle = GDK_LINE_SOLID; gdk_gc_set_line_attributes (gc, linetab[n].linewidth, linetab[n].linestyle, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_draw_line (previewarea->window, gc, linetab[n].x1, linetab[n].y1, linetab[n].x2, linetab[n].y2); n++; } gimp_vector_3d_to_2d (startx, starty, pw, ph, &x1, &y1, &mapvals.viewpoint, &c); gimp_vector_3d_to_2d (startx, starty, pw, ph, &x2, &y2, &mapvals.viewpoint, &d); if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE) { linetab[n].x1 = RINT (x1); linetab[n].y1 = RINT (y1); linetab[n].x2 = RINT (x2); linetab[n].y2 = RINT (y2); linetab[n].linewidth = 1; linetab[n].linestyle = GDK_LINE_SOLID; gdk_gc_set_line_attributes (gc, linetab[n].linewidth, linetab[n].linestyle, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_draw_line (previewarea->window, gc, linetab[n].x1, linetab[n].y1, linetab[n].x2, linetab[n].y2); n++; } gimp_vector3_sub (&a, &a, &dir1); gimp_vector3_sub (&b, &b, &dir1); gimp_vector3_add (&c, &c, &dir2); gimp_vector3_add (&d, &d, &dir2); } /* Mark end of lines */ /* ================= */ linetab[n].x1 = -1; } static void draw_wireframe_sphere (gint startx, gint starty, gint pw, gint ph) { GimpVector3 p[2 * (WIRESIZE + 5)]; gint cnt, cnt2, n = 0; gdouble x1, y1, x2, y2, twopifac, cx1, cy1, cx2, cy2; /* Compute wireframe points */ /* ======================== */ twopifac = (2.0 * G_PI) / WIRESIZE; for (cnt = 0; cnt < WIRESIZE; cnt++) { p[cnt].x = mapvals.radius * cos ((gdouble) cnt * twopifac); p[cnt].y = 0.0; p[cnt].z = mapvals.radius * sin ((gdouble) cnt * twopifac); gimp_vector3_rotate (&p[cnt], gimp_deg_to_rad (mapvals.alpha), gimp_deg_to_rad (mapvals.beta), gimp_deg_to_rad (mapvals.gamma)); gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position); } p[cnt] = p[0]; for (cnt = WIRESIZE + 1; cnt < 2 * WIRESIZE + 1; cnt++) { p[cnt].x = mapvals.radius * cos ((gdouble) (cnt-(WIRESIZE+1))*twopifac); p[cnt].y = mapvals.radius * sin ((gdouble) (cnt-(WIRESIZE+1))*twopifac); p[cnt].z = 0.0; gimp_vector3_rotate (&p[cnt], gimp_deg_to_rad (mapvals.alpha), gimp_deg_to_rad (mapvals.beta), gimp_deg_to_rad (mapvals.gamma)); gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position); } p[cnt] = p[WIRESIZE+1]; cnt++; cnt2 = cnt; /* Find rotated axis */ /* ================= */ gimp_vector3_set (&p[cnt], 0.0, -0.35, 0.0); gimp_vector3_rotate (&p[cnt], gimp_deg_to_rad (mapvals.alpha), gimp_deg_to_rad (mapvals.beta), gimp_deg_to_rad (mapvals.gamma)); p[cnt+1] = mapvals.position; gimp_vector3_set (&p[cnt+2], 0.0, 0.0, -0.35); gimp_vector3_rotate (&p[cnt+2], gimp_deg_to_rad (mapvals.alpha), gimp_deg_to_rad (mapvals.beta), gimp_deg_to_rad (mapvals.gamma)); p[cnt+3] = mapvals.position; p[cnt + 4] = p[cnt]; gimp_vector3_mul (&p[cnt + 4], -1.0); p[cnt + 5] = p[cnt + 1]; gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position); gimp_vector3_add (&p[cnt + 2], &p[cnt + 2], &mapvals.position); gimp_vector3_add (&p[cnt + 4], &p[cnt + 4], &mapvals.position); /* Draw the circles (equator and zero meridian) */ /* ============================================ */ cx1 = (gdouble) startx; cy1 = (gdouble) starty; cx2 = cx1 + (gdouble) pw; cy2 = cy1 + (gdouble) ph; for (cnt = 0; cnt < cnt2 - 1; cnt++) { if (p[cnt].z > mapvals.position.z && p[cnt + 1].z > mapvals.position.z) { gimp_vector_3d_to_2d (startx, starty, pw, ph, &x1, &y1, &mapvals.viewpoint, &p[cnt]); gimp_vector_3d_to_2d (startx, starty, pw, ph, &x2, &y2, &mapvals.viewpoint, &p[cnt + 1]); if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE) { linetab[n].x1 = (gint) (x1 + 0.5); linetab[n].y1 = (gint) (y1 + 0.5); linetab[n].x2 = (gint) (x2 + 0.5); linetab[n].y2 = (gint) (y2 + 0.5); linetab[n].linewidth = 3; linetab[n].linestyle = GDK_LINE_SOLID; gdk_gc_set_line_attributes (gc, linetab[n].linewidth, linetab[n].linestyle, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_draw_line (previewarea->window, gc, linetab[n].x1, linetab[n].y1, linetab[n].x2, linetab[n].y2); n++; } } } /* Draw the axis (pole to pole and center to zero meridian) */ /* ======================================================== */ for (cnt = 0; cnt < 3; cnt++) { gimp_vector_3d_to_2d (startx, starty, pw, ph, &x1, &y1, &mapvals.viewpoint, &p[cnt2]); gimp_vector_3d_to_2d (startx, starty, pw, ph, &x2, &y2, &mapvals.viewpoint, &p[cnt2 + 1]); if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE) { linetab[n].x1 = RINT (x1); linetab[n].y1 = RINT (y1); linetab[n].x2 = RINT (x2); linetab[n].y2 = RINT (y2); if (p[cnt2].z < mapvals.position.z || p[cnt2+1].z < mapvals.position.z) { linetab[n].linewidth = 1; linetab[n].linestyle = GDK_LINE_DOUBLE_DASH; } else { linetab[n].linewidth = 3; linetab[n].linestyle = GDK_LINE_SOLID; } gdk_gc_set_line_attributes (gc, linetab[n].linewidth, linetab[n].linestyle, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_draw_line (previewarea->window, gc, linetab[n].x1, linetab[n].y1, linetab[n].x2, linetab[n].y2); n++; } cnt2 += 2; } /* Mark end of lines */ /* ================= */ linetab[n].x1 = -1; } static gint draw_line (gint n, gint startx, gint starty, gint pw, gint ph, gdouble cx1, gdouble cy1, gdouble cx2, gdouble cy2, GimpVector3 a, GimpVector3 b) { gdouble x1, y1, x2, y2; gint i = n; gimp_vector_3d_to_2d (startx, starty, pw, ph, &x1, &y1, &mapvals.viewpoint, &a); gimp_vector_3d_to_2d (startx, starty, pw, ph, &x2, &y2, &mapvals.viewpoint, &b); if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE) { linetab[i].x1 = RINT (x1); linetab[i].y1 = RINT (y1); linetab[i].x2 = RINT (x2); linetab[i].y2 = RINT (y2); linetab[i].linewidth = 3; linetab[i].linestyle = GDK_LINE_SOLID; gdk_gc_set_line_attributes (gc, linetab[i].linewidth, linetab[i].linestyle, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_draw_line (previewarea->window, gc, linetab[i].x1, linetab[i].y1, linetab[i].x2, linetab[i].y2); i++; } return i; } static void draw_wireframe_box (gint startx, gint starty, gint pw, gint ph) { GimpVector3 p[8], tmp, scale; gint n = 0, i; gdouble cx1, cy1, cx2, cy2; /* Compute wireframe points */ /* ======================== */ init_compute (); scale = mapvals.scale; gimp_vector3_mul (&scale, 0.5); gimp_vector3_set (&p[0], -scale.x, -scale.y, scale.z); gimp_vector3_set (&p[1], scale.x, -scale.y, scale.z); gimp_vector3_set (&p[2], scale.x, scale.y, scale.z); gimp_vector3_set (&p[3], -scale.x, scale.y, scale.z); gimp_vector3_set (&p[4], -scale.x, -scale.y, -scale.z); gimp_vector3_set (&p[5], scale.x, -scale.y, -scale.z); gimp_vector3_set (&p[6], scale.x, scale.y, -scale.z); gimp_vector3_set (&p[7], -scale.x, scale.y, -scale.z); /* Rotate and translate points */ /* =========================== */ for (i = 0; i < 8; i++) { vecmulmat (&tmp, &p[i], rotmat); gimp_vector3_add (&p[i], &tmp, &mapvals.position); } /* Draw the box */ /* ============ */ cx1 = (gdouble) startx; cy1 = (gdouble) starty; cx2 = cx1 + (gdouble) pw; cy2 = cy1 + (gdouble) ph; n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[0],p[1]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[1],p[2]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[2],p[3]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[3],p[0]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[4],p[5]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[5],p[6]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[6],p[7]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[7],p[4]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[0],p[4]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[1],p[5]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[2],p[6]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[3],p[7]); /* Mark end of lines */ /* ================= */ linetab[n].x1 = -1; } static void draw_wireframe_cylinder (gint startx, gint starty, gint pw, gint ph) { GimpVector3 p[2*8], a, axis, scale; gint n = 0, i; gdouble cx1, cy1, cx2, cy2; gfloat m[16], l, angle; /* Compute wireframe points */ /* ======================== */ init_compute (); scale = mapvals.scale; gimp_vector3_mul (&scale, 0.5); l = mapvals.cylinder_length / 2.0; angle = 0; gimp_vector3_set (&axis, 0.0, 1.0, 0.0); for (i = 0; i < 8; i++) { rotatemat (angle, &axis, m); gimp_vector3_set (&a, mapvals.cylinder_radius, 0.0, 0.0); vecmulmat (&p[i], &a, m); p[i+8] = p[i]; p[i].y += l; p[i+8].y -= l; angle += 360.0 / 8.0; } /* Rotate and translate points */ /* =========================== */ for (i = 0; i < 16; i++) { vecmulmat (&a, &p[i], rotmat); gimp_vector3_add (&p[i], &a, &mapvals.position); } /* Draw the box */ /* ============ */ cx1 = (gdouble) startx; cy1 = (gdouble) starty; cx2 = cx1 + (gdouble) pw; cy2 = cy1 + (gdouble) ph; for (i = 0; i < 7; i++) { n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i],p[i+1]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i+8],p[i+9]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i],p[i+8]); } n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[7],p[0]); n = draw_line (n, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[15],p[8]); /* Mark end of lines */ /* ================= */ linetab[n].x1 = -1; } void clear_wireframe (void) { gint n = 0; while (linetab[n].x1 != -1) { gdk_gc_set_line_attributes (gc, linetab[n].linewidth, linetab[n].linestyle, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_draw_line (previewarea->window, gc, linetab[n].x1, linetab[n].y1, linetab[n].x2, linetab[n].y2); n++; } }