level,
911 | f->s[0],f->s[1],f->s[2],f->s[3],f->s[4],f->s[5],f->s[6],f->s[7]);
912 | }
913 | #endif
914 |
--------------------------------------------------------------------------------
/copyright.h:
--------------------------------------------------------------------------------
1 | /* $Id: copyright.h,v 1.2 1994/03/28 15:21:32 spb Exp $ */
2 | /*
3 |
4 | Copyright 1994 by Stephen Booth, the University of Edinburgh
5 |
6 | Permission to use, copy, modify, distribute, and sell this software and its
7 | documentation for any purpose is hereby granted without fee, provided that
8 | the above copyright notice appear in all copies and that both that
9 | copyright notice and this permission notice appear in supporting
10 | documentation, and that the name of the author not be used in advertising or
11 | publicity pertaining to distribution of the software without specific,
12 | written prior permission. The author makes no representations about the
13 | suitability of this software for any purpose. It is provided "as is"
14 | without express or implied warranty.
15 |
16 | */
17 |
--------------------------------------------------------------------------------
/crinkle.h:
--------------------------------------------------------------------------------
1 | /* $Id: crinkle.h,v 2.9 1997/10/24 14:52:10 spb Exp $ */
2 | #ifndef CRINKLE
3 | #define CRINKLE
4 | /* {{{ typedefs */
5 | typedef float Height;
6 | typedef float Length;
7 | /* }}} */
8 | /* {{{ defines */
9 | #ifndef NULL
10 | #define NULL (void *) 0
11 | #endif
12 | #ifndef FALSE
13 | #define FALSE 0
14 | #define TRUE 1
15 | #endif
16 |
17 | #define START 0
18 | #define STORE 1
19 |
20 | #define NSTRIP 8
21 | /* }}} */
22 | /* {{{ structs */
23 |
24 | /* parameters for the update */
25 | typedef struct parm{
26 | Height mean; /* mean altitude */
27 | int rg1; /* optional regeneration steps */
28 | int rg2;
29 | int rg3;
30 | int cross; /* use four point average on edges rather than 2 */
31 | int force_front; /* keep front edge low */
32 | int force_back; /* keep back edge low */
33 | Height forceval; /* value to force to */
34 | float mix; /* fraction of old value to include in average */
35 | float midmix; /* same but for cross updates */
36 | float fdim;
37 | }Parm;
38 |
39 | /* The parameter struct for the recursive procedure */
40 | typedef struct fold{
41 | int level; /* levels of recursion below us */
42 | int count; /* number of points at this level */
43 | Length length; /* width of the update square */
44 | Length scale; /* scale factor for perturbations */
45 | Length midscale; /* as above but for diagonal offsets */
46 | struct parm *p; /* update parameters */
47 | struct strip *s[NSTRIP]; /* pointers to the pipeline strips */
48 | struct strip *save; /* save position for STORE state */
49 | int stop; /* level to stop recursion */
50 | int state; /* internal stat of algorithm */
51 | struct fold *next; /* next iteration down */
52 | struct fold *parent; /* next iteration up */
53 | } Fold;
54 |
55 | /* strip of altitudes */
56 | typedef struct strip{
57 | struct fold *f; /* parent fold structure */
58 | Height *d; /* should have 2^level + 1 (f->count) points */
59 | }Strip;
60 |
61 |
62 | /* }}} */
63 | /* {{{ prototypes */
64 | #ifdef ANSI
65 | Strip *make_strip (Fold *);
66 | void free_strip (Strip *);
67 | Strip *double_strip (Strip *);
68 | Strip *set_strip(Fold *, Height );
69 | Strip *random_strip (Fold *);
70 | Strip *next_strip (Fold *);
71 | void reset_fold(Fold *f);
72 | Fold *make_fold (Fold *,Parm *,int, int, Length);
73 | void free_fold (Fold *);
74 | Length gaussian ();
75 | void x_update(Fold *, float, float, Strip *, Strip *, Strip *);
76 | void p_update(Fold *, float, float, Strip *, Strip *, Strip *);
77 | void t_update(Fold *, float, float, Strip *, Strip *, Strip *);
78 | void v_update(Fold *, float, float, Strip *, Strip *, Strip *);
79 | void vside_update(Fold *, float, float, Strip *);
80 | void hside_update(Fold *, float, float, Strip *, Strip *, Strip *);
81 | #else
82 | Strip *make_strip ();
83 | void free_strip ();
84 | Strip *double_strip ();
85 | Strip *set_strip ();
86 | Strip *random_strip ();
87 | Strip *next_strip ();
88 | void reset_fold();
89 | Fold *make_fold ();
90 | void free_fold ();
91 | Length gaussian ();
92 | void x_update();
93 | void p_update();
94 | void t_update();
95 | void v_update();
96 | void vside_update();
97 | void hside_update();
98 |
99 | #endif
100 | /* }}} */
101 | #endif
102 |
--------------------------------------------------------------------------------
/docs/about_xmountains.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | About xmountains
4 |
5 |
6 | All about xmountains
7 |
8 |
9 |
10 | Xmountains is a fractal terrain generator written by
11 | Stephen Booth
12 | This document describes what it does and how it works.
13 |
14 |
15 |
16 | The basic idea behind a fractal landscape is to generate a continuous surface
17 | which varies in height randomly but with the random variation obeying a
18 | particular statistical law.
19 |
20 |
21 |
22 | In the case of a fractal landscape the average difference in height
23 | between pairs of points separated by a distance l should go as
24 | a power law in l. If you are only interested in random terrain
25 | generation rather than fractal self-similarity then you could use other
26 | functions of l that tend to zero as l tends to zero.
27 | If the function does not tend to zero then the result will not be
28 | continuous. I use the following definition:
29 |
30 |
31 |
32 | 2H
33 | <|H1 - H2|> = l
34 |
35 |
36 |
37 |
38 | For values of H below 0.5 as l gets small the variation in height
39 | is greater than the
40 | horizontal distance between the points (l) so the surface becomes
41 | space-filling. For values of H at 0.5 or above the surface becomes
42 | smoother as H increases. This is because the variation in height at
43 | short length scales is a smaller fraction of the variation at longer
44 | length scales. When displaying the surface you usually re-scale the whole
45 | lot by a constant factor so it is the relative variation that matters.
46 |
47 |
48 |
49 | This program uses a modified form the mid-point displacement algorithm
50 |
51 |
52 |
53 | The mid-point displacement algorithm is a recursive algorithm.
54 | Starting from a crude outline of the surface more and more detail is
55 | added at progressively smaller length scales.
56 | Each iteration doubles the resolution of a 2 dimensional grid of altitudes.
57 |
58 |
59 | This is done in 2 stages:
60 |
61 | A B A B
62 | stage1
63 | ---------> E
64 |
65 | C D C D
66 |
67 |
68 |
69 | A B A F B
70 | stage2
71 | E --------> G E H
72 |
73 | C D C I D
74 |
75 |
76 | More detail can then be filled in by recursion:
77 |
78 |
79 | A F B A F B
80 | stage1 * *
81 | G E H --------> G E H
82 | * *
83 | C I D C I D
84 |
85 |
86 | A F B A + F + B
87 | * * stage2 + * + * +
88 | G E H --------> G + E + H
89 | * * + * + * +
90 | C I D C + I + D
91 |
92 |
93 |
94 |
95 | The new points are generated by taking an average of the surrounding points
96 | and adding a random offset. In order to generate the power law behaviour
97 | described above the random offset is scaled by a factor
98 | proportional to a power (2H in my notation) of the distance between the new
99 | points and the
100 | surrounding points. The results seem to be a little better if the random
101 | offsets are taken from a gaussian distribution. The basic idea is very
102 | similar to that used by the Koch snowflake.
103 |
104 |
105 | The modifications to the standard algorithm are as follows:
106 | There are three optional regeneration steps to reduce
107 | creasing. These are controlled by the
108 | -s flag.
109 |
110 |
111 | The -x flag (cross update) controls whether the
112 | midpoints (E) are included
113 | in the average when performing the stage2 update or if only the corner
114 | points are used.
115 |
116 |
117 |
118 |
119 | When I started in this game "creasing" was a big problem with square
120 | grid mid-point displacement surfaces
121 | and explicit smoothing steps were introduced to get rid of these.
122 | You can make my program revert to these early algorithms by specifying
123 | "-s 0" Things are particularly bad if you calculate the middle of the sides
124 | independently of the middle of the square ("-x" in my program)
125 | This was not uncommon in the other programs I have seen.
126 |
127 |
128 |
129 | If you only use a pair of points to perform the average for the middle
130 | of the sides then for any point that lies on one of the sides of a
131 | large length scale square its value depends ONLY on the values of other
132 | points that lie along that side. This line then forms a crease. Because
133 | no information ever crosses this line it acts as a kind of "event
134 | horizon". The heights of points on the crease are calculated
135 | independently of everything else and then the surfaces on the 2 sides
136 | form to match this line but the 2 surfaces are independent of each
137 | other. The crease is a mis-match between the 2 independent surfaces that
138 | are only constrained to follow a common boundary that has been specified
139 | independently of each of them
140 |
141 |
142 |
143 |
144 | When you split the update into 2 steps:
145 |
146 | - generate the middle of the square with an average of the
147 | 4 corners and a random offset based on a length scale of L/sqrt(2).
148 |
149 | - generate the sides as an average over 4 points (2 corner points and
150 | 2 middle of square points) followed by a random offset based on a
151 | length scale of L/2.
152 |
153 |
154 | the information flows sideways into the sides of the large squares.
155 | The problem does not go away but instead of creases along the sides of
156 | the squares you get conical deformations at the corners of the squares:
157 |
158 |
159 |
160 | This is an improvement but not the whole story.
161 |
162 |
163 |
164 |
165 | The root cause of creasing and the conical
166 | deformations is that the position
167 | of some points are fixed by the early (long-distance) iterations of the
168 | fractal algorithm. We are trying to generate a surface where the average
169 | difference in height between points on the surface is a function of the
170 | distance between them. Ideally two points should have an equal effect on
171 | each other. Instead we have implemented a hierarchy of points where the
172 | information only flows in one direction.
173 |
174 |
175 | The solution I came up with was to use the early iteration to set the
176 | overall trend of the surface rather than setting the exact position of
177 | particular points. This is done by a 2 steps forward/1 step back method.
178 | In the original algorithm the results at the end of one iteration are
179 | used to generate a new set of points with each iteration adding detail at a
180 | length scale of half the previous iteration. I added a second stage to
181 | each iteration that consisted of discarding all of the points generated
182 | by previous iterations and regenerating them from the new points.
183 | I think this is a lot closer to the desired result because every point
184 | is the result of updates at all length scales.
185 |
186 |
187 |
188 | However I have a
189 | suspicion that it may result in a slight shift in the fractal dimension.
190 | It would be nice to measure the fractal dimension produced as a function
191 | of the input parameter to the algorithm.
192 |
193 |
194 | A regeneration step recalculates the height of existing points using an
195 | average and offset from a newer generation of points. In xmountains the three
196 | regeneration steps are:
197 |
198 |
199 | - Step 1
200 | - recalculate corner points (A,B,C,D) from the midpoints (E)
201 | after the stage1 update.
202 | - Step 2
203 | - recalculate midpoints (E) from the edge points (F,G,H,I)
204 | after the stage2 update
205 | - Step 3
206 | - recalculate corner points (A,B,C,D) from the edge points (F,G,H,I)
207 | after the stage2 update
208 |
209 |
210 | The regeneration stages are turned on by the smoothing parameter
211 | (-s flag)
212 |
213 | flag Step-3 Step-2 Step-1
214 | 0 off off off
215 | 1 on off off
216 | 2 off on off
217 | 3 on on off
218 | 4 off off on
219 | 5 on off on
220 | 6 off on on
221 | 7 on on on
222 |
223 |
224 | The default is to just use step 3 (-s 1)
225 |
226 | When performing the regeneration steps the random offset is added to an
227 | average of the new points.
228 |
229 |
230 | I came across a different solution in the xmnts program by
231 |
232 | Paul Sharpe @ DEC, Reading, England.
233 |
234 | who also modified the old points at each iteration, but he only added an
235 | additional random offset to the old points.
236 |
237 |
238 | I added this capability to my program. The -X and -Y parameters
239 | trade off the two methods if you leave them at 0.0 (the default) you get
240 | my algorithm. If you set them to 1.0 you get Paul's and values
241 | in-between give you a mixture of the two, i.e. a weighted average of the
242 | new points and the old value of the point.
243 |
244 | How well does this all work
245 | The relative importance of the different algorithms can easily be seen
246 | if we remove the random element from the algorithm and replace the
247 | gaussian random number with a constant value. Without any random
248 | variation we should get a completely smooth surface. Without any
249 | regeneration steps or cross updates we get a surface
250 | consisting only of creases.
251 |
252 |
253 |
254 |
255 | The addition of cross updates generate
256 | a very interesting surface.
257 |
258 |
259 |
260 |
261 | This is an
262 | improvement as the surface has better rotational symmetry but it still
263 | has significant artifacts. These are completely missing when regeneration
264 | steps are used.
265 |
266 | Pipelining
267 |
268 | The other trick I came up with was to pipeline the code. This is also
269 | responsible for much of the speed because it reduces swapping and
270 | improves cache use. I don't think that anyone else does this but
271 | the idea is straightforward once you think of it.
272 |
273 |
274 | If you think of the normal algorithm it is possible to add extra detail
275 | to a region of the surface without adding this level of detail to the
276 | entire surface. Each iteration of the algorithm increases the number of
277 | squares by 4. You can then add further detail to a restricted region of
278 | the surface by only applying the next level of recursion to a subset of
279 | these squares. Obviously some squares you choose not to update
280 | will end up partially updated because they share sides with updated
281 | squares.
282 |
283 |
284 | As an aside this selective updating allows you to zoom-in on a surface
285 | efficiently. You don't bother updating squares outside of your field of
286 | view and you keep adding more detail to the squares you can see until
287 | the sides of the smallest level squares subtends less than a maximum
288 | angle at your point of view (i.e. the sides always look short).
289 |
290 |
291 | What I do in xmountains is slightly different.
292 | I only perform updates necessary to fully update the left hand
293 | row of squares. These fully updated points are used to generate a column
294 | of pixels in the output and then discarded. The new left hand edge is
295 | not fully updated so additional updates are now required.
296 | Imagine I have a level-1 surface as follows:
297 |
298 | 1 1 1
299 |
300 | 1 1 1
301 |
302 | 1 1 1
303 |
304 |
305 | And that I have some method of generating new points on the right hand
306 | side of this surface (I will show how I do this later but for the time
307 | being assume this is the top iteration level and we can generate new
308 | points by applying random offsets to a constant value).
309 |
310 |
311 | I can use these points to fill in part of the left hand squares
312 |
313 | 1 2 1 1
314 | 2 2
315 | 1 2 1 1
316 | 2 2
317 | 1 2 1 1
318 |
319 |
320 | Now scroll everything to the left
321 |
322 | 1 1
323 |
324 | 1 1
325 |
326 | 1 1
327 |
328 |
329 | and add in a new third column on the right hand side
330 |
331 | 1 1 1
332 |
333 | 1 1 1
334 |
335 | 1 1 1
336 |
337 |
338 | This returns us to our original state. This process can be repeated
339 | indefinitely. For each column of points it inputs on the right it outputs
340 | 2 columns on the left with level of detail doubled. If you want to
341 | perform N levels of update then you chain together N of these steps.
342 | If you want to use a more complicated update (For example the
343 | regeneration steps and the cross update) then the same basic approach
344 | applies but the details get more complicated.
345 | In the xmountains the equivalent to the step described above is a
346 | routine called next_strip.
347 |
348 | xmountain command line flags
349 | xmountains: version 2.3
350 | usage: xmountains -[bqgdPEmMrBZIASFTCapcevfRltxsXYH]
351 | -b [false] use root window
352 | -q [false] reset root window on exit
353 | -g string window geometry
354 | -d string display
355 | -P filename write PID to file
356 | -E [false] toggle explicit expose events
357 | -m [false] print map
358 | -M [false] implement reflections
359 | -r int [20] # columns before scrolling
360 | -B int [80] # shades in a colour band
361 | -n int [245] # number of colours
362 | -Z int [10] time to sleep before scrolling
363 | -I float [40.000000] vertical angle of light
364 | -A float [0.000000] horizontal angle of light
365 | -S float [0.600000] vertical stretch
366 | -T float [0.500000] vertical shift
367 | -W float [0.000000] sealevel
368 | -F int [1] reduce variation in the foreground
369 | -G float [-1.000000] average foreground height
370 | -C float [0.300000] contour parameter
371 | -a float [2.500000] altitude of viewpoint
372 | -p float [4.000000] distance of viewpoint
373 | -c float [1.000000] contrast
374 | -e float [0.300000] ambient light level
375 | -v float [0.600000] vertical light level
376 | Fractal options:
377 | -f float [0.650000] fractal dimension
378 | -R int [0] rng seed, read clock if 0
379 | -l int [10] # levels of recursion
380 | -t int [2] # non fractal iterations
381 | -x [true] cross update
382 | -s [1] smoothing (0-7)
383 | -X float [0.000000] fraction of old value for rg2 & rg3
384 | -Y float [0.000000] fraction of old value for rg1
385 | -H print short description of algorithm.
386 |
387 |
388 | X window graphics
389 | The algorithms and code for xmountains were originally developed for to
390 | drive particular graphics hardware and then ported to the X-window
391 | system. This history can still be seen in the following ways
392 |
393 |
394 | - All the options are given as command line flags.
395 |
- The code assume a CLUT based colour model rather than direct RGB values.
396 |
397 |
398 | Most of the suggestions I get for changes to xmountains involve either
399 | adding a X control panel to set parameters or implementing 24-bit
400 | graphics. Actually neither of these makes a great deal of sense.
401 |
402 | To save memory the program does not retain any knowledge of currently
403 | displayed surface. The only information that is retained is the final bitmap
404 | image. This makes it very difficult to change the viewpoint while the
405 | program is running (though you could probably get away with slow gradual
406 | changes).
407 |
408 | The program can already utilise 24-bit colour displays the default parameters
409 | are set to use less than 256 colours but the -B or -n flags can be used
410 | to increase the number of colours. The quality of the final image
411 | remains pretty much the same though because there are already 80 shades
412 | of each base colour. If you only ever run on a 24-bit display you may
413 | want to try increasing the number of base colours by increasing N_BANDS
414 | in paint.h and modifying the set_clut routine in artist.c
415 |
416 |
417 |
418 |
419 |
--------------------------------------------------------------------------------
/docs/cone.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spbooth/xmountains/5ed87c3b68c91dbae93290182e2c9d247223cae3/docs/cone.gif
--------------------------------------------------------------------------------
/docs/crease.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spbooth/xmountains/5ed87c3b68c91dbae93290182e2c9d247223cae3/docs/crease.gif
--------------------------------------------------------------------------------
/docs/cushion.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spbooth/xmountains/5ed87c3b68c91dbae93290182e2c9d247223cae3/docs/cushion.gif
--------------------------------------------------------------------------------
/docs/google4108777847be7f63.html:
--------------------------------------------------------------------------------
1 | google-site-verification: google4108777847be7f63.html
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Xmountains site
4 |
5 |
10 | This is the xmountains home page
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
This is actually the javascript version but the X version looks pretty much the same.
21 |
22 |
23 |
24 | Xmountains is a fractal terrain generator written by Stephen Booth
25 |
26 | There is also a
27 |
28 | Java version, a Android and a Javascript version of this code.
29 |
30 |
31 |
32 |
33 | If you find any bugs send me an Email
34 |
35 |
36 |
37 | There is a page describing how the program works.
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/docs/normal.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spbooth/xmountains/5ed87c3b68c91dbae93290182e2c9d247223cae3/docs/normal.gif
--------------------------------------------------------------------------------
/docs/quilt.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spbooth/xmountains/5ed87c3b68c91dbae93290182e2c9d247223cae3/docs/quilt.gif
--------------------------------------------------------------------------------
/global.c:
--------------------------------------------------------------------------------
1 | #include "crinkle.h"
2 | #include "paint.h"
3 |
4 | Fold *top;
5 | int levels = 10;
6 | int stop = 2;
7 | int smooth = 1;
8 | int cross = TRUE;
9 | int slope = 1;
10 | int snooze_time = 10;
11 | int n_col=DEF_COL;
12 | int band_size=BAND_SIZE;
13 | int request_clear = FALSE;
14 | #ifdef USE_E_EVENTS
15 | int e_events = TRUE;
16 | #else
17 | int e_events = FALSE;
18 | #endif
19 | Height start=0.0; /* starting value for the surface */
20 | Height mean=0.0; /* mean value of surface */
21 | Height varience; /* rough estimate of the height of the range */
22 | Height shift=0.5;
23 | Height delta_shadow; /* offset of shadow at each step */
24 | float stretch=0.6;
25 | float contour = 0.3;
26 | float ambient = 0.3;
27 | float contrast = 1.0;
28 | float vfract = 0.6;
29 | float altitude = 2.5;
30 | float distance = 4.0;
31 | double phi=(40.0 * PI)/180.0;
32 | double alpha=0.0;
33 |
34 | double shadow_slip;
35 | double shadow_register=0.0;
36 | double cos_phi;
37 | double sin_phi;
38 | double tan_phi;
39 | double x_fact;
40 | double y_fact;
41 | Height sealevel = 0.0;
42 | Height forceheight = -1.0;
43 | int width; /* width of the landscape, (function of levels) */
44 | int seed=0; /* zero means read the clock */
45 |
46 | /*
47 | * viewport parameters
48 | */
49 | int height; /* height of the screen */
50 | double vangle; /* view angle 0 == horizontal
51 | *increase to look down
52 | */
53 | double tan_vangle;
54 | float vscale;
55 | float viewpos;
56 | float viewheight; /* height of viewpoint */
57 | float focal; /* focal length, calc to preserve aspect ratio */
58 |
59 | Height *shadow; /* height of the shadows */
60 | Height *a_strip, *b_strip; /* the two most recent strips */
61 |
62 |
--------------------------------------------------------------------------------
/global.h:
--------------------------------------------------------------------------------
1 | #ifndef GLOBAL
2 | #define GLOBAL
3 |
4 | extern Fold *top;
5 | extern int levels;
6 | extern int stop;
7 | extern int smooth;
8 | extern int cross;
9 | extern int slope;
10 | extern int snooze_time;
11 | extern int request_clear;
12 | extern int n_col;
13 | extern int band_size;
14 | extern int e_events;
15 | extern float mix;
16 | extern float midmix;
17 | extern float fdim;
18 | extern Height start;
19 | extern Height mean;
20 | extern Height varience;
21 | extern Height shift;
22 | extern Height delta_shadow;
23 | extern float stretch;
24 | extern float contour;
25 | extern float ambient;
26 | extern float contrast;
27 | extern float vfract;
28 | extern float altitude;
29 | extern float distance;
30 | extern double phi;
31 | extern double alpha;
32 | extern double shadow_slip;
33 | extern double shadow_register;
34 | extern double cos_phi;
35 | extern double sin_phi;
36 | extern double tan_phi;
37 | extern double x_fact;
38 | extern double y_fact;
39 | extern Height sealevel;
40 | extern Height forceheight;
41 | extern int width;
42 | extern int seed;
43 | extern int height;
44 | extern double vangle;
45 | extern double tan_vangle;
46 | extern float vscale;
47 | extern float viewpos;
48 | extern float viewheight;
49 | extern float focal;
50 | extern Height *shadow;
51 | extern Height *a_strip, *b_strip;
52 |
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/mountainbench.c:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include "crinkle.h"
5 |
6 | Parm fold_param;
7 |
8 | #include
9 |
10 | long get_millis()
11 | {
12 |
13 | struct timeval ts;
14 | long t;
15 | int err;
16 |
17 | err = gettimeofday(&ts, NULL);
18 |
19 | t = (ts.tv_sec *1000) + ts.tv_usec/1000 ;
20 |
21 | return t;
22 |
23 | }
24 |
25 | void main(int argc, char *argv[]){
26 | Fold *f;
27 | int i;
28 | double sum;
29 | Strip *s;
30 | long stop,start;
31 |
32 |
33 | seed_uni(121265);
34 | f = make_fold(NULL,&fold_param,10,2,1.0);
35 | for(i=0;i<1000;i++){
36 | s = next_strip(f);
37 | free_strip(s);
38 | }
39 | start = get_millis();
40 | for(i=0;i<1000;i++){
41 | s = next_strip(f);
42 | free_strip(s);
43 | }
44 | stop = get_millis();
45 | printf("time was %ld \n",(stop - start));
46 | }
47 |
--------------------------------------------------------------------------------
/paint.h:
--------------------------------------------------------------------------------
1 | /* $Id: paint.h,v 1.16 2009/08/28 09:09:17 spb Exp $ */
2 | #ifndef PAINT
3 | #define PAINT
4 |
5 | #include "crinkle.h"
6 |
7 | /* colour code definitions */
8 | typedef int Col;
9 | typedef unsigned short Gun;
10 |
11 | typedef struct graph{
12 | int graph_height; /* height of display */
13 | int graph_width ; /* width of display */
14 |
15 | int pixmap_width; /* width of pixmap buffer */
16 |
17 | int width; /* width of terrain strip */
18 |
19 | float ambient; /* level of ambient light */
20 | float contrast; /* contrast,
21 | * increases or decreases effect of cosine rule */
22 | float contour;
23 | float vfract; /* relative strength of vertical light relative
24 | * to the main light source
25 | */
26 | float altitude;
27 | float distance;
28 | double phi; /* angle of the light (vertical plane)*/
29 | double alpha; /* angle of the light (horizontal plane)
30 | * must have -pi/4 < alpha < pi/4
31 | */
32 | Height base_shift; /* offset from calcalt to artist coordinates */
33 | Height sealevel;
34 | double stretch; /* vertical stretch */
35 | int n_col;
36 | int band_size;
37 | int levels;
38 | int stop;
39 | int map;
40 | int reflec;
41 | int repeat;
42 | int pos;
43 | int scroll;
44 | }Graph;
45 |
46 | #define BLACK 0
47 | #define WHITE 1
48 | #define SEA_LIT 2
49 | #define SEA_UNLIT 3
50 | #define SKY 4
51 | #define BAND_BASE 5
52 | #ifndef BAND_SIZE
53 | #define BAND_SIZE 80
54 | #endif
55 | #define N_BANDS 3
56 | #define DEF_COL (BAND_BASE + (N_BANDS * BAND_SIZE))
57 | #define MIN_COL (BAND_BASE + (N_BANDS * 2))
58 | #define COL_RANGE 65535
59 |
60 | #define PI 3.14159265
61 |
62 | #ifdef ANSI
63 | void set_clut(int, Gun *, Gun *, Gun *);
64 | Height *extract(Strip *s);
65 | void init_artist_variables();
66 | Col get_col(Height p, Height p_plus_x, Height p_plus_y, Height shadow);
67 | Col *makemap(Height *a, Height *b, Height *shadow);
68 | Col *camera(Height *a, Height *b, Height *shadow);
69 | Col *mirror(Height *a, Height *b, Height *shadow);
70 | int project( int x , Height y );
71 | #else
72 | void set_clut();
73 | Height *extract();
74 | void init_artist_variables();
75 | Col get_col();
76 | Col *makemap();
77 | Col *camera();
78 | Col *mirror();
79 | int project();
80 | #endif
81 |
82 |
83 | #endif
84 |
--------------------------------------------------------------------------------
/patchlevel.h:
--------------------------------------------------------------------------------
1 | #define PATCHLEVEL 10
2 |
--------------------------------------------------------------------------------
/print_alg.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define P(A) fprintf(stderr,"%s\n",A)
4 | void print_algorithm()
5 | {
6 | P("This program uses a modified form of the mid-point displacement algorithm");
7 | P("");
8 | P("The mid-point displacement algorithm is a recursive algorithm, each iteration");
9 | P("doubles the resolution of the grid. This is done in 2 stages.");
10 | P("");
11 | P("A B A B A F B");
12 | P(" stage1 stage2");
13 | P(" ---------> E --------> G E H");
14 | P("");
15 | P("C D C D C I D");
16 | P("");
17 | P("The new points are generated by taking an average of the surrounding points");
18 | P("and adding a random offset.");
19 | P("The modifications to the standard algorithm are as follows:");
20 | P("There are three optional regeneration steps to reduce \"creasing\". A");
21 | P("regeneration step recalculates the height of existing points using an");
22 | P("average and offset from a newer generation of points. The three");
23 | P("regeneration steps are:");
24 | P(" rg1: recalculate corner points (A,B,C,D) from the midpoints (E)");
25 | P(" after the stage1 update.");
26 | P(" rg2: recalculate midpoints (E) from the edge points (F,G,H,I)");
27 | P(" after the stage2 update");
28 | P(" rg3: recalculate corner points (A,B,C,D) from the edge points (F,G,H,I)");
29 | P(" after the stage2 update");
30 | P("The regeneration stages are turned on by the smoothing parameter (-s flag)");
31 | P("");
32 | P(" flag rg3 rg2 rg1");
33 | P(" 0 off off off");
34 | P(" 1 on off off");
35 | P(" 2 off on off");
36 | P(" 3 on on off");
37 | P(" 4 off off on");
38 | P(" 5 on off on");
39 | P(" 6 off on on");
40 | P(" 7 on on on");
41 | P("");
42 | P("When performing the regeneration steps the random offset is added to a");
43 | P("weighted average of the previous value of the point and a the average of");
44 | P("the new points. The weighting factors are controlled by the -X and -Y flags.");
45 | P("");
46 | P("The -x flag (cross update) controls whether the midpoints (E) are included");
47 | P("in the average when performing the stage2 update or if only the corner");
48 | P("points are used.");
49 | P("");
50 | }
51 |
--------------------------------------------------------------------------------
/random.c:
--------------------------------------------------------------------------------
1 | /*
2 | * C version of Marsaglia's UNI random number generator
3 | * More or less transliterated from the Fortran -- with 1 bug fix
4 | * Hence horrible style
5 | *
6 | * Features:
7 | * ANSI C
8 | * not callable from Fortran (yet)
9 | */
10 |
11 |
12 |
13 | char uni_id[] = "$Id: random.c,v 1.7 2009/08/28 09:09:17 spb Exp $" ;
14 | /*
15 | * Global variables for rstart & uni
16 | */
17 |
18 | #define PARANOID
19 | /* need types and time */
20 | #include
21 | /* #include
22 | * #include
23 | */
24 | #include
25 | #include
26 | #include
27 | typedef struct
28 | {
29 | float u[98];
30 | float c;
31 | float cd;
32 | float cm;
33 | int ui;
34 | int uj;
35 | }
36 | Uni_save;
37 |
38 | Uni_save uni_data;
39 |
40 | float uni()
41 | {
42 | float luni; /* local variable for uni */
43 |
44 | luni = uni_data.u[uni_data.ui] - uni_data.u[uni_data.uj];
45 | if (luni < 0.0)
46 | luni += 1.0;
47 | uni_data.u[uni_data.ui] = luni;
48 | if (--uni_data.ui == 0)
49 | uni_data.ui = 97;
50 | if (--uni_data.uj == 0)
51 | uni_data.uj = 97;
52 | if ((uni_data.c -= uni_data.cd) < 0.0)
53 | uni_data.c += uni_data.cm;
54 | if ((luni -= uni_data.c) < 0.0)
55 | luni += 1.0;
56 | return ((float) luni);
57 | }
58 |
59 | void rstart(i,j,k,l)
60 | int i;
61 | int j;
62 | int k;
63 | int l;
64 | {
65 | int ii, jj, m;
66 | float s, t;
67 |
68 | for (ii = 1; ii <= 97; ii++) {
69 | s = 0.0;
70 | t = 0.5;
71 | for (jj = 1; jj <= 24; jj++) {
72 | m = ((i*j % 179) * k) % 179;
73 | i = j;
74 | j = k;
75 | k = m;
76 | l = (53*l+1) % 169;
77 | if (l*m % 64 >= 32)
78 | s += t;
79 | t *= 0.5;
80 | }
81 | uni_data.u[ii] = s;
82 | }
83 | uni_data.c = 362436.0 / 16777216.0;
84 | uni_data.cd = 7654321.0 / 16777216.0;
85 | uni_data.cm = 16777213.0 / 16777216.0;
86 | uni_data.ui = 97; /* There is a bug in the original Fortran version */
87 | uni_data.uj = 33; /* of UNI -- i and j should be SAVEd in UNI() */
88 | }
89 |
90 |
91 | /* ~seed_uni: this takes a single integer in the range
92 | * 0 <= ijkl <= 900 000 000
93 | * and produces the four smaller integers needed for rstart. It is
94 | * based on the ideas contained in the RMARIN subroutine in
95 | * F. James, "A Review of Pseudorandom Number Generators",
96 | * Comp. Phys. Commun. Oct 1990, p.340
97 | * To reduce the modifications to the existing code, seed_uni now
98 | * takes the role of a preprocessor for rstart.
99 | *
100 | */
101 |
102 | void seed_uni(ijkl)
103 | int ijkl;
104 | {
105 | int i, j, k, l, ij, kl;
106 |
107 | if( ijkl == 0 )
108 | {
109 | ijkl = time((time_t *) 0);
110 | ijkl %= 900000000;
111 | }
112 | /* check ijkl is within range */
113 | if( (ijkl < 0) || (ijkl > 900000000) )
114 | {
115 | fprintf(stderr,"seed_uni: ijkl = %d -- out of range\n\n", ijkl);
116 | exit(3);
117 | }
118 |
119 |
120 | /* decompose the long integer into the the equivalent four
121 | * integers for rstart. This should be a 1-1 mapping
122 | * ijkl <--> (i, j, k, l)
123 | * though not quite all of the possible sets of (i, j, k, l)
124 | * can be produced.
125 | */
126 |
127 | ij = ijkl/30082;
128 | kl = ijkl - (30082 * ij);
129 |
130 | i = ((ij/177) % 177) + 2;
131 | j = (ij % 177) + 2;
132 | k = ((kl/169) % 178) + 1;
133 | l = kl % 169;
134 |
135 | #ifdef PARANOID
136 | if( (i <= 0) || (i > 178) )
137 | {
138 | fprintf(stderr,"seed_uni: i = %d -- out of range\n\n", i);
139 | exit(3);
140 | }
141 |
142 | if( (j <= 0) || (j > 178) )
143 | {
144 | fprintf(stderr,"seed_uni: j = %d -- out of range\n\n", j);
145 | exit(3);
146 | }
147 |
148 | if( (k <= 0) || (k > 178) )
149 | {
150 | fprintf(stderr,"seed_uni: k = %d -- out of range\n\n", k);
151 | exit(3);
152 | }
153 |
154 | if( (l < 0) || (l > 168) )
155 | {
156 | fprintf(stderr,"seed_uni: l = %d -- out of range\n\n", l);
157 | exit(3);
158 | }
159 |
160 | if (i == 1 && j == 1 && k == 1)
161 | {
162 | fprintf(stderr,"seed_uni: 1 1 1 not allowed for 1st 3 seeds\n\n");
163 | exit(4);
164 | }
165 | #endif
166 |
167 |
168 | rstart(i, j, k, l);
169 |
170 | }
171 |
172 | float gaussian()
173 | {
174 | double pi = 3.1415926536, two = 2.0, zero = 0.0;
175 | double ran1, ran2;
176 |
177 | do {
178 | ran1 = (double) uni();
179 | } while (ran1 == zero);
180 |
181 | ran2 = (double) uni();
182 | return (float) ( sqrt(-two * log(ran1)) * cos(two * pi * ran2) );
183 | }
184 |
185 |
--------------------------------------------------------------------------------
/vroot.h:
--------------------------------------------------------------------------------
1 | /* -*- Mode: C; tab-width: 2 -*- */
2 | /*****************************************************************************/
3 | /** Copyright 1991 by Andreas Stolcke **/
4 | /** Copyright 1990 by Solbourne Computer Inc. **/
5 | /** Longmont, Colorado **/
6 | /** **/
7 | /** All Rights Reserved **/
8 | /** **/
9 | /** Permission to use, copy, modify, and distribute this software and **/
10 | /** its documentation for any purpose and without fee is hereby **/
11 | /** granted, provided that the above copyright notice appear in all **/
12 | /** copies and that both that copyright notice and this permis- **/
13 | /** sion notice appear in supporting documentation, and that the **/
14 | /** name of Solbourne not be used in advertising **/
15 | /** in publicity pertaining to distribution of the software without **/
16 | /** specific, written prior permission. **/
17 | /** **/
18 | /** ANDREAS STOLCKE AND SOLBOURNE COMPUTER INC. DISCLAIMS ALL WARRANTIES **/
19 | /** WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF **/
20 | /** MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ANDREAS STOLCKE **/
21 | /** OR SOLBOURNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL **/
22 | /** DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
23 | /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
24 | /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
25 | /** OR PERFORMANCE OF THIS SOFTWARE. **/
26 | /*****************************************************************************/
27 | /*
28 | * vroot.h -- Virtual Root Window handling header file
29 | *
30 | * This header file redefines the X11 macros RootWindow and DefaultRootWindow,
31 | * making them look for a virtual root window as provided by certain `virtual'
32 | * window managers like swm and tvtwm. If none is found, the ordinary root
33 | * window is returned, thus retaining backward compatibility with standard
34 | * window managers.
35 | * The function implementing the virtual root lookup remembers the result of
36 | * its last invocation to avoid overhead in the case of repeated calls
37 | * on the same display and screen arguments.
38 | * The lookup code itself is taken from Tom LaStrange's ssetroot program.
39 | *
40 | * Most simple root window changing X programs can be converted to using
41 | * virtual roots by just including
42 | *
43 | * #include
44 | *
45 | * after all the X11 header files. It has been tested on such popular
46 | * X clients as xphoon, xfroot, xloadimage, and xaqua.
47 | * It also works with the core clients xprop, xwininfo, xwd, and editres
48 | * (and is necessary to get those clients working under tvtwm).
49 | * It does NOT work with xsetroot; get the xsetroot replacement included in
50 | * the tvtwm distribution instead.
51 | *
52 | * Andreas Stolcke , 9/7/90
53 | * - replaced all NULL's with properly cast 0's, 5/6/91
54 | * - free children list (suggested by Mark Martin ), 5/16/91
55 | * - include X11/Xlib.h and support RootWindowOfScreen, too 9/17/91
56 | *
57 | * Jamie Zawinski , 28-Apr-1997
58 | * - use ANSI C
59 | *
60 | * Jamie Zawinski , 3-Sep-2003
61 | * - if the environment variable "XSCREENSAVER_WINDOW" is set, use that
62 | * as the root window instead of searching for __SWM_VROOT.
63 | */
64 |
65 | #ifndef _VROOT_H_
66 | #define _VROOT_H_
67 | #define _XSCREENSAVER_VROOT_H_
68 |
69 | #if !defined(lint) && !defined(SABER)
70 | static const char vroot_rcsid[] =
71 | "#Id: vroot.h,v 1.5 2003/09/04 01:04:38 jwz Exp #" "\n"
72 | "#Id: vroot.h,v 1.4 1991/09/30 19:23:16 stolcke Exp stolcke #";
73 | #endif
74 |
75 | #include
76 | #include
77 | #include
78 |
79 | #include
80 |
81 | static Window
82 | #ifdef __STDC__ /* ANSIfication added by jwz, to avoid superfluous warnings. */
83 | VirtualRootWindowOfScreen(Screen *screen)
84 | #else /* !__STDC__ */
85 | VirtualRootWindowOfScreen(screen) Screen *screen;
86 | #endif /* !__STDC__ */
87 | {
88 | static Screen *save_screen = (Screen *)0;
89 | static Window root = (Window)0;
90 |
91 | if (screen != save_screen) {
92 | Display *dpy = DisplayOfScreen(screen);
93 | Atom __SWM_VROOT = None;
94 | int i;
95 | Window rootReturn, parentReturn, *children;
96 | unsigned int numChildren;
97 |
98 | /* first check for a hex or decimal window ID in the environment */
99 | const char *xss_id = getenv("XSCREENSAVER_WINDOW");
100 | if (xss_id && *xss_id) {
101 | unsigned long id = 0;
102 | char c;
103 | if (1 == sscanf (xss_id, " 0x%lx %c", &id, &c) ||
104 | 1 == sscanf (xss_id, " %lu %c", &id, &c)) {
105 | root = (Window) id;
106 | save_screen = screen;
107 | return root;
108 | }
109 | }
110 |
111 | root = RootWindowOfScreen(screen);
112 |
113 | /* go look for a virtual root */
114 | __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
115 | if (XQueryTree(dpy, root, &rootReturn, &parentReturn,
116 | &children, &numChildren)) {
117 | for (i = 0; i < numChildren; i++) {
118 | Atom actual_type;
119 | int actual_format;
120 | unsigned long nitems, bytesafter;
121 | Window *newRoot = (Window *)0;
122 |
123 | if (XGetWindowProperty(dpy, children[i],
124 | __SWM_VROOT, 0, 1, False, XA_WINDOW,
125 | &actual_type, &actual_format,
126 | &nitems, &bytesafter,
127 | (unsigned char **) &newRoot) == Success
128 | && newRoot) {
129 | root = *newRoot;
130 | break;
131 | }
132 | }
133 | if (children)
134 | XFree((char *)children);
135 | }
136 |
137 | save_screen = screen;
138 | }
139 |
140 | return root;
141 | }
142 |
143 | #undef RootWindowOfScreen
144 | #define RootWindowOfScreen(s) VirtualRootWindowOfScreen(s)
145 |
146 | #undef RootWindow
147 | #define RootWindow(dpy,screen) VirtualRootWindowOfScreen(ScreenOfDisplay(dpy,screen))
148 |
149 | #undef DefaultRootWindow
150 | #define DefaultRootWindow(dpy) VirtualRootWindowOfScreen(DefaultScreenOfDisplay(dpy))
151 |
152 | #endif /* _VROOT_H_ */
153 |
--------------------------------------------------------------------------------
/xmountains.c:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include "crinkle.h"
9 | #include "paint.h"
10 | #include "patchlevel.h"
11 | #include "copyright.h"
12 |
13 | #define VERSION 2
14 | #define SIDE 1.0
15 |
16 | char scroll_Id[]="$Id: xmountains.c,v 1.43 2010/12/17 09:25:36 spb Exp $";
17 | extern Graph g;
18 | Parm fold_param;
19 | extern char *display;
20 | extern char *geom;
21 |
22 | extern int swosh;
23 |
24 | /* {{{ my version on getopt*/
25 | int optind=1;
26 | char *optarg;
27 | int opterr=1;
28 |
29 | int my_getopt (int argc, char **argv, char *pat)
30 | {
31 | char *flag;
32 |
33 | if((optind >= argc) || (argv[optind][0] != '-'))
34 | {
35 | return -1;
36 | }
37 | if( argv[optind][1] == '-' )
38 | {
39 | optind++;
40 | return -1;
41 | }
42 | if( argv[optind][1] == ':' )
43 | {
44 | if( opterr )
45 | {
46 | fprintf(stderr,"getopt: found \":\" in optstring\n");
47 | }
48 | return '?';
49 | }
50 | for(flag=pat;*flag;flag++)
51 | {
52 | if( *flag == argv[optind][1] )
53 | {
54 | optind++;
55 | if( *(flag+1) == ':' )
56 | {
57 | if(optind >= argc )
58 | {
59 | if( opterr )
60 | {
61 | fprintf(stderr,"getopt: no option for flag %c\n",*flag);
62 | }
63 | return '?';
64 | }
65 | optarg = argv[optind];
66 | optind++;
67 | }
68 | return *flag;
69 | }
70 |
71 | }
72 | if( opterr )
73 | {
74 | fprintf(stderr,"getopt: flag %s not recognized\n",argv[optind]);
75 | }
76 | optind++;
77 | return '?';
78 | }
79 | /* }}} */
80 |
81 | double atof();
82 | #ifdef ANSI
83 | void init_graphics (int, Window, int,int, Graph *, Gun *, Gun *, Gun *);
84 | void clear_col( int );
85 | void finish_graphics();
86 | void plot_pixel (int, int, unsigned char);
87 | void scroll_screen ( int );
88 | void zap_events();
89 | #else
90 | void init_graphics ();
91 | void clear_col();
92 | void finish_graphics();
93 | void plot_pixel ();
94 | void scroll_screen ();
95 | void zap_events();
96 | #endif
97 |
98 | void finish_prog();
99 |
100 | int s_height=768, s_width=1024;
101 | int mapwid;
102 |
103 | /* Go through argv and find and extract any "-window-id NNNN" or
104 | "-window-id 0xXXXX" option. (Maybe this can be done with
105 | getopt, but I can't be bothered to figure it out.)
106 | */
107 | static unsigned long window_id_kludge (int *argcP, char **argv)
108 | {
109 | unsigned long id = 0;
110 | int i;
111 | int j;
112 | for (i = 1; i < *argcP; i++)
113 | {
114 | if (!strcmp (argv[i], "-window-id") && i+1 < *argcP)
115 | {
116 | char c;
117 | char *str = argv[i+1];
118 |
119 | if (1 != ((str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
120 | ? sscanf (str+2, "%lx %c", &id, &c)
121 | : sscanf (str, "%lu %c", &id, &c)))
122 | continue;
123 |
124 | /* remove "-window-id xxx" from the arglist */
125 | for (j = i+2; j < *argcP; j++)
126 | argv[j-2] = argv[j];
127 | *argcP -= 2;
128 | }
129 | }
130 | return id;
131 | }
132 |
133 |
134 | void init_parameters();
135 | void print_algorithm();
136 | void seed_uni(int ijkl);
137 | void plot_column(Graph *g);
138 |
139 | /* Note, Robbie Hatley, 2024-07-16: When installing xmountains as an AUR package,
140 | "main" no-longer compiles without being declared "int", presumably due to
141 | recent changes in gcc. */
142 | int main (int argc, char **argv)
143 | {
144 | int i;
145 | int e_events=FALSE;
146 | int request_clear=FALSE;
147 | int smooth=1;
148 | int snooze=10;
149 | int root= 0;
150 | unsigned long window_id = 0;
151 | int seed=0;
152 |
153 | int c, errflg=0;
154 | extern char *optarg;
155 | extern int optind;
156 | char *mesg[2];
157 | Gun *clut[3];
158 | FILE *pidfile;
159 | swosh = 0; /* default is ! -w */
160 |
161 | init_parameters();
162 | /* {{{ handle command line flags*/
163 |
164 | window_id = window_id_kludge (&argc, argv);
165 |
166 | mesg[0]="false";
167 | mesg[1]="true";
168 | 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)
169 | {
170 | switch(c){
171 | case 'w':
172 | swosh = TRUE; /* update window only when pixmap is complete */
173 | break;
174 | case 'b':
175 | root = 1- root;
176 | break; /* run on root window */
177 | case 'x':
178 | fold_param.cross = 1- fold_param.cross;
179 | break; /* use cross updates */
180 | case 'E':
181 | e_events = 1 - e_events;
182 | break;
183 | case 'q':
184 | request_clear = 1 - request_clear;
185 | break;
186 | case 'm': /* Map view only */
187 | g.map = 1 - g.map;
188 | break;
189 | case 'M': /* put in reflections */
190 | g.reflec = 1 - g.reflec;
191 | break;
192 | case 'l': /* Set # levels of recursion */
193 | g.levels = atoi( optarg );
194 | if( g.levels < 2 )
195 | {
196 | g.levels = 2;
197 | }
198 | break;
199 | case 'F': /* Set # levels to force front to mean */
200 | fold_param.force_front = atoi( optarg );
201 | break;
202 | case 's': /* Set smoothing parameter */
203 | smooth = atoi( optarg );
204 | fold_param.rg1 = smooth & 1;
205 | fold_param.rg2 = smooth & 2;
206 | fold_param.rg3 = smooth & 4;
207 | break;
208 | case 't': /* Set width of lowest level */
209 | g.stop = atoi( optarg );
210 | if( g.stop < 0 )
211 | {
212 | g.stop = 0;
213 | }
214 | break;
215 | case 'r':
216 | g.repeat = atoi( optarg );
217 | if( g.repeat < 0 )
218 | {
219 | g.repeat = -g.repeat;
220 | i= -1;
221 | }else{
222 | i=1;
223 | }
224 | /* we want repeat to be a multiple of 2 as we are using
225 | * a textured field for the sky.
226 | */
227 | g.repeat = i*(2 * ((g.repeat +1)/2));
228 | break;
229 | case 'B': /* set band_size */
230 | g.band_size = atoi( optarg );
231 | if( g.band_size < 2 )
232 | {
233 | g.band_size=2;
234 | }
235 | g.n_col = (BAND_BASE + (N_BANDS * g.band_size));
236 | break;
237 | case 'n': /* set max number of colours */
238 | g.n_col = atoi( optarg );
239 | if( g.n_col < MIN_COL )
240 | {
241 | g.n_col = MIN_COL;
242 | }
243 | g.band_size = (g.n_col - BAND_BASE)/N_BANDS;
244 | g.n_col = (BAND_BASE + (N_BANDS * g.band_size));
245 | break;
246 | case 'R': /* set seed, read clock if 0 */
247 | seed = atoi( optarg );
248 | break;
249 | case 'Z': /* put sleep into wait events */
250 | snooze = atoi( optarg );
251 | if( snooze < 0 )
252 | {
253 | snooze = 0;
254 | }
255 | break;
256 | case 'P':
257 | pidfile = fopen(optarg,"w");
258 | if( pidfile )
259 | {
260 | fprintf(pidfile,"%d\n",getpid());
261 | fclose(pidfile);
262 | }else{
263 | perror(optarg);
264 | }
265 | break;
266 | case 'f': /* set fractal dimension */
267 | fold_param.fdim = atof( optarg );
268 | if( fold_param.fdim < 0.5 )
269 | {
270 | fold_param.fdim=0.5;
271 | }
272 | if( fold_param.fdim > 1.0 )
273 | {
274 | fold_param.fdim=1.0;
275 | }
276 | break;
277 | case 'I': /* set Illumination angle */
278 | g.phi = ((PI * atof( optarg ))/180.0);
279 | if ( g.phi < 0.0 )
280 | {
281 | g.phi=0.0;
282 | }
283 | if( g.phi > PI/2.0 )
284 | {
285 | g.phi = PI/2.0;
286 | }
287 | break;
288 | case 'A': /* set Illumination angle (horizontal)*/
289 | g.alpha = ((PI * atof( optarg ))/180.0);
290 | if( g.alpha < -PI/3.0 )
291 | {
292 | g.alpha = -PI/3.0;
293 | }
294 | if( g.alpha > PI/3.0 )
295 | {
296 | g.alpha = PI/3.0;
297 | }
298 | break;
299 | case 'X': /* set mix */
300 | fold_param.mix = atof( optarg );
301 | break;
302 | case 'Y': /* set midmix */
303 | fold_param.midmix = atof( optarg );
304 | break;
305 | case 'S': /* set stretch */
306 | g.stretch = atof( optarg );
307 | break;
308 | case 'W': /* set sealevel */
309 | g.sealevel = atof( optarg );
310 | break;
311 | case 'G': /* set forceheight */
312 | fold_param.forceval = atof( optarg );
313 | break;
314 | case 'T': /* set shift */
315 | g.base_shift = atof( optarg );
316 | break;
317 | case 'C':
318 | g.contour = atof( optarg );
319 | break;
320 | case 'a': /* set altitude */
321 | g.altitude = atof( optarg );
322 | break;
323 | case 'p': /* set distance */
324 | g.distance = atof( optarg );
325 | break;
326 | case 'c':
327 | g.contrast = atof( optarg );
328 | if( g.contrast < 0.0 )
329 | {
330 | g.contrast=0.0;
331 | }
332 | break;
333 | case 'e':
334 | g.ambient = atof( optarg );
335 | if( g.ambient < 0.0 )
336 | {
337 | g.ambient = 0.0;
338 | }
339 | if( g.ambient > 1.0 )
340 | {
341 | g.ambient=1.0;
342 | }
343 | break;
344 | case 'v':
345 | g.vfract = atof( optarg );
346 | if( g.vfract < 0.0 )
347 | {
348 | g.vfract = 0.0;
349 | }
350 | break;
351 | case 'g':
352 | geom = optarg;
353 | break;
354 | case 'd':
355 | display = optarg;
356 | break;
357 | case 'H':
358 | print_algorithm();
359 | errflg++;
360 | break;
361 | case 'h':
362 | case '?':
363 | errflg++;
364 | }
365 | }
366 | if( errflg )
367 | {
368 | fprintf(stderr,"%s: version %d.%d\n",argv[0],VERSION,PATCHLEVEL);
369 | fprintf(stderr,"usage: %s -[hwbqgdPEmMrBZIASFTCapcevfRltxsXYH]\n",argv[0]);
370 | fprintf(stderr," -h Print this message\n");
371 | fprintf(stderr," -w [%s] update window with complete images only\n",mesg[swosh]);
372 | fprintf(stderr," -b [%s] use root window \n",mesg[root]);
373 | fprintf(stderr," -q [%s] reset root window on exit\n",mesg[request_clear]);
374 | fprintf(stderr," -g string window geometry\n");
375 | fprintf(stderr," -d string display\n");
376 | fprintf(stderr," -P filename write PID to file\n");
377 | fprintf(stderr," -E [%s] toggle explicit expose events \n",mesg[e_events]);
378 | fprintf(stderr," -m [%s] print map \n",mesg[g.map]);
379 | fprintf(stderr," -M [%s] implement reflections \n",mesg[g.reflec]);
380 | fprintf(stderr," -r int [%d] # columns before scrolling \n",g.repeat);
381 | fprintf(stderr," -B int [%d] # shades in a colour band\n",g.band_size);
382 | fprintf(stderr," -n int [%d] # number of colours\n",g.n_col);
383 | fprintf(stderr," -Z int [%d] time to sleep before scrolling\n",snooze);
384 | fprintf(stderr," -I float [%f] vertical angle of light \n",(g.phi*180.0)/PI);
385 | fprintf(stderr," -A float [%f] horizontal angle of light \n",(g.alpha*180.0)/PI);
386 | fprintf(stderr," -S float [%f] vertical stretch \n",g.stretch);
387 | fprintf(stderr," -T float [%f] vertical shift \n",g.base_shift);
388 | fprintf(stderr," -W float [%f] sealevel \n",g.sealevel);
389 | fprintf(stderr," -F int [%d] reduce variation in the foreground \n",fold_param.force_front);
390 | fprintf(stderr," -G float [%f] average foreground height \n",fold_param.forceval);
391 | fprintf(stderr," -C float [%f] contour parameter \n",g.contour);
392 | fprintf(stderr," -a float [%f] altitude of viewpoint \n",g.altitude);
393 | fprintf(stderr," -p float [%f] distance of viewpoint \n",g.distance);
394 | fprintf(stderr," -c float [%f] contrast\n",g.contrast);
395 | fprintf(stderr," -e float [%f] ambient light level\n",g.ambient);
396 | fprintf(stderr," -v float [%f] vertical light level\n",g.vfract);
397 | fprintf(stderr,"Fractal options:\n");
398 | fprintf(stderr," -f float [%f] fractal dimension \n",fold_param.fdim);
399 | fprintf(stderr," -R int [%d] rng seed, read clock if 0 \n",seed);
400 | fprintf(stderr," -l int [%d] # levels of recursion \n",g.levels);
401 | fprintf(stderr," -t int [%d] # non fractal iterations \n",g.stop);
402 | fprintf(stderr," -x [%s] cross update \n",mesg[fold_param.cross]);
403 | fprintf(stderr," -s [%x] smoothing (0-7)\n",smooth);
404 | fprintf(stderr," -X float [%f] fraction of old value for rg2 & rg3\n",fold_param.mix);
405 | fprintf(stderr," -Y float [%f] fraction of old value for rg1\n",fold_param.midmix);
406 | fprintf(stderr," -window-id 0xNNNNN draw on existing external window.\n");
407 | fprintf(stderr," -H print short description of algorithm.\n");
408 | exit(1);
409 | }
410 |
411 | /* }}} */
412 | for(i=0 ;i<3 ;i++)
413 | {
414 | clut[i] = (Gun *) malloc(g.n_col * sizeof(Gun));
415 | if( ! clut[i] )
416 | {
417 | fprintf(stderr,"malloc failed for clut\n");
418 | exit(1);
419 | }
420 | }
421 | set_clut(g.n_col,clut[0], clut[1], clut[2]);
422 | init_graphics(root,window_id, !e_events, request_clear, &g, clut[0], clut[1], clut[2]);
423 |
424 | for(i=0;i<3;i++)
425 | {
426 | free(clut[i]);
427 | }
428 |
429 |
430 | seed_uni(seed);
431 |
432 | init_artist_variables();
433 | if( SIG_ERR == signal(SIGINT, finish_prog ))
434 | {
435 | perror(argv[0]);
436 | exit(1);
437 | }
438 | if( SIG_ERR == signal(SIGTERM, finish_prog ))
439 | {
440 | perror(argv[0]);
441 | exit(1);
442 | }
443 | if( SIG_ERR == signal(SIGHUP, finish_prog ))
444 | {
445 | perror(argv[0]);
446 | exit(1);
447 | }
448 | if( SIG_ERR == signal(SIGQUIT, finish_prog ))
449 | {
450 | perror(argv[0]);
451 | exit(1);
452 | }
453 |
454 |
455 | /* This is a stand in for the event loop in a Widget set implementation
456 | * where we would call plot_column at regular intervals using
457 | * XTtimeout. However xmountains is an Xlib program
458 | * so I do the following.
459 | */
460 | while( TRUE )
461 | {
462 | plot_column(&g);
463 | zap_events();
464 | #ifndef NO_SLEEP
465 | if( g.scroll ){
466 | /* sleep if we are due a scroll next time */
467 | /* sleeping is very bad because it will prevent
468 | * events being processed but I suppose it is better
469 | * than being a CPU hog, as a compremise always check for
470 | * events at least once a second, looping for longer sleep times.
471 | * process the events before a sleep to make sure the screen is up to date.
472 | * the events must always be processed at least once.
473 | */
474 | for(i=0;i