summaryrefslogtreecommitdiffstats
path: root/dimension
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-01-14 01:00:09 -0500
committerTavian Barnes <tavianator@gmail.com>2010-01-14 01:00:09 -0500
commitcbdaf9ff41649174b72b0453b8a399f6abb11e8f (patch)
treefeecf5e43b7b4487b883514b2744fe17edf1f903 /dimension
parente261cff9bf8f4f42a769fecc5414d42b582dc9f7 (diff)
downloaddimension-cbdaf9ff41649174b72b0453b8a399f6abb11e8f.tar.xz
Support reflective finishes.
Diffstat (limited to 'dimension')
-rw-r--r--dimension/grammar.y44
-rw-r--r--dimension/lexer.l2
-rw-r--r--dimension/parse.h4
-rw-r--r--dimension/realize.c56
4 files changed, 101 insertions, 5 deletions
diff --git a/dimension/grammar.y b/dimension/grammar.y
index 7024180..8b744b0 100644
--- a/dimension/grammar.y
+++ b/dimension/grammar.y
@@ -167,7 +167,7 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner,
%name-prefix "dmnsn_yy"
-%expect 8
+%expect 10
%glr-parser
%parse-param {const char *filename}
@@ -340,7 +340,7 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner,
%token DMNSN_T_FADE_COLOR
%token DMNSN_T_FADE_DISTANCE
%token DMNSN_T_FADE_POWER
-%token DMNSN_T_FALLOFF
+%token DMNSN_T_FALLOFF "falloff"
%token DMNSN_T_FALLOFF_ANGLE
%token DMNSN_T_FALSE
%token DMNSN_T_FILE_EXISTS
@@ -522,7 +522,7 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner,
%token DMNSN_T_RECIPROCAL
%token DMNSN_T_RECURSION_LIMIT
%token DMNSN_T_RED "red"
-%token DMNSN_T_REFLECTION
+%token DMNSN_T_REFLECTION "reflection"
%token DMNSN_T_REFLECTION_EXPONENT
%token DMNSN_T_REFRACTION
%token DMNSN_T_REPEAT
@@ -722,6 +722,8 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner,
/* Finishes */
%type <astnode> FINISH
%type <astnode> FINISH_ITEMS
+%type <astnode> REFLECTION
+%type <astnode> REFLECTION_ITEMS
/* Floats */
%type <astnode> FLOAT
@@ -1002,6 +1004,38 @@ FINISH_ITEMS: /* empty */ {
$$ = $1;
dmnsn_array_push($$.children, &phong_size);
}
+ | FINISH_ITEMS REFLECTION {
+ $$ = $1;
+ dmnsn_array_push($$.children, &$2);
+ }
+;
+
+REFLECTION: "reflection" "{"
+ COLOR
+ REFLECTION_ITEMS
+ "}"
+ {
+ ++*$3.refcount;
+ $$ = dmnsn_new_astnode3(DMNSN_AST_REFLECTION, @$, $3, $3, $4);
+ }
+ | "reflection" "{"
+ COLOR "," COLOR
+ REFLECTION_ITEMS
+ "}"
+ {
+ $$ = dmnsn_new_astnode3(DMNSN_AST_REFLECTION, @$, $3, $5, $6);
+ }
+;
+
+REFLECTION_ITEMS: /* empty */ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_REFLECTION_ITEMS, @$);
+ }
+ | REFLECTION_ITEMS "falloff" FLOAT {
+ dmnsn_astnode falloff
+ = dmnsn_new_astnode1(DMNSN_AST_FALLOFF, @2, $3);
+ $$ = $1;
+ dmnsn_array_push($$.children, &falloff);
+ }
;
/* Floats */
@@ -1327,6 +1361,10 @@ dmnsn_astnode_string(dmnsn_astnode_type astnode_type)
dmnsn_astnode_map(DMNSN_AST_PHONG, "phong");
dmnsn_astnode_map(DMNSN_AST_PHONG_SIZE, "phong_size");
+ dmnsn_astnode_map(DMNSN_AST_REFLECTION, "reflection");
+ dmnsn_astnode_map(DMNSN_AST_REFLECTION_ITEMS, "reflection-items");
+ dmnsn_astnode_map(DMNSN_AST_FALLOFF, "falloff");
+
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 08712d7..2c75a41 100644
--- a/dimension/lexer.l
+++ b/dimension/lexer.l
@@ -167,6 +167,7 @@ unsigned long wchar;
"colour" RETURN_TOKEN(DMNSN_T_COLOR);
"direction" RETURN_TOKEN(DMNSN_T_DIRECTION);
"diffuse" RETURN_TOKEN(DMNSN_T_DIFFUSE);
+"falloff" RETURN_TOKEN(DMNSN_T_FALLOFF);
"filter" RETURN_TOKEN(DMNSN_T_FILTER);
"finish" RETURN_TOKEN(DMNSN_T_FINISH);
"gray" RETURN_TOKEN(DMNSN_T_GRAY);
@@ -180,6 +181,7 @@ unsigned long wchar;
"phong_size" RETURN_TOKEN(DMNSN_T_PHONG_SIZE);
"pigment" RETURN_TOKEN(DMNSN_T_PIGMENT);
"red" RETURN_TOKEN(DMNSN_T_RED);
+"reflection" RETURN_TOKEN(DMNSN_T_REFLECTION);
"rgb" RETURN_TOKEN(DMNSN_T_RGB);
"rgbf" RETURN_TOKEN(DMNSN_T_RGBF);
"rgbft" RETURN_TOKEN(DMNSN_T_RGBFT);
diff --git a/dimension/parse.h b/dimension/parse.h
index 7a7ded2..13fd5ff 100644
--- a/dimension/parse.h
+++ b/dimension/parse.h
@@ -62,6 +62,10 @@ typedef enum {
DMNSN_AST_PHONG,
DMNSN_AST_PHONG_SIZE,
+ DMNSN_AST_REFLECTION,
+ DMNSN_AST_REFLECTION_ITEMS,
+ DMNSN_AST_FALLOFF,
+
DMNSN_AST_FLOAT,
DMNSN_AST_INTEGER,
diff --git a/dimension/realize.c b/dimension/realize.c
index 7b1ce04..7f9379f 100644
--- a/dimension/realize.c
+++ b/dimension/realize.c
@@ -375,6 +375,48 @@ dmnsn_realize_pigment(dmnsn_astnode astnode)
return pigment;
}
+static dmnsn_finish *
+dmnsn_realize_reflection(dmnsn_astnode astnode)
+{
+ if (astnode.type != DMNSN_AST_REFLECTION) {
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Expected a reflection.");
+ }
+
+ dmnsn_astnode min_node, max_node;
+ dmnsn_array_get(astnode.children, 0, &min_node);
+ dmnsn_array_get(astnode.children, 1, &max_node);
+
+ dmnsn_color min = dmnsn_realize_color(min_node);
+ dmnsn_color max = dmnsn_realize_color(max_node);
+
+ double falloff = 1.0;
+
+ dmnsn_astnode items;
+ dmnsn_array_get(astnode.children, 2, &items);
+
+ unsigned int i;
+ for (i = 0; i < dmnsn_array_size(items.children); ++i) {
+ dmnsn_astnode item, child;
+ dmnsn_array_get(items.children, i, &item);
+
+ switch (item.type) {
+ case DMNSN_AST_FALLOFF:
+ dmnsn_array_get(item.children, 0, &child);
+ falloff = dmnsn_realize_float(child);
+ break;
+
+ default:
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Invalid reflection item.");
+ }
+ }
+
+ dmnsn_finish *reflection = dmnsn_new_reflective_finish(min, max, falloff);
+ if (!reflection) {
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate a reflection.");
+ }
+
+ return reflection;
+}
static dmnsn_finish *
dmnsn_realize_finish(dmnsn_astnode astnode)
@@ -394,10 +436,11 @@ dmnsn_realize_finish(dmnsn_astnode astnode)
double phong = 0.0;
double phong_size = 40.0;
+ dmnsn_finish *reflection = NULL;
+
unsigned int i;
for (i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode item;
- dmnsn_astnode child;
+ dmnsn_astnode item, child;
dmnsn_array_get(astnode.children, i, &item);
switch (item.type) {
@@ -422,6 +465,11 @@ dmnsn_realize_finish(dmnsn_astnode astnode)
phong_size = dmnsn_realize_float(child);
break;
+ case DMNSN_AST_REFLECTION:
+ dmnsn_delete_finish(reflection);
+ reflection = dmnsn_realize_reflection(item);
+ break;
+
default:
dmnsn_error(DMNSN_SEVERITY_HIGH, "Invalid finish item.");
}
@@ -448,6 +496,10 @@ dmnsn_realize_finish(dmnsn_astnode astnode)
);
}
+ if (reflection) {
+ finish = dmnsn_new_finish_combination(reflection, finish);
+ }
+
if (!finish) {
dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate finish.");
}