summaryrefslogtreecommitdiffstats
path: root/libdimension
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-04-06 01:28:29 -0400
committerTavian Barnes <tavianator@gmail.com>2010-04-06 01:28:29 -0400
commitffb8da7d94a130f2d152f706d1af113fc4640246 (patch)
tree2888622fe853c9a494c4ed6915b2e0a72538b349 /libdimension
parentb7405924923986314b09460995c2ebce3b717100 (diff)
downloaddimension-ffb8da7d94a130f2d152f706d1af113fc4640246.tar.xz
Add CSG unions to libdimension.
Diffstat (limited to 'libdimension')
-rw-r--r--libdimension/Makefile.am2
-rw-r--r--libdimension/csg.c143
-rw-r--r--libdimension/dimension.h1
-rw-r--r--libdimension/dimension/csg.h33
4 files changed, 179 insertions, 0 deletions
diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am
index 4f427d0..2dda68c 100644
--- a/libdimension/Makefile.am
+++ b/libdimension/Makefile.am
@@ -26,6 +26,7 @@ nobase_include_HEADERS = dimension.h \
dimension/cameras.h \
dimension/canvas.h \
dimension/color.h \
+ dimension/csg.h \
dimension/error.h \
dimension/finishes.h \
dimension/geometry.h \
@@ -52,6 +53,7 @@ libdimension_la_SOURCES = $(nobase_include_HEADERS) \
canvas.c \
color.c \
cube.c \
+ csg.c \
diffuse.c \
dimension_impl.h \
error.c \
diff --git a/libdimension/csg.c b/libdimension/csg.c
new file mode 100644
index 0000000..5b3cf9a
--- /dev/null
+++ b/libdimension/csg.c
@@ -0,0 +1,143 @@
+/*************************************************************************
+ * Copyright (C) 2010 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of The Dimension Library. *
+ * *
+ * The Dimension Library is free software; you can redistribute it and/ *
+ * or modify it under the terms of the GNU Lesser General Public License *
+ * as published by the Free Software Foundation; either version 3 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * The Dimension Library is distributed in the hope that it will be *
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty *
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+#include "dimension.h"
+#include <errno.h>
+
+static void
+dmnsn_csg_free_fn(void *ptr)
+{
+ dmnsn_object **params = ptr;
+ dmnsn_delete_object(params[1]);
+ dmnsn_delete_object(params[0]);
+ free(ptr);
+}
+
+/* Unions */
+
+static dmnsn_intersection *
+dmnsn_csg_union_intersection_fn(const dmnsn_object *csg, dmnsn_line line)
+{
+ 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) {
+ /* Transform the intersection back to the observer's view */
+ 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, dmnsn_zero)
+ )
+ );
+
+ if (!i1->texture)
+ i1->texture = csg->texture;
+ if (!i1->interior)
+ i1->interior = csg->interior;
+ }
+
+ if (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, dmnsn_zero)
+ )
+ );
+
+ 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;
+ } else {
+ dmnsn_delete_intersection(i1);
+ return i2;
+ }
+}
+
+static bool
+dmnsn_csg_union_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);
+}
+
+dmnsn_object *
+dmnsn_new_csg_union(dmnsn_object *A, dmnsn_object *B)
+{
+ if (A && B) {
+ A->trans_inv = dmnsn_matrix_inverse(A->trans);
+ B->trans_inv = dmnsn_matrix_inverse(B->trans);
+
+ dmnsn_object *csg = dmnsn_new_object();
+ if (csg) {
+ dmnsn_object **params = malloc(2*sizeof(dmnsn_object *));
+ if (!params) {
+ dmnsn_delete_object(csg);
+ dmnsn_delete_object(B);
+ dmnsn_delete_object(A);
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ params[0] = A;
+ params[1] = B;
+
+ csg->ptr = params;
+ csg->intersection_fn = &dmnsn_csg_union_intersection_fn;
+ csg->inside_fn = &dmnsn_csg_union_inside_fn;
+ csg->free_fn = &dmnsn_csg_free_fn;
+
+ dmnsn_bounding_box Abox
+ = dmnsn_matrix_bounding_box_mul(A->trans, A->bounding_box);
+ dmnsn_bounding_box Bbox
+ = dmnsn_matrix_bounding_box_mul(B->trans, B->bounding_box);
+ csg->bounding_box.min = dmnsn_vector_min(Abox.min, Bbox.min);
+ csg->bounding_box.max = dmnsn_vector_max(Abox.max, Bbox.max);
+
+ return csg;
+ } else {
+ dmnsn_delete_object(B);
+ dmnsn_delete_object(A);
+ }
+ } else if (A) {
+ dmnsn_delete_object(B);
+ } else if (B) {
+ dmnsn_delete_object(A);
+ }
+
+ return NULL;
+}
diff --git a/libdimension/dimension.h b/libdimension/dimension.h
index be0e9bb..e693841 100644
--- a/libdimension/dimension.h
+++ b/libdimension/dimension.h
@@ -74,6 +74,7 @@ typedef void dmnsn_free_fn(void *ptr);
#include <dimension/interior.h>
#include <dimension/object.h>
#include <dimension/objects.h>
+#include <dimension/csg.h>
#include <dimension/light.h>
#include <dimension/lights.h>
#include <dimension/camera.h>
diff --git a/libdimension/dimension/csg.h b/libdimension/dimension/csg.h
new file mode 100644
index 0000000..383efb4
--- /dev/null
+++ b/libdimension/dimension/csg.h
@@ -0,0 +1,33 @@
+/*************************************************************************
+ * Copyright (C) 2010 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of The Dimension Library. *
+ * *
+ * The Dimension Library is free software; you can redistribute it and/ *
+ * or modify it under the terms of the GNU Lesser General Public License *
+ * as published by the Free Software Foundation; either version 3 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * The Dimension Library is distributed in the hope that it will be *
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty *
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+/*
+ * Constructive solid geometry
+ */
+
+#ifndef DIMENSION_CSG_H
+#define DIMENSION_CSG_H
+
+dmnsn_object *dmnsn_new_csg_union(dmnsn_object *A, dmnsn_object *B);
+dmnsn_object *dmnsn_new_csg_intersection(dmnsn_object *A, dmnsn_object *B);
+dmnsn_object *dmnsn_new_csg_difference(dmnsn_object *A, dmnsn_object *B);
+dmnsn_object *dmnsn_new_csg_merge(dmnsn_object *A, dmnsn_object *B);
+
+#endif /* DIMENSION_CSG_H */