source: trunk/third/xscreensaver/hacks/anemone.c @ 20148

Revision 20148, 9.3 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
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
53static Display *dpy;
54static Window window;
55
56static Pixmap b,ba,bb;
57
58#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
59static  XdbeBackBuffer backb;
60#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
61
62static int
63arms,                       /* number of arms */
64  finpoints;                  /* final number of points in each array. */
65static long delay;              /* usecs to wait between updates. */
66
67static int         scrWidth, scrHeight;
68static GC          gcDraw, gcClear;
69
70typedef struct {
71  double x,y,z;
72  int sx,sy,sz;
73} vPend;
74
75typedef unsigned short bool;
76
77static bool dbuf;
78static int width;
79
80typedef struct {
81  long col;
82  int numpt;
83  int growth;
84  unsigned short rate;
85} appDef;
86
87static vPend *vPendage;  /* 3D representation of appendages */
88static appDef *appD;  /* defaults */
89static vPend *vCurr, *vNext;
90static appDef *aCurr;
91
92static double turn, turndelta;
93
94static int    mx, my;            /* max screen coordinates. */
95static int withdraw;
96
97static    XGCValues         gcv;
98static    Colormap          cmap;
99
100
101
102/*-----------------------------------------------------------------------+
103  |  PUBLIC DATA                                                           |
104  +-----------------------------------------------------------------------*/
105
106char *progclass = "Anemone";
107
108char *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
123XrmOptionDescRec 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};
132int options_size = (sizeof (options) / sizeof (options[0]));
133
134/*-----------------------------------------------------------------------+
135  |  PRIVATE FUNCTIONS                                                     |
136  +-----------------------------------------------------------------------*/
137
138static void *
139xmalloc(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
151static void
152initAppendages(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
210static void
211initAnemone(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
264static void
265createPoints(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
301static void
302drawImage(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
336static void
337animateAnemone(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
365void
366screenhack(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
Note: See TracBrowser for help on using the repository browser.