*** empty log message ***
[lsystem3d.git] / src / turtle.cpp
CommitLineData
15c82487 1// Copyright (C) 2006 Erik Dahlberg
2//
1a372e99 3// This file is part of LSystem3D.
15c82487 4//
5// LSystem3D is free software; you can redistribute it and/or
6// modify it under the terms of the GNU General Public License
7// as published by the Free Software Foundation; either version 2
8// of the License, or (at your option) any later version.
9//
10// LSystem3D is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with LSystem3D; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
20
21
22#include <cmath>
23
24#include <stack>
25
26#include "coordinate.h"
27#include "model.h"
28#include "turtle.h"
29#include "vector.h"
30
526db675 31using namespace std;
32
15c82487 33
34
35/**
36 * Constructor
526db675 37 * @param model create this model
15c82487 38 */
39Turtle::Turtle(Model *model)
40{
526db675 41 _model = model;
42
15c82487 43 // initial position and orientation
44 reset();
45
46 // 90 degrees
47 _angle = M_PIl / 2.0;
15c82487 48}
49
50
51
52/**
53 * Destructor
54 */
55Turtle::~Turtle()
56{
57}
58
59
60
61/**
62 * Turn left
63 */
64void Turtle::turnLeft()
65{
66 // rotate around "up vector"
67 _heading.rotate(-_angle, _up);
68 _left.rotate(-_angle, _up);
69}
70
71
72
73/**
74 * Turn right
75 */
76void Turtle::turnRight()
77{
78 // rotate around "up vector"
79 _heading.rotate(_angle, _up);
80 _left.rotate(_angle, _up);
81}
82
83
84
85/**
86 * Pitch down
87 */
88void Turtle::pitchDown()
89{
90 // rotate around "left vector"
91 _heading.rotate(-_angle, _left);
92 _up.rotate(-_angle, _left);
93}
94
95
96
97/**
98 * Pitch up
99 */
100void Turtle::pitchUp()
101{
102 // rotate around "left vector"
103 _heading.rotate(_angle, _left);
104 _up.rotate(_angle, _left);
105}
106
107
108
109/**
110 * Roll left
111 */
112void Turtle::rollLeft()
113{
114 // rotate around "heading vector"
115 _left.rotate(_angle, _heading);
116 _up.rotate(_angle, _heading);
117}
118
119
120
121/**
122 * Roll right
123 */
124void Turtle::rollRight()
125{
126 // rotate around "heading vector"
127 _left.rotate(-_angle, _heading);
128 _up.rotate(-_angle, _heading);
129}
130
131
132
133/**
134 * Turn around
135 */
136void Turtle::turnAround()
137{
138 // rotate 180 degrees around "up vector"
139 _heading.rotate(M_PIl, _up);
140 _left.rotate(M_PIl, _up);
141}
142
143
144
145/**
146 * Walk forward
147 */
148void Turtle::walk()
149{
150 // start point
151 double startX = _position.getX();
152 double startY = _position.getY();
153 double startZ = _position.getZ();
154
155 // end point
156 double endX = startX + _heading.getX();
157 double endY = startY + _heading.getY();
158 double endZ = startZ + _heading.getZ();
159
160
161 // move turtle to new position
162 _position.setXYZ(endX, endY, endZ);
163
526db675 164 // connect start and end point
165 _model->segment(startX, startY, startZ,
166 endX, endY, endZ);
167}
168
169
170
171/**
172 * Walk forward, creating a filled surface
173 * TODO: merge with walk() ?
174 */
175void Turtle::fillWalk()
176{
177 // end point
178 double destinationX = _position.getX() + _heading.getX();
179 double destinationY = _position.getY() + _heading.getY();
180 double destinationZ = _position.getZ() + _heading.getZ();
181
182 _model->normal(_up.getX(), _up.getY(), _up.getZ());
183
184 // move turtle to new position
185 _position.setXYZ(destinationX, destinationY, destinationZ);
186
187 // part of a filled polygon
188 _model->vertex(destinationX, destinationY, destinationZ);
15c82487 189}
190
191
192
193/**
194 * Save current state to stack
195 */
196void Turtle::push()
197{
198 // position
199 _positionStack.push(_position);
200
201 // orientation
202 _headingStack.push(_heading);
203 _leftStack.push(_left);
204 _upStack.push(_up);
205
206 // diameter
526db675 207 double diameter = _model->getDiameter();
208 _diameterStack.push(diameter);
209
210 // color index
211 int colorIndex = _model->getColorIndex();
212 _colorIndexStack.push(colorIndex);
15c82487 213}
214
215
216
217/**
218 * Restore old state from stack
219 */
220void Turtle::pop()
221{
222 // position
526db675 223 _position = _positionStack.top(); _positionStack.pop();
15c82487 224
225 // orientation
526db675 226 _heading = _headingStack.top(); _headingStack.pop();
227 _left = _leftStack.top(); _leftStack.pop();
228 _up = _upStack.top(); _upStack.pop();
15c82487 229
230 // diameter
526db675 231 double diameter = _diameterStack.top(); _diameterStack.pop();
232 _model->setDiameter(diameter);
233
234 // color index
235 int colorIndex = _colorIndexStack.top(); _colorIndexStack.pop();
236 _model->setColorIndex(colorIndex);
15c82487 237}
238
239
240
241/**
242 * Reset to default state
243 */
244void Turtle::reset()
526db675 245{
15c82487 246 // put turtle at (0,0,0), head upwards, back towards camera
247
248 _position.setXYZ(0.0, 0.0, 0.0);
249
250 _heading.setXYZ(0.0, 1.0, 0.0);
251 _left.setXYZ(1.0, 0.0, 0.0);
252 _up.setXYZ(0.0, 0.0, 1.0);
15c82487 253
15c82487 254
526db675 255 // empty the stacks
256 _positionStack = stack<Coordinate>();
257 _headingStack = stack<Vector>();
258 _leftStack = stack<Vector>();
259 _upStack = stack<Vector>();
260 _diameterStack = stack<double>();
261 _colorIndexStack = stack<int>();
15c82487 262}
263
264
265
266/**
267 * Set turn/pitch/roll angle
268 * @param angle the angle, in radians
269 */
270void Turtle::setAngle(double radians)
271{
272 _angle = radians;
273}
274
275
276
277/**
278 * Get turn/pitch/roll angle
279 * @return the angle, in radians
280 */
281double Turtle::getAngle()
282{
283 return _angle;
284}