Commit 85e884ce authored by William Skaggs's avatar William Skaggs
Browse files

Bill Skaggs <weskaggs@primate.ucdavis.edu>

	* plug-ins/Lighting/lighting_main.c
	* plug-ins/Lighting/lighting_main.h
	* plug-ins/Lighting/lighting_preview.c
	* plug-ins/Lighting/lighting_preview.h
	* plug-ins/Lighting/lighting_shade.c
	* plug-ins/Lighting/lighting_ui.c: completely reworked UI for
	lighting page.  Now supports up to 6 lights (more is trivial).
	Added ability to temporarily isolate selected light.  Added
	light intensity controls.  Can interactively position each light
	(does not quite work yet for directional lights).
parent 8f74e672
2004-07-20 Bill Skaggs <weskaggs@primate.ucdavis.edu>
* plug-ins/Lighting/lighting_main.c
* plug-ins/Lighting/lighting_main.h
* plug-ins/Lighting/lighting_preview.c
* plug-ins/Lighting/lighting_preview.h
* plug-ins/Lighting/lighting_shade.c
* plug-ins/Lighting/lighting_ui.c: completely reworked UI for
lighting page. Now supports up to 6 lights (more is trivial).
Added ability to temporarily isolate selected light. Added
light intensity controls. Can interactively position each light
(does not quite work yet for directional lights).
2004-07-20 Michael Natterer <mitch@gimp.org>
* app/actions/tools-actions.c: added an icon to the
......
......@@ -51,6 +51,10 @@ set_default_settings (void)
{
gint k;
mapvals.update_enabled = TRUE;
mapvals.light_selected = 0;
mapvals.light_isolated = FALSE;
gimp_vector3_set (&mapvals.viewpoint, 0.5, 0.5, 0.25);
gimp_vector3_set (&mapvals.planenormal, 0.0, 0.0, 1.0);
......@@ -60,6 +64,7 @@ set_default_settings (void)
gimp_rgba_set (&mapvals.lightsource[0].color, 1.0, 1.0, 1.0, 1.0);
mapvals.lightsource[0].intensity = 1.0;
mapvals.lightsource[0].type = POINT_LIGHT;
mapvals.lightsource[0].active = TRUE;
/* init lights 2 and 3 pos to upper left and below */
gimp_vector3_set (&mapvals.lightsource[1].position, 2.0, -1.0, 1.0);
......@@ -68,17 +73,25 @@ set_default_settings (void)
gimp_vector3_set (&mapvals.lightsource[2].position, 1.0, 2.0, 1.0);
gimp_vector3_set (&mapvals.lightsource[2].direction, 0.0, 1.0, 1.0);
/* init any remaining lights to directly overhead */
for (k = 3; k < NUM_LIGHTS; k++)
{
gimp_vector3_set (&mapvals.lightsource[k].position, 0.0, 0.0, 1.0);
gimp_vector3_set (&mapvals.lightsource[k].direction, 0.0, 0.0, 1.0);
}
for (k = 1; k < NUM_LIGHTS; k++)
{
gimp_rgba_set (&mapvals.lightsource[k].color, 0.0, 0.0, 0.0, 1.0);
gimp_rgba_set (&mapvals.lightsource[k].color, 1.0, 1.0, 1.0, 1.0);
mapvals.lightsource[k].intensity = 1.0;
mapvals.lightsource[k].type = NO_LIGHT;
mapvals.lightsource[k].active = TRUE;
}
mapvals.material.ambient_int = 0.3;
mapvals.material.diffuse_int = 1.0;
mapvals.material.ambient_int = 0.2;
mapvals.material.diffuse_int = 0.5;
mapvals.material.diffuse_ref = 0.4;
mapvals.material.specular_ref = 0.6;
mapvals.material.specular_ref = 0.5;
mapvals.material.highlight = 27.0;
mapvals.material.metallic = FALSE;
......
......@@ -5,7 +5,7 @@
/* ================= */
#define TILE_CACHE_SIZE 16
#define NUM_LIGHTS 3
#define NUM_LIGHTS 6
/* Typedefs */
/* ======== */
......@@ -14,7 +14,7 @@ typedef enum
{
POINT_LIGHT,
DIRECTIONAL_LIGHT,
SPOT_LIGHT,
SPOT_LIGHT,
NO_LIGHT
} LightType;
......@@ -34,13 +34,13 @@ enum
typedef struct
{
gdouble ambient_int;
gdouble diffuse_int;
gdouble diffuse_ref;
gdouble specular_ref;
gdouble highlight;
gboolean metallic;
GimpRGB color;
gdouble ambient_int;
gdouble diffuse_int;
gdouble diffuse_ref;
gdouble specular_ref;
gdouble highlight;
gboolean metallic;
GimpRGB color;
} MaterialSettings;
typedef struct
......@@ -50,13 +50,14 @@ typedef struct
GimpVector3 direction;
GimpRGB color;
gdouble intensity;
gboolean active;
} LightSettings;
typedef struct
{
gint32 drawable_id;
gint32 bumpmap_id;
gint32 envmap_id;
gint32 drawable_id;
gint32 bumpmap_id;
gint32 envmap_id;
/* Render variables */
/* ================ */
......@@ -67,34 +68,28 @@ typedef struct
MaterialSettings material;
MaterialSettings ref_material;
gdouble pixel_treshold;
gdouble bumpmax,bumpmin;
/* gdouble wave_cx,wave_cy;
gdouble wave_lx,wave_ly;
gdouble wave_amp,wave_ph; */
gint max_depth;
gint bumpmaptype;
/* gint bumptype; */
gdouble pixel_treshold;
gdouble bumpmax,bumpmin;
gint max_depth;
gint bumpmaptype;
/* Flags */
/* ===== */
gint antialiasing;
gint create_new_image;
gint transparent_background;
gint bump_mapped;
gint env_mapped;
gint ref_mapped;
gint bumpstretch;
gint previewquality;
gboolean symbols;
gboolean interactive_preview;
gint antialiasing;
gint create_new_image;
gint transparent_background;
gint bump_mapped;
gint env_mapped;
gint ref_mapped;
gint bumpstretch;
gint previewquality;
gboolean symbols;
gboolean interactive_preview;
/* Misc */
/* ==== */
gdouble preview_zoom_factor;
gboolean update_enabled;
gint light_selected;
gboolean light_isolated;
gdouble preview_zoom_factor;
} LightingValues;
/* Externally visible variables */
......
......@@ -224,13 +224,14 @@ gboolean
check_handle_hit (gint xpos, gint ypos)
{
gint dx,dy,r;
gint k = mapvals.light_selected;
dx = handle_xpos - xpos;
dy = handle_ypos - ypos;
if (mapvals.lightsource[0].type == POINT_LIGHT ||
mapvals.lightsource[0].type == DIRECTIONAL_LIGHT)
if (mapvals.lightsource[k].type == POINT_LIGHT ||
mapvals.lightsource[k].type == DIRECTIONAL_LIGHT)
{
r = sqrt (dx * dx + dy * dy) + 0.5;
if ((gint) r > 7)
......@@ -253,10 +254,11 @@ check_handle_hit (gint xpos, gint ypos)
static void
draw_handles (void)
{
gdouble dxpos, dypos;
gint startx, starty, pw, ph;
gdouble dxpos, dypos;
gint startx, starty, pw, ph;
GimpVector3 viewpoint;
GimpVector3 light_position;
gint k = mapvals.light_selected;
gfloat length;
gfloat delta_x = 0.0;
......@@ -264,15 +266,16 @@ draw_handles (void)
/* calculate handle position */
compute_preview_rectangle (&startx, &starty, &pw, &ph);
switch (mapvals.lightsource[0].type)
switch (mapvals.lightsource[k].type)
{
case NO_LIGHT:
return;
case POINT_LIGHT:
case SPOT_LIGHT:
case NO_LIGHT:
/* swap z to reverse light position */
viewpoint = mapvals.viewpoint;
viewpoint.z = -viewpoint.z;
light_position = mapvals.lightsource[0].position;
light_position = mapvals.lightsource[k].position;
gimp_vector_3d_to_2d (startx, starty, pw, ph, &dxpos, &dypos,
&viewpoint, &light_position);
handle_xpos = (gint) (dxpos + 0.5);
......@@ -285,8 +288,8 @@ draw_handles (void)
gimp_vector_3d_to_2d (startx, starty, pw, ph, &dxpos, &dypos,
&viewpoint, &light_position);
length = PREVIEW_HEIGHT / 4;
delta_x = mapvals.lightsource[0].direction.x * length;
delta_y = mapvals.lightsource[0].direction.y * length;
delta_x = mapvals.lightsource[k].direction.x * length;
delta_y = mapvals.lightsource[k].direction.y * length;
handle_xpos = dxpos + delta_x;
handle_ypos = dypos + delta_y;
break;
......@@ -294,7 +297,7 @@ draw_handles (void)
gdk_gc_set_function (gc, GDK_COPY);
if (mapvals.lightsource[0].type != NO_LIGHT)
if (mapvals.lightsource[k].type != NO_LIGHT)
{
GdkColor color;
......@@ -312,7 +315,7 @@ draw_handles (void)
}
/* calculate backbuffer */
switch (mapvals.lightsource[0].type)
switch (mapvals.lightsource[k].type)
{
case POINT_LIGHT:
backbuf.x = handle_xpos - LIGHT_SYMBOL_SIZE / 2;
......@@ -335,12 +338,13 @@ draw_handles (void)
backbuf.h = fabs(delta_y) + LIGHT_SYMBOL_SIZE;
break;
case SPOT_LIGHT:
case NO_LIGHT:
backbuf.x = handle_xpos - LIGHT_SYMBOL_SIZE / 2;
backbuf.y = handle_ypos - LIGHT_SYMBOL_SIZE / 2;
backbuf.w = LIGHT_SYMBOL_SIZE;
backbuf.h = LIGHT_SYMBOL_SIZE;
break;
case NO_LIGHT:
break;
}
/* Save background */
......@@ -372,7 +376,7 @@ draw_handles (void)
gdk_gc_set_rgb_fg_color (gc, &color);
/* draw circle at light position */
switch (mapvals.lightsource[0].type)
switch (mapvals.lightsource[k].type)
{
case POINT_LIGHT:
case SPOT_LIGHT:
......@@ -406,30 +410,32 @@ void
update_light (gint xpos, gint ypos)
{
gint startx, starty, pw, ph;
GimpVector3 vp;
GimpVector3 vp;
gint k = mapvals.light_selected;
compute_preview_rectangle (&startx, &starty, &pw, &ph);
vp = mapvals.viewpoint;
vp.z = -vp.z;
switch (mapvals.lightsource[0].type)
switch (mapvals.lightsource[k].type)
{
case NO_LIGHT:
break;
case POINT_LIGHT:
case SPOT_LIGHT:
gimp_vector_2d_to_3d (startx,
starty,
pw,
ph,
xpos, ypos, &vp, &mapvals.lightsource[0].position);
xpos, ypos, &vp, &mapvals.lightsource[k].position);
break;
case DIRECTIONAL_LIGHT:
gimp_vector_2d_to_3d (startx,
starty,
pw,
ph,
xpos, ypos, &vp, &mapvals.lightsource[0].direction);
xpos, ypos, &vp, &mapvals.lightsource[k].direction);
break;
}
}
......@@ -561,23 +567,24 @@ interactive_preview_callback (GtkWidget *widget)
static gboolean
interactive_preview_timer_callback ( gpointer data )
{
gint k;
for (k = 0; k < NUM_LIGHTS; k++)
{
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_x[k]),
mapvals.lightsource[k].position.x);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_y[k]),
mapvals.lightsource[k].position.y);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_z[k]),
mapvals.lightsource[k].position.z);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_x[k]),
mapvals.lightsource[k].direction.x);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_y[k]),
mapvals.lightsource[k].direction.y);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_z[k]),
mapvals.lightsource[k].direction.z);
}
gint k = mapvals.light_selected;
mapvals.update_enabled = FALSE; /* disable apply_settings() */
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_x),
mapvals.lightsource[k].position.x);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_y),
mapvals.lightsource[k].position.y);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_pos_z),
mapvals.lightsource[k].position.z);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_x),
mapvals.lightsource[k].direction.x);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_y),
mapvals.lightsource[k].direction.y);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin_dir_z),
mapvals.lightsource[k].direction.z);
mapvals.update_enabled = TRUE;
draw_preview_image (TRUE);
......
......@@ -35,12 +35,12 @@ extern gdouble *xpostab, *ypostab;
extern gboolean light_hit;
extern gboolean left_button_pressed;
GtkWidget *spin_pos_x[NUM_LIGHTS];
GtkWidget *spin_pos_y[NUM_LIGHTS];
GtkWidget *spin_pos_z[NUM_LIGHTS];
GtkWidget *spin_dir_x[NUM_LIGHTS];
GtkWidget *spin_dir_y[NUM_LIGHTS];
GtkWidget *spin_dir_z[NUM_LIGHTS];
GtkWidget *spin_pos_x;
GtkWidget *spin_pos_y;
GtkWidget *spin_pos_z;
GtkWidget *spin_dir_x;
GtkWidget *spin_dir_y;
GtkWidget *spin_dir_z;
/* Externally visible functions */
......
......@@ -143,8 +143,8 @@ precompute_init (gint w,
if (mapvals.bumpmap_id != -1)
{
bpp = gimp_drawable_bpp(mapvals.bumpmap_id);
}
}
bumprow = g_new (guchar, w * bpp);
triangle_normals[0] = g_new (GimpVector3, (w << 1) + 2);
......@@ -202,10 +202,10 @@ precompute_normals (gint x1,
heights[2] = tmpd;
if (mapvals.bumpmap_id != -1)
{
{
bpp = gimp_drawable_bpp(mapvals.bumpmap_id);
}
gimp_pixel_rgn_get_row (&bump_region, bumprow, x1, y, x2 - x1);
if (mapvals.bumpmaptype > 0)
......@@ -228,7 +228,7 @@ precompute_normals (gint x1,
if (bpp>1)
{
mapval = (guchar)((float)((bumprow[n * bpp] +bumprow[n * bpp +1] + bumprow[n * bpp + 2])/3.0 )) ;
}
}
else
{
mapval = bumprow[n * bpp];
......@@ -244,7 +244,7 @@ precompute_normals (gint x1,
if (bpp>1)
{
mapval = (guchar)((float)((bumprow[n * bpp] +bumprow[n * bpp +1] + bumprow[n * bpp + 2])/3.0 )) ;
}
}
else
{
mapval = bumprow[n * bpp];
......@@ -252,7 +252,7 @@ precompute_normals (gint x1,
heights[2][n] = (gdouble) mapvals.bumpmax * (gdouble) mapval / 255.0;
}
}
/* Compute triangle normals */
/* ======================== */
......@@ -260,7 +260,7 @@ precompute_normals (gint x1,
for (n = 0; n < (x2 - x1 - 1); n++)
{
p1.x = 0.0;
p1.y = ystep;
p1.y = ystep;
p1.z = heights[2][n] - heights[1][n];
p2.x = xstep;
......@@ -384,7 +384,7 @@ sphere_to_image (GimpVector3 *normal,
if (fac>1.0)
fac = 1.0;
else if (fac<-1.0)
else if (fac<-1.0)
fac = -1.0;
*u = acos (fac) / (2.0 * G_PI);
......@@ -404,17 +404,18 @@ GimpRGB
get_ray_color (GimpVector3 *position)
{
GimpRGB color;
GimpRGB color_int;
GimpRGB color_sum;
GimpRGB light_color;
gint x, f;
gdouble xf, yf;
GimpVector3 normal, *p;
gint k;
pos_to_float (position->x, position->y, &xf, &yf);
x = RINT (xf);
if (mapvals.transparent_background && heights[1][x] == 0)
{
gimp_rgb_set_alpha (&color_sum, 0.0);
......@@ -422,19 +423,23 @@ get_ray_color (GimpVector3 *position)
else
{
color = get_image_color (xf, yf, &f);
color_sum = color;
gimp_rgb_multiply (&color_sum, mapvals.material.ambient_int);
for (k = 0; k < NUM_LIGHTS; k++)
{
if (mapvals.lightsource[k].type == NO_LIGHT)
if (!mapvals.lightsource[k].active
|| mapvals.lightsource[k].type == NO_LIGHT)
continue;
else if (mapvals.lightsource[k].type == POINT_LIGHT)
p = &mapvals.lightsource[k].position;
else
p = &mapvals.lightsource[k].direction;
color_int = mapvals.lightsource[k].color;
gimp_rgb_multiply (&color_int, mapvals.lightsource[k].intensity);
if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1)
{
light_color = phong_shade (position,
......@@ -442,22 +447,22 @@ get_ray_color (GimpVector3 *position)
&mapvals.planenormal,
p,
&color,
&mapvals.lightsource[k].color,
&color_int,
mapvals.lightsource[k].type);
}
else
{
normal = vertex_normals[1][(gint) RINT (xf)];
light_color = phong_shade (position,
&mapvals.viewpoint,
&normal,
p,
&color,
&mapvals.lightsource[k].color,
&color_int,
mapvals.lightsource[k].type);
}
gimp_rgb_add (&color_sum, &light_color);
}
}
......@@ -469,10 +474,14 @@ get_ray_color (GimpVector3 *position)
GimpRGB
get_ray_color_ref (GimpVector3 *position)
{
GimpRGB color_sum;
GimpRGB color_int;
GimpRGB light_color;
GimpRGB color, env_color;
gint x, f;
gdouble xf, yf;
GimpVector3 normal, *p, v, r;
gint x, f;
gdouble xf, yf;
GimpVector3 normal, *p, v, r;
gint k;
pos_to_float (position->x, position->y, &xf, &yf);
......@@ -485,60 +494,74 @@ get_ray_color_ref (GimpVector3 *position)
else
{
color = get_image_color (xf, yf, &f);
color_sum = color;
if (mapvals.lightsource[0].type == POINT_LIGHT)
p = &mapvals.lightsource[0].position;
else
p = &mapvals.lightsource[0].direction;
if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1)
{
color = phong_shade (position,
&mapvals.viewpoint,
&mapvals.planenormal,
p,
&color,
&mapvals.lightsource[0].color,
mapvals.lightsource[0].type);
}
else
for (k = 0; k < NUM_LIGHTS; k++)
{
normal = vertex_normals[1][(gint) RINT (xf)];
if (!mapvals.lightsource[k].active
|| mapvals.lightsource[k].type == NO_LIGHT)
continue;
else if (mapvals.lightsource[k].type == POINT_LIGHT)
p = &mapvals.lightsource[k].position;
else
p = &mapvals.lightsource[k].direction;
gimp_vector3_sub (&v, &mapvals.viewpoint,position);
gimp_vector3_normalize (&v);
color_int = mapvals.lightsource[k].color;
gimp_rgb_multiply (&color_int, mapvals.lightsource[k].intensity);
r = compute_reflected_ray (&normal, &v);
if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1)
{
light_color = phong_shade (position,
&mapvals.viewpoint,
&mapvals.planenormal,
p,
&color,
&color_int,
mapvals.lightsource[0].type);
}
else
{
normal = vertex_normals[1][(gint) RINT (xf)];
gimp_vector3_sub (&v, &mapvals.viewpoint,position);
gimp_vector3_normalize (&v);
/* Get color in the direction of r */
/* =============================== */
r = compute_reflected_ray (&normal, &v);
sphere_to_image (&r, &xf, &yf);
env_color = peek_env_map (RINT (env_width * xf),
RINT (env_height * yf));
/* Get color in the direction of r */
/* =============================== */
color = phong_shade (position,
&mapvals.viewpoint,
&normal,
p,
&env_color,
&mapvals.lightsource[0].color,
mapvals.lightsource[0].type);
sphere_to_image (&r, &xf, &yf);
env_color = peek_env_map (RINT (env_width * xf),
RINT (env_height * yf));
light_color = phong_shade (position,