plug-ins: Replace GimpRGB in map-object

This commit is contained in:
Alx Sa 2024-09-13 12:32:34 +00:00
parent 4c11925433
commit 62c86a5e72
8 changed files with 434 additions and 378 deletions

View File

@ -187,18 +187,12 @@ render (gdouble x,
gpointer data)
{
GimpVector3 pos;
GimpRGB temp;
pos.x = x / (gdouble) width;
pos.y = y / (gdouble) height;
pos.z = 0.0;
temp = get_ray_color (&pos);
col[0] = temp.r;
col[1] = temp.g;
col[2] = temp.b;
col[3] = temp.a;
get_ray_color (&pos, col);
}
static void
@ -219,7 +213,7 @@ void
compute_image (void)
{
gint xcount, ycount;
GimpRGB color;
gdouble color[4];
glong progress_counter = 0;
GimpVector3 p;
GimpImage *new_image = NULL;
@ -229,13 +223,9 @@ compute_image (void)
init_compute ();
if (mapvals.create_new_image)
{
new_image = gimp_image_new (width, height, GIMP_RGB);
}
new_image = gimp_image_new (width, height, GIMP_RGB);
else
{
new_image = image;
}
new_image = image;
gimp_image_undo_group_start (new_image);
@ -289,8 +279,8 @@ compute_image (void)
for (xcount = 0; xcount < width; xcount++)
{
p = int_to_pos (xcount, ycount);
color = (* get_ray_color) (&p);
poke (xcount, ycount, &color, NULL);
(* get_ray_color) (&p, color);
poke (xcount, ycount, color, NULL);
progress_counter++;
}
@ -307,7 +297,7 @@ compute_image (void)
mapvals.pixelthreshold,
render,
NULL,
poke_adaptive,
poke,
NULL,
show_progress,
NULL);
@ -425,6 +415,6 @@ copy_from_config (GimpProcedureConfig *config)
/* TODO: Use GeglColor directly in this plug-in */
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"),
&mapvals.lightsource.color);
mapvals.lightsource.color);
g_object_unref (color);
}

View File

@ -42,68 +42,66 @@ cairo_surface_t *preview_surface = NULL;
glong maxcounter, old_depth, max_depth;
gint width, height;
GimpRGB background;
gdouble background[4];
gint border_x, border_y, border_w, border_h;
void peek_box_image (gint image,
gint x,
gint y,
gdouble *color);
/******************/
/* Implementation */
/******************/
GimpRGB
peek (gint x,
gint y)
void
peek (gint x,
gint y,
gdouble *color)
{
GimpRGB color;
gegl_buffer_sample (source_buffer, x, y, NULL,
&color, babl_format ("R'G'B'A double"),
color, babl_format ("R'G'B'A double"),
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
if (! babl_format_has_alpha (gegl_buffer_get_format (source_buffer)))
color.a = 1.0;
return color;
color[3] = 1.0;
}
static GimpRGB
peek_box_image (gint image,
gint x,
gint y)
void
peek_box_image (gint image,
gint x,
gint y,
gdouble *color)
{
GimpRGB color;
gegl_buffer_sample (box_buffers[image], x, y, NULL,
&color, babl_format ("R'G'B'A double"),
color, babl_format ("R'G'B'A double"),
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
if (! babl_format_has_alpha (gegl_buffer_get_format (box_buffers[image])))
color.a = 1.0;
return color;
color[3] = 1.0;
}
static GimpRGB
peek_cylinder_image (gint image,
gint x,
gint y)
static void
peek_cylinder_image (gint image,
gint x,
gint y,
gdouble *color)
{
GimpRGB color;
gegl_buffer_sample (cylinder_buffers[image], x, y, NULL,
&color, babl_format ("R'G'B'A double"),
color, babl_format ("R'G'B'A double"),
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
if (! babl_format_has_alpha (gegl_buffer_get_format (cylinder_buffers[image])))
color.a = 1.0;
return color;
color[3] = 1.0;
}
void
poke (gint x,
gint y,
GimpRGB *color,
gdouble *color,
gpointer user_data)
{
gegl_buffer_set (dest_buffer, GEGL_RECTANGLE (x, y, 1, 1), 0,
@ -111,17 +109,6 @@ poke (gint x,
GEGL_AUTO_ROWSTRIDE);
}
void
poke_adaptive (gint x,
gint y,
gdouble *color,
gpointer user_data)
{
gegl_buffer_set (dest_buffer, GEGL_RECTANGLE (x, y, 1, 1), 0,
babl_format ("R'G'B'A double"), color,
GEGL_AUTO_ROWSTRIDE);
}
gint
checkbounds (gint x,
gint y)
@ -195,18 +182,17 @@ pos_to_int (gdouble x,
/* Quartics bilinear interpolation stuff. */
/**********************************************/
GimpRGB
void
get_image_color (gdouble u,
gdouble v,
gint *inside)
gint *inside,
gdouble *color)
{
gint x1;
gint y1;
gint x2;
gint y2;
GimpRGB p[4];
GimpRGB p_rgba;
gdouble pixel[4];
gdouble p[4];
gdouble pixels[16];
pos_to_int (u, v, &x1, &y1);
@ -224,31 +210,32 @@ get_image_color (gdouble u,
x2 = (x1 + 1) % width;
y2 = (y1 + 1) % height;
p[0] = peek (x1, y1);
p[1] = peek (x2, y1);
p[2] = peek (x1, y2);
p[3] = peek (x2, y2);
peek (x1, y1, p);
for (gint i = 0; i < 4; i++)
{
pixels[(i * 4)] = p[i].r;
pixels[(i * 4) + 1] = p[i].g;
pixels[(i * 4) + 2] = p[i].b;
pixels[(i * 4) + 3] = p[i].a;
}
pixels[i] = p[i];
peek (x2, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i + 4] = p[i];
peek (x1, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 8] = p[i];
peek (x2, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 12] = p[i];
gimp_bilinear_rgb (u * width, v * height, pixels, TRUE, pixel);
gimp_bilinear_rgb (u * width, v * height, pixels, TRUE, color);
gimp_rgba_set (&p_rgba, pixel[0], pixel[1], pixel[2], pixel[3]);
return p_rgba;
return;
}
if (checkbounds (x1, y1) == FALSE)
{
*inside =FALSE;
return background;
for (gint i = 0; i < 4; i++)
color[i] = background[i];
return;
}
x2 = (x1 + 1);
@ -258,35 +245,32 @@ get_image_color (gdouble u,
{
*inside = TRUE;
return peek (x1, y1);
return peek (x1, y1, color);
}
*inside = TRUE;
p[0] = peek (x1, y1);
p[1] = peek (x2, y1);
p[2] = peek (x1, y2);
p[3] = peek (x2, y2);
peek (x1, y1, p);
for (gint i = 0; i < 4; i++)
{
pixels[(i * 4)] = p[i].r;
pixels[(i * 4) + 1] = p[i].g;
pixels[(i * 4) + 2] = p[i].b;
pixels[(i * 4) + 3] = p[i].a;
}
pixels[i] = p[i];
peek (x2, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i + 4] = p[i];
peek (x1, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 8] = p[i];
peek (x2, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 12] = p[i];
gimp_bilinear_rgb (u * width, v * height, pixels, TRUE, pixel);
gimp_rgba_set (&p_rgba, pixel[0], pixel[1], pixel[2], pixel[3]);
return p_rgba;
gimp_bilinear_rgb (u * width, v * height, pixels, TRUE, color);
}
GimpRGB
get_box_image_color (gint image,
gdouble u,
gdouble v)
void
get_box_image_color (gint image,
gdouble u,
gdouble v,
gdouble *color)
{
gint w;
gint h;
@ -294,9 +278,7 @@ get_box_image_color (gint image,
gint y1;
gint x2;
gint y2;
GimpRGB p[4];
GimpRGB p_rgba;
gdouble pixel[4];
gdouble p[4];
gdouble pixels[16];
w = gegl_buffer_get_width (box_buffers[image]);
@ -306,38 +288,40 @@ get_box_image_color (gint image,
y1 = (gint) ((v * (gdouble) h));
if (checkbounds_box_image (image, x1, y1) == FALSE)
return background;
{
for (gint i = 0; i < 4; i++)
color[i] = background[i];
return;
}
x2 = (x1 + 1);
y2 = (y1 + 1);
if (checkbounds_box_image (image, x2, y2) == FALSE)
return peek_box_image (image, x1,y1);
p[0] = peek_box_image (image, x1, y1);
p[1] = peek_box_image (image, x2, y1);
p[2] = peek_box_image (image, x1, y2);
p[3] = peek_box_image (image, x2, y2);
return peek_box_image (image, x1, y1, color);
peek_box_image (image, x1, y1, p);
for (gint i = 0; i < 4; i++)
{
pixels[(i * 4)] = p[i].r;
pixels[(i * 4) + 1] = p[i].g;
pixels[(i * 4) + 2] = p[i].b;
pixels[(i * 4) + 3] = p[i].a;
}
pixels[i] = p[i];
peek_box_image (image, x2, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i + 4] = p[i];
peek_box_image (image, x1, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 8] = p[i];
peek_box_image (image, x2, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 12] = p[i];
gimp_bilinear_rgb (u * w, v * h, pixels, TRUE, pixel);
gimp_rgba_set (&p_rgba, pixel[0], pixel[1], pixel[2], pixel[3]);
return p_rgba;
gimp_bilinear_rgb (u * w, v * w, pixels, TRUE, color);
}
GimpRGB
get_cylinder_image_color (gint image,
gdouble u,
gdouble v)
void
get_cylinder_image_color (gint image,
gdouble u,
gdouble v,
gdouble *color)
{
gint w;
gint h;
@ -345,9 +329,7 @@ get_cylinder_image_color (gint image,
gint y1;
gint x2;
gint y2;
GimpRGB p[4];
GimpRGB p_rgba;
gdouble pixel[4];
gdouble p[4];
gdouble pixels[16];
w = gegl_buffer_get_width (cylinder_buffers[image]);
@ -357,32 +339,33 @@ get_cylinder_image_color (gint image,
y1 = (gint) ((v * (gdouble) h));
if (checkbounds_cylinder_image (image, x1, y1) == FALSE)
return background;
{
for (gint i = 0; i < 4; i++)
color[i] = background[i];
return;
}
x2 = (x1 + 1);
y2 = (y1 + 1);
if (checkbounds_cylinder_image (image, x2, y2) == FALSE)
return peek_cylinder_image (image, x1,y1);
p[0] = peek_cylinder_image (image, x1, y1);
p[1] = peek_cylinder_image (image, x2, y1);
p[2] = peek_cylinder_image (image, x1, y2);
p[3] = peek_cylinder_image (image, x2, y2);
return peek_cylinder_image (image, x1, y1, color);
peek_cylinder_image (image, x1, y1, p);
for (gint i = 0; i < 4; i++)
{
pixels[(i * 4)] = p[i].r;
pixels[(i * 4) + 1] = p[i].g;
pixels[(i * 4) + 2] = p[i].b;
pixels[(i * 4) + 3] = p[i].a;
}
pixels[i] = p[i];
peek_cylinder_image (image, x2, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i + 4] = p[i];
peek_cylinder_image (image, x1, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 8] = p[i];
peek_cylinder_image (image, x2, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 12] = p[i];
gimp_bilinear_rgb (u * w, v * h, pixels, TRUE, pixel);
gimp_rgba_set (&p_rgba, pixel[0], pixel[1], pixel[2], pixel[3]);
return p_rgba;
gimp_bilinear_rgb (u * w, v * h, pixels, TRUE, color);
}
/****************************************/
@ -416,7 +399,8 @@ image_setup (GimpDrawable *drawable,
if (transparent_background == TRUE)
{
gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0);
for (gint i = 0; i < 4; i++)
background[i] = 0;
}
else
{
@ -424,7 +408,8 @@ image_setup (GimpDrawable *drawable,
gegl_color = gimp_context_get_background ();
gimp_color_set_alpha (gegl_color, 1.0);
gegl_color_get_rgba_with_space (gegl_color, &background.r, &background.g, &background.b, &background.a, NULL);
gegl_color_get_rgba_with_space (gegl_color, &background[0], &background[1],
&background[2], &background[3], NULL);
g_object_unref (gegl_color);
}

View File

@ -23,7 +23,7 @@ extern cairo_surface_t *preview_surface;
extern glong maxcounter, old_depth, max_depth;
extern gint width, height;
extern GimpRGB background;
extern gdouble background[4];
extern gint border_x1, border_y1, border_x2, border_y2;
@ -40,14 +40,10 @@ extern glong out_xy_to_index (gint x,
gint y);
extern gint checkbounds (gint x,
gint y);
extern GimpRGB peek (gint x,
gint y);
extern void poke (gint x,
extern void peek (gint x,
gint y,
GimpRGB *color,
gpointer user_data);
/* TODO: Merge back with poke when removing GimpRGB fully */
extern void poke_adaptive (gint x,
gdouble *color);
extern void poke (gint x,
gint y,
gdouble *color,
gpointer user_data);
@ -58,14 +54,17 @@ extern void pos_to_int (gdouble x,
gint *scr_x,
gint *scr_y);
extern GimpRGB get_image_color (gdouble u,
extern void get_image_color (gdouble u,
gdouble v,
gint *inside);
extern GimpRGB get_box_image_color (gint image,
gint *inside,
gdouble *color);
extern void get_box_image_color (gint image,
gdouble u,
gdouble v);
extern GimpRGB get_cylinder_image_color (gint image,
gdouble v,
gdouble *color);
extern void get_cylinder_image_color (gint image,
gdouble u,
gdouble v);
gdouble v,
gdouble *color);
#endif /* __MAPOBJECT_IMAGE_H__ */

View File

@ -471,7 +471,8 @@ set_default_settings (void)
mapvals.showgrid = TRUE;
mapvals.lightsource.intensity = 1.0;
gimp_rgba_set (&mapvals.lightsource.color, 1.0, 1.0, 1.0, 1.0);
for (i = 0; i < 4; i++)
mapvals.lightsource.color[i] = 1.0;
mapvals.material.ambient_int = 0.3;
mapvals.material.diffuse_int = 1.0;

View File

@ -28,6 +28,12 @@ typedef enum
MAP_CYLINDER
} MapType;
typedef enum
{
COMPOSITE_NORMAL,
COMPOSITE_BEHIND,
} CompositeType;
/* Typedefs */
/* ======== */
@ -38,7 +44,7 @@ typedef struct
gdouble diffuse_ref;
gdouble specular_ref;
gdouble highlight;
GimpRGB color;
gdouble color[4];
} MaterialSettings;
typedef struct
@ -46,7 +52,7 @@ typedef struct
LightType type;
GimpVector3 position;
GimpVector3 direction;
GimpRGB color;
gdouble color[4];
gdouble intensity;
} LightSettings;

View File

@ -88,8 +88,9 @@ compute_preview (gint x,
gdouble realw;
gdouble realh;
GimpVector3 p1, p2;
GimpRGB color;
GimpRGB lightcheck, darkcheck;
gdouble color[4];
gdouble lightcheck[4] = { GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, 1.0 };
gdouble darkcheck[4] = { GIMP_CHECK_DARK, GIMP_CHECK_DARK, GIMP_CHECK_DARK, 1.0 };
gint xcnt, ycnt, f1, f2;
guchar r, g, b;
glong index = 0;
@ -119,7 +120,8 @@ compute_preview (gint x,
if (mapvals.transparent_background == TRUE)
{
gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0);
for (gint i = 0; i < 4; i++)
background[i] = 0.0;
}
else
{
@ -127,15 +129,12 @@ compute_preview (gint x,
gegl_color = gimp_context_get_background ();
gimp_color_set_alpha (gegl_color, 1.0);
gegl_color_get_rgba_with_space (gegl_color, &background.r, &background.g, &background.b, &background.a, NULL);
gegl_color_get_rgba_with_space (gegl_color, &background[0], &background[1],
&background[2], &background[3], NULL);
g_object_unref (gegl_color);
}
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);
cairo_surface_flush (preview_surface);
@ -149,9 +148,9 @@ compute_preview (gint x,
p1.y = ypostab[ycnt];
p2 = p1;
color = (* get_ray_color) (&p1);
(* get_ray_color) (&p1, color);
if (color.a < 1.0)
if (color[3] < 1.0)
{
f1 = ((xcnt % 32) < 16);
f2 = ((ycnt % 32) < 16);
@ -159,23 +158,33 @@ compute_preview (gint x,
if (f1)
{
if (color.a == 0.0)
color = lightcheck;
if (color[3] == 0.0)
{
for (gint i = 0; i < 4; i++)
color[i] = lightcheck[i];
}
else
gimp_rgb_composite (&color, &lightcheck,
GIMP_RGB_COMPOSITE_BEHIND);
{
composite (color, lightcheck, COMPOSITE_BEHIND);
}
}
else
{
if (color.a == 0.0)
color = darkcheck;
if (color[3] == 0.0)
{
for (gint i = 0; i < 4; i++)
color[i] = darkcheck[i];
}
else
gimp_rgb_composite (&color, &darkcheck,
GIMP_RGB_COMPOSITE_BEHIND);
{
composite (color, darkcheck, COMPOSITE_BEHIND);
}
}
}
gimp_rgb_get_uchar (&color, &r, &g, &b);
r = (guchar) (color[0] * 255);
g = (guchar) (color[1] * 255);
b = (guchar) (color[2] * 255);
GIMP_CAIRO_RGB24_SET_PIXEL((preview_rgb_data + index), r, g, b);
index += 4;
}

View File

@ -31,17 +31,17 @@ typedef struct
/* Phong shading */
/*****************/
static GimpRGB
static void
phong_shade (GimpVector3 *pos,
GimpVector3 *viewpoint,
GimpVector3 *normal,
GimpRGB *diff_col,
GimpRGB *spec_col,
gdouble *diff_col,
gdouble *spec_col,
LightType type)
{
GimpRGB ambientcolor, diffusecolor, specularcolor;
gdouble NL, RV, dist;
GimpVector3 L, NN, V, N;
gdouble ambientcolor[4], diffusecolor[4], specularcolor[4];
gdouble NL, RV, dist;
GimpVector3 L, NN, V, N;
GimpVector3 *light;
light = mapvals.lightsource.type == DIRECTIONAL_LIGHT
@ -52,8 +52,10 @@ phong_shade (GimpVector3 *pos,
/* ========================= */
N = *normal;
ambientcolor = *diff_col;
gimp_rgb_multiply (&ambientcolor, mapvals.material.ambient_int);
for (gint i = 0; i < 4; i++)
ambientcolor[i] = diff_col[i];
for (gint i = 0; i < 3; i++)
ambientcolor[i] *= mapvals.material.ambient_int;
/* Compute (N*L) term of Phong's equation */
/* ====================================== */
@ -86,22 +88,33 @@ phong_shade (GimpVector3 *pos,
/* Compute diffuse and specular intensity contribution */
/* =================================================== */
diffusecolor = *diff_col;
gimp_rgb_multiply (&diffusecolor, mapvals.material.diffuse_ref);
gimp_rgb_multiply (&diffusecolor, NL);
for (gint i = 0; i < 4; i++)
diffusecolor[i] = diff_col[i];
for (gint i = 0; i < 3; i++)
{
diffusecolor[i] *= mapvals.material.diffuse_ref;
diffusecolor[i] *= NL;
}
specularcolor = *spec_col;
gimp_rgb_multiply (&specularcolor, mapvals.material.specular_ref);
gimp_rgb_multiply (&specularcolor, RV);
for (gint i = 0; i < 4; i++)
specularcolor[i] = spec_col[i];
for (gint i = 0; i < 3; i++)
{
specularcolor[i] *= mapvals.material.specular_ref;
specularcolor[i] *= RV;
}
gimp_rgb_add (&diffusecolor, &specularcolor);
gimp_rgb_multiply (&diffusecolor, mapvals.material.diffuse_int);
gimp_rgb_clamp (&diffusecolor);
gimp_rgb_add (&ambientcolor, &diffusecolor);
for (gint i = 0; i < 3; i++)
{
diffusecolor[i] += specularcolor[i];
diffusecolor[i] *= mapvals.material.diffuse_int;
diffusecolor[i] = CLAMP (diffusecolor[i], 0.0, 1.0);
ambientcolor[i] += diffusecolor[i];
}
}
return ambientcolor;
for (gint i = 0; i < 4; i++)
diff_col[i] = ambientcolor[i];
}
static gint
@ -183,11 +196,10 @@ plane_intersect (GimpVector3 *dir,
* of the plane at a given point
*****************************************************************************/
GimpRGB
get_ray_color_plane (GimpVector3 *pos)
void
get_ray_color_plane (GimpVector3 *pos,
gdouble *color)
{
GimpRGB color = background;
static gint inside = FALSE;
static GimpVector3 ray, spos;
static gdouble vx, vy;
@ -195,6 +207,9 @@ get_ray_color_plane (GimpVector3 *pos)
/* Construct a line from our VP to the point */
/* ========================================= */
for (gint i = 0; i < 4; i++)
color[i] = background[i];
gimp_vector3_sub (&ray, pos, &mapvals.viewpoint);
gimp_vector3_normalize (&ray);
@ -203,32 +218,28 @@ get_ray_color_plane (GimpVector3 *pos)
if (plane_intersect (&ray, &mapvals.viewpoint, &spos, &vx, &vy) == TRUE)
{
color = get_image_color (vx, vy, &inside);
get_image_color (vx, vy, &inside, color);
if (color.a != 0.0 && inside == TRUE &&
if (color[3] != 0.0 && inside == TRUE &&
mapvals.lightsource.type != NO_LIGHT)
{
/* Compute shading at this point */
/* ============================= */
color = phong_shade (&spos,
&mapvals.viewpoint,
&mapvals.normal,
&color,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&spos,
&mapvals.viewpoint,
&mapvals.normal,
color,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
}
}
if (mapvals.transparent_background == FALSE && color.a < 1.0)
{
gimp_rgb_composite (&color, &background,
GIMP_RGB_COMPOSITE_BEHIND);
}
return color;
if (mapvals.transparent_background == FALSE && color[3] < 1.0)
composite (color, background, COMPOSITE_BEHIND);
}
/***********************************************************************/
@ -323,21 +334,22 @@ sphere_intersect (GimpVector3 *dir,
* of the sphere at a given point
*****************************************************************************/
GimpRGB
get_ray_color_sphere (GimpVector3 *pos)
void
get_ray_color_sphere (GimpVector3 *pos,
gdouble *color)
{
GimpRGB color = background;
static GimpRGB color2;
static gdouble color2[4];
static gint inside = FALSE;
static GimpVector3 normal, ray, spos1, spos2;
static gdouble vx, vy;
for (gint i = 0; i < 4; i++)
color[i] = background[i];
/* Check if ray is within the bounding box */
/* ======================================= */
if (pos->x<bx1 || pos->x>bx2 || pos->y<by1 || pos->y>by2)
return color;
return;
/* Construct a line from our VP to the point */
/* ========================================= */
@ -356,76 +368,75 @@ get_ray_color_sphere (GimpVector3 *pos)
gimp_vector3_sub (&normal, &spos1, &mapvals.position);
gimp_vector3_normalize (&normal);
sphere_to_image (&normal, &vx, &vy);
color = get_image_color (vx, vy, &inside);
get_image_color (vx, vy, &inside, color);
/* Check for total transparency... */
/* =============================== */
if (color.a < 1.0)
if (color[3] < 1.0)
{
/* Hey, we can see through here! */
/* Lets see what's on the other side.. */
/* =================================== */
color = phong_shade (&spos1,
&mapvals.viewpoint,
&normal,
&color,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&spos1,
&mapvals.viewpoint,
&normal,
color,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
gimp_vector3_sub (&normal, &spos2, &mapvals.position);
gimp_vector3_normalize (&normal);
sphere_to_image (&normal, &vx, &vy);
color2 = get_image_color (vx, vy, &inside);
get_image_color (vx, vy, &inside, color2);
/* Make the normal point inwards */
/* ============================= */
gimp_vector3_mul (&normal, -1.0);
color2 = phong_shade (&spos2,
&mapvals.viewpoint,
&normal,
&color2,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&spos2,
&mapvals.viewpoint,
&normal,
color2,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color2);
for (gint i = 0; i < 4; i++)
color2[i] = CLAMP (color2[i], 0.0, 1.0);
/* Compute a mix of the first and second colors */
/* ============================================ */
gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL);
gimp_rgb_clamp (&color);
composite (color, color2, COMPOSITE_NORMAL);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
}
else if (color.a != 0.0 &&
else if (color[3] != 0.0 &&
inside == TRUE &&
mapvals.lightsource.type != NO_LIGHT)
{
/* Compute shading at this point */
/* ============================= */
color = phong_shade (&spos1,
&mapvals.viewpoint,
&normal,
&color,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&spos1,
&mapvals.viewpoint,
&normal,
color,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
}
}
if (mapvals.transparent_background == FALSE && color.a < 1.0)
{
gimp_rgb_composite (&color, &background,
GIMP_RGB_COMPOSITE_BEHIND);
}
return color;
if (mapvals.transparent_background == FALSE && color[3] < 1.0)
composite (color, background, COMPOSITE_BEHIND);
}
/***************************************************/
@ -834,16 +845,19 @@ intersect_box (GimpVector3 scale,
return result;
}
GimpRGB
get_ray_color_box (GimpVector3 *pos)
void
get_ray_color_box (GimpVector3 *pos,
gdouble *color)
{
GimpVector3 lvp, ldir, vp, p, dir, ns, nn;
GimpRGB color, color2;
gdouble color2[4];
gfloat m[16];
gint i;
FaceIntersectInfo face_intersect[2];
color = background;
for (i = 0; i < 4; i++)
color[i] = background[i];
vp = mapvals.viewpoint;
p = *pos;
@ -904,77 +918,78 @@ get_ray_color_box (GimpVector3 *pos)
face_intersect[i].n = nn;
}
color = get_box_image_color (face_intersect[0].face,
face_intersect[0].u,
face_intersect[0].v);
get_box_image_color (face_intersect[0].face,
face_intersect[0].u,
face_intersect[0].v,
color);
/* Check for total transparency... */
/* =============================== */
if (color.a < 1.0)
if (color[3] < 1.0)
{
/* Hey, we can see through here! */
/* Lets see what's on the other side.. */
/* =================================== */
color = phong_shade (&face_intersect[0].s,
&mapvals.viewpoint,
&face_intersect[0].n,
&color,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&face_intersect[0].s,
&mapvals.viewpoint,
&face_intersect[0].n,
color,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
color2 = get_box_image_color (face_intersect[1].face,
face_intersect[1].u,
face_intersect[1].v);
get_box_image_color (face_intersect[1].face,
face_intersect[1].u,
face_intersect[1].v,
color2);
/* Make the normal point inwards */
/* ============================= */
gimp_vector3_mul (&face_intersect[1].n, -1.0);
color2 = phong_shade (&face_intersect[1].s,
&mapvals.viewpoint,
&face_intersect[1].n,
&color2,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&face_intersect[1].s,
&mapvals.viewpoint,
&face_intersect[1].n,
color2,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color2);
for (gint i = 0; i < 4; i++)
color2[i] = CLAMP (color2[i], 0.0, 1.0);
if (mapvals.transparent_background == FALSE && color2.a < 1.0)
{
gimp_rgb_composite (&color2, &background,
GIMP_RGB_COMPOSITE_BEHIND);
}
if (mapvals.transparent_background == FALSE && color2[3] < 1.0)
composite (color2, background, COMPOSITE_BEHIND);
/* Compute a mix of the first and second colors */
/* ============================================ */
gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL);
gimp_rgb_clamp (&color);
composite (color, color2, COMPOSITE_NORMAL);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
}
else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT)
else if (color[3] != 0.0 && mapvals.lightsource.type != NO_LIGHT)
{
color = phong_shade (&face_intersect[0].s,
&mapvals.viewpoint,
&face_intersect[0].n,
&color,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&face_intersect[0].s,
&mapvals.viewpoint,
&face_intersect[0].n,
color,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
}
}
else
{
if (mapvals.transparent_background == TRUE)
gimp_rgb_set_alpha (&color, 0.0);
color[3] = 0.0;
}
return color;
}
static gboolean
@ -1106,32 +1121,32 @@ intersect_cylinder (GimpVector3 vp,
return result;
}
static GimpRGB
get_cylinder_color (gint face,
gdouble u,
gdouble v)
static void
get_cylinder_color (gint face,
gdouble u,
gdouble v,
gdouble *color)
{
GimpRGB color;
gint inside;
gint inside;
if (face == 0)
color = get_image_color (u, v, &inside);
get_image_color (u, v, &inside, color);
else
color = get_cylinder_image_color (face - 1, u, v);
return color;
get_cylinder_image_color (face - 1, u, v, color);
}
GimpRGB
get_ray_color_cylinder (GimpVector3 *pos)
void
get_ray_color_cylinder (GimpVector3 *pos,
gdouble *color)
{
GimpVector3 lvp, ldir, vp, p, dir, ns, nn;
GimpRGB color, color2;
gdouble color2[4];
gfloat m[16];
gint i;
FaceIntersectInfo face_intersect[2];
color = background;
for (i = 0; i < 4; i++)
color[i] = background[i];
vp = mapvals.viewpoint;
p = *pos;
@ -1180,75 +1195,117 @@ get_ray_color_cylinder (GimpVector3 *pos)
face_intersect[i].n = nn;
}
color = get_cylinder_color (face_intersect[0].face,
face_intersect[0].u,
face_intersect[0].v);
get_cylinder_color (face_intersect[0].face,
face_intersect[0].u,
face_intersect[0].v,
color);
/* Check for transparency... */
/* ========================= */
if (color.a < 1.0)
if (color[3] < 1.0)
{
/* Hey, we can see through here! */
/* Lets see what's on the other side.. */
/* =================================== */
color = phong_shade (&face_intersect[0].s,
&mapvals.viewpoint,
&face_intersect[0].n,
&color,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&face_intersect[0].s,
&mapvals.viewpoint,
&face_intersect[0].n,
color,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
color2 = get_cylinder_color (face_intersect[1].face,
face_intersect[1].u,
face_intersect[1].v);
get_cylinder_color (face_intersect[1].face,
face_intersect[1].u,
face_intersect[1].v,
color2);
/* Make the normal point inwards */
/* ============================= */
gimp_vector3_mul (&face_intersect[1].n, -1.0);
color2 = phong_shade (&face_intersect[1].s,
&mapvals.viewpoint,
&face_intersect[1].n,
&color2,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&face_intersect[1].s,
&mapvals.viewpoint,
&face_intersect[1].n,
color2,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color2);
for (gint i = 0; i < 4; i++)
color2[i] = CLAMP (color2[i], 0.0, 1.0);
if (mapvals.transparent_background == FALSE && color2.a < 1.0)
{
gimp_rgb_composite (&color2, &background,
GIMP_RGB_COMPOSITE_BEHIND);
}
if (mapvals.transparent_background == FALSE && color2[3] < 1.0)
composite (color2, background, COMPOSITE_BEHIND);
/* Compute a mix of the first and second colors */
/* ============================================ */
gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL);
gimp_rgb_clamp (&color);
composite (color, color2, COMPOSITE_NORMAL);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
}
else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT)
else if (color[3] != 0.0 && mapvals.lightsource.type != NO_LIGHT)
{
color = phong_shade (&face_intersect[0].s,
&mapvals.viewpoint,
&face_intersect[0].n,
&color,
&mapvals.lightsource.color,
mapvals.lightsource.type);
phong_shade (&face_intersect[0].s,
&mapvals.viewpoint,
&face_intersect[0].n,
color,
mapvals.lightsource.color,
mapvals.lightsource.type);
gimp_rgb_clamp (&color);
for (gint i = 0; i < 4; i++)
color[i] = CLAMP (color[i], 0.0, 1.0);
}
}
else
{
if (mapvals.transparent_background == TRUE)
gimp_rgb_set_alpha (&color, 0.0);
color[3] = 0.0;
}
}
void
composite (gdouble *color1,
gdouble *color2,
CompositeType composite)
{
g_return_if_fail (color1 != NULL);
g_return_if_fail (color2 != NULL);
if (composite == COMPOSITE_NORMAL)
{
/* put color2 on top of color1 */
if (color2[3] == 1.0)
{
for (gint i = 0; i < 4; i++)
color1[i] = color2[i];
}
else
{
gdouble factor = color1[3] * (1.0 - color2[3]);
color1[0] = color1[0] * factor + color2[0] * color2[3];
color1[1] = color1[1] * factor + color2[1] * color2[3];
color1[2] = color1[2] * factor + color2[2] * color2[3];
color1[3] = factor + color2[3];
}
}
else if (composite == COMPOSITE_BEHIND)
{
/* put color2 below color1 */
if (color1[3] < 1.0)
{
gdouble factor = color2[3] * (1.0 - color1[3]);
color1[0] = color2[0] * factor + color1[0] * color1[3];
color1[1] = color2[1] * factor + color1[1] * color1[3];
color1[2] = color2[2] * factor + color1[2] * color1[3];
color1[3] = factor + color1[3];
}
}
return color;
}

View File

@ -1,26 +1,35 @@
#ifndef __MAPOBJECT_SHADE_H__
#define __MAPOBJECT_SHADE_H__
typedef GimpRGB (* get_ray_color_func) (GimpVector3 *pos);
typedef void (* get_ray_color_func) (GimpVector3 *pos,
gdouble *color);
extern get_ray_color_func get_ray_color;
GimpRGB get_ray_color_plane (GimpVector3 *pos);
GimpRGB get_ray_color_sphere (GimpVector3 *pos);
GimpRGB get_ray_color_box (GimpVector3 *pos);
GimpRGB get_ray_color_cylinder (GimpVector3 *pos);
void get_ray_color_plane (GimpVector3 *pos,
gdouble *color);
void get_ray_color_sphere (GimpVector3 *pos,
gdouble *color);
void get_ray_color_box (GimpVector3 *pos,
gdouble *color);
void get_ray_color_cylinder (GimpVector3 *pos,
gdouble *color);
void compute_bounding_box (void);
void vecmulmat (GimpVector3 *u,
GimpVector3 *v,
gfloat m[16]);
void rotatemat (gfloat angle,
GimpVector3 *v,
gfloat m[16]);
void transpose_mat (gfloat m[16]);
void matmul (gfloat a[16],
gfloat b[16],
gfloat c[16]);
void ident_mat (gfloat m[16]);
void vecmulmat (GimpVector3 *u,
GimpVector3 *v,
gfloat m[16]);
void rotatemat (gfloat angle,
GimpVector3 *v,
gfloat m[16]);
void transpose_mat (gfloat m[16]);
void matmul (gfloat a[16],
gfloat b[16],
gfloat c[16]);
void ident_mat (gfloat m[16]);
void composite (gdouble *color1,
gdouble *color2,
CompositeType mode);
#endif /* __MAPOBJECT_SHADE_H__ */