X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lsystem3d%2Fsrc%2Fopenglwindow.cpp;fp=lsystem3d%2Fsrc%2Fopenglwindow.cpp;h=ba5c7533243b956c30c254a5f28dd2d3581b67a8;hb=e5247a3b88c449937af08f46afc271afda2954a2;hp=0000000000000000000000000000000000000000;hpb=c48a55e9e62ed7a9d46e3c6a53faae4bc05856e5;p=lsystem3d.git diff --git a/lsystem3d/src/openglwindow.cpp b/lsystem3d/src/openglwindow.cpp new file mode 100644 index 0000000..ba5c753 --- /dev/null +++ b/lsystem3d/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; +}