Minor cleanup.
[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
68a7b857 61/**
62 * Reset to default state
63 */
64void Turtle::reset()
65{
66 // put turtle at (0,0,0), head upwards, back towards camera
67
68 _position.setXYZ(0.0, 0.0, 0.0);
69
70 _heading.setXYZ(0.0, 1.0, 0.0);
71 _left.setXYZ(1.0, 0.0, 0.0);
72 _up.setXYZ(0.0, 0.0, 1.0);
73
74
75 // empty the stacks
76 _positionStack = stack<Coordinate>();
77 _headingStack = stack<Vector>();
78 _leftStack = stack<Vector>();
79 _upStack = stack<Vector>();
80 _diameterStack = stack<double>();
81 _colorIndexStack = stack<int>();
82}
83
84
85
15c82487 86/**
87 * Turn left
88 */
89void Turtle::turnLeft()
90{
91 // rotate around "up vector"
92 _heading.rotate(-_angle, _up);
93 _left.rotate(-_angle, _up);
94}
95
96
97
98/**
99 * Turn right
100 */
101void Turtle::turnRight()
102{
103 // rotate around "up vector"
104 _heading.rotate(_angle, _up);
105 _left.rotate(_angle, _up);
106}
107
108
109
110/**
111 * Pitch down
112 */
113void Turtle::pitchDown()
114{
115 // rotate around "left vector"
116 _heading.rotate(-_angle, _left);
117 _up.rotate(-_angle, _left);
118}
119
120
121
122/**
123 * Pitch up
124 */
125void Turtle::pitchUp()
126{
127 // rotate around "left vector"
128 _heading.rotate(_angle, _left);
129 _up.rotate(_angle, _left);
130}
131
132
133
134/**
135 * Roll left
136 */
137void Turtle::rollLeft()
138{
139 // rotate around "heading vector"
140 _left.rotate(_angle, _heading);
141 _up.rotate(_angle, _heading);
142}
143
144
145
146/**
147 * Roll right
148 */
149void Turtle::rollRight()
150{
151 // rotate around "heading vector"
152 _left.rotate(-_angle, _heading);
153 _up.rotate(-_angle, _heading);
154}
155
156
157
158/**
159 * Turn around
160 */
161void Turtle::turnAround()
162{
163 // rotate 180 degrees around "up vector"
164 _heading.rotate(M_PIl, _up);
165 _left.rotate(M_PIl, _up);
166}
167
168
169
170/**
171 * Walk forward
172 */
173void Turtle::walk()
174{
175 // start point
176 double startX = _position.getX();
177 double startY = _position.getY();
178 double startZ = _position.getZ();
179
180 // end point
181 double endX = startX + _heading.getX();
182 double endY = startY + _heading.getY();
183 double endZ = startZ + _heading.getZ();
184
185
186 // move turtle to new position
187 _position.setXYZ(endX, endY, endZ);
188
526db675 189 // connect start and end point
190 _model->segment(startX, startY, startZ,
191 endX, endY, endZ);
192}
193
194
195
196/**
197 * Walk forward, creating a filled surface
198 * TODO: merge with walk() ?
199 */
200void Turtle::fillWalk()
201{
202 // end point
203 double destinationX = _position.getX() + _heading.getX();
204 double destinationY = _position.getY() + _heading.getY();
205 double destinationZ = _position.getZ() + _heading.getZ();
206
207 _model->normal(_up.getX(), _up.getY(), _up.getZ());
208
209 // move turtle to new position
210 _position.setXYZ(destinationX, destinationY, destinationZ);
211
212 // part of a filled polygon
213 _model->vertex(destinationX, destinationY, destinationZ);
15c82487 214}
215
216
217
218/**
219 * Save current state to stack
220 */
221void Turtle::push()
222{
223 // position
224 _positionStack.push(_position);
225
226 // orientation
227 _headingStack.push(_heading);
228 _leftStack.push(_left);
229 _upStack.push(_up);
230
231 // diameter
526db675 232 double diameter = _model->getDiameter();
233 _diameterStack.push(diameter);
234
235 // color index
236 int colorIndex = _model->getColorIndex();
237 _colorIndexStack.push(colorIndex);
15c82487 238}
239
240
241
242/**
243 * Restore old state from stack
244 */
245void Turtle::pop()
246{
247 // position
526db675 248 _position = _positionStack.top(); _positionStack.pop();
15c82487 249
250 // orientation
526db675 251 _heading = _headingStack.top(); _headingStack.pop();
252 _left = _leftStack.top(); _leftStack.pop();
253 _up = _upStack.top(); _upStack.pop();
15c82487 254
255 // diameter
526db675 256 double diameter = _diameterStack.top(); _diameterStack.pop();
257 _model->setDiameter(diameter);
258
259 // color index
260 int colorIndex = _colorIndexStack.top(); _colorIndexStack.pop();
261 _model->setColorIndex(colorIndex);
15c82487 262}
263
264
265
15c82487 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}