--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include <unistd.h>
+
+#include <GL/freeglut.h>
+
+#include "callbacks.h"
+#include "openglwindow.h"
+
+extern OpenGLWindow *openglWindow;
+
+
+
+// GLUT callback functions
+// -----------------------
+
+/**
+ * Key press
+ * @param key the key
+ * @param x mouse x-coordinate
+ * @param y mouse y-coordinate
+ */
+void glutKeyboardCB(unsigned char key, int x, int y)
+{
+ switch (key)
+ {
+ // quit
+ case 27: // escape key
+ glutLeaveMainLoop();
+ break;
+
+ // zoom in
+ case '+':
+ openglWindow->zoomIn();
+ break;
+
+ // zoom out
+ case '-':
+ openglWindow->zoomOut();
+ break;
+
+ // rotate around the y-axis
+ case 'y':
+ case 'Y':
+ openglWindow->rotateY();
+
+ default:
+ break;
+ }
+}
+
+
+
+/**
+ * Special key press
+ * @param key the key
+ * @param x mouse x-coordinate
+ * @param y mouse y-coordinate
+ */
+void glutSpecialCB(int key, int x, int y)
+{
+ switch (key)
+ {
+ // move camera left
+ case GLUT_KEY_LEFT:
+ openglWindow->left();
+ break;
+
+ // move camera right
+ case GLUT_KEY_RIGHT:
+ openglWindow->right();
+ break;
+
+ // move camera up
+ case GLUT_KEY_UP:
+ openglWindow->up();
+ break;
+
+ // move camera down
+ case GLUT_KEY_DOWN:
+ openglWindow->down();
+ break;
+
+ // move camera forth
+ case GLUT_KEY_PAGE_UP:
+ openglWindow->forth();
+ break;
+
+ // move camera back
+ case GLUT_KEY_PAGE_DOWN:
+ openglWindow->back();
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+/**
+ * Redraw of screen
+ */
+void glutDisplayCB()
+{
+ openglWindow->draw();
+}
+
+
+
+/**
+ * Idling
+ */
+void glutIdleCB()
+{
+ // spare some cpu cycles
+ usleep(1);
+}
+
+
+
+// GLUI callback functions
+// -----------------------
+
+/**
+ * Angle changes
+ * @param id not used
+ */
+void gluiSpinnerAngleCB(int id)
+{
+ // regenerate and draw l-system only if "live mode" is enabled
+
+ if (openglWindow->liveActivated())
+ {
+ openglWindow->generate();
+ glutPostRedisplay();
+ }
+}
+
+
+
+/**
+ * Reset button pressed
+ * @param id not used
+ */
+void gluiButtonResetCB(int id)
+{
+ // place camera at initial position
+ openglWindow->defaultView();
+}
+
+
+
+/**
+ * Generate button pressed
+ * @param id not used
+ */
+void gluiButtonGenerateCB(int id)
+{
+ openglWindow->generate();
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef CALLBACKS_H
+#define CALLBACKS_H
+
+
+
+// GLUT callback functions
+// -----------------------
+
+/**
+ * Key press
+ * @param key the key
+ * @param x mouse x-coordinate
+ * @param y mouse y-coordinate
+ */
+void glutKeyboardCB(unsigned char key, int x, int y);
+
+/**
+ * Special key press
+ * @param key the key
+ * @param x mouse x-coordinate
+ * @param y mouse y-coordinate
+ */
+void glutSpecialCB(int key, int x, int y);
+
+/**
+ * Redraw of screen
+ */
+void glutDisplayCB();
+
+/**
+ * Idling
+ */
+void glutIdleCB();
+
+
+
+// GLUI callback functions
+// -----------------------
+
+/**
+ * Angle changes
+ * @param id not used
+ */
+void gluiSpinnerAngleCB(int id);
+
+/**
+ * Reset button pressed
+ * @param id not used
+ */
+void gluiButtonResetCB(int id);
+
+/**
+ * Generate button pressed
+ * @param id not used
+ */
+void gluiButtonGenerateCB(int id);
+
+
+
+#endif
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include "coordinate.h"
+
+
+
+/**
+ * Constructor
+ */
+Coordinate::Coordinate()
+{
+ setXYZ(0.0, 0.0, 0.0);
+}
+
+
+
+/**
+ * Destructor
+ */
+Coordinate::~Coordinate()
+{
+}
+
+
+
+/**
+ * Get x-coordinate
+ * @return the x-coordinate
+ */
+double Coordinate::getX()
+{
+ return _x;
+}
+
+
+
+/**
+ * Get y-coordinate
+ * @return the y-coordinate
+ */
+double Coordinate::getY()
+{
+ return _y;
+}
+
+
+
+/**
+ * Get z-coordinate
+ * @return the z-coordinate
+ */
+double Coordinate::getZ()
+{
+ 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;
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef COORDINATE_H
+#define COORDINATE_H
+
+
+
+/**
+ * 3d coordinate
+ */
+class Coordinate
+{
+public:
+ /**
+ * Constructor
+ */
+ Coordinate();
+
+ /**
+ * Destructor
+ */
+ ~Coordinate();
+
+ /**
+ * Get x-coordinate
+ * @return the x-coordinate
+ */
+ double getX();
+
+ /**
+ * Get y-coordinate
+ * @return the y-coordinate
+ */
+ double getY();
+
+ /**
+ * Get z-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:
+
+ double _x, _y, _z;
+};
+
+
+
+#endif
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#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
+ */
+LindenmayerSystem::LindenmayerSystem(Model *model)
+{
+ _model = model;
+ _turtle = new Turtle(model);
+
+ _axiom.clear();
+ _rules.clear();
+ _numIterations = 0;
+}
+
+
+
+/**
+ * Destructor
+ */
+LindenmayerSystem::~LindenmayerSystem()
+{
+ delete _turtle;
+}
+
+
+
+/**
+ * Set the initial rule (the axiom)
+ * @param axiom the axiom
+ */
+void LindenmayerSystem::setAxiom(string axiom)
+{
+ _axiom = verifyAndPreprocessRule(axiom);
+}
+
+
+
+/**
+ * Set one rule
+ * @param name rule name
+ * @param rule the rule
+ */
+void LindenmayerSystem::setRule(string name, string rule)
+{
+ _rules[name] = verifyAndPreprocessRule(rule);
+}
+
+
+
+/**
+ * Set the turn/pitch/roll angle
+ * @param degrees the angle, in degrees
+ */
+void LindenmayerSystem::setAngle(double degrees)
+{
+ // convert from degrees to radians
+ double radians = (degrees / 360.0) * (2.0 * M_PIl);
+
+ _turtle->setAngle(radians);
+}
+
+
+
+/**
+ * Set the number of iterations
+ * @param numIterations number of iterations
+ */
+void LindenmayerSystem::setNumIterations(int numIterations)
+{
+ _numIterations = numIterations;
+}
+
+
+
+/**
+ * Get the initial rule (the axiom)
+ * @return the axiom
+ */
+string LindenmayerSystem::getAxiom()
+{
+ return unpreprocessRule(_axiom);
+}
+
+
+
+/**
+ * Get all rules
+ * @return the rules
+ */
+map<string,string> LindenmayerSystem::getRules()
+{
+ map<string,string> theUnpreprocessedRules;
+
+ // unpreprocess all rules
+ map<string,string>::iterator currentRule;
+ for (currentRule = _rules.begin(); currentRule != _rules.end(); currentRule++)
+ {
+ theUnpreprocessedRules[currentRule->first] = unpreprocessRule(currentRule->second);
+ }
+
+ return theUnpreprocessedRules;
+}
+
+
+
+/**
+ * Get the turn/pitch/roll angle
+ * @return the angle, in degrees
+ */
+double LindenmayerSystem::getAngle()
+{
+ double radians = _turtle->getAngle();
+
+ // convert from radians to degrees
+ double degrees = 360.0 * (radians / (2.0 * M_PIl));
+
+ return degrees;
+}
+
+
+
+/**
+ * Get the number of iterations
+ * @return number of iterations
+ */
+int LindenmayerSystem::getNumIterations()
+{
+ return _numIterations;
+}
+
+
+
+/**
+ * Generate l-system data
+ */
+void LindenmayerSystem::generate()
+{
+ _model->clear();
+
+ recursiveWalk(_axiom, _numIterations);
+
+ _turtle->reset();
+}
+
+
+
+/**
+ * Walk through the rule string for specified number of levels
+ * @param rule the rule
+ * @param level current iteration level
+ */
+void LindenmayerSystem::recursiveWalk(string rule, int level)
+{
+ // Process every element in the rule string
+ for (int i = 0; i < rule.size(); i++)
+ {
+ switch (rule[i])
+ {
+ // walk
+ case '@':
+
+ // ignore marker, i.e. the "@"
+ i++;
+
+ // recursion
+ if (level == 0)
+ {
+ // at lowest level, start rendering
+
+ _turtle->walk();
+ }
+ else
+ {
+ // more levels to go
+
+ char ruleName[] = {rule[i], '\0'};
+ recursiveWalk(_rules[ruleName], level - 1);
+ }
+
+ break;
+
+
+ // turn left
+ case '+':
+
+ _turtle->turnLeft();
+ break;
+
+
+ // turn right
+ case '-':
+
+ _turtle->turnRight();
+ break;
+
+
+ // pitch down
+ case '&':
+
+ _turtle->pitchDown();
+ break;
+
+
+ // pitch up
+ case '^':
+
+ _turtle->pitchUp();
+ break;
+
+
+ // roll left
+ case '\\':
+
+ _turtle->rollLeft();
+ break;
+
+
+ // roll right
+ case '/':
+
+ _turtle->rollRight();
+ break;
+
+
+ // turn around 180 degrees
+ case '|':
+
+ _turtle->turnAround();
+ break;
+
+
+ // save state to stack
+ case '[':
+
+ _turtle->push();
+ break;
+
+
+ // restore state from stack
+ case ']':
+
+ _turtle->pop();
+ break;
+
+
+ // first vertex in a filled surface
+ case '{':
+
+ _turtle->fenceInBegin();
+ break;
+
+
+ // last vertex in a filled surface
+ case '}':
+
+ _turtle->fenceInEnd();
+ break;
+
+
+ // one vertex in a filled surface
+ case 'f':
+
+ _turtle->walk();
+ break;
+
+
+ // decrement diameter of segment
+ case '!':
+
+ _turtle->decrementDiameter();
+ break;
+
+
+ // unknown operation
+ default :
+
+ // TODO: filter these out when preprocessing
+ cerr << "Unknown operator in rule string:" << rule[i] << endl;
+ break;
+ }
+ }
+}
+
+
+
+/**
+ * Verify and preprocess one rule string
+ * @param ruleOrAxiom the rule
+ * @return the preprocessed rule
+ */
+string LindenmayerSystem::verifyAndPreprocessRule(string ruleOrAxiom)
+{
+ // 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++)
+ {
+ // TODO: remove the A-Z limit: use strings, not single chars
+ if (ruleOrAxiom[i] >= 'A' && ruleOrAxiom[i] <= 'Z')
+ {
+ // mark as rewriting operator
+ preprocessedRule += '@';
+ }
+ preprocessedRule += ruleOrAxiom[i];
+ }
+
+ return preprocessedRule;
+}
+
+
+
+/**
+ * Unpreprocess one rule string
+ * @param ruleOrAxiom the rule
+ * @return the unpreprocessed rule
+ */
+string LindenmayerSystem::unpreprocessRule(string ruleOrAxiom)
+{
+ string unpreprocessedRule;
+
+ // check every element in rule
+ for (int i = 0; i < ruleOrAxiom.size(); i++)
+ {
+ // ignore rewriting marker
+ if (ruleOrAxiom[i] != '@')
+ {
+ unpreprocessedRule += ruleOrAxiom[i];
+ }
+ }
+
+ return unpreprocessedRule;
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef LINDENMAYERSYSTEM_H
+#define LINDENMAYERSYSTEM_H
+
+#include <map>
+#include <string>
+
+#include "model.h"
+#include "turtle.h"
+
+using namespace std;
+
+
+
+/**
+ * Lindenmayer System
+ */
+class LindenmayerSystem
+{
+public:
+ /**
+ * Constructor
+ * @param model the model for generation
+ */
+ LindenmayerSystem(Model *model);
+
+ /**
+ * Destructor
+ */
+ ~LindenmayerSystem();
+
+ /**
+ * Set the initial rule (the axiom)
+ * @param axiom the axiom
+ */
+ void setAxiom(string axiom);
+
+ /**
+ * Set one rule
+ * @param name rule name
+ * @param rule the rule
+ */
+ void setRule(string name, string rule);
+
+ /**
+ * Set the turn/pitch/roll angle
+ * @param degrees the angle, in degrees
+ */
+ void setAngle(double degrees);
+
+ /**
+ * Set the number of iterations
+ * @param numIterations number of iterations
+ */
+ void setNumIterations(int numIterations);
+
+ /**
+ * Get the initial rule (the axiom)
+ * @return the axiom
+ */
+ string getAxiom();
+
+ /**
+ * Get all rules
+ * @return the rules
+ */
+ map<string,string> getRules();
+
+ /**
+ * Get the turn/pitch/roll angle
+ * @return the angle, in degrees
+ */
+ double getAngle();
+
+ /**
+ * Get the number of iterations
+ * @return number of iterations
+ */
+ int getNumIterations();
+
+ /**
+ * Generate l-system data
+ */
+ void generate();
+
+protected:
+
+ /**
+ * Walk through the rule string for specified number of levels
+ * @param rule the rule
+ * @param level current iteration level
+ */
+ void recursiveWalk(string rule, int level);
+
+ /**
+ * Verify and preprocess one rule string
+ * @param ruleOrAxiom the rule
+ * @return the preprocessed rule
+ */
+ string verifyAndPreprocessRule(string ruleOrAxiom);
+
+ /**
+ * Unpreprocess one rule string
+ * @param ruleOrAxiom the rule
+ * @return the unpreprocessed rule
+ */
+ string unpreprocessRule(string ruleOrAxiom);
+
+ // Parameters
+ string _axiom;
+ map<string,string> _rules; // TODO: use unsorted container?
+ int _numIterations;
+
+ Model *_model; // The model for generation
+ Turtle *_turtle; // The rendering turtle
+};
+
+
+
+#endif
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cstdlib>
+
+#include <GL/freeglut.h>
+
+#include "openglwindow.h"
+
+
+OpenGLWindow *openglWindow = NULL;
+
+
+
+int main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+
+ OpenGLWindow window;
+
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include <iostream>
+#include <string>
+
+#include "lsystemparameters.h"
+
+using namespace std;
+
+
+
+/**
+ * Constructor
+ */
+LSystemParameters::LSystemParameters()
+{
+}
+
+
+
+/**
+ * Destructor
+ */
+LSystemParameters::~LSystemParameters()
+{
+}
+
+
+
+/**
+ * Load parameters from xml file
+ * @param lsystem put parameters into this l-system
+ * @param path path to xml file
+ */
+void LSystemParameters::load(LindenmayerSystem *lsystem, string path)
+{
+ if (lsystem)
+ {
+ try
+ {
+ // load
+ loadFromDisk(path);
+
+ // axiom
+ findChild("axiom");
+ lsystem->setAxiom(getString());
+
+ // rules
+ if (findChild("rule"))
+ {
+ do
+ {
+ lsystem->setRule(getAttribute("name"), getString());
+ } while (findNextChild());
+ }
+
+ // angle
+ findChild("angle");
+ lsystem->setAngle(getNumber());
+
+ // iterations
+ findChild("iterations");
+ lsystem->setNumIterations((int)getNumber());
+ }
+ catch (xmlpp::exception e)
+ {
+ cerr << "LSystemParameters::load(): " << e.what() << endl;
+ }
+ }
+ else
+ {
+ cerr << "invalid lsystem" << endl;
+ }
+}
+
+
+
+/**
+ * Save parameters to xml file
+ * @param lsystem get parameters from this l-system
+ * @param path path to xml file
+ */
+void LSystemParameters::save(LindenmayerSystem *lsystem, string path)
+{
+ if (lsystem && !lsystem->getAxiom().empty() && !lsystem->getRules().empty())
+ {
+ // new document with root node
+ createDocumentWithRoot("lsystem");
+
+ // axiom
+ addChildToRoot("axiom");
+ addString(lsystem->getAxiom());
+
+ // rules
+ map<string,string> rules = lsystem->getRules();
+ map<string,string>::iterator currentRule;
+ for (currentRule = rules.begin(); currentRule != rules.end(); currentRule++)
+ {
+ addChildToRoot("rule");
+ addString(currentRule->second);
+ addAttribute("name", currentRule->first);
+ }
+
+ // angle
+ addChildToRoot("angle");
+ addNumber(lsystem->getAngle());
+
+ // iterations
+ addChildToRoot("iterations");
+ addNumber(lsystem->getNumIterations());
+
+ // save
+ saveToDisk(path);
+ }
+ else
+ {
+ cerr << "invalid lsystem" << endl;
+ }
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef LSYSTEMPARAMETERS_H
+#define LSYSTEMPARAMETERS_H
+
+#include <string>
+
+#include "lindenmayersystem.h"
+#include "xmlstructure.h"
+
+using namespace std;
+
+
+
+/**
+ * Save and load a l-system specification
+ */
+class LSystemParameters : protected XMLStructure
+{
+public:
+ /**
+ * Constructor
+ */
+ LSystemParameters();
+
+ /**
+ * Destructor
+ */
+ ~LSystemParameters();
+
+ /**
+ * Load parameters from xml file
+ * @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 path path to xml file
+ */
+ void save(LindenmayerSystem *lsystem, string path);
+};
+
+
+
+#endif
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include "GL/gl.h"
+#include "GL/glu.h"
+
+#include "model.h"
+#include "vector.h"
+
+
+
+/**
+ * Constructor
+ */
+Model::Model()
+{
+ _displayList = glGenLists(1);
+}
+
+
+
+/**
+ * Destructor
+ */
+Model::~Model()
+{
+ glDeleteLists(_displayList, 1);
+}
+
+
+
+/**
+ * Connect two points
+ * @param diameter diameter of segment
+ * @param x1 x start point
+ * @param y1 y start point
+ * @param z1 z start point
+ * @param x2 x end 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)
+{
+ // 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
+
+ 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);
+
+ // rotation vector
+ Vector crossProduct = initial.getCrossProduct(desired);
+ crossProduct.normalize();
+
+
+ // render the cylinder
+
+ GLUquadric *quadric = gluNewQuadric();
+
+ glColor3f(1.0, 0.5, 0.0);
+
+ glPushMatrix();
+ glTranslatef(x1, y1, z1);
+ glRotatef(angle, crossProduct.getX(), crossProduct.getY(), crossProduct.getZ());
+ glRotatef(-90, 1, 0, 0);
+
+ gluCylinder(quadric, diameter, diameter, 1.0, 6, 6);
+ glPopMatrix();
+}
+
+
+
+/**
+ * Draw model to screen
+ */
+void Model::draw()
+{
+ glCallList(_displayList);
+}
+
+
+
+/**
+ * Clear the model
+ */
+void Model::clear()
+{
+ // TODO: not needed?
+}
+
+
+
+/**
+ * Start recording of drawing operations
+ */
+void Model::begin()
+{
+ glNewList(_displayList, GL_COMPILE);
+}
+
+
+
+/**
+ * Stop recording of drawing operations
+ */
+void Model::end()
+{
+ glEndList();
+}
+
+
+
+/**
+ * Begin creation of a filled surface
+ */
+void Model::fillBegin()
+{
+ glColor3f(0.0, 0.5, 0.0);
+ glBegin(GL_POLYGON);
+}
+
+
+
+/**
+ * End creation of a filled surface
+ */
+void Model::fillEnd()
+{
+ glEnd();
+}
+
+
+
+/**
+ * Create one vertex in the filled surface
+ * @param x x-coordinate
+ * @param y y-coordinate
+ * @param z z-coordinate
+ */
+void Model::point(double x, double y, double z)
+{
+ glVertex3d(x, y, z);
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef MODEL_H
+#define MODEL_H
+
+#include <GL/gl.h>
+
+
+
+/**
+ * The generated l-system model
+ * TODO: inheritance, i.e. Model<-OpenGLModel/WireModel/...?
+ */
+class Model
+{
+public:
+ /**
+ * Constructor
+ */
+ Model();
+
+ /**
+ * Destructor
+ */
+ ~Model();
+
+ /**
+ * Connect two points
+ * @param diameter diameter of segment
+ * @param x1 x start point
+ * @param y1 y start point
+ * @param z1 z start point
+ * @param x2 x end 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);
+
+ /**
+ * Draw model to screen
+ */
+ void draw();
+
+ /**
+ * Clear the model
+ */
+ void clear();
+
+ /**
+ * Start recording of drawing operations
+ */
+ void begin();
+
+ /**
+ * Stop recording of drawing operations
+ */
+ void end();
+
+ /**
+ * Begin creation of a filled surface
+ */
+ void fillBegin();
+
+ /**
+ * End creation of a filled surface
+ */
+ void fillEnd();
+
+ /**
+ * Create one vertex in the filled surface
+ * @param x x-coordinate
+ * @param y y-coordinate
+ * @param z z-coordinate
+ */
+ void point(double x, double y, double z);
+
+protected:
+
+ GLuint _displayList; // all drawing operations
+};
+
+
+
+#endif
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include <string>
+
+#include <glui.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/freeglut.h>
+
+#include "callbacks.h"
+#include "lindenmayersystem.h"
+#include "lsystemparameters.h"
+#include "model.h"
+#include "openglwindow.h"
+
+using namespace std;
+
+extern OpenGLWindow *openglWindow;
+
+
+
+/**
+ * Constructor
+ */
+OpenGLWindow::OpenGLWindow()
+{
+ // misc init
+
+ openglWindow = this;
+ _busyGenerating = true;
+ lsystemParametersPath = "lsystem.xml";
+ defaultView();
+
+
+
+ // init GLUT & GLUI
+ // ----------------
+
+ // drawing window
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutInitWindowSize(800, 800);
+ int _window = glutCreateWindow("lsystem");
+
+ // return control after closing the window
+ glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, 1);
+
+ // register callbacks
+ glutKeyboardFunc(glutKeyboardCB);
+ glutSpecialFunc(glutSpecialCB);
+ glutDisplayFunc(glutDisplayCB);
+ GLUI_Master.set_glutIdleFunc(glutIdleCB);
+
+ // GUI window
+ _glui = GLUI_Master.create_glui("lsystem");
+
+ // model and l-system creation
+ _model = new Model;
+ _lsystem = new LindenmayerSystem(_model);
+
+ // load lsystem parameters
+ _lsystemParameters.load(_lsystem, lsystemParametersPath.c_str());
+
+
+
+ // create GLUI widgets
+ // -------------------
+
+ // axiom
+ _axiomEditText = _glui->add_edittext("Axiom", GLUI_EDITTEXT_TEXT);
+ _axiomEditText->set_text((char *)_lsystem->getAxiom().c_str());
+
+ // rules
+ // TODO: make dynamic!
+ GLUI_Panel *panel = _glui->add_panel("Rules", GLUI_PANEL_EMBOSSED);
+ _ruleEditTexts.push_back(_glui->add_edittext_to_panel(panel, "#1", GLUI_EDITTEXT_TEXT));
+ _ruleEditTexts.push_back(_glui->add_edittext_to_panel(panel, "#2", GLUI_EDITTEXT_TEXT));
+ _ruleEditTexts.push_back(_glui->add_edittext_to_panel(panel, "#3", GLUI_EDITTEXT_TEXT));
+ _ruleEditTexts.push_back(_glui->add_edittext_to_panel(panel, "#4", GLUI_EDITTEXT_TEXT));
+ _ruleEditTexts.push_back(_glui->add_edittext_to_panel(panel, "#5", GLUI_EDITTEXT_TEXT));
+ _ruleEditTexts[0]->set_w(200);
+ _ruleEditTexts[1]->set_w(200);
+ _ruleEditTexts[2]->set_w(200);
+ _ruleEditTexts[3]->set_w(200);
+ _ruleEditTexts[4]->set_w(200);
+
+ // sync gui and l-system
+ map<string,string> rules = _lsystem->getRules();
+ map<string,string>::iterator currentRule;
+ int i = 0;
+ for (currentRule = rules.begin(); currentRule != rules.end(); currentRule++)
+ {
+ string rule = currentRule->first + "=" + currentRule->second;
+ // TODO: bounds?
+ _ruleEditTexts[i++]->set_text((char *)rule.c_str());
+ }
+
+ // angle
+ _angleSpinner = _glui->add_spinner("Angle", GLUI_SPINNER_FLOAT, NULL, -1, (GLUI_Update_CB)gluiSpinnerAngleCB);
+ _angleSpinner->set_float_val(_lsystem->getAngle());
+ _angleSpinner->set_speed(1.0);
+
+ // iterations
+ _iterationsSpinner = _glui->add_spinner("Iterations", GLUI_SPINNER_INT);
+ _iterationsSpinner->set_int_val(_lsystem->getNumIterations());
+
+
+ _glui->add_separator();
+
+
+ // live update
+ _liveUpdates = 1;
+ _liveCheckbox = _glui->add_checkbox("Live update", &_liveUpdates);
+
+ // reset
+ _glui->add_button("Reset view", -1, (GLUI_Update_CB)gluiButtonResetCB);
+
+ // generate
+ _glui->add_button("Generate", -1, (GLUI_Update_CB)gluiButtonGenerateCB);
+
+
+ _glui->set_main_gfx_window(_window);
+
+
+
+
+ // init OpenGL view
+ // ----------------
+
+ // projection
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(65, 1, 1, 100);
+
+ // model view
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ gluLookAt(0.0, 0.0, 2.0,
+ 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+
+ glShadeModel(GL_SMOOTH);
+
+ // light
+ GLfloat lightPosition[] = {0.0, 0.0, 2.0, 0.0};
+ GLfloat white[] = {1.0, 1.0, 1.0, 1.0};
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+
+ glEnable(GL_COLOR_MATERIAL);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+
+ glutMainLoop();
+}
+
+
+
+/**
+ * Destructor
+ */
+OpenGLWindow::~OpenGLWindow()
+{
+ // save current l-system to disk
+ _lsystemParameters.save(_lsystem, lsystemParametersPath.c_str());
+
+ delete _lsystem;
+ delete _model;
+}
+
+
+
+/**
+ * Start generation of l-system data
+ */
+void OpenGLWindow::generate()
+{
+ _busyGenerating = true;
+
+ // read GLUI widgets and set corresponding l-system parameters
+
+ // axiom
+ char *axiom = _axiomEditText->get_text();
+ _lsystem->setAxiom(axiom);
+
+ // rules
+ vector<char *> rules;
+ rules.push_back(_ruleEditTexts[0]->get_text());
+ rules.push_back(_ruleEditTexts[1]->get_text());
+ rules.push_back(_ruleEditTexts[2]->get_text());
+ rules.push_back(_ruleEditTexts[3]->get_text());
+ rules.push_back(_ruleEditTexts[4]->get_text());
+
+ for (int i = 0; i < rules.size(); i++)
+ {
+ if (rules[i][0] != '\0')
+ {
+ // non-empty rule
+
+ // separate rule name from the actual rule
+ string ruleName(rules[i], 1);
+ string theRule(rules[i]+2);
+
+ _lsystem->setRule(ruleName, theRule);
+ }
+ }
+
+ // angle
+ float angle = _angleSpinner->get_float_val();
+ _lsystem->setAngle(angle);
+
+ // iterations
+ int iterations = _iterationsSpinner->get_int_val();
+ _lsystem->setNumIterations(iterations);
+
+
+ // start generation
+ _model->begin();
+ _lsystem->generate();
+ _model->end();
+
+ _busyGenerating = false;
+}
+
+
+
+/**
+ * Move camera left
+ */
+void OpenGLWindow::left()
+{
+ _xModel += 0.1;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Move camera right
+ */
+void OpenGLWindow::right()
+{
+ _xModel -= 0.1;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Move camera up
+ */
+void OpenGLWindow::up()
+{
+ _yModel -= 0.1;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Move camera down
+ */
+void OpenGLWindow::down()
+{
+ _yModel += 0.1;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Move camera forth
+ */
+void OpenGLWindow::forth()
+{
+ _zModel += 1;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Move camera back
+ */
+void OpenGLWindow::back()
+{
+ _zModel -= 1;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Zoom in
+ */
+void OpenGLWindow::zoomIn()
+{
+ _scaleModel *= 1.1;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Zoom out
+ */
+void OpenGLWindow::zoomOut()
+{
+ _scaleModel /= 1.1;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Rotate around y-axis
+ */
+void OpenGLWindow::rotateY()
+{
+ _yRotationModel = int(_yRotationModel + 5.0) % 360;
+ glutPostRedisplay();
+}
+
+
+
+/**
+ * Draw l-system model to screen
+ */
+void OpenGLWindow::draw()
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (!_busyGenerating)
+ {
+ // ready for rendering
+
+ glPushMatrix();
+ glTranslatef(_xModel, _yModel, _zModel);
+ glScalef(_scaleModel, _scaleModel, _scaleModel);
+ glRotatef(_yRotationModel, 0.0, 1.0, 0.0);
+
+ _model->draw();
+ glPopMatrix();
+ }
+
+ glutSwapBuffers();
+}
+
+
+
+/**
+ * Reset to default view
+ */
+void OpenGLWindow::defaultView()
+{
+ _xModel = _yModel = _zModel = 0.0;
+ _scaleModel = 1.0;
+ _yRotationModel = 0.0;
+}
+
+
+
+/**
+ * Check if live mode is activated
+ * @return true, if activated
+ */
+bool OpenGLWindow::liveActivated()
+{
+ return _liveUpdates;
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef OPENGLWINDOW_H
+#define OPENGLWINDOW_H
+
+#include <string>
+#include <vector>
+
+#include <glui.h>
+
+#include "lindenmayersystem.h"
+#include "lsystemparameters.h"
+#include "model.h"
+
+using namespace std;
+
+
+
+/**
+ * OpenGL drawing context
+ */
+class OpenGLWindow
+{
+public:
+ /**
+ * Constructor
+ */
+ OpenGLWindow();
+
+ /**
+ * Destructor
+ */
+ ~OpenGLWindow();
+
+ /**
+ * Start generation of l-system data
+ */
+ void generate();
+
+ /**
+ * Move camera left
+ */
+ void left();
+
+ /**
+ * Move camera right
+ */
+ void right();
+
+ /**
+ * Move camera up
+ */
+ void up();
+
+ /**
+ * Move camera down
+ */
+ void down();
+
+ /**
+ * Move camera forth
+ */
+ void forth();
+
+ /**
+ * Move camera back
+ */
+ void back();
+
+ /**
+ * Zoom in
+ */
+ void zoomIn();
+
+ /**
+ * Zoom out
+ */
+ void zoomOut();
+
+ /**
+ * Rotate around y-axis
+ */
+ void rotateY();
+
+ /**
+ * Draw l-system model to screen
+ */
+ void draw();
+
+ /**
+ * Reset to default view
+ */
+ void defaultView();
+
+ /**
+ * Check if live mode is activated
+ * @return true, if activated
+ */
+ bool liveActivated();
+
+protected:
+
+ // Model view
+ double _xModel, // model coordinate (starting point)
+ _yModel,
+ _zModel;
+ double _scaleModel; // model scale factor
+ double _yRotationModel; // model rotation
+
+ // L-system
+ LindenmayerSystem *_lsystem; // l-system generator
+ Model *_model; // the generated l-system model
+ LSystemParameters _lsystemParameters; // saves/loads l-system parameters from file
+ string lsystemParametersPath; // where to find the l-system rules
+
+ // Rendering window
+ int _window; // the rendering window
+ bool _busyGenerating; // currently generating?
+
+ // GUI window
+ GLUI *_glui; // the GUI window
+ GLUI_EditText *_axiomEditText; // axiom textbox
+ vector<GLUI_EditText *> _ruleEditTexts; // rule textboxes
+ GLUI_Spinner *_angleSpinner; // angle spinner
+ GLUI_Spinner *_iterationsSpinner; // iteration spinner
+ GLUI_Checkbox *_liveCheckbox; // live checkbox
+ int _liveUpdates; // status of live checkbox
+};
+
+
+
+#endif
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include <cmath>
+
+#include <stack>
+
+#include "coordinate.h"
+#include "model.h"
+#include "turtle.h"
+#include "vector.h"
+
+
+
+/**
+ * Constructor
+ * @param model render this model
+ */
+Turtle::Turtle(Model *model)
+{
+ // initial position and orientation
+ reset();
+
+ // 90 degrees
+ _angle = M_PIl / 2.0;
+
+ _model = model;
+}
+
+
+
+/**
+ * Destructor
+ */
+Turtle::~Turtle()
+{
+}
+
+
+
+/**
+ * Turn left
+ */
+void Turtle::turnLeft()
+{
+ // rotate around "up vector"
+ _heading.rotate(-_angle, _up);
+ _left.rotate(-_angle, _up);
+}
+
+
+
+/**
+ * Turn right
+ */
+void Turtle::turnRight()
+{
+ // rotate around "up vector"
+ _heading.rotate(_angle, _up);
+ _left.rotate(_angle, _up);
+}
+
+
+
+/**
+ * Pitch down
+ */
+void Turtle::pitchDown()
+{
+ // rotate around "left vector"
+ _heading.rotate(-_angle, _left);
+ _up.rotate(-_angle, _left);
+}
+
+
+
+/**
+ * Pitch up
+ */
+void Turtle::pitchUp()
+{
+ // rotate around "left vector"
+ _heading.rotate(_angle, _left);
+ _up.rotate(_angle, _left);
+}
+
+
+
+/**
+ * Roll left
+ */
+void Turtle::rollLeft()
+{
+ // rotate around "heading vector"
+ _left.rotate(_angle, _heading);
+ _up.rotate(_angle, _heading);
+}
+
+
+
+/**
+ * Roll right
+ */
+void Turtle::rollRight()
+{
+ // rotate around "heading vector"
+ _left.rotate(-_angle, _heading);
+ _up.rotate(-_angle, _heading);
+}
+
+
+
+/**
+ * Turn around
+ */
+void Turtle::turnAround()
+{
+ // rotate 180 degrees around "up vector"
+ _heading.rotate(M_PIl, _up);
+ _left.rotate(M_PIl, _up);
+}
+
+
+
+/**
+ * Walk forward
+ */
+void Turtle::walk()
+{
+ // start point
+ double startX = _position.getX();
+ double startY = _position.getY();
+ double startZ = _position.getZ();
+
+ // end point
+ double endX = startX + _heading.getX();
+ double endY = startY + _heading.getY();
+ double endZ = startZ + _heading.getZ();
+
+
+ // 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);
+ }
+}
+
+
+
+/**
+ * Save current state to stack
+ */
+void Turtle::push()
+{
+ // position
+ _positionStack.push(_position);
+
+ // orientation
+ _headingStack.push(_heading);
+ _leftStack.push(_left);
+ _upStack.push(_up);
+
+ // diameter
+ _diameterStack.push(_diameter);
+}
+
+
+
+/**
+ * Restore old state from stack
+ */
+void Turtle::pop()
+{
+ // position
+ _position = _positionStack.top(); _positionStack.pop();
+
+ // orientation
+ _heading = _headingStack.top(); _headingStack.pop();
+ _left = _leftStack.top(); _leftStack.pop();
+ _up = _upStack.top(); _upStack.pop();
+
+ // diameter
+ _diameter = _diameterStack.top(); _diameterStack.pop();
+}
+
+
+
+/**
+ * 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;
+}
+
+
+
+/**
+ * Set turn/pitch/roll angle
+ * @param angle the angle, in radians
+ */
+void Turtle::setAngle(double radians)
+{
+ _angle = radians;
+}
+
+
+
+/**
+ * Get turn/pitch/roll angle
+ * @return the angle, in radians
+ */
+double Turtle::getAngle()
+{
+ return _angle;
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef TURTLE_H
+#define TURTLE_H
+
+#include <stack>
+
+#include "coordinate.h"
+#include "model.h"
+#include "vector.h"
+
+using namespace std;
+
+
+
+/**
+ * The model renderer
+ */
+class Turtle
+{
+public:
+ /**
+ * Constructor
+ * @param model render this model
+ */
+ Turtle(Model *model);
+
+ /**
+ * Destructor
+ */
+ ~Turtle();
+
+ /**
+ * Turn left
+ */
+ void turnLeft();
+
+ /**
+ * Turn right
+ */
+ void turnRight();
+
+ /**
+ * Pitch down
+ */
+ void pitchDown();
+
+ /**
+ * Pitch up
+ */
+ void pitchUp();
+
+ /**
+ * Roll left
+ */
+ void rollLeft();
+
+ /**
+ * Roll right
+ */
+ void rollRight();
+
+ /**
+ * Turn around
+ */
+ void turnAround();
+
+ /**
+ * Walk forward
+ */
+ void walk();
+
+ /**
+ * Save current state to stack
+ */
+ void push();
+
+ /**
+ * Restore old state from stack
+ */
+ void pop();
+
+ /**
+ * Reset to default state
+ */
+ 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
+ */
+ void setAngle(double radians);
+
+ /**
+ * Get turn/pitch/roll angle
+ * @return the angle, in radians
+ */
+ double getAngle();
+
+protected:
+
+ Coordinate _position; // current position
+
+ 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?
+
+ 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
+
+ Model *_model; // the rendered model
+};
+
+
+
+#endif
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include <cmath>
+
+#include "vector.h"
+
+
+
+/**
+ * Constructor
+ * @param x the x-coordinate
+ * @param y the y-coordinate
+ * @param z the z-coordinate
+ */
+Vector::Vector(double x, double y, double z)
+{
+ setXYZ(x, y, z);
+}
+
+
+
+/**
+ * Destructor
+ */
+Vector::~Vector()
+{
+}
+
+
+
+/**
+ * Rotate around another vector
+ * @param angle rotation angle
+ * @param vector arbitrary vector to rotate around
+ */
+void Vector::rotate(double angle, Vector vector)
+{
+ double c = cos(angle);
+ double s = sin(angle);
+
+ double x =
+ _x * (vector._x * vector._x * (1.0 - c) + c) +
+ _y * (vector._x * vector._y * (1.0 - c) + vector._z * s) +
+ _z * (vector._x * vector._z * (1.0 - c) - vector._y * s);
+
+ double y =
+ _x * (vector._y * vector._x * (1.0 - c) - vector._z * s) +
+ _y * (vector._y * vector._y * (1.0 - c) + c) +
+ _z * (vector._y * vector._z * (1.0 - c) + vector._x * s);
+
+ double z =
+ _x * (vector._z * vector._x * (1.0 - c) + vector._y * s) +
+ _y * (vector._z * vector._y * (1.0 - c) - vector._x * s) +
+ _z * (vector._z * vector._z * (1.0 - c) + c);
+
+ _x = x;
+ _y = y;
+ _z = z;
+
+ // TODO: call it from outside?
+ normalize();
+}
+
+
+
+/**
+ * Normalize vector
+ */
+void Vector::normalize()
+{
+ double length = sqrt(_x * _x + _y * _y + _z * _z);
+
+ if (length != 0)
+ {
+ _x /= length;
+ _y /= length;
+ _z /= length;
+ }
+}
+
+
+
+/**
+ * Get scalar product of the vectors
+ * @param vector arbitrary vector
+ * @return the scalar product
+ */
+double Vector::getScalarProduct(Vector vector)
+{
+ double scalarProduct = getX() * vector.getX() +
+ getY() * vector.getY() +
+ getZ() * vector.getZ();
+
+ return scalarProduct;
+}
+
+
+
+/**
+ * Get cross product of the vectors
+ * @param vector arbitrary vector
+ * @return the cross product
+ */
+Vector Vector::getCrossProduct(Vector vector)
+{
+ Vector crossProduct(getY() * vector.getZ() - getZ() * vector.getY(),
+ getZ() * vector.getX() - getX() * vector.getZ(),
+ getX() * vector.getY() - getY() * vector.getX());
+
+ return crossProduct;
+}
+
+
+
+/**
+ * Get angle between the vectors
+ * @param vector the second (normalized) vector
+ * @return the angle, in degrees
+ */
+double Vector::getAngle(Vector vector)
+{
+ double scalarProduct = getScalarProduct(vector);
+ double angle = (acos(scalarProduct) / (M_PIl * 2.0)) * 360.0;
+
+ return angle;
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#include "coordinate.h"
+
+
+
+/**
+ * 3d vector
+ */
+class Vector : public Coordinate
+{
+public:
+ /**
+ * Constructor
+ * @param x the x-coordinate
+ * @param y the y-coordinate
+ * @param z the z-coordinate
+ */
+ Vector(double x = 0.0, double y = 1.0, double z = 0.0);
+
+ /**
+ * Destructor
+ */
+ ~Vector();
+
+ /**
+ * Rotate around another vector
+ * @param angle rotation angle
+ * @param vector arbitrary vector to rotate around
+ */
+ void rotate(double angle, Vector vector);
+
+ /**
+ * Normalize vector
+ */
+ void normalize();
+
+ /**
+ * Get scalar product of the vectors
+ * @param vector arbitrary vector
+ * @return the scalar product
+ */
+ double getScalarProduct(Vector vector);
+
+ /**
+ * Get cross product of the vectors
+ * @param vector arbitrary vector
+ * @return the cross product
+ */
+ Vector getCrossProduct(Vector vector);
+
+ /**
+ * Get angle between the vectors
+ * @param vector the second (normalized) vector
+ * @return the angle, in degrees
+ */
+ double getAngle(Vector vector);
+};
+
+
+
+#endif
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include <string>
+
+#include <libxml++/document.h>
+#include <libxml++/nodes/element.h>
+#include <libxml++/nodes/node.h>
+#include <libxml++/parsers/domparser.h>
+
+#include <glibmm/stringutils.h>
+
+#include "xmlstructure.h"
+
+using namespace std;
+
+
+
+/**
+ * Constructor
+ */
+XMLStructure::XMLStructure()
+{
+ _rootElement = NULL;
+ _activeElement = NULL;
+ _activeDocument = NULL;
+ _activeChildInList = NULL;
+}
+
+
+
+/**
+ * Destructor
+ */
+XMLStructure::~XMLStructure()
+{
+ delete _activeDocument;
+}
+
+
+
+/**
+ * Create new document with root node
+ * @param rootName name of root
+ */
+void XMLStructure::createDocumentWithRoot(string rootName)
+{
+ delete _activeDocument;
+ _activeDocument = new xmlpp::Document;
+
+ _rootElement = _activeDocument->create_root_node(rootName);
+}
+
+
+
+/**
+ * Add new child to root
+ * @param name name of child
+ */
+void XMLStructure::addChildToRoot(string name)
+{
+ _activeElement = _rootElement->add_child(name);
+}
+
+
+
+/**
+ * Add a string as content of current child
+ * @param text the text
+ */
+void XMLStructure::addString(string text)
+{
+ _activeElement->add_child_text(text);
+}
+
+
+
+/**
+ * Add a number as content of current child
+ * @param value the number
+ */
+void XMLStructure::addNumber(double value)
+{
+ // convert double -> string
+ string numberAsString = Glib::Ascii::dtostr(value);
+
+ addString(numberAsString);
+}
+
+
+
+/**
+ * Add attribute to current child
+ * @param name name of attribute
+ * @param value value of attribute
+ */
+void XMLStructure::addAttribute(string name, string value)
+{
+ _activeElement->set_attribute(name, value);
+}
+
+
+
+/**
+ * Save document to file
+ * @param path path to file
+ */
+void XMLStructure::saveToDisk(string path)
+{
+ _activeDocument->write_to_file_formatted(path);
+}
+
+
+
+/**
+ * Load document from file
+ * @param path path to file
+ */
+void XMLStructure::loadFromDisk(string path)
+{
+ // TODO: validate?
+ //_parser.set_validate(true);
+
+ _parser.parse_file(path);
+
+ _rootElement = _parser.get_document()->get_root_node();
+}
+
+
+
+/**
+ * Find all children with the specified name
+ * @param name name of children
+ * @return true if found, else false
+ */
+bool XMLStructure::findChild(string name)
+{
+ _activeList = _rootElement->get_children(name);
+ _activeChildInList = _activeList.begin();
+
+ return !_activeList.empty();
+}
+
+
+
+/**
+ * Find next child in current search result list
+ * @return true if found, else false
+ */
+bool XMLStructure::findNextChild()
+{
+ _activeChildInList++;
+
+ bool endOfList = false;
+
+ // last child?
+ if (_activeChildInList == _activeList.end())
+ {
+ _activeChildInList--;
+ endOfList = true;
+ }
+
+ return !endOfList;
+}
+
+
+
+/**
+ * Get content of current child as a string
+ * @return the string
+ */
+string XMLStructure::getString()
+{
+ // the child
+ xmlpp::Node *child = (*_activeChildInList)->get_children().front();
+
+ // its content
+ string content = dynamic_cast<xmlpp::ContentNode*>(child)->get_content();
+
+ return content;
+}
+
+
+
+/**
+ * Get content of current child as a number
+ * @return the number
+ */
+double XMLStructure::getNumber()
+{
+ // convert string -> double
+ double number = Glib::Ascii::strtod(getString());
+
+ return number;
+}
+
+
+
+/**
+ * Get attribute value of current child
+ * @param name name of attribute
+ * @return the value
+ */
+string XMLStructure::getAttribute(string name)
+{
+ // the child
+ xmlpp::Element *child = dynamic_cast<xmlpp::Element*>(*_activeChildInList);
+
+ // its attribute value
+ string attributeValue = child->get_attribute(name)->get_value();
+
+ return attributeValue;
+}
--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#ifndef XMLSTRUCTURE_H
+#define XMLSTRUCTURE_H
+
+#include <string>
+
+#include <libxml++/document.h>
+#include <libxml++/nodes/element.h>
+#include <libxml++/nodes/node.h>
+#include <libxml++/parsers/domparser.h>
+
+using namespace std;
+
+
+
+/**
+ * Basic logic for building and parsing xml-structures
+ */
+class XMLStructure
+{
+public:
+ /**
+ * Constructor
+ */
+ XMLStructure();
+
+ /**
+ * Destructor
+ */
+ ~XMLStructure();
+
+protected:
+
+ // Saver
+ // -----
+
+ /**
+ * Create new document with root node
+ * @param rootName name of root
+ */
+ void createDocumentWithRoot(string rootName);
+
+ /**
+ * Add new child to root
+ * @param name name of child
+ */
+ void addChildToRoot(string name);
+
+ /**
+ * Add a string as content of current child
+ * @param text the text
+ */
+ void addString(string text);
+
+ /**
+ * Add a number as content of current child
+ * @param value the number
+ */
+ void addNumber(double value);
+
+ /**
+ * Add attribute to current child
+ * @param name name of attribute
+ * @param value value of attribute
+ */
+ void addAttribute(string name, string value);
+
+ /**
+ * Save document to file
+ * @param path path to file
+ */
+ void saveToDisk(string path);
+
+
+ // Loader
+ // ------
+
+ /**
+ * Load document from file
+ * @param path path to file
+ */
+ void loadFromDisk(string path);
+
+ /**
+ * Find all children with the specified name
+ * @param name name of children
+ * @return true if found, else false
+ */
+ bool findChild(string name);
+
+ /**
+ * Find next child in current search result list
+ * @return true if found, else false
+ */
+ bool findNextChild();
+
+ /**
+ * Get content of current child as a string
+ * @return the string
+ */
+ string getString();
+
+ /**
+ * Get content of current child as a number
+ * @return the number
+ */
+ double getNumber();
+
+ /**
+ * Get attribute value of current child
+ * @param name name of attribute
+ * @return the value
+ */
+ string getAttribute(string name);
+
+private:
+
+ // Saver
+ xmlpp::Element *_rootElement;
+ xmlpp::Element *_activeElement;
+ xmlpp::Document *_activeDocument;
+
+ // Loader
+ xmlpp::DomParser _parser;
+ xmlpp::Node::NodeList _activeList;
+ xmlpp::Node::NodeList::iterator _activeChildInList;
+};
+
+
+
+#endif