summaryrefslogtreecommitdiffstats
path: root/dimension
diff options
context:
space:
mode:
Diffstat (limited to 'dimension')
-rw-r--r--dimension/common.nonterminals2
-rw-r--r--dimension/common.rules108
-rw-r--r--dimension/common.terminals6
-rw-r--r--dimension/directives.rules7
-rw-r--r--dimension/grammar.epilogue9
-rw-r--r--dimension/lexer.l3
-rw-r--r--dimension/parse.h3
-rw-r--r--dimension/realize.c124
8 files changed, 211 insertions, 51 deletions
diff --git a/dimension/common.nonterminals b/dimension/common.nonterminals
index 1d39424..5f915c5 100644
--- a/dimension/common.nonterminals
+++ b/dimension/common.nonterminals
@@ -25,6 +25,8 @@
/* Transformations */
%type <astnode> TRANSFORMATION
+%type <astnode> TRANSFORMATION_ITEMS
+%type <astnode> TRANSFORMATION_ITEM
/* The camera */
%type <astnode> CAMERA
diff --git a/dimension/common.rules b/dimension/common.rules
index d897eb3..77830a6 100644
--- a/dimension/common.rules
+++ b/dimension/common.rules
@@ -43,14 +43,116 @@ STRING: "string" {
/* Transformations */
TRANSFORMATION: "rotate" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_ROTATION, @$, $2);
+ dmnsn_astnode rotation
+ = dmnsn_new_astnode1(DMNSN_AST_ROTATION, @$, $2);
+ $$ = dmnsn_new_astnode1(DMNSN_AST_TRANSFORMATION, @$, rotation);
}
| "scale" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_SCALE, @$, $2);
+ dmnsn_astnode scale
+ = dmnsn_new_astnode1(DMNSN_AST_SCALE, @$, $2);
+ $$ = dmnsn_new_astnode1(DMNSN_AST_TRANSFORMATION, @$, scale);
}
| "translate" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_TRANSLATION, @$, $2);
+ dmnsn_astnode translation
+ = dmnsn_new_astnode1(DMNSN_AST_TRANSLATION, @$, $2);
+ $$ = dmnsn_new_astnode1(DMNSN_AST_TRANSFORMATION, @$,
+ translation);
}
+ | "matrix" "<" FLOAT "," FLOAT "," FLOAT ","
+ FLOAT "," FLOAT "," FLOAT ","
+ FLOAT "," FLOAT "," FLOAT ","
+ FLOAT "," FLOAT "," FLOAT ">"
+ {
+ dmnsn_astnode matrix = dmnsn_new_astnode(DMNSN_AST_MATRIX, @$);
+
+ dmnsn_array_push(matrix.children, &$3);
+ dmnsn_array_push(matrix.children, &$5);
+ dmnsn_array_push(matrix.children, &$7);
+
+ dmnsn_array_push(matrix.children, &$9);
+ dmnsn_array_push(matrix.children, &$11);
+ dmnsn_array_push(matrix.children, &$13);
+
+ dmnsn_array_push(matrix.children, &$15);
+ dmnsn_array_push(matrix.children, &$17);
+ dmnsn_array_push(matrix.children, &$19);
+
+ dmnsn_array_push(matrix.children, &$21);
+ dmnsn_array_push(matrix.children, &$23);
+ dmnsn_array_push(matrix.children, &$25);
+
+ $$ = dmnsn_new_astnode1(DMNSN_AST_TRANSFORMATION, @$, matrix);
+ }
+ | "transform" IDENTIFIER {
+ dmnsn_astnode *trans = dmnsn_find_symbol(symtable, $2.ptr);
+ if (!trans) {
+ dmnsn_diagnostic(@2, "unbound identifier '%s'",
+ (const char *)$2.ptr);
+ dmnsn_delete_astnode($2);
+ YYERROR;
+ }
+ if (trans->type != DMNSN_AST_TRANSFORMATION) {
+ dmnsn_diagnostic(
+ @2, "identifier '%s' is a %s; expected a %s",
+ (const char *)$2.ptr,
+ dmnsn_astnode_string(trans->type),
+ dmnsn_astnode_string(DMNSN_AST_TRANSFORMATION)
+ );
+ dmnsn_delete_astnode($2);
+ YYERROR;
+ }
+
+ $$ = dmnsn_new_astnode(DMNSN_AST_TRANSFORMATION, @$);
+ dmnsn_copy_children($$, *trans);
+ dmnsn_delete_astnode($2);
+ }
+ | "transform" "{"
+ TRANSFORMATION_ITEMS
+ "}"
+ {
+ $$ = $3;
+ }
+;
+
+TRANSFORMATION_ITEMS: TRANSFORMATION_ITEM {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_TRANSFORMATION, @$, $1);
+ }
+ | TRANSFORMATION_ITEMS TRANSFORMATION_ITEM {
+ $$ = $1;
+ dmnsn_array_push($$.children, &$2);
+ }
+;
+
+TRANSFORMATION_ITEM: IDENTIFIER {
+ dmnsn_astnode *trans = dmnsn_find_symbol(symtable, $1.ptr);
+ if (!trans) {
+ dmnsn_diagnostic(@1, "unbound identifier '%s'",
+ (const char *)$1.ptr);
+ dmnsn_delete_astnode($1);
+ YYERROR;
+ }
+ if (trans->type != DMNSN_AST_TRANSFORMATION) {
+ dmnsn_diagnostic(
+ @1, "identifier '%s' is a %s; expected a %s",
+ (const char *)$1.ptr,
+ dmnsn_astnode_string(trans->type),
+ dmnsn_astnode_string(DMNSN_AST_TRANSFORMATION)
+ );
+ dmnsn_delete_astnode($1);
+ YYERROR;
+ }
+
+ dmnsn_array_get(trans->children, 0, &$$);
+ ++*$$.refcount;
+ }
+ | TRANSFORMATION {
+ dmnsn_array_get($1.children, 0, &$$);
+ ++*$$.refcount;
+ dmnsn_delete_astnode($1);
+ }
+ | "inverse" {
+ $$ = dmnsn_new_astnode(DMNSN_AST_INVERSE, @$);
+ }
;
/* Cameras */
diff --git a/dimension/common.terminals b/dimension/common.terminals
index fd62320..7ccc8cb 100644
--- a/dimension/common.terminals
+++ b/dimension/common.terminals
@@ -240,7 +240,7 @@
%token DMNSN_T_INTERPOLATE
%token DMNSN_T_INTERSECTION "intersection"
%token DMNSN_T_INTERVALS
-%token DMNSN_T_INVERSE
+%token DMNSN_T_INVERSE "inverse"
%token DMNSN_T_IOR "ior"
%token DMNSN_T_IRID
%token DMNSN_T_IRID_WAVELENGTH
@@ -270,7 +270,7 @@
%token DMNSN_T_MARBLE
%token DMNSN_T_MATERIAL
%token DMNSN_T_MATERIAL_MAP
-%token DMNSN_T_MATRIX
+%token DMNSN_T_MATRIX "matrix"
%token DMNSN_T_MAX "max"
%token DMNSN_T_MAX_EXTENT
%token DMNSN_T_MAX_GRADIENT
@@ -445,7 +445,7 @@
%token DMNSN_T_TOROIDAL
%token DMNSN_T_TORUS
%token DMNSN_T_TRACE
-%token DMNSN_T_TRANSFORM
+%token DMNSN_T_TRANSFORM "transform"
%token DMNSN_T_TRANSLATE "translate"
%token DMNSN_T_TRANSMIT "transmit"
%token DMNSN_T_TRIANGLE
diff --git a/dimension/directives.rules b/dimension/directives.rules
index 84358f6..a3c53d2 100644
--- a/dimension/directives.rules
+++ b/dimension/directives.rules
@@ -115,7 +115,12 @@ RVALUE: ARITH_EXPR ";" %dprec 2 {
| FINISH
| INTERIOR
| CAMERA
- | TRANSFORMATION
+ | "transform" "{"
+ TRANSFORMATION_ITEMS
+ "}"
+ {
+ $$ = $3;
+ }
;
DECL_PARAMS: /* empty */ {
diff --git a/dimension/grammar.epilogue b/dimension/grammar.epilogue
index 7b004e3..073f412 100644
--- a/dimension/grammar.epilogue
+++ b/dimension/grammar.epilogue
@@ -163,9 +163,12 @@ dmnsn_astnode_string(dmnsn_astnode_type astnode_type)
dmnsn_astnode_map(DMNSN_AST_INTERIOR, "interior");
dmnsn_astnode_map(DMNSN_AST_IOR, "ior");
- dmnsn_astnode_map(DMNSN_AST_ROTATION, "rotate");
- dmnsn_astnode_map(DMNSN_AST_SCALE, "scale");
- dmnsn_astnode_map(DMNSN_AST_TRANSLATION, "translate");
+ dmnsn_astnode_map(DMNSN_AST_TRANSFORMATION, "transformation");
+ dmnsn_astnode_map(DMNSN_AST_ROTATION, "rotation");
+ dmnsn_astnode_map(DMNSN_AST_SCALE, "scale");
+ dmnsn_astnode_map(DMNSN_AST_TRANSLATION, "translation");
+ dmnsn_astnode_map(DMNSN_AST_MATRIX, "matrix");
+ dmnsn_astnode_map(DMNSN_AST_INVERSE, "inverse");
dmnsn_astnode_map(DMNSN_AST_FLOAT, "float");
dmnsn_astnode_map(DMNSN_AST_INTEGER, "integer");
diff --git a/dimension/lexer.l b/dimension/lexer.l
index 85c3fda..ea98c07 100644
--- a/dimension/lexer.l
+++ b/dimension/lexer.l
@@ -207,12 +207,14 @@ unsigned long wchar;
"int" RETURN_TOKEN(DMNSN_T_INT);
"interior" RETURN_TOKEN(DMNSN_T_INTERIOR);
"intersection" RETURN_TOKEN(DMNSN_T_INTERSECTION);
+"inverse" RETURN_TOKEN(DMNSN_T_INVERSE);
"ior" RETURN_TOKEN(DMNSN_T_IOR);
"ln" RETURN_TOKEN(DMNSN_T_LN);
"location" RETURN_TOKEN(DMNSN_T_LOCATION);
"log" RETURN_TOKEN(DMNSN_T_LOG);
"look_at" RETURN_TOKEN(DMNSN_T_LOOK_AT);
"light_source" RETURN_TOKEN(DMNSN_T_LIGHT_SOURCE);
+"matrix" RETURN_TOKEN(DMNSN_T_MATRIX);
"max" RETURN_TOKEN(DMNSN_T_MAX);
"max_trace_level" RETURN_TOKEN(DMNSN_T_MAX_TRACE_LEVEL);
"merge" RETURN_TOKEN(DMNSN_T_MERGE);
@@ -251,6 +253,7 @@ unsigned long wchar;
"tan" RETURN_TOKEN(DMNSN_T_TAN);
"tanh" RETURN_TOKEN(DMNSN_T_TANH);
"texture" RETURN_TOKEN(DMNSN_T_TEXTURE);
+"transform" RETURN_TOKEN(DMNSN_T_TRANSFORM);
"translate" RETURN_TOKEN(DMNSN_T_TRANSLATE);
"transmit" RETURN_TOKEN(DMNSN_T_TRANSMIT);
"true" RETURN_TOKEN(DMNSN_T_TRUE);
diff --git a/dimension/parse.h b/dimension/parse.h
index b4bd8fe..fd78665 100644
--- a/dimension/parse.h
+++ b/dimension/parse.h
@@ -77,9 +77,12 @@ typedef enum {
DMNSN_AST_INTERIOR,
DMNSN_AST_IOR,
+ DMNSN_AST_TRANSFORMATION,
DMNSN_AST_ROTATION,
DMNSN_AST_SCALE,
DMNSN_AST_TRANSLATION,
+ DMNSN_AST_MATRIX,
+ DMNSN_AST_INVERSE,
DMNSN_AST_FLOAT,
DMNSN_AST_INTEGER,
diff --git a/dimension/realize.c b/dimension/realize.c
index e558c5b..a9b9c71 100644
--- a/dimension/realize.c
+++ b/dimension/realize.c
@@ -113,6 +113,31 @@ dmnsn_realize_color(dmnsn_astnode astnode)
}
static dmnsn_matrix
+dmnsn_realize_translation(dmnsn_astnode astnode)
+{
+ dmnsn_assert(astnode.type == DMNSN_AST_TRANSLATION,
+ "Expected a translation.");
+
+ dmnsn_astnode trans_node;
+ dmnsn_array_get(astnode.children, 0, &trans_node);
+ dmnsn_vector trans = dmnsn_realize_vector(trans_node);
+
+ return dmnsn_translation_matrix(trans);
+}
+
+static dmnsn_matrix
+dmnsn_realize_scale(dmnsn_astnode astnode)
+{
+ dmnsn_assert(astnode.type == DMNSN_AST_SCALE, "Expected a scale.");
+
+ dmnsn_astnode scale_node;
+ dmnsn_array_get(astnode.children, 0, &scale_node);
+ dmnsn_vector scale = dmnsn_realize_vector(scale_node);
+
+ return dmnsn_scale_matrix(scale);
+}
+
+static dmnsn_matrix
dmnsn_realize_rotation(dmnsn_astnode astnode)
{
dmnsn_assert(astnode.type == DMNSN_AST_ROTATION, "Expected a rotation.");
@@ -143,45 +168,72 @@ dmnsn_realize_rotation(dmnsn_astnode astnode)
}
static dmnsn_matrix
-dmnsn_realize_scale(dmnsn_astnode astnode)
+dmnsn_realize_matrix(dmnsn_astnode astnode)
{
- dmnsn_assert(astnode.type == DMNSN_AST_SCALE, "Expected a scale.");
+ dmnsn_assert(astnode.type == DMNSN_AST_MATRIX, "Expected a matrix.");
- dmnsn_astnode scale_node;
- dmnsn_array_get(astnode.children, 0, &scale_node);
- dmnsn_vector scale = dmnsn_realize_vector(scale_node);
+ dmnsn_astnode *children = dmnsn_array_first(astnode.children);
+ dmnsn_matrix trans;
- return dmnsn_scale_matrix(scale);
-}
+ trans.n[0][0] = dmnsn_realize_float(children[0]);
+ trans.n[0][1] = dmnsn_realize_float(children[1]);
+ trans.n[0][2] = dmnsn_realize_float(children[2]);
+ trans.n[0][3] = dmnsn_realize_float(children[9]);
-static dmnsn_matrix
-dmnsn_realize_translation(dmnsn_astnode astnode)
-{
- dmnsn_assert(astnode.type == DMNSN_AST_TRANSLATION,
- "Expected a translation.");
+ trans.n[1][0] = dmnsn_realize_float(children[3]);
+ trans.n[1][1] = dmnsn_realize_float(children[4]);
+ trans.n[1][2] = dmnsn_realize_float(children[5]);
+ trans.n[1][3] = dmnsn_realize_float(children[10]);
- dmnsn_astnode trans_node;
- dmnsn_array_get(astnode.children, 0, &trans_node);
- dmnsn_vector trans = dmnsn_realize_vector(trans_node);
+ trans.n[2][0] = dmnsn_realize_float(children[6]);
+ trans.n[2][1] = dmnsn_realize_float(children[7]);
+ trans.n[2][2] = dmnsn_realize_float(children[8]);
+ trans.n[2][3] = dmnsn_realize_float(children[11]);
- return dmnsn_translation_matrix(trans);
+ trans.n[3][0] = 0.0;
+ trans.n[3][1] = 0.0;
+ trans.n[3][2] = 0.0;
+ trans.n[3][3] = 1.0;
+
+ return trans;
}
static dmnsn_matrix
dmnsn_realize_transformation(dmnsn_astnode astnode)
{
- switch (astnode.type) {
- case DMNSN_AST_ROTATION:
- return dmnsn_realize_rotation(astnode);
- case DMNSN_AST_SCALE:
- return dmnsn_realize_scale(astnode);
- case DMNSN_AST_TRANSLATION:
- return dmnsn_realize_translation(astnode);
+ dmnsn_assert(astnode.type == DMNSN_AST_TRANSFORMATION,
+ "Expected a transformation.");
- default:
- dmnsn_assert(false, "Expected a transformation.");
- return dmnsn_identity_matrix(); /* Shut up compiler */
+ dmnsn_matrix trans = dmnsn_identity_matrix();
+
+ DMNSN_ARRAY_FOREACH (dmnsn_astnode *, child, astnode.children) {
+ switch (child->type) {
+ case DMNSN_AST_TRANSLATION:
+ trans = dmnsn_matrix_mul(trans, dmnsn_realize_translation(*child));
+ break;
+ case DMNSN_AST_SCALE:
+ trans = dmnsn_matrix_mul(trans, dmnsn_realize_scale(*child));
+ break;
+ case DMNSN_AST_ROTATION:
+ trans = dmnsn_matrix_mul(trans, dmnsn_realize_rotation(*child));
+ break;
+ case DMNSN_AST_MATRIX:
+ trans = dmnsn_matrix_mul(trans, dmnsn_realize_matrix(*child));
+ break;
+ case DMNSN_AST_INVERSE:
+ trans = dmnsn_matrix_inverse(trans);
+ break;
+ case DMNSN_AST_TRANSFORMATION:
+ trans = dmnsn_matrix_mul(trans, dmnsn_realize_transformation(*child));
+ break;
+
+ default:
+ dmnsn_assert(false, "Invalid transformation type.");
+ break;
+ }
}
+
+ return trans;
}
static void
@@ -320,9 +372,7 @@ dmnsn_realize_camera(dmnsn_astnode astnode)
}
/* Transformations */
- case DMNSN_AST_ROTATION:
- case DMNSN_AST_SCALE:
- case DMNSN_AST_TRANSLATION:
+ case DMNSN_AST_TRANSFORMATION:
trans = dmnsn_matrix_mul(dmnsn_realize_transformation(*item), trans);
break;
@@ -408,9 +458,7 @@ dmnsn_realize_pigment_modifiers(dmnsn_astnode astnode, dmnsn_pigment *pigment)
DMNSN_ARRAY_FOREACH(dmnsn_astnode *, modifier, astnode.children) {
switch (modifier->type) {
- case DMNSN_AST_ROTATION:
- case DMNSN_AST_SCALE:
- case DMNSN_AST_TRANSLATION:
+ case DMNSN_AST_TRANSFORMATION:
pigment->trans = dmnsn_matrix_mul(
dmnsn_realize_transformation(*modifier),
pigment->trans
@@ -621,9 +669,7 @@ dmnsn_realize_texture(dmnsn_astnode astnode)
texture->finish = dmnsn_realize_finish(*item);
break;
- case DMNSN_AST_ROTATION:
- case DMNSN_AST_SCALE:
- case DMNSN_AST_TRANSLATION:
+ case DMNSN_AST_TRANSFORMATION:
texture->trans = dmnsn_matrix_mul(
dmnsn_realize_transformation(*item),
texture->trans
@@ -673,9 +719,7 @@ dmnsn_realize_object_modifiers(dmnsn_astnode astnode, dmnsn_object *object)
DMNSN_ARRAY_FOREACH (dmnsn_astnode *, modifier, astnode.children) {
switch (modifier->type) {
- case DMNSN_AST_ROTATION:
- case DMNSN_AST_SCALE:
- case DMNSN_AST_TRANSLATION:
+ case DMNSN_AST_TRANSFORMATION:
object->trans = dmnsn_matrix_mul(
dmnsn_realize_transformation(*modifier),
object->trans
@@ -728,9 +772,7 @@ dmnsn_realize_light_source_modifiers(dmnsn_astnode astnode, dmnsn_light *light)
DMNSN_ARRAY_FOREACH (dmnsn_astnode *, modifier, astnode.children) {
switch (modifier->type) {
- case DMNSN_AST_ROTATION:
- case DMNSN_AST_SCALE:
- case DMNSN_AST_TRANSLATION:
+ case DMNSN_AST_TRANSFORMATION:
light->x0 = dmnsn_transform_vector(
dmnsn_realize_transformation(*modifier),
light->x0