diff options
Diffstat (limited to 'dimension')
-rw-r--r-- | dimension/grammar.y | 44 | ||||
-rw-r--r-- | dimension/lexer.l | 2 | ||||
-rw-r--r-- | dimension/parse.h | 4 | ||||
-rw-r--r-- | dimension/realize.c | 56 |
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."); } |