summaryrefslogtreecommitdiffstats
path: root/dimension/realize.c
diff options
context:
space:
mode:
Diffstat (limited to 'dimension/realize.c')
-rw-r--r--dimension/realize.c85
1 files changed, 75 insertions, 10 deletions
diff --git a/dimension/realize.c b/dimension/realize.c
index 38a74e6..8bbf0cc 100644
--- a/dimension/realize.c
+++ b/dimension/realize.c
@@ -22,6 +22,21 @@
#include "utility.h"
#include <math.h>
+static double
+dmnsn_realize_float(dmnsn_astnode astnode)
+{
+ if (astnode.type == DMNSN_AST_FLOAT) {
+ double *x = astnode.ptr;
+ return *x;
+ } else if (astnode.type == DMNSN_AST_INTEGER) {
+ long *x = astnode.ptr;
+ return *x;
+ } else {
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Expected a float or an integer.");
+ return 0; /* Silence compiler warning */
+ }
+}
+
static dmnsn_vector
dmnsn_realize_vector(dmnsn_astnode astnode)
{
@@ -34,15 +49,11 @@ dmnsn_realize_vector(dmnsn_astnode astnode)
dmnsn_array_get(astnode.children, 1, &ynode);
dmnsn_array_get(astnode.children, 2, &znode);
- if (xnode.type != DMNSN_AST_FLOAT
- || ynode.type != DMNSN_AST_FLOAT
- || znode.type != DMNSN_AST_FLOAT)
- {
- dmnsn_error(DMNSN_SEVERITY_HIGH, "Expected a float.");
- }
+ double x = dmnsn_realize_float(xnode),
+ y = dmnsn_realize_float(ynode),
+ z = dmnsn_realize_float(znode);
- double *x = xnode.ptr, *y = ynode.ptr, *z = znode.ptr;
- return dmnsn_vector_construct(*x, *y, *z);
+ return dmnsn_vector_construct(x, y, z);
}
dmnsn_object *
@@ -60,6 +71,10 @@ dmnsn_realize_box(dmnsn_astnode astnode)
x2 = dmnsn_realize_vector(corner2);
dmnsn_object *box = dmnsn_new_cube();
+ if (!box) {
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate box.");
+ }
+
box->trans = dmnsn_scale_matrix(
dmnsn_vector_construct(fabs(x2.x - x1.x)/2.0,
fabs(x2.y - x1.y)/2.0,
@@ -76,6 +91,44 @@ dmnsn_realize_box(dmnsn_astnode astnode)
return box;
}
+dmnsn_object *
+dmnsn_realize_sphere(dmnsn_astnode astnode)
+{
+ if (astnode.type != DMNSN_AST_SPHERE) {
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Expected a sphere.");
+ }
+
+ dmnsn_astnode center, radius;
+ dmnsn_array_get(astnode.children, 0, &center);
+ dmnsn_array_get(astnode.children, 1, &radius);
+
+ dmnsn_vector x0 = dmnsn_realize_vector(center);
+ double r = dmnsn_realize_float(radius);
+
+ dmnsn_object *sphere = dmnsn_new_sphere();
+ if (!sphere) {
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate sphere.");
+ }
+
+ sphere->texture = dmnsn_new_texture();
+ if (!sphere->texture) {
+ dmnsn_delete_object(sphere);
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate sphere texture.");
+ }
+
+ sphere->texture->pigment = dmnsn_new_solid_pigment(dmnsn_white);
+ if (!sphere->texture->pigment) {
+ dmnsn_delete_object(sphere);
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate sphere pigment.");
+ }
+
+ sphere->trans = dmnsn_scale_matrix(dmnsn_vector_construct(r, r, r));
+ sphere->trans = dmnsn_matrix_mul(dmnsn_translation_matrix(x0), sphere->trans);
+ sphere->trans = dmnsn_matrix_inverse(sphere->trans);
+
+ return sphere;
+}
+
dmnsn_scene *
dmnsn_realize(const dmnsn_array *astree)
{
@@ -107,7 +160,11 @@ dmnsn_realize(const dmnsn_array *astree)
trans
);
trans = dmnsn_matrix_mul(
- dmnsn_rotation_matrix(dmnsn_vector_construct(0.8, 0.7, 0.0)),
+ dmnsn_rotation_matrix(dmnsn_vector_construct(0.0, 1.0, 0.0)),
+ trans
+ );
+ trans = dmnsn_matrix_mul(
+ dmnsn_rotation_matrix(dmnsn_vector_construct(-0.75, 0.0, 0.0)),
trans
);
@@ -136,8 +193,16 @@ dmnsn_realize(const dmnsn_array *astree)
dmnsn_array_push(scene->objects, &object);
break;
+ case DMNSN_AST_SPHERE:
+ object = dmnsn_realize_sphere(astnode);
+ dmnsn_array_push(scene->objects, &object);
+ break;
+
default:
- dmnsn_error(DMNSN_SEVERITY_HIGH, "We only handle boxes right now.");
+ fprintf(stderr, "Unrecognised syntax element '%s'.\n",
+ dmnsn_astnode_string(astnode.type));
+ dmnsn_delete_realized_scene(scene);
+ return NULL;
}
}