1 /* noof, Copyright (c) 2004 Bill Torzewski <billt@worksitez.com>
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
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.
16 #define DEFAULTS "*delay: 10000 \n" \
17 "*showFPS: False \n" \
18 "*fpsSolid: True \n" \
20 # define refresh_noof 0
21 # define release_noof 0
22 # define noof_handle_event 0
23 #include "xlockmore.h"
25 #ifdef USE_GL /* whole file */
29 ENTRYPOINT ModeSpecOpt noof_opts = {0, NULL, 0, NULL, NULL};
32 GLXContext *glx_context;
34 float pos[N_SHAPES * 3];
35 float dir[N_SHAPES * 3];
36 float acc[N_SHAPES * 3];
37 float col[N_SHAPES * 3];
38 float hsv[N_SHAPES * 3];
39 float hpr[N_SHAPES * 3];
45 float speedsq[N_SHAPES];
54 static noof_configuration *bps = NULL;
58 initshapes(noof_configuration *bp, int i)
63 /* random init of pos, dir, color */
64 for (k = i * 3; k <= i * 3 + 2; k++) {
65 f = random() / (double) RAND_MAX;
67 f = random() / (double) RAND_MAX;
70 f = random() / (double) RAND_MAX;
71 f = (f - 0.5) * 0.0002;
73 f = random() / (double) RAND_MAX;
77 bp->speedsq[i] = bp->dir[i * 3] * bp->dir[i * 3] + bp->dir[i * 3 + 1] * bp->dir[i * 3 + 1];
78 f = random() / (double) RAND_MAX;
79 bp->blad[i] = 2 + (int) (f * 17.0);
80 f = random() / (double) RAND_MAX;
82 f = random() / (double) RAND_MAX;
83 bp->spn[i] = (f - 0.5) * 40.0 / (10 + bp->blad[i]);
84 f = random() / (double) RAND_MAX;
85 bp->sca[i] = (f * 0.1 + 0.08);
86 bp->dir[i * 3] *= bp->sca[i];
87 bp->dir[i * 3 + 1] *= bp->sca[i];
89 f = random() / (double) RAND_MAX;
90 bp->hsv[i * 3] = f * 360.0;
92 f = random() / (double) RAND_MAX;
93 bp->hsv[i * 3 + 1] = f * 0.6 + 0.4;
95 f = random() / (double) RAND_MAX;
96 bp->hsv[i * 3 + 2] = f * 0.7 + 0.3;
98 f = random() / (double) RAND_MAX;
99 bp->hpr[i * 3] = f * 0.005 * 360.0;
100 f = random() / (double) RAND_MAX;
101 bp->hpr[i * 3 + 1] = f * 0.03;
102 f = random() / (double) RAND_MAX;
103 bp->hpr[i * 3 + 2] = f * 0.02;
106 f = random() / (double) RAND_MAX;
107 bp->peep[i] = 0.01 + f * 0.2;
110 static const float bladeratio[] =
113 0.0, 0.0, 3.00000, 1.73205, 1.00000, 0.72654, 0.57735, 0.48157,
115 0.41421, 0.36397, 0.19076, 0.29363, 0.26795, 0.24648,
117 0.22824, 0.21256, 0.19891, 0.18693, 0.17633, 0.16687,
121 drawleaf(noof_configuration *bp, int l)
128 blades = bp->blad[l];
130 y = 0.10 * sin(bp->geep[l] * M_PI / 180.0) + 0.099 * sin(bp->geep[l] * 5.12 * M_PI / 180.0);
133 x = 0.15 * cos(bp->geep[l] * M_PI / 180.0) + 0.149 * cos(bp->geep[l] * 5.12 * M_PI / 180.0);
136 if (y < 0.001 && x > 0.000002 && ((bp->tko & 0x1) == 0)) {
137 initshapes(bp, l); /* let it become reborn as something
142 float w1 = sin(bp->geep[l] * 15.3 * M_PI / 180.0);
143 wobble = 3.0 + 2.00 * sin(bp->geep[l] * 0.4 * M_PI / 180.0) + 3.94261 * w1;
147 if(blades == 2) if (y > 3.000*x) y = x*3.000;
148 if(blades == 3) if (y > 1.732*x) y = x*1.732;
149 if(blades == 4) if (y > x) y = x;
150 if(blades == 5) if (y > 0.726*x) y = x*0.726;
151 if(blades == 6) if (y > 0.577*x) y = x*0.577;
152 if(blades == 7) if (y > 0.481*x) y = x*0.481;
153 if(blades == 8) if (y > 0.414*x) y = x*0.414;
155 if (y > x * bladeratio[blades])
156 y = x * bladeratio[blades];
158 for (b = 0; b < blades; b++) {
160 glTranslatef(bp->pos[l * 3], bp->pos[l * 3 + 1], bp->pos[l * 3 + 2]);
161 glRotatef(bp->ang[l] + b * (360.0 / blades), 0.0, 0.0, 1.0);
162 glScalef(wobble * bp->sca[l], wobble * bp->sca[l], wobble * bp->sca[l]);
164 if(tko & 0x40000) glColor3f(col[l*3], col[l*3+1], col[l*3+2]);
167 glColor4ub(0, 0, 0, 0x60);
169 /* constrain geep cooridinates here XXX */
172 glBegin(GL_TRIANGLE_STRIP);
173 glVertex2f(x * bp->sca[l], 0.0);
175 glVertex2f(x, -y); /* C */
176 glVertex2f(0.3, 0.0); /* D */
180 if(tko++ & 0x40000) glColor3f(0,0,0);
183 glColor3f(bp->col[l * 3], bp->col[l * 3 + 1], bp->col[l * 3 + 2]);
184 glBegin(GL_LINE_LOOP);
185 glVertex2f(x * bp->sca[l], 0.0);
187 glVertex2f(0.3, 0.0); /* D */
188 glVertex2f(x, -y); /* C */
197 motionUpdate(noof_configuration *bp, int t)
199 if (bp->pos[t * 3] < -bp->sca[t] * bp->wd && bp->dir[t * 3] < 0.0) {
200 bp->dir[t * 3] = -bp->dir[t * 3];
202 acc[t*3+1] += 0.8*acc[t*3];
203 acc[t*3] = -0.8*acc[t*3];
205 } else if (bp->pos[t * 3] > (1 + bp->sca[t]) * bp->wd && bp->dir[t * 3] > 0.0) {
206 bp->dir[t * 3] = -bp->dir[t * 3];
208 acc[t*3+1] += 0.8*acc[t*3];
209 acc[t*3] = -0.8*acc[t*3];
211 } else if (bp->pos[t * 3 + 1] < -bp->sca[t] * bp->ht && bp->dir[t * 3 + 1] < 0.0) {
212 bp->dir[t * 3 + 1] = -bp->dir[t * 3 + 1];
214 acc[t*3] += 0.8*acc[t*3+1];
215 acc[t*3+1] = -0.8*acc[t*3+1];
217 } else if (bp->pos[t * 3 + 1] > (1 + bp->sca[t]) * bp->ht && bp->dir[t * 3 + 1] > 0.0) {
218 bp->dir[t * 3 + 1] = -bp->dir[t * 3 + 1];
220 acc[t*3] += 0.8*acc[t*3+1];
221 acc[t*3+1] = -0.8*acc[t*3+1];
225 bp->pos[t * 3] += bp->dir[t * 3];
226 bp->pos[t * 3 + 1] += bp->dir[t * 3 + 1];
228 dir[t*3] += acc[t*3];
229 dir[t*3+1] += acc[t*3+1];
231 bp->ang[t] += bp->spn[t];
232 bp->geep[t] += bp->peep[t];
233 if (bp->geep[t] > 360 * 5.0)
234 bp->geep[t] -= 360 * 5.0;
235 if (bp->ang[t] < 0.0) {
238 if (bp->ang[t] > 360.0) {
244 colorUpdate(noof_configuration *bp, int i)
246 if (bp->hsv[i * 3 + 1] <= 0.5 && bp->hpr[i * 3 + 1] < 0.0)
247 bp->hpr[i * 3 + 1] = -bp->hpr[i * 3 + 1]; /* adjust s */
248 if (bp->hsv[i * 3 + 1] >= 1.0 && bp->hpr[i * 3 + 1] > 0.0)
249 bp->hpr[i * 3 + 1] = -bp->hpr[i * 3 + 1]; /* adjust s */
250 if (bp->hsv[i * 3 + 2] <= 0.4 && bp->hpr[i * 3 + 2] < 0.0)
251 bp->hpr[i * 3 + 2] = -bp->hpr[i * 3 + 2]; /* adjust s */
252 if (bp->hsv[i * 3 + 2] >= 1.0 && bp->hpr[i * 3 + 2] > 0.0)
253 bp->hpr[i * 3 + 2] = -bp->hpr[i * 3 + 2]; /* adjust s */
255 bp->hsv[i * 3] += bp->hpr[i * 3];
256 bp->hsv[i * 3 + 1] += bp->hpr[i * 3 + 1];
257 bp->hsv[i * 3 + 2] += bp->hpr[i * 3 + 2];
259 /* --- hsv -> rgb --- */
260 #define H(hhh) hhh[i*3 ]
261 #define S(hhh) hhh[i*3+1]
262 #define V(hhh) hhh[i*3+2]
264 #define R(hhh) hhh[i*3 ]
265 #define G(hhh) hhh[i*3+1]
266 #define B(hhh) hhh[i*3+2]
268 if (V(bp->hsv) < 0.0)
270 if (V(bp->hsv) > 1.0)
272 if (S(bp->hsv) <= 0.0) {
273 R(bp->col) = V(bp->hsv);
274 G(bp->col) = V(bp->hsv);
275 B(bp->col) = V(bp->hsv);
277 float f, h, p, q, t, v;
280 while (H(bp->hsv) < 0.0)
282 while (H(bp->hsv) >= 360.0)
285 if (S(bp->hsv) < 0.0)
287 if (S(bp->hsv) > 1.0)
290 h = H(bp->hsv) / 60.0;
294 p = V(bp->hsv) * (1 - S(bp->hsv));
295 q = V(bp->hsv) * (1 - S(bp->hsv) * f);
296 t = V(bp->hsv) * (1 - S(bp->hsv) * (1 - f));
302 } else if (hi == 1) {
306 } else if (hi == 2) {
310 } else if (hi == 3) {
314 } else if (hi == 4) {
327 gravity(noof_configuration *bp, float fx)
331 for (a = 0; a < N_SHAPES; a++) {
332 for (b = 0; b < a; b++) {
335 t = bp->pos[b * 3] - bp->pos[a * 3];
337 t = bp->pos[b * 3 + 1] - bp->pos[a * 3 + 1];
344 v0 = bp->pos[b * 3] - bp->pos[a * 3];
345 v1 = bp->pos[b * 3 + 1] - bp->pos[a * 3 + 1];
347 z = 0.00000001 * fx / (d2);
349 bp->dir[a * 3] += v0 * z * bp->sca[b];
350 bp->dir[b * 3] += -v0 * z * bp->sca[a];
351 bp->dir[a * 3 + 1] += v1 * z * bp->sca[b];
352 bp->dir[b * 3 + 1] += -v1 * z * bp->sca[a];
357 if(dir[a*3]*dir[a*3] + dir[a*3+1]*dir[a*3+1]
367 draw_noof (ModeInfo *mi)
370 noof_configuration *bp = &bps[MI_SCREEN(mi)];
372 if (!bp->glx_context)
374 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
377 if((random() & 0xff) == 0x34){
378 glClear(GL_COLOR_BUFFER_BIT);
381 if((tko & 0x1f) == 0x1f){
383 glColor4f(0.0, 0.0, 0.0, 0.09);
384 glRectf(0.0, 0.0, wd, ht);
393 for (i = 0; i < N_SHAPES; i++) {
399 if (mi->fps_p) do_fps (mi);
402 /* For some reason this hack screws up on Cocoa if we try to double-buffer it.
403 It looks fine single-buffered, so let's just do that. */
404 /* glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); */
409 reshape_noof(ModeInfo *mi, int w, int h)
411 noof_configuration *bp = &bps[MI_SCREEN(mi)];
412 glViewport(0, 0, w, h);
413 glMatrixMode(GL_PROJECTION);
417 bp->ht = (GLfloat) h / (GLfloat) w;
419 0.0, 1.0 * (GLfloat) h / (GLfloat) w,
422 bp->wd = (GLfloat) w / (GLfloat) h;
424 glOrtho(0.0, 1.0 * (GLfloat) w / (GLfloat) h,
428 glMatrixMode(GL_MODELVIEW);
431 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
435 init_noof (ModeInfo *mi)
438 noof_configuration *bp;
441 bps = (noof_configuration *)
442 calloc (MI_NUM_SCREENS(mi), sizeof (noof_configuration));
444 fprintf(stderr, "%s: out of memory\n", progname);
449 bp = &bps[MI_SCREEN(mi)];
451 bp->glx_context = init_GL(mi);
453 glDrawBuffer(GL_FRONT);
454 glClearColor(0.0, 0.0, 0.0, 1.0);
455 glEnable(GL_LINE_SMOOTH);
456 glShadeModel(GL_FLAT);
457 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
458 for (i = 0; i < N_SHAPES; i++)
460 reshape_noof (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
464 XSCREENSAVER_MODULE ("Noof", noof)