1 | /* anemon, Copyright (c) 2001 Gabriel Finch |
---|
2 | * |
---|
3 | * Permission to use, copy, modify, distribute, and sell this software and its |
---|
4 | * documentation for any purpose is hereby granted without fee, provided that |
---|
5 | * the above copyright notice appear in all copies and that both that |
---|
6 | * copyright notice and this permission notice appear in supporting |
---|
7 | * documentation. No representations are made about the suitability of this |
---|
8 | * software for any purpose. It is provided "as is" without express or |
---|
9 | * implied warranty. |
---|
10 | */ |
---|
11 | |
---|
12 | /*------------------------------------------------------------------------ |
---|
13 | | |
---|
14 | | FILE anemone.c |
---|
15 | | MODULE OF xscreensaver |
---|
16 | | |
---|
17 | | DESCRIPTION Anemone. |
---|
18 | | |
---|
19 | | WRITTEN BY Gabriel Finch |
---|
20 | | |
---|
21 | | |
---|
22 | | |
---|
23 | | MODIFICATIONS june 2001 started |
---|
24 | | |
---|
25 | +----------------------------------------------------------------------*/ |
---|
26 | |
---|
27 | |
---|
28 | |
---|
29 | #include <stdio.h> |
---|
30 | #include <stdlib.h> |
---|
31 | #include <string.h> |
---|
32 | #include <math.h> |
---|
33 | #include "screenhack.h" |
---|
34 | |
---|
35 | |
---|
36 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
37 | #include "xdbe.h" |
---|
38 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
39 | |
---|
40 | |
---|
41 | /*-----------------------------------------------------------------------+ |
---|
42 | | PRIVATE DATA | |
---|
43 | +-----------------------------------------------------------------------*/ |
---|
44 | |
---|
45 | |
---|
46 | #define TWO_PI (2.0 * M_PI) |
---|
47 | #define RND(x) (random() % (x)) |
---|
48 | #define MAXPEND 2000 |
---|
49 | #define MAXPTS 200 |
---|
50 | #define TRUE 1 |
---|
51 | #define FALSE 0 |
---|
52 | |
---|
53 | static Display *dpy; |
---|
54 | static Window window; |
---|
55 | |
---|
56 | static Pixmap b,ba,bb; |
---|
57 | |
---|
58 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
59 | static XdbeBackBuffer backb; |
---|
60 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
61 | |
---|
62 | static int |
---|
63 | arms, /* number of arms */ |
---|
64 | finpoints; /* final number of points in each array. */ |
---|
65 | static long delay; /* usecs to wait between updates. */ |
---|
66 | |
---|
67 | static int scrWidth, scrHeight; |
---|
68 | static GC gcDraw, gcClear; |
---|
69 | |
---|
70 | typedef struct { |
---|
71 | double x,y,z; |
---|
72 | int sx,sy,sz; |
---|
73 | } vPend; |
---|
74 | |
---|
75 | typedef unsigned short bool; |
---|
76 | |
---|
77 | static bool dbuf; |
---|
78 | static int width; |
---|
79 | |
---|
80 | typedef struct { |
---|
81 | long col; |
---|
82 | int numpt; |
---|
83 | int growth; |
---|
84 | unsigned short rate; |
---|
85 | } appDef; |
---|
86 | |
---|
87 | static vPend *vPendage; /* 3D representation of appendages */ |
---|
88 | static appDef *appD; /* defaults */ |
---|
89 | static vPend *vCurr, *vNext; |
---|
90 | static appDef *aCurr; |
---|
91 | |
---|
92 | static double turn, turndelta; |
---|
93 | |
---|
94 | static int mx, my; /* max screen coordinates. */ |
---|
95 | static int withdraw; |
---|
96 | |
---|
97 | static XGCValues gcv; |
---|
98 | static Colormap cmap; |
---|
99 | |
---|
100 | |
---|
101 | |
---|
102 | /*-----------------------------------------------------------------------+ |
---|
103 | | PUBLIC DATA | |
---|
104 | +-----------------------------------------------------------------------*/ |
---|
105 | |
---|
106 | char *progclass = "Anemone"; |
---|
107 | |
---|
108 | char *defaults [] = { |
---|
109 | ".background: black", |
---|
110 | "*arms: 128", |
---|
111 | "*width: 2", |
---|
112 | "*finpoints: 64", |
---|
113 | "*delay: 40000", |
---|
114 | "*withdraw: 1200", |
---|
115 | "*turnspeed: 50", |
---|
116 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
117 | "*useDBE: True", |
---|
118 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
119 | 0 |
---|
120 | }; |
---|
121 | |
---|
122 | |
---|
123 | XrmOptionDescRec options [] = { |
---|
124 | { "-arms", ".arms", XrmoptionSepArg, 0 }, |
---|
125 | { "-finpoints", ".finpoints", XrmoptionSepArg, 0 }, |
---|
126 | { "-delay", ".delay", XrmoptionSepArg, 0 }, |
---|
127 | { "-width", ".width", XrmoptionSepArg, 0 }, |
---|
128 | { "-withdraw", ".withdraw", XrmoptionSepArg, 0 }, |
---|
129 | { "-turnspeed", ".turnspeed", XrmoptionSepArg, 0 }, |
---|
130 | { 0, 0, 0, 0 } |
---|
131 | }; |
---|
132 | int options_size = (sizeof (options) / sizeof (options[0])); |
---|
133 | |
---|
134 | /*-----------------------------------------------------------------------+ |
---|
135 | | PRIVATE FUNCTIONS | |
---|
136 | +-----------------------------------------------------------------------*/ |
---|
137 | |
---|
138 | static void * |
---|
139 | xmalloc(size_t size) |
---|
140 | { |
---|
141 | void *ret; |
---|
142 | |
---|
143 | if ((ret = malloc(size)) == NULL) { |
---|
144 | fprintf(stderr, "anemone: out of memory\n"); |
---|
145 | exit(1); |
---|
146 | } |
---|
147 | return ret; |
---|
148 | } |
---|
149 | |
---|
150 | |
---|
151 | static void |
---|
152 | initAppendages(void) |
---|
153 | { |
---|
154 | int i; |
---|
155 | /*int marginx, marginy; */ |
---|
156 | |
---|
157 | /*double scalex, scaley;*/ |
---|
158 | |
---|
159 | double x,y,z,dist; |
---|
160 | |
---|
161 | mx = scrWidth - 1; |
---|
162 | my = scrHeight - 1; |
---|
163 | |
---|
164 | /* each appendage will have: colour, |
---|
165 | number of points, and a grow or shrink indicator */ |
---|
166 | |
---|
167 | /* added: growth rate 1-10 (smaller==faster growth) */ |
---|
168 | /* each appendage needs virtual coords (x,y,z) with y and z combining to |
---|
169 | give the screen y */ |
---|
170 | |
---|
171 | vPendage = (vPend *) xmalloc((finpoints + 1) * sizeof(vPend) * arms); |
---|
172 | appD = (appDef *) xmalloc(sizeof(appDef) * arms); |
---|
173 | |
---|
174 | |
---|
175 | for (i = 0; i < arms; i++) { |
---|
176 | aCurr = appD + i; |
---|
177 | vCurr = vPendage + (finpoints + 1) * i; |
---|
178 | vNext = vCurr + 1; |
---|
179 | |
---|
180 | aCurr->col = (long)RND(256)*RND(256)+32768; |
---|
181 | aCurr->numpt = 1; |
---|
182 | aCurr->growth=finpoints/2+RND(finpoints/2); |
---|
183 | aCurr->rate=RND(11)*RND(11); |
---|
184 | |
---|
185 | dist=1.; |
---|
186 | |
---|
187 | do { |
---|
188 | x=(1-RND(1001)/500); |
---|
189 | y=(1-RND(1001)/500); |
---|
190 | z=(1-RND(1001)/500); |
---|
191 | dist=x*x+y*y+z*z; |
---|
192 | } while (dist>=1.); |
---|
193 | |
---|
194 | vCurr->x=x*200; |
---|
195 | vCurr->y=my/2+y*200; |
---|
196 | vCurr->z=0+z*200; |
---|
197 | |
---|
198 | /* start the arm going outwards */ |
---|
199 | vCurr->sx=vCurr->x/5; |
---|
200 | vCurr->sy=(vCurr->y-my/2)/5; |
---|
201 | vCurr->sz=(vCurr->z)/5; |
---|
202 | |
---|
203 | |
---|
204 | vNext->x=vCurr->x+vCurr->sx; |
---|
205 | vNext->y=vCurr->y+vCurr->sy; |
---|
206 | vNext->z=vCurr->z+vCurr->sz; |
---|
207 | } |
---|
208 | } |
---|
209 | |
---|
210 | static void |
---|
211 | initAnemone(void) |
---|
212 | { |
---|
213 | XWindowAttributes wa; |
---|
214 | |
---|
215 | turn = 0.; |
---|
216 | |
---|
217 | width = get_integer_resource("width", "Integer"); |
---|
218 | arms = get_integer_resource("arms", "Integer"); |
---|
219 | finpoints = get_integer_resource("finpoints", "Integer"); |
---|
220 | delay = get_integer_resource("delay", "Integer"); |
---|
221 | withdraw = get_integer_resource("withdraw", "Integer"); |
---|
222 | turndelta = get_float_resource("turnspeed", "float")/100000; |
---|
223 | |
---|
224 | dbuf=TRUE; |
---|
225 | |
---|
226 | |
---|
227 | b=ba=bb=0; /* double-buffer to reduce flicker */ |
---|
228 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
229 | b = backb = xdbe_get_backbuffer (dpy, window, XdbeUndefined); |
---|
230 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
231 | |
---|
232 | |
---|
233 | XGetWindowAttributes(dpy, window, &wa); |
---|
234 | scrWidth = wa.width; |
---|
235 | scrHeight = wa.height; |
---|
236 | cmap = wa.colormap; |
---|
237 | gcDraw = XCreateGC(dpy, window, GCForeground, &gcv); |
---|
238 | gcv.foreground = get_pixel_resource("background", "Background", dpy, cmap); |
---|
239 | gcClear = XCreateGC(dpy, window, GCForeground, &gcv); |
---|
240 | |
---|
241 | if (dbuf) { |
---|
242 | if (!b) |
---|
243 | { |
---|
244 | ba = XCreatePixmap (dpy, window, scrWidth, scrHeight, wa.depth); |
---|
245 | bb = XCreatePixmap (dpy, window, scrWidth, scrHeight, wa.depth); |
---|
246 | b = ba; |
---|
247 | } |
---|
248 | } |
---|
249 | else |
---|
250 | { |
---|
251 | b = window; |
---|
252 | } |
---|
253 | |
---|
254 | if (ba) XFillRectangle (dpy, ba, gcClear, 0, 0, scrWidth, scrHeight); |
---|
255 | if (bb) XFillRectangle (dpy, bb, gcClear, 0, 0, scrWidth, scrHeight); |
---|
256 | |
---|
257 | XClearWindow(dpy, window); |
---|
258 | XSetLineAttributes(dpy, gcDraw, width, LineSolid, CapRound, JoinBevel); |
---|
259 | |
---|
260 | initAppendages(); |
---|
261 | } |
---|
262 | |
---|
263 | |
---|
264 | static void |
---|
265 | createPoints(void) |
---|
266 | { |
---|
267 | int i; |
---|
268 | int withdrawall=RND(withdraw); |
---|
269 | |
---|
270 | for (i = 0; i< arms; i++) { |
---|
271 | aCurr = appD + i; |
---|
272 | if (!withdrawall) { |
---|
273 | aCurr->growth=-finpoints; |
---|
274 | turndelta=-turndelta; |
---|
275 | } |
---|
276 | |
---|
277 | else if (withdrawall<11) aCurr->growth=-aCurr->numpt; |
---|
278 | |
---|
279 | else if (RND(100)<aCurr->rate) { |
---|
280 | if (aCurr->growth>0) { |
---|
281 | if (!(--aCurr->growth)) aCurr->growth=-RND(finpoints)-1; |
---|
282 | vCurr = vPendage + (finpoints + 1) * i + aCurr->numpt-1; |
---|
283 | if (aCurr->numpt<finpoints - 1) { |
---|
284 | /* add a piece */ |
---|
285 | vNext=vCurr + 1; |
---|
286 | aCurr->numpt++; |
---|
287 | vNext->sx=vCurr->sx+RND(3)-1; |
---|
288 | vNext->sy=vCurr->sy+RND(3)-1; |
---|
289 | vNext->sz=vCurr->sz+RND(3)-1; |
---|
290 | vCurr=vNext+1; |
---|
291 | vCurr->x=vNext->x+vNext->sx; |
---|
292 | vCurr->y=vNext->y+vNext->sy; |
---|
293 | vCurr->z=vNext->z+vNext->sz; |
---|
294 | } |
---|
295 | } |
---|
296 | } |
---|
297 | } |
---|
298 | } |
---|
299 | |
---|
300 | |
---|
301 | static void |
---|
302 | drawImage(Drawable curr_window, double sint, double cost) |
---|
303 | { |
---|
304 | int q,numpt,mx2=mx/2; |
---|
305 | double cx,cy,cz,nx=0,ny=0,nz=0; |
---|
306 | |
---|
307 | if ((numpt=aCurr->numpt)==1) return; |
---|
308 | XSetForeground(dpy, gcDraw, aCurr->col); |
---|
309 | |
---|
310 | vNext=vCurr+1; |
---|
311 | |
---|
312 | cx=vCurr->x; |
---|
313 | cy=vCurr->y; |
---|
314 | cz=vCurr->z; |
---|
315 | |
---|
316 | |
---|
317 | for (q = 0; q < numpt-1; q++) { |
---|
318 | nx=vNext->x+2-RND(5); |
---|
319 | ny=vNext->y+2-RND(5); |
---|
320 | nz=vNext->z+2-RND(5); |
---|
321 | |
---|
322 | XDrawLine(dpy, curr_window, gcDraw,mx2+cx*cost-cz*sint, cy, mx2+nx*cost-nz*sint, ny); |
---|
323 | vCurr++; |
---|
324 | vNext++; |
---|
325 | |
---|
326 | cx=nx; |
---|
327 | cy=ny; |
---|
328 | cz=nz; |
---|
329 | } |
---|
330 | XSetLineAttributes(dpy, gcDraw, width*3, LineSolid, CapRound, JoinBevel); |
---|
331 | XDrawLine(dpy, curr_window, gcDraw,mx/2+cx*cost-cz*sint, cy, mx/2+nx*cost-nz*sint, ny); |
---|
332 | XSetLineAttributes(dpy, gcDraw, width, LineSolid, CapRound, JoinBevel); |
---|
333 | |
---|
334 | } |
---|
335 | |
---|
336 | static void |
---|
337 | animateAnemone(Drawable curr_window) |
---|
338 | { |
---|
339 | int i; |
---|
340 | double sint=sin(turn),cost=cos(turn); |
---|
341 | |
---|
342 | aCurr = appD; |
---|
343 | for (i = 0; i< arms; i++) { |
---|
344 | vCurr=vPendage + (finpoints + 1) * i; |
---|
345 | if (RND(25)<aCurr->rate) { |
---|
346 | if (aCurr->growth<0) { |
---|
347 | aCurr->numpt-=aCurr->numpt>1; |
---|
348 | if (!(++aCurr->growth)) aCurr->growth=RND(finpoints-aCurr->numpt)+1; |
---|
349 | } |
---|
350 | } |
---|
351 | drawImage(curr_window, sint, cost); |
---|
352 | turn+=turndelta; |
---|
353 | aCurr++; |
---|
354 | } |
---|
355 | createPoints(); |
---|
356 | usleep(delay); |
---|
357 | |
---|
358 | if (turn>=TWO_PI) turn-=TWO_PI; |
---|
359 | } |
---|
360 | |
---|
361 | /*-----------------------------------------------------------------------+ |
---|
362 | | PUBLIC FUNCTIONS | |
---|
363 | +-----------------------------------------------------------------------*/ |
---|
364 | |
---|
365 | void |
---|
366 | screenhack(Display *disp, Window win) |
---|
367 | { |
---|
368 | |
---|
369 | dpy=disp; |
---|
370 | window=win; |
---|
371 | |
---|
372 | initAnemone(); |
---|
373 | for (;;) { |
---|
374 | |
---|
375 | XFillRectangle (dpy, b, gcClear, 0, 0, scrWidth, scrHeight); |
---|
376 | |
---|
377 | animateAnemone(b); |
---|
378 | |
---|
379 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
380 | if (backb) |
---|
381 | { |
---|
382 | XdbeSwapInfo info[1]; |
---|
383 | info[0].swap_window = window; |
---|
384 | info[0].swap_action = XdbeUndefined; |
---|
385 | XdbeSwapBuffers (dpy, info, 1); |
---|
386 | } |
---|
387 | else |
---|
388 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
389 | if (dbuf) |
---|
390 | { |
---|
391 | XCopyArea (dpy, b, window, gcClear, 0, 0, |
---|
392 | scrWidth, scrHeight, 0, 0); |
---|
393 | b = (b == ba ? bb : ba); |
---|
394 | } |
---|
395 | |
---|
396 | screenhack_handle_events (dpy); |
---|
397 | } |
---|
398 | |
---|
399 | } |
---|
400 | |
---|
401 | |
---|
402 | |
---|
403 | |
---|
404 | |
---|
405 | |
---|
406 | |
---|
407 | |
---|
408 | |
---|
409 | |
---|
410 | |
---|
411 | |
---|
412 | |
---|
413 | |
---|
414 | |
---|