4b561b6e90
Updated the configure script for *BSD and GCC 2.95 (-fno-exceptions) Added install rule to documentation directory. Dumped old packages directory; added traditional RPM spec file and EPM list file (that replace all of the packages stuff) The FLUID man page is now "fluid.1" for the formatted page and "fluid.man" for the non-formatted page, since only IRIX uses pack'd formatted man pages. Whew! git-svn-id: file:///fltk/svn/fltk/branches/branch-1.0@1090 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
810 lines
22 KiB
C++
810 lines
22 KiB
C++
//
|
|
// "$Id: fractals.cxx,v 1.5.2.2 2000/04/25 22:16:54 mike Exp $"
|
|
//
|
|
// Fractal drawing demo for the Fast Light Tool Kit (FLTK).
|
|
//
|
|
// This is a GLUT demo program, with modifications to
|
|
// demonstrate how to add fltk controls to a glut program. The glut
|
|
// code is unchanged except for the end (search for fltk to find changes).
|
|
//
|
|
// Copyright 1998-2000 by Bill Spitzak and others.
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Library General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Library General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Library General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
// USA.
|
|
//
|
|
// Please report all bugs and problems to "fltk-bugs@easysw.com".
|
|
//
|
|
|
|
#include <config.h>
|
|
#if !HAVE_GL
|
|
#include <FL/Fl.H>
|
|
#include <FL/fl_message.H>
|
|
int main(int, char**) {
|
|
fl_alert("This demo does not work without GL");
|
|
return 1;
|
|
}
|
|
#else
|
|
/*
|
|
* To compile: cc -o fractals fractals.c -lGL -lGLU -lX11 -lglut -lXmu -lm
|
|
*
|
|
* Usage: fractals
|
|
*
|
|
* Homework 6, Part 2: fractal mountains and fractal trees
|
|
* (Pretty Late)
|
|
*
|
|
* Draws fractal mountains and trees -- and an island of mountains in water
|
|
* (I tried having trees on the island but it didn't work too well.)
|
|
*
|
|
* Two viewer modes: polar and flying (both restrained to y>0 for up vector).
|
|
* Keyboard 0->9 and +/- control speed when flying.
|
|
*
|
|
* Only keyboard commands are 0-9 and +/- for speed in flying mode.
|
|
*
|
|
* Fog would make the island look much better, but I couldn't get it to work
|
|
* correctly. Would line up on -z axis not from eye.
|
|
*
|
|
* Philip Winston - 3/4/95
|
|
* pwinston@hmc.edu
|
|
* http://www.cs.hmc.edu/people/pwinston
|
|
*
|
|
*/
|
|
|
|
#include <FL/glut.H>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <limits.h> /* ULONG_MAX is defined here */
|
|
#include <float.h> /* FLT_MAX is atleast defined here */
|
|
|
|
#include <time.h> /* for random seed */
|
|
|
|
#include "fracviewer.c" // changed from .h for fltk
|
|
|
|
#if defined(WIN32) || defined(__EMX__)
|
|
#define drand48() (((float) rand())/((float) RAND_MAX))
|
|
#define srand48(x) (srand((x)))
|
|
#endif
|
|
|
|
typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF,
|
|
MOUNTAIN_MAT, WATER_MAT, LEAF_MAT, TREE_MAT, STEMANDLEAVES,
|
|
AXES } DisplayLists;
|
|
|
|
#define MAXLEVEL 8
|
|
|
|
int Rebuild = 1, /* Rebuild display list in next display? */
|
|
Fract = TREE, /* What fractal are we building */
|
|
Level = 4; /* levels of recursion for fractals */
|
|
|
|
int DrawAxes = 0;
|
|
|
|
/***************************************************************/
|
|
/************************* VECTOR JUNK *************************/
|
|
/***************************************************************/
|
|
|
|
/* print vertex to stderr */
|
|
void printvert(float v[3])
|
|
{
|
|
fprintf(stderr, "(%f, %f, %f)\n", v[0], v[1], v[2]);
|
|
}
|
|
|
|
#if 0 // removed for FL, it is in fracviewer.c
|
|
/* normalizes v */
|
|
void normalize(GLfloat v[3])
|
|
{
|
|
GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
|
|
|
if (d == 0)
|
|
fprintf(stderr, "Zero length vector in normalize\n");
|
|
else
|
|
v[0] /= d; v[1] /= d; v[2] /= d;
|
|
}
|
|
|
|
/* calculates a normalized crossproduct to v1, v2 */
|
|
void ncrossprod(float v1[3], float v2[3], float cp[3])
|
|
{
|
|
cp[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
|
cp[1] = v1[2]*v2[0] - v1[0]*v2[2];
|
|
cp[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
|
normalize(cp);
|
|
}
|
|
#endif
|
|
|
|
/* calculates normal to the triangle designated by v1, v2, v3 */
|
|
void triagnormal(float v1[3], float v2[3], float v3[3], float norm[3])
|
|
{
|
|
float vec1[3], vec2[3];
|
|
|
|
vec1[0] = v3[0] - v1[0]; vec2[0] = v2[0] - v1[0];
|
|
vec1[1] = v3[1] - v1[1]; vec2[1] = v2[1] - v1[1];
|
|
vec1[2] = v3[2] - v1[2]; vec2[2] = v2[2] - v1[2];
|
|
|
|
ncrossprod(vec2, vec1, norm);
|
|
}
|
|
|
|
float xzlength(float v1[3], float v2[3])
|
|
{
|
|
return sqrt((v1[0] - v2[0])*(v1[0] - v2[0]) +
|
|
(v1[2] - v2[2])*(v1[2] - v2[2]));
|
|
}
|
|
|
|
float xzslope(float v1[3], float v2[3])
|
|
{
|
|
return ((v1[0] != v2[0]) ? ((v1[2] - v2[2]) / (v1[0] - v2[0]))
|
|
: FLT_MAX);
|
|
}
|
|
|
|
|
|
/***************************************************************/
|
|
/************************ MOUNTAIN STUFF ***********************/
|
|
/***************************************************************/
|
|
|
|
GLfloat DispFactor[MAXLEVEL]; /* Array of what to multiply random number
|
|
by for a given level to get midpoint
|
|
displacement */
|
|
GLfloat DispBias[MAXLEVEL]; /* Array of what to add to random number
|
|
before multiplying it by DispFactor */
|
|
|
|
#define NUMRANDS 191
|
|
float RandTable[NUMRANDS]; /* hash table of random numbers so we can
|
|
raise the same midpoints by the same amount */
|
|
|
|
/* The following are for permitting an edge of a moutain to be */
|
|
/* pegged so it won't be displaced up or down. This makes it */
|
|
/* easier to setup scenes and makes a single moutain look better */
|
|
|
|
GLfloat Verts[3][3], /* Vertices of outside edges of mountain */
|
|
Slopes[3]; /* Slopes between these outside edges */
|
|
int Pegged[3]; /* Is this edge pegged or not */
|
|
|
|
/*
|
|
* Comes up with a new table of random numbers [0,1)
|
|
*/
|
|
void InitRandTable(unsigned int seed)
|
|
{
|
|
int i;
|
|
|
|
srand48((long) seed);
|
|
for (i = 0; i < NUMRANDS; i++)
|
|
RandTable[i] = drand48() - 0.5;
|
|
}
|
|
|
|
/* calculate midpoint and displace it if required */
|
|
void Midpoint(GLfloat mid[3], GLfloat v1[3], GLfloat v2[3],
|
|
int edge, int level)
|
|
{
|
|
unsigned hash;
|
|
|
|
mid[0] = (v1[0] + v2[0]) / 2;
|
|
mid[1] = (v1[1] + v2[1]) / 2;
|
|
mid[2] = (v1[2] + v2[2]) / 2;
|
|
if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid)
|
|
- Slopes[edge]) > 0.00001)) {
|
|
srand48((int)((v1[0]+v2[0])*23344));
|
|
hash = unsigned(drand48() * 7334334);
|
|
srand48((int)((v2[2]+v1[2])*43433));
|
|
hash = (unsigned)(drand48() * 634344 + hash) % NUMRANDS;
|
|
mid[1] += ((RandTable[hash] + DispBias[level]) * DispFactor[level]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Recursive moutain drawing routine -- from lecture with addition of
|
|
* allowing an edge to be pegged. This function requires the above
|
|
* globals to be set, as well as the Level global for fractal level
|
|
*/
|
|
static float cutoff = -1;
|
|
|
|
void FMR(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int level)
|
|
{
|
|
if (level == Level) {
|
|
GLfloat norm[3];
|
|
if (v1[1] <= cutoff && v2[1]<=cutoff && v3[1]<=cutoff) return;
|
|
triagnormal(v1, v2, v3, norm);
|
|
glNormal3fv(norm);
|
|
glVertex3fv(v1);
|
|
glVertex3fv(v2);
|
|
glVertex3fv(v3);
|
|
|
|
} else {
|
|
GLfloat m1[3], m2[3], m3[3];
|
|
|
|
Midpoint(m1, v1, v2, 0, level);
|
|
Midpoint(m2, v2, v3, 1, level);
|
|
Midpoint(m3, v3, v1, 2, level);
|
|
|
|
FMR(v1, m1, m3, level + 1);
|
|
FMR(m1, v2, m2, level + 1);
|
|
FMR(m3, m2, v3, level + 1);
|
|
FMR(m1, m2, m3, level + 1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* sets up lookup tables and calls recursive mountain function
|
|
*/
|
|
void FractalMountain(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3],
|
|
int pegged[3])
|
|
{
|
|
GLfloat lengths[MAXLEVEL];
|
|
GLfloat fraction[8] = { 0.3, 0.3, 0.4, 0.2, 0.3, 0.2, 0.4, 0.4 };
|
|
GLfloat bias[8] = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 };
|
|
int i;
|
|
float avglen = (xzlength(v1, v2) +
|
|
xzlength(v2, v3) +
|
|
xzlength(v3, v1) / 3);
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
Verts[0][i] = v1[i]; /* set mountain vertex globals */
|
|
Verts[1][i] = v2[i];
|
|
Verts[2][i] = v3[i];
|
|
Pegged[i] = pegged[i];
|
|
}
|
|
|
|
Slopes[0] = xzslope(Verts[0], Verts[1]); /* set edge slope globals */
|
|
Slopes[1] = xzslope(Verts[1], Verts[2]);
|
|
Slopes[2] = xzslope(Verts[2], Verts[0]);
|
|
|
|
lengths[0] = avglen;
|
|
for (i = 1; i < Level; i++) {
|
|
lengths[i] = lengths[i-1]/2; /* compute edge length for each level */
|
|
}
|
|
|
|
for (i = 0; i < Level; i++) { /* DispFactor and DispBias arrays */
|
|
DispFactor[i] = (lengths[i] * ((i <= 7) ? fraction[i] : fraction[7]));
|
|
DispBias[i] = ((i <= 7) ? bias[i] : bias[7]);
|
|
}
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
FMR(v1, v2, v3, 0); /* issues no GL but vertex calls */
|
|
glEnd();
|
|
}
|
|
|
|
/*
|
|
* draw a mountain and build the display list
|
|
*/
|
|
void CreateMountain(void)
|
|
{
|
|
GLfloat v1[3] = { 0, 0, -1 }, v2[3] = { -1, 0, 1 }, v3[3] = { 1, 0, 1 };
|
|
int pegged[3] = { 1, 1, 1 };
|
|
|
|
glNewList(MOUNTAIN, GL_COMPILE);
|
|
glPushAttrib(GL_LIGHTING_BIT);
|
|
glCallList(MOUNTAIN_MAT);
|
|
FractalMountain(v1, v2, v3, pegged);
|
|
glPopAttrib();
|
|
glEndList();
|
|
}
|
|
|
|
/*
|
|
* new random numbers to make a different moutain
|
|
*/
|
|
void NewMountain(void)
|
|
{
|
|
InitRandTable(time(NULL));
|
|
}
|
|
|
|
/***************************************************************/
|
|
/***************************** TREE ****************************/
|
|
/***************************************************************/
|
|
|
|
long TreeSeed; /* for srand48 - remember so we can build "same tree"
|
|
at a different level */
|
|
|
|
/*
|
|
* recursive tree drawing thing, fleshed out from class notes pseudocode
|
|
*/
|
|
void FractalTree(int level)
|
|
{
|
|
long savedseed; /* need to save seeds while building tree too */
|
|
|
|
if (level == Level) {
|
|
glPushMatrix();
|
|
glRotatef(drand48()*180, 0, 1, 0);
|
|
glCallList(STEMANDLEAVES);
|
|
glPopMatrix();
|
|
} else {
|
|
glCallList(STEM);
|
|
glPushMatrix();
|
|
glRotatef(drand48()*180, 0, 1, 0);
|
|
glTranslatef(0, 1, 0);
|
|
glScalef(0.7, 0.7, 0.7);
|
|
|
|
savedseed = (long)((ulong)drand48()*ULONG_MAX);
|
|
glPushMatrix();
|
|
glRotatef(110 + drand48()*40, 0, 1, 0);
|
|
glRotatef(30 + drand48()*20, 0, 0, 1);
|
|
FractalTree(level + 1);
|
|
glPopMatrix();
|
|
|
|
srand48(savedseed);
|
|
savedseed = (long)((ulong)drand48()*ULONG_MAX);
|
|
glPushMatrix();
|
|
glRotatef(-130 + drand48()*40, 0, 1, 0);
|
|
glRotatef(30 + drand48()*20, 0, 0, 1);
|
|
FractalTree(level + 1);
|
|
glPopMatrix();
|
|
|
|
srand48(savedseed);
|
|
glPushMatrix();
|
|
glRotatef(-20 + drand48()*40, 0, 1, 0);
|
|
glRotatef(30 + drand48()*20, 0, 0, 1);
|
|
FractalTree(level + 1);
|
|
glPopMatrix();
|
|
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Create display lists for a leaf, a set of leaves, and a stem
|
|
*/
|
|
void CreateTreeLists(void)
|
|
{
|
|
GLUquadricObj *cylquad = gluNewQuadric();
|
|
int i;
|
|
|
|
glNewList(STEM, GL_COMPILE);
|
|
glPushMatrix();
|
|
glRotatef(-90, 1, 0, 0);
|
|
gluCylinder(cylquad, 0.1, 0.08, 1, 10, 2 );
|
|
glPopMatrix();
|
|
glEndList();
|
|
|
|
glNewList(LEAF, GL_COMPILE); /* I think this was jeff allen's leaf idea */
|
|
glBegin(GL_TRIANGLES);
|
|
glNormal3f(-0.1, 0, 0.25); /* not normalized */
|
|
glVertex3f(0, 0, 0);
|
|
glVertex3f(0.25, 0.25, 0.1);
|
|
glVertex3f(0, 0.5, 0);
|
|
|
|
glNormal3f(0.1, 0, 0.25);
|
|
glVertex3f(0, 0, 0);
|
|
glVertex3f(0, 0.5, 0);
|
|
glVertex3f(-0.25, 0.25, 0.1);
|
|
glEnd();
|
|
glEndList();
|
|
|
|
glNewList(STEMANDLEAVES, GL_COMPILE);
|
|
glPushMatrix();
|
|
glPushAttrib(GL_LIGHTING_BIT);
|
|
glCallList(STEM);
|
|
glCallList(LEAF_MAT);
|
|
for(i = 0; i < 3; i++) {
|
|
glTranslatef(0, 0.333, 0);
|
|
glRotatef(90, 0, 1, 0);
|
|
glPushMatrix();
|
|
glRotatef(0, 0, 1, 0);
|
|
glRotatef(50, 1, 0, 0);
|
|
glCallList(LEAF);
|
|
glPopMatrix();
|
|
glPushMatrix();
|
|
glRotatef(180, 0, 1, 0);
|
|
glRotatef(60, 1, 0, 0);
|
|
glCallList(LEAF);
|
|
glPopMatrix();
|
|
}
|
|
glPopAttrib();
|
|
glPopMatrix();
|
|
glEndList();
|
|
|
|
gluDeleteQuadric(cylquad);
|
|
}
|
|
|
|
/*
|
|
* draw and build display list for tree
|
|
*/
|
|
void CreateTree(void)
|
|
{
|
|
srand48(TreeSeed);
|
|
|
|
glNewList(TREE, GL_COMPILE);
|
|
glPushMatrix();
|
|
glPushAttrib(GL_LIGHTING_BIT);
|
|
glCallList(TREE_MAT);
|
|
glTranslatef(0, -1, 0);
|
|
FractalTree(0);
|
|
glPopAttrib();
|
|
glPopMatrix();
|
|
glEndList();
|
|
}
|
|
|
|
/*
|
|
* new seed for a new tree (groan)
|
|
*/
|
|
void NewTree(void)
|
|
{
|
|
TreeSeed = time(NULL);
|
|
}
|
|
|
|
/***************************************************************/
|
|
/*********************** FRACTAL PLANET ************************/
|
|
/***************************************************************/
|
|
|
|
void CreateIsland(void)
|
|
{
|
|
cutoff = .06;
|
|
CreateMountain();
|
|
cutoff = -1;
|
|
glNewList(ISLAND, GL_COMPILE);
|
|
glPushAttrib(GL_LIGHTING_BIT);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glCallList(WATER_MAT);
|
|
|
|
glBegin(GL_QUADS);
|
|
glNormal3f(0, 1, 0);
|
|
glVertex3f(10, 0.01, 10);
|
|
glVertex3f(10, 0.01, -10);
|
|
glVertex3f(-10, 0.01, -10);
|
|
glVertex3f(-10, 0.01, 10);
|
|
glEnd();
|
|
|
|
glPushMatrix();
|
|
glTranslatef(0, -0.1, 0);
|
|
glCallList(MOUNTAIN);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glRotatef(135, 0, 1, 0);
|
|
glTranslatef(0.2, -0.15, -0.4);
|
|
glCallList(MOUNTAIN);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glRotatef(-60, 0, 1, 0);
|
|
glTranslatef(0.7, -0.07, 0.5);
|
|
glCallList(MOUNTAIN);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glRotatef(-175, 0, 1, 0);
|
|
glTranslatef(-0.7, -0.05, -0.5);
|
|
glCallList(MOUNTAIN);
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glRotatef(165, 0, 1, 0);
|
|
glTranslatef(-0.9, -0.12, 0.0);
|
|
glCallList(MOUNTAIN);
|
|
glPopMatrix();
|
|
|
|
glPopMatrix();
|
|
glPopAttrib();
|
|
glEndList();
|
|
}
|
|
|
|
|
|
void NewFractals(void)
|
|
{
|
|
NewMountain();
|
|
NewTree();
|
|
}
|
|
|
|
void Create(int fract)
|
|
{
|
|
switch(fract) {
|
|
case MOUNTAIN:
|
|
CreateMountain();
|
|
break;
|
|
case TREE:
|
|
CreateTree();
|
|
break;
|
|
case ISLAND:
|
|
CreateIsland();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************/
|
|
/**************************** OPENGL ***************************/
|
|
/***************************************************************/
|
|
|
|
|
|
void SetupMaterials(void)
|
|
{
|
|
GLfloat mtn_ambuse[] = { 0.426, 0.256, 0.108, 1.0 };
|
|
GLfloat mtn_specular[] = { 0.394, 0.272, 0.167, 1.0 };
|
|
GLfloat mtn_shininess[] = { 10 };
|
|
|
|
GLfloat water_ambuse[] = { 0.0, 0.1, 0.5, 1.0 };
|
|
GLfloat water_specular[] = { 0.0, 0.1, 0.5, 1.0 };
|
|
GLfloat water_shininess[] = { 10 };
|
|
|
|
GLfloat tree_ambuse[] = { 0.4, 0.25, 0.1, 1.0 };
|
|
GLfloat tree_specular[] = { 0.0, 0.0, 0.0, 1.0 };
|
|
GLfloat tree_shininess[] = { 0 };
|
|
|
|
GLfloat leaf_ambuse[] = { 0.0, 0.8, 0.0, 1.0 };
|
|
GLfloat leaf_specular[] = { 0.0, 0.8, 0.0, 1.0 };
|
|
GLfloat leaf_shininess[] = { 10 };
|
|
|
|
glNewList(MOUNTAIN_MAT, GL_COMPILE);
|
|
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mtn_ambuse);
|
|
glMaterialfv(GL_FRONT, GL_SPECULAR, mtn_specular);
|
|
glMaterialfv(GL_FRONT, GL_SHININESS, mtn_shininess);
|
|
glEndList();
|
|
|
|
glNewList(WATER_MAT, GL_COMPILE);
|
|
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, water_ambuse);
|
|
glMaterialfv(GL_FRONT, GL_SPECULAR, water_specular);
|
|
glMaterialfv(GL_FRONT, GL_SHININESS, water_shininess);
|
|
glEndList();
|
|
|
|
glNewList(TREE_MAT, GL_COMPILE);
|
|
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tree_ambuse);
|
|
glMaterialfv(GL_FRONT, GL_SPECULAR, tree_specular);
|
|
glMaterialfv(GL_FRONT, GL_SHININESS, tree_shininess);
|
|
glEndList();
|
|
|
|
glNewList(LEAF_MAT, GL_COMPILE);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, leaf_ambuse);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, leaf_specular);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, leaf_shininess);
|
|
glEndList();
|
|
}
|
|
|
|
void myGLInit(void)
|
|
{
|
|
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
|
|
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
|
|
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
|
|
GLfloat light_position[] = { 0.0, 0.3, 0.3, 0.0 };
|
|
|
|
GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
|
|
|
|
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
|
|
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
|
|
|
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
glEnable(GL_LIGHT0);
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_NORMALIZE);
|
|
#if 0
|
|
glEnable(GL_CULL_FACE);
|
|
glCullFace(GL_BACK);
|
|
#endif
|
|
|
|
glShadeModel(GL_SMOOTH);
|
|
#if 0
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
#endif
|
|
|
|
SetupMaterials();
|
|
CreateTreeLists();
|
|
|
|
glFlush();
|
|
}
|
|
|
|
/***************************************************************/
|
|
/************************ GLUT STUFF ***************************/
|
|
/***************************************************************/
|
|
|
|
void reshape(int w, int h)
|
|
{
|
|
glViewport(0,0,w,h);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(60.0, (GLdouble)w/h, 0.01, 100);
|
|
glPushMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glFlush();
|
|
}
|
|
|
|
void display(void)
|
|
{
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glFlush();
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glPushMatrix(); /* clear of last viewing xform, leaving perspective */
|
|
|
|
agvViewTransform();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
if (Rebuild) {
|
|
Create(Fract);
|
|
Rebuild = 0;
|
|
}
|
|
|
|
glCallList(Fract);
|
|
|
|
if (DrawAxes)
|
|
glCallList(AXES);
|
|
|
|
glutSwapBuffers();
|
|
glFlush();
|
|
}
|
|
|
|
void visible(int v)
|
|
{
|
|
if (v == GLUT_VISIBLE)
|
|
agvSetAllowIdle(1);
|
|
else {
|
|
glutIdleFunc(NULL);
|
|
agvSetAllowIdle(0);
|
|
}
|
|
}
|
|
|
|
void menuuse(int v)
|
|
{
|
|
if (v == GLUT_MENU_NOT_IN_USE)
|
|
agvSetAllowIdle(1);
|
|
else {
|
|
glutIdleFunc(NULL);
|
|
agvSetAllowIdle(0);
|
|
}
|
|
}
|
|
|
|
/***************************************************************/
|
|
/******************* MENU SETUP & HANDLING *********************/
|
|
/***************************************************************/
|
|
|
|
typedef enum { MENU_QUIT, MENU_RAND, MENU_MOVE, MENU_AXES } MenuChoices;
|
|
|
|
void setlevel(int value)
|
|
{
|
|
Level = value;
|
|
Rebuild = 1;
|
|
glutPostRedisplay();
|
|
}
|
|
|
|
void choosefract(int value)
|
|
{
|
|
Fract = value;
|
|
Rebuild = 1;
|
|
glutPostRedisplay();
|
|
}
|
|
|
|
void handlemenu(int value)
|
|
{
|
|
switch (value) {
|
|
case MENU_QUIT:
|
|
exit(0);
|
|
break;
|
|
case MENU_RAND:
|
|
NewFractals();
|
|
Rebuild = 1;
|
|
glutPostRedisplay();
|
|
break;
|
|
case MENU_AXES:
|
|
DrawAxes = !DrawAxes;
|
|
glutPostRedisplay();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MenuInit(void)
|
|
{
|
|
int submenu3, submenu2, submenu1;
|
|
|
|
submenu1 = glutCreateMenu(setlevel);
|
|
glutAddMenuEntry("0", 0); glutAddMenuEntry("1", 1);
|
|
glutAddMenuEntry("2", 2); glutAddMenuEntry("3", 3);
|
|
glutAddMenuEntry("4", 4); glutAddMenuEntry("5", 5);
|
|
glutAddMenuEntry("6", 6); glutAddMenuEntry("7", 7);
|
|
glutAddMenuEntry("8", 8);
|
|
|
|
submenu2 = glutCreateMenu(choosefract);
|
|
glutAddMenuEntry("Moutain", MOUNTAIN);
|
|
glutAddMenuEntry("Tree", TREE);
|
|
glutAddMenuEntry("Island", ISLAND);
|
|
|
|
submenu3 = glutCreateMenu(agvSwitchMoveMode);
|
|
glutAddMenuEntry("Flying", FLYING);
|
|
glutAddMenuEntry("Polar", POLAR);
|
|
|
|
glutCreateMenu(handlemenu);
|
|
glutAddSubMenu("Level", submenu1);
|
|
glutAddSubMenu("Fractal", submenu2);
|
|
glutAddSubMenu("Movement", submenu3);
|
|
glutAddMenuEntry("New Fractal", MENU_RAND);
|
|
glutAddMenuEntry("Toggle Axes", MENU_AXES);
|
|
glutAddMenuEntry("Quit", MENU_QUIT);
|
|
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
|
}
|
|
|
|
|
|
/***************************************************************/
|
|
/**************************** MAIN *****************************/
|
|
/***************************************************************/
|
|
|
|
// fltk-style callbacks to Glut menu callback translators:
|
|
void setlevel(Fl_Widget*, void *value) {setlevel(long(value));}
|
|
|
|
void choosefract(Fl_Widget*, void *value) {choosefract(long(value));}
|
|
|
|
void handlemenu(Fl_Widget*, void *value) {handlemenu(long(value));}
|
|
|
|
#include <FL/Fl_Button.H>
|
|
#include <FL/Fl_Group.H>
|
|
#include <FL/Fl_Window.H>
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
// glutInit(&argc, argv); // this line removed for fltk
|
|
|
|
// create fltk window:
|
|
Fl_Window window(512+20, 512+100);
|
|
window.resizable(window);
|
|
|
|
// create a bunch of buttons:
|
|
Fl_Group *g = new Fl_Group(110,50,400-110,30,"Level:");
|
|
g->align(FL_ALIGN_LEFT);
|
|
g->begin();
|
|
Fl_Button *b;
|
|
b = new Fl_Button(110,50,30,30,"0"); b->callback(setlevel,(void*)0);
|
|
b = new Fl_Button(140,50,30,30,"1"); b->callback(setlevel,(void*)1);
|
|
b = new Fl_Button(170,50,30,30,"2"); b->callback(setlevel,(void*)2);
|
|
b = new Fl_Button(200,50,30,30,"3"); b->callback(setlevel,(void*)3);
|
|
b = new Fl_Button(230,50,30,30,"4"); b->callback(setlevel,(void*)4);
|
|
b = new Fl_Button(260,50,30,30,"5"); b->callback(setlevel,(void*)5);
|
|
b = new Fl_Button(290,50,30,30,"6"); b->callback(setlevel,(void*)6);
|
|
b = new Fl_Button(320,50,30,30,"7"); b->callback(setlevel,(void*)7);
|
|
b = new Fl_Button(350,50,30,30,"8"); b->callback(setlevel,(void*)8);
|
|
g->end();
|
|
|
|
b = new Fl_Button(400,50,100,30,"New Fractal"); b->callback(handlemenu,(void*)MENU_RAND);
|
|
|
|
b = new Fl_Button( 10,10,100,30,"Mountain"); b->callback(choosefract,(void*)MOUNTAIN);
|
|
b = new Fl_Button(110,10,100,30,"Tree"); b->callback(choosefract,(void*)TREE);
|
|
b = new Fl_Button(210,10,100,30,"Island"); b->callback(choosefract,(void*)ISLAND);
|
|
b = new Fl_Button(400,10,100,30,"Quit"); b->callback(handlemenu,(void*)MENU_QUIT);
|
|
|
|
|
|
window.show(argc,argv); // glut will die unless parent window visible
|
|
window.begin(); // this will cause Glut window to be a child
|
|
glutInitWindowSize(512, 512);
|
|
glutInitWindowPosition(10,90); // place it inside parent window
|
|
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
|
|
glutCreateWindow("Fractal Planet?");
|
|
window.end();
|
|
window.resizable(glut_window);
|
|
|
|
agvInit(1); /* 1 cause we don't have our own idle */
|
|
|
|
glutReshapeFunc(reshape);
|
|
glutDisplayFunc(display);
|
|
glutVisibilityFunc(visible);
|
|
glutMenuStateFunc(menuuse);
|
|
|
|
NewFractals();
|
|
agvMakeAxesList(AXES);
|
|
myGLInit();
|
|
MenuInit();
|
|
|
|
glutMainLoop(); // you could use Fl::run() instead
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// End of "$Id: fractals.cxx,v 1.5.2.2 2000/04/25 22:16:54 mike Exp $".
|
|
//
|