Minor cleanup.
[lsystem3d.git] / src / turtle.cpp
1 // Copyright (C) 2006 Erik Dahlberg
2 //
3 // This file is part of LSystem3D.
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
31 using namespace std;
32
33
34
35 /**
36 * Constructor
37 * @param model create this model
38 */
39 Turtle::Turtle(Model *model)
40 {
41 _model = model;
42
43 // initial position and orientation
44 reset();
45
46 // 90 degrees
47 _angle = M_PIl / 2.0;
48 }
49
50
51
52 /**
53 * Destructor
54 */
55 Turtle::~Turtle()
56 {
57 }
58
59
60
61 /**
62 * Reset to default state
63 */
64 void 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
86 /**
87 * Turn left
88 */
89 void 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 */
101 void 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 */
113 void 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 */
125 void 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 */
137 void 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 */
149 void 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 */
161 void 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 */
173 void 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
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 */
200 void 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);
214 }
215
216
217
218 /**
219 * Save current state to stack
220 */
221 void 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
232 double diameter = _model->getDiameter();
233 _diameterStack.push(diameter);
234
235 // color index
236 int colorIndex = _model->getColorIndex();
237 _colorIndexStack.push(colorIndex);
238 }
239
240
241
242 /**
243 * Restore old state from stack
244 */
245 void Turtle::pop()
246 {
247 // position
248 _position = _positionStack.top(); _positionStack.pop();
249
250 // orientation
251 _heading = _headingStack.top(); _headingStack.pop();
252 _left = _leftStack.top(); _leftStack.pop();
253 _up = _upStack.top(); _upStack.pop();
254
255 // diameter
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);
262 }
263
264
265
266 /**
267 * Set turn/pitch/roll angle
268 * @param angle the angle, in radians
269 */
270 void 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 */
281 double Turtle::getAngle()
282 {
283 return _angle;
284 }