home *** CD-ROM | disk | FTP | other *** search
- // This may look like C code, but it is really -*- C++ -*-
- /*
- ************************************************************************
- *
- * Generating Fractal Maps
- *
- * We use the following algorithm described in the "documentation" to
- * program MARS (Tim Clarke, tjc1005@hermes.cam.ac.uk, posted in some "games"
- * group)
- *
- * "This is a recursive subdivision, or plasma, fractal. You start of
- * with a random height at (0,0) and therefore also at (256,0), (0,256),
- * (256,256). Call a routine that takes as input the size and position
- * of a square, in the first case the entire map.
- * This routine get the heights from the corners of the square it gets
- * given. Across each edge (if the map has not been written to at the
- * point halfway along that edge), it takes the average of the heights of
- * the 2 corners on that edge, applies some noise proportional to the
- * length of the edge, and writes the result into the map at a position
- * halfway along the edge. The center of the square is the average of the
- * four corners+noise.
- * The routine then calls itself recursively, splitting each square into
- * four quadrants, calling itself for each quadrant until the length of
- * the side is 2 pixels.
- * This is probably old-hat to many people, but the map is made more
- * realistic by blurring [applying some filter to it]
- * The colors are done so that the sun is on the horizon to the East:
- * Color=A*[ w(u+1,v)-w(u,v) ]+B
- * with A and B chosen so that the full range of the palette is used.
- * The sky is a similar fractal but without the colour transformation"
- * <EOQ>
- *
- * Again, one can achieve this effect by applying an appropriate filter.
- * In principle, the filter for blurring and the filter for coloring
- * (the latter looks like a simple gradient/edge enhancement filter)
- * can be combined in a single one.
- *
- * In the present program, we use an iterative rather than recursive
- * procedure.
- *
- ************************************************************************
- */
-
- #include "image.h"
-
- // Fractal "cloud"
- class FractalMap : public IMAGE
- {
- void make_fractal_map(const int scale);
-
- public:
- FractalMap(const int dimension);
- ~FractalMap(void) {}
-
- void display(const char * title) const;
-
- };
-
- // Construng a fractal "cloud"
- FractalMap::FractalMap(const int dimension) : IMAGE(dimension,dimension,8)
- {
- (*this)(0,0) = 128; // Seed
-
- register int scale;
- for(scale=dimension; scale>1; scale >>= 1)
- make_fractal_map(scale);
- }
-
- // Get some noise with a dispersion 'scale'
- // (which is assumed to be a power of 2)
- // and average 0
- // Say, if scale=2 return either 0 or 1
- // if scale=128, return the random number
- // within [-64,63]
- // Note, that usually a couple of low-order
- // bits of Random() are "less" random; therefore,
- // we shift them out.
- static int get_noise(const int scale)
- {
- return ((Random() >> 2) & (scale-1)) - scale/2;
- }
-
- // Make the fractal map at a specified scale
- // Keep in mind "wrap-around" property of
- // the map
- void FractalMap::make_fractal_map(const int scale)
- {
- register int i, j;
- for(i=0; i<q_nrows(); i += scale)
- for(j=0; j<q_ncols(); j += scale)
- {
- int i_up = i+scale; if( i_up >= q_nrows() ) i_up-=q_nrows();
- int j_up = j+scale; if( j_up >= q_ncols() ) j_up-=q_ncols();
- int i_hp = i+scale/2; if( i_hp >= q_nrows() ) i_hp-=q_nrows();
- int j_hp = j+scale/2; if( j_hp >= q_ncols() ) j_hp-=q_ncols();
- int corner00 = (*this)(i,j);
- int corner10 = (*this)(i_up,j);
- int corner01 = (*this)(i,j_up);
- int corner11 = (*this)(i_up,j_up);
- //message("i %d, j%d, scale %d Corners %d %d %d %d",i,j,scale,corner00,corner01,corner10,corner11);
- int mid30 = (*this)(i_hp,j) = (corner00+corner10)/2 + get_noise(scale);
- int mid03 = (*this)(i,j_hp) = (corner00+corner01)/2 + get_noise(scale);
- int mid31 = (*this)(i_hp,j_up) = (corner01+corner11)/2 + get_noise(scale);
- int mid13 = (*this)(i_up,j_hp) = (corner10+corner11)/2 + get_noise(scale);
- (*this)(i_hp,j_hp) = (mid30+mid03+mid31+mid13)/4 + get_noise(scale);
- }
-
- }
-
-
- void display_map(const IMAGE& image, const char * title);
- void project_3D(const IMAGE& image, const char * title);
-
- void main(void)
- {
- initialize();
-
- GetDateTime((unsigned long *)&randSeed);
- Random(); Random(); Random(); Random(); // Just randomizing
-
- FractalMap map(128);
- map.clip_to_intensity_range();
- // map.invert();
- // map.write_pgm("map.pgm");
- project_3D(map,"map");
- // display_map(map,"map");
- }
-