diff options
author | Tavian Barnes <tavianator@gmail.com> | 2010-04-06 01:28:29 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2010-04-06 01:28:29 -0400 |
commit | ffb8da7d94a130f2d152f706d1af113fc4640246 (patch) | |
tree | 2888622fe853c9a494c4ed6915b2e0a72538b349 /libdimension | |
parent | b7405924923986314b09460995c2ebce3b717100 (diff) | |
download | dimension-ffb8da7d94a130f2d152f706d1af113fc4640246.tar.xz |
Add CSG unions to libdimension.
Diffstat (limited to 'libdimension')
-rw-r--r-- | libdimension/Makefile.am | 2 | ||||
-rw-r--r-- | libdimension/csg.c | 143 | ||||
-rw-r--r-- | libdimension/dimension.h | 1 | ||||
-rw-r--r-- | libdimension/dimension/csg.h | 33 |
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 */ |