diff options
Diffstat (limited to 'hacks/glx/crumbler.c')
| -rw-r--r-- | hacks/glx/crumbler.c | 922 |
1 files changed, 0 insertions, 922 deletions
diff --git a/hacks/glx/crumbler.c b/hacks/glx/crumbler.c deleted file mode 100644 index fccee8d..0000000 --- a/hacks/glx/crumbler.c +++ /dev/null @@ -1,922 +0,0 @@ -/* crumbler, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.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. - */ - -#define DEFAULTS "*delay: 30000 \n" \ - "*showFPS: False \n" \ - "*wireframe: False \n" \ - "*suppressRotationAnimation: True\n" \ - -# define release_crumbler 0 - -#include "xlockmore.h" -#include "colors.h" -#include "rotator.h" -#include "quickhull.h" -#include "gltrackball.h" -#include <ctype.h> - -#ifdef USE_GL /* whole file */ - - -#define DEF_SPIN "True" -#define DEF_WANDER "True" -#define DEF_SPEED "1.0" -#define DEF_DENSITY "1.0" -#define DEF_FRACTURE "0" - -#undef RANDSIGN -#define RANDSIGN() ((random() & 1) ? 1 : -1) - -typedef struct { - qh_vertex_t *verts; /* interior point cloud */ - int nverts, onverts; - qh_vertex_t min, max; /* enclosing box */ - qh_vertex_t mid, vec; - int polygon_count; - GLuint dlist; - int color; - int color_shift; -} chunk; - -typedef struct { - GLXContext *glx_context; - rotator *rot; - trackball_state *trackball; - enum { IDLE, SPLIT, PAUSE, FLEE, ZOOM } state; - GLfloat tick; - Bool button_down_p; - int nchunks; - chunk **chunks; - chunk *ghost; - - int ncolors; - XColor *colors; -} crumbler_configuration; - -static crumbler_configuration *bps = NULL; - -static Bool do_spin; -static GLfloat speed; -static GLfloat density; -static int fracture; -static Bool do_wander; - -static XrmOptionDescRec opts[] = { - { "-spin", ".spin", XrmoptionNoArg, "True" }, - { "+spin", ".spin", XrmoptionNoArg, "False" }, - { "-speed", ".speed", XrmoptionSepArg, 0 }, - { "-density", ".density", XrmoptionSepArg, 0 }, - { "-fracture",".fracture",XrmoptionSepArg, 0 }, - { "-wander", ".wander", XrmoptionNoArg, "True" }, - { "+wander", ".wander", XrmoptionNoArg, "False" } -}; - -static argtype vars[] = { - {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool}, - {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, - {&speed, "speed", "Speed", DEF_SPEED, t_Float}, - {&density, "density", "Density", DEF_DENSITY, t_Float}, - {&fracture, "fracture","Fracture",DEF_FRACTURE,t_Int}, -}; - -ENTRYPOINT ModeSpecOpt crumbler_opts = {countof(opts), opts, countof(vars), vars, NULL}; - - -/* Create a roughly spherical cloud of N random points. - */ -static void -make_point_cloud (qh_vertex_t *verts, int nverts) -{ - int i = 0; - while (i < nverts) - { - verts[i].x = (0.5 - frand(1.0)); - verts[i].y = (0.5 - frand(1.0)); - verts[i].z = (0.5 - frand(1.0)); - if ((verts[i].x * verts[i].x + - verts[i].y * verts[i].y + - verts[i].z * verts[i].z) - < 0.25) - i++; - } -} - -static void crumbler_oom (void) -{ -# ifdef HAVE_JWXYZ - jwxyz_abort ("%s: out of memory, try reducing 'density'", progname); -# else - fprintf (stderr, "%s: out of memory, try reducing 'density'\n", progname); - exit (1); -# endif -} - - -static chunk * -make_chunk (void) -{ - chunk *c = (chunk *) calloc (1, sizeof(*c)); - if (!c) crumbler_oom(); - c->dlist = glGenLists (1); - c->color_shift = 1 + (random() % 3) * RANDSIGN(); - return c; -} - -/* Return False if out of memory */ -static Bool -render_chunk (ModeInfo *mi, chunk *c) -{ - int wire = MI_IS_WIREFRAME(mi); - int i, j; - qh_mesh_t m; - GLfloat d; - - if (c->nverts <= 3) - { - fprintf (stderr, "%s: nverts %d\n", progname, c->nverts); - abort(); - } - - c->polygon_count = 0; - c->min.x = c->min.y = c->min.z = 999999; - c->max.x = c->max.y = c->max.z = -999999; - - for (i = 0; i < c->nverts; i++) - { - if (c->verts[i].x < c->min.x) c->min.x = c->verts[i].x; - if (c->verts[i].y < c->min.y) c->min.y = c->verts[i].y; - if (c->verts[i].z < c->min.z) c->min.z = c->verts[i].z; - if (c->verts[i].x > c->max.x) c->max.x = c->verts[i].x; - if (c->verts[i].y > c->max.y) c->max.y = c->verts[i].y; - if (c->verts[i].z > c->max.z) c->max.z = c->verts[i].z; - } - - c->mid.x = (c->max.x + c->min.x) / 2; - c->mid.y = (c->max.y + c->min.y) / 2; - c->mid.z = (c->max.z + c->min.z) / 2; - - /* midpoint as normalized vector from origin */ - d = sqrt (c->mid.x * c->mid.x + - c->mid.y * c->mid.y + - c->mid.z * c->mid.z); - c->vec.x = c->mid.x / d; - c->vec.y = c->mid.y / d; - c->vec.z = c->mid.z / d; - - if (c->nverts <= 3) - { - fprintf (stderr, "%s: nverts %d\n", progname, c->nverts); - abort(); - } - - m = qh_quickhull3d (c->verts, c->nverts); - - if (!m.vertices) /* out of memory */ - { - qh_free_mesh (m); - return False; - } - - glNewList (c->dlist, GL_COMPILE); - if (! wire) glBegin (GL_TRIANGLES); - for (i = 0, j = 0; i < m.nindices; i += 3, j++) - { - qh_vertex_t *v0 = &m.vertices[m.indices[i+0]]; - qh_vertex_t *v1 = &m.vertices[m.indices[i+1]]; - qh_vertex_t *v2 = &m.vertices[m.indices[i+2]]; - qh_vec3_t *n = &m.normals[m.normalindices[j]]; - - if (i+2 >= m.nindices) abort(); - if (j >= m.nnormals) abort(); - - glNormal3f (n->x, n->y, n->z); - if (wire) glBegin(GL_LINE_LOOP); - glVertex3f (v0->x, v0->y, v0->z); - glVertex3f (v1->x, v1->y, v1->z); - glVertex3f (v2->x, v2->y, v2->z); - if (wire) glEnd(); - c->polygon_count++; - } - if (! wire) glEnd(); - - if (wire) - { - glPointSize (1); - glColor3f (0, 1, 0); - glBegin (GL_POINTS); - for (i = 0; i < c->nverts; i++) - { - if (i > 0 && i == c->onverts) - { - glEnd(); - glColor3f (1, 0, 0); - glBegin (GL_POINTS); - } - glVertex3f (c->verts[i].x, c->verts[i].y, c->verts[i].z); - } - glEnd(); - } - - glEndList(); - - qh_free_mesh (m); - return True; -} - - -static void -free_chunk (chunk *c) -{ - if (c->dlist) - glDeleteLists (c->dlist, 1); - free (c->verts); - free (c); -} - - -/* Make sure the chunk contains at least N points. - As we subdivide, the number of points is reduced. - This adds new points to the interior that do not - affect the shape of the outer hull. - */ -static void -pad_chunk (chunk *c, int min) -{ - /* Allocate a new array of size N - Copy the old points into it - while size < N - pick two random points - add a point that is somewhere along the line between them - (that point will still be inside the old hull) - */ - qh_vertex_t *verts; - int i; - if (c->nverts >= min) return; - if (c->nverts <= 3) abort(); - verts = (qh_vertex_t *) calloc (min, sizeof(*verts)); - if (!verts) crumbler_oom(); - memcpy (verts, c->verts, c->nverts * sizeof(*verts)); - i = c->nverts; - while (i < min) - { - qh_vertex_t v; - int j0, j1; - GLfloat r; - j0 = random() % c->nverts; - do { - j1 = random() % c->nverts; - } while (j0 == j1); - - r = 0.2 + frand(0.6); -# undef R -# define R(F) v.F = c->verts[j0].F + \ - r * (fabs (c->verts[j1].F - c->verts[j0].F)) \ - * (c->verts[j0].F > c->verts[j1].F ? -1 : 1) - R(x); - R(y); - R(z); -# undef R - - /* Sometimes quickhull.c is giving us concave and un-closed polygons. - Maybe it gets confused if there are duplicate points? So reject - this point if it is within epsilon of any earlier point. - */ -# if 0 /* Nope, that's not it. */ - { - Bool ok = True; - int j; - for (j = 0; j < i; j++) - { - - double X = c->verts[j].x - v.x; - double Y = c->verts[j].y - v.y; - double Z = c->verts[j].z - v.z; - double d2 = X*X + Y*Y + Z*Z; - if (d2 < 0.0001) - { - /* fprintf (stderr, "## REJ %f\n",d2); */ - ok = False; - break; - } - } - if (! ok) continue; - } -# endif - - verts[i++] = v; - } - -#if 0 - fprintf (stdout, " int n = %d;\n", min); - fprintf (stdout, " qh_vertex_t v[] = {"); - for (i = 0; i < min; i++) - fprintf(stdout,"{%f,%f,%f},", verts[i].x, verts[i].y, verts[i].z); - fprintf (stdout, "};\n\n"); -#endif - - free (c->verts); - c->verts = verts; - c->onverts = c->nverts; - c->nverts = min; - -#if 0 - qh_vertex_t *verts2 = (qh_vertex_t *) calloc (n, sizeof(*verts2)); - if (!verts2) crumbler_oom(); - memcpy (verts2, v, n * sizeof(*verts2)); - free (c->verts); - c->verts = verts2; - c->onverts = 0; - c->nverts = n; -#endif -} - - -/* Returns a list of N new chunks. - */ -static chunk ** -split_chunk (ModeInfo *mi, chunk *c, int nchunks) -{ - /* Pick N key-points from the cloud. - Create N new chunks. - For each old point: - It goes in chunk N if it is closest to key-point N. - Free old chunk. - for each new chunk - render_chunk - */ - crumbler_configuration *bp = &bps[MI_SCREEN(mi)]; - chunk **chunks; - int *keys; - int i, j; - int retries = 0; - - RETRY: - chunks = (chunk **) calloc (nchunks, sizeof(*chunks)); - if (!chunks) crumbler_oom(); - keys = (int *) calloc (nchunks, sizeof(*keys)); - if (!keys) crumbler_oom(); - - for (i = 0; i < nchunks; i++) - { - /* Fill keys with random numbers that are not duplicates. */ - Bool ok = True; - chunk *c2 = 0; - if (nchunks >= c->nverts) - { - fprintf (stderr, "%s: nverts %d nchunks %d\n", progname, - c->nverts, nchunks); - abort(); - } - do { - keys[i] = random() % c->nverts; - ok = True; - for (j = 0; j < i; j++) - if (keys[i] == keys[j]) - { - ok = False; - break; - } - } while (!ok); - - c2 = make_chunk(); - chunks[i] = c2; - chunks[i]->nverts = 0; - c2->verts = (qh_vertex_t *) calloc (c->nverts, sizeof(*c2->verts)); - if (!c2->verts) crumbler_oom(); - c2->color = (c->color + (random() % (1 + (bp->ncolors / 3)))) - % bp->ncolors; - } - - /* Add the verts to the approprate chunks - */ - for (i = 0; i < c->nverts; i++) - { - qh_vertex_t *v0 = &c->verts[i]; - int target_chunk = -1; - double target_d2 = 9999999; - chunk *c2 = 0; - - for (j = 0; j < nchunks; j++) - { - qh_vertex_t *v1 = &c->verts[keys[j]]; - double X = v1->x - v0->x; - double Y = v1->y - v0->y; - double Z = v1->z - v0->z; - double d2 = X*X + Y*Y + Z*Z; - if (d2 < target_d2) - { - target_d2 = d2; - target_chunk = j; - } - } - if (target_chunk == -1) abort(); - - c2 = chunks[target_chunk]; - c2->verts[c2->nverts++] = *v0; - if (c2->nverts > c->nverts) abort(); - } - - free (keys); - keys = 0; - - for (i = 0; i < nchunks; i++) - { - chunk *c2 = chunks[i]; - - /* It is possible that the keys we have chosen have resulted in one or - more cells that have 3 or fewer points in them. If that's the case, - re-randomize. - */ - if (c2->nverts <= 3) - { - for (j = 0; j < nchunks; j++) - free_chunk (chunks[j]); - free (chunks); - chunks = 0; - if (retries++ > 100) - { - fprintf(stderr, "%s: unsplittable\n", progname); - abort(); - } - goto RETRY; - } - - if (i == 0) /* The one we're gonna keep */ - pad_chunk (c2, c->nverts); - if (! render_chunk (mi, c2)) - crumbler_oom(); /* We are too far in to recover from this */ - } - - return chunks; -} - - -static void -tick_crumbler (ModeInfo *mi) -{ - crumbler_configuration *bp = &bps[MI_SCREEN(mi)]; - GLfloat ts; - - if (bp->button_down_p) return; - - switch (bp->state) { - case IDLE: ts = 0.02; break; - case SPLIT: ts = 0.01; break; - case PAUSE: ts = 0.008; break; - case FLEE: ts = 0.005; break; - case ZOOM: ts = 0.03; break; - default: abort(); break; - } - - bp->tick += ts * speed; - - if (bp->tick < 1) return; - - bp->tick = 0; - bp->state = (bp->state + 1) % (ZOOM + 1); - - switch (bp->state) { - case IDLE: - { - chunk *c = bp->chunks[0]; - int i; - - /* We already animated it zooming to full size. Now make it real. */ - GLfloat X = (c->max.x - c->min.x); - GLfloat Y = (c->max.y - c->min.y); - GLfloat Z = (c->max.z - c->min.z); - GLfloat s = 1 / MAX(X, MAX(Y, Z)); - - for (i = 0; i < c->nverts; i++) - { - c->verts[i].x *= s; - c->verts[i].y *= s; - c->verts[i].z *= s; - } - - /* Re-render it to move the verts in the display list too. - This also recomputes min, max and mid. - */ - if (! render_chunk (mi, c)) - crumbler_oom(); /* We are too far in to recover from this */ - break; - } - - case SPLIT: - { - chunk *c = bp->chunks[0]; - int frac = (fracture >= 2 ? fracture : 2 + (2 * (random() % 5))); - chunk **chunks = split_chunk (mi, c, frac); - if (bp->nchunks != 1) abort(); - if (bp->ghost) abort(); - bp->ghost = c; - free (bp->chunks); - bp->chunks = chunks; - bp->nchunks = frac; - break; - } - - case PAUSE: - break; - - case FLEE: - if (bp->ghost) free_chunk (bp->ghost); - bp->ghost = 0; - break; - - case ZOOM: - { - chunk *c = bp->chunks[0]; - int i; - for (i = 1; i < bp->nchunks; i++) - free_chunk (bp->chunks[i]); - bp->nchunks = 1; - - /* We already animated the remaining chunk moving toward the origin. - Make it real. - */ - for (i = 0; i < c->nverts; i++) - { - c->verts[i].x -= c->mid.x; - c->verts[i].y -= c->mid.y; - c->verts[i].z -= c->mid.z; - } - - /* Re-render it to move the verts in the display list too. - This also recomputes min, max and mid (now 0). - */ - if (! render_chunk (mi, c)) - crumbler_oom(); /* We are too far in to recover from this */ - break; - } - - default: abort(); break; - } -} - - -static GLfloat -ease_fn (GLfloat r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -static GLfloat -ease_ratio (GLfloat r) -{ - GLfloat ease = 0.35; - if (r <= 0) return 0; - else if (r >= 1) return 1; - else if (r <= ease) return ease * ease_fn (r / ease); - else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease); - else return r; -} - - -/* Window management, etc - */ -ENTRYPOINT void -reshape_crumbler (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); - - { - GLfloat s = (MI_WIDTH(mi) < MI_HEIGHT(mi) - ? (MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi)) - : 1); - glScalef (s, s, s); - } - - glClear(GL_COLOR_BUFFER_BIT); -} - - -ENTRYPOINT Bool -crumbler_handle_event (ModeInfo *mi, XEvent *event) -{ - crumbler_configuration *bp = &bps[MI_SCREEN(mi)]; - - if (gltrackball_event_handler (event, bp->trackball, - MI_WIDTH (mi), MI_HEIGHT (mi), - &bp->button_down_p)) - return True; - - return False; -} - - -ENTRYPOINT void -init_crumbler (ModeInfo *mi) -{ - crumbler_configuration *bp; - int wire = MI_IS_WIREFRAME(mi); - int i; - - MI_INIT (mi, bps); - bp = &bps[MI_SCREEN(mi)]; - - bp->glx_context = init_GL(mi); - - reshape_crumbler (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); - - if (!wire) - { - GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; - GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; - GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; - GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; - - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - 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_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - { - double spin_speed = 0.5 * speed; - double spin_accel = 0.3; - double wander_speed = 0.01 * speed; - - bp->rot = make_rotator (do_spin ? spin_speed : 0, - do_spin ? spin_speed : 0, - do_spin ? spin_speed : 0, - spin_accel, - do_wander ? wander_speed : 0, - True); - bp->trackball = gltrackball_init (True); - } - - bp->ncolors = 1024; - bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); - if (!bp->colors) crumbler_oom(); - make_smooth_colormap (0, 0, 0, - bp->colors, &bp->ncolors, - False, 0, False); - - /* brighter colors, please... */ - for (i = 0; i < bp->ncolors; i++) - { -# undef R -# define R(F) F = 65535 * (0.3 + 0.7 * ((F) / 65535.0)) - R (bp->colors[i].red); - R (bp->colors[i].green); - R (bp->colors[i].blue); -# undef R - } - - { - double d2 = density; - chunk *c; - - bp->nchunks = 1; - bp->chunks = (chunk **) calloc (bp->nchunks, sizeof(*bp->chunks)); - if (! bp->chunks) crumbler_oom(); - - c = make_chunk(); - if (! c) crumbler_oom(); - - bp->chunks[0] = c; - - while (1) - { - c->nverts = 4500 * d2; - c->verts = (qh_vertex_t *) calloc (c->nverts, sizeof(*c->verts)); - if (c->verts) - { - make_point_cloud (c->verts, c->nverts); - - /* Let's shrink it to a point then zoom in. */ - bp->state = ZOOM; - bp->tick = 0; - for (i = 0; i < c->nverts; i++) - { - c->verts[i].x /= 500; - c->verts[i].y /= 500; - c->verts[i].z /= 500; - } - - if (! render_chunk (mi, c)) - { - free (c->verts); - c->verts = 0; - } - } - - if (c->verts) - break; - - if (d2 < 0.1) - crumbler_oom(); - d2 *= 0.9; - } - - if (density != d2) - fprintf (stderr, - "%s: out of memory: reduced density from %.01f to %0.1f\n", - progname, density, d2); - } -} - - -static void -draw_chunk (ModeInfo *mi, chunk *c, GLfloat alpha) -{ - crumbler_configuration *bp = &bps[MI_SCREEN(mi)]; - GLfloat color[4]; - - color[0] = bp->colors[c->color].red / 65536.0; - color[1] = bp->colors[c->color].green / 65536.0; - color[2] = bp->colors[c->color].blue / 65536.0; - color[3] = alpha; - glColor4fv (color); - glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); - - c->color += c->color_shift; - while (c->color < 0) c->color += bp->ncolors; - while (c->color >= bp->ncolors) c->color -= bp->ncolors; - - glCallList (c->dlist); - mi->polygon_count += c->polygon_count; -} - - -ENTRYPOINT void -draw_crumbler (ModeInfo *mi) -{ - int wire = MI_IS_WIREFRAME(mi); - crumbler_configuration *bp = &bps[MI_SCREEN(mi)]; - Display *dpy = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - GLfloat alpha = 1; - int i; - - static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0}; - static const GLfloat bshiny = 128.0; - - if (!bp->glx_context) - return; - - glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context); - - tick_crumbler (mi); - - glShadeModel(GL_SMOOTH); - glEnable(GL_DEPTH_TEST); - glEnable(GL_NORMALIZE); - glEnable(GL_CULL_FACE); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glPushMatrix (); - - { - double x, y, z; - get_position (bp->rot, &x, &y, &z, !bp->button_down_p); - glTranslatef((x - 0.5) * 8, - (y - 0.5) * 8, - (z - 0.5) * 15); - - gltrackball_rotate (bp->trackball); - - get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p); - glRotatef (x * 360, 1.0, 0.0, 0.0); - glRotatef (y * 360, 0.0, 1.0, 0.0); - glRotatef (z * 360, 0.0, 0.0, 1.0); - } - - mi->polygon_count = 0; - - glMaterialfv (GL_FRONT, GL_SPECULAR, bspec); - glMateriali (GL_FRONT, GL_SHININESS, bshiny); - - if (do_wander) - glScalef (10, 10, 10); - else - glScalef (13, 13, 13); - - alpha = 1; - for (i = 0; i < bp->nchunks; i++) - { - chunk *c = bp->chunks[i]; - - glPushMatrix(); - - switch (bp->state) { - case FLEE: - { - GLfloat r = ease_ratio (bp->tick); - /* Move everybody toward the origin, so that chunk #0 ends up - centered there. */ - glTranslatef (-r * c->mid.x, - -r * c->mid.y, - -r * c->mid.z); - if (i != 0) - { - /* Move this chunk away from the center, along a vector from - the origin to its midpoint. */ - GLfloat d2 = r * 6; - glTranslatef (c->vec.x * d2, c->vec.y * d2, c->vec.z * d2); - alpha = 1 - r; - } - } - break; - - case ZOOM: - { - chunk *c = bp->chunks[0]; - GLfloat X = (c->max.x - c->min.x); - GLfloat Y = (c->max.y - c->min.y); - GLfloat Z = (c->max.z - c->min.z); - GLfloat size0 = MAX(X, MAX(Y, Z)); - GLfloat size1 = 1.0; - GLfloat r = 1 - ease_ratio (bp->tick); - GLfloat s = 1 / (size0 + r * (size1 - size0)); - glScalef (s, s, s); - } - break; - - default: - break; - } - - draw_chunk (mi, c, alpha); - glPopMatrix(); - } - - /* Draw the old one, fading out. */ - if (!wire && bp->state == SPLIT && bp->ghost) - { - GLfloat s; - /* alpha = 1 - bp->tick; */ - alpha = 1; - /* s = 0.7 + (0.3 * ease_ratio (1-bp->tick)); */ - s = 2 * ease_ratio ((1-bp->tick) / 2); - s *= 1.01; - glScalef (s, s, s); - draw_chunk (mi, bp->ghost, alpha); - } - - glPopMatrix (); - - if (mi->fps_p) do_fps (mi); - glFinish(); - - glXSwapBuffers(dpy, window); -} - - -ENTRYPOINT void -free_crumbler (ModeInfo *mi) -{ - crumbler_configuration *bp = &bps[MI_SCREEN(mi)]; - int i; - if (!bp->glx_context) return; - glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context); - if (bp->trackball) gltrackball_free (bp->trackball); - if (bp->rot) free_rotator (bp->rot); - if (bp->colors) free (bp->colors); - for (i = 0; i < bp->nchunks; i++) - free_chunk (bp->chunks[i]); - if (bp->chunks) free (bp->chunks); -} - - -XSCREENSAVER_MODULE ("Crumbler", crumbler) - -#endif /* USE_GL */ |
