summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/dimension/finish.h59
-rw-r--r--libdimension/finish.c66
-rw-r--r--libdimension/lambertian.c27
-rw-r--r--libdimension/phong.c37
-rw-r--r--libdimension/reflection.c28
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;
}