Initial revision
[lsystem3d.git] / lsystem3d / src / turtle.cpp
CommitLineData
e5247a3b 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
32
33/**
34 * Constructor
35 * @param model render this model
36 */
37Turtle::Turtle(Model *model)
38{
39 // initial position and orientation
40 reset();
41
42 // 90 degrees
43 _angle = M_PIl / 2.0;
44
45 _model = model;
46}
47
48
49
50/**
51 * Destructor
52 */
53Turtle::~Turtle()
54{
55}
56
57
58
59/**
60 * Turn left
61 */
62void Turtle::turnLeft()
63{
64 // rotate around "up vector"
65 _heading.rotate(-_angle, _up);
66 _left.rotate(-_angle, _up);
67}
68
69
70
71/**
72 * Turn right
73 */
74void Turtle::turnRight()
75{
76 // rotate around "up vector"
77 _heading.rotate(_angle, _up);
78 _left.rotate(_angle, _up);
79}
80
81
82
83/**
84 * Pitch down
85 */
86void Turtle::pitchDown()
87{
88 // rotate around "left vector"
89 _heading.rotate(-_angle, _left);
90 _up.rotate(-_angle, _left);
91}
92
93
94
95/**
96 * Pitch up
97 */
98void Turtle::pitchUp()
99{
100 // rotate around "left vector"
101 _heading.rotate(_angle, _left);
102 _up.rotate(_angle, _left);
103}
104
105
106
107/**
108 * Roll left
109 */
110void Turtle::rollLeft()
111{
112 // rotate around "heading vector"
113 _left.rotate(_angle, _heading);
114 _up.rotate(_angle, _heading);
115}
116
117
118
119/**
120 * Roll right
121 */
122void Turtle::rollRight()
123{
124 // rotate around "heading vector"
125 _left.rotate(-_angle, _heading);
126 _up.rotate(-_angle, _heading);
127}
128
129
130
131/**
132 * Turn around
133 */
134void Turtle::turnAround()
135{
136 // rotate 180 degrees around "up vector"
137 _heading.rotate(M_PIl, _up);
138 _left.rotate(M_PIl, _up);
139}
140
141
142
143/**
144 * Walk forward
145 */
146void Turtle::walk()
147{
148 // start point
149 double startX = _position.getX();
150 double startY = _position.getY();
151 double startZ = _position.getZ();
152
153 // end point
154 double endX = startX + _heading.getX();
155 double endY = startY + _heading.getY();
156 double endZ = startZ + _heading.getZ();
157
158
159 // move turtle to new position
160 _position.setXYZ(endX, endY, endZ);
161
162 if (!_fenceMode)
163 {
164 // connect the points
165 _model->segment(_diameter,
166 startX, startY, startZ,
167 endX, endY, endZ);
168 }
169 else
170 {
171 // part of a filled surface
172 _model->point(endX, endY, endZ);
173 }
174}
175
176
177
178/**
179 * Save current state to stack
180 */
181void Turtle::push()
182{
183 // position
184 _positionStack.push(_position);
185
186 // orientation
187 _headingStack.push(_heading);
188 _leftStack.push(_left);
189 _upStack.push(_up);
190
191 // diameter
192 _diameterStack.push(_diameter);
193}
194
195
196
197/**
198 * Restore old state from stack
199 */
200void Turtle::pop()
201{
202 // position
203 _position = _positionStack.top(); _positionStack.pop();
204
205 // orientation
206 _heading = _headingStack.top(); _headingStack.pop();
207 _left = _leftStack.top(); _leftStack.pop();
208 _up = _upStack.top(); _upStack.pop();
209
210 // diameter
211 _diameter = _diameterStack.top(); _diameterStack.pop();
212}
213
214
215
216/**
217 * Reset to default state
218 */
219void Turtle::reset()
220{
221 _diameter = 0.1;
222
223 _fenceMode = false;
224
225
226 // put turtle at (0,0,0), head upwards, back towards camera
227
228 _position.setXYZ(0.0, 0.0, 0.0);
229
230 _heading.setXYZ(0.0, 1.0, 0.0);
231 _left.setXYZ(1.0, 0.0, 0.0);
232 _up.setXYZ(0.0, 0.0, 1.0);
233}
234
235
236
237/**
238 * Decrement diameter of segment
239 */
240void Turtle::decrementDiameter()
241{
242 // TODO: dynamic value...
243 _diameter *= 0.8;
244}
245
246
247
248/**
249 * Begin creation of a filled surface
250 */
251void Turtle::fenceInBegin()
252{
253 _fenceMode = true;
254
255 _model->fillBegin();
256 _model->point(_position.getX(), _position.getY(), _position.getZ());
257}
258
259
260
261/**
262 * End creation of a filled surface
263 */
264void Turtle::fenceInEnd()
265{
266 _model->fillEnd();
267
268 _fenceMode = false;
269}
270
271
272
273/**
274 * Set turn/pitch/roll angle
275 * @param angle the angle, in radians
276 */
277void Turtle::setAngle(double radians)
278{
279 _angle = radians;
280}
281
282
283
284/**
285 * Get turn/pitch/roll angle
286 * @return the angle, in radians
287 */
288double Turtle::getAngle()
289{
290 return _angle;
291}