summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-05-08 23:21:48 -0600
committerTavian Barnes <tavianator@gmail.com>2010-05-08 23:21:48 -0600
commit7a21db5914dd7a5666e603d66ed3948b659ba2fc (patch)
treebde8e00a1677ba865adae8a82780d1cc832ece8e
parent152362a57dc7fe9dce830ef69118984f854d6375 (diff)
downloaddimension-7a21db5914dd7a5666e603d66ed3948b659ba2fc.tar.xz
New DMNSN_ARRAY_FOREACH() macro, faster than iterating with dmnsn_array_get().
-rw-r--r--dimension/common.rules16
-rw-r--r--dimension/lexer.l17
-rw-r--r--dimension/parse.c48
-rw-r--r--dimension/realize.c199
-rw-r--r--dimension/tokenize.c6
-rw-r--r--libdimension/canvas.c15
-rw-r--r--libdimension/dimension/array.h22
-rw-r--r--libdimension/gl.c15
-rw-r--r--libdimension/png.c12
-rw-r--r--libdimension/prtree.c13
-rw-r--r--libdimension/raytrace.c10
-rw-r--r--libdimension/scene.c14
12 files changed, 169 insertions, 218 deletions
diff --git a/dimension/common.rules b/dimension/common.rules
index 4644627..d897eb3 100644
--- a/dimension/common.rules
+++ b/dimension/common.rules
@@ -152,11 +152,9 @@ OBJECT: FINITE_SOLID_OBJECT
*modifiers = dmnsn_new_astnode(DMNSN_AST_OBJECT_MODIFIERS, @4);
dmnsn_copy_children(*modifiers, orig_modifiers);
- for (size_t i = 0; i < dmnsn_array_size($4.children); ++i) {
- dmnsn_astnode astnode;
- dmnsn_array_get($4.children, i, &astnode);
- ++*astnode.refcount;
- dmnsn_array_push(modifiers->children, &astnode);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, astnode, $4.children) {
+ ++*astnode->refcount;
+ dmnsn_array_push(modifiers->children, astnode);
}
dmnsn_delete_astnode($4);
break;
@@ -185,11 +183,9 @@ OBJECT: FINITE_SOLID_OBJECT
dmnsn_array_size($$.children) - 1,
&modifiers);
- for (size_t i = 0; i < dmnsn_array_size($4.children); ++i) {
- dmnsn_astnode astnode;
- dmnsn_array_get($4.children, i, &astnode);
- ++*astnode.refcount;
- dmnsn_array_push(modifiers.children, &astnode);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, astnode, $4.children) {
+ ++*astnode->refcount;
+ dmnsn_array_push(modifiers.children, astnode);
}
dmnsn_delete_astnode($4);
diff --git a/dimension/lexer.l b/dimension/lexer.l
index 6198fea..a3dc683 100644
--- a/dimension/lexer.l
+++ b/dimension/lexer.l
@@ -421,10 +421,8 @@ dmnsn_delete_token(dmnsn_token token)
void
dmnsn_delete_tokens(dmnsn_array *tokens)
{
- dmnsn_token token;
- for (size_t i = 0; i < dmnsn_array_size(tokens); ++i) {
- dmnsn_array_get(tokens, i, &token);
- dmnsn_delete_token(token);
+ DMNSN_ARRAY_FOREACH (dmnsn_token *, token, tokens) {
+ dmnsn_delete_token(*token);
}
dmnsn_delete_array(tokens);
}
@@ -453,19 +451,16 @@ dmnsn_print_token(FILE *file, dmnsn_token token)
void
dmnsn_print_token_sexpr(FILE *file, const dmnsn_array *tokens)
{
- dmnsn_token token;
-
if (dmnsn_array_size(tokens) == 0) {
fprintf(file, "()");
} else {
fprintf(file, "(");
- dmnsn_array_get(tokens, 0, &token);
- dmnsn_print_token(file, token);
+ dmnsn_token *token = dmnsn_array_first(tokens);
+ dmnsn_print_token(file, *token);
- for (size_t i = 1; i < dmnsn_array_size(tokens); ++i) {
+ for (++token; token <= (dmnsn_token *)dmnsn_array_last(tokens); ++token) {
fprintf(file, " ");
- dmnsn_array_get(tokens, i, &token);
- dmnsn_print_token(file, token);
+ dmnsn_print_token(file, *token);
}
fprintf(file, ")");
diff --git a/dimension/parse.c b/dimension/parse.c
index 54b5880..efb208f 100644
--- a/dimension/parse.c
+++ b/dimension/parse.c
@@ -288,10 +288,8 @@ dmnsn_declare_symbol(dmnsn_symbol_table *symtable,
void
dmnsn_undef_symbol(dmnsn_symbol_table *symtable, const char *id)
{
- for (size_t i = 0; i < dmnsn_array_size(symtable); ++i) {
- dmnsn_patricia_trie *trie;
- dmnsn_array_get(symtable, dmnsn_array_size(symtable) - i - 1, &trie);
- if (dmnsn_patricia_remove(trie, id))
+ DMNSN_ARRAY_FOREACH (dmnsn_patricia_trie **, trie, symtable) {
+ if (dmnsn_patricia_remove(*trie, id))
break;
}
}
@@ -301,11 +299,11 @@ dmnsn_find_symbol(dmnsn_symbol_table *symtable, const char *id)
{
dmnsn_astnode *symbol = NULL;
- for (size_t i = 0; i < dmnsn_array_size(symtable); ++i) {
- dmnsn_patricia_trie *trie;
- dmnsn_array_get(symtable, dmnsn_array_size(symtable) - i - 1, &trie);
-
- symbol = dmnsn_patricia_find(trie, id);
+ for (dmnsn_patricia_trie **trie = dmnsn_array_last(symtable);
+ trie >= (dmnsn_patricia_trie **)dmnsn_array_first(symtable);
+ --trie)
+ {
+ symbol = dmnsn_patricia_find(*trie, id);
if (symbol)
break;
}
@@ -469,10 +467,8 @@ void
dmnsn_delete_astree(dmnsn_astree *astree)
{
if (astree) {
- for (size_t i = 0; i < dmnsn_array_size(astree); ++i) {
- dmnsn_astnode node;
- dmnsn_array_get(astree, i, &node);
- dmnsn_delete_astnode(node);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, node, astree) {
+ dmnsn_delete_astnode(*node);
}
dmnsn_delete_array(astree);
}
@@ -514,9 +510,8 @@ dmnsn_vector_promote(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
if (astnode.type == DMNSN_AST_VECTOR) {
dmnsn_astnode component;
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_array_get(astnode.children, i, &component);
- component = dmnsn_eval_scalar(component, symtable);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, i, astnode.children) {
+ component = dmnsn_eval_scalar(*i, symtable);
if (component.type == DMNSN_AST_NONE) {
dmnsn_delete_astnode(promoted);
@@ -1773,15 +1768,12 @@ dmnsn_print_astnode(FILE *file, dmnsn_astnode astnode)
static void
dmnsn_print_astree(FILE *file, dmnsn_astnode astnode)
{
- dmnsn_astnode child;
-
if (astnode.children && dmnsn_array_size(astnode.children) > 0) {
fprintf(file, "(");
dmnsn_print_astnode(file, astnode);
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_array_get(astnode.children, i, &child);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, child, astnode.children) {
fprintf(file, " ");
- dmnsn_print_astree(file, child);
+ dmnsn_print_astree(file, *child);
}
fprintf(file, ")");
} else {
@@ -1792,19 +1784,19 @@ dmnsn_print_astree(FILE *file, dmnsn_astnode astnode)
void
dmnsn_print_astree_sexpr(FILE *file, const dmnsn_astree *astree)
{
- dmnsn_astnode astnode;
-
if (dmnsn_array_size(astree) == 0) {
fprintf(file, "()");
} else {
fprintf(file, "(");
- dmnsn_array_get(astree, 0, &astnode);
- dmnsn_print_astree(file, astnode);
+ dmnsn_astnode *astnode = dmnsn_array_first(astree);
+ dmnsn_print_astree(file, *astnode);
- for (size_t i = 1; i < dmnsn_array_size(astree); ++i) {
+ for (++astnode;
+ astnode <= (dmnsn_astnode *)dmnsn_array_last(astree);
+ ++astnode)
+ {
fprintf(file, " ");
- dmnsn_array_get(astree, i, &astnode);
- dmnsn_print_astree(file, astnode);
+ dmnsn_print_astree(file, *astnode);
}
fprintf(file, ")");
diff --git a/dimension/realize.c b/dimension/realize.c
index 05eae07..ec0819f 100644
--- a/dimension/realize.c
+++ b/dimension/realize.c
@@ -190,17 +190,16 @@ dmnsn_realize_global_settings(dmnsn_astnode astnode, dmnsn_scene *scene)
dmnsn_assert(astnode.type == DMNSN_AST_GLOBAL_SETTINGS,
"Expected global settings.");
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode item, child;
- dmnsn_array_get(astnode.children, i, &item);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, item, astnode.children) {
+ dmnsn_astnode child;
- switch (item.type) {
+ switch (item->type) {
case DMNSN_AST_ASSUMED_GAMMA:
/* assumed_gamma not supported */
break;
case DMNSN_AST_MAX_TRACE_LEVEL:
- dmnsn_array_get(item.children, 0, &child);
+ dmnsn_array_get(item->children, 0, &child);
scene->reclimit = dmnsn_realize_integer(child);
break;
@@ -227,44 +226,43 @@ dmnsn_realize_camera(dmnsn_astnode astnode)
dmnsn_camera *camera = NULL;
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode item;
- dmnsn_array_get(astnode.children, i, &item);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, item, astnode.children) {
+ dmnsn_astnode child;
- switch (item.type) {
+ switch (item->type) {
/* Camera types */
case DMNSN_AST_PERSPECTIVE:
- camera_type = item.type;
+ camera_type = item->type;
break;
/* Camera vectors */
case DMNSN_AST_LOCATION:
- dmnsn_array_get(item.children, 0, &item);
- location = dmnsn_realize_vector(item);
+ dmnsn_array_get(item->children, 0, &child);
+ location = dmnsn_realize_vector(child);
break;
case DMNSN_AST_RIGHT:
- dmnsn_array_get(item.children, 0, &item);
- right = dmnsn_realize_vector(item);
+ dmnsn_array_get(item->children, 0, &child);
+ right = dmnsn_realize_vector(child);
break;
case DMNSN_AST_UP:
- dmnsn_array_get(item.children, 0, &item);
- right = dmnsn_realize_vector(item);
+ dmnsn_array_get(item->children, 0, &child);
+ right = dmnsn_realize_vector(child);
break;
case DMNSN_AST_SKY:
- dmnsn_array_get(item.children, 0, &item);
- sky = dmnsn_realize_vector(item);
+ dmnsn_array_get(item->children, 0, &child);
+ sky = dmnsn_realize_vector(child);
break;
case DMNSN_AST_DIRECTION:
- dmnsn_array_get(item.children, 0, &item);
- direction = dmnsn_realize_vector(item);
+ dmnsn_array_get(item->children, 0, &child);
+ direction = dmnsn_realize_vector(child);
break;
/* Camera modifiers */
case DMNSN_AST_LOOK_AT:
{
- dmnsn_array_get(item.children, 0, &item);
- dmnsn_vector look_at = dmnsn_realize_vector(item);
+ dmnsn_array_get(item->children, 0, &child);
+ dmnsn_vector look_at = dmnsn_realize_vector(child);
/* Line the camera up with the sky */
@@ -312,8 +310,8 @@ dmnsn_realize_camera(dmnsn_astnode astnode)
case DMNSN_AST_ANGLE:
{
- dmnsn_array_get(item.children, 0, &item);
- double angle = deg2rad*dmnsn_realize_float(item);
+ dmnsn_array_get(item->children, 0, &child);
+ double angle = deg2rad*dmnsn_realize_float(child);
direction = dmnsn_vector_mul(
0.5*dmnsn_vector_norm(right)/tan(angle/2.0),
dmnsn_vector_normalize(direction)
@@ -325,7 +323,7 @@ dmnsn_realize_camera(dmnsn_astnode astnode)
case DMNSN_AST_ROTATION:
case DMNSN_AST_SCALE:
case DMNSN_AST_TRANSLATION:
- trans = dmnsn_matrix_mul(dmnsn_realize_transformation(item), trans);
+ trans = dmnsn_matrix_mul(dmnsn_realize_transformation(*item), trans);
break;
default:
@@ -408,16 +406,13 @@ dmnsn_realize_pigment_modifiers(dmnsn_astnode astnode, dmnsn_pigment *pigment)
dmnsn_assert(astnode.type == DMNSN_AST_PIGMENT_MODIFIERS,
"Expected pigment modifiers.");
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode modifier;
- dmnsn_array_get(astnode.children, i, &modifier);
-
- switch (modifier.type) {
+ DMNSN_ARRAY_FOREACH(dmnsn_astnode *, modifier, astnode.children) {
+ switch (modifier->type) {
case DMNSN_AST_ROTATION:
case DMNSN_AST_SCALE:
case DMNSN_AST_TRANSLATION:
pigment->trans = dmnsn_matrix_mul(
- dmnsn_realize_transformation(modifier),
+ dmnsn_realize_transformation(*modifier),
pigment->trans
);
break;
@@ -507,13 +502,12 @@ dmnsn_realize_reflection(dmnsn_astnode astnode)
dmnsn_astnode items;
dmnsn_array_get(astnode.children, 2, &items);
- for (size_t i = 0; i < dmnsn_array_size(items.children); ++i) {
- dmnsn_astnode item, child;
- dmnsn_array_get(items.children, i, &item);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, item, items.children) {
+ dmnsn_astnode child;
- switch (item.type) {
+ switch (item->type) {
case DMNSN_AST_FALLOFF:
- dmnsn_array_get(item.children, 0, &child);
+ dmnsn_array_get(item->children, 0, &child);
falloff = dmnsn_realize_float(child);
break;
@@ -545,35 +539,34 @@ dmnsn_realize_finish(dmnsn_astnode astnode)
dmnsn_finish *reflection = NULL;
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode item, child;
- dmnsn_array_get(astnode.children, i, &item);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, item, astnode.children) {
+ dmnsn_astnode child;
- switch (item.type) {
+ switch (item->type) {
case DMNSN_AST_AMBIENT:
- dmnsn_array_get(item.children, 0, &child);
+ dmnsn_array_get(item->children, 0, &child);
ambient = dmnsn_realize_color(child);
ambient_set = true;
break;
case DMNSN_AST_DIFFUSE:
- dmnsn_array_get(item.children, 0, &child);
+ dmnsn_array_get(item->children, 0, &child);
diffuse = dmnsn_realize_float(child);
diffuse_set = true;
break;
case DMNSN_AST_PHONG:
- dmnsn_array_get(item.children, 0, &child);
+ dmnsn_array_get(item->children, 0, &child);
phong = dmnsn_realize_float(child);
break;
case DMNSN_AST_PHONG_SIZE:
- dmnsn_array_get(item.children, 0, &child);
+ dmnsn_array_get(item->children, 0, &child);
phong_size = dmnsn_realize_float(child);
break;
case DMNSN_AST_REFLECTION:
dmnsn_delete_finish(reflection);
- reflection = dmnsn_realize_reflection(item);
+ reflection = dmnsn_realize_reflection(*item);
break;
default:
@@ -616,26 +609,25 @@ dmnsn_realize_texture(dmnsn_astnode astnode)
dmnsn_texture *texture = dmnsn_new_texture();
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode item;
- dmnsn_array_get(astnode.children, i, &item);
-
- switch (item.type) {
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, item, astnode.children) {
+ switch (item->type) {
case DMNSN_AST_PIGMENT:
dmnsn_delete_pigment(texture->pigment);
- texture->pigment = dmnsn_realize_pigment(item);
+ texture->pigment = dmnsn_realize_pigment(*item);
break;
case DMNSN_AST_FINISH:
dmnsn_delete_finish(texture->finish);
- texture->finish = dmnsn_realize_finish(item);
+ texture->finish = dmnsn_realize_finish(*item);
break;
case DMNSN_AST_ROTATION:
case DMNSN_AST_SCALE:
case DMNSN_AST_TRANSLATION:
- texture->trans = dmnsn_matrix_mul(dmnsn_realize_transformation(item),
- texture->trans);
+ texture->trans = dmnsn_matrix_mul(
+ dmnsn_realize_transformation(*item),
+ texture->trans
+ );
break;
default:
@@ -653,13 +645,12 @@ dmnsn_realize_interior(dmnsn_astnode astnode)
dmnsn_interior *interior = dmnsn_new_interior();
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode item, child;
- dmnsn_array_get(astnode.children, i, &item);
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, item, astnode.children) {
+ dmnsn_astnode child;
- switch (item.type) {
+ switch (item->type) {
case DMNSN_AST_IOR:
- dmnsn_array_get(item.children, 0, &child);
+ dmnsn_array_get(item->children, 0, &child);
interior->ior = dmnsn_realize_float(child);
break;
@@ -680,40 +671,37 @@ dmnsn_realize_object_modifiers(dmnsn_astnode astnode, dmnsn_object *object)
/* Save the pre-existing transformations */
dmnsn_matrix existing_trans = dmnsn_matrix_inverse(object->trans);
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode modifier;
- dmnsn_array_get(astnode.children, i, &modifier);
-
- switch (modifier.type) {
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, modifier, astnode.children) {
+ switch (modifier->type) {
case DMNSN_AST_ROTATION:
case DMNSN_AST_SCALE:
case DMNSN_AST_TRANSLATION:
object->trans = dmnsn_matrix_mul(
- dmnsn_realize_transformation(modifier),
+ dmnsn_realize_transformation(*modifier),
object->trans
);
break;
case DMNSN_AST_TEXTURE:
dmnsn_delete_texture(object->texture);
- object->texture = dmnsn_realize_texture(modifier);
+ object->texture = dmnsn_realize_texture(*modifier);
break;
case DMNSN_AST_PIGMENT:
if (!object->texture)
object->texture = dmnsn_new_texture();
dmnsn_delete_pigment(object->texture->pigment);
- object->texture->pigment = dmnsn_realize_pigment(modifier);
+ object->texture->pigment = dmnsn_realize_pigment(*modifier);
break;
case DMNSN_AST_FINISH:
if (!object->texture)
object->texture = dmnsn_new_texture();
dmnsn_delete_finish(object->texture->finish);
- object->texture->finish = dmnsn_realize_finish(modifier);
+ object->texture->finish = dmnsn_realize_finish(*modifier);
break;
case DMNSN_AST_INTERIOR:
dmnsn_delete_interior(object->interior);
- object->interior = dmnsn_realize_interior(modifier);
+ object->interior = dmnsn_realize_interior(*modifier);
break;
default:
@@ -738,26 +726,13 @@ dmnsn_realize_light_source_modifiers(dmnsn_astnode astnode, dmnsn_light *light)
dmnsn_assert(astnode.type == DMNSN_AST_OBJECT_MODIFIERS,
"Expected object modifiers.");
- for (size_t i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode modifier;
- dmnsn_array_get(astnode.children, i, &modifier);
-
- switch (modifier.type) {
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, modifier, astnode.children) {
+ switch (modifier->type) {
case DMNSN_AST_ROTATION:
- light->x0 = dmnsn_transform_vector(
- dmnsn_realize_rotation(modifier),
- light->x0
- );
- break;
case DMNSN_AST_SCALE:
- light->x0 = dmnsn_transform_vector(
- dmnsn_realize_scale(modifier),
- light->x0
- );
- break;
case DMNSN_AST_TRANSLATION:
light->x0 = dmnsn_transform_vector(
- dmnsn_realize_translation(modifier),
+ dmnsn_realize_transformation(*modifier),
light->x0
);
break;
@@ -890,31 +865,32 @@ dmnsn_realize_csg(dmnsn_astnode astnode, dmnsn_array *lights,
dmnsn_array_get(astnode.children, 0, &objects);
dmnsn_array_get(astnode.children, 1, &modifiers);
- size_t i;
dmnsn_object *csg = NULL;
- for (i = 0; i < dmnsn_array_size(objects.children) && !csg; ++i) {
- dmnsn_astnode onode;
- dmnsn_array_get(objects.children, i, &onode);
-
- if (onode.type == DMNSN_AST_LIGHT_SOURCE) {
- dmnsn_light *light = dmnsn_realize_light_source(onode);
+ dmnsn_astnode *onode;
+ for (onode = dmnsn_array_first(objects.children);
+ onode <= (dmnsn_astnode *)dmnsn_array_last(objects.children);
+ ++onode)
+ {
+ 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 {
- csg = dmnsn_realize_object(onode, lights);
+ csg = dmnsn_realize_object(*onode, lights);
+ break;
}
}
- for (; i < dmnsn_array_size(objects.children); ++i) {
- dmnsn_astnode onode;
- dmnsn_array_get(objects.children, i, &onode);
-
- if (onode.type == DMNSN_AST_LIGHT_SOURCE) {
- dmnsn_light *light = dmnsn_realize_light_source(onode);
+ for (++onode;
+ onode <= (dmnsn_astnode *)dmnsn_array_last(objects.children);
+ ++onode)
+ {
+ 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);
+ dmnsn_object *object = dmnsn_realize_object(*onode, lights);
csg = (*csg_object_fn)(csg, object);
}
}
@@ -1009,25 +985,24 @@ dmnsn_realize_astree(const dmnsn_astree *astree)
* Now parse the abstract syntax tree
*/
- dmnsn_astnode astnode;
- for (size_t i = 0; i < dmnsn_array_size(astree); ++i) {
- dmnsn_array_get(astree, i, &astnode);
-
- dmnsn_light *light;
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, astnode, astree) {
+ dmnsn_astnode child;
+ dmnsn_light *light;
dmnsn_object *object;
- switch (astnode.type) {
+
+ switch (astnode->type) {
case DMNSN_AST_GLOBAL_SETTINGS:
- dmnsn_realize_global_settings(astnode, scene);
+ dmnsn_realize_global_settings(*astnode, scene);
break;
case DMNSN_AST_BACKGROUND:
- dmnsn_array_get(astnode.children, 0, &astnode);
- scene->background = dmnsn_realize_color(astnode);
+ dmnsn_array_get(astnode->children, 0, &child);
+ scene->background = dmnsn_realize_color(child);
break;
case DMNSN_AST_CAMERA:
dmnsn_delete_camera(scene->camera);
- scene->camera = dmnsn_realize_camera(astnode);
+ scene->camera = dmnsn_realize_camera(*astnode);
break;
case DMNSN_AST_BOX:
@@ -1037,13 +1012,13 @@ dmnsn_realize_astree(const dmnsn_astree *astree)
case DMNSN_AST_PLANE:
case DMNSN_AST_SPHERE:
case DMNSN_AST_UNION:
- object = dmnsn_realize_object(astnode, scene->lights);
+ object = dmnsn_realize_object(*astnode, scene->lights);
if (object)
dmnsn_array_push(scene->objects, &object);
break;
case DMNSN_AST_LIGHT_SOURCE:
- light = dmnsn_realize_light_source(astnode);
+ light = dmnsn_realize_light_source(*astnode);
dmnsn_array_push(scene->lights, &light);
break;
diff --git a/dimension/tokenize.c b/dimension/tokenize.c
index efa1064..98253ce 100644
--- a/dimension/tokenize.c
+++ b/dimension/tokenize.c
@@ -67,10 +67,8 @@ dmnsn_delete_token_buffer(void *ptr)
{
dmnsn_token_buffer *tbuffer = ptr;
if (tbuffer) {
- for (size_t i = 0; i < dmnsn_array_size(tbuffer->buffered); ++i) {
- dmnsn_buffered_token buffered;
- dmnsn_array_get(tbuffer->buffered, i, &buffered);
- free(buffered.lval.value);
+ DMNSN_ARRAY_FOREACH (dmnsn_buffered_token *, buffered, tbuffer->buffered) {
+ free(buffered->lval.value);
}
dmnsn_delete_array(tbuffer->buffered);
diff --git a/libdimension/canvas.c b/libdimension/canvas.c
index 4ed7fd5..2c60c60 100644
--- a/libdimension/canvas.c
+++ b/libdimension/canvas.c
@@ -48,11 +48,9 @@ dmnsn_delete_canvas(dmnsn_canvas *canvas)
{
if (canvas) {
/* Free the optimizers */
- for (size_t i = 0; i < dmnsn_array_size(canvas->optimizers); ++i) {
- dmnsn_canvas_optimizer optimizer;
- dmnsn_array_get(canvas->optimizers, i, &optimizer);
- if (optimizer.free_fn) {
- (*optimizer.free_fn)(optimizer.ptr);
+ DMNSN_ARRAY_FOREACH(dmnsn_canvas_optimizer *, i, canvas->optimizers) {
+ if (i->free_fn) {
+ (*i->free_fn)(i->ptr);
}
}
dmnsn_delete_array(canvas->optimizers);
@@ -75,15 +73,12 @@ void
dmnsn_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y,
dmnsn_color color)
{
- dmnsn_canvas_optimizer optimizer;
-
/* Set the pixel */
canvas->pixels[y*canvas->x + x] = color;
/* Call the optimizers */
- for (size_t i = 0; i < dmnsn_array_size(canvas->optimizers); ++i) {
- dmnsn_array_get(canvas->optimizers, i, &optimizer);
- (*optimizer.optimizer_fn)(canvas, optimizer, x, y);
+ DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
+ (*i->optimizer_fn)(canvas, *i, x, y);
}
}
diff --git a/libdimension/dimension/array.h b/libdimension/dimension/array.h
index e3dc7b4..afd5e16 100644
--- a/libdimension/dimension/array.h
+++ b/libdimension/dimension/array.h
@@ -100,7 +100,21 @@ dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj)
memcpy((char *)array->ptr + array->obj_size*i, obj, array->obj_size);
}
-/* Element access */
+/* First element */
+DMNSN_INLINE void *
+dmnsn_array_first(const dmnsn_array *array)
+{
+ return array->ptr;
+}
+
+/* Last element */
+DMNSN_INLINE void *
+dmnsn_array_last(const dmnsn_array *array)
+{
+ return (char *)array->ptr + array->obj_size*(array->length - 1);
+}
+
+/* Arbitrary element access */
DMNSN_INLINE void *
dmnsn_array_at(const dmnsn_array *array, size_t i)
{
@@ -156,4 +170,10 @@ dmnsn_array_remove(dmnsn_array *array, size_t i)
dmnsn_array_resize(array, size - 1);
}
+/* Macro to shorten array iteration */
+#define DMNSN_ARRAY_FOREACH(type, i, array) \
+ for (type i = dmnsn_array_first(array); \
+ i <= (type)dmnsn_array_last(array); \
+ ++i)
+
#endif /* DIMENSION_ARRAY_H */
diff --git a/libdimension/gl.c b/libdimension/gl.c
index 84dcc91..d07465f 100644
--- a/libdimension/gl.c
+++ b/libdimension/gl.c
@@ -32,16 +32,14 @@ static void dmnsn_gl_optimizer_fn(dmnsn_canvas *canvas,
int
dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas)
{
- dmnsn_canvas_optimizer optimizer;
-
/* Check if we've already optimized this canvas */
- for (size_t i = 0; i < dmnsn_array_size(canvas->optimizers); ++i) {
- dmnsn_array_get(canvas->optimizers, i, &optimizer);
- if (optimizer.optimizer_fn == &dmnsn_gl_optimizer_fn) {
+ DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
+ if (i->optimizer_fn == &dmnsn_gl_optimizer_fn) {
return 0;
}
}
+ dmnsn_canvas_optimizer optimizer;
optimizer.optimizer_fn = &dmnsn_gl_optimizer_fn;
optimizer.free_fn = &free;
@@ -67,10 +65,9 @@ dmnsn_gl_write_canvas(const dmnsn_canvas *canvas)
size_t height = canvas->y;
/* Check if we can optimize this */
- for (size_t i = 0; i < dmnsn_array_size(canvas->optimizers); ++i) {
- dmnsn_array_get(canvas->optimizers, i, &optimizer);
- if (optimizer.optimizer_fn == &dmnsn_gl_optimizer_fn) {
- glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_SHORT, optimizer.ptr);
+ DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
+ if (i->optimizer_fn == &dmnsn_gl_optimizer_fn) {
+ glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_SHORT, i->ptr);
return glGetError() == GL_NO_ERROR ? 0 : 1;
}
}
diff --git a/libdimension/png.c b/libdimension/png.c
index 021b9f2..177293c 100644
--- a/libdimension/png.c
+++ b/libdimension/png.c
@@ -39,9 +39,8 @@ dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
dmnsn_canvas_optimizer optimizer;
/* Check if we've already optimized this canvas */
- for (size_t i = 0; i < dmnsn_array_size(canvas->optimizers); ++i) {
- dmnsn_array_get(canvas->optimizers, i, &optimizer);
- if (optimizer.optimizer_fn == &dmnsn_png_optimizer_fn) {
+ DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
+ if (i->optimizer_fn == &dmnsn_png_optimizer_fn) {
return 0;
}
}
@@ -287,12 +286,11 @@ dmnsn_png_write_canvas_impl(dmnsn_progress *progress,
}
/* Check if we can optimize this */
- for (size_t i = 0; i < dmnsn_array_size(canvas->optimizers); ++i) {
- dmnsn_array_get(canvas->optimizers, i, &optimizer);
- if (optimizer.optimizer_fn == &dmnsn_png_optimizer_fn) {
+ DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
+ if (i->optimizer_fn == &dmnsn_png_optimizer_fn) {
for (size_t y = 0; y < height; ++y) {
/* Invert the rows. PNG coordinates are fourth quadrant. */
- uint16_t *row = (uint16_t *)optimizer.ptr + 4*(height - y - 1)*width;
+ uint16_t *row = (uint16_t *)i->ptr + 4*(height - y - 1)*width;
png_write_row(png_ptr, (png_bytep)row);
dmnsn_increment_progress(progress);
}
diff --git a/libdimension/prtree.c b/libdimension/prtree.c
index 04d8cc4..dc3ed38 100644
--- a/libdimension/prtree.c
+++ b/libdimension/prtree.c
@@ -430,10 +430,8 @@ dmnsn_pseudo_prtree_leaves(const dmnsn_pseudo_prtree *pseudo)
static void
dmnsn_precompute_objects(const dmnsn_array *objects)
{
- for (size_t i = 0; i < dmnsn_array_size(objects); ++i) {
- dmnsn_object *object;
- dmnsn_array_get(objects, i, &object);
- dmnsn_object_precompute(object);
+ DMNSN_ARRAY_FOREACH (dmnsn_object **, object, objects) {
+ dmnsn_object_precompute(*object);
}
}
@@ -555,12 +553,9 @@ dmnsn_prtree_search(const dmnsn_prtree *tree, dmnsn_line ray,
double t = -1.0;
/* Search the unbounded objects */
- for (size_t i = 0; i < dmnsn_array_size(tree->unbounded); ++i) {
- dmnsn_object *object;
- dmnsn_array_get(tree->unbounded, i, &object);
-
+ DMNSN_ARRAY_FOREACH (dmnsn_object **, object, tree->unbounded) {
dmnsn_intersection local_intersection;
- if ((*object->intersection_fn)(object, ray, &local_intersection)) {
+ if ((*(*object)->intersection_fn)(*object, ray, &local_intersection)) {
if (t < 0.0 || local_intersection.t < t) {
*intersection = local_intersection;
t = local_intersection.t;
diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c
index f5d0885..0c3b738 100644
--- a/libdimension/raytrace.c
+++ b/libdimension/raytrace.c
@@ -315,17 +315,13 @@ dmnsn_raytrace_lighting(dmnsn_raytrace_state *state)
return;
}
- const dmnsn_light *light;
-
/* Iterate over each light */
- for (size_t i = 0; i < dmnsn_array_size(state->scene->lights); ++i) {
- dmnsn_array_get(state->scene->lights, i, &light);
-
- dmnsn_color light_color = dmnsn_raytrace_light_ray(state, light);
+ DMNSN_ARRAY_FOREACH (dmnsn_light **, light, state->scene->lights) {
+ dmnsn_color light_color = dmnsn_raytrace_light_ray(state, *light);
if (!dmnsn_color_is_black(light_color)) {
if (state->scene->quality & DMNSN_RENDER_FINISH) {
dmnsn_vector ray = dmnsn_vector_normalize(
- dmnsn_vector_sub(light->x0, state->r)
+ dmnsn_vector_sub((*light)->x0, state->r)
);
/* Get this light's color contribution to the object */
diff --git a/libdimension/scene.c b/libdimension/scene.c
index 177e7fe..58d2eda 100644
--- a/libdimension/scene.c
+++ b/libdimension/scene.c
@@ -50,17 +50,11 @@ void
dmnsn_delete_scene(dmnsn_scene *scene)
{
if (scene) {
- dmnsn_light *light;
- dmnsn_object *object;
-
- for (size_t i = 0; i < dmnsn_array_size(scene->lights); ++i) {
- dmnsn_array_get(scene->lights, i, &light);
- dmnsn_delete_light(light);
+ DMNSN_ARRAY_FOREACH (dmnsn_light **, light, scene->lights) {
+ dmnsn_delete_light(*light);
}
-
- for (size_t i = 0; i < dmnsn_array_size(scene->objects); ++i) {
- dmnsn_array_get(scene->objects, i, &object);
- dmnsn_delete_object(object);
+ DMNSN_ARRAY_FOREACH (dmnsn_object **, object, scene->objects) {
+ dmnsn_delete_object(*object);
}
dmnsn_delete_array(scene->lights);