merged branch scene-file-parsing into trunk

git-svn-id: svn://anubis/fart/trunk@343 7f9b0f55-74a9-4bce-be96-3c2cd072584d
This commit is contained in:
Josh Holtrop 2010-10-06 20:21:48 +00:00
commit 700e47901b
9 changed files with 933 additions and 281 deletions

View File

@ -9,6 +9,7 @@
#include "parser/parser.h" #include "parser/parser.h"
#include "parser/nodes.h" #include "parser/nodes.h"
#include "util/Polygon.h" #include "util/Polygon.h"
#include "util/Scope.h"
using namespace std; using namespace std;
@ -16,64 +17,16 @@ typedef vector< refptr<Node> >::const_iterator Node_Iterator;
void Scene::load(const char * filename) void Scene::load(const char * filename)
{ {
refptr<Node> node = parse(filename); refptr<Scope> scope = new Scope();
processNode(node); refptr<Node> node = parse(filename, scope);
} if ( ! node.isNull() )
{
/* evaluate any scripting nodes in the node tree */
refptr<Node> processed_scene = node->evaluate();
node->evaluateChildren(processed_scene);
void Scene::processNode(refptr<Node> node) /* now we have a new node tree under 'dummy' with no scripting nodes */
{ processScene(processed_scene);
if (node.isNull())
return;
if ( typeid(*node) == typeid(SceneNode) )
{
processScene(node);
}
else if ( node->isShape() )
{
refptr<Shape> shape = processShape(node);
if ( ! shape.isNull() )
m_shapes.push_back(shape);
}
else if ( typeid(*node) == typeid(LightNode) )
{
refptr<Light> light = processLight(node);
if ( ! light.isNull() )
m_lights.push_back(light);
}
else if ( typeid(*node) == typeid(OptionsNode) )
{
processOptions(node);
}
else if (node->isTransformBlock())
{
vector< refptr<Shape> > shapes = processTransformBlock(node);
for (int i = 0, sz = shapes.size(); i < sz; i++)
{
m_shapes.push_back(shapes[i]);
}
}
else if ( typeid(*node) == typeid(MaterialDefinitionNode) )
{
processMaterialDefinition(node);
}
else if ( typeid(*node) == typeid(ShapeDefinitionNode) )
{
processShapeDefinition(node);
}
else
{
cerr << __FILE__ << ": " << __LINE__
<< ": error: unrecognized node!" << endl;
}
}
void Scene::processChildren(refptr<Node> node)
{
std::vector< refptr<Node> > & children = node->getChildren();
for (int i = 0, sz = children.size(); i < sz; i++)
{
processNode(children[i]);
} }
} }
@ -98,18 +51,34 @@ void Scene::processScene(refptr<Node> node)
} }
} }
/* then any other scene-specific items */
for (Node_Iterator it = node->getChildren().begin(); for (Node_Iterator it = node->getChildren().begin();
it != node->getChildren().end(); it != node->getChildren().end();
it++) it++)
{ {
if ( typeid(**it) != typeid(CameraNode) ) if ( typeid(**it) == typeid(LightNode) )
{ {
processNode(*it); refptr<Light> light = processLight(*it);
if ( ! light.isNull() )
m_lights.push_back(light);
} }
else if ( typeid(**it) == typeid(OptionsNode) )
{
processOptions(*it);
}
}
/* then any general items */
vector<ShapeRef> shapes = processGeneralItems(node);
for (vector<ShapeRef>::iterator it = shapes.begin();
it != shapes.end();
it++)
{
m_shapes.push_back(*it);
} }
} }
refptr<Shape> Scene::processShape(refptr<Node> node) ShapeRef Scene::processShape(refptr<Node> node)
{ {
if ( typeid(*node) == typeid(BoxNode) ) if ( typeid(*node) == typeid(BoxNode) )
{ {
@ -147,7 +116,7 @@ refptr<Shape> Scene::processShape(refptr<Node> node)
exit(3); exit(3);
} }
return refptr<Shape>(NULL); return ShapeRef(NULL);
} }
void Scene::processCamera(refptr<Node> node) void Scene::processCamera(refptr<Node> node)
@ -220,7 +189,7 @@ void Scene::processOptions(refptr<Node> node)
} }
} }
vector< refptr<Shape> > Scene::processTransformBlock(refptr<Node> node) vector<ShapeRef> Scene::processTransformBlock(refptr<Node> node)
{ {
if ( typeid(*node) == typeid(TranslateBlockNode) ) if ( typeid(*node) == typeid(TranslateBlockNode) )
{ {
@ -238,8 +207,22 @@ vector< refptr<Shape> > Scene::processTransformBlock(refptr<Node> node)
m_transforms.push(m_transforms.top()); m_transforms.push(m_transforms.top());
m_transforms.top().scale(node->getVector()); m_transforms.top().scale(node->getVector());
} }
else
{
cerr << "Unknown transformation block node type!" << endl;
exit(4);
}
vector< refptr<Shape> > shapes; vector<ShapeRef> shapes = processGeneralItems(node);
m_transforms.pop();
return shapes;
}
vector<ShapeRef> Scene::processGeneralItems(refptr<Node> node)
{
vector<ShapeRef> shapes, incoming;
for (Node_Iterator it = node->getChildren().begin(); for (Node_Iterator it = node->getChildren().begin();
it != node->getChildren().end(); it != node->getChildren().end();
@ -247,30 +230,27 @@ vector< refptr<Shape> > Scene::processTransformBlock(refptr<Node> node)
{ {
if ((*it)->isTransformBlock()) if ((*it)->isTransformBlock())
{ {
vector< refptr<Shape> > in = processTransformBlock(*it); incoming = processTransformBlock(*it);
for (int i = 0, sz = in.size(); i < sz; i++)
{
shapes.push_back(in[i]);
} }
} else if ( typeid(**it) == typeid(MaterialDefinitionNode) )
else if ( (*it)->isShape() )
{ {
shapes.push_back(processShape(*it)); processMaterialDefinition(*it);
} }
else if ( typeid(**it) == typeid(ShapeDefinitionNode) ) else if ( typeid(**it) == typeid(ShapeDefinitionNode) )
{ {
processShapeDefinition(*it); processShapeDefinition(*it);
} }
else else if ( (*it)->isShape() )
{ {
cerr << "Unknown transform block item: " << typeid(**it).name() shapes.push_back(processShape(*it));
<< endl; }
exit(3); while (incoming.size() > 0)
{
shapes.push_back(incoming[0]);
incoming.erase(incoming.begin());
} }
} }
m_transforms.pop();
return shapes; return shapes;
} }
@ -346,7 +326,7 @@ refptr<Material> Scene::processMaterial(refptr<Node> node)
return material; return material;
} }
refptr<Shape> Scene::processBox(refptr<Node> node) ShapeRef Scene::processBox(refptr<Node> node)
{ {
refptr<Vector> size = new Vector(1, 1, 1); refptr<Vector> size = new Vector(1, 1, 1);
refptr<Material> material; refptr<Material> material;
@ -367,7 +347,7 @@ refptr<Shape> Scene::processBox(refptr<Node> node)
} }
} }
refptr<Shape> box = new Box(size); ShapeRef box = new Box(size);
if ( ! material.isNull() ) if ( ! material.isNull() )
box->setMaterial(material); box->setMaterial(material);
box->setTransform(m_transforms.top()); box->setTransform(m_transforms.top());
@ -378,7 +358,7 @@ refptr<Shape> Scene::processBox(refptr<Node> node)
return box; return box;
} }
refptr<Shape> Scene::processCyl(refptr<Node> node) ShapeRef Scene::processCyl(refptr<Node> node)
{ {
double radius1 = 1.0; double radius1 = 1.0;
double radius2 = 1.0; double radius2 = 1.0;
@ -404,7 +384,7 @@ refptr<Shape> Scene::processCyl(refptr<Node> node)
} }
} }
refptr<Shape> cyl = new Cyl(radius1, radius2, height); ShapeRef cyl = new Cyl(radius1, radius2, height);
if ( ! material.isNull() ) if ( ! material.isNull() )
cyl->setMaterial(material); cyl->setMaterial(material);
cyl->setTransform(m_transforms.top()); cyl->setTransform(m_transforms.top());
@ -457,7 +437,7 @@ refptr<Light> Scene::processLight(refptr<Node> node)
return light; return light;
} }
refptr<Shape> Scene::processPlane(refptr<Node> node) ShapeRef Scene::processPlane(refptr<Node> node)
{ {
Vector normal(0, 0, 1); Vector normal(0, 0, 1);
double dist = 0; double dist = 0;
@ -480,7 +460,7 @@ refptr<Shape> Scene::processPlane(refptr<Node> node)
} }
} }
refptr<Shape> plane = new Plane(normal[0], ShapeRef plane = new Plane(normal[0],
normal[1], normal[1],
normal[2], normal[2],
dist); dist);
@ -494,7 +474,7 @@ refptr<Shape> Scene::processPlane(refptr<Node> node)
return plane; return plane;
} }
refptr<Shape> Scene::processSphere(refptr<Node> node) ShapeRef Scene::processSphere(refptr<Node> node)
{ {
double radius = 1.0; double radius = 1.0;
refptr<Material> material; refptr<Material> material;
@ -515,7 +495,7 @@ refptr<Shape> Scene::processSphere(refptr<Node> node)
} }
} }
refptr<Shape> sphere = new Sphere(radius); ShapeRef sphere = new Sphere(radius);
if ( ! material.isNull() ) if ( ! material.isNull() )
sphere->setMaterial(material); sphere->setMaterial(material);
sphere->setTransform(m_transforms.top()); sphere->setTransform(m_transforms.top());
@ -526,9 +506,9 @@ refptr<Shape> Scene::processSphere(refptr<Node> node)
return sphere; return sphere;
} }
refptr<Shape> Scene::processBool(refptr<Node> node) ShapeRef Scene::processBool(refptr<Node> node)
{ {
vector< refptr<Shape> > shapes; vector<ShapeRef> shapes;
refptr<Material> material; refptr<Material> material;
bool restore_transform = processTransforms(node); bool restore_transform = processTransforms(node);
@ -540,7 +520,7 @@ refptr<Shape> Scene::processBool(refptr<Node> node)
{ {
if ( (*it)->isShape() ) if ( (*it)->isShape() )
{ {
refptr<Shape> shape = processShape(*it); ShapeRef shape = processShape(*it);
if ( ! shape.isNull() ) if ( ! shape.isNull() )
shapes.push_back(shape); shapes.push_back(shape);
} }
@ -550,7 +530,7 @@ refptr<Shape> Scene::processBool(refptr<Node> node)
} }
else if ( (*it)->isTransformBlock() ) else if ( (*it)->isTransformBlock() )
{ {
vector< refptr<Shape> > in = processTransformBlock(*it); vector<ShapeRef> in = processTransformBlock(*it);
for (int i = 0, sz = in.size(); i < sz; i++) for (int i = 0, sz = in.size(); i < sz; i++)
{ {
shapes.push_back(in[i]); shapes.push_back(in[i]);
@ -569,7 +549,7 @@ refptr<Shape> Scene::processBool(refptr<Node> node)
exit(3); exit(3);
} }
refptr<Shape> shape; ShapeRef shape;
if ( typeid(*node) == typeid(IntersectNode) ) if ( typeid(*node) == typeid(IntersectNode) )
shape = new Intersect(shapes); shape = new Intersect(shapes);
else if ( typeid(*node) == typeid(UnionNode) ) else if ( typeid(*node) == typeid(UnionNode) )
@ -594,7 +574,7 @@ refptr<Shape> Scene::processBool(refptr<Node> node)
return shape; return shape;
} }
refptr<Shape> Scene::processExtrude(refptr<Node> node) ShapeRef Scene::processExtrude(refptr<Node> node)
{ {
refptr<Material> material; refptr<Material> material;
Extrude * extrude = new Extrude(); Extrude * extrude = new Extrude();
@ -706,7 +686,7 @@ refptr<Polygon> Scene::processNGon(refptr<Node> node)
return p; return p;
} }
refptr<Shape> Scene::processShapeRef(refptr<Node> node) ShapeRef Scene::processShapeRef(refptr<Node> node)
{ {
if (m_shape_definitions.find(node->getString()) if (m_shape_definitions.find(node->getString())
== m_shape_definitions.end()) == m_shape_definitions.end())
@ -717,7 +697,7 @@ refptr<Shape> Scene::processShapeRef(refptr<Node> node)
} }
refptr<Material> material; refptr<Material> material;
refptr<Shape> shape = m_shape_definitions[node->getString()]->clone(); ShapeRef shape = m_shape_definitions[node->getString()]->clone();
bool restore_transform = processTransforms(node); bool restore_transform = processTransforms(node);

View File

@ -58,25 +58,25 @@ class Scene
/* In Scene-load.cc */ /* In Scene-load.cc */
void load(const char * filename); void load(const char * filename);
void processNode(refptr<Node> node);
void processChildren(refptr<Node> node);
void processScene(refptr<Node> node); void processScene(refptr<Node> node);
refptr<Material> processMaterial(refptr<Node> node); refptr<Material> processMaterial(refptr<Node> node);
refptr<Shape> processBox(refptr<Node> node); ShapeRef processBox(refptr<Node> node);
refptr<Shape> processCyl(refptr<Node> node); ShapeRef processCyl(refptr<Node> node);
refptr<Light> processLight(refptr<Node> node); refptr<Light> processLight(refptr<Node> node);
refptr<Shape> processPlane(refptr<Node> node); ShapeRef processPlane(refptr<Node> node);
refptr<Shape> processSphere(refptr<Node> node); ShapeRef processSphere(refptr<Node> node);
refptr<Shape> processShape(refptr<Node> node); ShapeRef processShape(refptr<Node> node);
refptr<Shape> processBool(refptr<Node> node); ShapeRef processBool(refptr<Node> node);
refptr<Shape> processExtrude(refptr<Node> node); ShapeRef processExtrude(refptr<Node> node);
refptr<Shape> processShapeRef(refptr<Node> node); ShapeRef processShapeRef(refptr<Node> node);
refptr<Polygon> processPolygon(refptr<Node> node); refptr<Polygon> processPolygon(refptr<Node> node);
refptr<Polygon> processNGon(refptr<Node> node); refptr<Polygon> processNGon(refptr<Node> node);
bool processTransforms(refptr<Node> node); bool processTransforms(refptr<Node> node);
void processCamera(refptr<Node> node); void processCamera(refptr<Node> node);
void processOptions(refptr<Node> node); void processOptions(refptr<Node> node);
std::vector< refptr<Shape> > processTransformBlock(refptr<Node> node); std::vector<ShapeRef> processTransformBlock(refptr<Node> node);
std::vector<ShapeRef> processGeneralItems(refptr<Node> node);
std::vector<ShapeRef> processForNode(refptr<Node> node);
void processMaterialDefinition(refptr<Node> node); void processMaterialDefinition(refptr<Node> node);
void processShapeDefinition(refptr<Node> node); void processShapeDefinition(refptr<Node> node);
@ -91,8 +91,8 @@ class Scene
int m_ambient_occlusion_level; int m_ambient_occlusion_level;
/* private data */ /* private data */
std::vector< refptr<Shape> > m_shapes; std::vector<ShapeRef> m_shapes;
std::map< std::string, refptr<Shape> > m_shape_definitions; std::map<std::string, ShapeRef> m_shape_definitions;
std::vector< refptr<Light> > m_lights; std::vector< refptr<Light> > m_lights;
std::stack<Transform> m_transforms; std::stack<Transform> m_transforms;
double m_view_plane_dist; double m_view_plane_dist;

View File

@ -1,14 +1,49 @@
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <typeinfo>
#include "nodes.h" #include "nodes.h"
#include <vector>
using namespace std; using namespace std;
void Node::addChildren(refptr<Node> other) void Node::evaluateChildren(refptr<Node> parent)
{
/* recursively evaluate all children nodes */
for (std::vector< refptr<Node> >::iterator it = m_children.begin();
it != m_children.end();
it++)
{
refptr<Node> evaluated = (*it)->evaluate();
if ( ! evaluated.isNull() )
{
if (typeid(*evaluated) == typeid(EvaluatePropagateNode))
{
for (vector<NodeRef>::iterator it2
= evaluated->getChildren().begin();
it2 != evaluated->getChildren().end();
it2++)
{
parent->addChild(*it2);
}
}
else
{
(*it)->evaluateChildren(evaluated);
parent->addChild(evaluated);
}
}
}
}
void Node::addChildren(NodeRef other)
{ {
if (other.isNull()) if (other.isNull())
return; return;
for (vector< refptr<Node> >::const_iterator it = other->m_children.begin(); for (vector<NodeRef>::const_iterator it = other->m_children.begin();
it != other->m_children.end(); it != other->m_children.end();
it++) it++)
{ {
@ -19,3 +54,110 @@ void Node::addChildren(refptr<Node> other)
Node::~Node() Node::~Node()
{ {
} }
NodeRef BinOpNode::evaluate()
{
double o = one->evaluate()->getNumber();
double t = two->evaluate()->getNumber();
double r = 0.0;
switch (m_op)
{
case '*':
r = o * t;
break;
case '/':
r = o / t;
break;
case '+':
r = o + t;
break;
case '-':
r = o - t;
break;
default:
cerr << "Error: BinOpNode created with op '" << m_op << "'" << endl;
exit(-3);
}
return new NumberNode(r);
}
NodeRef BoolExpressionNode::evaluate()
{
double o, t;
double r = 0;
if (m_op != '!')
{
o = one->evaluate()->getNumber();
t = two->evaluate()->getNumber();
}
switch (m_op)
{
case '<':
r = o < t ? 0 : 1;
break;
case '>':
r = o > t ? 0 : 1;
break;
case '=':
r = o == t ? 0 : 1;
break;
case 'n':
r = o != t ? 0 : 1;
break;
case '!':
r = ! one->evaluate()->getInteger();
break;
case 'T':
r = 1;
break;
}
return new NumberNode(r);
}
NodeRef ForNode::evaluate()
{
NodeRef eval = new EvaluatePropagateNode();
if (!m_nodes[0].isNull())
{
m_nodes[0]->evaluate();
}
while (m_nodes[1]->evaluate()->getInteger() != 0)
{
for (vector<NodeRef>::iterator it = m_children.begin();
it != m_children.end();
it++)
{
NodeRef n = (*it)->evaluate();
if ( ! n.isNull() )
{
if (typeid(*n) == typeid(EvaluatePropagateNode))
{
for (vector<NodeRef>::iterator it2 = n->getChildren().begin();
it2 != n->getChildren().end();
it2++)
{
eval->addChild(*it2);
}
}
else
{
eval->addChild(n);
}
}
}
if (!m_nodes[2].isNull())
{
m_nodes[2]->evaluate();
}
}
/* clear out all child nodes so that evaluateChildren() doesn't
* attempt to evaluate them */
m_children.clear();
return eval;
}

View File

@ -2,10 +2,17 @@
#ifndef NODES_H #ifndef NODES_H
#define NODES_H NODES_H #define NODES_H NODES_H
#include "util/refptr.h" #include <stdlib.h> /* exit() */
#include "util/Vector.h"
#include <vector> #include <vector>
#include <string> #include <string>
#include <iostream>
#include "util/refptr.h"
#include "util/Vector.h"
#include "util/Scope.h"
extern refptr<Scope> parser_scope;
class Node class Node
{ {
@ -15,119 +22,211 @@ class Node
void addChildren(refptr<Node> other); void addChildren(refptr<Node> other);
std::vector< refptr<Node> > & getChildren() { return m_children; } std::vector< refptr<Node> > & getChildren() { return m_children; }
virtual int getInteger() { return 0; } virtual int getInteger() { return getNumber(); }
virtual double getNumber() { return 0.0; }
virtual double getNumber()
{
std::cerr << "Warning: Node::getNumber() called!" << std::endl;
return 0.0;
}
virtual refptr<Vector> getVector() virtual refptr<Vector> getVector()
{ {
std::cerr << "Warning: Node::getVector() called!" << std::endl;
return refptr<Vector>(NULL); return refptr<Vector>(NULL);
} }
virtual std::string getString()
{
std::cerr << "Warning: Node::getString() called!" << std::endl;
return "";
}
virtual refptr<Node> evaluate()
{
std::cerr << "Warning: Node::evaluate() called!" << std::endl;
return NULL;
}
virtual void evaluateChildren(refptr<Node> parent);
virtual bool isShape() { return false; } virtual bool isShape() { return false; }
virtual bool isMaterial() { return false; } virtual bool isMaterial() { return false; }
virtual bool isTransformBlock() { return false; } virtual bool isTransformBlock() { return false; }
virtual std::string getString() { return ""; } virtual bool isExpression() { return false; }
protected: protected:
std::vector< refptr<Node> > m_children; std::vector< refptr<Node> > m_children;
}; };
typedef refptr<Node> NodeRef;
class IntegerNode : public Node
{
public:
IntegerNode(int number) { m_number = number; }
int getInteger() { return m_number; }
double getNumber() { return m_number; }
protected:
int m_number;
};
class NumberNode : public Node class NumberNode : public Node
{ {
public: public:
NumberNode(double number) { m_number = number; } NumberNode(double number)
double getNumber() { return m_number; } : m_number(number), m_direct(true)
{
}
NumberNode(NodeRef expr)
: m_direct(false)
{
m_expr = expr;
}
virtual double getNumber()
{
return m_direct ? m_number : m_expr->getNumber();
}
virtual refptr<Node> evaluate()
{
return m_direct
? new NumberNode(m_number)
: new NumberNode(m_expr->evaluate());
}
protected: protected:
double m_number; double m_number;
bool m_direct;
NodeRef m_expr;
}; };
class VectorNode : public Node class VectorNode : public Node
{ {
public: public:
VectorNode(refptr<Vector> vector) { m_vector = vector; } VectorNode(NodeRef a, NodeRef b, NodeRef c)
refptr<Vector> getVector() { return m_vector; } : m_a(a), m_b(b), m_c(c), m_direct(true)
{
}
VectorNode(NodeRef node)
: m_vector(node), m_direct(false)
{
}
refptr<Vector> getVector()
{
return m_direct
? new Vector(m_a->getNumber(),
m_b->getNumber(),
m_c->getNumber())
: m_vector->getVector();
}
virtual NodeRef evaluate()
{
return m_direct
? new VectorNode(m_a->evaluate(),
m_b->evaluate(),
m_c->evaluate())
: m_vector->evaluate();
}
protected: protected:
refptr<Vector> m_vector; NodeRef m_a, m_b, m_c, m_vector;
bool m_direct;
}; };
class AmbientNode : public VectorNode class AmbientNode : public VectorNode
{ {
public: public:
AmbientNode(refptr<Vector> vector) : VectorNode(vector) {} AmbientNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new AmbientNode(m_vector->evaluate());
}
}; };
class AmbientOcclusionNode : public IntegerNode class AmbientOcclusionNode : public NumberNode
{ {
public: public:
AmbientOcclusionNode(int i) : IntegerNode(i) {} AmbientOcclusionNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new AmbientOcclusionNode(m_expr->evaluate());
}
}; };
class BoxNode : public Node class BoxNode : public Node
{ {
public: public:
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate()
{
return new BoxNode();
}
}; };
class CameraNode : public Node class CameraNode : public Node
{ {
public:
virtual NodeRef evaluate()
{
return new CameraNode();
}
}; };
class ColorNode : public VectorNode class ColorNode : public VectorNode
{ {
public: public:
ColorNode(refptr<Vector> vector) : VectorNode(vector) {} ColorNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new ColorNode(m_vector->evaluate());
}
}; };
class CylNode : public Node class CylNode : public Node
{ {
public: public:
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate()
{
return new CylNode();
}
}; };
class DiffuseNode : public VectorNode class DiffuseNode : public VectorNode
{ {
public: public:
DiffuseNode(refptr<Vector> vector) : VectorNode(vector) {} DiffuseNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new DiffuseNode(m_vector->evaluate());
}
}; };
class ExposureNode : public NumberNode class ExposureNode : public NumberNode
{ {
public: public:
ExposureNode(double d) : NumberNode(d) {} ExposureNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new ExposureNode(m_expr->evaluate());
}
}; };
class ExtrudeNode : public Node class ExtrudeNode : public Node
{ {
public: public:
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate()
{
return new ExtrudeNode();
}
}; };
class HeightNode : public IntegerNode class HeightNode : public NumberNode
{ {
public: public:
HeightNode(int i) : IntegerNode(i) {} HeightNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new HeightNode(m_expr->evaluate());
}
}; };
class IdentifierNode : public Node class IdentifierNode : public Node
{ {
public: public:
IdentifierNode(const std::string & str) { m_string = str; } IdentifierNode(const std::string & str) { m_string = str; }
std::string getString() std::string getString() { return m_string; }
virtual NodeRef evaluate()
{ {
return m_string; return new IdentifierNode(m_string);
} }
protected: protected:
std::string m_string; std::string m_string;
@ -137,38 +236,62 @@ class IntersectNode : public Node
{ {
public: public:
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate()
{
return new IntersectNode();
}
}; };
class ItemsNode : public Node class ItemsNode : public Node
{ {
public:
virtual NodeRef evaluate()
{
return new ItemsNode();
}
}; };
class JitterNode : public IntegerNode class JitterNode : public NumberNode
{ {
public: public:
JitterNode(int i) : IntegerNode(i) {} JitterNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new JitterNode(m_expr->evaluate());
}
}; };
class LightNode : public Node class LightNode : public Node
{ {
public:
virtual NodeRef evaluate() { return new LightNode(); }
}; };
class LookAtNode : public VectorNode class LookAtNode : public VectorNode
{ {
public: public:
LookAtNode(refptr<Vector> vector) : VectorNode(vector) {} LookAtNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new LookAtNode(m_vector->evaluate());
}
}; };
class MaterialNode : public Node class MaterialNode : public Node
{ {
public: public:
bool isMaterial() { return true; } bool isMaterial() { return true; }
virtual NodeRef evaluate() { return new MaterialNode(); }
}; };
class MaterialDefinitionNode : public IdentifierNode class MaterialDefinitionNode : public IdentifierNode
{ {
public: public:
MaterialDefinitionNode(const std::string & str) : IdentifierNode(str) {} MaterialDefinitionNode(const std::string & str) : IdentifierNode(str) {}
virtual NodeRef evaluate()
{
return new MaterialDefinitionNode(m_string);
}
}; };
class MaterialRefNode : public IdentifierNode class MaterialRefNode : public IdentifierNode
@ -176,123 +299,195 @@ class MaterialRefNode : public IdentifierNode
public: public:
MaterialRefNode(const std::string & str) : IdentifierNode(str) {} MaterialRefNode(const std::string & str) : IdentifierNode(str) {}
bool isMaterial() { return true; } bool isMaterial() { return true; }
virtual NodeRef evaluate() { return new MaterialRefNode(m_string); }
}; };
class MaxDepthNode : public IntegerNode class MaxDepthNode : public NumberNode
{ {
public: public:
MaxDepthNode(int i) : IntegerNode(i) {} MaxDepthNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new MaxDepthNode(m_expr->evaluate());
}
}; };
class MultisampleNode : public IntegerNode class MultisampleNode : public NumberNode
{ {
public: public:
MultisampleNode(int i) : IntegerNode(i) {} MultisampleNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new MultisampleNode(m_expr->evaluate());
}
}; };
class NGonNode : public IntegerNode class NGonNode : public NumberNode
{ {
public: public:
NGonNode(int i) : IntegerNode(i) {} NGonNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new NGonNode(m_expr->evaluate());
}
}; };
class OffsetNode : public NumberNode class OffsetNode : public NumberNode
{ {
public: public:
OffsetNode(double d) : NumberNode(d) {} OffsetNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new OffsetNode(m_expr->evaluate());
}
}; };
class OptionsNode : public Node class OptionsNode : public Node
{ {
public:
virtual NodeRef evaluate() { return new OptionsNode(); }
}; };
class PlaneNode : public Node class PlaneNode : public Node
{ {
public: public:
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate() { return new PlaneNode(); }
}; };
class PlanePositionNode : public Node class PlanePositionNode : public VectorNode
{ {
public: public:
PlanePositionNode(refptr<Vector> vec, double dist) PlanePositionNode(NodeRef vec_node, NodeRef dist)
: VectorNode(vec_node)
{ {
m_vector = vec;
m_dist = dist; m_dist = dist;
} }
refptr<Vector> getVector() { return m_vector; } double getNumber() { return m_dist->getNumber(); }
double getNumber() { return m_dist; } virtual NodeRef evaluate()
{
return new PlanePositionNode(m_vector->evaluate(),
m_dist->evaluate());
}
protected: protected:
refptr<Vector> m_vector; NodeRef m_dist;
double m_dist;
}; };
class PolygonNode : public Node class PolygonNode : public Node
{ {
public:
virtual NodeRef evaluate() { return new PolygonNode(); }
}; };
class PositionNode : public VectorNode class PositionNode : public VectorNode
{ {
public: public:
PositionNode(refptr<Vector> vector) : VectorNode(vector) {} PositionNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new PositionNode(m_vector->evaluate());
}
}; };
class RadiusNode : public NumberNode class RadiusNode : public NumberNode
{ {
public: public:
RadiusNode(double d) : NumberNode(d) {} RadiusNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new RadiusNode(m_expr->evaluate());
}
}; };
class ReflectanceNode : public NumberNode class ReflectanceNode : public NumberNode
{ {
public: public:
ReflectanceNode(double d) : NumberNode(d) {} ReflectanceNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new ReflectanceNode(m_expr->evaluate());
}
}; };
class RotateNode : public VectorNode class RotateNode : public VectorNode
{ {
public: public:
RotateNode(double angle, refptr<Vector> vector) RotateNode(NodeRef angle, NodeRef vec_node)
: VectorNode(vector) : VectorNode(vec_node)
{ {
m_angle = angle; m_angle = angle;
} }
double getNumber() { return m_angle; } double getNumber() { return m_angle->getNumber(); }
virtual NodeRef evaluate()
{
return new RotateNode(m_angle->evaluate(), m_vector->evaluate());
}
protected: protected:
double m_angle; NodeRef m_angle;
}; };
class RotateBlockNode : public RotateNode class RotateBlockNode : public RotateNode
{ {
public: public:
RotateBlockNode(double angle, refptr<Vector> vector) RotateBlockNode(NodeRef angle, NodeRef vec_node)
: RotateNode(angle, vector) {} : RotateNode(angle, vec_node) {}
bool isTransformBlock() { return true; } bool isTransformBlock() { return true; }
virtual NodeRef evaluate()
{
return new RotateBlockNode(m_angle->evaluate(), m_vector->evaluate());
}
}; };
class ScaleNode : public VectorNode class ScaleNode : public VectorNode
{ {
public: public:
ScaleNode(refptr<Vector> vector) : VectorNode(vector) {} ScaleNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new ScaleNode(m_vector->evaluate());
}
}; };
class ScaleBlockNode : public ScaleNode class ScaleBlockNode : public ScaleNode
{ {
public: public:
ScaleBlockNode(refptr<Vector> vector) : ScaleNode(vector) {} ScaleBlockNode(NodeRef vector) : ScaleNode(vector) {}
bool isTransformBlock() { return true; } bool isTransformBlock() { return true; }
virtual NodeRef evaluate()
{
return new ScaleBlockNode(m_vector->evaluate());
}
};
class ScaleScalarNode : public Node
{
public:
ScaleScalarNode(NodeRef expr)
: m_expr(expr)
{
}
virtual NodeRef evaluate()
{
NodeRef n = m_expr->evaluate();
return new VectorNode(n, n, n);
}
protected:
NodeRef m_expr;
}; };
class SceneNode : public Node class SceneNode : public Node
{ {
public:
virtual NodeRef evaluate() { return new SceneNode(); }
}; };
class ShapeDefinitionNode : public IdentifierNode class ShapeDefinitionNode : public IdentifierNode
{ {
public: public:
ShapeDefinitionNode(const std::string & str) : IdentifierNode(str) {} ShapeDefinitionNode(const std::string & str) : IdentifierNode(str) {}
virtual NodeRef evaluate() { return new ShapeDefinitionNode(m_string); }
}; };
class ShapeRefNode : public IdentifierNode class ShapeRefNode : public IdentifierNode
@ -300,79 +495,247 @@ class ShapeRefNode : public IdentifierNode
public: public:
ShapeRefNode(const std::string & str) : IdentifierNode(str) {} ShapeRefNode(const std::string & str) : IdentifierNode(str) {}
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate() { return new ShapeRefNode(m_string); }
}; };
class ShininessNode : public NumberNode class ShininessNode : public NumberNode
{ {
public: public:
ShininessNode(double d) : NumberNode(d) {} ShininessNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new ShininessNode(m_expr->evaluate());
}
}; };
class SizeNode : public VectorNode class SizeNode : public VectorNode
{ {
public: public:
SizeNode(refptr<Vector> vector) : VectorNode(vector) {} SizeNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new SizeNode(m_vector->evaluate());
}
}; };
class SpecularNode : public VectorNode class SpecularNode : public VectorNode
{ {
public: public:
SpecularNode(refptr<Vector> vector) : VectorNode(vector) {} SpecularNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new SpecularNode(m_vector->evaluate());
}
}; };
class SphereNode : public Node class SphereNode : public Node
{ {
public: public:
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate() { return new SphereNode(); }
}; };
class SubtractNode : public Node class SubtractNode : public Node
{ {
public: public:
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate() { return new SubtractNode(); }
}; };
class TranslateNode : public VectorNode class TranslateNode : public VectorNode
{ {
public: public:
TranslateNode(refptr<Vector> vector) : VectorNode(vector) {} TranslateNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new TranslateNode(m_vector->evaluate());
}
}; };
class TranslateBlockNode : public TranslateNode class TranslateBlockNode : public TranslateNode
{ {
public: public:
TranslateBlockNode(refptr<Vector> vector) : TranslateNode(vector) {} TranslateBlockNode(NodeRef vector) : TranslateNode(vector) {}
bool isTransformBlock() { return true; } bool isTransformBlock() { return true; }
virtual NodeRef evaluate()
{
return new TranslateBlockNode(m_vector->evaluate());
}
}; };
class TransparencyNode : public NumberNode class TransparencyNode : public NumberNode
{ {
public: public:
TransparencyNode(double d) : NumberNode(d) {} TransparencyNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new TransparencyNode(m_expr->evaluate());
}
}; };
class UnionNode : public Node class UnionNode : public Node
{ {
public: public:
bool isShape() { return true; } bool isShape() { return true; }
virtual NodeRef evaluate() { return new UnionNode(); }
}; };
class UpNode : public VectorNode class UpNode : public VectorNode
{ {
public: public:
UpNode(refptr<Vector> vector) : VectorNode(vector) {} UpNode(NodeRef vector) : VectorNode(vector) {}
virtual NodeRef evaluate()
{
return new UpNode(m_vector->evaluate());
}
}; };
class VFOVNode : public NumberNode class VFOVNode : public NumberNode
{ {
public: public:
VFOVNode(double d) : NumberNode(d) {} VFOVNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new VFOVNode(m_expr->evaluate());
}
}; };
class WidthNode : public IntegerNode class WidthNode : public NumberNode
{ {
public: public:
WidthNode(int i) : IntegerNode(i) {} WidthNode(NodeRef e) : NumberNode(e) {}
virtual NodeRef evaluate()
{
return new WidthNode(m_expr->evaluate());
}
};
/******** scripting nodes ********/
class ExpressionNode : public Node
{
public:
bool isExpression() { return true; }
virtual NodeRef evaluate() = 0;
};
class AssignmentNode : public ExpressionNode
{
public:
AssignmentNode(NodeRef varref, NodeRef expr)
: m_varref(varref), m_expr(expr)
{
}
std::string getString() { return m_varref->getString(); }
virtual NodeRef evaluate()
{
double n = m_expr->evaluate()->getNumber();
parser_scope->putGlobal(getString(), n);
return new NumberNode(n);
}
protected:
NodeRef m_varref;
NodeRef m_expr;
};
class LocalAssignmentNode : public ExpressionNode
{
public:
LocalAssignmentNode(NodeRef varref, NodeRef expr)
: m_varref(varref), m_expr(expr)
{
}
std::string getString() { return m_varref->getString(); }
virtual NodeRef evaluate()
{
double n = m_expr->evaluate()->getNumber();
parser_scope->putLocal(getString(), n);
return new NumberNode(n);
}
protected:
NodeRef m_varref;
NodeRef m_expr;
};
class LocalDeclNode : public ExpressionNode
{
public:
LocalDeclNode(NodeRef varref) : m_varref(varref) { }
virtual NodeRef evaluate()
{
parser_scope->putLocal(m_varref->getString(), 0.0);
return NULL;
}
protected:
NodeRef m_varref;
};
class BinOpNode : public ExpressionNode
{
public:
BinOpNode(char op, NodeRef one, NodeRef two)
: m_op(op), one(one), two(two)
{
}
virtual NodeRef evaluate();
protected:
char m_op;
NodeRef one;
NodeRef two;
};
class BoolExpressionNode : public Node
{
public:
BoolExpressionNode(char op, NodeRef one, NodeRef two)
: m_op(op), one(one), two(two)
{
}
virtual NodeRef evaluate();
protected:
char m_op;
NodeRef one;
NodeRef two;
};
class VarRefNode : public Node
{
public:
VarRefNode(const std::string & str) { m_string = str; }
std::string getString() { return m_string; }
virtual NodeRef evaluate()
{
if (parser_scope->contains(m_string))
{
return new NumberNode(parser_scope->get(m_string));
}
std::cerr << "Error: No identifier '" << m_string << "' in scope"
<< std::endl;
exit(4);
}
protected:
std::string m_string;
};
class ForNode : public Node
{
public:
ForNode(NodeRef e1, NodeRef e2, NodeRef e3)
{
m_nodes[0] = e1;
m_nodes[1] = e2;
m_nodes[2] = e3;
}
virtual NodeRef evaluate();
protected:
NodeRef m_nodes[3];
};
/* this class is only used to hold a set of items coming out of a class's
* evaluate() from above. the evaluateChildren() top-level method will
* propagate children of this class up to the level of their parent */
class EvaluatePropagateNode : public Node
{
}; };
#endif #endif

View File

@ -4,9 +4,10 @@
#include "nodes.h" #include "nodes.h"
#include "util/refptr.h" #include "util/refptr.h"
#include "util/Scope.h"
#define YYSTYPE refptr<Node> #define YYSTYPE refptr<Node>
refptr<Node> parse(const char * fileName); refptr<Node> parse(const char * fileName, refptr<Scope> scope);
#endif #endif

View File

@ -14,9 +14,13 @@
\+ return PLUS; \+ return PLUS;
- return MINUS; - return MINUS;
\* return STAR; \* return TIMES;
\/ return DIVIDE; \/ return DIVIDE;
% return MOD; % return MOD;
:= return ASSIGN;
= return EQUALS;
!= return NOTEQUALS;
! return NOT;
; return SEMICOLON; ; return SEMICOLON;
: return COLON; : return COLON;
@ -36,8 +40,8 @@
\< return LESS; \< return LESS;
\> return GREATER; \> return GREATER;
-?[0-9]+ *yylval = new IntegerNode(atoi(yytext)); return DEC_NUMBER; [0-9]+ *yylval = new NumberNode(atof(yytext)); return REAL_NUMBER;
-?[0-9]*\.[0-9]+ *yylval = new NumberNode(atof(yytext)); return REAL_NUMBER; [0-9]*\.[0-9]+ *yylval = new NumberNode(atof(yytext)); return REAL_NUMBER;
ambient return AMBIENT; ambient return AMBIENT;
ambient_occlusion return AMBIENT_OCCLUSION; ambient_occlusion return AMBIENT_OCCLUSION;
@ -81,10 +85,21 @@ up return UP;
vfov return VFOV; vfov return VFOV;
width return WIDTH; width return WIDTH;
else return ELSE;
elsif return ELSIF;
for return FOR;
if return IF;
while return WHILE;
local return LOCAL;
[a-zA-Z_][a-zA-Z_0-9]* { [a-zA-Z_][a-zA-Z_0-9]* {
*yylval = new IdentifierNode(yytext); *yylval = new IdentifierNode(yytext);
return IDENTIFIER; return IDENTIFIER;
} }
\$[a-zA-Z_][a-zA-Z_0-9]* {
*yylval = new VarRefNode(yytext+1);
return VARREF;
}
#.*\n yylloc->first_line++; yylloc->last_line++; #.*\n yylloc->first_line++; yylloc->last_line++;
\n yylloc->first_line++; yylloc->last_line++; \n yylloc->first_line++; yylloc->last_line++;

View File

@ -5,6 +5,7 @@
#include <iostream> #include <iostream>
#include "util/Vector.h" #include "util/Vector.h"
#include "util/refptr.h" #include "util/refptr.h"
#include "util/Scope.h"
#include "nodes.h" #include "nodes.h"
#include "parser.h" #include "parser.h"
#include "parser.tab.hh" /* bison-generated header with YY[SL]TYPE */ #include "parser.tab.hh" /* bison-generated header with YY[SL]TYPE */
@ -24,6 +25,7 @@ int yywrap()
} }
static refptr<Node> parsed_scene_node; static refptr<Node> parsed_scene_node;
refptr<Scope> parser_scope;
%} %}
@ -33,9 +35,13 @@ static refptr<Node> parsed_scene_node;
%token PLUS; %token PLUS;
%token MINUS; %token MINUS;
%token STAR; %token TIMES;
%token DIVIDE; %token DIVIDE;
%token MOD; %token MOD;
%token ASSIGN;
%token EQUALS;
%token NOTEQUALS;
%token NOT;
%token SEMICOLON; %token SEMICOLON;
%token COLON; %token COLON;
@ -55,7 +61,6 @@ static refptr<Node> parsed_scene_node;
%token LESS; %token LESS;
%token GREATER; %token GREATER;
%token DEC_NUMBER;
%token REAL_NUMBER; %token REAL_NUMBER;
%token AMBIENT; %token AMBIENT;
@ -101,6 +106,19 @@ static refptr<Node> parsed_scene_node;
%token WIDTH; %token WIDTH;
%token IDENTIFIER; %token IDENTIFIER;
%token VARREF;
%token ELSE;
%token ELSIF;
%token FOR;
%token IF;
%token WHILE;
%token LOCAL;
%right ASSIGN
%left PLUS MINUS
%left TIMES DIVIDE
%left UMINUS
%% %%
@ -140,7 +158,7 @@ box_items: /* empty */
; ;
box_item: SIZE vector3 { box_item: SIZE vector3 {
$$ = new SizeNode($2->getVector()); $$ = new SizeNode($2);
} }
| shape_item { $$ = $1; } | shape_item { $$ = $1; }
; ;
@ -160,16 +178,16 @@ camera_items: /* empty */
; ;
camera_item: POSITION vector3 { camera_item: POSITION vector3 {
$$ = new PositionNode($2->getVector()); $$ = new PositionNode($2);
} }
| LOOKAT vector3 { | LOOKAT vector3 {
$$ = new LookAtNode($2->getVector()); $$ = new LookAtNode($2);
} }
| UP vector3 { | UP vector3 {
$$ = new UpNode($2->getVector()); $$ = new UpNode($2);
} }
| VFOV number { | VFOV expression {
$$ = new VFOVNode($2->getNumber()); $$ = new VFOVNode($2);
} }
; ;
@ -188,7 +206,7 @@ cyl_items: /* empty */
; ;
cyl_item: SIZE vector3 { cyl_item: SIZE vector3 {
$$ = new SizeNode($2->getVector()); $$ = new SizeNode($2);
} }
| shape_item { $$ = $1; } | shape_item { $$ = $1; }
; ;
@ -213,14 +231,30 @@ extrude_item: polygon { $$ = $1; }
| shape_item { $$ = $1; } | shape_item { $$ = $1; }
; ;
general_items: /* empty */
| general_item general_items {
$$ = new ItemsNode();
$$->addChild($1);
$$->addChildren($2);
}
;
general_item: transform_block { $$ = $1; }
| material_definition { $$ = $1; }
| shape_definition { $$ = $1; }
| shape { $$ = $1; }
| for { $$ = $1; }
| stmt_expression { $$ = $1; }
;
intersect: INTERSECT LCURLY bool_items RCURLY { intersect: INTERSECT LCURLY bool_items RCURLY {
$$ = new IntersectNode(); $$ = new IntersectNode();
$$->addChildren($3); $$->addChildren($3);
} }
; ;
jitter: JITTER number { jitter: JITTER expression {
$$ = new JitterNode($2->getInteger()); $$ = new JitterNode($2);
} }
; ;
@ -239,16 +273,16 @@ light_items: /* empty */
; ;
light_item: POSITION vector3 { light_item: POSITION vector3 {
$$ = new PositionNode($2->getVector()); $$ = new PositionNode($2);
} }
| DIFFUSE vector3 { | DIFFUSE vector3 {
$$ = new DiffuseNode($2->getVector()); $$ = new DiffuseNode($2);
} }
| SPECULAR vector3 { | SPECULAR vector3 {
$$ = new SpecularNode($2->getVector()); $$ = new SpecularNode($2);
} }
| COLOR vector3 { | COLOR vector3 {
$$ = new ColorNode($2->getVector()); $$ = new ColorNode($2);
} }
| radius { | radius {
$$ = $1; $$ = $1;
@ -273,25 +307,25 @@ material_items: /* empty */
; ;
material_item: COLOR vector3 { material_item: COLOR vector3 {
$$ = new ColorNode($2->getVector()); $$ = new ColorNode($2);
} }
| AMBIENT vector3 { | AMBIENT vector3 {
$$ = new AmbientNode($2->getVector()); $$ = new AmbientNode($2);
} }
| DIFFUSE vector3 { | DIFFUSE vector3 {
$$ = new DiffuseNode($2->getVector()); $$ = new DiffuseNode($2);
} }
| SPECULAR vector3 { | SPECULAR vector3 {
$$ = new SpecularNode($2->getVector()); $$ = new SpecularNode($2);
} }
| REFLECTANCE number { | REFLECTANCE expression {
$$ = new ReflectanceNode($2->getNumber()); $$ = new ReflectanceNode($2);
} }
| SHININESS number { | SHININESS expression {
$$ = new ShininessNode($2->getNumber()); $$ = new ShininessNode($2);
} }
| TRANSPARENCY number { | TRANSPARENCY expression {
$$ = new TransparencyNode($2->getNumber()); $$ = new TransparencyNode($2);
} }
; ;
@ -306,21 +340,20 @@ material_ref: MATERIAL IDENTIFIER {
} }
; ;
number: DEC_NUMBER { $$ = $1; } number: REAL_NUMBER { $$ = $1; }
| REAL_NUMBER { $$ = $1; }
; ;
ngon: NGON DEC_NUMBER COMMA number { ngon: NGON expression COMMA expression {
$$ = new NGonNode($2->getInteger()); $$ = new NGonNode($2);
$$->addChild(new RadiusNode($4->getNumber())); $$->addChild(new RadiusNode($4));
} }
; ;
offset: OFFSET number { offset: OFFSET expression {
$$ = new OffsetNode($2->getNumber()); $$ = new OffsetNode($2);
} }
| OFFSET number LCURLY offset_items RCURLY { | OFFSET expression LCURLY offset_items RCURLY {
$$ = new OffsetNode($2->getNumber()); $$ = new OffsetNode($2);
$$->addChildren($4); $$->addChildren($4);
} }
; ;
@ -333,15 +366,14 @@ offset_items: /* empty */
} }
; ;
offset_item: SCALE number { offset_item: SCALE expression {
$$ = new ScaleNode(new Vector($2->getNumber(), $2->getNumber(), $$ = new ScaleNode(new ScaleScalarNode($2));
$2->getNumber()));
} }
| SCALE vector2 { | SCALE vector2 {
$$ = new ScaleNode($2->getVector()); $$ = new ScaleNode($2);
} }
| POSITION vector2 { | POSITION vector2 {
$$ = new PositionNode($2->getVector()); $$ = new PositionNode($2);
} }
; ;
@ -359,26 +391,26 @@ options_items: /* empty */
} }
; ;
options_item: WIDTH DEC_NUMBER { options_item: WIDTH expression {
$$ = new WidthNode($2->getInteger()); $$ = new WidthNode($2);
} }
| HEIGHT DEC_NUMBER { | HEIGHT expression {
$$ = new HeightNode($2->getInteger()); $$ = new HeightNode($2);
} }
| MULTISAMPLE DEC_NUMBER { | MULTISAMPLE expression {
$$ = new MultisampleNode($2->getInteger()); $$ = new MultisampleNode($2);
} }
| MAXDEPTH DEC_NUMBER { | MAXDEPTH expression {
$$ = new MaxDepthNode($2->getInteger()); $$ = new MaxDepthNode($2);
} }
| EXPOSURE number { | EXPOSURE expression {
$$ = new ExposureNode($2->getNumber()); $$ = new ExposureNode($2);
} }
| AMBIENT vector3 { | AMBIENT vector3 {
$$ = new AmbientNode($2->getVector()); $$ = new AmbientNode($2);
} }
| AMBIENT_OCCLUSION DEC_NUMBER { | AMBIENT_OCCLUSION expression {
$$ = new AmbientOcclusionNode($2->getInteger()); $$ = new AmbientOcclusionNode($2);
} }
; ;
@ -396,8 +428,8 @@ plane_items: /* empty */
} }
; ;
plane_item: POSITION vector3 COMMA number { plane_item: POSITION vector3 COMMA expression {
$$ = new PlanePositionNode($2->getVector(), $4->getNumber()); $$ = new PlanePositionNode($2, $4);
} }
| shape_item { $$ = $1; } | shape_item { $$ = $1; }
; ;
@ -419,8 +451,8 @@ polygon_items: /* empty */
polygon_item: vector2 { $$ = $1; } polygon_item: vector2 { $$ = $1; }
; ;
radius: RADIUS number { radius: RADIUS expression {
$$ = new RadiusNode($2->getNumber()); $$ = new RadiusNode($2);
} }
; ;
@ -433,12 +465,9 @@ scene_items: /* empty */
; ;
scene_item: camera { $$ = $1; } scene_item: camera { $$ = $1; }
| shape { $$ = $1; }
| options { $$ = $1; }
| light { $$ = $1; } | light { $$ = $1; }
| transform_block { $$ = $1; } | options { $$ = $1; }
| material_definition { $$ = $1; } | general_item { $$ = $1; }
| shape_definition { $$ = $1; }
; ;
shape: plane { $$ = $1; } shape: plane { $$ = $1; }
@ -506,77 +535,125 @@ subtract: SUBTRACT LCURLY bool_items RCURLY {
; ;
transform: TRANSLATE vector3 { transform: TRANSLATE vector3 {
$$ = new TranslateNode($2->getVector()); $$ = new TranslateNode($2);
} }
| ROTATE number COMMA vector3 { | ROTATE expression COMMA vector3 {
$$ = new RotateNode($2->getNumber(), $4->getVector()); $$ = new RotateNode($2, $4);
} }
| SCALE vector3 { | SCALE vector3 {
$$ = new ScaleNode($2->getVector()); $$ = new ScaleNode($2);
} }
| SCALE number { | SCALE expression {
$$ = new ScaleNode(new Vector($2->getNumber(), $$ = new ScaleNode(new ScaleScalarNode($2));
$2->getNumber(), $2->getNumber()));
} }
; ;
transform_block: TRANSLATE vector3 LCURLY transform_block_items RCURLY { transform_block: TRANSLATE vector3 LCURLY general_items RCURLY {
$$ = new TranslateBlockNode($2->getVector()); $$ = new TranslateBlockNode($2);
$$->addChildren($4); $$->addChildren($4);
} }
| ROTATE number COMMA vector3 LCURLY transform_block_items RCURLY { | ROTATE expression COMMA vector3 LCURLY general_items RCURLY {
$$ = new RotateBlockNode($2->getNumber(), $4->getVector()); $$ = new RotateBlockNode($2, $4);
$$->addChildren($6); $$->addChildren($6);
} }
| SCALE vector3 LCURLY transform_block_items RCURLY { | SCALE vector3 LCURLY general_items RCURLY {
$$ = new ScaleBlockNode($2->getVector()); $$ = new ScaleBlockNode($2);
$$->addChildren($4); $$->addChildren($4);
} }
| SCALE number LCURLY transform_block_items RCURLY { | SCALE expression LCURLY general_items RCURLY {
$$ = new ScaleBlockNode( $$ = new ScaleBlockNode(new ScaleScalarNode($2));
new Vector($2->getNumber(), $2->getNumber(),
$2->getNumber()));
$$->addChildren($4); $$->addChildren($4);
} }
; ;
transform_block_items: /* empty */
| transform_block_item transform_block_items {
$$ = new ItemsNode();
$$->addChild($1);
$$->addChildren($2);
}
;
transform_block_item: transform_block { $$ = $1; }
| shape { $$ = $1; }
| shape_definition { $$ = $1; }
;
union: UNION LCURLY bool_items RCURLY { union: UNION LCURLY bool_items RCURLY {
$$ = new UnionNode(); $$ = new UnionNode();
$$->addChildren($3); $$->addChildren($3);
} }
; ;
vector2: LESS number COMMA number GREATER { vector2: LESS expression COMMA expression GREATER {
refptr<Vector> vec = $$ = new VectorNode($2, $4, new NumberNode(0.0));
new Vector($2->getNumber(), $4->getNumber(), 0.0);
$$ = new VectorNode(vec);
} }
; ;
vector3: LESS number COMMA number COMMA number GREATER { vector3: LESS expression COMMA expression COMMA expression GREATER {
refptr<Vector> vec = $$ = new VectorNode($2, $4, $6);
new Vector($2->getNumber(), $4->getNumber(), $6->getNumber()); }
$$ = new VectorNode(vec); ;
expression: term { $$ = $1; }
| expression TIMES term { $$ = new BinOpNode('*', $1, $3); }
| expression DIVIDE term { $$ = new BinOpNode('/', $1, $3); }
| MINUS expression %prec UMINUS {
$$ = new BinOpNode('-', new NumberNode(0.0), $2);
}
| stmt_expression { $$ = $1; }
;
maybe_expression: /* empty */
| expression { $$ = $1; }
;
stmt_expression: assignment { $$ = $1; }
| local_assignment { $$ = $1; }
| local_decl { $$ = $1; }
;
bool_expression: expression LESS expression {
$$ = new BoolExpressionNode('<', $1, $3);
}
| expression GREATER expression {
$$ = new BoolExpressionNode('>', $1, $3);
}
| expression EQUALS expression {
$$ = new BoolExpressionNode('=', $1, $3);
}
| expression NOTEQUALS expression {
$$ = new BoolExpressionNode('n', $1, $3);
}
| NOT bool_expression {
$$ = new BoolExpressionNode('!', $2, NULL);
}
;
term: factor { $$ = $1; }
| term PLUS factor { $$ = new BinOpNode('+', $1, $3); }
| term MINUS factor { $$ = new BinOpNode('-', $1, $3); }
;
factor: number { $$ = $1; }
| VARREF { $$ = $1; }
| LPAREN expression RPAREN { $$ = $2; }
;
assignment: VARREF ASSIGN expression {
$$ = new AssignmentNode($1, $3);
}
;
local_assignment: LOCAL VARREF ASSIGN expression {
$$ = new LocalAssignmentNode($2, $4);
}
;
local_decl: LOCAL VARREF {
$$ = new LocalDeclNode($2);
}
;
for: FOR LPAREN maybe_expression SEMICOLON bool_expression SEMICOLON maybe_expression RPAREN LCURLY general_items RCURLY {
$$ = new ForNode($3, $5, $7);
$$->addChildren($10);
} }
; ;
%% %%
refptr<Node> parse(const char * fileName) refptr<Node> parse(const char * fileName, refptr<Scope> scope)
{ {
parser_scope = scope;
yyin = fopen(fileName, "r"); yyin = fopen(fileName, "r");
if (yyin == NULL) if (yyin == NULL)
{ {

View File

@ -125,6 +125,7 @@ class Shape
refptr<Material> m_material; refptr<Material> m_material;
}; };
typedef refptr<Shape> ShapeRef;
#endif #endif

73
util/Scope.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef SCOPE_H
#define SCOPE_H
#include <list>
#include <map>
#include <string>
class Scope
{
public:
Scope() { push(); }
bool contains(const std::string & key)
{
for (m_list_type::const_reverse_iterator it = m_list.rbegin();
it != m_list.rend();
it++)
{
if (it->find(key) != it->end())
{
return true;
}
}
return false;
}
double get(const std::string & key)
{
for (m_list_type::reverse_iterator it = m_list.rbegin();
it != m_list.rend();
it++)
{
if (it->find(key) != it->end())
{
return (*it)[key];
}
}
return 0.0;
}
void putLocal(const std::string & key, double val)
{
(*m_list.rbegin())[key] = val;
}
void putGlobal(const std::string & key, double val)
{
for (m_list_type::reverse_iterator it = m_list.rbegin();
it != m_list.rend();
it++)
{
if (it->find(key) != it->end())
{
(*it)[key] = val;
return;
}
}
putLocal(key, val);
}
void push()
{
m_list.push_back(std::map< std::string, double >());
}
void pop()
{
if (m_list.size() > 1)
{
m_list.pop_back();
}
}
protected:
typedef std::list< std::map< std::string, double > > m_list_type;
m_list_type m_list;
};
#endif