http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.16.tar.gz
[xscreensaver] / hacks / glx / noof.c
1 /* noof, Copyright (c) 2004 Mark Kilgard <mjk@nvidia.com>
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  * Originally a demo included with GLUT;
12  * (Apparently this was called "diatoms" on Irix.)
13  * ported to raw GL and xscreensaver by jwz, 12-Feb-2004.
14  */
15
16 #include <X11/Intrinsic.h>
17
18 extern XtAppContext app;
19
20 #define PROGCLASS       "Noof"
21 #define HACK_INIT       init_noof
22 #define HACK_DRAW       draw_noof
23 #define HACK_RESHAPE    reshape_noof
24 #define noof_opts       xlockmore_opts
25
26 #define DEFAULTS        "*delay:        10000       \n" \
27                         "*showFPS:      False       \n" \
28                         "*fpsSolid:     True        \n" \
29
30 #include "xlockmore.h"
31
32 #ifdef USE_GL /* whole file */
33
34 typedef struct {
35   GLXContext *glx_context;
36 } noof_configuration;
37
38 static noof_configuration *bps = NULL;
39 ModeSpecOpt noof_opts = {0, NULL, 0, NULL, NULL};
40
41
42 /* --- shape parameters def'n --- */
43 #define N_SHAPES 7
44 static float pos[N_SHAPES * 3];
45 static float dir[N_SHAPES * 3];
46 static float acc[N_SHAPES * 3];
47 static float col[N_SHAPES * 3];
48 static float hsv[N_SHAPES * 3];
49 static float hpr[N_SHAPES * 3];
50 static float ang[N_SHAPES];
51 static float spn[N_SHAPES];
52 static float sca[N_SHAPES];
53 static float geep[N_SHAPES];
54 static float peep[N_SHAPES];
55 static float speedsq[N_SHAPES];
56 static int blad[N_SHAPES];
57
58 static float ht, wd;
59
60 static void
61 initshapes(int i)
62 {
63   int k;
64   float f;
65
66   /* random init of pos, dir, color */
67   for (k = i * 3; k <= i * 3 + 2; k++) {
68     f = random() / (double) RAND_MAX;
69     pos[k] = f;
70     f = random() / (double) RAND_MAX;
71     f = (f - 0.5) * 0.05;
72     dir[k] = f;
73     f = random() / (double) RAND_MAX;
74     f = (f - 0.5) * 0.0002;
75     acc[k] = f;
76     f = random() / (double) RAND_MAX;
77     col[k] = f;
78   }
79
80   speedsq[i] = dir[i * 3] * dir[i * 3] + dir[i * 3 + 1] * dir[i * 3 + 1];
81   f = random() / (double) RAND_MAX;
82   blad[i] = 2 + (int) (f * 17.0);
83   f = random() / (double) RAND_MAX;
84   ang[i] = f;
85   f = random() / (double) RAND_MAX;
86   spn[i] = (f - 0.5) * 40.0 / (10 + blad[i]);
87   f = random() / (double) RAND_MAX;
88   sca[i] = (f * 0.1 + 0.08);
89   dir[i * 3] *= sca[i];
90   dir[i * 3 + 1] *= sca[i];
91
92   f = random() / (double) RAND_MAX;
93   hsv[i * 3] = f * 360.0;
94
95   f = random() / (double) RAND_MAX;
96   hsv[i * 3 + 1] = f * 0.6 + 0.4;
97
98   f = random() / (double) RAND_MAX;
99   hsv[i * 3 + 2] = f * 0.7 + 0.3;
100
101   f = random() / (double) RAND_MAX;
102   hpr[i * 3] = f * 0.005 * 360.0;
103   f = random() / (double) RAND_MAX;
104   hpr[i * 3 + 1] = f * 0.03;
105   f = random() / (double) RAND_MAX;
106   hpr[i * 3 + 2] = f * 0.02;
107
108   geep[i] = 0;
109   f = random() / (double) RAND_MAX;
110   peep[i] = 0.01 + f * 0.2;
111 }
112
113 static int tko = 0;
114
115 static float bladeratio[] =
116 {
117   /* nblades = 2..7 */
118   0.0, 0.0, 3.00000, 1.73205, 1.00000, 0.72654, 0.57735, 0.48157,
119   /* 8..13 */
120   0.41421, 0.36397, 0.19076, 0.29363, 0.26795, 0.24648,
121   /* 14..19 */
122   0.22824, 0.21256, 0.19891, 0.18693, 0.17633, 0.16687,
123 };
124
125 static void
126 drawleaf(int l)
127 {
128
129   int b, blades;
130   float x, y;
131   float wobble;
132
133   blades = blad[l];
134
135   y = 0.10 * sin(geep[l] * M_PI / 180.0) + 0.099 * sin(geep[l] * 5.12 * M_PI / 180.0);
136   if (y < 0)
137     y = -y;
138   x = 0.15 * cos(geep[l] * M_PI / 180.0) + 0.149 * cos(geep[l] * 5.12 * M_PI / 180.0);
139   if (x < 0.0)
140     x = 0.0 - x;
141   if (y < 0.001 && x > 0.000002 && ((tko & 0x1) == 0)) {
142     initshapes(l);      /* let it become reborn as something
143                            else */
144     tko++;
145     return;
146   } {
147     float w1 = sin(geep[l] * 15.3 * M_PI / 180.0);
148     wobble = 3.0 + 2.00 * sin(geep[l] * 0.4 * M_PI / 180.0) + 3.94261 * w1;
149   }
150
151   /**
152   if(blades == 2) if (y > 3.000*x) y = x*3.000;
153   if(blades == 3) if (y > 1.732*x) y = x*1.732;
154   if(blades == 4) if (y >       x) y = x;
155   if(blades == 5) if (y > 0.726*x) y = x*0.726;
156   if(blades == 6) if (y > 0.577*x) y = x*0.577;
157   if(blades == 7) if (y > 0.481*x) y = x*0.481;
158   if(blades == 8) if (y > 0.414*x) y = x*0.414;
159   */
160   if (y > x * bladeratio[blades])
161     y = x * bladeratio[blades];
162
163   for (b = 0; b < blades; b++) {
164     glPushMatrix();
165     glTranslatef(pos[l * 3], pos[l * 3 + 1], pos[l * 3 + 2]);
166     glRotatef(ang[l] + b * (360.0 / blades), 0.0, 0.0, 1.0);
167     glScalef(wobble * sca[l], wobble * sca[l], wobble * sca[l]);
168     /**
169     if(tko & 0x40000) glColor3f(col[l*3], col[l*3+1], col[l*3+2]); 
170     else
171     */
172     glColor4ub(0, 0, 0, 0x60);
173
174     /* constrain geep cooridinates here XXX */
175     glEnable(GL_BLEND);
176
177     glBegin(GL_TRIANGLE_STRIP);
178     glVertex2f(x * sca[l], 0.0);
179     glVertex2f(x, y);
180     glVertex2f(x, -y);  /* C */
181     glVertex2f(0.3, 0.0);  /* D */
182     glEnd();
183
184     /**
185     if(tko++ & 0x40000) glColor3f(0,0,0);
186     else
187     */
188     glColor3f(col[l * 3], col[l * 3 + 1], col[l * 3 + 2]);
189     glBegin(GL_LINE_LOOP);
190     glVertex2f(x * sca[l], 0.0);
191     glVertex2f(x, y);
192     glVertex2f(0.3, 0.0);  /* D */
193     glVertex2f(x, -y);  /* C */
194     glEnd();
195     glDisable(GL_BLEND);
196
197     glPopMatrix();
198   }
199 }
200
201 static void
202 motionUpdate(int t)
203 {
204   if (pos[t * 3] < -sca[t] * wd && dir[t * 3] < 0.0) {
205     dir[t * 3] = -dir[t * 3];
206   /**
207   acc[t*3+1] += 0.8*acc[t*3];
208   acc[t*3] = -0.8*acc[t*3];
209   */
210   } else if (pos[t * 3] > (1 + sca[t]) * wd && dir[t * 3] > 0.0) {
211     dir[t * 3] = -dir[t * 3];
212     /**
213     acc[t*3+1] += 0.8*acc[t*3];
214     acc[t*3] = -0.8*acc[t*3];
215     */
216   } else if (pos[t * 3 + 1] < -sca[t] * ht && dir[t * 3 + 1] < 0.0) {
217     dir[t * 3 + 1] = -dir[t * 3 + 1];
218     /**
219     acc[t*3] += 0.8*acc[t*3+1];
220     acc[t*3+1] = -0.8*acc[t*3+1];
221     */
222   } else if (pos[t * 3 + 1] > (1 + sca[t]) * ht && dir[t * 3 + 1] > 0.0) {
223     dir[t * 3 + 1] = -dir[t * 3 + 1];
224     /**
225     acc[t*3] += 0.8*acc[t*3+1];
226     acc[t*3+1] = -0.8*acc[t*3+1];
227     */
228   }
229
230   pos[t * 3] += dir[t * 3];
231   pos[t * 3 + 1] += dir[t * 3 + 1];
232   /**
233   dir[t*3]   += acc[t*3];
234   dir[t*3+1] += acc[t*3+1];
235   */
236   ang[t] += spn[t];
237   geep[t] += peep[t];
238   if (geep[t] > 360 * 5.0)
239     geep[t] -= 360 * 5.0;
240   if (ang[t] < 0.0) {
241     ang[t] += 360.0;
242   }
243   if (ang[t] > 360.0) {
244     ang[t] -= 360.0;
245   }
246 }
247
248 static void
249 colorUpdate(int i)
250 {
251   if (hsv[i * 3 + 1] <= 0.5 && hpr[i * 3 + 1] < 0.0)
252     hpr[i * 3 + 1] = -hpr[i * 3 + 1];  /* adjust s */
253   if (hsv[i * 3 + 1] >= 1.0 && hpr[i * 3 + 1] > 0.0)
254     hpr[i * 3 + 1] = -hpr[i * 3 + 1];  /* adjust s */
255   if (hsv[i * 3 + 2] <= 0.4 && hpr[i * 3 + 2] < 0.0)
256     hpr[i * 3 + 2] = -hpr[i * 3 + 2];  /* adjust s */
257   if (hsv[i * 3 + 2] >= 1.0 && hpr[i * 3 + 2] > 0.0)
258     hpr[i * 3 + 2] = -hpr[i * 3 + 2];  /* adjust s */
259
260   hsv[i * 3] += hpr[i * 3];
261   hsv[i * 3 + 1] += hpr[i * 3 + 1];
262   hsv[i * 3 + 2] += hpr[i * 3 + 2];
263
264   /* --- hsv -> rgb --- */
265 #define H(hhh) hhh[i*3  ]
266 #define S(hhh) hhh[i*3+1]
267 #define V(hhh) hhh[i*3+2]
268
269 #define R(hhh) hhh[i*3  ]
270 #define G(hhh) hhh[i*3+1]
271 #define B(hhh) hhh[i*3+2]
272
273   if (V(hsv) < 0.0)
274     V(hsv) = 0.0;
275   if (V(hsv) > 1.0)
276     V(hsv) = 1.0;
277   if (S(hsv) <= 0.0) {
278     R(col) = V(hsv);
279     G(col) = V(hsv);
280     B(col) = V(hsv);
281   } else {
282     float f, h, p, q, t, v;
283     int hi;
284
285     while (H(hsv) < 0.0)
286       H(hsv) += 360.0;
287     while (H(hsv) >= 360.0)
288       H(hsv) -= 360.0;
289
290     if (S(hsv) < 0.0)
291       S(hsv) = 0.0;
292     if (S(hsv) > 1.0)
293       S(hsv) = 1.0;
294
295     h = H(hsv) / 60.0;
296     hi = (int) (h);
297     f = h - hi;
298     v = V(hsv);
299     p = V(hsv) * (1 - S(hsv));
300     q = V(hsv) * (1 - S(hsv) * f);
301     t = V(hsv) * (1 - S(hsv) * (1 - f));
302
303     if (hi <= 0) {
304       R(col) = v;
305       G(col) = t;
306       B(col) = p;
307     } else if (hi == 1) {
308       R(col) = q;
309       G(col) = v;
310       B(col) = p;
311     } else if (hi == 2) {
312       R(col) = p;
313       G(col) = v;
314       B(col) = t;
315     } else if (hi == 3) {
316       R(col) = p;
317       G(col) = q;
318       B(col) = v;
319     } else if (hi == 4) {
320       R(col) = t;
321       G(col) = p;
322       B(col) = v;
323     } else {
324       R(col) = v;
325       G(col) = p;
326       B(col) = q;
327     }
328   }
329 }
330
331 static void
332 gravity(float fx)
333 {
334   int a, b;
335
336   for (a = 0; a < N_SHAPES; a++) {
337     for (b = 0; b < a; b++) {
338       float t, d2;
339
340       t = pos[b * 3] - pos[a * 3];
341       d2 = t * t;
342       t = pos[b * 3 + 1] - pos[a * 3 + 1];
343       d2 += t * t;
344       if (d2 < 0.000001)
345         d2 = 0.00001;
346       if (d2 < 0.1) {
347
348         float v0, v1, z;
349         v0 = pos[b * 3] - pos[a * 3];
350         v1 = pos[b * 3 + 1] - pos[a * 3 + 1];
351
352         z = 0.00000001 * fx / (d2);
353
354         dir[a * 3] += v0 * z * sca[b];
355         dir[b * 3] += -v0 * z * sca[a];
356         dir[a * 3 + 1] += v1 * z * sca[b];
357         dir[b * 3 + 1] += -v1 * z * sca[a];
358
359       }
360     }
361     /** apply brakes
362     if(dir[a*3]*dir[a*3] + dir[a*3+1]*dir[a*3+1]
363       > 0.0001) {
364       dir[a*3] *= 0.9;
365       dir[a*3+1] *= 0.9;
366     }
367     */
368   }
369 }
370
371 void
372 draw_noof (ModeInfo *mi)
373 {
374   int i;
375
376   /**
377   if((random() & 0xff) == 0x34){
378     glClear(GL_COLOR_BUFFER_BIT);
379   }
380
381   if((tko & 0x1f) == 0x1f){
382     glEnable(GL_BLEND);
383     glColor4f(0.0, 0.0, 0.0, 0.09);
384     glRectf(0.0, 0.0, wd, ht);
385     glDisable(GL_BLEND);
386 #ifdef __sgi
387     sginap(0);
388 #endif
389   }
390   */
391
392   gravity(-2.0);
393   for (i = 0; i < N_SHAPES; i++) {
394     motionUpdate(i);
395     colorUpdate(i);
396     drawleaf(i);
397   }
398
399   if (mi->fps_p) do_fps (mi);
400   glFinish();
401
402   glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi));
403 }
404
405
406 void
407 reshape_noof(ModeInfo *mi, int w, int h)
408 {
409   glViewport(0, 0, w, h);
410   glMatrixMode(GL_PROJECTION);
411   glLoadIdentity();
412   if (w <= h) {
413     wd = 1.0;
414     ht = (GLfloat) h / (GLfloat) w;
415     glOrtho(0.0, 1.0,
416       0.0, 1.0 * (GLfloat) h / (GLfloat) w,
417       -16.0, 4.0);
418   } else {
419     wd = (GLfloat) w / (GLfloat) h;
420     ht = 1.0;
421     glOrtho(0.0, 1.0 * (GLfloat) w / (GLfloat) h,
422       0.0, 1.0,
423       -16.0, 4.0);
424   }
425   glMatrixMode(GL_MODELVIEW);
426   glLoadIdentity();
427
428   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
429 }
430
431 void 
432 init_noof (ModeInfo *mi)
433 {
434   int i;
435   noof_configuration *bp;
436
437   if (!bps) {
438     bps = (noof_configuration *)
439       calloc (MI_NUM_SCREENS(mi), sizeof (noof_configuration));
440     if (!bps) {
441       fprintf(stderr, "%s: out of memory\n", progname);
442       exit(1);
443     }
444     bp = &bps[MI_SCREEN(mi)];
445   }
446
447   bp = &bps[MI_SCREEN(mi)];
448
449   bp->glx_context = init_GL(mi);
450
451   glClearColor(0.0, 0.0, 0.0, 1.0);
452   glEnable(GL_LINE_SMOOTH);
453   glShadeModel(GL_FLAT);
454   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
455   for (i = 0; i < N_SHAPES; i++)
456     initshapes(i);
457   reshape_noof (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
458 }
459
460
461 #endif /* USE_GL */