summaryrefslogtreecommitdiffstats
path: root/hacks/glx/noof.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/glx/noof.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'hacks/glx/noof.c')
-rw-r--r--hacks/glx/noof.c519
1 files changed, 519 insertions, 0 deletions
diff --git a/hacks/glx/noof.c b/hacks/glx/noof.c
new file mode 100644
index 0000000..4e42840
--- /dev/null
+++ b/hacks/glx/noof.c
@@ -0,0 +1,519 @@
+/* noof, Copyright (c) 2004-2018 Bill Torzewski <billt@worksitez.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * Originally a demo included with GLUT;
+ * (Apparently this was called "diatoms" on Irix.)
+ * ported to raw GL and xscreensaver by jwz, 12-Feb-2004.
+ */
+
+#define DEFAULTS "*delay: 10000 \n" \
+ "*showFPS: False \n" \
+ "*fpsSolid: True \n" \
+ "*doubleBuffer: False \n" \
+ "*suppressRotationAnimation: True\n" \
+
+# define free_noof 0
+# define release_noof 0
+# define noof_handle_event 0
+#include "xlockmore.h"
+#include "pow2.h"
+
+#ifdef USE_GL /* whole file */
+
+#define N_SHAPES 7
+
+ENTRYPOINT ModeSpecOpt noof_opts = {0, NULL, 0, NULL, NULL};
+
+typedef struct {
+ GLXContext *glx_context;
+
+ float pos[N_SHAPES * 3];
+ float dir[N_SHAPES * 3];
+ float acc[N_SHAPES * 3];
+ float col[N_SHAPES * 3];
+ float hsv[N_SHAPES * 3];
+ float hpr[N_SHAPES * 3];
+ float ang[N_SHAPES];
+ float spn[N_SHAPES];
+ float sca[N_SHAPES];
+ float geep[N_SHAPES];
+ float peep[N_SHAPES];
+ float speedsq[N_SHAPES];
+ int blad[N_SHAPES];
+
+ float ht, wd;
+
+ int tko;
+
+ GLuint screenshot_texture, tex_w, tex_h;
+
+} noof_configuration;
+
+static noof_configuration *bps = NULL;
+
+
+static void
+initshapes(noof_configuration *bp, int i)
+{
+ int k;
+ float f;
+
+ /* random init of pos, dir, color */
+ for (k = i * 3; k <= i * 3 + 2; k++) {
+ f = random() / (double) RAND_MAX;
+ bp->pos[k] = f;
+ f = random() / (double) RAND_MAX;
+ f = (f - 0.5) * 0.05;
+ bp->dir[k] = f;
+ f = random() / (double) RAND_MAX;
+ f = (f - 0.5) * 0.0002;
+ bp->acc[k] = f;
+ f = random() / (double) RAND_MAX;
+ bp->col[k] = f;
+ }
+
+ bp->speedsq[i] = bp->dir[i * 3] * bp->dir[i * 3] + bp->dir[i * 3 + 1] * bp->dir[i * 3 + 1];
+ f = random() / (double) RAND_MAX;
+ bp->blad[i] = 2 + (int) (f * 17.0);
+ f = random() / (double) RAND_MAX;
+ bp->ang[i] = f;
+ f = random() / (double) RAND_MAX;
+ bp->spn[i] = (f - 0.5) * 40.0 / (10 + bp->blad[i]);
+ f = random() / (double) RAND_MAX;
+ bp->sca[i] = (f * 0.1 + 0.08);
+ bp->dir[i * 3] *= bp->sca[i];
+ bp->dir[i * 3 + 1] *= bp->sca[i];
+
+ f = random() / (double) RAND_MAX;
+ bp->hsv[i * 3] = f * 360.0;
+
+ f = random() / (double) RAND_MAX;
+ bp->hsv[i * 3 + 1] = f * 0.6 + 0.4;
+
+ f = random() / (double) RAND_MAX;
+ bp->hsv[i * 3 + 2] = f * 0.7 + 0.3;
+
+ f = random() / (double) RAND_MAX;
+ bp->hpr[i * 3] = f * 0.005 * 360.0;
+ f = random() / (double) RAND_MAX;
+ bp->hpr[i * 3 + 1] = f * 0.03;
+ f = random() / (double) RAND_MAX;
+ bp->hpr[i * 3 + 2] = f * 0.02;
+
+ bp->geep[i] = 0;
+ f = random() / (double) RAND_MAX;
+ bp->peep[i] = 0.01 + f * 0.2;
+}
+
+static const float bladeratio[] =
+{
+ /* nblades = 2..7 */
+ 0.0, 0.0, 3.00000, 1.73205, 1.00000, 0.72654, 0.57735, 0.48157,
+ /* 8..13 */
+ 0.41421, 0.36397, 0.19076, 0.29363, 0.26795, 0.24648,
+ /* 14..19 */
+ 0.22824, 0.21256, 0.19891, 0.18693, 0.17633, 0.16687,
+};
+
+static int
+drawleaf(noof_configuration *bp, int l)
+{
+ int polys = 0;
+ int b, blades;
+ float x, y;
+ float wobble;
+
+ blades = bp->blad[l];
+
+ y = 0.10 * sin(bp->geep[l] * M_PI / 180.0) + 0.099 * sin(bp->geep[l] * 5.12 * M_PI / 180.0);
+ if (y < 0)
+ y = -y;
+ x = 0.15 * cos(bp->geep[l] * M_PI / 180.0) + 0.149 * cos(bp->geep[l] * 5.12 * M_PI / 180.0);
+ if (x < 0.0)
+ x = 0.0 - x;
+ if (y < 0.001 && x > 0.000002 && ((bp->tko & 0x1) == 0)) {
+ initshapes(bp, l); /* let it become reborn as something
+ else */
+ bp->tko++;
+ return polys;
+ } {
+ float w1 = sin(bp->geep[l] * 15.3 * M_PI / 180.0);
+ wobble = 3.0 + 2.00 * sin(bp->geep[l] * 0.4 * M_PI / 180.0) + 3.94261 * w1;
+ }
+
+ /**
+ if(blades == 2) if (y > 3.000*x) y = x*3.000;
+ if(blades == 3) if (y > 1.732*x) y = x*1.732;
+ if(blades == 4) if (y > x) y = x;
+ if(blades == 5) if (y > 0.726*x) y = x*0.726;
+ if(blades == 6) if (y > 0.577*x) y = x*0.577;
+ if(blades == 7) if (y > 0.481*x) y = x*0.481;
+ if(blades == 8) if (y > 0.414*x) y = x*0.414;
+ */
+ if (y > x * bladeratio[blades])
+ y = x * bladeratio[blades];
+
+ for (b = 0; b < blades; b++) {
+ glPushMatrix();
+ glTranslatef(bp->pos[l * 3], bp->pos[l * 3 + 1], bp->pos[l * 3 + 2]);
+ glRotatef(bp->ang[l] + b * (360.0 / blades), 0.0, 0.0, 1.0);
+ glScalef(wobble * bp->sca[l], wobble * bp->sca[l], wobble * bp->sca[l]);
+ /**
+ if(tko & 0x40000) glColor3f(col[l*3], col[l*3+1], col[l*3+2]);
+ else
+ */
+ glColor4ub(0, 0, 0, 0x60);
+
+ /* constrain geep cooridinates here XXX */
+ glEnable(GL_BLEND);
+
+ glBegin(GL_TRIANGLE_STRIP);
+ glVertex2f(x * bp->sca[l], 0.0);
+ glVertex2f(x, y);
+ glVertex2f(x, -y); /* C */
+ glVertex2f(0.3, 0.0); /* D */
+ polys += 2;
+ glEnd();
+
+ /**
+ if(tko++ & 0x40000) glColor3f(0,0,0);
+ else
+ */
+ glColor3f(bp->col[l * 3], bp->col[l * 3 + 1], bp->col[l * 3 + 2]);
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(x * bp->sca[l], 0.0);
+ glVertex2f(x, y);
+ glVertex2f(0.3, 0.0); /* D */
+ glVertex2f(x, -y); /* C */
+ polys += 3;
+ glEnd();
+ glDisable(GL_BLEND);
+
+ glPopMatrix();
+ }
+ return polys;
+}
+
+static void
+motionUpdate(noof_configuration *bp, int t)
+{
+ if (bp->pos[t * 3] < -bp->sca[t] * bp->wd && bp->dir[t * 3] < 0.0) {
+ bp->dir[t * 3] = -bp->dir[t * 3];
+ /**
+ acc[t*3+1] += 0.8*acc[t*3];
+ acc[t*3] = -0.8*acc[t*3];
+ */
+ } else if (bp->pos[t * 3] > (1 + bp->sca[t]) * bp->wd && bp->dir[t * 3] > 0.0) {
+ bp->dir[t * 3] = -bp->dir[t * 3];
+ /**
+ acc[t*3+1] += 0.8*acc[t*3];
+ acc[t*3] = -0.8*acc[t*3];
+ */
+ } else if (bp->pos[t * 3 + 1] < -bp->sca[t] * bp->ht && bp->dir[t * 3 + 1] < 0.0) {
+ bp->dir[t * 3 + 1] = -bp->dir[t * 3 + 1];
+ /**
+ acc[t*3] += 0.8*acc[t*3+1];
+ acc[t*3+1] = -0.8*acc[t*3+1];
+ */
+ } else if (bp->pos[t * 3 + 1] > (1 + bp->sca[t]) * bp->ht && bp->dir[t * 3 + 1] > 0.0) {
+ bp->dir[t * 3 + 1] = -bp->dir[t * 3 + 1];
+ /**
+ acc[t*3] += 0.8*acc[t*3+1];
+ acc[t*3+1] = -0.8*acc[t*3+1];
+ */
+ }
+
+ bp->pos[t * 3] += bp->dir[t * 3];
+ bp->pos[t * 3 + 1] += bp->dir[t * 3 + 1];
+ /**
+ dir[t*3] += acc[t*3];
+ dir[t*3+1] += acc[t*3+1];
+ */
+ bp->ang[t] += bp->spn[t];
+ bp->geep[t] += bp->peep[t];
+ if (bp->geep[t] > 360 * 5.0)
+ bp->geep[t] -= 360 * 5.0;
+ if (bp->ang[t] < 0.0) {
+ bp->ang[t] += 360.0;
+ }
+ if (bp->ang[t] > 360.0) {
+ bp->ang[t] -= 360.0;
+ }
+}
+
+static void
+colorUpdate(noof_configuration *bp, int i)
+{
+ if (bp->hsv[i * 3 + 1] <= 0.5 && bp->hpr[i * 3 + 1] < 0.0)
+ bp->hpr[i * 3 + 1] = -bp->hpr[i * 3 + 1]; /* adjust s */
+ if (bp->hsv[i * 3 + 1] >= 1.0 && bp->hpr[i * 3 + 1] > 0.0)
+ bp->hpr[i * 3 + 1] = -bp->hpr[i * 3 + 1]; /* adjust s */
+ if (bp->hsv[i * 3 + 2] <= 0.4 && bp->hpr[i * 3 + 2] < 0.0)
+ bp->hpr[i * 3 + 2] = -bp->hpr[i * 3 + 2]; /* adjust s */
+ if (bp->hsv[i * 3 + 2] >= 1.0 && bp->hpr[i * 3 + 2] > 0.0)
+ bp->hpr[i * 3 + 2] = -bp->hpr[i * 3 + 2]; /* adjust s */
+
+ bp->hsv[i * 3] += bp->hpr[i * 3];
+ bp->hsv[i * 3 + 1] += bp->hpr[i * 3 + 1];
+ bp->hsv[i * 3 + 2] += bp->hpr[i * 3 + 2];
+
+ /* --- hsv -> rgb --- */
+#define H(hhh) hhh[i*3 ]
+#define S(hhh) hhh[i*3+1]
+#define V(hhh) hhh[i*3+2]
+
+#define R(hhh) hhh[i*3 ]
+#define G(hhh) hhh[i*3+1]
+#define B(hhh) hhh[i*3+2]
+
+ if (V(bp->hsv) < 0.0)
+ V(bp->hsv) = 0.0;
+ if (V(bp->hsv) > 1.0)
+ V(bp->hsv) = 1.0;
+ if (S(bp->hsv) <= 0.0) {
+ R(bp->col) = V(bp->hsv);
+ G(bp->col) = V(bp->hsv);
+ B(bp->col) = V(bp->hsv);
+ } else {
+ float f, h, p, q, t, v;
+ int hi;
+
+ while (H(bp->hsv) < 0.0)
+ H(bp->hsv) += 360.0;
+ while (H(bp->hsv) >= 360.0)
+ H(bp->hsv) -= 360.0;
+
+ if (S(bp->hsv) < 0.0)
+ S(bp->hsv) = 0.0;
+ if (S(bp->hsv) > 1.0)
+ S(bp->hsv) = 1.0;
+
+ h = H(bp->hsv) / 60.0;
+ hi = (int) (h);
+ f = h - hi;
+ v = V(bp->hsv);
+ p = V(bp->hsv) * (1 - S(bp->hsv));
+ q = V(bp->hsv) * (1 - S(bp->hsv) * f);
+ t = V(bp->hsv) * (1 - S(bp->hsv) * (1 - f));
+
+ if (hi <= 0) {
+ R(bp->col) = v;
+ G(bp->col) = t;
+ B(bp->col) = p;
+ } else if (hi == 1) {
+ R(bp->col) = q;
+ G(bp->col) = v;
+ B(bp->col) = p;
+ } else if (hi == 2) {
+ R(bp->col) = p;
+ G(bp->col) = v;
+ B(bp->col) = t;
+ } else if (hi == 3) {
+ R(bp->col) = p;
+ G(bp->col) = q;
+ B(bp->col) = v;
+ } else if (hi == 4) {
+ R(bp->col) = t;
+ G(bp->col) = p;
+ B(bp->col) = v;
+ } else {
+ R(bp->col) = v;
+ G(bp->col) = p;
+ B(bp->col) = q;
+ }
+ }
+}
+
+static void
+gravity(noof_configuration *bp, float fx)
+{
+ int a, b;
+
+ for (a = 0; a < N_SHAPES; a++) {
+ for (b = 0; b < a; b++) {
+ float t, d2;
+
+ t = bp->pos[b * 3] - bp->pos[a * 3];
+ d2 = t * t;
+ t = bp->pos[b * 3 + 1] - bp->pos[a * 3 + 1];
+ d2 += t * t;
+ if (d2 < 0.000001)
+ d2 = 0.00001;
+ if (d2 < 0.1) {
+
+ float v0, v1, z;
+ v0 = bp->pos[b * 3] - bp->pos[a * 3];
+ v1 = bp->pos[b * 3 + 1] - bp->pos[a * 3 + 1];
+
+ z = 0.00000001 * fx / (d2);
+
+ bp->dir[a * 3] += v0 * z * bp->sca[b];
+ bp->dir[b * 3] += -v0 * z * bp->sca[a];
+ bp->dir[a * 3 + 1] += v1 * z * bp->sca[b];
+ bp->dir[b * 3 + 1] += -v1 * z * bp->sca[a];
+
+ }
+ }
+ /** apply brakes
+ if(dir[a*3]*dir[a*3] + dir[a*3+1]*dir[a*3+1]
+ > 0.0001) {
+ dir[a*3] *= 0.9;
+ dir[a*3+1] *= 0.9;
+ }
+ */
+ }
+}
+
+ENTRYPOINT void
+draw_noof (ModeInfo *mi)
+{
+ int i;
+ noof_configuration *bp = &bps[MI_SCREEN(mi)];
+
+ if (!bp->glx_context)
+ return;
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* In the olden days, one could just render directly into the front buffer,
+ or fail to clear the back buffer and assume that one's bits were still
+ there. Not so on modern devices, particularly mobile. So to achieve
+ the effect of frame N+1 accumulating atop frame N, we must save and
+ restore a screenshot of frame N.
+ */
+ if (bp->screenshot_texture)
+ {
+ GLfloat tw = MI_WIDTH(mi) / (GLfloat) bp->tex_w;
+ GLfloat th = MI_HEIGHT(mi) / (GLfloat) bp->tex_h;
+ glDisable (GL_BLEND);
+ glEnable (GL_TEXTURE_2D);
+ glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glBegin (GL_QUADS);
+ glTexCoord2f (0, 0); glVertex3f (0, 0, 0);
+ glTexCoord2f (tw, 0); glVertex3f (bp->wd, 0, 0);
+ glTexCoord2f (tw, th); glVertex3f (bp->wd, bp->ht, 0);
+ glTexCoord2f (0, th); glVertex3f (0, bp->ht, 0);
+ glEnd();
+ glDisable (GL_TEXTURE_2D);
+ glClear (GL_DEPTH_BUFFER_BIT);
+ }
+
+ mi->polygon_count = 0;
+
+ /**
+ if((random() & 0xff) == 0x34){
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ if((tko & 0x1f) == 0x1f){
+ glEnable(GL_BLEND);
+ glColor4f(0.0, 0.0, 0.0, 0.09);
+ glRectf(0.0, 0.0, wd, ht);
+ glDisable(GL_BLEND);
+#ifdef __sgi
+ sginap(0);
+#endif
+ }
+ */
+
+ gravity(bp, -2.0);
+ for (i = 0; i < N_SHAPES; i++) {
+ motionUpdate(bp, i);
+ colorUpdate(bp, i);
+ mi->polygon_count += drawleaf(bp, i);
+ }
+
+ if (bp->screenshot_texture) /* Store a screenshot into the texture. */
+ {
+ glDisable (GL_BLEND);
+ glEnable (GL_TEXTURE_2D);
+ glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture);
+ glCopyTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 0, 0,
+ MI_WIDTH(mi), MI_HEIGHT(mi));
+ check_gl_error("screenshot texture");
+ glDisable (GL_TEXTURE_2D);
+ }
+
+ if (mi->fps_p) do_fps (mi);
+ glFinish();
+
+ glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi));
+}
+
+
+ENTRYPOINT void
+reshape_noof(ModeInfo *mi, int w, int h)
+{
+ noof_configuration *bp = &bps[MI_SCREEN(mi)];
+ char *s;
+ glViewport(0, 0, w, h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ if (w <= h) {
+ bp->wd = 1.0;
+ bp->ht = (GLfloat) h / (GLfloat) w;
+ glOrtho(0.0, 1.0,
+ 0.0, 1.0 * (GLfloat) h / (GLfloat) w,
+ -16.0, 4.0);
+ } else {
+ bp->wd = (GLfloat) w / (GLfloat) h;
+ bp->ht = 1.0;
+ glOrtho(0.0, 1.0 * (GLfloat) w / (GLfloat) h,
+ 0.0, 1.0,
+ -16.0, 4.0);
+ }
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ if (!bp->screenshot_texture)
+ glGenTextures (1, &bp->screenshot_texture);
+
+ glEnable (GL_TEXTURE_2D);
+ glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture);
+
+ bp->tex_w = to_pow2 (MI_WIDTH(mi));
+ bp->tex_h = to_pow2 (MI_HEIGHT(mi));
+ s = calloc (4, bp->tex_w * bp->tex_h); /* init with black */
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, bp->tex_w, bp->tex_h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, s);
+ check_gl_error ("texture generation");
+ free (s);
+ glDisable (GL_TEXTURE_2D);
+ glClear (GL_COLOR_BUFFER_BIT);
+}
+
+ENTRYPOINT void
+init_noof (ModeInfo *mi)
+{
+ int i;
+ noof_configuration *bp;
+
+ MI_INIT (mi, bps);
+
+ bp = &bps[MI_SCREEN(mi)];
+
+ bp->glx_context = init_GL(mi);
+
+ glEnable(GL_LINE_SMOOTH);
+ glShadeModel(GL_FLAT);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ for (i = 0; i < N_SHAPES; i++)
+ initshapes(bp, i);
+
+ reshape_noof (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+}
+
+
+XSCREENSAVER_MODULE ("Noof", noof)
+
+#endif /* USE_GL */