diff options
Diffstat (limited to 'libdimension')
-rw-r--r-- | libdimension/dimension/finishes.h | 5 | ||||
-rw-r--r-- | libdimension/finishes.c | 51 | ||||
-rw-r--r-- | libdimension/scene.c | 4 |
3 files changed, 48 insertions, 12 deletions
diff --git a/libdimension/dimension/finishes.h b/libdimension/dimension/finishes.h index 5f00d43..e3d0597 100644 --- a/libdimension/dimension/finishes.h +++ b/libdimension/dimension/finishes.h @@ -25,7 +25,8 @@ #ifndef DIMENSION_FINISHES_H #define DIMENSION_FINISHES_H -/* A diffuse finish */ -dmnsn_finish *dmnsn_new_diffuse_finish(); +/* A phong finish */ +dmnsn_finish *dmnsn_new_phong_finish(double diffuse, double specular, + double exp); #endif /* DIMENSION_FINISHES_H */ diff --git a/libdimension/finishes.c b/libdimension/finishes.c index d70cfb7..a7cfaea 100644 --- a/libdimension/finishes.c +++ b/libdimension/finishes.c @@ -20,25 +20,56 @@ #include "dimension.h" #include <stdlib.h> /* For malloc */ +#include <math.h> 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) +dmnsn_phong_finish_fn(const dmnsn_finish *finish, + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer) { - double diffuse = dmnsn_vector_dot(ray, normal); - dmnsn_color illum = dmnsn_color_illuminate(light, color); - return dmnsn_color_mul(diffuse, illum); + 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 */ + + 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); } -/* A diffuse finish */ +/* A phong finish */ dmnsn_finish * -dmnsn_new_diffuse_finish() +dmnsn_new_phong_finish(double diffuse, double specular, double exp) { dmnsn_finish *finish = dmnsn_new_finish(); if (finish) { - finish->finish_fn = &dmnsn_diffuse_finish_fn; + double *params = malloc(3*sizeof(double)); + if (!params) { + dmnsn_delete_finish(finish); + return NULL; + } + + params[0] = diffuse; + params[1] = specular; + params[2] = exp; + + finish->ptr = params; + finish->finish_fn = &dmnsn_phong_finish_fn; + finish->free_fn = &free; } return finish; } diff --git a/libdimension/scene.c b/libdimension/scene.c index 38b1d19..7a39679 100644 --- a/libdimension/scene.c +++ b/libdimension/scene.c @@ -28,6 +28,10 @@ dmnsn_new_scene() dmnsn_scene *scene = malloc(sizeof(dmnsn_scene)); if (scene) { scene->default_texture = dmnsn_new_texture(); + if (!scene->default_texture) { + dmnsn_delete_scene(scene); + return NULL; + } scene->camera = NULL; scene->canvas = NULL; |