summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/cone.c18
-rw-r--r--libdimension/csg.c47
-rw-r--r--libdimension/cube.c9
-rw-r--r--libdimension/dimension/object.h19
-rw-r--r--libdimension/object.c20
-rw-r--r--libdimension/plane.c46
-rw-r--r--libdimension/sphere.c10
-rw-r--r--libdimension/torus.c10
-rw-r--r--libdimension/triangle.c18
9 files changed, 123 insertions, 74 deletions
diff --git a/libdimension/cone.c b/libdimension/cone.c
index c83a260..b221380 100644
--- a/libdimension/cone.c
+++ b/libdimension/cone.c
@@ -89,6 +89,12 @@ dmnsn_cone_inside_fn(const dmnsn_object *object, dmnsn_vector point)
&& point.y > -1.0 && point.y < 1.0;
}
+/** Cone vtable. */
+static const dmnsn_object_vtable dmnsn_cone_vtable = {
+ .intersection_fn = dmnsn_cone_intersection_fn,
+ .inside_fn = dmnsn_cone_inside_fn,
+};
+
/** Cone cap type. */
typedef struct dmnsn_cone_cap {
dmnsn_object object;
@@ -122,6 +128,12 @@ dmnsn_cone_cap_inside_fn(const dmnsn_object *object, dmnsn_vector point)
return false;
}
+/** Cone cap vtable. */
+static const dmnsn_object_vtable dmnsn_cone_cap_vtable = {
+ .intersection_fn = dmnsn_cone_cap_intersection_fn,
+ .inside_fn = dmnsn_cone_cap_inside_fn,
+};
+
/** Allocate a new cone cap. */
dmnsn_object *
dmnsn_new_cone_cap(dmnsn_pool *pool, double r)
@@ -131,8 +143,7 @@ dmnsn_new_cone_cap(dmnsn_pool *pool, double r)
dmnsn_object *object = &cap->object;
dmnsn_init_object(object);
- object->intersection_fn = dmnsn_cone_cap_intersection_fn;
- object->inside_fn = dmnsn_cone_cap_inside_fn;
+ object->vtable = &dmnsn_cone_cap_vtable;
object->bounding_box.min = dmnsn_new_vector(-r, 0.0, -r);
object->bounding_box.max = dmnsn_new_vector(+r, 0.0, +r);
return object;
@@ -148,8 +159,7 @@ dmnsn_new_cone(dmnsn_pool *pool, double r1, double r2, bool open)
dmnsn_object *object = &cone->object;
dmnsn_init_object(object);
- object->intersection_fn = dmnsn_cone_intersection_fn;
- object->inside_fn = dmnsn_cone_inside_fn;
+ object->vtable = &dmnsn_cone_vtable;
double rmax = dmnsn_max(r1, r2);
object->bounding_box.min = dmnsn_new_vector(-rmax, -1.0, -rmax);
diff --git a/libdimension/csg.c b/libdimension/csg.c
index a8d0acc..e4ee672 100644
--- a/libdimension/csg.c
+++ b/libdimension/csg.c
@@ -65,6 +65,13 @@ dmnsn_csg_union_initialize_fn(dmnsn_object *object)
csg->object.bounding_box = dmnsn_bvh_bounding_box(bvh);
}
+/** CSG union vtable. */
+static const dmnsn_object_vtable dmnsn_csg_union_vtable = {
+ .intersection_fn = dmnsn_csg_union_intersection_fn,
+ .inside_fn = dmnsn_csg_union_inside_fn,
+ .initialize_fn = dmnsn_csg_union_initialize_fn,
+};
+
/** CSG union destruction callback. */
static void
dmnsn_csg_union_cleanup(void *ptr)
@@ -83,11 +90,9 @@ dmnsn_new_csg_union(dmnsn_pool *pool, dmnsn_array *objects)
dmnsn_object *object = &csg->object;
dmnsn_init_object(object);
+ object->vtable = &dmnsn_csg_union_vtable;
object->children = objects;
object->split_children = true;
- object->intersection_fn = dmnsn_csg_union_intersection_fn;
- object->inside_fn = dmnsn_csg_union_inside_fn;
- object->initialize_fn = dmnsn_csg_union_initialize_fn;
return object;
}
@@ -202,19 +207,23 @@ dmnsn_csg_intersection_initialize_fn(dmnsn_object *csg)
= dmnsn_vector_min(A->bounding_box.max, B->bounding_box.max);
}
+/** CSG intersection vtable. */
+static const dmnsn_object_vtable dmnsn_csg_intersection_vtable = {
+ .intersection_fn = dmnsn_csg_intersection_intersection_fn,
+ .inside_fn = dmnsn_csg_intersection_inside_fn,
+ .initialize_fn = dmnsn_csg_intersection_initialize_fn,
+};
+
dmnsn_object *
dmnsn_new_csg_intersection(dmnsn_pool *pool, dmnsn_object *A, dmnsn_object *B)
{
dmnsn_object *csg = dmnsn_new_object(pool);
+ csg->vtable = &dmnsn_csg_intersection_vtable;
csg->children = DMNSN_PALLOC_ARRAY(pool, dmnsn_object *);
dmnsn_array_push(csg->children, &A);
dmnsn_array_push(csg->children, &B);
- csg->intersection_fn = dmnsn_csg_intersection_intersection_fn;
- csg->inside_fn = dmnsn_csg_intersection_inside_fn;
- csg->initialize_fn = dmnsn_csg_intersection_initialize_fn;
-
return csg;
}
@@ -250,19 +259,23 @@ dmnsn_csg_difference_initialize_fn(dmnsn_object *csg)
csg->bounding_box = A->bounding_box;
}
+/** CSG difference vtable. */
+static const dmnsn_object_vtable dmnsn_csg_difference_vtable = {
+ .intersection_fn = dmnsn_csg_difference_intersection_fn,
+ .inside_fn = dmnsn_csg_difference_inside_fn,
+ .initialize_fn = dmnsn_csg_difference_initialize_fn,
+};
+
dmnsn_object *
dmnsn_new_csg_difference(dmnsn_pool *pool, dmnsn_object *A, dmnsn_object *B)
{
dmnsn_object *csg = dmnsn_new_object(pool);
+ csg->vtable = &dmnsn_csg_difference_vtable;
csg->children = DMNSN_PALLOC_ARRAY(pool, dmnsn_object *);
dmnsn_array_push(csg->children, &A);
dmnsn_array_push(csg->children, &B);
- csg->intersection_fn = dmnsn_csg_difference_intersection_fn;
- csg->inside_fn = dmnsn_csg_difference_inside_fn;
- csg->initialize_fn = dmnsn_csg_difference_initialize_fn;
-
return csg;
}
@@ -302,18 +315,22 @@ dmnsn_csg_merge_initialize_fn(dmnsn_object *csg)
= dmnsn_vector_max(A->bounding_box.max, B->bounding_box.max);
}
+/** CSG merge vtable. */
+static const dmnsn_object_vtable dmnsn_csg_merge_vtable = {
+ .intersection_fn = dmnsn_csg_merge_intersection_fn,
+ .inside_fn = dmnsn_csg_merge_inside_fn,
+ .initialize_fn = dmnsn_csg_merge_initialize_fn,
+};
+
dmnsn_object *
dmnsn_new_csg_merge(dmnsn_pool *pool, dmnsn_object *A, dmnsn_object *B)
{
dmnsn_object *csg = dmnsn_new_object(pool);
+ csg->vtable = &dmnsn_csg_merge_vtable;
csg->children = DMNSN_PALLOC_ARRAY(pool, dmnsn_object *);
dmnsn_array_push(csg->children, &A);
dmnsn_array_push(csg->children, &B);
- csg->intersection_fn = dmnsn_csg_merge_intersection_fn;
- csg->inside_fn = dmnsn_csg_merge_inside_fn;
- csg->initialize_fn = dmnsn_csg_merge_initialize_fn;
-
return csg;
}
diff --git a/libdimension/cube.c b/libdimension/cube.c
index 8a1a503..d4c9d5b 100644
--- a/libdimension/cube.c
+++ b/libdimension/cube.c
@@ -129,13 +129,18 @@ dmnsn_cube_inside_fn(const dmnsn_object *cube, dmnsn_vector point)
&& point.z > -1.0 && point.z < 1.0;
}
+/** Cube vtable. */
+static const dmnsn_object_vtable dmnsn_cube_vtable = {
+ .intersection_fn = dmnsn_cube_intersection_fn,
+ .inside_fn = dmnsn_cube_inside_fn,
+};
+
/* Allocate a new cube object */
dmnsn_object *
dmnsn_new_cube(dmnsn_pool *pool)
{
dmnsn_object *cube = dmnsn_new_object(pool);
- cube->intersection_fn = dmnsn_cube_intersection_fn;
- cube->inside_fn = dmnsn_cube_inside_fn;
+ cube->vtable = &dmnsn_cube_vtable;
cube->bounding_box.min = dmnsn_new_vector(-1.0, -1.0, -1.0);
cube->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 1.0);
return cube;
diff --git a/libdimension/dimension/object.h b/libdimension/dimension/object.h
index 4bb5b0e..0f7c940 100644
--- a/libdimension/dimension/object.h
+++ b/libdimension/dimension/object.h
@@ -67,9 +67,18 @@ typedef bool dmnsn_object_intersection_fn(const dmnsn_object *object,
typedef bool dmnsn_object_inside_fn(const dmnsn_object *object,
dmnsn_vector point);
+/** Object callbacks. */
+typedef struct dmnsn_object_vtable {
+ dmnsn_object_intersection_fn *intersection_fn; /**< Intersection callback. */
+ dmnsn_object_inside_fn *inside_fn; /**< Inside callback. */
+ dmnsn_object_initialize_fn *initialize_fn; /**< Initialization callback. */
+} dmnsn_object_vtable;
+
/** An object. */
struct dmnsn_object {
- dmnsn_texture *texture; /**< Surface properties. */
+ const dmnsn_object_vtable *vtable; /**< Callbacks. */
+
+ dmnsn_texture *texture; /**< Surface properties. */
dmnsn_interior *interior; /**< Interior properties. */
dmnsn_matrix trans; /**< Transformation matrix. */
@@ -82,10 +91,6 @@ struct dmnsn_object {
dmnsn_array *children; /**< Child objects. */
bool split_children; /**< Whether the child objects can be split. */
- dmnsn_object_initialize_fn *initialize_fn; /**< Initialization callback. */
- dmnsn_object_intersection_fn *intersection_fn; /**< Intersection callback. */
- dmnsn_object_inside_fn *inside_fn; /**< Inside callback. */
-
bool initialized; /**< @internal Whether the object is initialized yet. */
};
@@ -121,7 +126,7 @@ dmnsn_object_intersection(const dmnsn_object *object, dmnsn_line line,
{
dmnsn_line line_trans = dmnsn_transform_line(object->trans_inv, line);
intersection->object = NULL;
- if (object->intersection_fn(object, line_trans, intersection)) {
+ if (object->vtable->intersection_fn(object, line_trans, intersection)) {
/* Get us back into world coordinates */
intersection->ray = line;
intersection->normal = dmnsn_vector_normalized(
@@ -151,5 +156,5 @@ DMNSN_INLINE bool
dmnsn_object_inside(const dmnsn_object *object, dmnsn_vector point)
{
point = dmnsn_transform_point(object->trans_inv, point);
- return object->inside_fn(object, point);
+ return object->vtable->inside_fn(object, point);
}
diff --git a/libdimension/object.c b/libdimension/object.c
index 126f41a..3eeb4eb 100644
--- a/libdimension/object.c
+++ b/libdimension/object.c
@@ -39,16 +39,14 @@ dmnsn_new_object(dmnsn_pool *pool)
void
dmnsn_init_object(dmnsn_object *object)
{
- object->texture = NULL;
- object->interior = NULL;
- object->trans = dmnsn_identity_matrix();
+ object->vtable = NULL;
+ object->texture = NULL;
+ object->interior = NULL;
+ object->trans = dmnsn_identity_matrix();
object->intrinsic_trans = dmnsn_identity_matrix();
- object->children = NULL;
- object->split_children = false;
- object->intersection_fn = NULL;
- object->inside_fn = NULL;
- object->initialize_fn = NULL;
- object->initialized = false;
+ object->children = NULL;
+ object->split_children = false;
+ object->initialized = false;
}
/** Recursively initialize objects. */
@@ -88,8 +86,8 @@ dmnsn_object_initialize_recursive(dmnsn_object *object,
}
/* Initialization callback */
- if (object->initialize_fn) {
- object->initialize_fn(object);
+ if (object->vtable->initialize_fn) {
+ object->vtable->initialize_fn(object);
}
/* Precalculate more object values */
diff --git a/libdimension/plane.c b/libdimension/plane.c
index 97f20b3..6e995b4 100644
--- a/libdimension/plane.c
+++ b/libdimension/plane.c
@@ -33,30 +33,7 @@ typedef struct {
dmnsn_vector normal;
} dmnsn_plane;
-/* Plane object callbacks */
-
-static bool dmnsn_plane_intersection_fn(const dmnsn_object *plane,
- dmnsn_line line,
- dmnsn_intersection *intersection);
-static bool dmnsn_plane_inside_fn(const dmnsn_object *plane,
- dmnsn_vector point);
-
-/* Allocate a new plane */
-dmnsn_object *
-dmnsn_new_plane(dmnsn_pool *pool, dmnsn_vector normal)
-{
- dmnsn_plane *plane = DMNSN_PALLOC(pool, dmnsn_plane);
- plane->normal = normal;
-
- dmnsn_object *object = &plane->object;
- dmnsn_init_object(object);
- object->intersection_fn = dmnsn_plane_intersection_fn;
- object->inside_fn = dmnsn_plane_inside_fn;
- object->bounding_box = dmnsn_infinite_bounding_box();
- return object;
-}
-
-/* Returns the closest intersection of `line' with `plane' */
+/** Returns the closest intersection of `line' with `plane'. */
static bool
dmnsn_plane_intersection_fn(const dmnsn_object *object, dmnsn_line line,
dmnsn_intersection *intersection)
@@ -76,10 +53,29 @@ dmnsn_plane_intersection_fn(const dmnsn_object *object, dmnsn_line line,
return false;
}
-/* Return whether a point is inside a plane */
+/** Return whether a point is inside a plane. */
static bool
dmnsn_plane_inside_fn(const dmnsn_object *object, dmnsn_vector point)
{
const dmnsn_plane *plane = (const dmnsn_plane *)object;
return dmnsn_vector_dot(point, plane->normal) < 0.0;
}
+
+/** Plane vtable. */
+static const dmnsn_object_vtable dmnsn_plane_vtable = {
+ .intersection_fn = dmnsn_plane_intersection_fn,
+ .inside_fn = dmnsn_plane_inside_fn,
+};
+
+dmnsn_object *
+dmnsn_new_plane(dmnsn_pool *pool, dmnsn_vector normal)
+{
+ dmnsn_plane *plane = DMNSN_PALLOC(pool, dmnsn_plane);
+ plane->normal = normal;
+
+ dmnsn_object *object = &plane->object;
+ dmnsn_init_object(object);
+ object->vtable = &dmnsn_plane_vtable;
+ object->bounding_box = dmnsn_infinite_bounding_box();
+ return object;
+}
diff --git a/libdimension/sphere.c b/libdimension/sphere.c
index 821113d..105d8d6 100644
--- a/libdimension/sphere.c
+++ b/libdimension/sphere.c
@@ -58,13 +58,17 @@ dmnsn_sphere_inside_fn(const dmnsn_object *sphere, dmnsn_vector point)
return point.x*point.x + point.y*point.y + point.z*point.z < 1.0;
}
-/* Allocate a new sphere */
+/** Torus vtable. */
+static const dmnsn_object_vtable dmnsn_sphere_vtable = {
+ .intersection_fn = dmnsn_sphere_intersection_fn,
+ .inside_fn = dmnsn_sphere_inside_fn,
+};
+
dmnsn_object *
dmnsn_new_sphere(dmnsn_pool *pool)
{
dmnsn_object *sphere = dmnsn_new_object(pool);
- sphere->intersection_fn = dmnsn_sphere_intersection_fn;
- sphere->inside_fn = dmnsn_sphere_inside_fn;
+ sphere->vtable = &dmnsn_sphere_vtable;
sphere->bounding_box.min = dmnsn_new_vector(-1.0, -1.0, -1.0);
sphere->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 1.0);
return sphere;
diff --git a/libdimension/torus.c b/libdimension/torus.c
index 5723fdb..dd3f9ce 100644
--- a/libdimension/torus.c
+++ b/libdimension/torus.c
@@ -140,7 +140,12 @@ dmnsn_torus_inside_fn(const dmnsn_object *object, dmnsn_vector point)
return dmajor*dmajor + point.y*point.y < torus->minor*torus->minor;
}
-/* Allocate a new torus */
+/** Torus vtable. */
+static const dmnsn_object_vtable dmnsn_torus_vtable = {
+ .intersection_fn = dmnsn_torus_intersection_fn,
+ .inside_fn = dmnsn_torus_inside_fn,
+};
+
dmnsn_object *
dmnsn_new_torus(dmnsn_pool *pool, double major, double minor)
{
@@ -150,8 +155,7 @@ dmnsn_new_torus(dmnsn_pool *pool, double major, double minor)
dmnsn_object *object = &torus->object;
dmnsn_init_object(object);
- object->intersection_fn = dmnsn_torus_intersection_fn;
- object->inside_fn = dmnsn_torus_inside_fn;
+ object->vtable = &dmnsn_torus_vtable;
double extent = major + minor;
object->bounding_box.min = dmnsn_new_vector(-extent, -minor, -extent);
diff --git a/libdimension/triangle.c b/libdimension/triangle.c
index 9db0229..f665670 100644
--- a/libdimension/triangle.c
+++ b/libdimension/triangle.c
@@ -60,6 +60,12 @@ dmnsn_triangle_inside_fn(const dmnsn_object *triangle, dmnsn_vector point)
return false;
}
+/** Triangle vtable. */
+static const dmnsn_object_vtable dmnsn_triangle_vtable = {
+ .intersection_fn = dmnsn_triangle_intersection_fn,
+ .inside_fn = dmnsn_triangle_inside_fn,
+};
+
/** Smooth triangle type. */
typedef struct {
dmnsn_object object;
@@ -89,6 +95,12 @@ dmnsn_smooth_triangle_intersection_fn(const dmnsn_object *object, dmnsn_line l,
return false;
}
+/** Smooth triangle vtable. */
+static const dmnsn_object_vtable dmnsn_smooth_triangle_vtable = {
+ .intersection_fn = dmnsn_smooth_triangle_intersection_fn,
+ .inside_fn = dmnsn_triangle_inside_fn,
+};
+
/** Make a change-of-basis matrix. */
static inline dmnsn_matrix
dmnsn_triangle_basis(dmnsn_vector vertices[3])
@@ -107,8 +119,7 @@ dmnsn_object *
dmnsn_new_triangle(dmnsn_pool *pool, dmnsn_vector vertices[3])
{
dmnsn_object *object = dmnsn_new_object(pool);
- object->intersection_fn = dmnsn_triangle_intersection_fn;
- object->inside_fn = dmnsn_triangle_inside_fn;
+ object->vtable = &dmnsn_triangle_vtable;
object->bounding_box.min = dmnsn_zero;
object->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 0.0);
object->intrinsic_trans = dmnsn_triangle_basis(vertices);
@@ -132,8 +143,7 @@ dmnsn_new_smooth_triangle(dmnsn_pool *pool, dmnsn_vector vertices[3], dmnsn_vect
dmnsn_object *object = &triangle->object;
dmnsn_init_object(object);
- object->intersection_fn = dmnsn_smooth_triangle_intersection_fn;
- object->inside_fn = dmnsn_triangle_inside_fn;
+ object->vtable = &dmnsn_smooth_triangle_vtable;
object->bounding_box.min = dmnsn_zero;
object->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 0.0);
object->intrinsic_trans = P;