diff options
Diffstat (limited to 'hacks/glx/beats.c')
| -rw-r--r-- | hacks/glx/beats.c | 439 |
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 */ |
