From d87497e168632b2e0755003b86614dd7d432489a Mon Sep 17 00:00:00 2001 From: Bill Kendrick Date: Tue, 17 Jan 2023 01:09:08 -0800 Subject: [PATCH] Rivulet - More WIP --- magic/icons/rivulet-brush-add.png | Bin 7733 -> 7877 bytes magic/icons/rivulet-brush-alpha.png | Bin 0 -> 7205 bytes magic/src/rivulet.c | 139 ++++++++++++++++++++++------ 3 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 magic/icons/rivulet-brush-alpha.png diff --git a/magic/icons/rivulet-brush-add.png b/magic/icons/rivulet-brush-add.png index c4d910fdcb8bfa223d0b8c77a8fb5ed72637e9d1..94063ae7aae8b1f33aee5d5f2854672553f8a6b5 100644 GIT binary patch delta 4240 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 Aw*UYD literal 0 HcmV?d00001 diff --git a/magic/src/rivulet.c b/magic/src/rivulet.c index e2780fbb6..dcc588d0d 100644 --- a/magic/src/rivulet.c +++ b/magic/src/rivulet.c @@ -21,13 +21,19 @@ #include "SDL_image.h" #include "SDL_mixer.h" +// #define DEBUG_RADIUS +// #define DEBUG_ALPHA +// #define DEBUG_ANGLE + Mix_Chunk *snd_effect = NULL; SDL_Surface * rivulet_img_brush_add = NULL, + * rivulet_img_brush_alpha = NULL, * rivulet_img_brush_sub = NULL, * rivulet_img_angles = NULL; SDL_Surface * rivulet_snapshot = NULL; int riv_x, riv_y; Uint8 * riv_radii = NULL, + * riv_alpha = NULL, * riv_angles = NULL; Uint32 rivulet_api_version(void); @@ -74,6 +80,7 @@ int rivulet_init(magic_api * api) // snd_effect = Mix_LoadWAV(fname); /* Load our images */ + snprintf(fname, sizeof(fname), "%simages/magic/rivulet-brush-add.png", api->data_directory); rivulet_img_brush_add = IMG_Load(fname); @@ -83,6 +90,15 @@ int rivulet_init(magic_api * api) return 0; } + snprintf(fname, sizeof(fname), "%simages/magic/rivulet-brush-alpha.png", + api->data_directory); + rivulet_img_brush_alpha = IMG_Load(fname); + if (rivulet_img_brush_alpha == NULL) + { + fprintf(stderr, "Can't open %s\n", fname); + return 0; + } + snprintf(fname, sizeof(fname), "%simages/magic/rivulet-brush-sub.png", api->data_directory); rivulet_img_brush_sub = IMG_Load(fname); @@ -92,7 +108,7 @@ int rivulet_init(magic_api * api) return 0; } - snprintf(fname, sizeof(fname), "%simages/magic/rivulet-brush-sub.png", + snprintf(fname, sizeof(fname), "%simages/magic/rivulet-angles.png", api->data_directory); rivulet_img_angles = IMG_Load(fname); if (rivulet_img_angles == NULL) @@ -159,6 +175,9 @@ void rivulet_shutdown(magic_api * api ATTRIBUTE_UNUSED) if (rivulet_img_brush_add != NULL) SDL_FreeSurface(rivulet_img_brush_add); + if (rivulet_img_brush_alpha != NULL) + SDL_FreeSurface(rivulet_img_brush_alpha); + if (rivulet_img_brush_sub != NULL) SDL_FreeSurface(rivulet_img_brush_sub); @@ -168,6 +187,9 @@ void rivulet_shutdown(magic_api * api ATTRIBUTE_UNUSED) if (riv_radii != NULL) free(riv_radii); + if (riv_alpha != NULL) + free(riv_alpha); + if (riv_angles != NULL) free(riv_angles); } @@ -179,7 +201,7 @@ rivulet_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED, SDL_Rect * update_rect) { riv_x = x; - riv_y = y; + riv_y = y - 1; if (riv_radii == NULL || rivulet_snapshot == NULL) return; @@ -205,7 +227,7 @@ rivulet_drag(magic_api * api ATTRIBUTE_UNUSED, int which, SDL_Surface * canvas, return; /* Don't go backwards */ - if (y < riv_y) + if (y <= riv_y) return; /* Don't stray too far left/right */ @@ -237,39 +259,72 @@ rivulet_release(magic_api * api, int which ATTRIBUTE_UNUSED, int x, int y, /* ignored and reused in a for-loop */ SDL_Rect * update_rect) { - int src_x, src_y; + int src_x, src_y, idx; double radius, angle_deg, angle_rad; + Uint8 alpha; Uint32 pix; + Uint8 r, g, b, r1, g1, b1, r2, g2, b2; + if (riv_radii == NULL || rivulet_snapshot == NULL) return; /* Undo all of the placeholder drawings */ - SDL_BlitSurface(snapshot, NULL, canvas, NULL); + SDL_BlitSurface(rivulet_snapshot, NULL, canvas, NULL); /* Apply the lense effect */ for (y = 0; y < canvas->h; y++) { for (x = 0; x < canvas->w; x++) { - radius = ((double) riv_radii[(y * canvas->w) + x]) / 2.0; + idx = (y * canvas->w) + x; + +#if defined(DEBUG_RADIUS) || defined(DEBUG_ALPHA) || defined(DEBUG_ANGLE) + int v; + +#if defined(DEBUG_RADIUS) + v = riv_radii[idx]; +#elif defined(DEBUG_ALPHA) + v = riv_alpha[idx]; +#else + v = riv_angles[idx]; +#endif + + api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format, v, 64, 64)); +#else + + radius = ((double) riv_radii[idx]); + alpha = riv_alpha[idx] / 2; if (radius != 0.0) { /* Angle is stored as 0-255 (so 256 would be 360 degrees) */ - /* FIXME: Simplify this :-P */ - angle_deg = ((((double) riv_angles[(y * canvas->w) + x]) / 256.0) * 360.0); - -// angle_deg = angle_deg + 90.0; + angle_deg = ((((double) riv_angles[idx]) / 256.0) * 360.0); angle_rad = (angle_deg * M_PI) / 180.0; - /* FIXME */ - src_x = x - cos(angle_rad) * radius; + src_x = x + cos(angle_rad) * radius; src_y = y - sin(angle_rad) * radius; + pix = api->getpixel(rivulet_snapshot, x, y); + SDL_GetRGB(pix, rivulet_snapshot->format, &r1, &g1, &b1); + pix = api->getpixel(rivulet_snapshot, src_x, src_y); - api->putpixel(canvas, x, y, pix); + SDL_GetRGB(pix, rivulet_snapshot->format, &r2, &g2, &b2); + + r = ((r2 * alpha) / 255) + ((r1 * (255 - alpha) / 255)); + g = ((g2 * alpha) / 255) + ((g1 * (255 - alpha) / 255)); + b = ((b2 * alpha) / 255) + ((b1 * (255 - alpha) / 255)); + + if (riv_radii[idx] > 128) + { + r = (r + riv_radii[idx]) / 2; + g = (g + riv_radii[idx]) / 2; + b = (b + riv_radii[idx]) / 2; + } + + api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format, r, g, b)); } +#endif } } @@ -293,11 +348,11 @@ void rivulet_line_callback_drag(void *ptr, int which ATTRIBUTE_UNUSED, { magic_api * api; SDL_Rect dest; - int w, h, half_w, half_h; + int w, h, half_w, half_h, idx; int src_x, src_y, dest_x, dest_y; Uint32 pix; - Uint8 r, g, b; - int new_rad; + Uint8 intensity, tmp; + int alpha, radius; api = (magic_api *) ptr; @@ -324,24 +379,38 @@ void rivulet_line_callback_drag(void *ptr, int which ATTRIBUTE_UNUSED, for (src_x = 0; src_x < w; src_x++) { dest_x = (x - half_w) + src_x; if (dest_x >= 0 && dest_x < canvas->w) { + idx = (dest_y * canvas->w) + dest_x; + + /* Add alpha */ + pix = api->getpixel(rivulet_img_brush_alpha, src_x, src_y); + SDL_GetRGB(pix, rivulet_img_brush_alpha->format, &intensity, &tmp, &tmp); + + alpha = ((int) riv_alpha[idx] + (int) (intensity)); + if (alpha > 255) + alpha = 255; + riv_alpha[idx] = (Uint8) alpha; + + /* Apply radius brush to radius displacement map */ - pix = api->getpixel(rivulet_img_brush_add, src_x, src_y); - SDL_GetRGB(pix, rivulet_img_brush_add->format, &r, &g, &b); + if (alpha > 0) + { + pix = api->getpixel(rivulet_img_brush_add, src_x, src_y); + SDL_GetRGB(pix, rivulet_img_brush_add->format, &intensity, &tmp, &tmp); - new_rad = ((int) riv_radii[(dest_y * canvas->w) + dest_x] + (int) r - 64) / 2; - if (new_rad < 0) - new_rad = 0; - if (new_rad > 255) - new_rad = 255; - - riv_radii[(dest_y * canvas->w) + dest_x] = (Uint8) new_rad; + radius = ((int) riv_radii[idx] + (int) intensity - 128); + if (radius < 0) + radius = 0; + if (radius > 255) + radius = 255; + riv_radii[idx] = radius; + } /* Apply angle brush to angle displacement map */ pix = api->getpixel(rivulet_img_angles, src_x, src_y); - SDL_GetRGB(pix, rivulet_img_angles->format, &r, &g, &b); + SDL_GetRGB(pix, rivulet_img_angles->format, &intensity, &tmp, &tmp); - riv_angles[(dest_y * canvas->w) + dest_x] = r; + riv_angles[idx] = intensity; } } } @@ -361,11 +430,25 @@ void rivulet_switchin(magic_api * api ATTRIBUTE_UNUSED, return; } + riv_alpha = (Uint8 *) malloc(sizeof(Uint8) * canvas->w * canvas->h); + if (riv_alpha == NULL) + { + free(riv_radii); + riv_radii = NULL; + + fprintf(stderr, "rivulet: Cannot malloc() riv_alpha!\n"); + return; + } + riv_angles = (Uint8 *) malloc(sizeof(Uint8) * canvas->w * canvas->h); if (riv_angles == NULL) { free(riv_radii); riv_radii = NULL; + + free(riv_alpha); + riv_alpha = NULL; + fprintf(stderr, "rivulet: Cannot malloc() riv_angles!\n"); return; } @@ -395,6 +478,8 @@ void zero_riv_arrays(SDL_Surface * canvas) { if (riv_radii != NULL) memset(riv_radii, 0, (canvas->w * canvas->h)); + if (riv_alpha != NULL) + memset(riv_alpha, 0, (canvas->w * canvas->h)); if (riv_angles != NULL) memset(riv_angles, 0, (canvas->w * canvas->h)); }