summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-11-04 14:44:09 -0500
committerTavian Barnes <tavianator@gmail.com>2009-11-04 14:44:09 -0500
commit5bde27bf4b3064a94131b71019469464023a6f63 (patch)
treea4d4e0c287628207fea892ce5c736f728582d00d
parent92efb5d0d7ba0c2b49cf189d5055bc0d9b09994c (diff)
downloaddimension-5bde27bf4b3064a94131b71019469464023a6f63.tar.xz
Handle spheres.
-rw-r--r--dimension/parse.c51
-rw-r--r--dimension/parse.h2
-rw-r--r--dimension/realize.c85
-rw-r--r--tests/dimension/Makefile.am4
-rw-r--r--tests/dimension/demo.pov (renamed from tests/dimension/box.pov)9
-rwxr-xr-xtests/dimension/demo.sh (renamed from tests/dimension/box.sh)14
6 files changed, 139 insertions, 26 deletions
diff --git a/dimension/parse.c b/dimension/parse.c
index 42a48bd..51203c5 100644
--- a/dimension/parse.c
+++ b/dimension/parse.c
@@ -190,6 +190,45 @@ dmnsn_parse_box(const dmnsn_array *tokens, unsigned int *ip,
return 1;
}
+static int
+dmnsn_parse_sphere(const dmnsn_array *tokens, unsigned int *ip,
+ dmnsn_array *astree)
+{
+ unsigned int i = *ip;
+
+ if (dmnsn_parse_expect(DMNSN_T_SPHERE, tokens, &i) != 0)
+ return 1;
+ if (dmnsn_parse_expect(DMNSN_T_LBRACE, tokens, &i) != 0)
+ return 1;
+
+ dmnsn_astnode astnode;
+ astnode.type = DMNSN_AST_SPHERE;
+ astnode.children = dmnsn_new_array(sizeof(dmnsn_astnode));
+ astnode.ptr = NULL;
+
+ /* Center */
+ if (dmnsn_parse_vector(tokens, &i, astnode.children) != 0)
+ goto bailout;
+
+ if (dmnsn_parse_expect(DMNSN_T_COMMA, tokens, &i) != 0)
+ goto bailout;
+
+ /* Radius */
+ if (dmnsn_parse_float(tokens, &i, astnode.children) != 0)
+ goto bailout;
+
+ if (dmnsn_parse_expect(DMNSN_T_RBRACE, tokens, &i) != 0)
+ goto bailout;
+
+ dmnsn_array_push(astree, &astnode);
+ *ip = i;
+ return 0;
+
+ bailout:
+ dmnsn_delete_astree(astnode.children);
+ return 1;
+}
+
dmnsn_array *
dmnsn_parse(const dmnsn_array *tokens)
{
@@ -212,10 +251,15 @@ dmnsn_parse(const dmnsn_array *tokens)
switch (token.type) {
case DMNSN_T_BOX:
if (dmnsn_parse_box(tokens, &i, astree) != 0) {
+ dmnsn_diagnostic(token.filename, token.line, token.col, "Invalid box");
+ goto bailout;
+ }
+ break;
+
+ case DMNSN_T_SPHERE:
+ if (dmnsn_parse_sphere(tokens, &i, astree) != 0) {
dmnsn_diagnostic(token.filename, token.line, token.col,
- "Invalid box",
- dmnsn_token_string(DMNSN_T_BOX),
- dmnsn_token_string(token.type));
+ "Invalid sphere");
goto bailout;
}
break;
@@ -336,6 +380,7 @@ dmnsn_astnode_string(dmnsn_astnode_type astnode_type)
dmnsn_astnode_map(DMNSN_AST_BOX, "box");
dmnsn_astnode_map(DMNSN_AST_VECTOR, "vector");
dmnsn_astnode_map(DMNSN_AST_FLOAT, "float");
+ dmnsn_astnode_map(DMNSN_AST_SPHERE, "sphere");
default:
fprintf(stderr, "Warning: unrecognised astnode type %d.\n",
diff --git a/dimension/parse.h b/dimension/parse.h
index 0b818bf..02bda6e 100644
--- a/dimension/parse.h
+++ b/dimension/parse.h
@@ -21,8 +21,10 @@
typedef enum {
DMNSN_AST_FLOAT,
+ DMNSN_AST_INTEGER,
DMNSN_AST_VECTOR,
DMNSN_AST_BOX,
+ DMNSN_AST_SPHERE,
} dmnsn_astnode_type;
typedef struct dmnsn_astnode dmnsn_astnode;
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;
}
}
diff --git a/tests/dimension/Makefile.am b/tests/dimension/Makefile.am
index 36d0989..214c88a 100644
--- a/tests/dimension/Makefile.am
+++ b/tests/dimension/Makefile.am
@@ -19,7 +19,7 @@
INCLUDES = -I$(top_srcdir)/libdimension
-TESTS = punctuation.sh numeric.sh strings.sh labels.sh directives.sh box.sh
+TESTS = punctuation.sh numeric.sh strings.sh labels.sh directives.sh demo.sh
TESTS_ENVIRONMENT = top_builddir=$(top_builddir)
%.sh:
@@ -31,7 +31,7 @@ EXTRA_DIST = $(TESTS) \
strings.pov \
labels.pov \
directives.pov \
- box.pov
+ demo.pov
clean-local:
rm *.png
diff --git a/tests/dimension/box.pov b/tests/dimension/demo.pov
index 762e5df..386fdd0 100644
--- a/tests/dimension/box.pov
+++ b/tests/dimension/demo.pov
@@ -17,11 +17,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
-// Render a box
+// Render demo scene
box {
- <-0.125, -1, -1>, <0.125, 1, 1>
+ <-1.0, -1.0, -1.0>, <1.0, 1.0, 1.0>
}
-box {
- <-1, -1, -0.125>, <1, 1, 0.125>
+
+sphere {
+ <0, 0, 0>, 1.25
}
diff --git a/tests/dimension/box.sh b/tests/dimension/demo.sh
index 7a9f754..7674fd4 100755
--- a/tests/dimension/box.sh
+++ b/tests/dimension/demo.sh
@@ -19,14 +19,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
#########################################################################
-box=$(${top_builddir}/dimension/dimension --tokenize --parse ${srcdir}/box.pov)
-box_exp='(box { < - (float "0.125") , - (integer "1") , - (integer "1") > , < (float "0.125") , (integer "1") , (integer "1") > } box { < - (integer "1") , - (integer "1") , - (float "0.125") > , < (integer "1") , (integer "1") , (float "0.125") > })
-((box (vector (float -0.125) (float -1) (float -1)) (vector (float 0.125) (float 1) (float 1))) (box (vector (float -1) (float -1) (float -0.125)) (vector (float 1) (float 1) (float 0.125))))'
+demo=$(${top_builddir}/dimension/dimension --tokenize --parse ${srcdir}/demo.pov)
+demo_exp='(box { < - (float "1.0") , - (float "1.0") , - (float "1.0") > , < (float "1.0") , (float "1.0") , (float "1.0") > } sphere { < (integer "0") , (integer "0") , (integer "0") > , (float "1.25") })
+((box (vector (float -1) (float -1) (float -1)) (vector (float 1) (float 1) (float 1))) (sphere (vector (float 0) (float 0) (float 0)) (float 1.25)))'
-if [ "$box" != "$box_exp" ]; then
- echo "box.pov parsed as \"$box\"" >&2
- echo " -- expected \"$box_exp\"" >&2
+if [ "$demo" != "$demo_exp" ]; then
+ echo "demo.pov parsed as \"$demo\"" >&2
+ echo " -- expected \"$demo_exp\"" >&2
exit 1
fi
-${top_builddir}/dimension/dimension -o box.png ${srcdir}/box.pov
+${top_builddir}/dimension/dimension -o demo.png ${srcdir}/demo.pov