diff options
-rw-r--r-- | dimension/grammar.y | 64 | ||||
-rw-r--r-- | dimension/lexer.l | 5 | ||||
-rw-r--r-- | dimension/parse.h | 7 | ||||
-rw-r--r-- | dimension/realize.c | 86 | ||||
-rw-r--r-- | tests/dimension/demo.pov | 10 | ||||
-rwxr-xr-x | tests/dimension/demo.sh | 12 |
6 files changed, 171 insertions, 13 deletions
diff --git a/dimension/grammar.y b/dimension/grammar.y index b7e2b19..7024180 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 7 +%expect 8 %glr-parser %parse-param {const char *filename} @@ -232,7 +232,7 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner, %token DMNSN_T_ALPHA %token DMNSN_T_ALTITUDE %token DMNSN_T_ALWAYS_SAMPLE -%token DMNSN_T_AMBIENT +%token DMNSN_T_AMBIENT "ambient" %token DMNSN_T_AMBIENT_LIGHT %token DMNSN_T_ANGLE "angle" %token DMNSN_T_APERTURE @@ -315,7 +315,7 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner, %token DMNSN_T_DENTS %token DMNSN_T_DF3 %token DMNSN_T_DIFFERENCE -%token DMNSN_T_DIFFUSE +%token DMNSN_T_DIFFUSE "diffuse" %token DMNSN_T_DIMENSION_SIZE %token DMNSN_T_DIMENSIONS %token DMNSN_T_DIRECTION "direction" @@ -347,7 +347,7 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner, %token DMNSN_T_FILTER "filter" %token DMNSN_T_FINAL_CLOCK %token DMNSN_T_FINAL_FRAME -%token DMNSN_T_FINISH +%token DMNSN_T_FINISH "finish" %token DMNSN_T_FISHEYE %token DMNSN_T_FLATNESS %token DMNSN_T_FLIP @@ -480,8 +480,8 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner, %token DMNSN_T_PERSPECTIVE "perspective" %token DMNSN_T_PGM %token DMNSN_T_PHASE -%token DMNSN_T_PHONG -%token DMNSN_T_PHONG_SIZE +%token DMNSN_T_PHONG "phong" +%token DMNSN_T_PHONG_SIZE "phong_size" %token DMNSN_T_PHOTONS %token DMNSN_T_PI %token DMNSN_T_PIGMENT "pigment" @@ -584,7 +584,7 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner, %token DMNSN_T_TANH %token DMNSN_T_TARGET %token DMNSN_T_TEXT -%token DMNSN_T_TEXTURE +%token DMNSN_T_TEXTURE "texture" %token DMNSN_T_TEXTURE_LIST %token DMNSN_T_TEXTURE_MAP %token DMNSN_T_TGA @@ -719,6 +719,10 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner, %type <astnode> PIGMENT %type <astnode> PIGMENT_TYPE +/* Finishes */ +%type <astnode> FINISH +%type <astnode> FINISH_ITEMS + /* Floats */ %type <astnode> FLOAT %type <astnode> FLOAT_LITERAL @@ -943,6 +947,10 @@ TEXTURE_ITEMS: /* empty */ { $$ = $1; dmnsn_array_push($$.children, &$2); } + | TEXTURE_ITEMS FINISH { + $$ = $1; + dmnsn_array_push($$.children, &$2); + } ; /* Pigments */ @@ -961,6 +969,41 @@ PIGMENT_TYPE: /* empty */ { | COLOR ; +/* Finishes */ +FINISH: "finish" "{" + FINISH_ITEMS + "}" + { $$ = $3; } +; + +FINISH_ITEMS: /* empty */ { + $$ = dmnsn_new_astnode(DMNSN_AST_FINISH, @$); + } + | FINISH_ITEMS "ambient" COLOR { + dmnsn_astnode ambient = dmnsn_new_astnode1(DMNSN_AST_AMBIENT, + @2, $3); + $$ = $1; + dmnsn_array_push($$.children, &ambient); + } + | FINISH_ITEMS "diffuse" FLOAT { + dmnsn_astnode diffuse = dmnsn_new_astnode1(DMNSN_AST_DIFFUSE, + @2, $3); + $$ = $1; + dmnsn_array_push($$.children, &diffuse); + } + | FINISH_ITEMS "phong" FLOAT { + dmnsn_astnode phong = dmnsn_new_astnode1(DMNSN_AST_PHONG, @2, $3); + $$ = $1; + dmnsn_array_push($$.children, &phong); + } + | FINISH_ITEMS "phong_size" FLOAT { + dmnsn_astnode phong_size + = dmnsn_new_astnode1(DMNSN_AST_PHONG_SIZE, @2, $3); + $$ = $1; + dmnsn_array_push($$.children, &phong_size); + } +; + /* Floats */ FLOAT: ARITH_EXPR { @@ -1275,8 +1318,15 @@ dmnsn_astnode_string(dmnsn_astnode_type astnode_type) dmnsn_astnode_map(DMNSN_AST_OBJECT_MODIFIERS, "object-modifiers"); dmnsn_astnode_map(DMNSN_AST_TEXTURE, "texture"); + dmnsn_astnode_map(DMNSN_AST_PIGMENT, "pigment"); + dmnsn_astnode_map(DMNSN_AST_FINISH, "finish"); + dmnsn_astnode_map(DMNSN_AST_AMBIENT, "ambient"); + dmnsn_astnode_map(DMNSN_AST_DIFFUSE, "diffuse"); + dmnsn_astnode_map(DMNSN_AST_PHONG, "phong"); + dmnsn_astnode_map(DMNSN_AST_PHONG_SIZE, "phong_size"); + 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 691467b..08712d7 100644 --- a/dimension/lexer.l +++ b/dimension/lexer.l @@ -157,6 +157,7 @@ unsigned long wchar; } (?# Keywords) +"ambient" RETURN_TOKEN(DMNSN_T_AMBIENT); "angle" RETURN_TOKEN(DMNSN_T_ANGLE); "background" RETURN_TOKEN(DMNSN_T_BACKGROUND); "box" RETURN_TOKEN(DMNSN_T_BOX); @@ -165,7 +166,9 @@ unsigned long wchar; "color" RETURN_TOKEN(DMNSN_T_COLOR); "colour" RETURN_TOKEN(DMNSN_T_COLOR); "direction" RETURN_TOKEN(DMNSN_T_DIRECTION); +"diffuse" RETURN_TOKEN(DMNSN_T_DIFFUSE); "filter" RETURN_TOKEN(DMNSN_T_FILTER); +"finish" RETURN_TOKEN(DMNSN_T_FINISH); "gray" RETURN_TOKEN(DMNSN_T_GRAY); "grey" RETURN_TOKEN(DMNSN_T_GRAY); "green" RETURN_TOKEN(DMNSN_T_GREEN); @@ -173,6 +176,8 @@ unsigned long wchar; "look_at" RETURN_TOKEN(DMNSN_T_LOOK_AT); "light_source" RETURN_TOKEN(DMNSN_T_LIGHT_SOURCE); "perspective" RETURN_TOKEN(DMNSN_T_PERSPECTIVE); +"phong" RETURN_TOKEN(DMNSN_T_PHONG); +"phong_size" RETURN_TOKEN(DMNSN_T_PHONG_SIZE); "pigment" RETURN_TOKEN(DMNSN_T_PIGMENT); "red" RETURN_TOKEN(DMNSN_T_RED); "rgb" RETURN_TOKEN(DMNSN_T_RGB); diff --git a/dimension/parse.h b/dimension/parse.h index 2b2a878..7a7ded2 100644 --- a/dimension/parse.h +++ b/dimension/parse.h @@ -53,8 +53,15 @@ typedef enum { DMNSN_AST_OBJECT_MODIFIERS, DMNSN_AST_TEXTURE, + DMNSN_AST_PIGMENT, + DMNSN_AST_FINISH, + DMNSN_AST_AMBIENT, + DMNSN_AST_DIFFUSE, + DMNSN_AST_PHONG, + DMNSN_AST_PHONG_SIZE, + DMNSN_AST_FLOAT, DMNSN_AST_INTEGER, diff --git a/dimension/realize.c b/dimension/realize.c index 5ba4c8b..7b1ce04 100644 --- a/dimension/realize.c +++ b/dimension/realize.c @@ -24,6 +24,7 @@ #include "utility.h" #include <math.h> #include <stdio.h> +#include <stdbool.h> static double dmnsn_realize_float(dmnsn_astnode astnode) @@ -374,6 +375,86 @@ dmnsn_realize_pigment(dmnsn_astnode astnode) return pigment; } + +static dmnsn_finish * +dmnsn_realize_finish(dmnsn_astnode astnode) +{ + if (astnode.type != DMNSN_AST_FINISH) { + dmnsn_error(DMNSN_SEVERITY_HIGH, "Expected a finish."); + } + + dmnsn_finish *finish = dmnsn_new_finish(); + + dmnsn_color ambient = dmnsn_black; + bool ambient_set = false; + + double diffuse = 0.0; + bool diffuse_set = false; + + double phong = 0.0; + double phong_size = 40.0; + + unsigned int i; + for (i = 0; i < dmnsn_array_size(astnode.children); ++i) { + dmnsn_astnode item; + dmnsn_astnode child; + dmnsn_array_get(astnode.children, i, &item); + + switch (item.type) { + case DMNSN_AST_AMBIENT: + dmnsn_array_get(item.children, 0, &child); + ambient = dmnsn_realize_color(child); + ambient_set = true; + break; + + case DMNSN_AST_DIFFUSE: + dmnsn_array_get(item.children, 0, &child); + diffuse = dmnsn_realize_float(child); + diffuse_set = true; + break; + + case DMNSN_AST_PHONG: + dmnsn_array_get(item.children, 0, &child); + phong = dmnsn_realize_float(child); + break; + case DMNSN_AST_PHONG_SIZE: + dmnsn_array_get(item.children, 0, &child); + phong_size = dmnsn_realize_float(child); + break; + + default: + dmnsn_error(DMNSN_SEVERITY_HIGH, "Invalid finish item."); + } + } + + if (ambient_set) { + finish = dmnsn_new_finish_combination( + dmnsn_new_ambient_finish(ambient), + finish + ); + } + + if (diffuse_set) { + finish = dmnsn_new_finish_combination( + dmnsn_new_diffuse_finish(diffuse), + finish + ); + } + + if (phong) { + finish = dmnsn_new_finish_combination( + dmnsn_new_phong_finish(phong, phong_size), + finish + ); + } + + if (!finish) { + dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate finish."); + } + + return finish; +} + static dmnsn_texture * dmnsn_realize_texture(dmnsn_astnode astnode) { @@ -397,6 +478,11 @@ dmnsn_realize_texture(dmnsn_astnode astnode) texture->pigment = dmnsn_realize_pigment(modifier); break; + case DMNSN_AST_FINISH: + dmnsn_delete_finish(texture->finish); + texture->finish = dmnsn_realize_finish(modifier); + break; + default: dmnsn_error(DMNSN_SEVERITY_HIGH, "Invalid texture item."); } diff --git a/tests/dimension/demo.pov b/tests/dimension/demo.pov index bb43573..c59148a 100644 --- a/tests/dimension/demo.pov +++ b/tests/dimension/demo.pov @@ -46,7 +46,13 @@ box { sphere { <0, 0, 0>, 1.25 - pigment { - color rgb <0, 1, 0> + texture { + pigment { + color rgb <0, 1, 0> + } + finish { + phong 0.2 + phong_size 40.0 + } } } diff --git a/tests/dimension/demo.sh b/tests/dimension/demo.sh index c49e0ca..05225b6 100755 --- a/tests/dimension/demo.sh +++ b/tests/dimension/demo.sh @@ -42,15 +42,19 @@ demo_exp=$(echo -n \ (rotate (vector (integer 45) (integer 0) (integer 0) (integer 0) (integer 0))) (texture - (pigment (color (integer 0) (integer 0) (integer 1) - (float 0.25) (float 0.25)))))) + (pigment + (color (integer 0) (integer 0) (integer 1) + (float 0.25) (float 0.25)))))) (sphere (vector (integer 0) (integer 0) (integer 0) (integer 0) (integer 0)) (float 1.25) (object-modifiers (texture - (pigment (color (integer 0) (integer 1) (integer 0) - (integer 0) (integer 0)))))))' \ + (pigment + (color (integer 0) (integer 1) (integer 0) (integer 0) (integer 0))) + (finish + (phong (float 0.2)) + (phong_size (float 40)))))))' \ | tr '\n' ' ' | sed -r 's/[[:space:]]+/ /g') if [ "$demo" != "$demo_exp" ]; then |