http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.28.tar.gz
[xscreensaver] / hacks / glx / stonerview-osc.h
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 /* This defines the osc_t object, which generates a stream of
14    numbers. It is the heart of the StonerSound/StonerView engine.
15     
16    The idea is simple; an osc_t represents some function f(), which
17    can be evaluated to generate an infinite stream of integers (f(0),
18    f(1), f(2), f(3)...). Some of these functions are defined in
19    terms of other osc_t functions: f(i) = g(h(i)) or some such thing.
20     
21    To simplify the code, we don't try to calculate f(i) for any
22    arbitrary i. Instead, we start with i=0. Calling osc_get(f)
23    returns f(0) for all osc_t's in the system. When we're ready, we
24    call osc_increment(), which advances every osc_t to i=1;
25    thereafter, calling osc_get(f) returns f(1). When you call
26    osc_increment() again, you get f(2). And so on. You can't go
27    backwards, or move forwards more than 1 at a time, or move some
28    osc_t's without moving others. This is a very restricted model, but
29    it's exactly what's needed for this system.
30     
31    Now, there's an additional complication. To get the rippling
32    effect, we don't pull out single values, but *sets* of N elements
33    at a time. (N is defined by NUM_ELS below.) So f(i) is really an
34    ordered N-tuple (f(i,0), f(i,1), f(i,2), f(i,3), f(i,4)). And f()
35    generates an infinite stream of these N-tuples. The osc_get() call
36    really has two parameters; you call osc_get(f, n) to find the n'th
37    element of the current N-tuple. Remember, n must be between 0 and
38    n-1.
39     
40    (Do *not* try to get an infinite stream f(i) by calling 
41    osc_get(f, i) for i ranging to infinity! Use osc_increment() to 
42    advance to the next N-tuple in the stream.)
43 */
44
45 #define NUM_ELS (40) /* Forty polygons at a time. */
46
47 #define NUM_PHASES (4) /* Some of the osc functions switch between P 
48                           alternatives. We arbitrarily choose P=4. */
49
50 /* Here are the functions which are available. 
51    Constant: f(i,n) = k. Always the same value. Very simple.
52    Wrap: f(i,n) slides up or down as i increases. There's a minimum and maximum
53      value, and a step. When the current value reaches the min or max, it jumps
54      to the other end and keeps moving the same direction. 
55    Bounce: f(i,n) slides up and down as i increases. There's a minimum and
56      maximum value, and a step. When the current value reaches the min or max,
57      the step is flipped to move the other way.
58    Phaser: f(i,n) = floor(i / phaselen) modulo 4. That is, it generates
59      phaselen 0 values, and then phaselen 1 values, then phaselen 2 values,
60      then phaselen 3 values, then back to 0. (Phaselen is a parameter you
61      supply when you create the phaser.) As you see, this is much the same as
62      the Wrap function, with a minimum of 0, a maximum of 3, and a step of
63      1/phaselen. But since this code uses integer math, fractional steps
64      aren't possible; it's easier to write a separate function.
65    RandPhaser: The same as Phaser, but the phaselen isn't fixed. It varies
66      randomly between a minimum and maximum value you supply.
67    Multiplex: There are five subsidiary functions within a multiplex function: 
68      g0, g1, g2, g3, and a selector function s. Then:
69      f(i,n) = gX(i,n), where X = s(i,n). (Obviously s must generate only values
70      in the range 0 to 3. This is what the phaser functions are designed for,
71      but you can use anything.)
72    Linear: There are two subsidiary functions within this, a and b. Then:
73      f(i,n) = a(i,n) + n*b(i,n). This is an easy way to make an N-tuple that
74      forms a linear sequence, such as (41, 43, 45, 47, 49).
75    Buffer: This takes a subsidiary function g, and computes:
76      f(i,n) = g(i-n,0). That is, the 0th element of the N-tuple is the
77      *current* value of g; the 1st element is the *previous* value of g; the
78      2nd element is the second-to-last value, and so on back in time. This
79      is a weird idea, but it causes exactly the rippling-change effect that
80      we want.
81         
82    Note that Buffer only looks up g(i,0) -- it only uses the 0th elements of
83      the N-tuples that g generates. This saves time and memory, but it means
84      that certain things don't work. For example, if you try to build 
85      Buffer(Linear(A,B)), B will have no effect, because Linear computes
86      a(i,n) + n*b(i,n), and inside the Buffer, n is always zero. On the other
87      hand, Linear(Buffer(A),Buffer(B)) works fine, and is probably what you
88      wanted anyway.
89    Similarly, Buffer(Buffer(A)) is the same as Buffer(A). Proof left as an
90      exercise.
91 */
92
93 #define otyp_Constant (1)
94 #define otyp_Bounce (2)
95 #define otyp_Wrap (3)
96 #define otyp_Phaser (4)
97 #define otyp_RandPhaser (5)
98 #define otyp_VeloWrap (7)
99 #define otyp_Linear (6)
100 #define otyp_Buffer (8)
101 #define otyp_Multiplex (9)
102
103 /* The osc_t structure itself. */
104 typedef struct osc_struct {
105   int type; /* An otyp_* constant. */
106     
107   struct osc_struct *next; /* osc.c uses this to maintain a private linked list
108                               of all osc_t objects created. */
109     
110   /* Union of the data used by all the possible osc_t functions. */
111   union {
112     struct {
113       int val;
114     } oconstant;
115     struct owrap_struct {
116       int min, max, step;
117       int val;
118     } owrap;
119     struct obounce_struct {
120       int min, max, step;
121       int val;
122     } obounce;
123     struct omultiplex_struct {
124       struct osc_struct *sel;
125       struct osc_struct *val[NUM_PHASES];
126     } omultiplex;
127     struct ophaser_struct {
128       int phaselen;
129       int count;
130       int curphase;
131     } ophaser;
132     struct orandphaser_struct {
133       int minphaselen, maxphaselen;
134       int count;
135       int curphaselen;
136       int curphase;
137     } orandphaser;
138     struct ovelowrap_struct {
139       int min, max;
140       struct osc_struct *step;
141       int val;
142     } ovelowrap;
143     struct olinear_struct {
144       struct osc_struct *base;
145       struct osc_struct *diff;
146     } olinear;
147     struct obuffer_struct {
148       struct osc_struct *val;
149       int firstel;
150       int el[NUM_ELS];
151     } obuffer;
152   } u;
153 } osc_t;
154
155 extern osc_t *new_osc_constant(int val);
156 extern osc_t *new_osc_bounce(int min, int max, int step);
157 extern osc_t *new_osc_wrap(int min, int max, int step);
158 extern osc_t *new_osc_phaser(int phaselen);
159 extern osc_t *new_osc_randphaser(int minphaselen, int maxphaselen);
160 extern osc_t *new_osc_velowrap(int min, int max, osc_t *step);
161 extern osc_t *new_osc_linear(osc_t *base, osc_t *diff);
162 extern osc_t *new_osc_buffer(osc_t *val);
163 extern osc_t *new_osc_multiplex(osc_t *sel, osc_t *ox0, osc_t *ox1, 
164   osc_t *ox2, osc_t *ox3);
165
166 extern int osc_get(osc_t *osc, int el);
167 extern void osc_increment(void);
168