summaryrefslogtreecommitdiffstats
path: root/libdimension/csg.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension/csg.c')
-rw-r--r--libdimension/csg.c186
1 files changed, 23 insertions, 163 deletions
diff --git a/libdimension/csg.c b/libdimension/csg.c
index 4619759..14240d5 100644
--- a/libdimension/csg.c
+++ b/libdimension/csg.c
@@ -126,13 +126,15 @@ dmnsn_new_csg_union(dmnsn_object *A, dmnsn_object *B)
return csg;
}
-/* Intersections */
-
+/* Generic CSG intersection function */
static bool
-dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
- dmnsn_line line,
- dmnsn_intersection *intersection)
+dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line,
+ dmnsn_intersection *intersection,
+ bool inside1, bool inside2)
{
+ /* inside1 is whether the first object is allowed inside the second object;
+ respectively for inside2 */
+
const dmnsn_object **params = csg->ptr;
dmnsn_line line1 = dmnsn_matrix_line_mul(params[0]->trans_inv, line);
@@ -146,7 +148,7 @@ dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
while (is_i1) {
i1.ray = line;
i1.t += oldt;
- oldt = i1.t;
+ oldt = i1.t + dmnsn_epsilon;
i1.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
dmnsn_matrix_vector_mul(params[0]->trans, i1.normal),
@@ -161,7 +163,7 @@ dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
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)) {
+ if (inside1 ^ (*params[1]->inside_fn)(params[1], point)) {
line1.x0 = dmnsn_line_point(line1, i1.t);
line1 = dmnsn_line_add_epsilon(line1);
is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
@@ -174,7 +176,7 @@ dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
while (is_i2) {
i2.ray = line;
i2.t += oldt;
- oldt = i2.t;
+ oldt = i2.t + dmnsn_epsilon;
i2.normal = dmnsn_vector_normalize(
dmnsn_vector_sub(
dmnsn_matrix_vector_mul(params[1]->trans, i2.normal),
@@ -189,7 +191,7 @@ dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
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)) {
+ if (inside2 ^ (*params[0]->inside_fn)(params[0], point)) {
line2.x0 = dmnsn_line_point(line2, i2.t);
line2 = dmnsn_line_add_epsilon(line2);
is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
@@ -212,6 +214,16 @@ dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
return true;
}
+/* Intersections */
+
+static bool
+dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
+ dmnsn_line line,
+ dmnsn_intersection *intersection)
+{
+ return dmnsn_csg_intersection_fn(csg, line, intersection, true, true);
+}
+
static bool
dmnsn_csg_intersection_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
{
@@ -254,83 +266,7 @@ 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, 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 (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, dmnsn_zero)
- )
- );
-
- if (!i1.texture)
- i1.texture = csg->texture;
- if (!i1.interior)
- i1.interior = csg->interior;
-
- 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 = dmnsn_line_add_epsilon(line1);
- is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
- } else {
- break;
- }
- }
-
- oldt = 0.0;
- 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, dmnsn_zero)
- )
- );
-
- if (!i2.texture)
- i2.texture = csg->texture;
- if (!i2.interior)
- i2.interior = csg->interior;
-
- 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 = dmnsn_line_add_epsilon(line2);
- is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
- } else {
- break;
- }
- }
-
- 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 {
- *intersection = i2;
- }
- return true;
+ return dmnsn_csg_intersection_fn(csg, line, intersection, false, true);
}
static bool
@@ -369,83 +305,7 @@ 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, 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 (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, dmnsn_zero)
- )
- );
-
- if (!i1.texture)
- i1.texture = csg->texture;
- if (!i1.interior)
- i1.interior = csg->interior;
-
- 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 = dmnsn_line_add_epsilon(line1);
- is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1);
- } else {
- break;
- }
- }
-
- oldt = 0.0;
- 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, dmnsn_zero)
- )
- );
-
- if (!i2.texture)
- i2.texture = csg->texture;
- if (!i2.interior)
- i2.interior = csg->interior;
-
- 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 = dmnsn_line_add_epsilon(line2);
- is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2);
- } else {
- break;
- }
- }
-
- 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 {
- *intersection = i2;
- }
- return true;
+ return dmnsn_csg_intersection_fn(csg, line, intersection, false, false);
}
static bool