diff --git a/solidify/gui_util.c b/solidify/gui_util.c index 25e6005..dc155fd 100644 --- a/solidify/gui_util.c +++ b/solidify/gui_util.c @@ -11,11 +11,77 @@ */ +#include +#include +#include #include #include "gui_util.h" +void hpoint(guchar *rgbbuf, int x, int y, int sx, uint8_t c[3]) +{ + guchar *p = rgbbuf+(y*sx+x)*3; + + p[0] = c[0]; + p[1] = c[1]; + p[2] = c[2]; +} + + +void vpoint(guchar *rgbbuf, int y, int x, int sx, uint8_t c[3]) +{ + guchar *p = rgbbuf+(y*sx+x)*3; + + p[0] = c[0]; + p[1] = c[1]; + p[2] = c[2]; +} + + +static void alpha(guchar *rgbbuf, int f, int i, int sx, uint8_t c[3], double w, + void (*point)(guchar *rgbbuf, int f, int i, int sx, uint8_t c[3])) +{ + uint8_t ct[3]; + int n; + + assert(w >= 0); + assert(w <= 1); + for (n = 0; n != 3; n++) + ct[n] = round(c[n]*w); + point(rgbbuf, f, i, sx, ct); +} + + +void aa_line(guchar *rgbbuf, int i, double fa, double fb, int max, int sx, + uint8_t c[3], + void (*point)(guchar *rgbbuf, int f, int i, int sx, uint8_t c[3])) +{ + int f0, f1; + int from, to, n; + + assert(max > 0); + assert(fb >= fa); + f0 = floor(fa); + f1 = ceil(fb); + if (f0 > max || f1 < 0) + return; + if (f0 == f1) { + if (f0 >= 0 && f1 <= max) + point(rgbbuf, f0, i, sx, c); + return; + } + if (f0 >= 0) + alpha(rgbbuf, f0, i, sx, c, 1-(fa-f0), point); + if (f1 <= max) + alpha(rgbbuf, f1, i, sx, c, 1-(f1-fb), point); + from = f0+1 > 0 ? f0+1 : 0; + to = f1-1 < max ? f1-1: max; + for (n = from; n <= to; n++) + point(rgbbuf, n, i, sx, c); +} + + void draw_circle(GdkDrawable *da, GdkGC *gc, int x, int y, int r) { gdk_draw_arc(da, gc, FALSE, x-r, y-r, 2*r, 2*r, 0, 360*64); diff --git a/solidify/gui_util.h b/solidify/gui_util.h index fe3d8e6..49fe97a 100644 --- a/solidify/gui_util.h +++ b/solidify/gui_util.h @@ -13,9 +13,17 @@ #ifndef GUI_UTIL_H #define GUI_UTIL_H +#include #include +void hpoint(guchar *rgbbuf, int x, int y, int sx, uint8_t c[3]); +void vpoint(guchar *rgbbuf, int y, int x, int sx, uint8_t c[3]); + +void aa_line(guchar *rgbbuf, int i, double fa, double fb, int max, int sx, + uint8_t c[3], + void (*point)(guchar *rgbbuf, int f, int i, int sx, uint8_t c[3])); + void draw_circle(GdkDrawable *da, GdkGC *gc, int x, int y, int r); #endif /* !GUI_UTIL_H */ diff --git a/solidify/level.c b/solidify/level.c index c0425a3..df805fd 100644 --- a/solidify/level.c +++ b/solidify/level.c @@ -94,7 +94,9 @@ static void draw_image(GtkWidget *widget, struct face *f, int osd) static void draw_xz(GtkWidget *widget, struct face *f, int y) { - int x, z, z0; + int zm = f->a->max_z; + int x, z; + double z0; guchar *rgbbuf, *p; rgbbuf = p = calloc(f->sx*f->sz, 3); @@ -105,19 +107,18 @@ static void draw_xz(GtkWidget *widget, struct face *f, int y) if (y != -1) for (x = 0; x != f->sx ; x++) { z = get(f->a, x+f->a->min_x, y+f->a->min_y); - if (z != UNDEF) { - p = rgbbuf+3*(x+f->sx*(f->sz-z+f->a->min_z-1)); - p[0] = 0xff; - p[1] = 0xff; - p[2] = 0xff; - } - z0 = round(face_z0(f, x, y)); - /* @@@ anti-alias */ - if (z0 >= f->a->min_z && z0 <= f->a->max_z) { - p = rgbbuf+3*(x+f->sx*(f->sz-z0+f->a->min_z-1)); - p[0] = 0x80; - p[1] = 0xc0; - p[2] = 0xff; + z0 = face_z0(f, x, y); + if (z == UNDEF || z == z0) { + aa_line(rgbbuf, x, zm-z0, zm-z0, zm, f->sx, + (uint8_t *) "\0\0\xff", vpoint); + continue; + } + if (z > z0) { + aa_line(rgbbuf, x, zm-z, zm-z0, zm, f->sx, + (uint8_t *) "\0\xff\0", vpoint); + } else { + aa_line(rgbbuf, x, zm-z0, zm-z, zm, f->sx, + (uint8_t *) "\xff\0\0", vpoint); } } gdk_draw_rgb_image(widget->window, @@ -130,7 +131,9 @@ static void draw_xz(GtkWidget *widget, struct face *f, int y) static void draw_zy(GtkWidget *widget, struct face *f, int x) { - int y, z, z0; + int zm = f->a->max_z; + int y, z; + double z0; guchar *rgbbuf, *p; rgbbuf = p = calloc(f->sy*f->sz, 3); @@ -140,20 +143,19 @@ static void draw_zy(GtkWidget *widget, struct face *f, int x) } if (x != -1) for (y = 0; y != f->sy ; y++) { - z = get(f->a, x+f->a->min_x, y+f->a->min_y); - if (z != UNDEF) { - p = rgbbuf+3*(f->a->max_z-z+f->sz*(f->sy-y-1)); - p[0] = 0xff; - p[1] = 0xff; - p[2] = 0xff; + z = get(f->a, x+f->a->min_x, f->a->max_y-y); + z0 = face_z0(f, x, f->sy-y-1); + if (z == UNDEF || z == z0) { + aa_line(rgbbuf, y, zm-z0, zm-z0, zm, f->sz, + (uint8_t *) "\0\0\xff", hpoint); + continue; } - z0 = round(face_z0(f, x, y)); - /* @@@ anti-alias */ - if (z0 >= f->a->min_z && z0 <= f->a->max_z) { - p = rgbbuf+3*(f->a->max_z-z0+f->sz*(f->sy-y-1)); - p[0] = 0x80; - p[1] = 0xc0; - p[2] = 0xff; + if (z > z0) { + aa_line(rgbbuf, y, zm-z, zm-z0, zm, f->sz, + (uint8_t *) "\0\xff\0", hpoint); + } else { + aa_line(rgbbuf, y, zm-z0, zm-z, zm, f->sz, + (uint8_t *) "\xff\0\0", hpoint); } } gdk_draw_rgb_image(widget->window,