From 708954192219feead526f84c0c8bdb29088aeae0 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 6 Jun 2014 14:14:00 -0400 Subject: objects: Use a vtable to shrink object structs. --- libdimension/cone.c | 18 ++++++++++++---- libdimension/csg.c | 47 ++++++++++++++++++++++++++++------------- libdimension/cube.c | 9 ++++++-- libdimension/dimension/object.h | 19 +++++++++++------ libdimension/object.c | 20 ++++++++---------- libdimension/plane.c | 46 ++++++++++++++++++---------------------- libdimension/sphere.c | 10 ++++++--- libdimension/torus.c | 10 ++++++--- libdimension/triangle.c | 18 ++++++++++++---- 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; -- cgit v1.2.3