http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / glx / stonerview-osc.c
1 /* StonerView: An eccentric visual toy.
2    Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com)
3
4    Permission to use, copy, modify, distribute, and sell this software and its
5    documentation for any purpose is hereby granted without fee, provided that
6    the above copyright notice appear in all copies and that both that
7    copyright notice and this permission notice appear in supporting
8    documentation.  No representations are made about the suitability of this
9    software for any purpose.  It is provided "as is" without express or 
10    implied warranty.
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #include "yarandom.h"
21 #include "stonerview.h"
22
23
24 /* Return a random number between min and max, inclusive. */
25 static int rand_range(int min, int max)
26 {
27   int res;
28   unsigned int diff = (max+1) - min;
29   if (diff <= 1)
30     return min;
31   res = random() % diff;
32   return min+res;
33 }
34
35
36 /* Create a new, blank osc_t. The caller must fill in the type data. */
37 static osc_t *create_osc(stonerview_state *st, int type)
38 {
39   osc_t *osc = (osc_t *)malloc(sizeof(osc_t));
40   if (!osc) 
41     return NULL;
42         
43   osc->type = type;
44   osc->next = NULL;
45     
46   *st->osctail = osc;
47   st->osctail = &(osc->next);
48     
49   return osc;
50 }
51
52 /* Creation functions for all the osc_t types. These are all pretty obvious
53    in their construction. */
54
55 osc_t *new_osc_constant(stonerview_state *st, int val)
56 {
57   osc_t *osc = create_osc(st, otyp_Constant);
58   if (!osc)
59     return NULL;
60         
61   osc->u.oconstant.val = val;
62   return osc;
63 }
64
65 osc_t *new_osc_bounce(stonerview_state *st, int min, int max, int step)
66 {
67   int diff;
68   osc_t *osc = create_osc(st, otyp_Bounce);
69   if (!osc)
70     return NULL;
71         
72   osc->u.obounce.min = min;
73   osc->u.obounce.max = max;
74   osc->u.obounce.step = step;
75     
76   /* Pick a random initial value between min and max. */
77   if (step < 0)
78     step = (-step);
79   diff = (max-min) / step;
80   osc->u.obounce.val = min + step * rand_range(0, diff-1);
81     
82   return osc;
83 }
84
85 osc_t *new_osc_wrap(stonerview_state *st, int min, int max, int step)
86 {
87   int diff;
88   osc_t *osc = create_osc(st, otyp_Wrap);
89   if (!osc)
90     return NULL;
91         
92   osc->u.owrap.min = min;
93   osc->u.owrap.max = max;
94   osc->u.owrap.step = step;
95     
96   /* Pick a random initial value between min and max. */
97   if (step < 0)
98     step = (-step);
99   diff = (max-min) / step;
100   osc->u.owrap.val = min + step * rand_range(0, diff-1);
101     
102   return osc;
103 }
104
105 osc_t *new_osc_velowrap(stonerview_state *st, int min, int max, osc_t *step)
106 {
107   osc_t *osc = create_osc(st, otyp_VeloWrap);
108   if (!osc)
109     return NULL;
110         
111   osc->u.ovelowrap.min = min;
112   osc->u.ovelowrap.max = max;
113   osc->u.ovelowrap.step = step;
114     
115   /* Pick a random initial value between min and max. */
116   osc->u.ovelowrap.val = rand_range(min, max);
117     
118   return osc;
119 }
120
121 osc_t *new_osc_multiplex(stonerview_state *st, 
122                          osc_t *sel, osc_t *ox0, 
123                          osc_t *ox1, osc_t *ox2, 
124                          osc_t *ox3)
125 {
126   osc_t *osc = create_osc(st, otyp_Multiplex);
127   if (!osc)
128     return NULL;
129     
130   osc->u.omultiplex.sel = sel;
131   osc->u.omultiplex.val[0] = ox0;
132   osc->u.omultiplex.val[1] = ox1;
133   osc->u.omultiplex.val[2] = ox2;
134   osc->u.omultiplex.val[3] = ox3;
135     
136   return osc;
137 }
138
139 osc_t *new_osc_phaser(stonerview_state *st, int phaselen)
140 {
141   osc_t *osc = create_osc(st, otyp_Phaser);
142   if (!osc)
143     return NULL;
144         
145   osc->u.ophaser.phaselen = phaselen;
146
147   osc->u.ophaser.count = 0;
148   /* Pick a random phase to start in. */
149   osc->u.ophaser.curphase = rand_range(0, NUM_PHASES-1);
150
151   return osc;
152 }
153
154 osc_t *new_osc_randphaser(stonerview_state *st, 
155                           int minphaselen, int maxphaselen)
156 {
157   osc_t *osc = create_osc(st, otyp_RandPhaser);
158   if (!osc)
159     return NULL;
160         
161   osc->u.orandphaser.minphaselen = minphaselen;
162   osc->u.orandphaser.maxphaselen = maxphaselen;
163
164   osc->u.orandphaser.count = 0;
165   /* Pick a random phaselen to start with. */
166   osc->u.orandphaser.curphaselen = rand_range(minphaselen, maxphaselen);
167   /* Pick a random phase to start in. */
168   osc->u.orandphaser.curphase = rand_range(0, NUM_PHASES-1);
169
170   return osc;
171 }
172
173 osc_t *new_osc_linear(stonerview_state *st, osc_t *base, osc_t *diff)
174 {
175   osc_t *osc = create_osc(st, otyp_Linear);
176   if (!osc)
177     return NULL;
178
179   osc->u.olinear.base = base;
180   osc->u.olinear.diff = diff;
181     
182   return osc;
183 }
184
185 osc_t *new_osc_buffer(stonerview_state *st, osc_t *val)
186 {
187   int ix;
188   osc_t *osc = create_osc(st, otyp_Buffer);
189   if (!osc)
190     return NULL;
191     
192   osc->u.obuffer.val = val;
193   osc->u.obuffer.firstel = st->num_els-1;
194     
195   /* The last N values are stored in a ring buffer, which we must initialize
196      here. */
197   for (ix=0; ix<st->num_els; ix++) {
198     osc->u.obuffer.el[ix] = osc_get(st, val, 0);
199   }
200
201   return osc;
202 }
203
204 /* Compute f(i,el) for the current i. */
205 int osc_get(stonerview_state *st, osc_t *osc, int el)
206 {
207   if (!osc)
208     return 0;
209         
210   switch (osc->type) {
211     
212   case otyp_Constant:
213     return osc->u.oconstant.val;
214             
215   case otyp_Bounce:
216     return osc->u.obounce.val;
217             
218   case otyp_Wrap:
219     return osc->u.owrap.val;
220         
221   case otyp_VeloWrap:
222     return osc->u.ovelowrap.val;
223         
224   case otyp_Linear:
225     return osc_get(st, osc->u.olinear.base, el)
226       + el * osc_get(st, osc->u.olinear.diff, el);
227         
228   case otyp_Multiplex: {
229     struct omultiplex_struct *ox = &(osc->u.omultiplex);
230     int sel = osc_get(st, ox->sel, el);
231     return osc_get(st, ox->val[sel % NUM_PHASES], el);
232   }
233         
234   case otyp_Phaser: {
235     struct ophaser_struct *ox = &(osc->u.ophaser);
236     return ox->curphase;
237   }
238         
239   case otyp_RandPhaser: {
240     struct orandphaser_struct *ox = &(osc->u.orandphaser);
241     return ox->curphase;
242   }
243         
244   case otyp_Buffer: {
245     struct obuffer_struct *ox = &(osc->u.obuffer);
246     return ox->el[(ox->firstel + el) % st->num_els];
247   }
248         
249   default:
250     return 0;
251   }
252 }
253
254 /* Increment i. This affects all osc_t objects; we go down the linked list to
255    get them all. */
256 void osc_increment(stonerview_state *st)
257 {
258   osc_t *osc;
259     
260   for (osc = st->oscroot; osc; osc = osc->next) {
261     switch (osc->type) {
262         
263     case otyp_Bounce: {
264       struct obounce_struct *ox = &(osc->u.obounce);
265       ox->val += ox->step;
266       if (ox->val < ox->min && ox->step < 0) {
267         ox->step = -(ox->step);
268         ox->val = ox->min + (ox->min - ox->val);
269       }
270       if (ox->val > ox->max && ox->step > 0) {
271         ox->step = -(ox->step);
272         ox->val = ox->max + (ox->max - ox->val);
273       }
274       break;
275     }
276                 
277     case otyp_Wrap: {
278       struct owrap_struct *ox = &(osc->u.owrap);
279       ox->val += ox->step;
280       if (ox->val < ox->min && ox->step < 0) {
281         ox->val += (ox->max - ox->min);
282       }
283       if (ox->val > ox->max && ox->step > 0) {
284         ox->val -= (ox->max - ox->min);
285       }
286       break;
287     }
288             
289     case otyp_VeloWrap: {
290       struct ovelowrap_struct *ox = &(osc->u.ovelowrap);
291       int diff = (ox->max - ox->min);
292       ox->val += osc_get(st, ox->step, 0);
293       while (ox->val < ox->min)
294         ox->val += diff;
295       while (ox->val > ox->max)
296         ox->val -= diff;
297       break;
298     }
299             
300     case otyp_Phaser: {
301       struct ophaser_struct *ox = &(osc->u.ophaser);
302       ox->count++;
303       if (ox->count >= ox->phaselen) {
304         ox->count = 0;
305         ox->curphase++;
306         if (ox->curphase >= NUM_PHASES)
307           ox->curphase = 0;
308       }
309       break;
310     }
311             
312     case otyp_RandPhaser: {
313       struct orandphaser_struct *ox = &(osc->u.orandphaser);
314       ox->count++;
315       if (ox->count >= ox->curphaselen) {
316         ox->count = 0;
317         ox->curphaselen = rand_range(ox->minphaselen, ox->maxphaselen);
318         ox->curphase++;
319         if (ox->curphase >= NUM_PHASES)
320           ox->curphase = 0;
321       }
322       break;
323     }
324             
325     case otyp_Buffer: {
326       struct obuffer_struct *ox = &(osc->u.obuffer);
327       ox->firstel--;
328       if (ox->firstel < 0)
329         ox->firstel += st->num_els;
330       ox->el[ox->firstel] = osc_get(st, ox->val, 0);
331       /* We can assume that ox->val has already been incremented, since it
332          was created first. This is why new objects are put on the end
333          of the linked list... yeah, it's gross. */
334       break;
335     }
336             
337     default:
338       break;
339     }
340   }
341 }