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