summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/bench/prtree.c20
-rw-r--r--libdimension/bench/triangle.c2
-rw-r--r--libdimension/cone.c30
-rw-r--r--libdimension/csg.c44
-rw-r--r--libdimension/cube.c11
-rw-r--r--libdimension/dimension/geometry.h45
-rw-r--r--libdimension/dimension/object.h45
-rw-r--r--libdimension/object.c48
-rw-r--r--libdimension/plane.c9
-rw-r--r--libdimension/scene.c2
-rw-r--r--libdimension/sphere.c31
-rw-r--r--libdimension/tests/prtree.c19
-rw-r--r--libdimension/torus.c17
-rw-r--r--libdimension/triangle.c22
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;