You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

840 lines
22KB

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