README0000644000767600076400000001137405766024265010261 0ustar spbepccXmountains is a X11 based fractal landscape generator. It generates random fractal surfaces and displays them in a window. While the program is running the fractal is continuously extended on the right and the image is scrolled from right to left to expose the newly generated area. This distribution contains an Imakefile. If your X-window software has been correctly installed a Makefile appropriate to your system can be generated from this using the command "xmkmf". Once this has been done the program is compiled with the command "make". ./xmountains: version 2.2 usage: ./xmountains -[bqgdPEmMrBZIASFTCapcevfRltxsXYH] -b [false] use root window -q [false] reset root window on exit -g string window geometry -d string display -P filename write PID to file -E [false] toggle explicit expose events -m [false] print map -M [false] implement reflections -r int [20] # columns before scrolling -B int [80] # shades in a colour band -n int [245] # number of colours -Z int [10] time to sleep before scrolling -I float [40.000000] vertical angle of light -A float [0.000000] horizontal angle of light -S float [0.600000] vertical stretch -T float [0.500000] vertical shift -W float [0.000000] sealevel -F int [1] reduce variation in the foreground -G float [-1.000000] average foreground height -C float [0.300000] contour parameter -a float [2.500000] altitude of viewpoint -p float [4.000000] distance of viewpoint -c float [1.000000] contrast -e float [0.300000] ambient light level -v float [0.600000] vertical light level Fractal options: -f float [0.650000] fractal dimension -R int [0] rng seed, read clock if 0 -l int [10] # levels of recursion -t int [2] # non fractal iterations -x [true] cross update -s [1] smoothing (0-7) -X float [0.000000] fraction of old value for rg2 & rg3 -Y float [0.000000] fraction of old value for rg1 -H print short description of algorithm. This program works best on a colour display. It will work on monochrome displays but the default parameter values are not optimal for this. The program breaks down into three sections 1) Fractal generation (calcalt.c random.c crinkle.h) This code should be fairly solid, It also contains some algorithmic tricks I had to invent (though it is not inconceivable that somebody else has also thought of them) 2) Image rendering & main program (artist.c global.c scroll.c global.h paint.h) This code is a bit more sloppy but seems to work OK. 3) The X interface (X_graphics.c) The X interface was retro-fitted to an earlier version of the program that was designed to use memory mapped video hardware. As a result this code is a little crude. A more experienced X hacker could do better but ... PROBLEMS All parameters are set on the command line. The choice of colours looks strange on some hardware. The program will not work with Xscreensaver or virtual window managers. This can be fixed by including vroot.h in X_graphics.c (define VROOT to cpp to do this) but I was a little wary of putting this in by default. CHANGES from V2.1 Added a -n flag to set the number of colours. This changes the same parameter as -B but you request total number of colours. CHANGES from V1.4 The fractal generation code has been reworked. There algorithm has been extended significantly and should be able to generate much better looking surfaces. There may be a performance hit for some options though. CHANGES from V1.3 1) There is now a flag to control the horizontal light angle. 2) negative values of the scroll parameter make the image scroll in the opposite direction. 3) water reflections have been implemented. CHANGES from V1.2 1) program now sleeps after a scroll rather than once per column. 2) added a -B flag to control the number of colours needed. 3) added a -q flag that clears the root window when the program exits. 4) fixed memory leak when in `map' mode. CHANGES from V1.1 Several changes including: 1) There is now a secondary (vertical) light source to add some detail to the shadows. 2) There is a -Z flag to reduce the CPU load, once the initial screen has been generated the program will call sleep once for each column of pixels. 3) Xmountains creates a pixmap containing the current state of the image. This is now installed as the background pixmap of the window. This means that root-window images will remain in place if the program is stopped. The -E flag disables this feature and explicitly traps expose events instead. There may be some delay in repainting the window if both the -E and -Z flags are used at the same time. If you have any comments/fixes etc for this program Email me at S.Booth@ed.ac.uk or spb@epcc.ed.ac.uk Copyright 1994 Stephen Booth, see copyright.h calcalt.c0000644000767600076400000004730311245717275011150 0ustar spbepcc/* * Recursive update procedure for fractal landscapes * * The only procedures needed outside this file are * make_fold, called once to initialise the data structs. * next_strip, each call returns a new strip off the side of the surface * you can keep calling this as often as you want. * free_strip, get rid of the strip when finished with it. * free_fold, get rid of the data structs when finished with this surface. * * Apart from make_fold all these routines get their parameters from their * local Fold struct, make_fold initialises all these values and has to * get it right for the fractal to work. If you want to change the fractal * dim in mid run you will have to change values at every level. * each recursive level only calls the level below once for every two times it * is called itself so it will take a number of iterations for any changes to * be notices by the bottom (long length scale) level. */ #include #include #include #include "crinkle.h" char calcalt_Id[] = "$Id: calcalt.c,v 2.18 2009/08/28 09:09:17 spb Exp $"; #ifdef DEBUG #define DB(A,B) dump_pipeline(A,B) #else #define DB(A,B) #endif /* {{{ Strip *make_strip(Fold *f) */ #ifdef ANSI Strip *make_strip(Fold *f) #else Strip *make_strip (f) Fold *f; #endif { Strip *p; int n; p = (Strip *) malloc( sizeof(Strip) ); if( p == NULL ) { fprintf(stderr,"make_strip: malloc failed\n"); exit(1); } p->f = f; n = f->count; p->d = (Height *)malloc( n * sizeof(Height) ); if( p->d == NULL ) { fprintf(stderr,"make_strip: malloc failed\n"); exit(1); } return(p); } /* }}} */ /* {{{ void free_strip(Strip *p) */ #ifdef ANSI void free_strip(Strip *p) #else void free_strip (p) Strip *p; #endif { if( p->d ) { free(p->d); p->d = NULL; } free(p); } /* }}} */ /* {{{ Strip *double_strip(Strip *s) */ #ifdef ANSI Strip *double_strip(Strip *s) #else Strip *double_strip (s) Strip *s; #endif { Strip *p; Height *a, *b; int i; int count; p = make_strip(s->f->parent); a = s->d; b = p->d; count = s->f->count; for(i=0; i < count-1; i++) { *b = *a; a++; b++; *b = 0.0; b++; } *b = *a; return(p); } /* }}} */ /* {{{ Strip *set_strip(Fold *f, Height value)*/ #ifdef ANSI Strip *set_strip(Fold *f, Height value) #else Strip *set_strip (f,value) Fold *f; Height value; #endif { int i; Strip *s; Height *h; int count; s = make_strip(f); h = s->d; count = f->count; for( i=0 ; i < count ; i++) { *h = value; h++; } return(s); } /* }}} */ /* {{{ Strip *random_strip(Fold *f)*/ #ifdef ANSI Strip *random_strip(Fold *f) #else Strip *random_strip(f) Fold *f; #endif { Strip *result; int i, count; result=make_strip(f); count = f->count; for( i=0 ; i < count ; i++) { result->d[i] = f->p->mean + (f->scale * gaussian()); } return(result); } /* }}} */ /* {{{ void reset_fold(Fold *f) */ #ifdef ANSI void reset_fold(Fold *f) #else void reset_fold(f) Fold *f; #endif { /* * resets any cached values within the fold structure * this should be called if the param struct is changed. */ Length scale, midscale; double root2; root2=sqrt((double) 2.0 ); scale = pow((double) f->length, (double) (2.0 * f->p->fdim)); midscale = pow((((double) f->length)*root2), (double) (2.0 * f->p->fdim)); f->scale = scale; f->midscale = midscale; if( f->next ){ reset_fold(f->next); } } /* }}} */ /* {{{ Fold *make_fold(Fold *parent,Parm *param, int levels, int stop, Length len) */ /* * Initialise the fold structures. * As everything else reads the parameters from their fold * structs we need to set these here, * p is the parameter struct common to all update levels. * levels is the number of levels of recursion below this one. * Number of points = 2^levels+1 * stop is the number of levels that are generated as random offsets from a * constant rather than from an average. * fractal_start, if true we start in the middle of a mountain range * if false we build up mountains from the start height. * length is the length of the side of the square at this level. * N.B this means the update square NOT the width of the fractal. * len gets smaller as the level increases. * start, the starting height for a non-fractal start. */ #ifdef ANSI Fold *make_fold(Fold *parent,Parm *param, int levels, int stop, Length length) #else Fold *make_fold (parent,param,levels,stop,length) struct fold *parent; struct parm *param; int levels; int stop; Length length; #endif { Fold *p; int i; if( (levels < stop) || (stop<0) ) { fprintf(stderr,"make_fold: invalid parameters\n"); fprintf(stderr,"make_fold: levels = %d , stop = %d \n",levels,stop); exit(1); } p = (Fold *)malloc(sizeof(Fold)); if( p == NULL ) { fprintf(stderr,"make_fold: malloc failed\n"); exit(1); } p->length=length; p->level = levels; p->count = (1 << levels) +1; p->stop = stop; p->state = START; p->save =NULL; p->p = param; for(i=0;is[i] = NULL; } p->parent=parent; p->next = NULL; /* truncate recursion in reset */ reset_fold(p); if( levels > stop ) { p->next = make_fold(p,param,(levels-1),stop,(2.0*length)); }else{ p->next = NULL; } return( p ); } /* }}} */ /* {{{ void free_fold(Fold *f) */ #ifdef ANSI void free_fold(Fold *f) #else void free_fold (f) Fold *f; #endif { int i; if( f->next ){ free_fold(f->next); f->next=NULL; } if( f->save ){ free_strip(f->save); f->save=NULL; } for(i=0;is[i] != NULL ) { free_strip(f->s[i]); f->s[i] = NULL; } } free(f); return; } /* }}} */ /* {{{ Strip *next_strip(Fold *fold) */ #ifdef ANSI Strip *next_strip(Fold *fold) #else Strip *next_strip (fold) Fold *fold; #endif { Strip *result=NULL; Strip *tmp; Strip **t; int i, iter; int count=fold->count; if( fold->level == fold->stop) { /* {{{ generate values from scratch */ result=random_strip(fold); /* }}} */ }else{ /* * There are two types of strip, * A strips - generated by the lower recursion layers. * these contain the corner points and half the side points * B strips - added by this layer, this contains the mid points and * half the side points. * * The various update routines test for NULL pointer arguments so * that this routine will not fail while filling the pipeline. */ while( result == NULL ) { /* {{{ iterate*/ switch(fold->state) { case START: /* {{{ perform an update. return first result*/ DB("S1",fold); t=fold->s; /* read in a new A strip at the start of the pipeline */ tmp =next_strip(fold->next); t[0] = double_strip(tmp); free_strip(tmp); /* make the new B strip */ t[1]=set_strip(fold,0.0); if( ! t[2] ) { /* we want to have an A B A pattern of strips at the * start of the pipeline. * force this when starting the pipe */ t[2]=t[0]; tmp =next_strip(fold->next); t[0] = double_strip(tmp); free_strip(tmp); } DB("E1",fold); /* * create the mid point * t := A B A */ DB("S2",fold); x_update(fold,fold->midscale,0.0,t[0],t[1],t[2]); DB("E2",fold); if(fold->p->rg1) { DB("S3",fold); /* * first possible regeneration step * use the midpoints to regenerate the corner values * increment t by 2 so we still have and A B A pattern */ if( t[3] == NULL ) { /* rather than do no update add offset to old value */ v_update(fold,fold->midscale,1.0,t[1],t[2],t[1]); }else{ v_update(fold,fold->midscale,fold->p->midmix,t[1],t[2],t[3]); } t+=2; DB("E3",fold); } /* * fill in the edge points * increment t by 2 to preserve the A B A pattern */ DB("S4",fold); if( fold->p->cross ) { t_update(fold,fold->scale,0.0,t[0],t[1],t[2]); p_update(fold,fold->scale,0.0,t[1],t[2],t[3]); t+=2; }else{ hside_update(fold,fold->scale,0.0,t[0],t[1],t[2]); vside_update(fold,fold->scale,0.0,t[2]); t+=2; } DB("E4",fold); if(fold->p->rg2) { DB("S5",fold); /* * second regeneration step update midpoint * from the new edge values */ if( fold->p->cross ) { if( t[2] == NULL ) { /* add random offset to old rather than skip update */ p_update(fold,fold->scale,fold->p->mix,t[0],t[1],t[0]); }else{ p_update(fold,fold->scale,fold->p->mix,t[0],t[1],t[2]); } }else{ vside_update(fold,fold->scale,fold->p->mix,t[1]); } DB("E5",fold); } /* increment t by 1 * this gives a B A B pattern to regen-3 * if regen 3 is not being used it leaves t pointing to the * 2 new result strips */ t++; if(fold->p->rg3) { DB("S6",fold); /* final regenration step * regenerate the corner points from the new edge values * this needs a B A B pattern * leave t pointing to the 2 new result strips * * this has to be a t_update */ if( t[2] == NULL ) { /* add random offset to old rather than skip update */ t_update(fold,fold->scale,1.0,t[0],t[1],t[0]); }else{ t_update(fold,fold->scale,fold->p->mix,t[0],t[1],t[2]); } t++; DB("E6",fold); } result=t[1]; fold->save=t[0]; t[0]=t[1]=NULL; fold->state = STORE; break; /* }}} */ case STORE: /* {{{ return second value from previous update. */ result = fold->save; fold->save=NULL; for(i=NSTRIP-1;i>1;i--) { fold->s[i] =fold->s[i-2]; } fold->s[0] = fold->s[1]=NULL; fold->state = START; break; /* }}} */ default: fprintf(stderr,"next_strip: invalid state level %d state %d\n", fold->level,fold->state); exit(3); } /* }}} */ } } iter = fold->level - fold->stop; if( fold->p->force_front > iter){ result->d[0] = fold->p->forceval; } if( fold->p->force_back > iter){ result->d[count-1] = fold->p->forceval; } return(result); } /* }}} */ /* {{{ void x_update(Fold *fold,float scale, float mix, Strip *a, Strip *b, Strip *c)*/ #ifdef ANSI void x_update(Fold *fold,float scale, float mix, Strip *a, Strip *b, Strip *c) #else void x_update(fold, scale, mix, a, b, c) Fold *fold; float scale; float mix; Strip *a; Strip *b; Strip *c; #endif { int i; int count=fold->count; float w; Height *mp, *lp, *rp; /* don't run unless we have all the parameters */ if( !a || !c ) return; if( !b ) { fprintf(stderr,"x_update: attempt to update NULL strip\n"); exit(1); } w = (1.0 - mix)*0.25; mp=b->d; lp=a->d; rp=c->d; if( mix <= 0.0 ){ /* {{{ random offset to average of new points*/ for(i=0; i= 1.0 ){ /* {{{ random offset to old value*/ for(i=0; icount; float w; Height *mp, *lp, *rp; /* don't run if we have no parameters */ if( !a || !b ) return; /* if c is missing we can do a vside update instead * should really be a sideways t but what the heck we only * need this at the start */ if( !c ) { vside_update(fold,scale,mix,b); return; } w = (1.0 - mix)*0.25; mp=b->d; lp=a->d; rp=c->d; if( mix <= 0.0 ){ /* {{{ random offset to average of new points*/ for(i=0; i= 1.0){ /* {{{ random offset to old values*/ for(i=0; icount; float w, we; Height *mp, *lp, *rp; float third=(1.0/3.0); /* don't run unless we have all the parameters */ if( !a || !c ) return; if( !b ) { fprintf(stderr,"t_update: attempt to update NULL strip\n"); exit(1); } w = (1.0 - mix)*0.25; we = (1.0 - mix)*third; mp=b->d; lp=a->d; rp=c->d; if( mix <= 0.0){ /* {{{ random offset to average of new points*/ mp[0] = third * ( lp[0] + rp[0] + mp[1] ) + (scale * gaussian()); mp++; lp++; rp++; for(i=1; i= 1.0){ /* {{{ random offset to old values*/ for(i=0; icount; float w, we; Height *mp, *lp, *rp; /* don't run unless we have all the parameters */ if( !a || !c ) return; if( !b ) { fprintf(stderr,"v_update: attempt to update NULL strip\n"); exit(1); } w = (1.0 - mix)*0.25; we = (1.0 - mix)*0.5; mp=b->d; lp=a->d; rp=c->d; if( mix <= 0.0){ /* {{{ random offset of average of new points*/ mp[0] = 0.5 * ( lp[1] + rp[1] ) + (scale * gaussian()); mp++; lp++; rp++; for(i=1; i= 1.0){ /* {{{ random offset to old values*/ for(i=0; icount; float w; Height *mp; /* don't run unless we have all the parameters */ if( !a ) return; w = (1.0 - mix)*0.5; mp=a->d; if( mix <= 0.0){ /* {{{ random offset to average of new points*/ for(i=0; i= 1.0){ /* {{{ random offset to old values*/ for(i=0; icount; float w; Height *mp, *lp, *rp; /* don't run unless we have all the parameters */ if( !a || !c ) return; if( !b ) { fprintf(stderr,"x_update: attempt to update NULL strip\n"); exit(1); } w = (1.0 - mix)*0.5; mp=b->d; lp=a->d; rp=c->d; if( mix <= 0.0 ){ /* {{{ random offset to average of new points*/ for(i=0; i= 1.0){ /* {{{ random offset to old points*/ for(i=0; ilevel, f->s[0],f->s[1],f->s[2],f->s[3],f->s[4],f->s[5],f->s[6],f->s[7]); } #endif random.c0000644000767600076400000000717411245717275011027 0ustar spbepcc/* * C version of Marsaglia's UNI random number generator * More or less transliterated from the Fortran -- with 1 bug fix * Hence horrible style * * Features: * ANSI C * not callable from Fortran (yet) */ char uni_id[] = "$Id: random.c,v 1.7 2009/08/28 09:09:17 spb Exp $" ; /* * Global variables for rstart & uni */ #define PARANOID /* need types and time */ #include /* #include * #include */ #include #include #include typedef struct { float u[98]; float c; float cd; float cm; int ui; int uj; } Uni_save; Uni_save uni_data; float uni() { float luni; /* local variable for uni */ luni = uni_data.u[uni_data.ui] - uni_data.u[uni_data.uj]; if (luni < 0.0) luni += 1.0; uni_data.u[uni_data.ui] = luni; if (--uni_data.ui == 0) uni_data.ui = 97; if (--uni_data.uj == 0) uni_data.uj = 97; if ((uni_data.c -= uni_data.cd) < 0.0) uni_data.c += uni_data.cm; if ((luni -= uni_data.c) < 0.0) luni += 1.0; return ((float) luni); } void rstart(i,j,k,l) int i; int j; int k; int l; { int ii, jj, m; float s, t; for (ii = 1; ii <= 97; ii++) { s = 0.0; t = 0.5; for (jj = 1; jj <= 24; jj++) { m = ((i*j % 179) * k) % 179; i = j; j = k; k = m; l = (53*l+1) % 169; if (l*m % 64 >= 32) s += t; t *= 0.5; } uni_data.u[ii] = s; } uni_data.c = 362436.0 / 16777216.0; uni_data.cd = 7654321.0 / 16777216.0; uni_data.cm = 16777213.0 / 16777216.0; uni_data.ui = 97; /* There is a bug in the original Fortran version */ uni_data.uj = 33; /* of UNI -- i and j should be SAVEd in UNI() */ } /* ~seed_uni: this takes a single integer in the range * 0 <= ijkl <= 900 000 000 * and produces the four smaller integers needed for rstart. It is * based on the ideas contained in the RMARIN subroutine in * F. James, "A Review of Pseudorandom Number Generators", * Comp. Phys. Commun. Oct 1990, p.340 * To reduce the modifications to the existing code, seed_uni now * takes the role of a preprocessor for rstart. * */ void seed_uni(ijkl) int ijkl; { int i, j, k, l, ij, kl; if( ijkl == 0 ) { ijkl = time((time_t *) 0); ijkl %= 900000000; } /* check ijkl is within range */ if( (ijkl < 0) || (ijkl > 900000000) ) { fprintf(stderr,"seed_uni: ijkl = %d -- out of range\n\n", ijkl); exit(3); } /* decompose the long integer into the the equivalent four * integers for rstart. This should be a 1-1 mapping * ijkl <--> (i, j, k, l) * though not quite all of the possible sets of (i, j, k, l) * can be produced. */ ij = ijkl/30082; kl = ijkl - (30082 * ij); i = ((ij/177) % 177) + 2; j = (ij % 177) + 2; k = ((kl/169) % 178) + 1; l = kl % 169; #ifdef PARANOID if( (i <= 0) || (i > 178) ) { fprintf(stderr,"seed_uni: i = %d -- out of range\n\n", i); exit(3); } if( (j <= 0) || (j > 178) ) { fprintf(stderr,"seed_uni: j = %d -- out of range\n\n", j); exit(3); } if( (k <= 0) || (k > 178) ) { fprintf(stderr,"seed_uni: k = %d -- out of range\n\n", k); exit(3); } if( (l < 0) || (l > 168) ) { fprintf(stderr,"seed_uni: l = %d -- out of range\n\n", l); exit(3); } if (i == 1 && j == 1 && k == 1) { fprintf(stderr,"seed_uni: 1 1 1 not allowed for 1st 3 seeds\n\n"); exit(4); } #endif rstart(i, j, k, l); } float gaussian() { double pi = 3.1415926536, two = 2.0, zero = 0.0; double ran1, ran2; do { ran1 = (double) uni(); } while (ran1 == zero); ran2 = (double) uni(); return (float) ( sqrt(-two * log(ran1)) * cos(two * pi * ran2) ); } artist.c0000644000767600076400000005135011245717275011050 0ustar spbepcc/* * routines to render a fractal landscape as an image */ #include #include #include #include "paint.h" #include "crinkle.h" char artist_Id[] = "$Id: artist.c,v 1.41 2009/08/28 09:09:17 spb Exp $"; #define SIDE 1.0 #ifndef PI #define PI 3.14159265 #endif int base=0; /* parity flag for mirror routine */ extern Parm fold_param; extern Graph g; extern int swosh; Fold *top; Height varience; Height delta_shadow; Height shift; double shadow_slip; double shadow_register; double cos_phi; double sin_phi; double tan_phi; double x_fact; double y_fact; double vangle; double vscale; double tan_vangle; float viewpos; /* position of viewpoint */ float viewheight; /* height of viewpoint */ float focal; float vstrength; /* strength of vertical light source */ float lstrength; /* strength of vertical light source */ Height *shadow; /* height of the shadows */ Height *a_strip, *b_strip; /* the two most recent strips */ float uni(); /* {{{ void set_clut(int max_col, Gun *red, Gun *green, Gun *blue)*/ /* * setup the colour lookup table */ void set_clut (max_col,red,green,blue) int max_col; Gun *red; Gun *green; Gun *blue; { int band,shade; float top, bot; float intensity; int tmp; /* * float rb[N_BANDS] = { 0.167,0.200,0.333,0.450,0.600,1.000 }; * float gb[N_BANDS] = { 0.667,0.667,0.500,0.500,0.600,1.000 }; * float bb[N_BANDS] = { 0.500,0.450,0.333,0.200,0.000,1.000 }; */ float rb[N_BANDS]; float gb[N_BANDS]; float bb[N_BANDS]; /* band base colours as RGB fractions */ rb[0] = 0.450; rb[1] = 0.600; rb[2] = 1.000; gb[0] = 0.500; gb[1] = 0.600; gb[2] = 1.000; bb[0] = 0.333; bb[1] = 0.000; bb[2] = 1.000; /* {{{ black */ red[BLACK] = 0; green[BLACK] = 0; blue[BLACK] = 0; /* }}} */ /* {{{ white */ red[WHITE] = COL_RANGE; green[WHITE] = COL_RANGE; blue[WHITE] = COL_RANGE; /* }}} */ /* {{{ sky*/ red[SKY] = 0.404*COL_RANGE; green[SKY] = 0.588*COL_RANGE; blue[SKY] = COL_RANGE; /* }}} */ /* {{{ sea (lit) */ red[SEA_LIT] = 0; green[SEA_LIT] = 0.500*COL_RANGE; blue[SEA_LIT] = 0.700*COL_RANGE; /* }}} */ /* {{{ sea (unlit)*/ red[SEA_UNLIT] = 0; green[SEA_UNLIT] = ((g.ambient+(g.vfract/(1.0+g.vfract)))*0.500)*COL_RANGE; blue[SEA_UNLIT] = ((g.ambient+(g.vfract/(1.0+g.vfract)))*0.700)*COL_RANGE; /* }}} */ if( MIN_COL > max_col ) { fprintf(stderr,"set_clut: less than the minimum number of colours available\n"); exit(1); } /* max_col can over-rule band_size */ while( (BAND_BASE +g.band_size*N_BANDS) > max_col ) { g.band_size--; } for( band=0 ; band= max_col ) { fprintf(stderr,"INTERNAL ERROR, overflowed clut\n"); exit(1); } /* {{{ set red */ top = rb[band]; bot = g.ambient * top; intensity = bot + ((shade * (top - bot))/(g.band_size-1)); tmp = COL_RANGE * intensity; if (tmp < 0) { fprintf(stderr,"set_clut: internal error: invalid code %d\n",tmp); exit(2); } if( tmp > COL_RANGE ) { tmp = COL_RANGE; } red[BAND_BASE + (band*g.band_size) + shade] = tmp; /* }}} */ /* {{{ set green */ top = gb[band]; bot = g.ambient * top; intensity = bot + ((shade * (top - bot))/(g.band_size-1)); tmp = COL_RANGE * intensity; if (tmp < 0) { fprintf(stderr,"set_clut: internal error: invalid code %d\n",tmp); exit(2); } if( tmp > COL_RANGE ) { tmp = COL_RANGE; } green[BAND_BASE + (band*g.band_size) + shade] = tmp; /* }}} */ /* {{{ set blue */ top = bb[band]; bot = g.ambient * top; intensity = bot + ((shade * (top - bot))/(g.band_size-1)); tmp = COL_RANGE * intensity; if (tmp < 0) { fprintf(stderr,"set_clut: internal error: invalid code %d\n",tmp); exit(2); } if( tmp > COL_RANGE ) { tmp = COL_RANGE; } blue[BAND_BASE + (band*g.band_size) + shade] = tmp; /* }}} */ } } } /* }}} */ /* {{{ Height *extract(Strip *s) */ /* * extract the table of heights from the Strip struct * and discard the rest of the struct. */ Height *extract (s) Strip *s; { int i; Height *p; p = s->d; free(s); for(i=0 ; i= 0 ){ g.pos=0; }else{ g.pos = g.pixmap_width - 1; } } /* }}} */ /* {{{ Col get_col(Height p, Height p_minus_x, Height p_minus_y, Height shadow) */ /* * calculate the colour of a point. */ Col get_col (p,p_minus_x,p_minus_y,shadow) Height p; Height p_minus_x; Height p_minus_y; Height shadow; { Height delta_x, delta_y; Height delta_x_sqr, delta_y_sqr; Height hypot_sqr; double norm, dshade; Height effective; Col result; int band, shade; /* {{{ if underwater*/ if ( p < g.sealevel ) { if( shadow > g.sealevel ) { return( SEA_UNLIT ); }else{ return( SEA_LIT ); } } /* }}} */ /* * We have three light sources, one slanting in from the left * one directly from above and an ambient light. * For the directional sources illumination is proportional to the * cosine between the normal to the surface and the light. * * The surface contains two vectors * ( 1, 0, delta_x ) * ( 0, 1, delta_y ) * * The normal therefore is parallel to * ( -delta_x, -delta_y, 1)/sqrt( 1 + delta_x^2 + delta_y^2) * * For light parallel to ( cos_phi, 0, -sin_phi) the cosine is * (cos_phi*delta_x + sin_phi)/sqrt( 1 + delta_x^2 + delta_y^2) * * For light parallel to ( cos_phi*cos_alpha, cos_phi*sin_alpha, -sin_phi) * the cosine is * (cos_phi*cos_alpha*delta_x + cos_phi*sin_alpha*delta_y+ sin_phi)/sqrt( 1 + delta_x^2 + delta_y^2) * * For vertical light the cosine is * 1 / sqrt( 1 + delta_x^2 + delta_y^2) */ delta_x = p - p_minus_x; delta_y = p - p_minus_y; delta_x_sqr = delta_x * delta_x; delta_y_sqr = delta_y * delta_y; hypot_sqr = delta_x_sqr + delta_y_sqr; norm = sqrt( 1.0 + hypot_sqr ); /* {{{ calculate effective height */ effective = (p + (varience * g.contour * (1.0/ ( 1.0 + hypot_sqr)))); /* }}} */ /* {{{ calculate colour band. */ band = ( effective / varience) * N_BANDS; if ( band < 0 ) { band = 0; } if( band > (N_BANDS - 1)) { band = (N_BANDS -1); } result = (BAND_BASE + (band * g.band_size)); /* }}} */ /* {{{ calculate the illumination stength*/ /* * add in a contribution for the vertical light. The normalisation factor * is applied later * */ dshade = vstrength; if( p >= shadow ) { /* * add in contribution from the main light source */ /* dshade += ((double) lstrength * ((delta_x * cos_phi) + sin_phi));*/ dshade += ((double) lstrength * ((delta_x * x_fact) + (delta_y * y_fact) + sin_phi)); } /* divide by the normalisation factor (the same for both light sources) */ dshade /= norm; /* }}} */ /* {{{ calculate shading */ /* dshade should be in the range 0.0 -> 1.0 * if the light intensities add to 1.0 * now convert to an integer */ shade = dshade * (double) g.band_size; if( shade > (g.band_size-1)) { shade = (g.band_size-1); } /* {{{ if shade is negative then point is really in deep shadow */ if( shade < 0 ) { shade = 0; } /* }}} */ /* }}} */ result += shade; if( (result >= g.n_col) || (result < 0) ) { fprintf(stderr,"INTERNAL ERROR colour out of range %d max %d\n",result,g.n_col); exit(1); } return(result); } /* }}} */ /* {{{ Col *makemap(Height *a, Height *b, Height *shadow) */ Col *makemap (a,b,shadow) Height *a; Height *b; Height *shadow; { Col *res; int i; /* This routine returns a plan view of the surface */ res = (Col *) malloc(g.width * sizeof(Col) ); if (res == NULL) { fprintf(stderr,"malloc failed for colour strip\n"); exit(1); } res[0] = BLACK; for(i=1 ; i last ) { /* get the colour of this point, the front strip should be black */ if( i==0 ) { col = BLACK; }else{ col = get_col(b[i],a[i],b[i-1],shadow[i]); } if( coord > g.graph_height ) { coord = g.graph_height; } for(;last0;i--) { if(map[i] < BAND_BASE) { /* {{{ stipple water values*/ for(j=last_bottom;j<=last_top;j++) { res[j]=last_col; } last_col=map[i]; /* invalidate strip so last stip does not exist */ last_bottom=g.graph_height; last_top= -1; /* fill in water values */ coord=1+project(i,g.sealevel); for(j=0;j last_top) { last_top=top; } if( bottom < last_bottom) { last_bottom=bottom; } }else{ if(top < last_top) { for(j=top+1;j<=last_top;j++) { res[j]=last_col; } } if(bottom > last_bottom) { for(j=last_bottom;j (g.graph_height-1)) { pos = g.graph_height-1; } else if( pos < 0 ) { pos = 0; } return( pos ); } /* }}} */ /* {{{ void finish_artist() */ /* * Tidy up and free everything. */ void finish_artist() { free(a_strip); free(b_strip); free(shadow); free_fold(top); } /* }}} */ /* {{{ void init_parameters() */ void init_parameters() { g.graph_height=768; g.graph_width=1024; g.levels = 10; g.stop=2; g.n_col=DEF_COL; g.band_size=BAND_SIZE; g.ambient=0.3; g.contrast=1.0; g.contour=0.3; g.vfract=0.6; g.altitude=2.5; g.distance=4.0; g.phi=(40.0 * PI)/180.0; g.alpha=0.0; g.base_shift=0.5; g.sealevel=0.0; g.stretch=0.6; g.map=FALSE; g.reflec=TRUE; g.repeat=20; g.pos=0; g.scroll=0; fold_param.mean=0; fold_param.rg1=FALSE; fold_param.rg2=FALSE; fold_param.rg3=TRUE; fold_param.cross=TRUE; fold_param.force_front=TRUE; fold_param.force_back=FALSE; fold_param.forceval=-1.0; fold_param.fdim = 0.65; fold_param.mix =0.0; fold_param.midmix=0.0; } /* }}} */ /* {{{ Col *next_col(int paint, int reflec) */ Col *next_col (paint, reflec) int paint; int reflec; { Col *res; int i,offset=0; /* {{{ update strips */ if(paint) { if(reflec) { res = mirror( a_strip,b_strip,shadow); }else{ res = camera( a_strip,b_strip,shadow); } }else{ res = makemap(a_strip,b_strip,shadow); } free(a_strip); a_strip=b_strip; b_strip = extract( next_strip(top) ); /* }}} */ /* {{{ update the shadows*/ /* shadow_slip is the Y component of the light vector. * The shadows can only step an integer number of points in the Y * direction so we maintain shadow_register as the deviation between * where the shadows are and where they should be. When the magnitude of * this gets larger then 1 the shadows are slipped by the required number of * points. * This will not work for very oblique angles so the horizontal angle * of illumination should be constrained. */ shadow_register += shadow_slip; if( shadow_register >= 1.0 ) { /* {{{ negative offset*/ while( shadow_register >= 1.0 ) { shadow_register -= 1.0; offset++; } for(i=g.width-1 ; i>=offset ; i--) { shadow[i] = shadow[i-offset]-delta_shadow; if( shadow[i] < b_strip[i] ) { shadow[i] = b_strip[i]; } /* {{{ stop shadow at sea level */ if( shadow[i] < g.sealevel ) { shadow[i] = g.sealevel; } /* }}} */ } for(i=0;irepeat >= 0){ if(g->pos == 0){ blank_region(0,0,g->graph_width,g->graph_height); flush_region(0,0,g->graph_width,g->graph_height); } }else{ if( g->pos == g->graph_width-1){ blank_region(0,0,g->graph_width,g->graph_height); flush_region(0,0,g->graph_width,g->graph_height); } } if( g->scroll && !swosh ){ scroll_screen(g->scroll); } l = next_col(1-g->map,g->reflec); if( g->map ) { if( g->graph_height > g->width ){ mapwid=g->width; }else{ mapwid=g->graph_height; } for( j=0 ;j<(g->graph_height-mapwid); j++) { plot_pixel(g->pos,((g->graph_height-1)-j),BLACK); } for(j=0; jpos,((mapwid-1)-j),l[j]); } }else{ for(j=0 ; jgraph_height ; j++) { /* we assume that the scroll routine fills the * new region with a SKY value. This allows us to * use a testured sky for B/W displays */ if( l[j] != SKY ) { plot_pixel(g->pos,((g->graph_height-1)-j),l[j]); } } } free(l); flush_region(g->pos,0,1,g->graph_height); g->scroll = 0; /* now update pos ready for next time */ if( g->repeat >=0 ){ g->pos++; if(g->pos >= g->pixmap_width) { g->pos -= g->repeat; if( g->pos < 0 || g->pos > g->pixmap_width-1 ) { g->pos=0; }else{ g->scroll = g->repeat; } } }else{ g->pos--; if( g->pos < 0 ){ g->pos -= g->repeat; if( g->pos < 0 || g->pos > (g->pixmap_width-1) ){ g->pos=g->pixmap_width-1; }else{ g->scroll = g->repeat; } } } if(g->scroll && swosh) { scroll_screen(g->scroll); } } /* }}} */ xmountains.c0000644000767600076400000003256511502626220011737 0ustar spbepcc #include #include #include #include #include #include #include "crinkle.h" #include "paint.h" #include "patchlevel.h" #include "copyright.h" #define VERSION 2 #define SIDE 1.0 char scroll_Id[]="$Id: xmountains.c,v 1.43 2010/12/17 09:25:36 spb Exp $"; extern Graph g; Parm fold_param; char *display; extern char *geom; extern int swosh; /* {{{ my version on getopt*/ int optind=1; char *optarg; int opterr=1; int my_getopt (argc, argv, pat) int argc; char **argv; char *pat; { char *flag; if((optind >= argc) || (argv[optind][0] != '-')) { return -1; } if( argv[optind][1] == '-' ) { optind++; return -1; } if( argv[optind][1] == ':' ) { if( opterr ) { fprintf(stderr,"getopt: found \":\" in optstring\n"); } return '?'; } for(flag=pat;*flag;flag++) { if( *flag == argv[optind][1] ) { optind++; if( *(flag+1) == ':' ) { if(optind >= argc ) { if( opterr ) { fprintf(stderr,"getopt: no option for flag %c\n",*flag); } return '?'; } optarg = argv[optind]; optind++; } return *flag; } } if( opterr ) { fprintf(stderr,"getopt: flag %s not recognized\n",argv[optind]); } optind++; return '?'; } /* }}} */ double atof(); #ifdef ANSI void init_graphics (int, Window, int,int, Graph *, Gun *, Gun *, Gun *); void clear_col( int ); void finish_graphics(); void plot_pixel (int, int, unsigned char); void scroll_screen ( int ); void zap_events(); #else void init_graphics (); void clear_col(); void finish_graphics(); void plot_pixel (); void scroll_screen (); void zap_events(); #endif void finish_prog(); int s_height=768, s_width=1024; int mapwid; /* Go through argv and find and extract any "-window-id NNNN" or "-window-id 0xXXXX" option. (Maybe this can be done with getopt, but I can't be bothered to figure it out.) */ static unsigned long window_id_kludge (argcP, argv) int *argcP; char **argv; { unsigned long id = 0; int i; int j; for (i = 1; i < *argcP; i++) { if (!strcmp (argv[i], "-window-id") && i+1 < *argcP) { char c; char *str = argv[i+1]; if (1 != ((str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) ? sscanf (str+2, "%lx %c", &id, &c) : sscanf (str, "%lu %c", &id, &c))) continue; /* remove "-window-id xxx" from the arglist */ for (j = i+2; j < *argcP; j++) argv[j-2] = argv[j]; *argcP -= 2; } } return id; } void init_parameters(); void print_algorithm(); void seed_uni(int ijkl); void plot_column(Graph *g); main (argc,argv) int argc; char **argv; { int i; int e_events=FALSE; int request_clear=FALSE; int smooth=1; int snooze=10; int root= 0; unsigned long window_id = 0; int seed=0; int c, errflg=0; extern char *optarg; extern int optind; char *mesg[2]; Gun *clut[3]; FILE *pidfile; swosh = 0; /* default is ! -w */ init_parameters(); /* {{{ handle command line flags*/ window_id = window_id_kludge (&argc, argv); mesg[0]="false"; mesg[1]="true"; while((c = my_getopt(argc,argv,"whbxmqMEHl:r:f:t:I:A:S:T:W:C:a:p:B:n:R:g:d:c:e:v:Z:s:X:Y:P:F:G:"))!= -1) { switch(c){ case 'w': swosh = TRUE; /* update window only when pixmap is complete */ break; case 'b': root = 1- root; break; /* run on root window */ case 'x': fold_param.cross = 1- fold_param.cross; break; /* use cross updates */ case 'E': e_events = 1 - e_events; break; case 'q': request_clear = 1 - request_clear; break; case 'm': /* Map view only */ g.map = 1 - g.map; break; case 'M': /* put in reflections */ g.reflec = 1 - g.reflec; break; case 'l': /* Set # levels of recursion */ g.levels = atoi( optarg ); if( g.levels < 2 ) { g.levels = 2; } break; case 'F': /* Set # levels to force front to mean */ fold_param.force_front = atoi( optarg ); break; case 's': /* Set smoothing parameter */ smooth = atoi( optarg ); fold_param.rg1 = smooth & 1; fold_param.rg2 = smooth & 2; fold_param.rg3 = smooth & 4; break; case 't': /* Set width of lowest level */ g.stop = atoi( optarg ); if( g.stop < 0 ) { g.stop = 0; } break; case 'r': g.repeat = atoi( optarg ); if( g.repeat < 0 ) { g.repeat = -g.repeat; i= -1; }else{ i=1; } /* we want repeat to be a multiple of 2 as we are using * a textured field for the sky. */ g.repeat = i*(2 * ((g.repeat +1)/2)); break; case 'B': /* set band_size */ g.band_size = atoi( optarg ); if( g.band_size < 2 ) { g.band_size=2; } g.n_col = (BAND_BASE + (N_BANDS * g.band_size)); break; case 'n': /* set max number of colours */ g.n_col = atoi( optarg ); if( g.n_col < MIN_COL ) { g.n_col = MIN_COL; } g.band_size = (g.n_col - BAND_BASE)/N_BANDS; g.n_col = (BAND_BASE + (N_BANDS * g.band_size)); break; case 'R': /* set seed, read clock if 0 */ seed = atoi( optarg ); break; case 'Z': /* put sleep into wait events */ snooze = atoi( optarg ); if( snooze < 0 ) { snooze = 0; } break; case 'P': pidfile = fopen(optarg,"w"); if( pidfile ) { fprintf(pidfile,"%d\n",getpid()); fclose(pidfile); }else{ perror(optarg); } break; case 'f': /* set fractal dimension */ fold_param.fdim = atof( optarg ); if( fold_param.fdim < 0.5 ) { fold_param.fdim=0.5; } if( fold_param.fdim > 1.0 ) { fold_param.fdim=1.0; } break; case 'I': /* set Illumination angle */ g.phi = ((PI * atof( optarg ))/180.0); if ( g.phi < 0.0 ) { g.phi=0.0; } if( g.phi > PI/2.0 ) { g.phi = PI/2.0; } break; case 'A': /* set Illumination angle (horizontal)*/ g.alpha = ((PI * atof( optarg ))/180.0); if( g.alpha < -PI/3.0 ) { g.alpha = -PI/3.0; } if( g.alpha > PI/3.0 ) { g.alpha = PI/3.0; } break; case 'X': /* set mix */ fold_param.mix = atof( optarg ); break; case 'Y': /* set midmix */ fold_param.midmix = atof( optarg ); break; case 'S': /* set stretch */ g.stretch = atof( optarg ); break; case 'W': /* set sealevel */ g.sealevel = atof( optarg ); break; case 'G': /* set forceheight */ fold_param.forceval = atof( optarg ); break; case 'T': /* set shift */ g.base_shift = atof( optarg ); break; case 'C': g.contour = atof( optarg ); break; case 'a': /* set altitude */ g.altitude = atof( optarg ); break; case 'p': /* set distance */ g.distance = atof( optarg ); break; case 'c': g.contrast = atof( optarg ); if( g.contrast < 0.0 ) { g.contrast=0.0; } break; case 'e': g.ambient = atof( optarg ); if( g.ambient < 0.0 ) { g.ambient = 0.0; } if( g.ambient > 1.0 ) { g.ambient=1.0; } break; case 'v': g.vfract = atof( optarg ); if( g.vfract < 0.0 ) { g.vfract = 0.0; } break; case 'g': geom = optarg; break; case 'd': display = optarg; break; case 'H': print_algorithm(); errflg++; break; case 'h': case '?': errflg++; } } if( errflg ) { fprintf(stderr,"%s: version %d.%d\n",argv[0],VERSION,PATCHLEVEL); fprintf(stderr,"usage: %s -[hwbqgdPEmMrBZIASFTCapcevfRltxsXYH]\n",argv[0]); fprintf(stderr," -h Print this message\n"); fprintf(stderr," -w [%s] update window with complete images only\n",mesg[swosh]); fprintf(stderr," -b [%s] use root window \n",mesg[root]); fprintf(stderr," -q [%s] reset root window on exit\n",mesg[request_clear]); fprintf(stderr," -g string window geometry\n"); fprintf(stderr," -d string display\n"); fprintf(stderr," -P filename write PID to file\n"); fprintf(stderr," -E [%s] toggle explicit expose events \n",mesg[e_events]); fprintf(stderr," -m [%s] print map \n",mesg[g.map]); fprintf(stderr," -M [%s] implement reflections \n",mesg[g.reflec]); fprintf(stderr," -r int [%d] # columns before scrolling \n",g.repeat); fprintf(stderr," -B int [%d] # shades in a colour band\n",g.band_size); fprintf(stderr," -n int [%d] # number of colours\n",g.n_col); fprintf(stderr," -Z int [%d] time to sleep before scrolling\n",snooze); fprintf(stderr," -I float [%f] vertical angle of light \n",(g.phi*180.0)/PI); fprintf(stderr," -A float [%f] horizontal angle of light \n",(g.alpha*180.0)/PI); fprintf(stderr," -S float [%f] vertical stretch \n",g.stretch); fprintf(stderr," -T float [%f] vertical shift \n",g.base_shift); fprintf(stderr," -W float [%f] sealevel \n",g.sealevel); fprintf(stderr," -F int [%d] reduce variation in the foreground \n",fold_param.force_front); fprintf(stderr," -G float [%f] average foreground height \n",fold_param.forceval); fprintf(stderr," -C float [%f] contour parameter \n",g.contour); fprintf(stderr," -a float [%f] altitude of viewpoint \n",g.altitude); fprintf(stderr," -p float [%f] distance of viewpoint \n",g.distance); fprintf(stderr," -c float [%f] contrast\n",g.contrast); fprintf(stderr," -e float [%f] ambient light level\n",g.ambient); fprintf(stderr," -v float [%f] vertical light level\n",g.vfract); fprintf(stderr,"Fractal options:\n"); fprintf(stderr," -f float [%f] fractal dimension \n",fold_param.fdim); fprintf(stderr," -R int [%d] rng seed, read clock if 0 \n",seed); fprintf(stderr," -l int [%d] # levels of recursion \n",g.levels); fprintf(stderr," -t int [%d] # non fractal iterations \n",g.stop); fprintf(stderr," -x [%s] cross update \n",mesg[fold_param.cross]); fprintf(stderr," -s [%x] smoothing (0-7)\n",smooth); fprintf(stderr," -X float [%f] fraction of old value for rg2 & rg3\n",fold_param.mix); fprintf(stderr," -Y float [%f] fraction of old value for rg1\n",fold_param.midmix); fprintf(stderr," -window-id 0xNNNNN draw on existing external window.\n"); fprintf(stderr," -H print short description of algorithm.\n"); exit(1); } /* }}} */ for(i=0 ;i<3 ;i++) { clut[i] = (Gun *) malloc(g.n_col * sizeof(Gun)); if( ! clut[i] ) { fprintf(stderr,"malloc failed for clut\n"); exit(1); } } set_clut(g.n_col,clut[0], clut[1], clut[2]); init_graphics(root,window_id, !e_events, request_clear, &g, clut[0], clut[1], clut[2]); for(i=0;i<3;i++) { free(clut[i]); } seed_uni(seed); init_artist_variables(); if( SIG_ERR == signal(SIGINT, finish_prog )) { perror(argv[0]); exit(1); } if( SIG_ERR == signal(SIGTERM, finish_prog )) { perror(argv[0]); exit(1); } if( SIG_ERR == signal(SIGHUP, finish_prog )) { perror(argv[0]); exit(1); } if( SIG_ERR == signal(SIGQUIT, finish_prog )) { perror(argv[0]); exit(1); } /* This is a stand in for the event loop in a Widget set implementation * where we would call plot_column at regular intervals using * XTtimeout. However xmountains is an Xlib program * so I do the following. */ while( TRUE ) { plot_column(&g); zap_events(); #ifndef NO_SLEEP if( g.scroll ){ /* sleep if we are due a scroll next time */ /* sleeping is very bad because it will prevent * events being processed but I suppose it is better * than being a CPU hog, as a compremise always check for * events at least once a second, looping for longer sleep times. * process the events before a sleep to make sure the screen is up to date. * the events must always be processed at least once. */ for(i=0;i #include #include #include #include # define VROOT /* always do this */ #ifdef VROOT #include"vroot.h" #endif #include "paint.h" char X_graphics_Id[]="$Id: X_graphics.c,v 1.26 2009/08/28 09:09:17 spb Exp $"; char *display=NULL; /* name of display to open, NULL for default */ char *geom=NULL; /* geometry of window, NULL for default */ Atom wm_protocols; Atom wm_delete_window; #ifndef FALSE #define TRUE 1 #define FALSE 0 #endif int quit_xmount=FALSE; Display *dpy; int screen; unsigned int graph_width; unsigned int graph_height; Window parent, win, root; int use_root=FALSE; int do_clear=FALSE; int pixmap_installed=FALSE; int swosh=FALSE; /* plot history */ int plot_x, plot_y1, plot_y2; unsigned long plot_col; int plot_saved=FALSE; #include Pixmap stip; unsigned int depth=0; GC gc; Pixmap pix; Pixmap bg_pix; Colormap map, defaultmap; XColor *table=NULL; void zap_events(); void finish_graphics(); Graph g={ 1024, 768, 0, 0, 0.3, 1.0, 0.3, 0.6, 2.5, 4.0, (40.0 * PI)/180.0, 0.0, 0.5, 0.0, 0.6, DEF_COL, 60, 10, 2, FALSE, TRUE, 20, 0, 0 }; void finish_artist(); /*{{{void zap_events(int snooze)*/ void zap_events(snooze) int snooze; { XEvent event; XExposeEvent *expose = (XExposeEvent *)&event; int exw, exh; while( XPending(dpy) ){ XNextEvent(dpy, &event); switch(event.type) { case ClientMessage: if (event.xclient.message_type == wm_protocols && event.xclient.data.l[0] == wm_delete_window) { quit_xmount=TRUE; } break; case ButtonPress: break; case ButtonRelease: quit_xmount=TRUE; break; case Expose: if( (expose->x < graph_width) && (expose->y < graph_height)) { if( (expose->x + expose->width) > graph_width) { exw=graph_width - expose->x; }else{ exw = expose->width; } if( (expose->y + expose->height) > graph_height) { exh=graph_height - expose->y; }else{ exh = expose->height; } if(g.repeat < 0) { XCopyArea(dpy, pix, win, gc, expose->x - g.repeat, expose->y, exw, exh, expose->x,expose->y); } else { XCopyArea(dpy,pix,win,gc,expose->x,expose->y, exw,exh, expose->x,expose->y); } } break; default: fprintf(stderr,"xmountains: unrecognized event %d\n",event.type); /* XCloseDisplay(dpy); * exit(1); */ break; } } if( quit_xmount ) { finish_graphics(); finish_artist(); exit(0); } } /*}}}*/ /*{{{void finish_graphics()*/ void finish_graphics() { unsigned long attmask; XSetWindowAttributes attributes; int x,y; unsigned int border; int count; XFreePixmap(dpy,pix); XFreeGC(dpy,gc); XFreePixmap(dpy,stip); /* reset things if this was the root window. */ if( use_root ) { if( pixmap_installed && do_clear ) { /* restore default pixmap for the root window */ XSetWindowBackgroundPixmap(dpy,win,ParentRelative); XClearWindow(dpy,win); }else{ XGetGeometry(dpy,win,&root,&x,&y,&graph_width,&graph_height,&border,&depth); XClearArea(dpy,win,0,0,graph_width,graph_height,FALSE); } if( map != defaultmap ) { attmask = 0; attmask |= CWColormap; attributes.colormap = defaultmap; XChangeWindowAttributes(dpy,win,attmask,&attributes); } } if( map != defaultmap ) { XFreeColormap(dpy, map ); } if((count = XPending(dpy))) { fprintf(stderr,"WARNING: %d events still pending\n",count); } XCloseDisplay(dpy); } /*}}}*/ /*{{{void blank_region(lx,ly,ux,uy)*/ void blank_region(lx,ly,ux,uy) int lx,ly,ux,uy; { if( depth < 4 ) { /* use a textured gray sky on monochrome displays * we may need this on any low-depth display */ XSetForeground(dpy,gc,WhitePixel(dpy,screen)); XSetFillStyle(dpy,gc,FillOpaqueStippled); XFillRectangle(dpy,pix,gc,lx,ly,ux,uy); XSetFillStyle(dpy,gc,FillSolid); }else{ XSetForeground(dpy,gc,table[SKY].pixel); XFillRectangle(dpy,pix,gc,lx,ly,ux,uy); } } /*}}}*/ /*{{{void blank_col( pos )*/ void blank_col( pos ) int pos; { blank_region(pos,0,pos,graph_height); } /*}}}*/ /*{{{void init_graphics( ... )*/ void init_graphics( want_use_root, use_window, use_background, want_clear,gptr,red,green,blue ) int want_use_root; /* display on the root window */ Window use_window; /* display on external window */ int use_background; /* install the pixmap as the background-pixmap */ int want_clear; Graph *gptr; Gun *red; Gun *green; Gun *blue; { /*{{{defs*/ Visual *vis; int x=0; int y=0; int gbits=0; unsigned long attmask; XSetWindowAttributes attributes; char * winname="Xmountains"; XTextProperty textprop; unsigned int border; unsigned long gcvmask; XGCValues gcv; XWindowAttributes xgwa; int i; int newmap=FALSE; /*}}}*/ if (use_window) use_root = 0; do_clear = want_clear; use_root = want_use_root; pixmap_installed = use_background; graph_width = gptr->graph_width; graph_height = gptr->graph_height; /*{{{open display*/ dpy = XOpenDisplay(display); if( ! dpy ) { fprintf(stderr,"failed to open display\n"); exit(1); } screen = DefaultScreen(dpy); parent = (use_window ? use_window : RootWindow(dpy, screen)); /*}}}*/ /*{{{find appropriate vis*/ /* map=defaultmap=DefaultColormap(dpy,screen); */ XGetWindowAttributes (dpy, parent, &xgwa); map=defaultmap=xgwa.colormap; vis = DefaultVisual(dpy,screen); depth = DefaultDepth(dpy,screen); /*}}}*/ /*{{{set colormap*/ table = (XColor *)malloc(gptr->n_col * sizeof(XColor)); if( NULL == table ) { fprintf(stderr,"malloc failed for colour table\n"); exit(1); } for(i = 0; i < gptr->n_col; i++) { table[i].red = red[i]; table[i].green = green[i]; table[i].blue = blue[i]; while( ! XAllocColor(dpy,map,table+i) ) { if( newmap ){ fprintf(stderr,"failed to allocate colour %d\n",i); XCloseDisplay(dpy); exit(1); }else{ map = XCopyColormapAndFree(dpy,map); newmap=TRUE; } } } /*}}}*/ /*{{{create window*/ attmask = 0; if( use_root || use_window ) { win = (use_window ? use_window : parent); if( ! use_background ) { attmask |= CWEventMask; attributes.event_mask = ExposureMask; /* catch expose events */ } attmask |= CWColormap; attributes.colormap = map; XChangeWindowAttributes(dpy,win,attmask,&attributes); }else{ if( geom ) { gbits =XParseGeometry(geom,&x,&y,&graph_width,&graph_height); if((gbits & XValue) && (gbits & XNegative)) { x += DisplayWidth(dpy,screen) - graph_width; } if((gbits & YValue) && (gbits & YNegative)) { y += DisplayHeight(dpy,screen) - graph_height; } } attmask |= CWEventMask; if( ! use_background ) { attributes.event_mask = ButtonPressMask|ButtonReleaseMask|ExposureMask; }else{ attributes.event_mask = ButtonPressMask|ButtonReleaseMask; } attmask |= CWBackPixel; attributes.background_pixel = BlackPixel(dpy,screen); attmask |= CWBackingStore; attributes.backing_store = NotUseful; attmask |= CWColormap; attributes.colormap = map; win = XCreateWindow(dpy,parent,x,y,graph_width,graph_height,0, depth,InputOutput,vis,attmask,&attributes); /* Setup for ICCCM delete window. */ wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); (void) XSetWMProtocols (dpy, win, &wm_delete_window, 1); textprop.value = (unsigned char *) winname; textprop.encoding = XA_STRING; textprop.format = 8; textprop.nitems = strlen(winname); XSetWMName(dpy,win,&textprop); } /*}}}*/ /*{{{create pixmap*/ XGetGeometry(dpy,win,&root,&x,&y,&graph_width,&graph_height,&border,&depth); stip = XCreateBitmapFromData(dpy,win,gray_bits,gray_width,gray_height); gcvmask = 0; gcvmask |= GCForeground; gcv.foreground = WhitePixel(dpy,screen); gcvmask |= GCBackground; gcv.background = BlackPixel(dpy,screen); gcvmask |= GCGraphicsExposures; gcv.graphics_exposures = FALSE; gcvmask |= GCStipple; gcv.stipple = stip; gcvmask |= GCFillStyle; gcv.fill_style = FillSolid; gcv.graphics_exposures = FALSE; gc = XCreateGC(dpy,win,gcvmask,&gcv); /* if we are going to install this as a root pixmap, throw away * the old one FIRST. this reduces fragmentation */ if( use_background && (use_root || use_window)) { XSetWindowBackgroundPixmap(dpy,win,None); } if( use_root ) { /* in case of virtual window manager set to size of display */ /* This is bogus -- always obey the size of the window itself */ /* graph_width = DisplayWidth(dpy,screen); */ /* graph_height = DisplayHeight(dpy,screen); */ } if(swosh) { if(gptr->repeat < 0) { gptr->pixmap_width = graph_width - gptr->repeat; bg_pix = XCreatePixmap(dpy, win, graph_width, graph_height, depth); } else { if(gptr->repeat == 0) { gptr->repeat = graph_width; } gptr->pixmap_width = graph_width + gptr->repeat; } } else { gptr->pixmap_width = graph_width; } pix = XCreatePixmap(dpy, win, gptr->pixmap_width, graph_height, depth); /*}}}*/ blank_region(0, 0, gptr->pixmap_width, graph_height); if( use_background ) { XSetWindowBackgroundPixmap(dpy,win,pix); } if( ! use_root ) { XMapWindow(dpy, win ); } XClearWindow(dpy,win); zap_events(0); gptr->graph_width = graph_width; gptr->graph_height = graph_height; } /*}}}*/ /*{{{void scroll_screen( int dist )*/ void scroll_screen( dist ) int dist; { int reverse=FALSE; if( dist < 0 ) { dist = -dist; reverse=TRUE; } /* scroll the pixmap */ if( dist > g.pixmap_width ) { dist = g.pixmap_width; } if( reverse ) { /* copy the data */ XCopyArea(dpy, pix, pix, gc, 0, 0, g.pixmap_width - dist, graph_height, dist, 0); /* blank new region */ blank_region(0,0,dist,graph_height); }else{ /* copy the data */ XCopyArea(dpy, pix, pix, gc, dist, 0, g.pixmap_width - dist, graph_height, 0, 0); /* blank new region */ blank_region(g.pixmap_width - dist, 0, dist, graph_height); } /* update the window to match */ if( pixmap_installed ) { /* this line never seems to be needed on any system I know about * but the manual says an X server * may make a copy of a background pixmap * so in principle we should re-install. */ XSetWindowBackgroundPixmap(dpy,win,None); if(swosh && reverse) { XCopyArea(dpy, pix, bg_pix, gc, dist, 0, graph_width, graph_height, 0, 0); XSetWindowBackgroundPixmap(dpy, win, bg_pix); } else { XSetWindowBackgroundPixmap(dpy,win,pix); } XClearWindow(dpy,win); }else{ if(reverse) { XCopyArea(dpy, pix, win, gc, dist, 0, graph_width, graph_height, 0, 0); } else { XCopyArea(dpy, pix, win, gc, 0, 0, graph_width, graph_height, 0, 0); } } } /*}}}*/ /*{{{void plot_pixel( int x, int y, Gun value )*/ void plot_pixel( x, y, value ) int x; int y; Gun value; { int do_draw, draw_x, draw_y1, draw_y2; unsigned long draw_colour; /* if x is negative this means flush the stored request */ if(! plot_saved) /* no stored values */ { plot_x = x; plot_y1=plot_y2 = y; plot_col=table[value].pixel; do_draw=FALSE; plot_saved = (x >=0); }else{ if( x < 0 ) /* requesting a flush */ { draw_x=plot_x; draw_y1=plot_y1; draw_y2=plot_y2; draw_colour = plot_col; plot_saved=FALSE; do_draw=TRUE; }else{ /* plot request with saved value */ if( (x==plot_x) && (plot_col == table[value].pixel)) /* add to line */ { if(yplot_y2) plot_y2=y; do_draw=FALSE; }else{ draw_x=plot_x; draw_y1=plot_y1; draw_y2=plot_y2; draw_colour=plot_col; do_draw=TRUE; plot_x=x; plot_y1=plot_y2=y; plot_col=table[value].pixel; } } } if( do_draw ) { XSetForeground(dpy,gc,draw_colour); if( draw_y1 == draw_y2 ) { XDrawPoint(dpy,pix,gc,draw_x,draw_y1); }else{ XDrawLine(dpy,pix,gc,draw_x,draw_y1,draw_x,draw_y2); } } } /*}}}*/ /*{{{void flush_region(int x, int y, int w, int h)*/ void flush_region( x, y, w, h) int x; int y; int w; int h; { /* flush outstanding plots */ plot_pixel(-1,0,0); if(!swosh) { XCopyArea(dpy,pix,win,gc,x,y,w,h,x,y); } } /*}}}*/ print_alg.c0000644000767600076400000000425511245717275011523 0ustar spbepcc#include #define P(A) fprintf(stderr,"%s\n",A) void print_algorithm() { P("This program uses a modified form of the mid-point displacement algorithm"); P(""); P("The mid-point displacement algorithm is a recursive algorithm, each iteration"); P("doubles the resolution of the grid. This is done in 2 stages."); P(""); P("A B A B A F B"); P(" stage1 stage2"); P(" ---------> E --------> G E H"); P(""); P("C D C D C I D"); P(""); P("The new points are generated by taking an average of the surrounding points"); P("and adding a random offset."); P("The modifications to the standard algorithm are as follows:"); P("There are three optional regeneration steps to reduce \"creasing\". A"); P("regeneration step recalculates the height of existing points using an"); P("average and offset from a newer generation of points. The three"); P("regeneration steps are:"); P(" rg1: recalculate corner points (A,B,C,D) from the midpoints (E)"); P(" after the stage1 update."); P(" rg2: recalculate midpoints (E) from the edge points (F,G,H,I)"); P(" after the stage2 update"); P(" rg3: recalculate corner points (A,B,C,D) from the edge points (F,G,H,I)"); P(" after the stage2 update"); P("The regeneration stages are turned on by the smoothing parameter (-s flag)"); P(""); P(" flag rg3 rg2 rg1"); P(" 0 off off off"); P(" 1 on off off"); P(" 2 off on off"); P(" 3 on on off"); P(" 4 off off on"); P(" 5 on off on"); P(" 6 off on on"); P(" 7 on on on"); P(""); P("When performing the regeneration steps the random offset is added to a"); P("weighted average of the previous value of the point and a the average of"); P("the new points. The weighting factors are controlled by the -X and -Y flags."); P(""); P("The -x flag (cross update) controls whether the midpoints (E) are included"); P("in the average when performing the stage2 update or if only the corner"); P("points are used."); P(""); } crinkle.h0000644000767600076400000000567506424133032011171 0ustar spbepcc/* $Id: crinkle.h,v 2.9 1997/10/24 14:52:10 spb Exp $ */ #ifndef CRINKLE #define CRINKLE /* {{{ typedefs */ typedef float Height; typedef float Length; /* }}} */ /* {{{ defines */ #ifndef NULL #define NULL (void *) 0 #endif #ifndef FALSE #define FALSE 0 #define TRUE 1 #endif #define START 0 #define STORE 1 #define NSTRIP 8 /* }}} */ /* {{{ structs */ /* parameters for the update */ typedef struct parm{ Height mean; /* mean altitude */ int rg1; /* optional regeneration steps */ int rg2; int rg3; int cross; /* use four point average on edges rather than 2 */ int force_front; /* keep front edge low */ int force_back; /* keep back edge low */ Height forceval; /* value to force to */ float mix; /* fraction of old value to include in average */ float midmix; /* same but for cross updates */ float fdim; }Parm; /* The parameter struct for the recursive procedure */ typedef struct fold{ int level; /* levels of recursion below us */ int count; /* number of points at this level */ Length length; /* width of the update square */ Length scale; /* scale factor for perturbations */ Length midscale; /* as above but for diagonal offsets */ struct parm *p; /* update parameters */ struct strip *s[NSTRIP]; /* pointers to the pipeline strips */ struct strip *save; /* save position for STORE state */ int stop; /* level to stop recursion */ int state; /* internal stat of algorithm */ struct fold *next; /* next iteration down */ struct fold *parent; /* next iteration up */ } Fold; /* strip of altitudes */ typedef struct strip{ struct fold *f; /* parent fold structure */ Height *d; /* should have 2^level + 1 (f->count) points */ }Strip; /* }}} */ /* {{{ prototypes */ #ifdef ANSI Strip *make_strip (Fold *); void free_strip (Strip *); Strip *double_strip (Strip *); Strip *set_strip(Fold *, Height ); Strip *random_strip (Fold *); Strip *next_strip (Fold *); void reset_fold(Fold *f); Fold *make_fold (Fold *,Parm *,int, int, Length); void free_fold (Fold *); Length gaussian (); void x_update(Fold *, float, float, Strip *, Strip *, Strip *); void p_update(Fold *, float, float, Strip *, Strip *, Strip *); void t_update(Fold *, float, float, Strip *, Strip *, Strip *); void v_update(Fold *, float, float, Strip *, Strip *, Strip *); void vside_update(Fold *, float, float, Strip *); void hside_update(Fold *, float, float, Strip *, Strip *, Strip *); #else Strip *make_strip (); void free_strip (); Strip *double_strip (); Strip *set_strip (); Strip *random_strip (); Strip *next_strip (); void reset_fold(); Fold *make_fold (); void free_fold (); Length gaussian (); void x_update(); void p_update(); void t_update(); void v_update(); void vside_update(); void hside_update(); #endif /* }}} */ #endif paint.h0000644000767600076400000000414611245717275010663 0ustar spbepcc/* $Id: paint.h,v 1.16 2009/08/28 09:09:17 spb Exp $ */ #ifndef PAINT #define PAINT #include "crinkle.h" /* colour code definitions */ typedef int Col; typedef unsigned short Gun; typedef struct graph{ int graph_height; /* height of display */ int graph_width ; /* width of display */ int pixmap_width; /* width of pixmap buffer */ int width; /* width of terrain strip */ float ambient; /* level of ambient light */ float contrast; /* contrast, * increases or decreases effect of cosine rule */ float contour; float vfract; /* relative strength of vertical light relative * to the main light source */ float altitude; float distance; double phi; /* angle of the light (vertical plane)*/ double alpha; /* angle of the light (horizontal plane) * must have -pi/4 < alpha < pi/4 */ Height base_shift; /* offset from calcalt to artist coordinates */ Height sealevel; double stretch; /* vertical stretch */ int n_col; int band_size; int levels; int stop; int map; int reflec; int repeat; int pos; int scroll; }Graph; #define BLACK 0 #define WHITE 1 #define SEA_LIT 2 #define SEA_UNLIT 3 #define SKY 4 #define BAND_BASE 5 #ifndef BAND_SIZE #define BAND_SIZE 80 #endif #define N_BANDS 3 #define DEF_COL (BAND_BASE + (N_BANDS * BAND_SIZE)) #define MIN_COL (BAND_BASE + (N_BANDS * 2)) #define COL_RANGE 65535 #define PI 3.14159265 #ifdef ANSI void set_clut(int, Gun *, Gun *, Gun *); Height *extract(Strip *s); void init_artist_variables(); Col get_col(Height p, Height p_plus_x, Height p_plus_y, Height shadow); Col *makemap(Height *a, Height *b, Height *shadow); Col *camera(Height *a, Height *b, Height *shadow); Col *mirror(Height *a, Height *b, Height *shadow); int project( int x , Height y ); #else void set_clut(); Height *extract(); void init_artist_variables(); Col get_col(); Col *makemap(); Col *camera(); Col *mirror(); int project(); #endif #endif patchlevel.h0000644000767600076400000000002511502626220011650 0ustar spbepcc#define PATCHLEVEL 9 copyright.h0000644000767600076400000000134305545572774011565 0ustar spbepcc/* $Id: copyright.h,v 1.2 1994/03/28 15:21:32 spb Exp $ */ /* Copyright 1994 by Stephen Booth, the University of Edinburgh Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. The author makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ vroot.h0000644000767600076400000001370111245717275010716 0ustar spbepcc/* -*- Mode: C; tab-width: 2 -*- */ /*****************************************************************************/ /** Copyright 1991 by Andreas Stolcke **/ /** Copyright 1990 by Solbourne Computer Inc. **/ /** Longmont, Colorado **/ /** **/ /** All Rights Reserved **/ /** **/ /** Permission to use, copy, modify, and distribute this software and **/ /** its documentation for any purpose and without fee is hereby **/ /** granted, provided that the above copyright notice appear in all **/ /** copies and that both that copyright notice and this permis- **/ /** sion notice appear in supporting documentation, and that the **/ /** name of Solbourne not be used in advertising **/ /** in publicity pertaining to distribution of the software without **/ /** specific, written prior permission. **/ /** **/ /** ANDREAS STOLCKE AND SOLBOURNE COMPUTER INC. DISCLAIMS ALL WARRANTIES **/ /** WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF **/ /** MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ANDREAS STOLCKE **/ /** OR SOLBOURNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL **/ /** DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ /** OR PERFORMANCE OF THIS SOFTWARE. **/ /*****************************************************************************/ /* * vroot.h -- Virtual Root Window handling header file * * This header file redefines the X11 macros RootWindow and DefaultRootWindow, * making them look for a virtual root window as provided by certain `virtual' * window managers like swm and tvtwm. If none is found, the ordinary root * window is returned, thus retaining backward compatibility with standard * window managers. * The function implementing the virtual root lookup remembers the result of * its last invocation to avoid overhead in the case of repeated calls * on the same display and screen arguments. * The lookup code itself is taken from Tom LaStrange's ssetroot program. * * Most simple root window changing X programs can be converted to using * virtual roots by just including * * #include * * after all the X11 header files. It has been tested on such popular * X clients as xphoon, xfroot, xloadimage, and xaqua. * It also works with the core clients xprop, xwininfo, xwd, and editres * (and is necessary to get those clients working under tvtwm). * It does NOT work with xsetroot; get the xsetroot replacement included in * the tvtwm distribution instead. * * Andreas Stolcke , 9/7/90 * - replaced all NULL's with properly cast 0's, 5/6/91 * - free children list (suggested by Mark Martin ), 5/16/91 * - include X11/Xlib.h and support RootWindowOfScreen, too 9/17/91 * * Jamie Zawinski , 28-Apr-1997 * - use ANSI C * * Jamie Zawinski , 3-Sep-2003 * - if the environment variable "XSCREENSAVER_WINDOW" is set, use that * as the root window instead of searching for __SWM_VROOT. */ #ifndef _VROOT_H_ #define _VROOT_H_ #define _XSCREENSAVER_VROOT_H_ #if !defined(lint) && !defined(SABER) static const char vroot_rcsid[] = "#Id: vroot.h,v 1.5 2003/09/04 01:04:38 jwz Exp #" "\n" "#Id: vroot.h,v 1.4 1991/09/30 19:23:16 stolcke Exp stolcke #"; #endif #include #include #include #include static Window #ifdef __STDC__ /* ANSIfication added by jwz, to avoid superfluous warnings. */ VirtualRootWindowOfScreen(Screen *screen) #else /* !__STDC__ */ VirtualRootWindowOfScreen(screen) Screen *screen; #endif /* !__STDC__ */ { static Screen *save_screen = (Screen *)0; static Window root = (Window)0; if (screen != save_screen) { Display *dpy = DisplayOfScreen(screen); Atom __SWM_VROOT = None; int i; Window rootReturn, parentReturn, *children; unsigned int numChildren; /* first check for a hex or decimal window ID in the environment */ const char *xss_id = getenv("XSCREENSAVER_WINDOW"); if (xss_id && *xss_id) { unsigned long id = 0; char c; if (1 == sscanf (xss_id, " 0x%lx %c", &id, &c) || 1 == sscanf (xss_id, " %lu %c", &id, &c)) { root = (Window) id; save_screen = screen; return root; } } root = RootWindowOfScreen(screen); /* go look for a virtual root */ __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False); if (XQueryTree(dpy, root, &rootReturn, &parentReturn, &children, &numChildren)) { for (i = 0; i < numChildren; i++) { Atom actual_type; int actual_format; unsigned long nitems, bytesafter; Window *newRoot = (Window *)0; if (XGetWindowProperty(dpy, children[i], __SWM_VROOT, 0, 1, False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytesafter, (unsigned char **) &newRoot) == Success && newRoot) { root = *newRoot; break; } } if (children) XFree((char *)children); } save_screen = screen; } return root; } #undef RootWindowOfScreen #define RootWindowOfScreen(s) VirtualRootWindowOfScreen(s) #undef RootWindow #define RootWindow(dpy,screen) VirtualRootWindowOfScreen(ScreenOfDisplay(dpy,screen)) #undef DefaultRootWindow #define DefaultRootWindow(dpy) VirtualRootWindowOfScreen(DefaultScreenOfDisplay(dpy)) #endif /* _VROOT_H_ */ Imakefile0000644000767600076400000000106107261100177011167 0ustar spbepccLOCAL_LIBRARIES = -lX11 SYS_LIBRARIES = -lm SRCS = calcalt.c random.c artist.c xmountains.c X_graphics.c print_alg.c OBJS = calcalt.o random.o artist.o xmountains.o X_graphics.o print_alg.o HDRS = crinkle.h paint.h patchlevel.h copyright.h vroot.h SHARS = README $(SRCS) $(HDRS) Imakefile xmountains.man Makefile.alt ComplexProgramTarget(xmountains) xmountains.shar: $(SHARS) shar -o xmountains.shar README $(HDRS) Imakefile xmountains.man $(SRCS) xmountains.tar: $(SHARS) tar cvf xmountains.tar $(SHARS) xmountains.man0000644000767600076400000001114306700103054012254 0ustar spbepcc.de Id .ds Rv \\$3 .ds Dt \\$4 .. .Id $Id: xmountains.man,v 1.14 1999/03/30 08:07:08 spb Exp $ .ds r \s-1RCS\s0 .if n .ds - \%-- .if t .ds - \(em .TH XMOUNTAINS 1 .SH NAME xmountains \- A fractal landscape generator. .SH SYNOPSIS .B xmountains [ .B bqgPdEmMrBnZIASTWFGCapcevfRltxsXYH ] .SH DESCRIPTION .B xmountains is a X11 based fractal landscape generator. It generates random fractal surfaces and displays them in a window. While the program is running the fractal is continuously extended on the right and the image is scrolled from right to left to expose the newly generated area. .PP Flags: .br .B \-b .RS Use the root window. .RE .br .B \-q .RS Reset the root window when the program exits. This option is ignored unless the program is using the root window. .RE .br .B \-g [string] .RS Set the geometry of the window. .RE .br .B \-P [filename] .RS Write the PID to the specified file. .RE .br .B \-d [string] .RS Set the display. .RE .br .B \-E .RS Toggle the way that window repainting is done. By default the image pixmap is installed as the background pixmap of the window and window repainting should be performed automatically by the X server. If this does not work on a particular system then this flag can be used to enable explicit expose event processing. In the default mode root window images will remain in place after the program exits. .RE .br .B \-m .RS Display a map of the surface rather than a perspective view. .RE .br .B \-M .RS Produce reflections in the water. This may be a little slower. .RE .br .B \-r [20] .RS To reduce the load on the X server the program generates several columns of pixels before scrolling the image. This flag sets the number of columns. A negative value reverses the direction of scrolling. A value of zero makes the program scan across the window without scrolling at all. .RE .br .B \-B [80] .RS Set the number of shades of each colour that the program allocates. .RE .br .B \-n [245] .RS Set a maximum number of colours to use. This is just a different way of setting the number of shades of each colour. .RE .br .B \-Z [10] .RS Set the number of seconds that the program sleeps after scrolling the screen. .RE .br .B \-I [40.0] .RS Set the vertical angle of illumination. .RE .br .B \-A [0.0] .RS Set the horizontal angle of illumination. .RE .br .B \-S [0.6] .RS Set the vertical stretch of the surface. .RE .br .B \-T [0.5] .RS Set the vertical shift of the surface. .RE .br .B \-W [0.5] .RS Set the height where the water occurs. .RE .br .B \-F [1] .RS Reduce the variation in the foreground height to ensure a good view of the surface. This flag sets the number of iterations for which the foreground height is constrained to a constant value. .RE .br .B \-G [-1.0] .RS Mean altitude for the for foreground. .RE .br .B \-C [0.3] .RS Set the contour parameter. The base colour of a point depends on its height and how flat the surface is. This parameter controls the relative importance of these factors. .RE .br .B \-a [2.5] .RS Set the Altitude of the viewpoint. .RE .br .B \-p [4.0] .RS Set the distance of the viewpoint from the front of the surface. .RE .br .B \-c [1.0] .RS Set the contrast parameter. Values too far from 1.0 will give strange results .RE .br .B \-e [0.3] .RS Set the ambient light level. This is a fractional value that sets how bright shaded areas will be compared to fully illuminated ground. .RE .br .B \-v [0.6] .RS Set the vertical light level. The program also implements a secondary light source shining from directly above the surface. This flag sets how bright this light source is relative to the main light source. .RE .br .B \-f [0.65] .RS Set the fractal dimension of the surface. This should be in the range 0.5\-1.0. .RE .br .B \-R [0] .RS Set the seed for the random number generator. A value of 0 causes the seed to be set from the clock. .RE .br .B \-l [10] .RS Set the width of the surface. Increasing this value by one doubles the width of the surface. .RE .br .B \-t [2] .RS Set the number of non\-fractal iterations. Increasing this value by one doubles the average number of mountains across the width of the surface. .RE .br .B \-x .RS Use cross updates (see under \-H) .RE .br .B \-s [1] .RS Control the regeneration steps used to reduce creasing. There are three possible regeneration steps controlled by the first 3 bits of this flag value. (see under \-H) .RE .br .B \-X [0.0] .RS regeneration step parameter (see under \-H) .RE .br .B \-Y [0.0] .RS regeneration step parameter (see under \-H) .RE .br .B \-H .RS Print a short description of the algorithm explaining the \-x \-s \-X and \-Y parameters. .RE .PP .SH IDENTIFICATION Author: S.Booth@ed.ac.uk Makefile.alt0000644000767600076400000000136506216231656011612 0ustar spbepcc# # Generic makefile for xmountins. You will have to add the locations # of your X include files and libraries to the appropriate macros # CC=cc CFLAGS=-I/usr/iclude/X11 LDFLAGS=-L/usr/lib/X11 LOCAL_LIBRARIES = -lX11 SYS_LIBRARIES = -lm SRCS = calcalt.c random.c artist.c global.c xmountains.c X_graphics.c print_alg.c OBJS = calcalt.o random.o artist.o global.o xmountains.o X_graphics.o print_alg.o HDRS = crinkle.h global.h paint.h patchlevel.h copyright.h xmountains: $(OBJS) $(CC) $(LDFLAGS) -o xmountains $(OBJS) -lX11 -lm calcalt.o: crinkle.h artist.o: global.h paint.h crinkle.h global.o: crinkle.h paint.h xmountains.o: paint.h global.h patchlevel.h copyright.h crinkle.h X_graphics.o: paint.h crinkle.h