diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2014-06-07 14:15:06 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2014-06-07 14:30:26 -0400 |
commit | a79085ab984979dbf4f78545f7592c8b47e4a794 (patch) | |
tree | e2518532db860db8ba59878ecd6d0d4b60f0b5c4 /libdimension | |
parent | 708954192219feead526f84c0c8bdb29088aeae0 (diff) | |
download | dimension-a79085ab984979dbf4f78545f7592c8b47e4a794.tar.xz |
objects: Refactor how bounding and initialization work.
Diffstat (limited to 'libdimension')
-rw-r--r-- | libdimension/bench/prtree.c | 20 | ||||
-rw-r--r-- | libdimension/bench/triangle.c | 2 | ||||
-rw-r--r-- | libdimension/cone.c | 30 | ||||
-rw-r--r-- | libdimension/csg.c | 44 | ||||
-rw-r--r-- | libdimension/cube.c | 11 | ||||
-rw-r--r-- | libdimension/dimension/geometry.h | 45 | ||||
-rw-r--r-- | libdimension/dimension/object.h | 45 | ||||
-rw-r--r-- | libdimension/object.c | 48 | ||||
-rw-r--r-- | libdimension/plane.c | 9 | ||||
-rw-r--r-- | libdimension/scene.c | 2 | ||||
-rw-r--r-- | libdimension/sphere.c | 31 | ||||
-rw-r--r-- | libdimension/tests/prtree.c | 19 | ||||
-rw-r--r-- | libdimension/torus.c | 17 | ||||
-rw-r--r-- | libdimension/triangle.c | 22 |
14 files changed, 233 insertions, 112 deletions
diff --git a/libdimension/bench/prtree.c b/libdimension/bench/prtree.c index c09a701..dc5a90d 100644 --- a/libdimension/bench/prtree.c +++ b/libdimension/bench/prtree.c @@ -40,8 +40,8 @@ dmnsn_fake_inside_fn(const dmnsn_object *object, dmnsn_vector point) return true; } -static void -dmnsn_randomize_bounding_box(dmnsn_object *object) +static dmnsn_bounding_box +dmnsn_fake_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans) { dmnsn_vector a, b; @@ -53,18 +53,20 @@ dmnsn_randomize_bounding_box(dmnsn_object *object) b.y = 2.0*((double)rand())/RAND_MAX - 1.0; b.z = 2.0*((double)rand())/RAND_MAX - 1.0; - object->bounding_box.min = dmnsn_vector_min(a, b); - object->bounding_box.max = dmnsn_vector_max(a, b); + return dmnsn_new_bounding_box(dmnsn_vector_min(a, b), dmnsn_vector_max(a, b)); } +static dmnsn_object_vtable dmnsn_fake_vtable = { + .intersection_fn = dmnsn_fake_intersection_fn, + .inside_fn = dmnsn_fake_inside_fn, + .bounding_fn = dmnsn_fake_bounding_fn, +}; + static dmnsn_object * dmnsn_new_fake_object(dmnsn_pool *pool) { dmnsn_object *object = dmnsn_new_object(pool); - /* Generate a bounding box in (-1, -1, -1), (1, 1, 1) */ - dmnsn_randomize_bounding_box(object); - object->intersection_fn = dmnsn_fake_intersection_fn; - object->inside_fn = dmnsn_fake_inside_fn; + object->vtable = &dmnsn_fake_vtable; return object; } @@ -86,7 +88,7 @@ main(void) for (size_t i = 0; i < nobjects; ++i) { dmnsn_object *object = dmnsn_new_fake_object(pool); object->texture = texture; - dmnsn_object_initialize(object); + dmnsn_object_precompute(object); dmnsn_array_push(objects, &object); } diff --git a/libdimension/bench/triangle.c b/libdimension/bench/triangle.c index b149c27..05b8f47 100644 --- a/libdimension/bench/triangle.c +++ b/libdimension/bench/triangle.c @@ -40,7 +40,7 @@ main(void) dmnsn_object *triangle = dmnsn_new_triangle(pool, vertices); triangle->texture = dmnsn_new_texture(pool); triangle->texture->pigment = dmnsn_new_pigment(pool); - dmnsn_object_initialize(triangle); + dmnsn_object_precompute(triangle); dmnsn_intersection intersection; dmnsn_line line; diff --git a/libdimension/cone.c b/libdimension/cone.c index b221380..fb05231 100644 --- a/libdimension/cone.c +++ b/libdimension/cone.c @@ -82,17 +82,29 @@ dmnsn_cone_intersection_fn(const dmnsn_object *object, dmnsn_line l, static bool dmnsn_cone_inside_fn(const dmnsn_object *object, dmnsn_vector point) { - const dmnsn_cone *cone = (const dmnsn_cone *)cone; + const dmnsn_cone *cone = (const dmnsn_cone *)object; double r1 = cone->r1, r2 = cone->r2; double r = (point.y*(r2 - r1) + r1 + r2)/2.0; return point.x*point.x + point.z*point.z < r*r && point.y > -1.0 && point.y < 1.0; } +/** Cone bounding callback. */ +static dmnsn_bounding_box +dmnsn_cone_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans) +{ + const dmnsn_cone *cone = (const dmnsn_cone *)object; + + double rmax = dmnsn_max(cone->r1, cone->r2); + dmnsn_bounding_box box = dmnsn_symmetric_bounding_box(dmnsn_new_vector(rmax, 1.0, rmax)); + return dmnsn_transform_bounding_box(trans, box); +} + /** Cone vtable. */ static const dmnsn_object_vtable dmnsn_cone_vtable = { .intersection_fn = dmnsn_cone_intersection_fn, .inside_fn = dmnsn_cone_inside_fn, + .bounding_fn = dmnsn_cone_bounding_fn, }; /** Cone cap type. */ @@ -128,10 +140,20 @@ dmnsn_cone_cap_inside_fn(const dmnsn_object *object, dmnsn_vector point) return false; } +/** Cone cap bounding callback. */ +static dmnsn_bounding_box +dmnsn_cone_cap_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans) +{ + const dmnsn_cone_cap *cap = (const dmnsn_cone_cap *)object; + dmnsn_bounding_box box = dmnsn_symmetric_bounding_box(dmnsn_new_vector(cap->r, 0.0, cap->r)); + return dmnsn_transform_bounding_box(trans, box); +} + /** 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, + .bounding_fn = dmnsn_cone_cap_bounding_fn, }; /** Allocate a new cone cap. */ @@ -144,8 +166,6 @@ dmnsn_new_cone_cap(dmnsn_pool *pool, double r) dmnsn_object *object = &cap->object; dmnsn_init_object(object); 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; } @@ -161,10 +181,6 @@ dmnsn_new_cone(dmnsn_pool *pool, double r1, double r2, bool open) dmnsn_init_object(object); object->vtable = &dmnsn_cone_vtable; - double rmax = dmnsn_max(r1, r2); - object->bounding_box.min = dmnsn_new_vector(-rmax, -1.0, -rmax); - object->bounding_box.max = dmnsn_new_vector(rmax, 1.0, rmax); - if (open) { return object; } diff --git a/libdimension/csg.c b/libdimension/csg.c index e4ee672..713bd16 100644 --- a/libdimension/csg.c +++ b/libdimension/csg.c @@ -53,12 +53,12 @@ dmnsn_csg_union_inside_fn(const dmnsn_object *object, dmnsn_vector point) return dmnsn_bvh_inside(csg->bvh, point); } -/** CSG union initialization callback. */ +/** CSG union precomputation callback. */ static void -dmnsn_csg_union_initialize_fn(dmnsn_object *object) +dmnsn_csg_union_precompute_fn(dmnsn_object *object) { dmnsn_csg_union *csg = (dmnsn_csg_union *)object; - csg->object.trans = dmnsn_identity_matrix(); + csg->object.trans_inv = dmnsn_identity_matrix(); dmnsn_bvh *bvh = dmnsn_new_bvh(csg->object.children, DMNSN_BVH_PRTREE); csg->bvh = bvh; @@ -69,7 +69,7 @@ dmnsn_csg_union_initialize_fn(dmnsn_object *object) 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, + .precompute_fn = dmnsn_csg_union_precompute_fn, }; /** CSG union destruction callback. */ @@ -193,25 +193,23 @@ dmnsn_csg_intersection_inside_fn(const dmnsn_object *csg, dmnsn_vector point) return dmnsn_object_inside(A, point) && dmnsn_object_inside(B, point); } -/** CSG intersection initialization callback. */ +/** CSG intersection precomputation callback. */ static void -dmnsn_csg_intersection_initialize_fn(dmnsn_object *csg) +dmnsn_csg_intersection_precompute_fn(dmnsn_object *csg) { dmnsn_object *A = *(dmnsn_object **)dmnsn_array_first(csg->children); dmnsn_object *B = *(dmnsn_object **)dmnsn_array_last(csg->children); - csg->trans = dmnsn_identity_matrix(); - csg->bounding_box.min - = dmnsn_vector_max(A->bounding_box.min, B->bounding_box.min); - csg->bounding_box.max - = dmnsn_vector_min(A->bounding_box.max, B->bounding_box.max); + csg->trans_inv = dmnsn_identity_matrix(); + csg->bounding_box.min = dmnsn_vector_max(A->bounding_box.min, B->bounding_box.min); + csg->bounding_box.max = 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, + .precompute_fn = dmnsn_csg_intersection_precompute_fn, }; dmnsn_object * @@ -249,13 +247,13 @@ dmnsn_csg_difference_inside_fn(const dmnsn_object *csg, dmnsn_vector point) return dmnsn_object_inside(A, point) && !dmnsn_object_inside(B, point); } -/** CSG difference initialization callback. */ +/** CSG difference precomputation callback. */ static void -dmnsn_csg_difference_initialize_fn(dmnsn_object *csg) +dmnsn_csg_difference_precompute_fn(dmnsn_object *csg) { dmnsn_object *A = *(dmnsn_object **)dmnsn_array_first(csg->children); - csg->trans = dmnsn_identity_matrix(); + csg->trans_inv = dmnsn_identity_matrix(); csg->bounding_box = A->bounding_box; } @@ -263,7 +261,7 @@ dmnsn_csg_difference_initialize_fn(dmnsn_object *csg) 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, + .precompute_fn = dmnsn_csg_difference_precompute_fn, }; dmnsn_object * @@ -301,25 +299,23 @@ dmnsn_csg_merge_inside_fn(const dmnsn_object *csg, dmnsn_vector point) return dmnsn_object_inside(A, point) || dmnsn_object_inside(B, point); } -/** CSG merge initialization callback. */ +/** CSG merge precomputation callback. */ static void -dmnsn_csg_merge_initialize_fn(dmnsn_object *csg) +dmnsn_csg_merge_precompute_fn(dmnsn_object *csg) { dmnsn_object *A = *(dmnsn_object **)dmnsn_array_first(csg->children); dmnsn_object *B = *(dmnsn_object **)dmnsn_array_last(csg->children); - csg->trans = dmnsn_identity_matrix(); - csg->bounding_box.min - = dmnsn_vector_min(A->bounding_box.min, B->bounding_box.min); - csg->bounding_box.max - = dmnsn_vector_max(A->bounding_box.max, B->bounding_box.max); + csg->trans_inv = dmnsn_identity_matrix(); + csg->bounding_box.min = dmnsn_vector_min(A->bounding_box.min, B->bounding_box.min); + csg->bounding_box.max = 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, + .precompute_fn = dmnsn_csg_merge_precompute_fn, }; dmnsn_object * diff --git a/libdimension/cube.c b/libdimension/cube.c index d4c9d5b..4c1b955 100644 --- a/libdimension/cube.c +++ b/libdimension/cube.c @@ -129,10 +129,19 @@ dmnsn_cube_inside_fn(const dmnsn_object *cube, dmnsn_vector point) && point.z > -1.0 && point.z < 1.0; } +/** Boundary callback for a cube. */ +static dmnsn_bounding_box +dmnsn_cube_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans) +{ + dmnsn_bounding_box box = dmnsn_symmetric_bounding_box(dmnsn_new_vector(1.0, 1.0, 1.0)); + return dmnsn_transform_bounding_box(trans, box); +} + /** Cube vtable. */ static const dmnsn_object_vtable dmnsn_cube_vtable = { .intersection_fn = dmnsn_cube_intersection_fn, .inside_fn = dmnsn_cube_inside_fn, + .bounding_fn = dmnsn_cube_bounding_fn, }; /* Allocate a new cube object */ @@ -141,7 +150,5 @@ dmnsn_new_cube(dmnsn_pool *pool) { dmnsn_object *cube = dmnsn_new_object(pool); 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/geometry.h b/libdimension/dimension/geometry.h index d2479f3..26dd608 100644 --- a/libdimension/dimension/geometry.h +++ b/libdimension/dimension/geometry.h @@ -218,6 +218,19 @@ dmnsn_new_line(dmnsn_vector x0, dmnsn_vector n) return l; } +/** + * Construct a new bounding box. + * @param[in] min The minimal extent of the bounding box. + * @param[in] max The maximal extent of the bounding box. + * @return The new bounding box. + */ +DMNSN_INLINE dmnsn_bounding_box +dmnsn_new_bounding_box(dmnsn_vector min, dmnsn_vector max) +{ + dmnsn_bounding_box box = { min, max }; + return box; +} + /** Return the bounding box which contains nothing. */ DMNSN_INLINE dmnsn_bounding_box dmnsn_zero_bounding_box(void) @@ -442,6 +455,22 @@ dmnsn_line_add_epsilon(dmnsn_line l) ); } +/** + * Construct a new symmetric bounding box. + * @param[in] r The extent of the bounding box from the origin. + * @return The new bounding box. + */ +DMNSN_INLINE dmnsn_bounding_box +dmnsn_symmetric_bounding_box(dmnsn_vector r) +{ + dmnsn_vector minus_r = dmnsn_vector_negate(r); + dmnsn_bounding_box box = { + dmnsn_vector_min(r, minus_r), + dmnsn_vector_max(r, minus_r) + }; + return box; +} + /** Return whether \p p is within the axis-aligned bounding box. */ DMNSN_INLINE bool dmnsn_bounding_box_contains(dmnsn_bounding_box box, dmnsn_vector p) @@ -457,6 +486,22 @@ dmnsn_bounding_box_is_infinite(dmnsn_bounding_box box) return box.min.x == -INFINITY; } +/** + * Expand a bounding box to contain a point + * @param[in] box The bounding box to expand. + * @param[in] point The point to swallow. + * @return The expanded bounding box. + */ +DMNSN_INLINE dmnsn_bounding_box +dmnsn_bounding_box_swallow(dmnsn_bounding_box box, dmnsn_vector point) +{ + dmnsn_bounding_box ret = { + dmnsn_vector_min(box.min, point), + dmnsn_vector_max(box.max, point) + }; + return ret; +} + /** Return whether a vector contains any NaN components. */ DMNSN_INLINE bool dmnsn_vector_isnan(dmnsn_vector v) diff --git a/libdimension/dimension/object.h b/libdimension/dimension/object.h index 0f7c940..2e4c68c 100644 --- a/libdimension/dimension/object.h +++ b/libdimension/dimension/object.h @@ -41,12 +41,6 @@ typedef struct dmnsn_intersection { } dmnsn_intersection; /** - * Object initialization callback. - * @param[in,out] object The object to initialize. - */ -typedef void dmnsn_object_initialize_fn(dmnsn_object *object); - -/** * Ray-object intersection callback. * @param[in] object The object to test. * @param[in] line The line to test. @@ -54,9 +48,7 @@ typedef void dmnsn_object_initialize_fn(dmnsn_object *object); * closest (if any) intersection. * @return Whether \p line intersected \p object. */ -typedef bool dmnsn_object_intersection_fn(const dmnsn_object *object, - dmnsn_line line, - dmnsn_intersection *intersection); +typedef bool dmnsn_object_intersection_fn(const dmnsn_object *object, dmnsn_line line, dmnsn_intersection *intersection); /** * Object inside callback. @@ -64,14 +56,27 @@ typedef bool dmnsn_object_intersection_fn(const dmnsn_object *object, * @param[in] point The point to test. * @return Whether \p point is inside \p object. */ -typedef bool dmnsn_object_inside_fn(const dmnsn_object *object, - dmnsn_vector point); +typedef bool dmnsn_object_inside_fn(const dmnsn_object *object, dmnsn_vector point); + +/** + * Object bounding callback. + * @param[in,out] object The object to bound. + * @param[in,out] trans The effective transformation for the object. + */ +typedef dmnsn_bounding_box dmnsn_object_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans); + +/** + * Object precomputation callback. + * @param[in,out] object The object to precompute. + */ +typedef void dmnsn_object_precompute_fn(dmnsn_object *object); /** 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_bounding_fn *bounding_fn; /**< Bounding callback. */ + dmnsn_object_precompute_fn *precompute_fn; /**< Precomputation callback. */ } dmnsn_object_vtable; /** An object. */ @@ -82,16 +87,16 @@ struct dmnsn_object { dmnsn_interior *interior; /**< Interior properties. */ dmnsn_matrix trans; /**< Transformation matrix. */ - dmnsn_matrix trans_inv; /**< Inverse of the transformation matrix. */ dmnsn_matrix intrinsic_trans; /**< Transformations intrinsic to the object. */ - dmnsn_matrix pigment_trans; /**< Inverse transformation for the texture. */ - - dmnsn_bounding_box bounding_box; /**< Object bounding box. */ dmnsn_array *children; /**< Child objects. */ bool split_children; /**< Whether the child objects can be split. */ - bool initialized; /**< @internal Whether the object is initialized yet. */ + /* Precomputed values */ + bool precomputed; /**< @internal Whether the object is precomputed yet. */ + dmnsn_matrix trans_inv; /**< Inverse of the transformation matrix. */ + dmnsn_matrix pigment_trans; /**< Inverse transformation for the texture. */ + dmnsn_bounding_box bounding_box; /**< Bounding box in world coordinates. */ }; /** @@ -108,10 +113,10 @@ dmnsn_object *dmnsn_new_object(dmnsn_pool *pool); void dmnsn_init_object(dmnsn_object *object); /** - * Initialize an object and potentially its children. - * @param[in,out] object The object to initialize. + * Precompute values for an object and its children. + * @param[in,out] object The object to precompute. */ -void dmnsn_object_initialize(dmnsn_object *object); +void dmnsn_object_precompute(dmnsn_object *object); /** * Appropriately transform a ray, then test for an intersection. diff --git a/libdimension/object.c b/libdimension/object.c index 3eeb4eb..2521353 100644 --- a/libdimension/object.c +++ b/libdimension/object.c @@ -46,30 +46,33 @@ dmnsn_init_object(dmnsn_object *object) object->intrinsic_trans = dmnsn_identity_matrix(); object->children = NULL; object->split_children = false; - object->initialized = false; + object->precomputed = false; } -/** Recursively initialize objects. */ +/** Recursively precompute objects. */ static void -dmnsn_object_initialize_recursive(dmnsn_object *object, - dmnsn_matrix pigment_trans) +dmnsn_object_precompute_recursive(dmnsn_object *object, dmnsn_matrix pigment_trans) { - dmnsn_assert(!object->initialized, "Object double-initialized."); - object->initialized = true; + dmnsn_assert(!object->precomputed, "Object double-precomputed."); + object->precomputed = true; + + const dmnsn_object_vtable *vtable = object->vtable; + dmnsn_assert(vtable->intersection_fn, "Missing intersection function."); + dmnsn_assert(vtable->inside_fn, "Missing inside function."); + dmnsn_assert(vtable->bounding_fn || vtable->precompute_fn, "Missing bounding and precompute function."); /* Initialize the texture */ if (!object->texture->initialized) { dmnsn_texture_initialize(object->texture); } - /* Precalculate object values */ - object->pigment_trans = pigment_trans; - object->trans = dmnsn_matrix_mul(object->trans, object->intrinsic_trans); + dmnsn_matrix total_trans = dmnsn_matrix_mul(object->trans, object->intrinsic_trans); - /* Initialize the object's children */ + /* Precompute the object's children */ if (object->children) { DMNSN_ARRAY_FOREACH (dmnsn_object **, child, object->children) { - (*child)->trans = dmnsn_matrix_mul(object->trans, (*child)->trans); + dmnsn_matrix saved_trans = (*child)->trans; + (*child)->trans = dmnsn_matrix_mul(total_trans, saved_trans); dmnsn_matrix child_pigment_trans; if ((*child)->texture == NULL || (*child)->texture->pigment == NULL) { @@ -81,25 +84,26 @@ dmnsn_object_initialize_recursive(dmnsn_object *object, dmnsn_texture_cascade(object->texture, &(*child)->texture); dmnsn_interior_cascade(object->interior, &(*child)->interior); - dmnsn_object_initialize_recursive(*child, child_pigment_trans); + dmnsn_object_precompute_recursive(*child, child_pigment_trans); + (*child)->trans = saved_trans; } } - /* Initialization callback */ - if (object->vtable->initialize_fn) { - object->vtable->initialize_fn(object); + /* Precalculate object values */ + object->pigment_trans = pigment_trans; + object->trans_inv = dmnsn_matrix_inverse(total_trans); + if (vtable->bounding_fn) { + object->bounding_box = vtable->bounding_fn(object, total_trans); + } + if (vtable->precompute_fn) { + vtable->precompute_fn(object); } - - /* Precalculate more object values */ - object->bounding_box - = dmnsn_transform_bounding_box(object->trans, object->bounding_box); - object->trans_inv = dmnsn_matrix_inverse(object->trans); } /* Precompute object properties */ void -dmnsn_object_initialize(dmnsn_object *object) +dmnsn_object_precompute(dmnsn_object *object) { dmnsn_matrix pigment_trans = dmnsn_matrix_inverse(object->trans); - dmnsn_object_initialize_recursive(object, pigment_trans); + dmnsn_object_precompute_recursive(object, pigment_trans); } diff --git a/libdimension/plane.c b/libdimension/plane.c index 6e995b4..c09dd70 100644 --- a/libdimension/plane.c +++ b/libdimension/plane.c @@ -61,10 +61,18 @@ dmnsn_plane_inside_fn(const dmnsn_object *object, dmnsn_vector point) return dmnsn_vector_dot(point, plane->normal) < 0.0; } +/** Plane bounding callback. */ +static dmnsn_bounding_box +dmnsn_plane_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans) +{ + return dmnsn_infinite_bounding_box(); +} + /** Plane vtable. */ static const dmnsn_object_vtable dmnsn_plane_vtable = { .intersection_fn = dmnsn_plane_intersection_fn, .inside_fn = dmnsn_plane_inside_fn, + .bounding_fn = dmnsn_plane_bounding_fn, }; dmnsn_object * @@ -76,6 +84,5 @@ dmnsn_new_plane(dmnsn_pool *pool, dmnsn_vector 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/scene.c b/libdimension/scene.c index 39be881..18cda80 100644 --- a/libdimension/scene.c +++ b/libdimension/scene.c @@ -72,6 +72,6 @@ dmnsn_scene_initialize(dmnsn_scene *scene) DMNSN_ARRAY_FOREACH (dmnsn_object **, object, scene->objects) { dmnsn_texture_cascade(scene->default_texture, &(*object)->texture); dmnsn_interior_cascade(scene->default_interior, &(*object)->interior); - dmnsn_object_initialize(*object); + dmnsn_object_precompute(*object); } } diff --git a/libdimension/sphere.c b/libdimension/sphere.c index 105d8d6..cd791c3 100644 --- a/libdimension/sphere.c +++ b/libdimension/sphere.c @@ -39,16 +39,17 @@ dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line l, size_t n = dmnsn_polynomial_solve(poly, 2, x); if (n == 0) { return false; - } else { - double t = x[0]; - /* Optimize for the case where we're outside the sphere */ - if (dmnsn_likely(n == 2)) - t = dmnsn_min(t, x[1]); + } - intersection->t = t; - intersection->normal = dmnsn_line_point(l, t); - return true; + double t = x[0]; + /* Optimize for the case where we're outside the sphere */ + if (dmnsn_likely(n == 2)) { + t = dmnsn_min(t, x[1]); } + + intersection->t = t; + intersection->normal = dmnsn_line_point(l, t); + return true; } /** Sphere inside callback. */ @@ -58,10 +59,20 @@ 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; } -/** Torus vtable. */ +/** Sphere bounding callback. */ +static dmnsn_bounding_box +dmnsn_sphere_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans) +{ + /* TODO: tighter bound */ + dmnsn_bounding_box box = dmnsn_symmetric_bounding_box(dmnsn_new_vector(1.0, 1.0, 1.0)); + return dmnsn_transform_bounding_box(trans, box); +} + +/** Sphere vtable. */ static const dmnsn_object_vtable dmnsn_sphere_vtable = { .intersection_fn = dmnsn_sphere_intersection_fn, .inside_fn = dmnsn_sphere_inside_fn, + .bounding_fn = dmnsn_sphere_bounding_fn, }; dmnsn_object * @@ -69,7 +80,5 @@ dmnsn_new_sphere(dmnsn_pool *pool) { dmnsn_object *sphere = dmnsn_new_object(pool); 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/tests/prtree.c b/libdimension/tests/prtree.c index a7db68e..fdc5878 100644 --- a/libdimension/tests/prtree.c +++ b/libdimension/tests/prtree.c @@ -58,6 +58,20 @@ dmnsn_randomize_bounding_box(dmnsn_object *object) object->bounding_box.max = dmnsn_vector_max(a, b); } +static const dmnsn_object_vtable dmnsn_fake_vtable = { + .intersection_fn = dmnsn_fake_intersection_fn, +}; + +static dmnsn_object * +dmnsn_new_fake_object(dmnsn_pool *pool) +{ + dmnsn_object *object = dmnsn_new_object(pool); + dmnsn_randomize_bounding_box(object); + object->vtable = &dmnsn_fake_vtable; + object->trans_inv = dmnsn_identity_matrix(); + return object; +} + int main(void) { @@ -70,10 +84,7 @@ main(void) dmnsn_array *objects = DMNSN_PALLOC_ARRAY(pool, dmnsn_object *); for (size_t i = 0; i < nobjects; ++i) { - dmnsn_object *object = dmnsn_new_object(pool); - dmnsn_randomize_bounding_box(object); - object->intersection_fn = dmnsn_fake_intersection_fn; - object->trans_inv = dmnsn_identity_matrix(); + dmnsn_object *object = dmnsn_new_fake_object(pool); dmnsn_array_push(objects, &object); } diff --git a/libdimension/torus.c b/libdimension/torus.c index dd3f9ce..2b7a818 100644 --- a/libdimension/torus.c +++ b/libdimension/torus.c @@ -140,10 +140,22 @@ dmnsn_torus_inside_fn(const dmnsn_object *object, dmnsn_vector point) return dmajor*dmajor + point.y*point.y < torus->minor*torus->minor; } +/** Torus bounding callback. */ +static dmnsn_bounding_box +dmnsn_torus_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans) +{ + const dmnsn_torus *torus = (const dmnsn_torus *)object; + + double extent = torus->major + torus->minor; + dmnsn_bounding_box box = dmnsn_symmetric_bounding_box(dmnsn_new_vector(extent, torus->minor, extent)); + return dmnsn_transform_bounding_box(trans, box); +} + /** Torus vtable. */ static const dmnsn_object_vtable dmnsn_torus_vtable = { .intersection_fn = dmnsn_torus_intersection_fn, .inside_fn = dmnsn_torus_inside_fn, + .bounding_fn = dmnsn_torus_bounding_fn, }; dmnsn_object * @@ -156,10 +168,5 @@ dmnsn_new_torus(dmnsn_pool *pool, double major, double minor) dmnsn_object *object = &torus->object; dmnsn_init_object(object); object->vtable = &dmnsn_torus_vtable; - - double extent = major + minor; - object->bounding_box.min = dmnsn_new_vector(-extent, -minor, -extent); - object->bounding_box.max = dmnsn_new_vector(extent, minor, extent); - return object; } diff --git a/libdimension/triangle.c b/libdimension/triangle.c index f665670..30ba6c0 100644 --- a/libdimension/triangle.c +++ b/libdimension/triangle.c @@ -55,15 +55,30 @@ dmnsn_triangle_intersection_fn(const dmnsn_object *object, dmnsn_line l, /** Triangle inside callback. */ static bool -dmnsn_triangle_inside_fn(const dmnsn_object *triangle, dmnsn_vector point) +dmnsn_triangle_inside_fn(const dmnsn_object *object, dmnsn_vector point) { return false; } +/** Triangle bounding callback. */ +static dmnsn_bounding_box +dmnsn_triangle_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans) +{ + dmnsn_vector a = dmnsn_transform_point(trans, dmnsn_zero); + dmnsn_vector b = dmnsn_transform_point(trans, dmnsn_x); + dmnsn_vector c = dmnsn_transform_point(trans, dmnsn_y); + + dmnsn_bounding_box box = dmnsn_new_bounding_box(a, a); + box = dmnsn_bounding_box_swallow(box, b); + box = dmnsn_bounding_box_swallow(box, c); + return box; +} + /** Triangle vtable. */ static const dmnsn_object_vtable dmnsn_triangle_vtable = { .intersection_fn = dmnsn_triangle_intersection_fn, .inside_fn = dmnsn_triangle_inside_fn, + .bounding_fn = dmnsn_triangle_bounding_fn, }; /** Smooth triangle type. */ @@ -99,6 +114,7 @@ dmnsn_smooth_triangle_intersection_fn(const dmnsn_object *object, dmnsn_line l, static const dmnsn_object_vtable dmnsn_smooth_triangle_vtable = { .intersection_fn = dmnsn_smooth_triangle_intersection_fn, .inside_fn = dmnsn_triangle_inside_fn, + .bounding_fn = dmnsn_triangle_bounding_fn, }; /** Make a change-of-basis matrix. */ @@ -120,8 +136,6 @@ dmnsn_new_triangle(dmnsn_pool *pool, dmnsn_vector vertices[3]) { dmnsn_object *object = dmnsn_new_object(pool); 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); return object; } @@ -144,8 +158,6 @@ dmnsn_new_smooth_triangle(dmnsn_pool *pool, dmnsn_vector vertices[3], dmnsn_vect dmnsn_object *object = &triangle->object; dmnsn_init_object(object); 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; return object; |