summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/csg.c24
-rw-r--r--libdimension/cube.c17
-rw-r--r--libdimension/cylinder.c12
-rw-r--r--libdimension/dimension/object.h20
-rw-r--r--libdimension/object.c39
-rw-r--r--libdimension/plane.c7
-rw-r--r--libdimension/prtree.c8
-rw-r--r--libdimension/sphere.c10
-rw-r--r--libdimension/torus.c8
-rw-r--r--tests/libdimension/prtree.c1
10 files changed, 82 insertions, 64 deletions
diff --git a/libdimension/csg.c b/libdimension/csg.c
index cfce242..58104ff 100644
--- a/libdimension/csg.c
+++ b/libdimension/csg.c
@@ -116,8 +116,8 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line,
const dmnsn_object **params = csg->ptr;
dmnsn_intersection i1, i2;
- bool is_i1 = (*params[0]->intersection_fn)(params[0], line, &i1);
- bool is_i2 = (*params[1]->intersection_fn)(params[1], line, &i2);
+ bool is_i1 = dmnsn_object_intersection(params[0], line, &i1);
+ bool is_i2 = dmnsn_object_intersection(params[1], line, &i2);
double oldt = 0.0;
while (is_i1) {
@@ -126,11 +126,11 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line,
oldt = i1.t + dmnsn_epsilon;
dmnsn_vector point = dmnsn_line_point(i1.ray, i1.t);
- if (inside2 ^ (*params[1]->inside_fn)(params[1], point)) {
+ if (inside2 ^ dmnsn_object_inside(params[1], point)) {
dmnsn_line newline = line;
newline.x0 = dmnsn_line_point(line, i1.t);
newline = dmnsn_line_add_epsilon(newline);
- is_i1 = (*params[0]->intersection_fn)(params[0], newline, &i1);
+ is_i1 = dmnsn_object_intersection(params[0], newline, &i1);
} else {
break;
}
@@ -143,11 +143,11 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line,
oldt = i2.t + dmnsn_epsilon;
dmnsn_vector point = dmnsn_line_point(i2.ray, i2.t);
- if (inside1 ^ (*params[0]->inside_fn)(params[0], point)) {
+ if (inside1 ^ dmnsn_object_inside(params[0], point)) {
dmnsn_line newline = line;
newline.x0 = dmnsn_line_point(line, i2.t);
newline = dmnsn_line_add_epsilon(newline);
- is_i2 = (*params[1]->intersection_fn)(params[1], newline, &i2);
+ is_i2 = dmnsn_object_intersection(params[1], newline, &i2);
} else {
break;
}
@@ -184,8 +184,8 @@ static bool
dmnsn_csg_intersection_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
{
dmnsn_object **params = csg->ptr;
- return (*params[0]->inside_fn)(params[0], point)
- && (*params[1]->inside_fn)(params[1], point);
+ return dmnsn_object_inside(params[0], point)
+ && dmnsn_object_inside(params[1], point);
}
static void
@@ -240,8 +240,8 @@ static bool
dmnsn_csg_difference_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
{
dmnsn_object **params = csg->ptr;
- return (*params[0]->inside_fn)(params[0], point)
- && !(*params[1]->inside_fn)(params[1], point);
+ return dmnsn_object_inside(params[0], point)
+ && !dmnsn_object_inside(params[1], point);
}
static void
@@ -293,8 +293,8 @@ static bool
dmnsn_csg_merge_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
{
dmnsn_object **params = csg->ptr;
- return (*params[0]->inside_fn)(params[0], point)
- || (*params[1]->inside_fn)(params[1], point);
+ return dmnsn_object_inside(params[0], point)
+ || dmnsn_object_inside(params[1], point);
}
static void
diff --git a/libdimension/cube.c b/libdimension/cube.c
index 52fff92..c70ebf6 100644
--- a/libdimension/cube.c
+++ b/libdimension/cube.c
@@ -51,13 +51,11 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line,
{
/* Clip the given line against the X, Y, and Z slabs */
- dmnsn_line line_trans = dmnsn_transform_line(cube->trans_inv, line);
-
dmnsn_vector nmin, nmax;
double tmin, tmax;
- double tx1 = (-1.0 - line_trans.x0.x)/line_trans.n.x;
- double tx2 = (+1.0 - line_trans.x0.x)/line_trans.n.x;
+ double tx1 = (-1.0 - line.x0.x)/line.n.x;
+ double tx2 = (+1.0 - line.x0.x)/line.n.x;
if (tx1 < tx2) {
tmin = tx1;
@@ -74,8 +72,8 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line,
if (tmin > tmax)
return false;
- double ty1 = (-1.0 - line_trans.x0.y)/line_trans.n.y;
- double ty2 = (+1.0 - line_trans.x0.y)/line_trans.n.y;
+ double ty1 = (-1.0 - line.x0.y)/line.n.y;
+ double ty2 = (+1.0 - line.x0.y)/line.n.y;
if (ty1 < ty2) {
if (ty1 > tmin) {
@@ -100,8 +98,8 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line,
if (tmin > tmax)
return false;
- double tz1 = (-1.0 - line_trans.x0.z)/line_trans.n.z;
- double tz2 = (+1.0 - line_trans.x0.z)/line_trans.n.z;
+ double tz1 = (-1.0 - line.x0.z)/line.n.z;
+ double tz2 = (+1.0 - line.x0.z)/line.n.z;
if (tz1 < tz2) {
if (tz1 > tmin) {
@@ -134,7 +132,7 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line,
if (tmin >= 0.0) {
intersection->ray = line;
intersection->t = tmin;
- intersection->normal = dmnsn_transform_normal(cube->trans, nmin);
+ intersection->normal = nmin;
intersection->texture = cube->texture;
intersection->interior = cube->interior;
return true;
@@ -147,7 +145,6 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line,
static bool
dmnsn_cube_inside_fn(const dmnsn_object *cube, dmnsn_vector point)
{
- point = dmnsn_transform_vector(cube->trans_inv, point);
return point.x > -1.0 && point.x < 1.0
&& point.y > -1.0 && point.y < 1.0
&& point.z > -1.0 && point.z < 1.0;
diff --git a/libdimension/cylinder.c b/libdimension/cylinder.c
index ba016cf..9f5b7ff 100644
--- a/libdimension/cylinder.c
+++ b/libdimension/cylinder.c
@@ -60,10 +60,9 @@ dmnsn_new_cylinder(double r1, double r2, bool open)
/* Intersections callback for a cylinder */
static bool
-dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line line,
+dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line l,
dmnsn_intersection *intersection)
{
- dmnsn_line l = dmnsn_transform_line(cylinder->trans_inv, line);
const dmnsn_cylinder_payload *payload = cylinder->ptr;
double r1 = payload->r1, r2 = payload->r2;
@@ -128,9 +127,9 @@ dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line line,
&& (tcap < t || p.y <= -1.0 || p.y >= 1.0)
&& pcap.x*pcap.x + pcap.z*pcap.z < r*r)
{
- intersection->ray = line;
+ intersection->ray = l;
intersection->t = tcap;
- intersection->normal = dmnsn_transform_normal(cylinder->trans, norm);
+ intersection->normal = norm;
intersection->texture = cylinder->texture;
intersection->interior = cylinder->interior;
return true;
@@ -141,9 +140,9 @@ dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line line,
dmnsn_vector norm = dmnsn_vector_normalize(
dmnsn_new_vector(p.x, -(r2 - r1)*sqrt(p.x*p.x + p.z*p.z)/2.0, p.z)
);
- intersection->ray = line;
+ intersection->ray = l;
intersection->t = t;
- intersection->normal = dmnsn_transform_normal(cylinder->trans, norm);
+ intersection->normal = norm;
intersection->texture = cylinder->texture;
intersection->interior = cylinder->interior;
return true;
@@ -157,7 +156,6 @@ dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line line,
static bool
dmnsn_cylinder_inside_fn(const dmnsn_object *cylinder, dmnsn_vector point)
{
- point = dmnsn_transform_vector(cylinder->trans_inv, point);
const dmnsn_cylinder_payload *payload = cylinder->ptr;
double r1 = payload->r1, r2 = payload->r2;
double r = (point.y*(r2 - r1) + r1 + r2)/2.0;
diff --git a/libdimension/dimension/object.h b/libdimension/dimension/object.h
index cef1acb..56cfacd 100644
--- a/libdimension/dimension/object.h
+++ b/libdimension/dimension/object.h
@@ -85,22 +85,12 @@ dmnsn_object *dmnsn_new_object(void);
/* Free an object */
void dmnsn_delete_object(dmnsn_object *object);
+/* Initialize an object and potentially its children */
void dmnsn_object_init(dmnsn_object *object);
-/* Useful function to transform a normal vector */
-DMNSN_INLINE dmnsn_vector
-dmnsn_transform_normal(dmnsn_matrix trans, dmnsn_vector normal)
-{
- return dmnsn_vector_normalize(
- dmnsn_vector_sub(
- dmnsn_transform_vector(trans, normal),
- /* Optimized form of dmnsn_transform_vector(trans, dmnsn_zero) */
- dmnsn_vector_div(
- dmnsn_new_vector(trans.n[0][3], trans.n[1][3], trans.n[2][3]),
- trans.n[3][3]
- )
- )
- );
-}
+/* Helpers for invoking object callbacks with correct transformations */
+bool dmnsn_object_intersection(const dmnsn_object *object, dmnsn_line line,
+ dmnsn_intersection *intersection);
+bool dmnsn_object_inside(const dmnsn_object *object, dmnsn_vector point);
#endif /* DIMENSION_OBJECT_H */
diff --git a/libdimension/object.c b/libdimension/object.c
index 768cf68..873f5ee 100644
--- a/libdimension/object.c
+++ b/libdimension/object.c
@@ -71,3 +71,42 @@ dmnsn_object_init(dmnsn_object *object)
dmnsn_texture_init(object->texture);
}
}
+
+/* Helper function to transform a normal vector */
+static inline dmnsn_vector
+dmnsn_transform_normal(dmnsn_matrix trans, dmnsn_vector normal)
+{
+ return dmnsn_vector_normalize(
+ dmnsn_vector_sub(
+ dmnsn_transform_vector(trans, normal),
+ /* Optimized form of dmnsn_transform_vector(trans, dmnsn_zero) */
+ dmnsn_vector_div(
+ dmnsn_new_vector(trans.n[0][3], trans.n[1][3], trans.n[2][3]),
+ trans.n[3][3]
+ )
+ )
+ );
+}
+
+bool
+dmnsn_object_intersection(const dmnsn_object *object, dmnsn_line line,
+ dmnsn_intersection *intersection)
+{
+ dmnsn_line line_trans = dmnsn_transform_line(object->trans_inv, line);
+ if ((*object->intersection_fn)(object, line_trans, intersection)) {
+ /* Get us back into world coordinates */
+ intersection->ray = line;
+ intersection->normal = dmnsn_transform_normal(object->trans,
+ intersection->normal);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool
+dmnsn_object_inside(const dmnsn_object *object, dmnsn_vector point)
+{
+ point = dmnsn_transform_vector(object->trans_inv, point);
+ return (*object->inside_fn)(object, point);
+}
diff --git a/libdimension/plane.c b/libdimension/plane.c
index 93d5173..be3d91a 100644
--- a/libdimension/plane.c
+++ b/libdimension/plane.c
@@ -58,14 +58,13 @@ dmnsn_plane_intersection_fn(const dmnsn_object *plane, dmnsn_line line,
{
dmnsn_vector *normal = plane->ptr;
- dmnsn_line line_trans = dmnsn_transform_line(plane->trans_inv, line);
- double den = dmnsn_vector_dot(line_trans.n, *normal);
+ double den = dmnsn_vector_dot(line.n, *normal);
if (den != 0.0) {
- double t = -dmnsn_vector_dot(line_trans.x0, *normal)/den;
+ double t = -dmnsn_vector_dot(line.x0, *normal)/den;
if (t >= 0.0) {
intersection->ray = line;
intersection->t = t;
- intersection->normal = dmnsn_transform_normal(plane->trans, *normal);
+ intersection->normal = *normal;
intersection->texture = plane->texture;
intersection->interior = plane->interior;
return true;
diff --git a/libdimension/prtree.c b/libdimension/prtree.c
index 3367384..73c2484 100644
--- a/libdimension/prtree.c
+++ b/libdimension/prtree.c
@@ -605,7 +605,7 @@ dmnsn_prtree_intersection_recursive(const dmnsn_prtree_node *node,
if (dmnsn_ray_box_intersection(ray, node->bounding_boxes[i], *t)) {
dmnsn_object *object = node->children[i];
dmnsn_intersection local_intersection;
- if ((*object->intersection_fn)(object, ray.line, &local_intersection)) {
+ if (dmnsn_object_intersection(object, ray.line, &local_intersection)) {
if (local_intersection.t < *t) {
*intersection = local_intersection;
*t = local_intersection.t;
@@ -636,7 +636,7 @@ dmnsn_prtree_intersection(const dmnsn_prtree *tree, dmnsn_line ray,
/* Search the unbounded objects */
DMNSN_ARRAY_FOREACH (dmnsn_object **, object, tree->unbounded) {
dmnsn_intersection local_intersection;
- if ((*(*object)->intersection_fn)(*object, ray, &local_intersection)) {
+ if (dmnsn_object_intersection(*object, ray, &local_intersection)) {
if (local_intersection.t < t) {
*intersection = local_intersection;
t = local_intersection.t;
@@ -667,7 +667,7 @@ dmnsn_prtree_inside_recursive(const dmnsn_prtree_node *node, dmnsn_vector point)
if (dmnsn_bounding_box_contains(node->bounding_boxes[i], point)) {
if (node->is_leaf) {
dmnsn_object *object = node->children[i];
- if ((*object->inside_fn)(object, point))
+ if (dmnsn_object_inside(object, point))
return true;
} else {
if (dmnsn_prtree_inside_recursive(node->children[i], point))
@@ -684,7 +684,7 @@ dmnsn_prtree_inside(const dmnsn_prtree *tree, dmnsn_vector point)
{
/* Search the unbounded objects */
DMNSN_ARRAY_FOREACH (dmnsn_object **, object, tree->unbounded) {
- if ((*(*object)->inside_fn)(*object, point))
+ if (dmnsn_object_inside(*object, point))
return true;
}
diff --git a/libdimension/sphere.c b/libdimension/sphere.c
index 490074b..7ff2292 100644
--- a/libdimension/sphere.c
+++ b/libdimension/sphere.c
@@ -47,11 +47,9 @@ dmnsn_new_sphere()
/* Returns the closest intersection of `line' with `sphere' */
static bool
-dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line,
+dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line l,
dmnsn_intersection *intersection)
{
- dmnsn_line l = dmnsn_transform_line(sphere->trans_inv, line);
-
/* Solve (x0 + nx*t)^2 + (y0 + ny*t)^2 + (z0 + nz*t)^2 == 1 */
double poly[3], x[2];
poly[2] = dmnsn_vector_dot(l.n, l.n);
@@ -66,10 +64,9 @@ dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line,
if (n == 2)
t = dmnsn_min(t, x[1]);
- intersection->ray = line;
+ intersection->ray = l;
intersection->t = t;
- intersection->normal = dmnsn_transform_normal(sphere->trans,
- dmnsn_line_point(l, t));
+ intersection->normal = dmnsn_line_point(l, t);
intersection->texture = sphere->texture;
intersection->interior = sphere->interior;
return true;
@@ -80,6 +77,5 @@ dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line,
static bool
dmnsn_sphere_inside_fn(const dmnsn_object *sphere, dmnsn_vector point)
{
- point = dmnsn_transform_vector(sphere->trans_inv, point);
return point.x*point.x + point.y*point.y + point.z*point.z < 1.0;
}
diff --git a/libdimension/torus.c b/libdimension/torus.c
index df78212..702404b 100644
--- a/libdimension/torus.c
+++ b/libdimension/torus.c
@@ -105,10 +105,9 @@ dmnsn_torus_bound_intersection(const dmnsn_torus_payload *payload, dmnsn_line l)
/* Returns the closest intersection of `line' with `torus' */
static bool
-dmnsn_torus_intersection_fn(const dmnsn_object *torus, dmnsn_line line,
+dmnsn_torus_intersection_fn(const dmnsn_object *torus, dmnsn_line l,
dmnsn_intersection *intersection)
{
- dmnsn_line l = dmnsn_transform_line(torus->trans_inv, line);
const dmnsn_torus_payload *payload = torus->ptr;
double R = payload->major, r = payload->minor;
double R2 = R*R, r2 = r*r;
@@ -152,9 +151,9 @@ dmnsn_torus_intersection_fn(const dmnsn_object *torus, dmnsn_line line,
dmnsn_vector_normalize(dmnsn_new_vector(p.x, 0.0, p.z))
);
dmnsn_vector normal = dmnsn_vector_normalize(dmnsn_vector_sub(p, center));
- intersection->ray = line;
+ intersection->ray = l;
intersection->t = t;
- intersection->normal = dmnsn_transform_normal(torus->trans, normal);
+ intersection->normal = normal;
intersection->texture = torus->texture;
intersection->interior = torus->interior;
return true;
@@ -164,7 +163,6 @@ dmnsn_torus_intersection_fn(const dmnsn_object *torus, dmnsn_line line,
static bool
dmnsn_torus_inside_fn(const dmnsn_object *torus, dmnsn_vector point)
{
- point = dmnsn_transform_vector(torus->trans_inv, point);
const dmnsn_torus_payload *payload = torus->ptr;
double dmajor = payload->major - sqrt(point.x*point.x + point.z*point.z);
return dmajor*dmajor + point.y*point.y < payload->minor*payload->minor;
diff --git a/tests/libdimension/prtree.c b/tests/libdimension/prtree.c
index 2cf259f..e8e9953 100644
--- a/tests/libdimension/prtree.c
+++ b/tests/libdimension/prtree.c
@@ -64,6 +64,7 @@ main(void)
dmnsn_object *object = dmnsn_new_object();
dmnsn_randomize_bounding_box(object);
object->intersection_fn = &dmnsn_fake_intersection_fn;
+ dmnsn_object_init(object);
dmnsn_array_push(scene->objects, &object);
}