1 | // |
---|
2 | // "$Id$" |
---|
3 | // |
---|
4 | // Fractal drawing demo for the Fast Light Tool Kit (FLTK). |
---|
5 | // |
---|
6 | // This is a GLUT demo program, with modifications to |
---|
7 | // demonstrate how to add FLTK controls to a GLUT program. The GLUT |
---|
8 | // code is unchanged except for the end (search for FLTK to find changes). |
---|
9 | // |
---|
10 | // Copyright 1998-2005 by Bill Spitzak and others. |
---|
11 | // |
---|
12 | // This library is free software; you can redistribute it and/or |
---|
13 | // modify it under the terms of the GNU Library General Public |
---|
14 | // License as published by the Free Software Foundation; either |
---|
15 | // version 2 of the License, or (at your option) any later version. |
---|
16 | // |
---|
17 | // This library is distributed in the hope that it will be useful, |
---|
18 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
19 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
20 | // Library General Public License for more details. |
---|
21 | // |
---|
22 | // You should have received a copy of the GNU Library General Public |
---|
23 | // License along with this library; if not, write to the Free Software |
---|
24 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
---|
25 | // USA. |
---|
26 | // |
---|
27 | // Please report all bugs and problems on the following page: |
---|
28 | // |
---|
29 | // http://www.fltk.org/str.php |
---|
30 | // |
---|
31 | |
---|
32 | #include "config.h" |
---|
33 | #if !HAVE_GL || !HAVE_GL_GLU_H |
---|
34 | #include <FL/Fl.H> |
---|
35 | #include <FL/fl_message.H> |
---|
36 | int main(int, char**) { |
---|
37 | fl_alert("This demo does not work without GL and GLU (%d)"); |
---|
38 | return 1; |
---|
39 | } |
---|
40 | #else |
---|
41 | /* |
---|
42 | * To compile: cc -o fractals fractals.c -lGL -lGLU -lX11 -lglut -lXmu -lm |
---|
43 | * |
---|
44 | * Usage: fractals |
---|
45 | * |
---|
46 | * Homework 6, Part 2: fractal mountains and fractal trees |
---|
47 | * (Pretty Late) |
---|
48 | * |
---|
49 | * Draws fractal mountains and trees -- and an island of mountains in water |
---|
50 | * (I tried having trees on the island but it didn't work too well.) |
---|
51 | * |
---|
52 | * Two viewer modes: polar and flying (both restrained to y>0 for up vector). |
---|
53 | * Keyboard 0->9 and +/- control speed when flying. |
---|
54 | * |
---|
55 | * Only keyboard commands are 0-9 and +/- for speed in flying mode. |
---|
56 | * |
---|
57 | * Fog would make the island look much better, but I couldn't get it to work |
---|
58 | * correctly. Would line up on -z axis not from eye. |
---|
59 | * |
---|
60 | * Philip Winston - 3/4/95 |
---|
61 | * pwinston@hmc.edu |
---|
62 | * http://www.cs.hmc.edu/people/pwinston |
---|
63 | * |
---|
64 | */ |
---|
65 | |
---|
66 | #include <FL/glut.H> |
---|
67 | #include <FL/glu.h> |
---|
68 | |
---|
69 | #include <stdio.h> |
---|
70 | #include <stdlib.h> |
---|
71 | #include <math.h> |
---|
72 | #include <limits.h> /* ULONG_MAX is defined here */ |
---|
73 | #include <float.h> /* FLT_MAX is atleast defined here */ |
---|
74 | |
---|
75 | #include <time.h> /* for random seed */ |
---|
76 | |
---|
77 | #include "fracviewer.h" |
---|
78 | |
---|
79 | #if defined(WIN32) || defined(__EMX__) |
---|
80 | # define drand48() (((float) rand())/((float) RAND_MAX)) |
---|
81 | # define srand48(x) (srand((x))) |
---|
82 | #elif defined __APPLE__ |
---|
83 | # define drand48() (((float) rand())/((float) RAND_MAX)) |
---|
84 | # define srand48(x) (srand((x))) |
---|
85 | #endif |
---|
86 | |
---|
87 | typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF, |
---|
88 | MOUNTAIN_MAT, WATER_MAT, LEAF_MAT, TREE_MAT, STEMANDLEAVES, |
---|
89 | AXES } DisplayLists; |
---|
90 | |
---|
91 | #define MAXLEVEL 8 |
---|
92 | |
---|
93 | int Rebuild = 1, /* Rebuild display list in next display? */ |
---|
94 | fractal = TREE, /* What fractal are we building */ |
---|
95 | Level = 4; /* levels of recursion for fractals */ |
---|
96 | |
---|
97 | int DrawAxes = 0; |
---|
98 | |
---|
99 | /***************************************************************/ |
---|
100 | /************************* VECTOR JUNK *************************/ |
---|
101 | /***************************************************************/ |
---|
102 | |
---|
103 | /* print vertex to stderr */ |
---|
104 | void printvert(float v[3]) |
---|
105 | { |
---|
106 | fprintf(stderr, "(%f, %f, %f)\n", v[0], v[1], v[2]); |
---|
107 | } |
---|
108 | |
---|
109 | #if 0 // removed for FL, it is in fracviewer.c |
---|
110 | /* normalizes v */ |
---|
111 | void normalize(GLfloat v[3]) |
---|
112 | { |
---|
113 | GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); |
---|
114 | |
---|
115 | if (d == 0) |
---|
116 | fprintf(stderr, "Zero length vector in normalize\n"); |
---|
117 | else |
---|
118 | v[0] /= d; v[1] /= d; v[2] /= d; |
---|
119 | } |
---|
120 | |
---|
121 | /* calculates a normalized crossproduct to v1, v2 */ |
---|
122 | void ncrossprod(float v1[3], float v2[3], float cp[3]) |
---|
123 | { |
---|
124 | cp[0] = v1[1]*v2[2] - v1[2]*v2[1]; |
---|
125 | cp[1] = v1[2]*v2[0] - v1[0]*v2[2]; |
---|
126 | cp[2] = v1[0]*v2[1] - v1[1]*v2[0]; |
---|
127 | normalize(cp); |
---|
128 | } |
---|
129 | #endif |
---|
130 | |
---|
131 | /* calculates normal to the triangle designated by v1, v2, v3 */ |
---|
132 | void triagnormal(float v1[3], float v2[3], float v3[3], float norm[3]) |
---|
133 | { |
---|
134 | float vec1[3], vec2[3]; |
---|
135 | |
---|
136 | vec1[0] = v3[0] - v1[0]; vec2[0] = v2[0] - v1[0]; |
---|
137 | vec1[1] = v3[1] - v1[1]; vec2[1] = v2[1] - v1[1]; |
---|
138 | vec1[2] = v3[2] - v1[2]; vec2[2] = v2[2] - v1[2]; |
---|
139 | |
---|
140 | ncrossprod(vec2, vec1, norm); |
---|
141 | } |
---|
142 | |
---|
143 | float xzlength(float v1[3], float v2[3]) |
---|
144 | { |
---|
145 | return sqrt((v1[0] - v2[0])*(v1[0] - v2[0]) + |
---|
146 | (v1[2] - v2[2])*(v1[2] - v2[2])); |
---|
147 | } |
---|
148 | |
---|
149 | float xzslope(float v1[3], float v2[3]) |
---|
150 | { |
---|
151 | return ((v1[0] != v2[0]) ? ((v1[2] - v2[2]) / (v1[0] - v2[0])) |
---|
152 | : FLT_MAX); |
---|
153 | } |
---|
154 | |
---|
155 | |
---|
156 | /***************************************************************/ |
---|
157 | /************************ MOUNTAIN STUFF ***********************/ |
---|
158 | /***************************************************************/ |
---|
159 | |
---|
160 | GLfloat DispFactor[MAXLEVEL]; /* Array of what to multiply random number |
---|
161 | by for a given level to get midpoint |
---|
162 | displacement */ |
---|
163 | GLfloat DispBias[MAXLEVEL]; /* Array of what to add to random number |
---|
164 | before multiplying it by DispFactor */ |
---|
165 | |
---|
166 | #define NUMRANDS 191 |
---|
167 | float RandTable[NUMRANDS]; /* hash table of random numbers so we can |
---|
168 | raise the same midpoints by the same amount */ |
---|
169 | |
---|
170 | /* The following are for permitting an edge of a moutain to be */ |
---|
171 | /* pegged so it won't be displaced up or down. This makes it */ |
---|
172 | /* easier to setup scenes and makes a single moutain look better */ |
---|
173 | |
---|
174 | GLfloat Verts[3][3], /* Vertices of outside edges of mountain */ |
---|
175 | Slopes[3]; /* Slopes between these outside edges */ |
---|
176 | int Pegged[3]; /* Is this edge pegged or not */ |
---|
177 | |
---|
178 | /* |
---|
179 | * Comes up with a new table of random numbers [0,1) |
---|
180 | */ |
---|
181 | void InitRandTable(unsigned int seed) |
---|
182 | { |
---|
183 | int i; |
---|
184 | |
---|
185 | srand48((long) seed); |
---|
186 | for (i = 0; i < NUMRANDS; i++) |
---|
187 | RandTable[i] = drand48() - 0.5; |
---|
188 | } |
---|
189 | |
---|
190 | /* calculate midpoint and displace it if required */ |
---|
191 | void Midpoint(GLfloat mid[3], GLfloat v1[3], GLfloat v2[3], |
---|
192 | int edge, int level) |
---|
193 | { |
---|
194 | unsigned hash; |
---|
195 | |
---|
196 | mid[0] = (v1[0] + v2[0]) / 2; |
---|
197 | mid[1] = (v1[1] + v2[1]) / 2; |
---|
198 | mid[2] = (v1[2] + v2[2]) / 2; |
---|
199 | if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid) |
---|
200 | - Slopes[edge]) > 0.00001)) { |
---|
201 | srand48((int)((v1[0]+v2[0])*23344)); |
---|
202 | hash = unsigned(drand48() * 7334334); |
---|
203 | srand48((int)((v2[2]+v1[2])*43433)); |
---|
204 | hash = (unsigned)(drand48() * 634344 + hash) % NUMRANDS; |
---|
205 | mid[1] += ((RandTable[hash] + DispBias[level]) * DispFactor[level]); |
---|
206 | } |
---|
207 | } |
---|
208 | |
---|
209 | /* |
---|
210 | * Recursive moutain drawing routine -- from lecture with addition of |
---|
211 | * allowing an edge to be pegged. This function requires the above |
---|
212 | * globals to be set, as well as the Level global for fractal level |
---|
213 | */ |
---|
214 | static float cutoff = -1; |
---|
215 | |
---|
216 | void FMR(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int level) |
---|
217 | { |
---|
218 | if (level == Level) { |
---|
219 | GLfloat norm[3]; |
---|
220 | if (v1[1] <= cutoff && v2[1]<=cutoff && v3[1]<=cutoff) return; |
---|
221 | triagnormal(v1, v2, v3, norm); |
---|
222 | glNormal3fv(norm); |
---|
223 | glVertex3fv(v1); |
---|
224 | glVertex3fv(v2); |
---|
225 | glVertex3fv(v3); |
---|
226 | |
---|
227 | } else { |
---|
228 | GLfloat m1[3], m2[3], m3[3]; |
---|
229 | |
---|
230 | Midpoint(m1, v1, v2, 0, level); |
---|
231 | Midpoint(m2, v2, v3, 1, level); |
---|
232 | Midpoint(m3, v3, v1, 2, level); |
---|
233 | |
---|
234 | FMR(v1, m1, m3, level + 1); |
---|
235 | FMR(m1, v2, m2, level + 1); |
---|
236 | FMR(m3, m2, v3, level + 1); |
---|
237 | FMR(m1, m2, m3, level + 1); |
---|
238 | } |
---|
239 | } |
---|
240 | |
---|
241 | /* |
---|
242 | * sets up lookup tables and calls recursive mountain function |
---|
243 | */ |
---|
244 | void FractalMountain(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], |
---|
245 | int pegged[3]) |
---|
246 | { |
---|
247 | GLfloat lengths[MAXLEVEL]; |
---|
248 | GLfloat fraction[8] = { 0.3, 0.3, 0.4, 0.2, 0.3, 0.2, 0.4, 0.4 }; |
---|
249 | GLfloat bias[8] = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 }; |
---|
250 | int i; |
---|
251 | float avglen = (xzlength(v1, v2) + |
---|
252 | xzlength(v2, v3) + |
---|
253 | xzlength(v3, v1) / 3); |
---|
254 | |
---|
255 | for (i = 0; i < 3; i++) { |
---|
256 | Verts[0][i] = v1[i]; /* set mountain vertex globals */ |
---|
257 | Verts[1][i] = v2[i]; |
---|
258 | Verts[2][i] = v3[i]; |
---|
259 | Pegged[i] = pegged[i]; |
---|
260 | } |
---|
261 | |
---|
262 | Slopes[0] = xzslope(Verts[0], Verts[1]); /* set edge slope globals */ |
---|
263 | Slopes[1] = xzslope(Verts[1], Verts[2]); |
---|
264 | Slopes[2] = xzslope(Verts[2], Verts[0]); |
---|
265 | |
---|
266 | lengths[0] = avglen; |
---|
267 | for (i = 1; i < Level; i++) { |
---|
268 | lengths[i] = lengths[i-1]/2; /* compute edge length for each level */ |
---|
269 | } |
---|
270 | |
---|
271 | for (i = 0; i < Level; i++) { /* DispFactor and DispBias arrays */ |
---|
272 | DispFactor[i] = (lengths[i] * ((i <= 7) ? fraction[i] : fraction[7])); |
---|
273 | DispBias[i] = ((i <= 7) ? bias[i] : bias[7]); |
---|
274 | } |
---|
275 | |
---|
276 | glBegin(GL_TRIANGLES); |
---|
277 | FMR(v1, v2, v3, 0); /* issues no GL but vertex calls */ |
---|
278 | glEnd(); |
---|
279 | } |
---|
280 | |
---|
281 | /* |
---|
282 | * draw a mountain and build the display list |
---|
283 | */ |
---|
284 | void CreateMountain(void) |
---|
285 | { |
---|
286 | GLfloat v1[3] = { 0, 0, -1 }, v2[3] = { -1, 0, 1 }, v3[3] = { 1, 0, 1 }; |
---|
287 | int pegged[3] = { 1, 1, 1 }; |
---|
288 | |
---|
289 | glNewList(MOUNTAIN, GL_COMPILE); |
---|
290 | glPushAttrib(GL_LIGHTING_BIT); |
---|
291 | glCallList(MOUNTAIN_MAT); |
---|
292 | FractalMountain(v1, v2, v3, pegged); |
---|
293 | glPopAttrib(); |
---|
294 | glEndList(); |
---|
295 | } |
---|
296 | |
---|
297 | /* |
---|
298 | * new random numbers to make a different moutain |
---|
299 | */ |
---|
300 | void NewMountain(void) |
---|
301 | { |
---|
302 | InitRandTable(time(NULL)); |
---|
303 | } |
---|
304 | |
---|
305 | /***************************************************************/ |
---|
306 | /***************************** TREE ****************************/ |
---|
307 | /***************************************************************/ |
---|
308 | |
---|
309 | long TreeSeed; /* for srand48 - remember so we can build "same tree" |
---|
310 | at a different level */ |
---|
311 | |
---|
312 | /* |
---|
313 | * recursive tree drawing thing, fleshed out from class notes pseudocode |
---|
314 | */ |
---|
315 | void FractalTree(int level) |
---|
316 | { |
---|
317 | long savedseed; /* need to save seeds while building tree too */ |
---|
318 | |
---|
319 | if (level == Level) { |
---|
320 | glPushMatrix(); |
---|
321 | glRotatef(drand48()*180, 0, 1, 0); |
---|
322 | glCallList(STEMANDLEAVES); |
---|
323 | glPopMatrix(); |
---|
324 | } else { |
---|
325 | glCallList(STEM); |
---|
326 | glPushMatrix(); |
---|
327 | glRotatef(drand48()*180, 0, 1, 0); |
---|
328 | glTranslatef(0, 1, 0); |
---|
329 | glScalef(0.7, 0.7, 0.7); |
---|
330 | |
---|
331 | savedseed = (long)((ulong)drand48()*ULONG_MAX); |
---|
332 | glPushMatrix(); |
---|
333 | glRotatef(110 + drand48()*40, 0, 1, 0); |
---|
334 | glRotatef(30 + drand48()*20, 0, 0, 1); |
---|
335 | FractalTree(level + 1); |
---|
336 | glPopMatrix(); |
---|
337 | |
---|
338 | srand48(savedseed); |
---|
339 | savedseed = (long)((ulong)drand48()*ULONG_MAX); |
---|
340 | glPushMatrix(); |
---|
341 | glRotatef(-130 + drand48()*40, 0, 1, 0); |
---|
342 | glRotatef(30 + drand48()*20, 0, 0, 1); |
---|
343 | FractalTree(level + 1); |
---|
344 | glPopMatrix(); |
---|
345 | |
---|
346 | srand48(savedseed); |
---|
347 | glPushMatrix(); |
---|
348 | glRotatef(-20 + drand48()*40, 0, 1, 0); |
---|
349 | glRotatef(30 + drand48()*20, 0, 0, 1); |
---|
350 | FractalTree(level + 1); |
---|
351 | glPopMatrix(); |
---|
352 | |
---|
353 | glPopMatrix(); |
---|
354 | } |
---|
355 | } |
---|
356 | |
---|
357 | /* |
---|
358 | * Create display lists for a leaf, a set of leaves, and a stem |
---|
359 | */ |
---|
360 | void CreateTreeLists(void) |
---|
361 | { |
---|
362 | GLUquadricObj *cylquad = gluNewQuadric(); |
---|
363 | int i; |
---|
364 | |
---|
365 | glNewList(STEM, GL_COMPILE); |
---|
366 | glPushMatrix(); |
---|
367 | glRotatef(-90, 1, 0, 0); |
---|
368 | gluCylinder(cylquad, 0.1, 0.08, 1, 10, 2 ); |
---|
369 | glPopMatrix(); |
---|
370 | glEndList(); |
---|
371 | |
---|
372 | glNewList(LEAF, GL_COMPILE); /* I think this was jeff allen's leaf idea */ |
---|
373 | glBegin(GL_TRIANGLES); |
---|
374 | glNormal3f(-0.1, 0, 0.25); /* not normalized */ |
---|
375 | glVertex3f(0, 0, 0); |
---|
376 | glVertex3f(0.25, 0.25, 0.1); |
---|
377 | glVertex3f(0, 0.5, 0); |
---|
378 | |
---|
379 | glNormal3f(0.1, 0, 0.25); |
---|
380 | glVertex3f(0, 0, 0); |
---|
381 | glVertex3f(0, 0.5, 0); |
---|
382 | glVertex3f(-0.25, 0.25, 0.1); |
---|
383 | glEnd(); |
---|
384 | glEndList(); |
---|
385 | |
---|
386 | glNewList(STEMANDLEAVES, GL_COMPILE); |
---|
387 | glPushMatrix(); |
---|
388 | glPushAttrib(GL_LIGHTING_BIT); |
---|
389 | glCallList(STEM); |
---|
390 | glCallList(LEAF_MAT); |
---|
391 | for(i = 0; i < 3; i++) { |
---|
392 | glTranslatef(0, 0.333, 0); |
---|
393 | glRotatef(90, 0, 1, 0); |
---|
394 | glPushMatrix(); |
---|
395 | glRotatef(0, 0, 1, 0); |
---|
396 | glRotatef(50, 1, 0, 0); |
---|
397 | glCallList(LEAF); |
---|
398 | glPopMatrix(); |
---|
399 | glPushMatrix(); |
---|
400 | glRotatef(180, 0, 1, 0); |
---|
401 | glRotatef(60, 1, 0, 0); |
---|
402 | glCallList(LEAF); |
---|
403 | glPopMatrix(); |
---|
404 | } |
---|
405 | glPopAttrib(); |
---|
406 | glPopMatrix(); |
---|
407 | glEndList(); |
---|
408 | |
---|
409 | gluDeleteQuadric(cylquad); |
---|
410 | } |
---|
411 | |
---|
412 | /* |
---|
413 | * draw and build display list for tree |
---|
414 | */ |
---|
415 | void CreateTree(void) |
---|
416 | { |
---|
417 | srand48(TreeSeed); |
---|
418 | |
---|
419 | glNewList(TREE, GL_COMPILE); |
---|
420 | glPushMatrix(); |
---|
421 | glPushAttrib(GL_LIGHTING_BIT); |
---|
422 | glCallList(TREE_MAT); |
---|
423 | glTranslatef(0, -1, 0); |
---|
424 | FractalTree(0); |
---|
425 | glPopAttrib(); |
---|
426 | glPopMatrix(); |
---|
427 | glEndList(); |
---|
428 | } |
---|
429 | |
---|
430 | /* |
---|
431 | * new seed for a new tree (groan) |
---|
432 | */ |
---|
433 | void NewTree(void) |
---|
434 | { |
---|
435 | TreeSeed = time(NULL); |
---|
436 | } |
---|
437 | |
---|
438 | /***************************************************************/ |
---|
439 | /*********************** FRACTAL PLANET ************************/ |
---|
440 | /***************************************************************/ |
---|
441 | |
---|
442 | void CreateIsland(void) |
---|
443 | { |
---|
444 | cutoff = .06; |
---|
445 | CreateMountain(); |
---|
446 | cutoff = -1; |
---|
447 | glNewList(ISLAND, GL_COMPILE); |
---|
448 | glPushAttrib(GL_LIGHTING_BIT); |
---|
449 | glMatrixMode(GL_MODELVIEW); |
---|
450 | glPushMatrix(); |
---|
451 | glCallList(WATER_MAT); |
---|
452 | |
---|
453 | glBegin(GL_QUADS); |
---|
454 | glNormal3f(0, 1, 0); |
---|
455 | glVertex3f(10, 0.01, 10); |
---|
456 | glVertex3f(10, 0.01, -10); |
---|
457 | glVertex3f(-10, 0.01, -10); |
---|
458 | glVertex3f(-10, 0.01, 10); |
---|
459 | glEnd(); |
---|
460 | |
---|
461 | glPushMatrix(); |
---|
462 | glTranslatef(0, -0.1, 0); |
---|
463 | glCallList(MOUNTAIN); |
---|
464 | glPopMatrix(); |
---|
465 | |
---|
466 | glPushMatrix(); |
---|
467 | glRotatef(135, 0, 1, 0); |
---|
468 | glTranslatef(0.2, -0.15, -0.4); |
---|
469 | glCallList(MOUNTAIN); |
---|
470 | glPopMatrix(); |
---|
471 | |
---|
472 | glPushMatrix(); |
---|
473 | glRotatef(-60, 0, 1, 0); |
---|
474 | glTranslatef(0.7, -0.07, 0.5); |
---|
475 | glCallList(MOUNTAIN); |
---|
476 | glPopMatrix(); |
---|
477 | |
---|
478 | glPushMatrix(); |
---|
479 | glRotatef(-175, 0, 1, 0); |
---|
480 | glTranslatef(-0.7, -0.05, -0.5); |
---|
481 | glCallList(MOUNTAIN); |
---|
482 | glPopMatrix(); |
---|
483 | |
---|
484 | glPushMatrix(); |
---|
485 | glRotatef(165, 0, 1, 0); |
---|
486 | glTranslatef(-0.9, -0.12, 0.0); |
---|
487 | glCallList(MOUNTAIN); |
---|
488 | glPopMatrix(); |
---|
489 | |
---|
490 | glPopMatrix(); |
---|
491 | glPopAttrib(); |
---|
492 | glEndList(); |
---|
493 | } |
---|
494 | |
---|
495 | |
---|
496 | void NewFractals(void) |
---|
497 | { |
---|
498 | NewMountain(); |
---|
499 | NewTree(); |
---|
500 | } |
---|
501 | |
---|
502 | void Create(int fract) |
---|
503 | { |
---|
504 | switch(fract) { |
---|
505 | case MOUNTAIN: |
---|
506 | CreateMountain(); |
---|
507 | break; |
---|
508 | case TREE: |
---|
509 | CreateTree(); |
---|
510 | break; |
---|
511 | case ISLAND: |
---|
512 | CreateIsland(); |
---|
513 | break; |
---|
514 | } |
---|
515 | } |
---|
516 | |
---|
517 | |
---|
518 | |
---|
519 | /***************************************************************/ |
---|
520 | /**************************** OPENGL ***************************/ |
---|
521 | /***************************************************************/ |
---|
522 | |
---|
523 | |
---|
524 | void SetupMaterials(void) |
---|
525 | { |
---|
526 | GLfloat mtn_ambuse[] = { 0.426, 0.256, 0.108, 1.0 }; |
---|
527 | GLfloat mtn_specular[] = { 0.394, 0.272, 0.167, 1.0 }; |
---|
528 | GLfloat mtn_shininess[] = { 10 }; |
---|
529 | |
---|
530 | GLfloat water_ambuse[] = { 0.0, 0.1, 0.5, 1.0 }; |
---|
531 | GLfloat water_specular[] = { 0.0, 0.1, 0.5, 1.0 }; |
---|
532 | GLfloat water_shininess[] = { 10 }; |
---|
533 | |
---|
534 | GLfloat tree_ambuse[] = { 0.4, 0.25, 0.1, 1.0 }; |
---|
535 | GLfloat tree_specular[] = { 0.0, 0.0, 0.0, 1.0 }; |
---|
536 | GLfloat tree_shininess[] = { 0 }; |
---|
537 | |
---|
538 | GLfloat leaf_ambuse[] = { 0.0, 0.8, 0.0, 1.0 }; |
---|
539 | GLfloat leaf_specular[] = { 0.0, 0.8, 0.0, 1.0 }; |
---|
540 | GLfloat leaf_shininess[] = { 10 }; |
---|
541 | |
---|
542 | glNewList(MOUNTAIN_MAT, GL_COMPILE); |
---|
543 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mtn_ambuse); |
---|
544 | glMaterialfv(GL_FRONT, GL_SPECULAR, mtn_specular); |
---|
545 | glMaterialfv(GL_FRONT, GL_SHININESS, mtn_shininess); |
---|
546 | glEndList(); |
---|
547 | |
---|
548 | glNewList(WATER_MAT, GL_COMPILE); |
---|
549 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, water_ambuse); |
---|
550 | glMaterialfv(GL_FRONT, GL_SPECULAR, water_specular); |
---|
551 | glMaterialfv(GL_FRONT, GL_SHININESS, water_shininess); |
---|
552 | glEndList(); |
---|
553 | |
---|
554 | glNewList(TREE_MAT, GL_COMPILE); |
---|
555 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tree_ambuse); |
---|
556 | glMaterialfv(GL_FRONT, GL_SPECULAR, tree_specular); |
---|
557 | glMaterialfv(GL_FRONT, GL_SHININESS, tree_shininess); |
---|
558 | glEndList(); |
---|
559 | |
---|
560 | glNewList(LEAF_MAT, GL_COMPILE); |
---|
561 | glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, leaf_ambuse); |
---|
562 | glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, leaf_specular); |
---|
563 | glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, leaf_shininess); |
---|
564 | glEndList(); |
---|
565 | } |
---|
566 | |
---|
567 | void myGLInit(void) |
---|
568 | { |
---|
569 | GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; |
---|
570 | GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; |
---|
571 | GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; |
---|
572 | GLfloat light_position[] = { 0.0, 0.3, 0.3, 0.0 }; |
---|
573 | |
---|
574 | GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 }; |
---|
575 | |
---|
576 | glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); |
---|
577 | glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); |
---|
578 | glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); |
---|
579 | glLightfv(GL_LIGHT0, GL_POSITION, light_position); |
---|
580 | |
---|
581 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); |
---|
582 | |
---|
583 | glEnable(GL_LIGHTING); |
---|
584 | glEnable(GL_LIGHT0); |
---|
585 | |
---|
586 | glDepthFunc(GL_LEQUAL); |
---|
587 | glEnable(GL_DEPTH_TEST); |
---|
588 | |
---|
589 | glEnable(GL_NORMALIZE); |
---|
590 | #if 0 |
---|
591 | glEnable(GL_CULL_FACE); |
---|
592 | glCullFace(GL_BACK); |
---|
593 | #endif |
---|
594 | |
---|
595 | glShadeModel(GL_SMOOTH); |
---|
596 | #if 0 |
---|
597 | glEnable(GL_BLEND); |
---|
598 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
---|
599 | #endif |
---|
600 | |
---|
601 | SetupMaterials(); |
---|
602 | CreateTreeLists(); |
---|
603 | |
---|
604 | glFlush(); |
---|
605 | } |
---|
606 | |
---|
607 | /***************************************************************/ |
---|
608 | /************************ GLUT STUFF ***************************/ |
---|
609 | /***************************************************************/ |
---|
610 | |
---|
611 | int winwidth = 1; |
---|
612 | int winheight = 1; |
---|
613 | |
---|
614 | void reshape(int w, int h) |
---|
615 | { |
---|
616 | glViewport(0,0,w,h); |
---|
617 | |
---|
618 | winwidth = w; |
---|
619 | winheight = h; |
---|
620 | } |
---|
621 | |
---|
622 | void display(void) |
---|
623 | { |
---|
624 | time_t curtime; |
---|
625 | char buf[255]; |
---|
626 | static time_t fpstime = 0; |
---|
627 | static int fpscount = 0; |
---|
628 | static int fps = 0; |
---|
629 | |
---|
630 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
---|
631 | |
---|
632 | glMatrixMode(GL_PROJECTION); |
---|
633 | glLoadIdentity(); |
---|
634 | gluPerspective(60.0, (GLdouble)winwidth/winheight, 0.01, 100); |
---|
635 | agvViewTransform(); |
---|
636 | |
---|
637 | glMatrixMode(GL_MODELVIEW); |
---|
638 | glLoadIdentity(); |
---|
639 | |
---|
640 | if (Rebuild) { |
---|
641 | Create(fractal); |
---|
642 | Rebuild = 0; |
---|
643 | } |
---|
644 | |
---|
645 | glCallList(fractal); |
---|
646 | |
---|
647 | if (DrawAxes) |
---|
648 | glCallList(AXES); |
---|
649 | |
---|
650 | glMatrixMode(GL_PROJECTION); |
---|
651 | glLoadIdentity(); |
---|
652 | gluOrtho2D(0.0, winwidth, 0.0, winheight); |
---|
653 | |
---|
654 | sprintf(buf, "FPS=%d", fps); |
---|
655 | glColor3f(1.0f, 1.0f, 1.0f); |
---|
656 | gl_font(FL_HELVETICA, 12); |
---|
657 | gl_draw(buf, 10, 10); |
---|
658 | |
---|
659 | // |
---|
660 | // Use glFinish() instead of glFlush() to avoid getting many frames |
---|
661 | // ahead of the display (problem with some Linux OpenGL implementations...) |
---|
662 | // |
---|
663 | |
---|
664 | glFinish(); |
---|
665 | |
---|
666 | // Update frames-per-second |
---|
667 | fpscount ++; |
---|
668 | curtime = time(NULL); |
---|
669 | if ((curtime - fpstime) >= 2) |
---|
670 | { |
---|
671 | fps = (fps + fpscount / (curtime - fpstime)) / 2; |
---|
672 | fpstime = curtime; |
---|
673 | fpscount = 0; |
---|
674 | } |
---|
675 | } |
---|
676 | |
---|
677 | void visible(int v) |
---|
678 | { |
---|
679 | if (v == GLUT_VISIBLE) |
---|
680 | agvSetAllowIdle(1); |
---|
681 | else { |
---|
682 | glutIdleFunc(NULL); |
---|
683 | agvSetAllowIdle(0); |
---|
684 | } |
---|
685 | } |
---|
686 | |
---|
687 | void menuuse(int v) |
---|
688 | { |
---|
689 | if (v == GLUT_MENU_NOT_IN_USE) |
---|
690 | agvSetAllowIdle(1); |
---|
691 | else { |
---|
692 | glutIdleFunc(NULL); |
---|
693 | agvSetAllowIdle(0); |
---|
694 | } |
---|
695 | } |
---|
696 | |
---|
697 | /***************************************************************/ |
---|
698 | /******************* MENU SETUP & HANDLING *********************/ |
---|
699 | /***************************************************************/ |
---|
700 | |
---|
701 | typedef enum { MENU_QUIT, MENU_RAND, MENU_MOVE, MENU_AXES } MenuChoices; |
---|
702 | |
---|
703 | void setlevel(int value) |
---|
704 | { |
---|
705 | Level = value; |
---|
706 | Rebuild = 1; |
---|
707 | glutPostRedisplay(); |
---|
708 | } |
---|
709 | |
---|
710 | void choosefract(int value) |
---|
711 | { |
---|
712 | fractal = value; |
---|
713 | Rebuild = 1; |
---|
714 | glutPostRedisplay(); |
---|
715 | } |
---|
716 | |
---|
717 | void handlemenu(int value) |
---|
718 | { |
---|
719 | switch (value) { |
---|
720 | case MENU_QUIT: |
---|
721 | exit(0); |
---|
722 | break; |
---|
723 | case MENU_RAND: |
---|
724 | NewFractals(); |
---|
725 | Rebuild = 1; |
---|
726 | glutPostRedisplay(); |
---|
727 | break; |
---|
728 | case MENU_AXES: |
---|
729 | DrawAxes = !DrawAxes; |
---|
730 | glutPostRedisplay(); |
---|
731 | break; |
---|
732 | } |
---|
733 | } |
---|
734 | |
---|
735 | void MenuInit(void) |
---|
736 | { |
---|
737 | int submenu3, submenu2, submenu1; |
---|
738 | |
---|
739 | submenu1 = glutCreateMenu(setlevel); |
---|
740 | glutAddMenuEntry((char *)"0", 0); glutAddMenuEntry((char *)"1", 1); |
---|
741 | glutAddMenuEntry((char *)"2", 2); glutAddMenuEntry((char *)"3", 3); |
---|
742 | glutAddMenuEntry((char *)"4", 4); glutAddMenuEntry((char *)"5", 5); |
---|
743 | glutAddMenuEntry((char *)"6", 6); glutAddMenuEntry((char *)"7", 7); |
---|
744 | glutAddMenuEntry((char *)"8", 8); |
---|
745 | |
---|
746 | submenu2 = glutCreateMenu(choosefract); |
---|
747 | glutAddMenuEntry((char *)"Moutain", MOUNTAIN); |
---|
748 | glutAddMenuEntry((char *)"Tree", TREE); |
---|
749 | glutAddMenuEntry((char *)"Island", ISLAND); |
---|
750 | |
---|
751 | submenu3 = glutCreateMenu(agvSwitchMoveMode); |
---|
752 | glutAddMenuEntry((char *)"Flying", FLYING); |
---|
753 | glutAddMenuEntry((char *)"Polar", POLAR); |
---|
754 | |
---|
755 | glutCreateMenu(handlemenu); |
---|
756 | glutAddSubMenu((char *)"Level", submenu1); |
---|
757 | glutAddSubMenu((char *)"Fractal", submenu2); |
---|
758 | glutAddSubMenu((char *)"Movement", submenu3); |
---|
759 | glutAddMenuEntry((char *)"New Fractal", MENU_RAND); |
---|
760 | glutAddMenuEntry((char *)"Toggle Axes", MENU_AXES); |
---|
761 | glutAddMenuEntry((char *)"Quit", MENU_QUIT); |
---|
762 | glutAttachMenu(GLUT_RIGHT_BUTTON); |
---|
763 | } |
---|
764 | |
---|
765 | |
---|
766 | /***************************************************************/ |
---|
767 | /**************************** MAIN *****************************/ |
---|
768 | /***************************************************************/ |
---|
769 | |
---|
770 | // FLTK-style callbacks to Glut menu callback translators: |
---|
771 | void setlevel(Fl_Widget*, void *value) {setlevel(long(value));} |
---|
772 | |
---|
773 | void choosefract(Fl_Widget*, void *value) {choosefract(long(value));} |
---|
774 | |
---|
775 | void handlemenu(Fl_Widget*, void *value) {handlemenu(long(value));} |
---|
776 | |
---|
777 | #include <FL/Fl_Button.H> |
---|
778 | #include <FL/Fl_Group.H> |
---|
779 | #include <FL/Fl_Window.H> |
---|
780 | |
---|
781 | int main(int argc, char** argv) |
---|
782 | { |
---|
783 | // glutInit(&argc, argv); // this line removed for FLTK |
---|
784 | |
---|
785 | // create FLTK window: |
---|
786 | Fl_Window window(512+20, 512+100); |
---|
787 | window.resizable(window); |
---|
788 | |
---|
789 | // create a bunch of buttons: |
---|
790 | Fl_Group *g = new Fl_Group(110,50,400-110,30,"Level:"); |
---|
791 | g->align(FL_ALIGN_LEFT); |
---|
792 | g->begin(); |
---|
793 | Fl_Button *b; |
---|
794 | b = new Fl_Button(110,50,30,30,"0"); b->callback(setlevel,(void*)0); |
---|
795 | b = new Fl_Button(140,50,30,30,"1"); b->callback(setlevel,(void*)1); |
---|
796 | b = new Fl_Button(170,50,30,30,"2"); b->callback(setlevel,(void*)2); |
---|
797 | b = new Fl_Button(200,50,30,30,"3"); b->callback(setlevel,(void*)3); |
---|
798 | b = new Fl_Button(230,50,30,30,"4"); b->callback(setlevel,(void*)4); |
---|
799 | b = new Fl_Button(260,50,30,30,"5"); b->callback(setlevel,(void*)5); |
---|
800 | b = new Fl_Button(290,50,30,30,"6"); b->callback(setlevel,(void*)6); |
---|
801 | b = new Fl_Button(320,50,30,30,"7"); b->callback(setlevel,(void*)7); |
---|
802 | b = new Fl_Button(350,50,30,30,"8"); b->callback(setlevel,(void*)8); |
---|
803 | g->end(); |
---|
804 | |
---|
805 | b = new Fl_Button(400,50,100,30,"New Fractal"); b->callback(handlemenu,(void*)MENU_RAND); |
---|
806 | |
---|
807 | b = new Fl_Button( 10,10,100,30,"Mountain"); b->callback(choosefract,(void*)MOUNTAIN); |
---|
808 | b = new Fl_Button(110,10,100,30,"Tree"); b->callback(choosefract,(void*)TREE); |
---|
809 | b = new Fl_Button(210,10,100,30,"Island"); b->callback(choosefract,(void*)ISLAND); |
---|
810 | b = new Fl_Button(400,10,100,30,"Quit"); b->callback(handlemenu,(void*)MENU_QUIT); |
---|
811 | |
---|
812 | |
---|
813 | window.show(argc,argv); // glut will die unless parent window visible |
---|
814 | window.begin(); // this will cause Glut window to be a child |
---|
815 | glutInitWindowSize(512, 512); |
---|
816 | glutInitWindowPosition(10,90); // place it inside parent window |
---|
817 | glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE); |
---|
818 | glutCreateWindow("Fractal Planet?"); |
---|
819 | window.end(); |
---|
820 | window.resizable(glut_window); |
---|
821 | |
---|
822 | agvInit(1); /* 1 cause we don't have our own idle */ |
---|
823 | |
---|
824 | glutReshapeFunc(reshape); |
---|
825 | glutDisplayFunc(display); |
---|
826 | glutVisibilityFunc(visible); |
---|
827 | glutMenuStateFunc(menuuse); |
---|
828 | |
---|
829 | NewFractals(); |
---|
830 | agvMakeAxesList(AXES); |
---|
831 | myGLInit(); |
---|
832 | MenuInit(); |
---|
833 | |
---|
834 | glutMainLoop(); // you could use Fl::run() instead |
---|
835 | |
---|
836 | return 0; |
---|
837 | } |
---|
838 | #endif |
---|
839 | |
---|
840 | // |
---|
841 | // End of "$Id$". |
---|
842 | // |
---|