summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-06-14 19:22:33 -0600
committerTavian Barnes <tavianator@gmail.com>2010-06-14 19:22:33 -0600
commitde8a9632a6859010cc9d9bb4bcff721d640cdbd5 (patch)
tree70969c63dcc7afe3751b1dbd026846fbe3680bf4
parentee485871988b606966cd6779f818ef67067ef3f3 (diff)
downloaddimension-de8a9632a6859010cc9d9bb4bcff721d640cdbd5.tar.xz
Bulk-load CSG unions.
The old way made O(n) PR-trees for no particular reason.
-rw-r--r--dimension/realize.c40
-rw-r--r--libdimension/csg.c9
-rw-r--r--libdimension/dimension/csg.h2
3 files changed, 40 insertions, 11 deletions
diff --git a/dimension/realize.c b/dimension/realize.c
index 711090b..e558c5b 100644
--- a/dimension/realize.c
+++ b/dimension/realize.c
@@ -854,6 +854,39 @@ dmnsn_realize_plane(dmnsn_astnode astnode)
return plane;
}
+/* Bulk-load a union */
+static dmnsn_object *
+dmnsn_realize_union(dmnsn_astnode astnode, dmnsn_array *lights)
+{
+ dmnsn_assert(astnode.type == DMNSN_AST_UNION, "Expected a union.");
+
+ dmnsn_astnode objects, modifiers;
+ dmnsn_array_get(astnode.children, 0, &objects);
+ dmnsn_array_get(astnode.children, 1, &modifiers);
+
+ dmnsn_array *children = dmnsn_new_array(sizeof(dmnsn_object *));
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, onode, objects.children) {
+ if (onode->type == DMNSN_AST_LIGHT_SOURCE) {
+ dmnsn_light *light = dmnsn_realize_light_source(*onode);
+ dmnsn_realize_light_source_modifiers(modifiers, light);
+ dmnsn_array_push(lights, &light);
+ } else {
+ dmnsn_object *object = dmnsn_realize_object(*onode, lights);
+ if (object)
+ dmnsn_array_push(children, &object);
+ }
+ }
+
+ dmnsn_object *csg = NULL;
+ if (dmnsn_array_size(children) > 0) {
+ csg = dmnsn_new_csg_union(children);
+ dmnsn_realize_object_modifiers(modifiers, csg);
+ }
+
+ dmnsn_delete_array(children);
+ return csg;
+}
+
typedef dmnsn_object *dmnsn_csg_object_fn(dmnsn_object *a, dmnsn_object *b);
/* Generalized CSG realizer */
@@ -901,13 +934,6 @@ dmnsn_realize_csg(dmnsn_astnode astnode, dmnsn_array *lights,
}
static dmnsn_object *
-dmnsn_realize_union(dmnsn_astnode astnode, dmnsn_array *lights)
-{
- dmnsn_assert(astnode.type == DMNSN_AST_UNION, "Expected a union.");
- return dmnsn_realize_csg(astnode, lights, &dmnsn_new_csg_union);
-}
-
-static dmnsn_object *
dmnsn_realize_intersection(dmnsn_astnode astnode, dmnsn_array *lights)
{
dmnsn_assert(astnode.type == DMNSN_AST_INTERSECTION,
diff --git a/libdimension/csg.c b/libdimension/csg.c
index 02c4d37..b48c2fa 100644
--- a/libdimension/csg.c
+++ b/libdimension/csg.c
@@ -76,13 +76,16 @@ dmnsn_csg_union_free_fn(void *ptr)
dmnsn_delete_prtree(ptr);
}
+/* Bulk-load a union */
dmnsn_object *
-dmnsn_new_csg_union(dmnsn_object *A, dmnsn_object *B)
+dmnsn_new_csg_union(dmnsn_array *objects)
{
dmnsn_object *csg = dmnsn_new_object();
- dmnsn_array_push(csg->children, &A);
- dmnsn_array_push(csg->children, &B);
+ DMNSN_ARRAY_FOREACH (dmnsn_object **, object, objects) {
+ dmnsn_array_push(csg->children, object);
+ }
+
csg->intersection_fn = &dmnsn_csg_union_intersection_fn;
csg->inside_fn = &dmnsn_csg_union_inside_fn;
csg->init_fn = &dmnsn_csg_union_init_fn;
diff --git a/libdimension/dimension/csg.h b/libdimension/dimension/csg.h
index 383efb4..176467a 100644
--- a/libdimension/dimension/csg.h
+++ b/libdimension/dimension/csg.h
@@ -25,7 +25,7 @@
#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_union(dmnsn_array *objects);
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);