From a9ce26a1cd786690b4b8f4b54fc7077b3d3569e5 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 23 Dec 2009 02:04:32 -0500 Subject: Separate finishes into single-purpose finishes. --- libdimension/dimension/finishes.h | 11 ++- libdimension/dimension/texture.h | 6 +- libdimension/finishes.c | 174 +++++++++++++++++++++++++++++++++----- libdimension/raytrace.c | 8 +- libdimension/texture.c | 4 +- 5 files changed, 172 insertions(+), 31 deletions(-) (limited to 'libdimension') diff --git a/libdimension/dimension/finishes.h b/libdimension/dimension/finishes.h index e3d0597..b836e51 100644 --- a/libdimension/dimension/finishes.h +++ b/libdimension/dimension/finishes.h @@ -25,8 +25,13 @@ #ifndef DIMENSION_FINISHES_H #define DIMENSION_FINISHES_H -/* A phong finish */ -dmnsn_finish *dmnsn_new_phong_finish(double diffuse, double specular, - double exp); +/* Add two finishes */ +dmnsn_finish *dmnsn_new_finish_combination(dmnsn_finish *f1, dmnsn_finish *f2); + +dmnsn_finish *dmnsn_new_ambient_finish(dmnsn_color ambient); +dmnsn_finish *dmnsn_new_diffuse_finish(double diffuse); + +/* A phong specular highlight */ +dmnsn_finish *dmnsn_new_phong_finish(double specular, double exp); #endif /* DIMENSION_FINISHES_H */ diff --git a/libdimension/dimension/texture.h b/libdimension/dimension/texture.h index e5a1bfd..c5f4b3f 100644 --- a/libdimension/dimension/texture.h +++ b/libdimension/dimension/texture.h @@ -61,14 +61,14 @@ typedef dmnsn_color dmnsn_finish_fn(const dmnsn_finish *finish, dmnsn_color light, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal, dmnsn_vector viewer); +typedef dmnsn_color dmnsn_ambient_fn(const dmnsn_finish *finish, + dmnsn_color pigment); /* dmnsn_finish definition */ struct dmnsn_finish { - /* Ambient contribution factor */ - double ambient; - /* Callbacks */ dmnsn_finish_fn *finish_fn; + dmnsn_ambient_fn *ambient_fn; dmnsn_free_fn *free_fn; /* Generic pointer */ diff --git a/libdimension/finishes.c b/libdimension/finishes.c index a7cfaea..a8347bd 100644 --- a/libdimension/finishes.c +++ b/libdimension/finishes.c @@ -22,7 +22,151 @@ #include /* For malloc */ #include -dmnsn_color +/* + * Finish combinations + */ + +static dmnsn_color +dmnsn_finish_combination_fn(const dmnsn_finish *finish, + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer) +{ + dmnsn_finish **params = finish->ptr; + if (params[0]->finish_fn && params[1]->finish_fn) { + return dmnsn_color_add((*params[0]->finish_fn)(params[0], light, color, ray, + normal, viewer), + (*params[1]->finish_fn)(params[1], light, color, ray, + normal, viewer)); + } else if (params[0]->finish_fn) { + return (*params[0]->finish_fn)(params[0], light, color, ray, + normal, viewer); + } else if (params[1]->finish_fn) { + return (*params[1]->finish_fn)(params[1], light, color, ray, + normal, viewer); + } else { + return dmnsn_black; + } +} + +static dmnsn_color +dmnsn_finish_combination_ambient_fn(const dmnsn_finish *finish, + dmnsn_color pigment) +{ + dmnsn_finish **params = finish->ptr; + if (params[0]->ambient_fn && params[1]->ambient_fn) { + return dmnsn_color_add((*params[0]->ambient_fn)(params[0], pigment), + (*params[1]->ambient_fn)(params[1], pigment)); + } else if (params[0]->ambient_fn) { + return (*params[0]->ambient_fn)(params[0], pigment); + } else if (params[1]->ambient_fn) { + return (*params[1]->ambient_fn)(params[1], pigment); + } else { + return dmnsn_black; + } +} + +static void +dmnsn_finish_combination_free_fn(void *ptr) +{ + dmnsn_finish **params = ptr; + dmnsn_delete_finish(params[0]); + dmnsn_delete_finish(params[1]); + free(ptr); +} + +dmnsn_finish * +dmnsn_new_finish_combination(dmnsn_finish *f1, dmnsn_finish *f2) +{ + dmnsn_finish *finish = dmnsn_new_finish(); + if (finish) { + dmnsn_finish **params = malloc(2*sizeof(dmnsn_finish *)); + if (!params) { + dmnsn_delete_finish(finish); + return NULL; + } + + params[0] = f1; + params[1] = f2; + + finish->ptr = params; + finish->finish_fn = &dmnsn_finish_combination_fn; + finish->ambient_fn = &dmnsn_finish_combination_ambient_fn; + finish->free_fn = &dmnsn_finish_combination_free_fn; + } + return finish; +} + +/* + * Ambient finish + */ + +static dmnsn_color +dmnsn_ambient_finish_fn(const dmnsn_finish *finish, dmnsn_color pigment) +{ + dmnsn_color *ambient = finish->ptr; + return dmnsn_color_illuminate(*ambient, pigment); +} + +dmnsn_finish * +dmnsn_new_ambient_finish(dmnsn_color ambient) +{ + dmnsn_finish *finish = dmnsn_new_finish(); + if (finish) { + dmnsn_color *param = malloc(sizeof(dmnsn_color)); + if (!param) { + dmnsn_delete_finish(finish); + return NULL; + } + + *param = ambient; + finish->ptr = param; + finish->ambient_fn = &dmnsn_ambient_finish_fn; + finish->free_fn = &free; + } + return finish; +} + +/* + * Diffuse finish + */ + +static dmnsn_color +dmnsn_diffuse_finish_fn(const dmnsn_finish *finish, + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer) +{ + double *diffuse = finish->ptr; + double diffuse_factor = (*diffuse)*dmnsn_vector_dot(ray, normal); + return dmnsn_color_mul(diffuse_factor, dmnsn_color_illuminate(light, color)); +} + +dmnsn_finish * +dmnsn_new_diffuse_finish(double diffuse) +{ + dmnsn_finish *finish = dmnsn_new_finish(); + if (finish) { + double *param = malloc(sizeof(double)); + if (!param) { + dmnsn_delete_finish(finish); + return NULL; + } + + *param = diffuse; + + finish->ptr = param; + finish->finish_fn = &dmnsn_diffuse_finish_fn; + finish->free_fn = &free; + } + return finish; +} + +/* + * Phong finish + */ + +static dmnsn_color dmnsn_phong_finish_fn(const dmnsn_finish *finish, dmnsn_color light, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal, @@ -30,42 +174,30 @@ dmnsn_phong_finish_fn(const dmnsn_finish *finish, { double *params = finish->ptr; - double diffuse = params[0]; - double specular = params[1]; - double exp = params[2]; - - /* Diffuse component */ - double diffuse_factor = diffuse*dmnsn_vector_dot(ray, normal); - dmnsn_color diffuse_color - = dmnsn_color_mul(diffuse_factor, dmnsn_color_illuminate(light, color)); - - /* Specular component */ + double specular = params[0]; + double exp = params[1]; dmnsn_vector proj = dmnsn_vector_mul(2*dmnsn_vector_dot(ray, normal), normal); dmnsn_vector reflected = dmnsn_vector_sub(proj, ray); - double specular_factor - = specular*pow(dmnsn_vector_dot(reflected, viewer), exp); - dmnsn_color specular_color = dmnsn_color_mul(specular_factor, light); - - return dmnsn_color_add(diffuse_color, specular_color); + double specular_factor = pow(dmnsn_vector_dot(reflected, viewer), exp); + return dmnsn_color_mul(specular*specular_factor, light); } /* A phong finish */ dmnsn_finish * -dmnsn_new_phong_finish(double diffuse, double specular, double exp) +dmnsn_new_phong_finish(double specular, double exp) { dmnsn_finish *finish = dmnsn_new_finish(); if (finish) { - double *params = malloc(3*sizeof(double)); + double *params = malloc(2*sizeof(double)); if (!params) { dmnsn_delete_finish(finish); return NULL; } - params[0] = diffuse; - params[1] = specular; - params[2] = exp; + params[0] = specular; + params[1] = exp; finish->ptr = params; finish->finish_fn = &dmnsn_phong_finish_fn; diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c index 71e60cd..594149c 100644 --- a/libdimension/raytrace.c +++ b/libdimension/raytrace.c @@ -359,8 +359,8 @@ dmnsn_raytrace_lighting(dmnsn_intersection *intersection, dmnsn_scene *scene, /* The illuminated color */ dmnsn_color illum = dmnsn_black; - if (finish) - illum = dmnsn_color_mul(finish->ambient, color); + if (finish && finish->ambient_fn) + illum = (*finish->ambient_fn)(finish, color); dmnsn_vector x0 = dmnsn_line_point(intersection->ray, intersection->t); @@ -375,7 +375,9 @@ dmnsn_raytrace_lighting(dmnsn_intersection *intersection, dmnsn_scene *scene, if (dmnsn_raytrace_light_ray(intersection, scene, kD_splay_tree, light, &light_color)) { - if (scene->quality >= DMNSN_RENDER_FINISH && finish) { + if (scene->quality >= DMNSN_RENDER_FINISH + && finish && finish->finish_fn) + { dmnsn_vector ray = dmnsn_vector_normalize( dmnsn_vector_sub(light->x0, x0) ); diff --git a/libdimension/texture.c b/libdimension/texture.c index a9d7de1..5fdd708 100644 --- a/libdimension/texture.c +++ b/libdimension/texture.c @@ -50,7 +50,9 @@ dmnsn_new_finish() { dmnsn_finish *finish = malloc(sizeof(dmnsn_finish)); if (finish) { - finish->free_fn = NULL; + finish->finish_fn = NULL; + finish->ambient_fn = NULL; + finish->free_fn = NULL; } return finish; } -- cgit v1.2.3