summaryrefslogtreecommitdiffstats
path: root/libdimension/csg.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension/csg.c')
-rw-r--r--libdimension/csg.c322
1 files changed, 166 insertions, 156 deletions
diff --git a/libdimension/csg.c b/libdimension/csg.c
index 24f1f80..4619759 100644
--- a/libdimension/csg.c
+++ b/libdimension/csg.c
@@ -32,59 +32,63 @@ dmnsn_csg_free_fn(void *ptr)
/* Unions */
-static dmnsn_intersection *
-dmnsn_csg_union_intersection_fn(const dmnsn_object *csg, dmnsn_line line)
+static bool
+dmnsn_csg_union_intersection_fn(const dmnsn_object *csg,
+ dmnsn_line line,
+ dmnsn_intersection *intersection)
{
const dmnsn_object **params = csg->ptr;
dmnsn_line line1 = dmnsn_matrix_line_mul(params[0]->trans_inv, line);
dmnsn_line line2 = dmnsn_matrix_line_mul(params[1]->trans_inv, line);
- dmnsn_intersection *i1 = (*params[0]->intersection_fn)(params[0], line1);
- dmnsn_intersection *i2 = (*params[1]->intersection_fn)(params[1], line2);
- if (i1) {
+ dmnsn_intersection i1, i2;
+ bool is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
+ bool is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
+
+ if (is_i1) {
/* Transform the intersection back to the observer's view */
- i1->ray = line;
- i1->normal = dmnsn_vector_normalize(
+ i1.ray = line;
+ i1.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
- dmnsn_matrix_vector_mul(params[0]->trans, i1->normal),
+ dmnsn_matrix_vector_mul(params[0]->trans, i1.normal),
dmnsn_matrix_vector_mul(params[0]->trans, dmnsn_zero)
)
);
- if (!i1->texture)
- i1->texture = csg->texture;
- if (!i1->interior)
- i1->interior = csg->interior;
+ if (!i1.texture)
+ i1.texture = csg->texture;
+ if (!i1.interior)
+ i1.interior = csg->interior;
}
- if (i2) {
- i2->ray = line;
- i2->normal = dmnsn_vector_normalize(
+ if (is_i2) {
+ i2.ray = line;
+ i2.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
- dmnsn_matrix_vector_mul(params[1]->trans, i2->normal),
+ dmnsn_matrix_vector_mul(params[1]->trans, i2.normal),
dmnsn_matrix_vector_mul(params[1]->trans, dmnsn_zero)
)
);
- if (!i2->texture)
- i2->texture = csg->texture;
- if (!i2->interior)
- i2->interior = csg->interior;
+ if (!i2.texture)
+ i2.texture = csg->texture;
+ if (!i2.interior)
+ i2.interior = csg->interior;
}
- if (!i1)
- return i2;
- if (!i2)
- return i1;
-
- if (i1->t < i2->t) {
- dmnsn_delete_intersection(i2);
- return i1;
+ if (!is_i1 && !is_i2) {
+ return false;
+ } else if (is_i1 && !is_i2) {
+ *intersection = i1;
+ } else if (!is_i1 && is_i2) {
+ *intersection = i2;
+ } else if (i1.t < i2.t) {
+ *intersection = i1;
} else {
- dmnsn_delete_intersection(i1);
- return i2;
+ *intersection = i2;
}
+ return true;
}
static bool
@@ -124,86 +128,88 @@ dmnsn_new_csg_union(dmnsn_object *A, dmnsn_object *B)
/* Intersections */
-static dmnsn_intersection *
-dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg, dmnsn_line line)
+static bool
+dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
+ dmnsn_line line,
+ dmnsn_intersection *intersection)
{
const dmnsn_object **params = csg->ptr;
dmnsn_line line1 = dmnsn_matrix_line_mul(params[0]->trans_inv, line);
dmnsn_line line2 = dmnsn_matrix_line_mul(params[1]->trans_inv, line);
- dmnsn_intersection *i1 = (*params[0]->intersection_fn)(params[0], line1);
- dmnsn_intersection *i2 = (*params[1]->intersection_fn)(params[1], line2);
+
+ dmnsn_intersection i1, i2;
+ bool is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
+ bool is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
double oldt = 0.0;
- while (i1) {
- i1->ray = line;
- i1->t += oldt;
- oldt = i1->t;
- i1->normal = dmnsn_vector_normalize(
+ while (is_i1) {
+ i1.ray = line;
+ i1.t += oldt;
+ oldt = i1.t;
+ i1.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
- dmnsn_matrix_vector_mul(params[0]->trans, i1->normal),
+ dmnsn_matrix_vector_mul(params[0]->trans, i1.normal),
dmnsn_matrix_vector_mul(params[0]->trans, dmnsn_zero)
)
);
- if (!i1->texture)
- i1->texture = csg->texture;
- if (!i1->interior)
- i1->interior = csg->interior;
+ if (!i1.texture)
+ i1.texture = csg->texture;
+ if (!i1.interior)
+ i1.interior = csg->interior;
- dmnsn_vector point = dmnsn_line_point(i1->ray, i1->t);
+ dmnsn_vector point = dmnsn_line_point(i1.ray, i1.t);
point = dmnsn_matrix_vector_mul(params[1]->trans_inv, point);
if (!(*params[1]->inside_fn)(params[1], point)) {
- line1.x0 = dmnsn_line_point(line1, i1->t);
+ line1.x0 = dmnsn_line_point(line1, i1.t);
line1 = dmnsn_line_add_epsilon(line1);
- dmnsn_delete_intersection(i1);
- i1 = (*params[0]->intersection_fn)(params[0], line1);
+ is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
} else {
break;
}
}
oldt = 0.0;
- while (i2) {
- i2->ray = line;
- i2->t += oldt;
- oldt = i2->t;
- i2->normal = dmnsn_vector_normalize(
+ while (is_i2) {
+ i2.ray = line;
+ i2.t += oldt;
+ oldt = i2.t;
+ i2.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
- dmnsn_matrix_vector_mul(params[1]->trans, i2->normal),
+ dmnsn_matrix_vector_mul(params[1]->trans, i2.normal),
dmnsn_matrix_vector_mul(params[1]->trans, dmnsn_zero)
)
);
- if (!i2->texture)
- i2->texture = csg->texture;
- if (!i2->interior)
- i2->interior = csg->interior;
+ if (!i2.texture)
+ i2.texture = csg->texture;
+ if (!i2.interior)
+ i2.interior = csg->interior;
- dmnsn_vector point = dmnsn_line_point(i2->ray, i2->t);
+ dmnsn_vector point = dmnsn_line_point(i2.ray, i2.t);
point = dmnsn_matrix_vector_mul(params[0]->trans_inv, point);
if (!(*params[0]->inside_fn)(params[0], point)) {
- line2.x0 = dmnsn_line_point(line2, i2->t);
+ line2.x0 = dmnsn_line_point(line2, i2.t);
line2 = dmnsn_line_add_epsilon(line2);
- dmnsn_delete_intersection(i2);
- i2 = (*params[1]->intersection_fn)(params[1], line2);
+ is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
} else {
break;
}
}
- if (!i1)
- return i2;
- if (!i2)
- return i1;
-
- if (i1->t < i2->t) {
- dmnsn_delete_intersection(i2);
- return i1;
+ if (!is_i1 && !is_i2) {
+ return false;
+ } else if (is_i1 && !is_i2) {
+ *intersection = i1;
+ } else if (!is_i1 && is_i2) {
+ *intersection = i2;
+ } else if (i1.t < i2.t) {
+ *intersection = i1;
} else {
- dmnsn_delete_intersection(i1);
- return i2;
+ *intersection = i2;
}
+ return true;
}
static bool
@@ -243,86 +249,88 @@ dmnsn_new_csg_intersection(dmnsn_object *A, dmnsn_object *B)
/* Differences */
-static dmnsn_intersection *
-dmnsn_csg_difference_intersection_fn(const dmnsn_object *csg, dmnsn_line line)
+static bool
+dmnsn_csg_difference_intersection_fn(const dmnsn_object *csg,
+ dmnsn_line line,
+ dmnsn_intersection *intersection)
{
const dmnsn_object **params = csg->ptr;
dmnsn_line line1 = dmnsn_matrix_line_mul(params[0]->trans_inv, line);
dmnsn_line line2 = dmnsn_matrix_line_mul(params[1]->trans_inv, line);
- dmnsn_intersection *i1 = (*params[0]->intersection_fn)(params[0], line1);
- dmnsn_intersection *i2 = (*params[1]->intersection_fn)(params[1], line2);
+
+ dmnsn_intersection i1, i2;
+ bool is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
+ bool is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
double oldt = 0.0;
- while (i1) {
- i1->ray = line;
- i1->t += oldt;
- oldt = i1->t;
- i1->normal = dmnsn_vector_normalize(
+ while (is_i1) {
+ i1.ray = line;
+ i1.t += oldt;
+ oldt = i1.t;
+ i1.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
- dmnsn_matrix_vector_mul(params[0]->trans, i1->normal),
+ dmnsn_matrix_vector_mul(params[0]->trans, i1.normal),
dmnsn_matrix_vector_mul(params[0]->trans, dmnsn_zero)
)
);
- if (!i1->texture)
- i1->texture = csg->texture;
- if (!i1->interior)
- i1->interior = csg->interior;
+ if (!i1.texture)
+ i1.texture = csg->texture;
+ if (!i1.interior)
+ i1.interior = csg->interior;
- dmnsn_vector point = dmnsn_line_point(i1->ray, i1->t);
+ dmnsn_vector point = dmnsn_line_point(i1.ray, i1.t);
point = dmnsn_matrix_vector_mul(params[1]->trans_inv, point);
if ((*params[1]->inside_fn)(params[1], point)) {
- line1.x0 = dmnsn_line_point(line1, i1->t);
+ line1.x0 = dmnsn_line_point(line1, i1.t);
line1 = dmnsn_line_add_epsilon(line1);
- dmnsn_delete_intersection(i1);
- i1 = (*params[0]->intersection_fn)(params[0], line1);
+ is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
} else {
break;
}
}
oldt = 0.0;
- while (i2) {
- i2->ray = line;
- i2->t += oldt;
- oldt = i2->t;
- i2->normal = dmnsn_vector_normalize(
+ while (is_i2) {
+ i2.ray = line;
+ i2.t += oldt;
+ oldt = i2.t;
+ i2.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
- dmnsn_matrix_vector_mul(params[1]->trans, i2->normal),
+ dmnsn_matrix_vector_mul(params[1]->trans, i2.normal),
dmnsn_matrix_vector_mul(params[1]->trans, dmnsn_zero)
)
);
- if (!i2->texture)
- i2->texture = csg->texture;
- if (!i2->interior)
- i2->interior = csg->interior;
+ if (!i2.texture)
+ i2.texture = csg->texture;
+ if (!i2.interior)
+ i2.interior = csg->interior;
- dmnsn_vector point = dmnsn_line_point(i2->ray, i2->t);
+ dmnsn_vector point = dmnsn_line_point(i2.ray, i2.t);
point = dmnsn_matrix_vector_mul(params[0]->trans_inv, point);
if (!(*params[0]->inside_fn)(params[0], point)) {
- line2.x0 = dmnsn_line_point(line2, i2->t);
+ line2.x0 = dmnsn_line_point(line2, i2.t);
line2 = dmnsn_line_add_epsilon(line2);
- dmnsn_delete_intersection(i2);
- i2 = (*params[1]->intersection_fn)(params[1], line2);
+ is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
} else {
break;
}
}
- if (!i1)
- return i2;
- if (!i2)
- return i1;
-
- if (i1->t < i2->t) {
- dmnsn_delete_intersection(i2);
- return i1;
+ if (!is_i1 && !is_i2) {
+ return false;
+ } else if (is_i1 && !is_i2) {
+ *intersection = i1;
+ } else if (!is_i1 && is_i2) {
+ *intersection = i2;
+ } else if (i1.t < i2.t) {
+ *intersection = i1;
} else {
- dmnsn_delete_intersection(i1);
- return i2;
+ *intersection = i2;
}
+ return true;
}
static bool
@@ -356,86 +364,88 @@ dmnsn_new_csg_difference(dmnsn_object *A, dmnsn_object *B)
/* Merges */
-static dmnsn_intersection *
-dmnsn_csg_merge_intersection_fn(const dmnsn_object *csg, dmnsn_line line)
+static bool
+dmnsn_csg_merge_intersection_fn(const dmnsn_object *csg,
+ dmnsn_line line,
+ dmnsn_intersection *intersection)
{
const dmnsn_object **params = csg->ptr;
dmnsn_line line1 = dmnsn_matrix_line_mul(params[0]->trans_inv, line);
dmnsn_line line2 = dmnsn_matrix_line_mul(params[1]->trans_inv, line);
- dmnsn_intersection *i1 = (*params[0]->intersection_fn)(params[0], line1);
- dmnsn_intersection *i2 = (*params[1]->intersection_fn)(params[1], line2);
+
+ dmnsn_intersection i1, i2;
+ bool is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
+ bool is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
double oldt = 0.0;
- while (i1) {
- i1->ray = line;
- i1->t += oldt;
- oldt = i1->t;
- i1->normal = dmnsn_vector_normalize(
+ while (is_i1) {
+ i1.ray = line;
+ i1.t += oldt;
+ oldt = i1.t;
+ i1.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
- dmnsn_matrix_vector_mul(params[0]->trans, i1->normal),
+ dmnsn_matrix_vector_mul(params[0]->trans, i1.normal),
dmnsn_matrix_vector_mul(params[0]->trans, dmnsn_zero)
)
);
- if (!i1->texture)
- i1->texture = csg->texture;
- if (!i1->interior)
- i1->interior = csg->interior;
+ if (!i1.texture)
+ i1.texture = csg->texture;
+ if (!i1.interior)
+ i1.interior = csg->interior;
- dmnsn_vector point = dmnsn_line_point(i1->ray, i1->t);
+ dmnsn_vector point = dmnsn_line_point(i1.ray, i1.t);
point = dmnsn_matrix_vector_mul(params[1]->trans_inv, point);
if ((*params[1]->inside_fn)(params[1], point)) {
- line1.x0 = dmnsn_line_point(line1, i1->t);
+ line1.x0 = dmnsn_line_point(line1, i1.t);
line1 = dmnsn_line_add_epsilon(line1);
- dmnsn_delete_intersection(i1);
- i1 = (*params[0]->intersection_fn)(params[0], line1);
+ is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
} else {
break;
}
}
oldt = 0.0;
- while (i2) {
- i2->ray = line;
- i2->t += oldt;
- oldt = i2->t;
- i2->normal = dmnsn_vector_normalize(
+ while (is_i2) {
+ i2.ray = line;
+ i2.t += oldt;
+ oldt = i2.t;
+ i2.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
- dmnsn_matrix_vector_mul(params[1]->trans, i2->normal),
+ dmnsn_matrix_vector_mul(params[1]->trans, i2.normal),
dmnsn_matrix_vector_mul(params[1]->trans, dmnsn_zero)
)
);
- if (!i2->texture)
- i2->texture = csg->texture;
- if (!i2->interior)
- i2->interior = csg->interior;
+ if (!i2.texture)
+ i2.texture = csg->texture;
+ if (!i2.interior)
+ i2.interior = csg->interior;
- dmnsn_vector point = dmnsn_line_point(i2->ray, i2->t);
+ dmnsn_vector point = dmnsn_line_point(i2.ray, i2.t);
point = dmnsn_matrix_vector_mul(params[0]->trans_inv, point);
if ((*params[0]->inside_fn)(params[0], point)) {
- line2.x0 = dmnsn_line_point(line2, i2->t);
+ line2.x0 = dmnsn_line_point(line2, i2.t);
line2 = dmnsn_line_add_epsilon(line2);
- dmnsn_delete_intersection(i2);
- i2 = (*params[1]->intersection_fn)(params[1], line2);
+ is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
} else {
break;
}
}
- if (!i1)
- return i2;
- if (!i2)
- return i1;
-
- if (i1->t < i2->t) {
- dmnsn_delete_intersection(i2);
- return i1;
+ if (!is_i1 && !is_i2) {
+ return false;
+ } else if (is_i1 && !is_i2) {
+ *intersection = i1;
+ } else if (!is_i1 && is_i2) {
+ *intersection = i2;
+ } else if (i1.t < i2.t) {
+ *intersection = i1;
} else {
- dmnsn_delete_intersection(i1);
- return i2;
+ *intersection = i2;
}
+ return true;
}
static bool