Save and load segment dimeter and factor.
[lsystem3d.git] / src / model.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 <vector>
23
24 #include "GL/gl.h"
25 #include "GL/glu.h"
26
27 #include "color.h"
28 #include "model.h"
29 #include "vector.h"
30
31 using namespace std;
32
33
34
35 /**
36 * Constructor
37 */
38 Model::Model()
39 {
40 // default color table
41 Color brown(0.5, 0.2, 0.0); _colorTable.push_back(brown);
42 Color white(1.0, 1.0, 1.0); _colorTable.push_back(white);
43 Color green(0.0, 0.5, 0.0); _colorTable.push_back(green);
44
45 _displayList = 0;
46
47 clear();
48 }
49
50
51
52 /**
53 * Destructor
54 */
55 Model::~Model()
56 {
57 glDeleteLists(_displayList, 1);
58 }
59
60
61
62 /**
63 * Create a segment
64 * @param x1 x start point
65 * @param y1 y start point
66 * @param z1 z start point
67 * @param x2 x end point
68 * @param y2 y end point
69 * @param z2 z end point
70 */
71 void Model::segment(double x1, double y1, double z1, double x2, double y2, double z2)
72 {
73 // find rotation vector and angle
74
75 Vector initial(0.0, 1.0, 0.0); // initial rotation of cylinder
76 Vector desired(x2-x1, y2-y1, z2-z1); // desired rotation of cylinder
77 desired.normalize();
78
79 // rotation angle
80 double rotationAngle = initial.getAngle(desired);
81
82 // rotation vector
83 Vector rotationVector = initial.getCrossProduct(desired);
84 rotationVector.normalize();
85
86
87 // render the cylinder
88
89 static GLUquadric *quadric = gluNewQuadric();
90
91 glPushMatrix();
92 glTranslatef(x1, y1, z1);
93 glRotatef(rotationAngle, rotationVector.getX(), rotationVector.getY(), rotationVector.getZ());
94 glRotatef(-90, 1, 0, 0);
95
96 gluCylinder(quadric, _diameter, _diameter, 1.0, 6, 6);
97 glPopMatrix();
98 }
99
100
101
102 /**
103 * Specify a vertex
104 * @param x x-coordinate
105 * @param y y-coordinate
106 * @param z z-coordinate
107 */
108 void Model::vertex(double x, double y, double z)
109 {
110 glVertex3d(x, y, z);
111 }
112
113
114
115 /**
116 * Specify a normal
117 * @param x x-coordinate
118 * @param y y-coordinate
119 * @param z z-coordinate
120 */
121 void Model::normal(double x, double y, double z)
122 {
123 glNormal3f(x, y, z);
124 }
125
126
127
128 /**
129 * Render to screen
130 */
131 void Model::draw()
132 {
133 glCallList(_displayList);
134 }
135
136
137
138 /**
139 * Clear the model
140 */
141 void Model::clear()
142 {
143 glDeleteLists(_displayList, 1);
144 _displayList = glGenLists(1);
145
146 setColorIndex(0);
147
148 _diameter = 0.1;
149 _diameterFactor = 0.8;
150 }
151
152
153
154 /**
155 * Begin a modelling session
156 */
157 void Model::begin()
158 {
159 glNewList(_displayList, GL_COMPILE);
160 }
161
162
163
164 /**
165 * End a modelling session
166 */
167 void Model::end()
168 {
169 glEndList();
170 }
171
172
173
174 /**
175 * Begin creation of a filled polygon
176 */
177 void Model::fillBegin()
178 {
179 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
180
181 glBegin(GL_POLYGON);
182 }
183
184
185
186 /**
187 * End creation of a filled polygon
188 */
189 void Model::fillEnd()
190 {
191 glEnd();
192
193 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
194 }
195
196
197
198 /**
199 * Increment current index to color table
200 */
201 void Model::nextColor()
202 {
203 setColorIndex(_colorIndex + 1);
204 }
205
206
207
208 /**
209 * Decrement current index to color table
210 */
211 void Model::prevColor()
212 {
213 setColorIndex(_colorIndex - 1);
214 }
215
216
217
218 /**
219 * Decrement diameter of segment
220 */
221 void Model::decrementDiameter()
222 {
223 _diameter *= _diameterFactor;
224 }
225
226
227
228 /**
229 * Set current color index
230 * @param index the color index
231 */
232 void Model::setColorIndex(int index)
233 {
234 // keep in range
235
236 if (index < 0)
237 {
238 _colorIndex = _colorTable.size() - 1;
239 }
240 else if (index > (_colorTable.size() - 1))
241 {
242 _colorIndex = 0;
243 }
244 else
245 {
246 _colorIndex = index;
247 }
248
249
250 // set color
251
252 Color color = _colorTable[_colorIndex];
253 double r = color.getR();
254 double g = color.getG();
255 double b = color.getB();
256
257 glColor3f(r, g, b);
258 }
259
260
261
262 /**
263 * Set current diameter of segment
264 * @param diameter the diameter
265 */
266 void Model::setDiameter(double diameter)
267 {
268 _diameter = diameter;
269 }
270
271
272
273 /**
274 * Set diameter factor
275 * @param diameter the diameter factor
276 */
277 void Model::setDiameterFactor(double diameterFactor)
278 {
279 _diameterFactor = diameterFactor;
280 }
281
282
283
284 /**
285 * Get current color index
286 * @return color index
287 */
288 int Model::getColorIndex()
289 {
290 return _colorIndex;
291 }
292
293
294
295 /**
296 * Get current diameter of segment
297 * @return diameter of segment
298 */
299 double Model::getDiameter()
300 {
301 return _diameter;
302 }