summaryrefslogtreecommitdiffstats
path: root/hacks/glx/beats.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/glx/beats.c')
-rw-r--r--hacks/glx/beats.c439
1 files changed, 0 insertions, 439 deletions
diff --git a/hacks/glx/beats.c b/hacks/glx/beats.c
deleted file mode 100644
index 67a6eb8..0000000
--- a/hacks/glx/beats.c
+++ /dev/null
@@ -1,439 +0,0 @@
-/* beats, Copyright (c) 2020 David Eccles (gringer) <hacking@gringene.org>
- *
- * 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.
- */
-
-/* Beats changes the position of objects in time with a
- * synchronisation signal (or more correctly, based on the time
- * elapsed since the last synchronisation point). By default, the
- * system clock is used for this signal, with synchronisation
- * happening every minute. The location of objects is entirely
- * dependant on this synchronisation signal; there is no multi-object
- * state that needs to be stored, although there may be some styling
- * state required.
- */
-
-#define DEFAULTS "*count: 30 \n" \
- "*delay: 30000 \n" \
- "*showFPS: False \n" \
- "*wireframe: False \n" \
-
-# define release_beats 0
-
-#include "xlockmore.h"
-#include "colors.h"
-#include "sphere.h"
-#include "hsv.h"
-#include <ctype.h>
-#include <sys/time.h>
-
-#ifdef USE_GL /* whole file */
-
-#define DEF_CYCLE "-1"
-#define DEF_TICK "True"
-#define DEF_BLUR "True"
-
-#define SPHERE_SLICES 16 /* how densely to render spheres */
-#define SPHERE_STACKS 16
-
-
-typedef struct {
- GLXContext *glx_context;
- Bool button_down_p;
-
- GLuint beats_list;
-
- GLfloat pos;
-
- int ball_count; /* Number of balls */
- int preset_cycle; /* Cycle to show (-1 for random) */
- Bool use_tick; /* Add tick for clockwise / galaxy */
- Bool use_blur; /* Motion blur */
- int ncolors;
- XColor *colors;
- int ccolor;
- int color_shift;
-
-} beats_configuration;
-
-static beats_configuration *bps = NULL;
-
-static int cycle_arg;
-static Bool tick_arg;
-static Bool blur_arg;
-
-static XrmOptionDescRec opts[] = {
- { "-cycle", ".cycle", XrmoptionSepArg, 0 },
- { "-count", ".count", XrmoptionSepArg, 0 },
- { "-tick", ".tick", XrmoptionNoArg, "on" },
- { "+tick", ".tick", XrmoptionNoArg, "off" },
- { "-blur", ".blur", XrmoptionNoArg, "on" },
- { "+blur", ".blur", XrmoptionNoArg, "off" }
-};
-
-static argtype vars[] = {
- {&cycle_arg, "cycle", "Cycle", DEF_CYCLE, t_Int},
- {&tick_arg, "tick", "Tick", DEF_TICK, t_Bool},
- {&blur_arg, "blur", "Blur", DEF_BLUR, t_Bool}
-};
-
-static OptionStruct desc[] = {
- {"-count num", "number of balls"},
- {"-cycle num", "cycle / pattern type"},
- {"-/+tick", "enable/disable tick for clockwise and galaxy"},
- {"-/+blur", "enable/disable motion blur"}
-};
-
-ENTRYPOINT ModeSpecOpt beats_opts =
- {countof(opts), opts, countof(vars), vars, desc};
-
-/* Window management, etc
- */
-ENTRYPOINT void
-reshape_beats (ModeInfo *mi, int width, int height)
-{
- GLfloat h = (GLfloat) height / (GLfloat) width;
- int y = 0;
-
- if (width > height * 5) { /* tiny window: show middle */
- height = width * 9/16;
- y = -height/2;
- h = height / (GLfloat) width;
- }
-
- glViewport (0, y, (GLint) width, (GLint) height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective (30.0, 1/h, 1.0, 100.0);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- gluLookAt( 0.0, 0.0, 30.0,
- 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0);
-
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-
-ENTRYPOINT Bool
-beats_handle_event (ModeInfo *mi, XEvent *event)
-{
- return True;
-}
-
-static Bool getFracColour (GLfloat* retVal, float posFrac, float s){
- /* top: red, right: yellow, bottom: [dark] green, left: blue */
- /* note: fixed point; align to 0.1 degree increments */
- int theta, h, v;
- unsigned short r,g,b;
- theta = ((int)(posFrac * 3600) % 3600 + 3600) % 3600;
- v = 100;
- if ((theta >= 0) && (theta < 900)) {
- h = (theta * 600) / 900;
- } else if ((theta >= 900) && (theta < 1800)) {
- h = ((theta - 900) * 600) / 900 + 600;
- v = 100 - ((theta - 900) / 18);
- } else if ((theta >= 1800) && (theta < 2700)) {
- h = ((theta - 1800) * 1200) / 900 + 1200;
- v = ((theta - 1800) / 18) + 50;
- } else /* if ((theta >= 2700) && (theta < 3600))*/ {
- h = ((theta - 2700) * 1200) / 900 + 2400;
- }
- hsv_to_rgb((int)h / 10.0, s, v / 100.0, &r, &g, &b);
- retVal[0] = r / 65535.0;
- retVal[1] = g / 65535.0;
- retVal[2] = b / 65535.0;
- return True;
-}
-
-
-ENTRYPOINT void
-init_beats (ModeInfo *mi)
-{
- beats_configuration *bp;
- int wire = MI_IS_WIREFRAME(mi);
-
- MI_INIT (mi, bps);
- bp = &bps[MI_SCREEN(mi)];
-
- bp->glx_context = init_GL(mi);
-
- reshape_beats (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-
- if (!wire)
- {
- GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0};
- GLfloat amb[4] = {0.02, 0.02, 0.02, 1.0};
- GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
- GLfloat spc[4] = {0.2, 0.2, 0.2, 0.2};
-
- glEnable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
-
- glLightfv(GL_LIGHT0, GL_POSITION, pos);
- glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
- glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
-
- glEnable(GL_LIGHT0);
- }
-
- if (cycle_arg > 3) cycle_arg = -1;
-
- bp->ball_count = MI_COUNT(mi);
- if (bp->ball_count < 2) bp->ball_count = 2;
-
- bp->preset_cycle = cycle_arg;
- bp->use_tick = tick_arg;
- bp->use_blur = blur_arg;
-
-# ifdef HAVE_ANDROID
- bp->use_blur = False; /* Works on iOS but not Android */
-# endif
-
- bp->ncolors = 128;
- bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor));
- make_smooth_colormap (0, 0, 0,
- bp->colors, &bp->ncolors,
- False, 0, False);
-
- bp->beats_list = glGenLists(1);
-
- glNewList (bp->beats_list, GL_COMPILE);
- glScalef(0.71, 0.71, 0.71);
- unit_sphere (SPHERE_STACKS, SPHERE_SLICES, wire);
- glEndList ();
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-
-ENTRYPOINT void
-draw_beats (ModeInfo *mi)
-{
- beats_configuration *bp = &bps[MI_SCREEN(mi)];
- Display *dpy = MI_DISPLAY(mi);
- Window window = MI_WINDOW(mi);
- unsigned num_objects = bp->ball_count, oi;
- struct timeval tv, tvOrig;
- struct tm *now;
- Bool sineWaveTick = bp->use_tick;
- Bool motionBlur = bp->use_blur;
- size_t cycle, dist;
- unsigned int tmS, tmM, tmH, tmD;
- unsigned int timeSeed;
- int timeDelta = 0;
- size_t blurOffset = 10; /* offset per blur frame, in milliseconds */
- size_t framesPerBlur = 20; /* number of sub-frames to blur */
- size_t deltaLimit = (motionBlur) ? (blurOffset * framesPerBlur) : 1;
- float ballAlpha;
- float secFrac, minFrac, minProp, hourProp, halfDayProp,
- z, op, mp, m2m,
- theta, delta, blurFrac, oFP, pathLength;
-
- static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0};
- static const GLfloat bshiny = 92.0;
-
- GLfloat bcolor[4] = {0.85, 0.75, 0.75, 1.0};
-
- if (!bp->glx_context)
- return;
- gettimeofday (&tvOrig, NULL);
-
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
-
- glShadeModel(GL_SMOOTH);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_ALPHA_TEST);
- glEnable(GL_NORMALIZE);
- glEnable(GL_CULL_FACE);
- glEnable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glPushMatrix ();
- glRotatef(current_device_rotation(), 0, 0, 1);
-
- {
- GLfloat s = (MI_WIDTH(mi) < MI_HEIGHT(mi)
- ? MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi)
- : 1);
- glScalef (s, s, s);
- }
-
- /* timeDelta is in milliseconds */
- for(timeDelta = 0; timeDelta <= deltaLimit; timeDelta += blurOffset){
- if(timeDelta < blurOffset){
- /* glEnable(GL_DEPTH_TEST); */
- ballAlpha = 1.0;
- } else {
- /* glDisable(GL_DEPTH_TEST); */
- ballAlpha = 1.0 / framesPerBlur;
- }
- blurFrac = sin((1 - (float) timeDelta / deltaLimit) * M_PI_2) * ballAlpha;
- tv = tvOrig;
- now = localtime (&tv.tv_sec); /* This seems to be needed for seconds */
- tmS = now->tm_sec;
- tmM = now->tm_min;
- tmH = now->tm_hour;
- tmD = now->tm_yday;
- secFrac = ((tv.tv_usec % 1000000) - (timeDelta * 1000)) / (1e6);
- if(secFrac < 0){
- secFrac += 1;
- tmS--;
- if(tmS < 0){
- tmS += 60;
- tmM--;
- }
- if(tmM < 0){
- tmM += 60;
- tmH--;
- }
- if(tmH < 0){
- tmH += 24;
- tmD--;
- }
- if(tmD < 0){
- /* note: this won't be accurate for leap years, but the rare
- event logic is complex enough */
- tmD += 365;
- }
- }
- /* pseudo-random generator based on current minute */
- timeSeed = (((tmM+1) * (tmM+1) * ((tmH+1) * 37) *
- ((tmD+1) * 1151) * 1233599) % 653);
- cycle = timeSeed % 4;
- if(bp->preset_cycle != -1){
- cycle = bp->preset_cycle;
- }
- if(sineWaveTick && (cycle == 0 || cycle == 3)){
- Bool doTick = (timeSeed % 2 == 0);
- if(doTick){ /* choose to tick randomly */
- /* sine-wave 'tick' motion, converts linear 0..1 to
- pause/fast/pause 0..1 */
- secFrac = (1.0 - sin((0.5-secFrac) * M_PI))/2.0;
- }
- }
- minFrac = tmS / 60.0;
- /* now we have enough information to calculate our goal statistic,
- minProp: the position in the synchronisation cycle of one
- minute */
- minProp = (minFrac - trunc(minFrac)) + (secFrac / 60);
- m2m = minProp * 2 * M_PI;
-
- /* change colour based on the minute and hour */
- hourProp = tmM / 60.0 + minProp / 60.0;
- hourProp = hourProp - trunc(hourProp);
-
- halfDayProp = tmH / 12.0 + hourProp / 12.0;
- halfDayProp = halfDayProp - trunc(halfDayProp);
-
- mi->polygon_count = 0;
-
- for(oi = 0; oi < num_objects; oi++){
- glPushMatrix ();
- glScalef(1.1, 1.1, 1.1);
-
- /* Object Fraction Position - 0..1 depending on native Z order */
- oFP = oi * 1.0 / (num_objects - 1);
-
- /* set Z distance between [-3.5 .. 0.5] (common to all cycles) */
- z = (oFP) * 4.0 - 3.5;
-
- /* set colour (common to all cycles) */
- if(oFP < (1 / 3.0)){ /* "second" objects */
- getFracColour(bcolor, minProp, 1.0);
- } else if(oFP < (2 / 3.0)) { /* "minute" objects */
- getFracColour(bcolor, hourProp, 1.0);
- } else { /* "hour" objects */
- getFracColour(bcolor, halfDayProp, 1.0);
- }
-
- /* set x/y location */
- if(cycle == 0){
- /* clockwise */
- glRotatef(-minProp * 360 * (oi + 1), 0, 0, 1);
- glTranslatef(0, 5, 0);
- } else if(cycle == 1){
- /* rain dance */
- float y = 10 * cos(m2m * (oi + 1.0))/2;
- /* rotate around Y axis */
- glTranslatef(0, 0, -20);
- glRotatef(minProp * 360, 0, 1, 0);
- glTranslatef(0, y, 20);
- } else if(cycle == 2){
- /* metronome */
- theta = sin(-m2m * (oi + 1.0)) * 90;
- /* rotate around z axis at (-5, 0, 0) */
- glTranslatef(0, -5, 0);
- glRotatef(theta, 0, 0, 1);
- glTranslatef(0, 10, 0);
- } else if (cycle == 3){
- /* galaxy */
- mp = (num_objects - 1.0) / 2;
- op = mp - oi;
- dist = (int)(fabs(op)+0.5); /* dist from centre */
- /* make sure each object travels an integer number of loops in
- a path through one cycle */
- pathLength = (int)((60.0 / dist) + 0.5) * 720.0;
- delta = pathLength / 2;
- theta = -minProp * delta - 180;
- /* rotate around X axis after translating (0,-5,0) */
- glTranslatef(0, 0, -20);
- glRotatef(minProp * 360 - 180, 1, 0, 0);
- glTranslatef(0, 0, 20);
- glTranslatef(0, -5, 0);
- /* rotate around Y axis */
- glTranslatef(0, 0, -20);
- glRotatef(theta, 0, 1, 0);
- glTranslatef(0, 0, 20);
- }
-
- /* spread out based on Z position */
- glTranslatef(0, 0, (z - 0.5) * 10);
-
- /* set up colours */
- glMaterialfv (GL_FRONT, GL_SPECULAR, bspec);
- glMateriali (GL_FRONT, GL_SHININESS, bshiny);
- if(motionBlur){
- bcolor[3] = (timeDelta == 0) ? 1.0 : blurFrac; /* was ballAlpha */
- }
- glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bcolor);
- glCallList (bp->beats_list); /* draw sphere */
- mi->polygon_count += (SPHERE_SLICES * SPHERE_STACKS);
-
- glPopMatrix();
- }
- }
- glPopMatrix();
- if (mi->fps_p) do_fps (mi);
- glFinish();
- glXSwapBuffers(dpy, window);
-}
-
-
-ENTRYPOINT void
-free_beats (ModeInfo *mi)
-{
- beats_configuration *bp = &bps[MI_SCREEN(mi)];
- if (!bp->glx_context) return;
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
- if (bp->colors) free (bp->colors);
- if (glIsList(bp->beats_list)) glDeleteLists(bp->beats_list, 1);
-}
-
-XSCREENSAVER_MODULE ("Beats", beats)
-
-#endif /* USE_GL */