bin_PROGRAMS = lsystem3d
-lsystem3d_SOURCES = lsystem.cpp callbacks.cpp lindenmayersystem.cpp model.cpp \
- openglwindow.cpp turtle.cpp vector.cpp xmlstructure.cpp lsystemparameters.cpp \
- coordinate.cpp
+lsystem3d_SOURCES = lsystem.cpp lindenmayersystem.cpp model.cpp turtle.cpp \
+ vector.cpp xmlstructure.cpp lsystemparameters.cpp coordinate.cpp lsystem3d.cpp \
+ renderingsurface.cpp gui.cpp color.cpp
# set the include path found by configure
-INCLUDES = `pkg-config libxml++-2.6 --cflags` $(all_includes)
+INCLUDES = `fox-config --cflags` `pkg-config libxml++-2.6 --cflags` \
+ $(all_includes)
# the library search path.
-lsystem3d_LDFLAGS = $(all_libraries) -lglui -lglut -lGLU -lGL `pkg-config \
- libxml++-2.6 --libs`
-noinst_HEADERS = callbacks.h lindenmayersystem.h model.h openglwindow.h \
- turtle.h vector.h xmlstructure.h lsystemparameters.h coordinate.h lsystem.xml
+lsystem3d_LDFLAGS = $(all_libraries) `pkg-config libxml++-2.6 --libs` \
+ `fox-config --libs`
+noinst_HEADERS = lindenmayersystem.h model.h turtle.h vector.h xmlstructure.h \
+ lsystemparameters.h coordinate.h lsystem.xml lsystem3d.h renderingsurface.h gui.h color.h
+/**
+ * Set coordinate
+ * @param x the x-coordinate
+ * @param y the y-coordinate
+ * @param z the z-coordinate
+ */
+void Coordinate::setXYZ(double x, double y, double z)
+{
+ _x = x;
+ _y = y;
+ _z = z;
+}
+
+
+
/**
* Get x-coordinate
* @return the x-coordinate
{
return _z;
}
-
-
-
-/**
- * Set coordinate
- * @param x the x-coordinate
- * @param y the y-coordinate
- * @param z the z-coordinate
- */
-void Coordinate::setXYZ(double x, double y, double z)
-{
- _x = x;
- _y = y;
- _z = z;
-}
class Coordinate
{
public:
+
/**
* Constructor
*/
*/
~Coordinate();
+ /**
+ * Set coordinate
+ * @param x the x-coordinate
+ * @param y the y-coordinate
+ * @param z the z-coordinate
+ */
+ void setXYZ(double x, double y, double z);
+
/**
* Get x-coordinate
* @return the x-coordinate
* @return the z-coordinate
*/
double getZ();
-
- /**
- * Set coordinate
- * @param x the x-coordinate
- * @param y the y-coordinate
- * @param z the z-coordinate
- */
- void setXYZ(double x, double y, double z);
protected:
#include <cmath>
#include <map>
-#include <iostream>
#include <string>
#include "lindenmayersystem.h"
#include "model.h"
#include "turtle.h"
-using namespace std;
-
/**
* Constructor
- * @param model the model for generation
+ * @param model empty model
*/
LindenmayerSystem::LindenmayerSystem(Model *model)
{
_model = model;
_turtle = new Turtle(model);
- _axiom.clear();
- _rules.clear();
- _numIterations = 0;
+ clear();
}
+/**
+ * Clear all parameters
+ */
+void LindenmayerSystem::clear()
+{
+ _axiom.clear();
+ _rules.clear();
+ _turtle->setAngle(0.0);
+ _numIterations = 0;
+
+ _turtle->reset();
+ _model->clear();
+}
+
+
+
+/**
+ * Generate L-system data
+ */
+void LindenmayerSystem::generate()
+{
+ // model session
+ _model->begin();
+ _model->setColorIndex(0);
+ recursiveWalk(_axiom, _numIterations);
+ _model->end();
+}
+
+
+
/**
* Set the initial rule (the axiom)
* @param axiom the axiom
+/**
+ * Set diameter of segment
+ * @param diameter the diameter
+ */
+void LindenmayerSystem::setDiameter(double diameter)
+{
+ _model->setDiameter(diameter);
+}
+
+
+
+/**
+ * Set diameter factor
+ * @param diameterFactor the diameter factor
+ */
+void LindenmayerSystem::setDiameterFactor(double diameterFactor)
+{
+ _model->setDiameterFactor(diameterFactor);
+}
+
+
+
/**
* Get the initial rule (the axiom)
* @return the axiom
/**
- * Generate l-system data
+ * Get the generated model
+ * @return generated model
*/
-void LindenmayerSystem::generate()
+Model *LindenmayerSystem::getModel()
{
- _model->clear();
-
- recursiveWalk(_axiom, _numIterations);
-
- _turtle->reset();
+ return _model;
}
/**
- * Walk through the rule string for specified number of levels
- * @param rule the rule
- * @param level current iteration level
+ * Recursively apply the replacement rules
+ * @param rule rule
+ * @param level recursion level
*/
void LindenmayerSystem::recursiveWalk(string rule, int level)
{
- // Process every element in the rule string
+ // process every element in the rule string
for (int i = 0; i < rule.size(); i++)
{
switch (rule[i])
{
- // walk
+ // rule
case '@':
-
+
// ignore marker, i.e. the "@"
i++;
// recursion
- if (level == 0)
+ if (level > 0)
{
- // at lowest level, start rendering
+ char ruleName[] = {rule[i], '\0'};
+ recursiveWalk(_rules[ruleName], level - 1);
+ }
- _turtle->walk();
+ break;
+
+
+ // walk / rule
+ case 'F':
+
+ // replacement rule for 'F'?
+ if (_rules.count("F") != 0 && level > 0)
+ {
+ recursiveWalk(_rules["F"], level - 1);
}
else
{
- // more levels to go
-
- char ruleName[] = {rule[i], '\0'};
- recursiveWalk(_rules[ruleName], level - 1);
+ // no rule for "F"
+ _turtle->walk();
}
-
+
break;
break;
- // first vertex in a filled surface
+ // create a filled surface
case '{':
- _turtle->fenceInBegin();
+ _model->fillBegin();
break;
- // last vertex in a filled surface
+ // close a filled surface
case '}':
- _turtle->fenceInEnd();
+ _model->fillEnd();
break;
// one vertex in a filled surface
case 'f':
- _turtle->walk();
+ _turtle->fillWalk();
break;
// decrement diameter of segment
case '!':
- _turtle->decrementDiameter();
+ _model->decrementDiameter();
break;
- // unknown operation
- default :
+ // increment current index to color table
+ case '\'':
- // TODO: filter these out when preprocessing
- cerr << "Unknown operator in rule string:" << rule[i] << endl;
+ _model->nextColor();
+ break;
+
+
+ // decrement current index to color table
+ case '`':
+
+ _model->prevColor();
break;
}
}
/**
* Verify and preprocess one rule string
- * @param ruleOrAxiom the rule
+ * @param rule the rule
* @return the preprocessed rule
*/
-string LindenmayerSystem::verifyAndPreprocessRule(string ruleOrAxiom)
+string LindenmayerSystem::verifyAndPreprocessRule(string rule)
{
- // for now, simply put "@" before every rewriting operator
// TODO: verifying
string preprocessedRule;
// check every element in rule
- for (int i = 0; i < ruleOrAxiom.size(); i++)
+ for (int i = 0; i < rule.size(); i++)
{
- // TODO: remove the A-Z limit: use strings, not single chars
- if (ruleOrAxiom[i] >= 'A' && ruleOrAxiom[i] <= 'Z')
+ // TODO: allow strings as names
+ if (rule[i] >= 'A' && rule[i] <= 'Z' && rule[i] != 'F')
{
- // mark as rewriting operator
+ // add rule operator
preprocessedRule += '@';
}
- preprocessedRule += ruleOrAxiom[i];
+ preprocessedRule += rule[i];
}
return preprocessedRule;
/**
* Unpreprocess one rule string
- * @param ruleOrAxiom the rule
+ * @param rule the rule
* @return the unpreprocessed rule
*/
-string LindenmayerSystem::unpreprocessRule(string ruleOrAxiom)
+string LindenmayerSystem::unpreprocessRule(string rule)
{
string unpreprocessedRule;
// check every element in rule
- for (int i = 0; i < ruleOrAxiom.size(); i++)
+ for (int i = 0; i < rule.size(); i++)
{
- // ignore rewriting marker
- if (ruleOrAxiom[i] != '@')
+ // ignore rule operator
+ if (rule[i] != '@')
{
- unpreprocessedRule += ruleOrAxiom[i];
+ unpreprocessedRule += rule[i];
}
}
#include "model.h"
#include "turtle.h"
-using namespace std;
-
/**
class LindenmayerSystem
{
public:
+
/**
* Constructor
- * @param model the model for generation
+ * @param model empty model
*/
LindenmayerSystem(Model *model);
*/
~LindenmayerSystem();
+ /**
+ * Clear all parameters
+ */
+ void clear();
+
+ /**
+ * Generate L-system data
+ */
+ void generate();
+
/**
* Set the initial rule (the axiom)
* @param axiom the axiom
*/
void setNumIterations(int numIterations);
+ /**
+ * Set diameter of segment
+ * @param diameter the diameter
+ */
+ void setDiameter(double diameter);
+
+ /**
+ * Set diameter factor
+ * @param diameterFactor the diameter factor
+ */
+ void setDiameterFactor(double diameterFactor);
+
/**
* Get the initial rule (the axiom)
* @return the axiom
int getNumIterations();
/**
- * Generate l-system data
+ * Get the generated model
+ * @return generated model
*/
- void generate();
+ Model *getModel();
protected:
/**
- * Walk through the rule string for specified number of levels
- * @param rule the rule
- * @param level current iteration level
+ * Recursively apply the replacement rules
+ * @param rule rule
+ * @param level recursion level
*/
void recursiveWalk(string rule, int level);
/**
* Verify and preprocess one rule string
- * @param ruleOrAxiom the rule
+ * @param rule the rule
* @return the preprocessed rule
*/
- string verifyAndPreprocessRule(string ruleOrAxiom);
+ string verifyAndPreprocessRule(string rule);
/**
* Unpreprocess one rule string
- * @param ruleOrAxiom the rule
+ * @param rule the rule
* @return the unpreprocessed rule
*/
- string unpreprocessRule(string ruleOrAxiom);
+ string unpreprocessRule(string rule);
// Parameters
string _axiom;
- map<string,string> _rules; // TODO: use unsorted container?
+ map<string,string> _rules; // TODO: use unsorted container?
int _numIterations;
- Model *_model; // The model for generation
+ Model *_model; // The active model
Turtle *_turtle; // The rendering turtle
};
#include <cstdlib>
-#include <GL/freeglut.h>
-
-#include "openglwindow.h"
-
-
-OpenGLWindow *openglWindow = NULL;
+#include "lsystem3d.h"
int main(int argc, char *argv[])
{
- glutInit(&argc, argv);
-
- OpenGLWindow window;
+ LSystem3D lsystem3d(argc, argv);
return EXIT_SUCCESS;
<?xml version="1.0"?>
<lsystem>
- <axiom>A</axiom>
- <rule name="A">A/[!+A&A]/A</rule>
- <angle>30.0</angle>
- <iterations>4</iterations>
+ <axiom>P</axiom>
+ <rule name="E">FF</rule>
+ <rule name="I">FS[//&&L][//^^L]FS!</rule>
+ <rule name="L">[`{-f+ff+f-|-f+ff+f}]</rule>
+ <rule name="O">[&&&E'/W////W////W////W////W]</rule>
+ <rule name="P">I+[P+O]--//[--L]I[++L]-[PO]++PO</rule>
+ <rule name="S">SFS</rule>
+ <rule name="W">['^F][{&&&&-f+f|-f+f}]</rule>
+ <angle>18.0</angle>
+ <iterations>6</iterations>
</lsystem>
/**
* Load parameters from xml file
- * @param lsystem put parameters into this l-system
+ * @param lsystem put parameters into this L-system
* @param path path to xml file
*/
void LSystemParameters::load(LindenmayerSystem *lsystem, string path)
}
else
{
- cerr << "invalid lsystem" << endl;
+ cerr << "invalid L-system" << endl;
}
}
/**
* Save parameters to xml file
- * @param lsystem get parameters from this l-system
+ * @param lsystem get parameters from this L-system
* @param path path to xml file
*/
void LSystemParameters::save(LindenmayerSystem *lsystem, string path)
}
else
{
- cerr << "invalid lsystem" << endl;
+ cerr << "invalid L-system" << endl;
}
}
/**
- * Save and load a l-system specification
+ * Save and load a L-system specification
*/
class LSystemParameters : protected XMLStructure
{
/**
* Load parameters from xml file
- * @param lsystem put parameters into this l-system
+ * @param lsystem put parameters into this L-system
* @param path path to xml file
*/
void load(LindenmayerSystem *lsystem, string path);
/**
* Save parameters to xml file
- * @param lsystem get parameters from this l-system
+ * @param lsystem get parameters from this L-system
* @param path path to xml file
*/
void save(LindenmayerSystem *lsystem, string path);
+#include <vector>
+
#include "GL/gl.h"
#include "GL/glu.h"
+#include "color.h"
#include "model.h"
#include "vector.h"
*/
Model::Model()
{
- _displayList = glGenLists(1);
+ // default color table
+ Color brown(0.5, 0.2, 0.0); _colorTable.push_back(brown);
+ Color white(1.0, 1.0, 1.0); _colorTable.push_back(white);
+ Color green(0.0, 0.5, 0.0); _colorTable.push_back(green);
+
+ _displayList = 0;
+
+ clear();
}
/**
- * Connect two points
- * @param diameter diameter of segment
+ * Create a segment
* @param x1 x start point
* @param y1 y start point
* @param z1 z start point
* @param y2 y end point
* @param z2 z end point
*/
-void Model::segment(double diameter, double x1, double y1, double z1, double x2, double y2, double z2)
+void Model::segment(double x1, double y1, double z1, double x2, double y2, double z2)
{
- // wireframe
- //
- // glColor3f(1,1,1);
- // glBegin(GL_LINES);
- // glVertex3d(x1, y1, z1);
- // glVertex3d(x2, y2, z2);
- // glEnd();
-
-
-
- // solid
-
- // find rotation vector and angle of cylinder
+ // find rotation vector and angle
Vector initial(0.0, 1.0, 0.0); // initial rotation of cylinder
Vector desired(x2-x1, y2-y1, z2-z1); // desired rotation of cylinder
desired.normalize();
// rotation angle
- double angle = initial.getAngle(desired);
+ double rotationAngle = initial.getAngle(desired);
// rotation vector
- Vector crossProduct = initial.getCrossProduct(desired);
- crossProduct.normalize();
+ Vector rotationVector = initial.getCrossProduct(desired);
+ rotationVector.normalize();
// render the cylinder
- GLUquadric *quadric = gluNewQuadric();
+ static GLUquadric *quadric = gluNewQuadric();
- glColor3f(1.0, 0.5, 0.0);
-
glPushMatrix();
glTranslatef(x1, y1, z1);
- glRotatef(angle, crossProduct.getX(), crossProduct.getY(), crossProduct.getZ());
+ glRotatef(rotationAngle, rotationVector.getX(), rotationVector.getY(), rotationVector.getZ());
glRotatef(-90, 1, 0, 0);
- gluCylinder(quadric, diameter, diameter, 1.0, 6, 6);
+ gluCylinder(quadric, _diameter, _diameter, 1.0, 6, 6);
glPopMatrix();
}
/**
- * Draw model to screen
+ * Specify a vertex
+ * @param x x-coordinate
+ * @param y y-coordinate
+ * @param z z-coordinate
+ */
+void Model::vertex(double x, double y, double z)
+{
+ glVertex3d(x, y, z);
+}
+
+
+
+/**
+ * Specify a normal
+ * @param x x-coordinate
+ * @param y y-coordinate
+ * @param z z-coordinate
+ */
+void Model::normal(double x, double y, double z)
+{
+ glNormal3f(x, y, z);
+}
+
+
+
+/**
+ * Render to screen
*/
void Model::draw()
{
*/
void Model::clear()
{
- // TODO: not needed?
+ glDeleteLists(_displayList, 1);
+ _displayList = glGenLists(1);
+
+ setColorIndex(0);
+
+ _diameter = 0.1;
+ _diameterFactor = 0.8;
}
/**
- * Start recording of drawing operations
+ * Begin a modelling session
*/
void Model::begin()
{
/**
- * Stop recording of drawing operations
+ * End a modelling session
*/
void Model::end()
{
/**
- * Begin creation of a filled surface
+ * Begin creation of a filled polygon
*/
void Model::fillBegin()
{
- glColor3f(0.0, 0.5, 0.0);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
+
glBegin(GL_POLYGON);
}
/**
- * End creation of a filled surface
+ * End creation of a filled polygon
*/
void Model::fillEnd()
{
glEnd();
+
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
}
/**
- * Create one vertex in the filled surface
- * @param x x-coordinate
- * @param y y-coordinate
- * @param z z-coordinate
+ * Increment current index to color table
*/
-void Model::point(double x, double y, double z)
+void Model::nextColor()
{
- glVertex3d(x, y, z);
+ setColorIndex(_colorIndex + 1);
+}
+
+
+
+/**
+ * Decrement current index to color table
+ */
+void Model::prevColor()
+{
+ setColorIndex(_colorIndex - 1);
+}
+
+
+
+/**
+ * Decrement diameter of segment
+ */
+void Model::decrementDiameter()
+{
+ _diameter *= _diameterFactor;
+}
+
+
+
+/**
+ * Set current color index
+ * @param index the color index
+ */
+void Model::setColorIndex(int index)
+{
+ // keep in range
+
+ if (index < 0)
+ {
+ _colorIndex = _colorTable.size() - 1;
+ }
+ else if (index > (_colorTable.size() - 1))
+ {
+ _colorIndex = 0;
+ }
+ else
+ {
+ _colorIndex = index;
+ }
+
+
+ // set color
+
+ Color color = _colorTable[_colorIndex];
+ double r = color.getR();
+ double g = color.getG();
+ double b = color.getB();
+
+ glColor3f(r, g, b);
+}
+
+
+
+/**
+ * Set current diameter of segment
+ * @param diameter the diameter
+ */
+void Model::setDiameter(double diameter)
+{
+ _diameter = diameter;
+}
+
+
+
+/**
+ * Set diameter factor
+ * @param diameter the diameter factor
+ */
+void Model::setDiameterFactor(double diameterFactor)
+{
+ _diameterFactor = diameterFactor;
+}
+
+
+
+/**
+ * Get current color index
+ * @return color index
+ */
+int Model::getColorIndex()
+{
+ return _colorIndex;
+}
+
+
+
+/**
+ * Get current diameter of segment
+ * @return diameter of segment
+ */
+double Model::getDiameter()
+{
+ return _diameter;
}
#ifndef MODEL_H
#define MODEL_H
+#include <vector>
+
#include <GL/gl.h>
+#include "color.h"
+
+using namespace std;
+
/**
- * The generated l-system model
- * TODO: inheritance, i.e. Model<-OpenGLModel/WireModel/...?
+ * The L-system model
*/
class Model
{
~Model();
/**
- * Connect two points
- * @param diameter diameter of segment
+ * Create a segment
* @param x1 x start point
* @param y1 y start point
* @param z1 z start point
* @param y2 y end point
* @param z2 z end point
*/
- void segment(double diameter, double x1, double y1, double z1, double x2, double y2, double z2);
+ void segment(double x1, double y1, double z1, double x2, double y2, double z2);
+
+ /**
+ * Specify a vertex
+ * @param x x-coordinate
+ * @param y y-coordinate
+ * @param z z-coordinate
+ */
+ void vertex(double x, double y, double z);
+
+ /**
+ * Specify a normal
+ * @param x x-coordinate
+ * @param y y-coordinate
+ * @param z z-coordinate
+ */
+ void normal(double x, double y, double z);
/**
- * Draw model to screen
+ * Render to screen
*/
void draw();
void clear();
/**
- * Start recording of drawing operations
+ * Begin a modelling session
*/
void begin();
/**
- * Stop recording of drawing operations
+ * End a modelling session
*/
void end();
/**
- * Begin creation of a filled surface
+ * Begin creation of a filled polygon
*/
void fillBegin();
/**
- * End creation of a filled surface
+ * End creation of a filled polygon
*/
void fillEnd();
/**
- * Create one vertex in the filled surface
- * @param x x-coordinate
- * @param y y-coordinate
- * @param z z-coordinate
+ * Increment current index to color table
+ */
+ void nextColor();
+
+ /**
+ * Decrement current index to color table
+ */
+ void prevColor();
+
+ /**
+ * Decrement diameter of segment
+ */
+ void decrementDiameter();
+
+ /**
+ * Set current color index
+ * @param index the color index
+ */
+ void setColorIndex(int index);
+
+ /**
+ * Set current diameter of segment
+ * @param diameter the diameter
*/
- void point(double x, double y, double z);
+ void setDiameter(double diameter);
+
+ /**
+ * Set diameter factor
+ * @param diameter the diameter factor
+ */
+ void setDiameterFactor(double diameterFactor);
+
+ /**
+ * Get current color index
+ * @return color index
+ */
+ int getColorIndex();
+
+ /**
+ * Get current diameter of segment
+ * @return diameter of segment
+ */
+ double getDiameter();
protected:
- GLuint _displayList; // all drawing operations
+ GLuint _displayList; // All drawing operations
+
+ vector<Color> _colorTable; // Color table
+ int _colorIndex; // Current index to color table
+ double _diameter; // Current diameter of segment
+ double _diameterFactor; // Diameter factor // TODO: "Diameter factor"?
};
#include "turtle.h"
#include "vector.h"
+using namespace std;
+
/**
* Constructor
- * @param model render this model
+ * @param model create this model
*/
Turtle::Turtle(Model *model)
{
+ _model = model;
+
// initial position and orientation
reset();
// 90 degrees
_angle = M_PIl / 2.0;
-
- _model = model;
}
// move turtle to new position
_position.setXYZ(endX, endY, endZ);
- if (!_fenceMode)
- {
- // connect the points
- _model->segment(_diameter,
- startX, startY, startZ,
- endX, endY, endZ);
- }
- else
- {
- // part of a filled surface
- _model->point(endX, endY, endZ);
- }
+ // connect start and end point
+ _model->segment(startX, startY, startZ,
+ endX, endY, endZ);
+}
+
+
+
+/**
+ * Walk forward, creating a filled surface
+ * TODO: merge with walk() ?
+ */
+void Turtle::fillWalk()
+{
+ // end point
+ double destinationX = _position.getX() + _heading.getX();
+ double destinationY = _position.getY() + _heading.getY();
+ double destinationZ = _position.getZ() + _heading.getZ();
+
+ _model->normal(_up.getX(), _up.getY(), _up.getZ());
+
+ // move turtle to new position
+ _position.setXYZ(destinationX, destinationY, destinationZ);
+
+ // part of a filled polygon
+ _model->vertex(destinationX, destinationY, destinationZ);
}
_upStack.push(_up);
// diameter
- _diameterStack.push(_diameter);
+ double diameter = _model->getDiameter();
+ _diameterStack.push(diameter);
+
+ // color index
+ int colorIndex = _model->getColorIndex();
+ _colorIndexStack.push(colorIndex);
}
void Turtle::pop()
{
// position
- _position = _positionStack.top(); _positionStack.pop();
+ _position = _positionStack.top(); _positionStack.pop();
// orientation
- _heading = _headingStack.top(); _headingStack.pop();
- _left = _leftStack.top(); _leftStack.pop();
- _up = _upStack.top(); _upStack.pop();
+ _heading = _headingStack.top(); _headingStack.pop();
+ _left = _leftStack.top(); _leftStack.pop();
+ _up = _upStack.top(); _upStack.pop();
// diameter
- _diameter = _diameterStack.top(); _diameterStack.pop();
+ double diameter = _diameterStack.top(); _diameterStack.pop();
+ _model->setDiameter(diameter);
+
+ // color index
+ int colorIndex = _colorIndexStack.top(); _colorIndexStack.pop();
+ _model->setColorIndex(colorIndex);
}
* Reset to default state
*/
void Turtle::reset()
-{
- _diameter = 0.1;
-
- _fenceMode = false;
-
-
+{
// put turtle at (0,0,0), head upwards, back towards camera
_position.setXYZ(0.0, 0.0, 0.0);
_heading.setXYZ(0.0, 1.0, 0.0);
_left.setXYZ(1.0, 0.0, 0.0);
_up.setXYZ(0.0, 0.0, 1.0);
-}
-
-
-
-/**
- * Decrement diameter of segment
- */
-void Turtle::decrementDiameter()
-{
- // TODO: dynamic value...
- _diameter *= 0.8;
-}
-
-
-
-/**
- * Begin creation of a filled surface
- */
-void Turtle::fenceInBegin()
-{
- _fenceMode = true;
- _model->fillBegin();
- _model->point(_position.getX(), _position.getY(), _position.getZ());
-}
-
-
-
-/**
- * End creation of a filled surface
- */
-void Turtle::fenceInEnd()
-{
- _model->fillEnd();
- _fenceMode = false;
+ // empty the stacks
+ _positionStack = stack<Coordinate>();
+ _headingStack = stack<Vector>();
+ _leftStack = stack<Vector>();
+ _upStack = stack<Vector>();
+ _diameterStack = stack<double>();
+ _colorIndexStack = stack<int>();
}
/**
- * The model renderer
+ * The model creator
*/
class Turtle
{
public:
/**
* Constructor
- * @param model render this model
+ * @param model create this model
*/
Turtle(Model *model);
*/
void walk();
+ /**
+ * Walk forward, creating a filled surface
+ */
+ void fillWalk();
+
/**
* Save current state to stack
*/
*/
void reset();
- /**
- * Decrement diameter of segment
- */
- void decrementDiameter();
-
- /**
- * Begin creation of a filled surface
- */
- void fenceInBegin();
-
- /**
- * End creation of a filled surface
- */
- void fenceInEnd();
-
/**
* Set turn/pitch/roll angle
* @param angle the angle, in radians
protected:
- Coordinate _position; // current position
+ Coordinate _position; // Current position
- Vector _heading; // forward pointing vector
- Vector _left; // left pointing vector
- Vector _up; // up pointing vector
+ Vector _heading; // Forward pointing vector
+ Vector _left; // Left pointing vector
+ Vector _up; // Up pointing vector
- double _angle; // turn/pitch/roll angle
- double _diameter; // diameter of segment
- bool _fenceMode; // create filled surface?
+ double _angle; // Turn/pitch/roll angle, in radians
- stack<Coordinate> _positionStack; // positions in stack
- stack<Vector> _headingStack; // heading vectors in stack
- stack<Vector> _leftStack; // left vectors in stack
- stack<Vector> _upStack; // up vectors in stack
- stack<double> _diameterStack; // diameters in stack
+ stack<Coordinate> _positionStack; // Positions in stack
+ stack<Vector> _headingStack; // Heading vectors in stack
+ stack<Vector> _leftStack; // Left vectors in stack
+ stack<Vector> _upStack; // Up vectors in stack
+ stack<double> _diameterStack; // Diameters in stack
+ stack<int> _colorIndexStack; // Colors indices in stack
- Model *_model; // the rendered model
+ Model *_model; // The created model
};
/**
- * Get scalar product of the vectors
+ * Get scalar product of two vectors
* @param vector arbitrary vector
* @return the scalar product
*/
/**
- * Get cross product of the vectors
+ * Get cross product of two vectors
* @param vector arbitrary vector
* @return the cross product
*/
/**
- * Get angle between the vectors
+ * Get angle between two vectors
* @param vector the second (normalized) vector
* @return the angle, in degrees
*/
void normalize();
/**
- * Get scalar product of the vectors
+ * Get scalar product of two vectors
* @param vector arbitrary vector
* @return the scalar product
*/
double getScalarProduct(Vector vector);
/**
- * Get cross product of the vectors
+ * Get cross product of two vectors
* @param vector arbitrary vector
* @return the cross product
*/
Vector getCrossProduct(Vector vector);
/**
- * Get angle between the vectors
+ * Get angle between two vectors
* @param vector the second (normalized) vector
* @return the angle, in degrees
*/
_rootElement = NULL;
_activeElement = NULL;
_activeDocument = NULL;
- _activeChildInList = NULL;
+ _activeChildInList = (xmlpp::Node::NodeList::iterator)NULL;
}