diff options
Diffstat (limited to 'libdimension')
-rw-r--r-- | libdimension/dimension/finish.h | 59 | ||||
-rw-r--r-- | libdimension/finish.c | 66 | ||||
-rw-r--r-- | libdimension/lambertian.c | 27 | ||||
-rw-r--r-- | libdimension/phong.c | 37 | ||||
-rw-r--r-- | libdimension/reflection.c | 28 |
5 files changed, 128 insertions, 89 deletions
diff --git a/libdimension/dimension/finish.h b/libdimension/dimension/finish.h index 5ff6a2c..5f2443b 100644 --- a/libdimension/dimension/finish.h +++ b/libdimension/dimension/finish.h @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> * + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * * * * This file is part of The Dimension Library. * * * @@ -25,22 +25,11 @@ /* Ambient component */ -typedef struct dmnsn_ambient dmnsn_ambient; - -/** - * Ambient light callback. - * @param[in] ambient The ambient object itself. - * @param[in] pigment The pigment of the object. - * @return The ambient contribution to the object's color. - */ -typedef dmnsn_color dmnsn_ambient_fn(const dmnsn_ambient *ambient, - dmnsn_color pigment); - /** Ambient finish component. */ -struct dmnsn_ambient { +typedef struct dmnsn_ambient { dmnsn_color ambient; /**< Ambient light. */ DMNSN_REFCOUNT; /**< Reference count. */ -}; +} dmnsn_ambient; /** Allocate a dummy ambient component. */ dmnsn_ambient *dmnsn_new_ambient(dmnsn_color ambient); @@ -64,16 +53,24 @@ typedef dmnsn_color dmnsn_diffuse_fn(const dmnsn_diffuse *diffuse, dmnsn_color light, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal); +/** + * Diffuse destruction callback. + * @param[in,out] diffuse The diffuse object to destroy. + */ +typedef void dmnsn_diffuse_free_fn(dmnsn_diffuse *diffuse); + /** Diffuse finish component. */ struct dmnsn_diffuse { dmnsn_diffuse_fn *diffuse_fn; /**< Diffuse callback. */ - dmnsn_free_fn *free_fn; /**< Destructor callback. */ - void *ptr; /**< Generic data pointer. */ - DMNSN_REFCOUNT; /**< Reference count. */ + dmnsn_diffuse_free_fn *free_fn; /**< Destructor callback. */ + + DMNSN_REFCOUNT; /**< Reference count. */ }; /** Allocate a dummy diffuse component. */ dmnsn_diffuse *dmnsn_new_diffuse(void); +/** Initialize a dmnsn_diffuse field. */ +void dmnsn_init_diffuse(dmnsn_diffuse *diffuse); /** Delete a diffuse component. */ void dmnsn_delete_diffuse(dmnsn_diffuse *diffuse); @@ -96,16 +93,24 @@ typedef dmnsn_color dmnsn_specular_fn(const dmnsn_specular *specular, dmnsn_vector ray, dmnsn_vector normal, dmnsn_vector viewer); +/** + * Specular destruction callback. + * @param[in,out] specular The specular object to destroy. + */ +typedef void dmnsn_specular_free_fn(dmnsn_specular *specular); + /** Specular finish component. */ struct dmnsn_specular { dmnsn_specular_fn *specular_fn; /**< Specular callback. */ - dmnsn_free_fn *free_fn; /**< Destructor callback. */ - void *ptr; /**< Generic data pointer. */ - DMNSN_REFCOUNT; /**< Reference count. */ + dmnsn_specular_free_fn *free_fn; /**< Destructor callback. */ + + DMNSN_REFCOUNT; /**< Reference count. */ }; /** Allocate a dummy specular component. */ dmnsn_specular *dmnsn_new_specular(void); +/** Initialize a dmnsn_specular field. */ +void dmnsn_init_specular(dmnsn_specular *specular); /** Delete a specular component. */ void dmnsn_delete_specular(dmnsn_specular *specular); @@ -126,16 +131,24 @@ typedef dmnsn_color dmnsn_reflection_fn(const dmnsn_reflection *reflection, dmnsn_color reflect, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal); +/** + * Reflection destruction callback. + * @param[in,out] reflection The reflection object to destroy. + */ +typedef void dmnsn_reflection_free_fn(dmnsn_reflection *reflection); + /** The reflection component. */ struct dmnsn_reflection { dmnsn_reflection_fn *reflection_fn; /**< Reflection callback. */ - dmnsn_free_fn *free_fn; /**< Destructor callback. */ - void *ptr; /**< Generic data pointer. */ - DMNSN_REFCOUNT; /**< Reference count. */ + dmnsn_reflection_free_fn *free_fn; /**< Destructor callback. */ + + DMNSN_REFCOUNT; /**< Reference count. */ }; /** Allocate a dummy reflection component. */ dmnsn_reflection *dmnsn_new_reflection(void); +/** Initialize a dmnsn_reflection field. */ +void dmnsn_init_reflection(dmnsn_reflection *reflection); /** Delete a reflection component. */ void dmnsn_delete_reflection(dmnsn_reflection *reflection); diff --git a/libdimension/finish.c b/libdimension/finish.c index 6178db3..276969d 100644 --- a/libdimension/finish.c +++ b/libdimension/finish.c @@ -42,66 +42,90 @@ dmnsn_delete_ambient(dmnsn_ambient *ambient) } } +static void +dmnsn_default_diffuse_free_fn(dmnsn_diffuse *diffuse) +{ + dmnsn_free(diffuse); +} + dmnsn_diffuse * dmnsn_new_diffuse(void) { dmnsn_diffuse *diffuse = DMNSN_MALLOC(dmnsn_diffuse); - diffuse->free_fn = NULL; - diffuse->ptr = NULL; - DMNSN_REFCOUNT_INIT(diffuse); + dmnsn_init_diffuse(diffuse); return diffuse; } void +dmnsn_init_diffuse(dmnsn_diffuse *diffuse) +{ + diffuse->free_fn = dmnsn_default_diffuse_free_fn; + DMNSN_REFCOUNT_INIT(diffuse); +} + +void dmnsn_delete_diffuse(dmnsn_diffuse *diffuse) { if (DMNSN_DECREF(diffuse)) { - if (diffuse->free_fn) { - diffuse->free_fn(diffuse->ptr); - } - dmnsn_free(diffuse); + diffuse->free_fn(diffuse); } } +static void +dmnsn_default_specular_free_fn(dmnsn_specular *specular) +{ + dmnsn_free(specular); +} + dmnsn_specular * dmnsn_new_specular(void) { dmnsn_specular *specular = DMNSN_MALLOC(dmnsn_specular); - specular->free_fn = NULL; - specular->ptr = NULL; - DMNSN_REFCOUNT_INIT(specular); + dmnsn_init_specular(specular); return specular; } void +dmnsn_init_specular(dmnsn_specular *specular) +{ + specular->free_fn = dmnsn_default_specular_free_fn; + DMNSN_REFCOUNT_INIT(specular); +} + +void dmnsn_delete_specular(dmnsn_specular *specular) { if (DMNSN_DECREF(specular)) { - if (specular->free_fn) { - specular->free_fn(specular->ptr); - } - dmnsn_free(specular); + specular->free_fn(specular); } } +static void +dmnsn_default_reflection_free_fn(dmnsn_reflection *reflection) +{ + dmnsn_free(reflection); +} + dmnsn_reflection * dmnsn_new_reflection(void) { dmnsn_reflection *reflection = DMNSN_MALLOC(dmnsn_reflection); - reflection->free_fn = NULL; - reflection->ptr = NULL; - DMNSN_REFCOUNT_INIT(reflection); + dmnsn_init_reflection(reflection); return reflection; } void +dmnsn_init_reflection(dmnsn_reflection *reflection) +{ + reflection->free_fn = dmnsn_default_reflection_free_fn; + DMNSN_REFCOUNT_INIT(reflection); +} + +void dmnsn_delete_reflection(dmnsn_reflection *reflection) { if (DMNSN_DECREF(reflection)) { - if (reflection->free_fn) { - reflection->free_fn(reflection->ptr); - } - dmnsn_free(reflection); + reflection->free_fn(reflection); } } diff --git a/libdimension/lambertian.c b/libdimension/lambertian.c index 17bed6d..9b305df 100644 --- a/libdimension/lambertian.c +++ b/libdimension/lambertian.c @@ -27,28 +27,31 @@ #include <math.h> #include <stdlib.h> +/** Lambertian diffuse type. */ +typedef struct dmnsn_lambertian { + dmnsn_diffuse diffuse; + double coeff; +} dmnsn_lambertian; + /** Diffuse finish callback. */ static dmnsn_color dmnsn_lambertian_diffuse_fn(const dmnsn_diffuse *diffuse, dmnsn_color light, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal) { - double *coeff = diffuse->ptr; - double diffuse_factor = fabs((*coeff)*dmnsn_vector_dot(ray, normal)); + const dmnsn_lambertian *lambertian = (const dmnsn_lambertian *)diffuse; + double diffuse_factor = fabs((lambertian->coeff)*dmnsn_vector_dot(ray, normal)); return dmnsn_color_mul(diffuse_factor, dmnsn_color_illuminate(light, color)); } dmnsn_diffuse * -dmnsn_new_lambertian(double diffuse) +dmnsn_new_lambertian(double coeff) { - dmnsn_diffuse *lambertian = dmnsn_new_diffuse(); - - double *param = DMNSN_MALLOC(double); - *param = diffuse; - - lambertian->diffuse_fn = dmnsn_lambertian_diffuse_fn; - lambertian->free_fn = dmnsn_free; - lambertian->ptr = param; + dmnsn_lambertian *lambertian = DMNSN_MALLOC(dmnsn_lambertian); + lambertian->coeff = coeff; - return lambertian; + dmnsn_diffuse *diffuse = &lambertian->diffuse; + dmnsn_init_diffuse(diffuse); + diffuse->diffuse_fn = dmnsn_lambertian_diffuse_fn; + return diffuse; } diff --git a/libdimension/phong.c b/libdimension/phong.c index 2bfbe90..bbf521d 100644 --- a/libdimension/phong.c +++ b/libdimension/phong.c @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> * + * Copyright (C) 2010-2014 Tavian Barnes <tavianator@tavianator.com> * * * * This file is part of The Dimension Library. * * * @@ -26,6 +26,13 @@ #include "dimension.h" #include <stdlib.h> +/** Phone specular type. */ +typedef struct dmnsn_phong { + dmnsn_specular specular; + double coeff; + double exp; +} dmnsn_phong; + /** Phong specular highlight callback. */ static dmnsn_color dmnsn_phong_specular_fn(const dmnsn_specular *specular, @@ -33,10 +40,7 @@ dmnsn_phong_specular_fn(const dmnsn_specular *specular, dmnsn_vector ray, dmnsn_vector normal, dmnsn_vector viewer) { - double *params = specular->ptr; - - double coeff = params[0]; - double exp = params[1]; + const dmnsn_phong *phong = (const dmnsn_phong *)specular; dmnsn_vector proj = dmnsn_vector_mul(2*dmnsn_vector_dot(ray, normal), normal); dmnsn_vector reflected = dmnsn_vector_sub(proj, ray); @@ -46,23 +50,20 @@ dmnsn_phong_specular_fn(const dmnsn_specular *specular, return dmnsn_black; } - specular_factor = pow(specular_factor, exp); - return dmnsn_color_mul(coeff*specular_factor, light); + specular_factor = pow(specular_factor, phong->exp); + return dmnsn_color_mul(phong->coeff*specular_factor, light); } /* A phong finish */ dmnsn_specular * -dmnsn_new_phong(double specular, double exp) +dmnsn_new_phong(double coeff, double exp) { - dmnsn_specular *phong = dmnsn_new_specular(); - - double *params = dmnsn_malloc(2*sizeof(double)); - params[0] = specular; - params[1] = exp; - - phong->specular_fn = dmnsn_phong_specular_fn; - phong->free_fn = dmnsn_free; - phong->ptr = params; + dmnsn_phong *phong = DMNSN_MALLOC(dmnsn_phong); + phong->coeff = coeff; + phong->exp = exp; - return phong; + dmnsn_specular *specular = &phong->specular; + dmnsn_init_specular(specular); + specular->specular_fn = dmnsn_phong_specular_fn; + return specular; } diff --git a/libdimension/reflection.c b/libdimension/reflection.c index 934fcf6..ca279b8 100644 --- a/libdimension/reflection.c +++ b/libdimension/reflection.c @@ -27,11 +27,12 @@ #include <math.h> #include <stdlib.h> -/** Reflective finish payload. */ -typedef struct dmnsn_reflection_params { +/** Basic reflective finish type. */ +typedef struct dmnsn_basic_reflection { + dmnsn_reflection reflection; dmnsn_color min, max; double falloff; -} dmnsn_reflection_params; +} dmnsn_basic_reflection; /** Reflective finish callback. */ static dmnsn_color @@ -39,11 +40,11 @@ dmnsn_basic_reflection_fn(const dmnsn_reflection *reflection, dmnsn_color reflect, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal) { - dmnsn_reflection_params *params = reflection->ptr; - double coeff = pow(fabs(dmnsn_vector_dot(ray, normal)), params->falloff); + const dmnsn_basic_reflection *basic = (const dmnsn_basic_reflection *)reflection; + double coeff = pow(fabs(dmnsn_vector_dot(ray, normal)), basic->falloff); return dmnsn_color_illuminate( - dmnsn_color_gradient(params->min, params->max, coeff), + dmnsn_color_gradient(basic->min, basic->max, coeff), reflect ); } @@ -51,16 +52,13 @@ dmnsn_basic_reflection_fn(const dmnsn_reflection *reflection, dmnsn_reflection * dmnsn_new_basic_reflection(dmnsn_color min, dmnsn_color max, double falloff) { - dmnsn_reflection *reflection = dmnsn_new_reflection(); - - dmnsn_reflection_params *params = DMNSN_MALLOC(dmnsn_reflection_params); - params->min = min; - params->max = max; - params->falloff = falloff; + dmnsn_basic_reflection *basic = DMNSN_MALLOC(dmnsn_basic_reflection); + basic->min = min; + basic->max = max; + basic->falloff = falloff; + dmnsn_reflection *reflection = &basic->reflection; + dmnsn_init_reflection(reflection); reflection->reflection_fn = dmnsn_basic_reflection_fn; - reflection->free_fn = dmnsn_free; - reflection->ptr = params; - return reflection; } |