summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-08-15 00:22:47 -0600
committerTavian Barnes <tavianator@gmail.com>2010-08-15 00:22:47 -0600
commite0efc5ef27039f03be4783d593508ea7480aa4d0 (patch)
treeec3f69ad6d79ce1378fa6cdd7545d6b6901c2e3c
parent8fed0cea862554f1d8316c2244e6d94f691abad6 (diff)
downloaddimension-e0efc5ef27039f03be4783d593508ea7480aa4d0.tar.xz
Add cylinder support to dimension.
-rw-r--r--dimension/common.nonterminals2
-rw-r--r--dimension/common.rules20
-rw-r--r--dimension/common.terminals4
-rw-r--r--dimension/grammar.epilogue1
-rw-r--r--dimension/lexer.l2
-rw-r--r--dimension/parse.h1
-rw-r--r--dimension/realize.c47
-rw-r--r--tests/dimension/demo.pov8
-rwxr-xr-xtests/dimension/demo.sh14
9 files changed, 97 insertions, 2 deletions
diff --git a/dimension/common.nonterminals b/dimension/common.nonterminals
index 5f915c5..09a4f5f 100644
--- a/dimension/common.nonterminals
+++ b/dimension/common.nonterminals
@@ -40,6 +40,8 @@
%type <astnode> OBJECT
%type <astnode> FINITE_SOLID_OBJECT
%type <astnode> BOX
+%type <astnode> CYLINDER
+%type <astnode> MAYBE_OPEN
%type <astnode> SPHERE
%type <astnode> INFINITE_SOLID_OBJECT
%type <astnode> PLANE
diff --git a/dimension/common.rules b/dimension/common.rules
index 89b7ab8..e5e6543 100644
--- a/dimension/common.rules
+++ b/dimension/common.rules
@@ -283,6 +283,7 @@ OBJECT: FINITE_SOLID_OBJECT
;
FINITE_SOLID_OBJECT: BOX
+ | CYLINDER
| SPHERE
;
@@ -296,6 +297,25 @@ BOX: "box" "{"
}
;
+CYLINDER: "cylinder" "{"
+ VECTOR "," VECTOR "," FLOAT
+ MAYBE_OPEN
+ OBJECT_MODIFIERS
+ "}"
+ {
+ dmnsn_astnode object
+ = dmnsn_new_astnode4(DMNSN_AST_CYLINDER, @$, $3, $5, $7, $8);
+ $$ = dmnsn_new_astnode2(DMNSN_AST_OBJECT, @$, object, $9);
+ }
+;
+
+MAYBE_OPEN: /* empty */ {
+ $$ = dmnsn_new_ast_integer(false);
+ }
+ | "open" {
+ $$ = dmnsn_new_ast_integer(true);
+ }
+
SPHERE: "sphere" "{"
VECTOR "," FLOAT
OBJECT_MODIFIERS
diff --git a/dimension/common.terminals b/dimension/common.terminals
index 7ccc8cb..af75bb4 100644
--- a/dimension/common.terminals
+++ b/dimension/common.terminals
@@ -152,7 +152,7 @@
%token DMNSN_T_CUBIC_SPLINE
%token DMNSN_T_CUBIC_WAVE
%token DMNSN_T_CUTAWAY_TEXTURES
-%token DMNSN_T_CYLINDER
+%token DMNSN_T_CYLINDER "cylinder"
%token DMNSN_T_CYLINDRICAL
%token DMNSN_T_DEFINED
%token DMNSN_T_DEGREES "degrees"
@@ -315,7 +315,7 @@
%token DMNSN_T_ON "on"
%token DMNSN_T_ONCE
%token DMNSN_T_ONION
-%token DMNSN_T_OPEN
+%token DMNSN_T_OPEN "open"
%token DMNSN_T_ORIENT
%token DMNSN_T_ORIENTATION
%token DMNSN_T_ORTHOGRAPHIC
diff --git a/dimension/grammar.epilogue b/dimension/grammar.epilogue
index 25d678a..d766a07 100644
--- a/dimension/grammar.epilogue
+++ b/dimension/grammar.epilogue
@@ -134,6 +134,7 @@ dmnsn_astnode_string(dmnsn_astnode_type astnode_type)
dmnsn_astnode_map(DMNSN_AST_OBJECT, "object");
dmnsn_astnode_map(DMNSN_AST_BOX, "box");
+ dmnsn_astnode_map(DMNSN_AST_CYLINDER, "cylinder");
dmnsn_astnode_map(DMNSN_AST_DIFFERENCE, "difference");
dmnsn_astnode_map(DMNSN_AST_INTERSECTION, "intersection");
dmnsn_astnode_map(DMNSN_AST_LIGHT_SOURCE, "light_source");
diff --git a/dimension/lexer.l b/dimension/lexer.l
index ea98c07..190acb0 100644
--- a/dimension/lexer.l
+++ b/dimension/lexer.l
@@ -186,6 +186,7 @@ unsigned long wchar;
"colour" RETURN_TOKEN(DMNSN_T_COLOR);
"cos" RETURN_TOKEN(DMNSN_T_COS);
"cosh" RETURN_TOKEN(DMNSN_T_COSH);
+"cylinder" RETURN_TOKEN(DMNSN_T_CYLINDER);
"degrees" RETURN_TOKEN(DMNSN_T_DEGREES);
"difference" RETURN_TOKEN(DMNSN_T_DIFFERENCE);
"diffuse" RETURN_TOKEN(DMNSN_T_DIFFUSE);
@@ -224,6 +225,7 @@ unsigned long wchar;
"object" RETURN_TOKEN(DMNSN_T_OBJECT);
"off" RETURN_TOKEN(DMNSN_T_OFF);
"on" RETURN_TOKEN(DMNSN_T_ON);
+"open" RETURN_TOKEN(DMNSN_T_OPEN);
"perspective" RETURN_TOKEN(DMNSN_T_PERSPECTIVE);
"phong" RETURN_TOKEN(DMNSN_T_PHONG);
"phong_size" RETURN_TOKEN(DMNSN_T_PHONG_SIZE);
diff --git a/dimension/parse.h b/dimension/parse.h
index e81f76e..d9b9195 100644
--- a/dimension/parse.h
+++ b/dimension/parse.h
@@ -48,6 +48,7 @@ typedef enum {
DMNSN_AST_OBJECT,
DMNSN_AST_BOX,
+ DMNSN_AST_CYLINDER,
DMNSN_AST_DIFFERENCE,
DMNSN_AST_INTERSECTION,
DMNSN_AST_LIGHT_SOURCE,
diff --git a/dimension/realize.c b/dimension/realize.c
index ad6630f..15eb334 100644
--- a/dimension/realize.c
+++ b/dimension/realize.c
@@ -843,6 +843,50 @@ dmnsn_realize_box(dmnsn_astnode astnode)
}
static dmnsn_object *
+dmnsn_realize_cylinder(dmnsn_astnode astnode)
+{
+ dmnsn_assert(astnode.type == DMNSN_AST_CYLINDER, "Expected a cylinder.");
+
+ dmnsn_astnode pnode1, pnode2, radius, open;
+ dmnsn_array_get(astnode.children, 0, &pnode1);
+ dmnsn_array_get(astnode.children, 1, &pnode2);
+ dmnsn_array_get(astnode.children, 2, &radius);
+ dmnsn_array_get(astnode.children, 3, &open);
+
+ dmnsn_vector p1 = dmnsn_realize_vector(pnode1);
+ dmnsn_vector p2 = dmnsn_realize_vector(pnode2);
+ double r = dmnsn_realize_float(radius);
+
+ dmnsn_vector dir = dmnsn_vector_sub(p2, p1);
+ double l = dmnsn_vector_norm(dir);
+
+ double theta1 = dmnsn_vector_axis_angle(dmnsn_y, dir, dmnsn_x);
+ double theta2 = dmnsn_vector_axis_angle(dmnsn_y, dir, dmnsn_z);
+
+ dmnsn_object *cylinder = dmnsn_new_cylinder(dmnsn_realize_integer(open));
+ /* Transformations: lift the cylinder to start at the origin, scale, rotate,
+ and translate properly */
+ cylinder->trans = dmnsn_translation_matrix(dmnsn_new_vector(0.0, 1.0, 0.0));
+ cylinder->trans = dmnsn_matrix_mul(
+ dmnsn_scale_matrix(dmnsn_new_vector(r, l/2.0, r)),
+ cylinder->trans
+ );
+ cylinder->trans = dmnsn_matrix_mul(
+ dmnsn_rotation_matrix(dmnsn_new_vector(theta1, 0.0, 0.0)),
+ cylinder->trans
+ );
+ cylinder->trans = dmnsn_matrix_mul(
+ dmnsn_rotation_matrix(dmnsn_new_vector(0.0, 0.0, theta2)),
+ cylinder->trans
+ );
+ cylinder->trans = dmnsn_matrix_mul(
+ dmnsn_translation_matrix(p1),
+ cylinder->trans
+ );
+ return cylinder;
+}
+
+static dmnsn_object *
dmnsn_realize_sphere(dmnsn_astnode astnode)
{
dmnsn_assert(astnode.type == DMNSN_AST_SPHERE, "Expected a sphere.");
@@ -989,6 +1033,9 @@ dmnsn_realize_object(dmnsn_astnode astnode, dmnsn_array *lights)
case DMNSN_AST_BOX:
object = dmnsn_realize_box(onode);
break;
+ case DMNSN_AST_CYLINDER:
+ object = dmnsn_realize_cylinder(onode);
+ break;
case DMNSN_AST_DIFFERENCE:
object = dmnsn_realize_difference(onode, modifiers, lights);
break;
diff --git a/tests/dimension/demo.pov b/tests/dimension/demo.pov
index 4e8ba4d..69c9d4e 100644
--- a/tests/dimension/demo.pov
+++ b/tests/dimension/demo.pov
@@ -71,6 +71,14 @@ difference {
}
}
+cylinder {
+ -1.25*y, 1.25*y, 0.1
+ pigment {
+ color rgb <1, 0, 0>
+ }
+ rotate -45*x
+}
+
plane {
y, -2
pigment {
diff --git a/tests/dimension/demo.sh b/tests/dimension/demo.sh
index a5f05a5..2bf21b9 100755
--- a/tests/dimension/demo.sh
+++ b/tests/dimension/demo.sh
@@ -77,6 +77,20 @@ demo_exp=$(echo -n \
(phong_size (float 40)))))))
object-modifiers)
(object
+ (cylinder
+ (vector (float 0) (float -1.25) (float 0) (float 0) (float 0))
+ (vector (float 0) (float 1.25) (float 0) (float 0) (float 0))
+ (float 0.1)
+ (integer 0))
+ (object-modifiers
+ (pigment
+ (vector (integer 1) (integer 0) (integer 0)
+ (integer 0) (integer 0))
+ pigment-modifiers)
+ (transformation
+ (rotation (vector (integer -45) (integer 0) (integer 0)
+ (integer 0) (integer 0))))))
+ (object
(plane
(vector (integer 0) (integer 1) (integer 0) (integer 0) (integer 0))
(integer -2))