From dd73b028a74ef8b57569c3e76751481d2124e491 Mon Sep 17 00:00:00 2001 From: spixx Date: Tue, 25 Apr 2006 11:55:17 +0000 Subject: [PATCH] Initial revision --- src/callbacks.cpp | 180 ++++++++++++++++++ src/callbacks.h | 81 ++++++++ src/coordinate.cpp | 89 +++++++++ src/coordinate.h | 76 ++++++++ src/lindenmayersystem.cpp | 370 ++++++++++++++++++++++++++++++++++++ src/lindenmayersystem.h | 140 ++++++++++++++ src/lsystem.cpp | 45 +++++ src/lsystemparameters.cpp | 138 ++++++++++++++ src/lsystemparameters.h | 67 +++++++ src/model.cpp | 175 +++++++++++++++++ src/model.h | 103 ++++++++++ src/openglwindow.cpp | 391 ++++++++++++++++++++++++++++++++++++++ src/openglwindow.h | 151 +++++++++++++++ src/turtle.cpp | 291 ++++++++++++++++++++++++++++ src/turtle.h | 157 +++++++++++++++ src/vector.cpp | 145 ++++++++++++++ src/vector.h | 84 ++++++++ src/xmlstructure.cpp | 231 ++++++++++++++++++++++ src/xmlstructure.h | 151 +++++++++++++++ 19 files changed, 3065 insertions(+) create mode 100644 src/callbacks.cpp create mode 100644 src/callbacks.h create mode 100644 src/coordinate.cpp create mode 100644 src/coordinate.h create mode 100644 src/lindenmayersystem.cpp create mode 100644 src/lindenmayersystem.h create mode 100644 src/lsystem.cpp create mode 100644 src/lsystemparameters.cpp create mode 100644 src/lsystemparameters.h create mode 100644 src/model.cpp create mode 100644 src/model.h create mode 100644 src/openglwindow.cpp create mode 100644 src/openglwindow.h create mode 100644 src/turtle.cpp create mode 100644 src/turtle.h create mode 100644 src/vector.cpp create mode 100644 src/vector.h create mode 100644 src/xmlstructure.cpp create mode 100644 src/xmlstructure.h diff --git a/src/callbacks.cpp b/src/callbacks.cpp new file mode 100644 index 0000000..b4437b2 --- /dev/null +++ b/src/callbacks.cpp @@ -0,0 +1,180 @@ +// 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 + +#include + +#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(); +} diff --git a/src/callbacks.h b/src/callbacks.h new file mode 100644 index 0000000..f827f4d --- /dev/null +++ b/src/callbacks.h @@ -0,0 +1,81 @@ +// 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 diff --git a/src/coordinate.cpp b/src/coordinate.cpp new file mode 100644 index 0000000..026addb --- /dev/null +++ b/src/coordinate.cpp @@ -0,0 +1,89 @@ +// 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; +} diff --git a/src/coordinate.h b/src/coordinate.h new file mode 100644 index 0000000..cac2a1a --- /dev/null +++ b/src/coordinate.h @@ -0,0 +1,76 @@ +// 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 diff --git a/src/lindenmayersystem.cpp b/src/lindenmayersystem.cpp new file mode 100644 index 0000000..9a66023 --- /dev/null +++ b/src/lindenmayersystem.cpp @@ -0,0 +1,370 @@ +// 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 + +#include +#include +#include + +#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 LindenmayerSystem::getRules() +{ + map theUnpreprocessedRules; + + // unpreprocess all rules + map::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; +} diff --git a/src/lindenmayersystem.h b/src/lindenmayersystem.h new file mode 100644 index 0000000..efadab9 --- /dev/null +++ b/src/lindenmayersystem.h @@ -0,0 +1,140 @@ +// 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 +#include + +#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 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 _rules; // TODO: use unsorted container? + int _numIterations; + + Model *_model; // The model for generation + Turtle *_turtle; // The rendering turtle +}; + + + +#endif diff --git a/src/lsystem.cpp b/src/lsystem.cpp new file mode 100644 index 0000000..27e51d3 --- /dev/null +++ b/src/lsystem.cpp @@ -0,0 +1,45 @@ +// 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 +#endif + +#include + +#include + +#include "openglwindow.h" + + +OpenGLWindow *openglWindow = NULL; + + + +int main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + + OpenGLWindow window; + + + return EXIT_SUCCESS; +} diff --git a/src/lsystemparameters.cpp b/src/lsystemparameters.cpp new file mode 100644 index 0000000..c12e9e3 --- /dev/null +++ b/src/lsystemparameters.cpp @@ -0,0 +1,138 @@ +// 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 +#include + +#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 rules = lsystem->getRules(); + map::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; + } +} diff --git a/src/lsystemparameters.h b/src/lsystemparameters.h new file mode 100644 index 0000000..1d80635 --- /dev/null +++ b/src/lsystemparameters.h @@ -0,0 +1,67 @@ +// 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 + +#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 diff --git a/src/model.cpp b/src/model.cpp new file mode 100644 index 0000000..48308a0 --- /dev/null +++ b/src/model.cpp @@ -0,0 +1,175 @@ +// 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); +} diff --git a/src/model.h b/src/model.h new file mode 100644 index 0000000..d7ebf26 --- /dev/null +++ b/src/model.h @@ -0,0 +1,103 @@ +// 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 + + + +/** + * 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 diff --git a/src/openglwindow.cpp b/src/openglwindow.cpp new file mode 100644 index 0000000..ba5c753 --- /dev/null +++ b/src/openglwindow.cpp @@ -0,0 +1,391 @@ +// 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 + +#include +#include +#include +#include + +#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 rules = _lsystem->getRules(); + map::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 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; +} diff --git a/src/openglwindow.h b/src/openglwindow.h new file mode 100644 index 0000000..53dbf61 --- /dev/null +++ b/src/openglwindow.h @@ -0,0 +1,151 @@ +// 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 +#include + +#include + +#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 _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 diff --git a/src/turtle.cpp b/src/turtle.cpp new file mode 100644 index 0000000..9847b5a --- /dev/null +++ b/src/turtle.cpp @@ -0,0 +1,291 @@ +// 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 + +#include + +#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; +} diff --git a/src/turtle.h b/src/turtle.h new file mode 100644 index 0000000..d56c09a --- /dev/null +++ b/src/turtle.h @@ -0,0 +1,157 @@ +// 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 + +#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 _positionStack; // positions in stack + stack _headingStack; // heading vectors in stack + stack _leftStack; // left vectors in stack + stack _upStack; // up vectors in stack + stack _diameterStack; // diameters in stack + + Model *_model; // the rendered model +}; + + + +#endif diff --git a/src/vector.cpp b/src/vector.cpp new file mode 100644 index 0000000..7b51842 --- /dev/null +++ b/src/vector.cpp @@ -0,0 +1,145 @@ +// 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 + +#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; +} diff --git a/src/vector.h b/src/vector.h new file mode 100644 index 0000000..df1e758 --- /dev/null +++ b/src/vector.h @@ -0,0 +1,84 @@ +// 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 diff --git a/src/xmlstructure.cpp b/src/xmlstructure.cpp new file mode 100644 index 0000000..b7466c0 --- /dev/null +++ b/src/xmlstructure.cpp @@ -0,0 +1,231 @@ +// 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 + +#include +#include +#include +#include + +#include + +#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(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(*_activeChildInList); + + // its attribute value + string attributeValue = child->get_attribute(name)->get_value(); + + return attributeValue; +} diff --git a/src/xmlstructure.h b/src/xmlstructure.h new file mode 100644 index 0000000..6f3f658 --- /dev/null +++ b/src/xmlstructure.h @@ -0,0 +1,151 @@ +// 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 + +#include +#include +#include +#include + +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 -- 2.34.1