summaryrefslogtreecommitdiffstats
path: root/hacks/glx/lament.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/glx/lament.c')
-rw-r--r--hacks/glx/lament.c1800
1 files changed, 0 insertions, 1800 deletions
diff --git a/hacks/glx/lament.c b/hacks/glx/lament.c
deleted file mode 100644
index 87e3575..0000000
--- a/hacks/glx/lament.c
+++ /dev/null
@@ -1,1800 +0,0 @@
-/* xscreensaver, Copyright (c) 1998-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.
- */
-
-/* Animates Lemarchand's Box, the Lament Configuration. By jwz, 25-Jul-98.
-
- TODO:
-
- * The gold leaf should appear to be raised up from the surface, but
- I think this isn't possible with OpenGL. No bump maps.
-
- * There should be strange lighting effects playing across the surface:
- electric sparks, or little glittery blobs of light. Maybe like
- http://www.opengl.org/archives/resources/features/KilgardTechniques/
- LensFlare/
-
- * Chains.
-
- * Needs music. ("Hellraiser Themes" by Coil: TORSO CD161; also
- duplicated on the "Unnatural History 2" compilation, WORLN M04699.)
- */
-
-#define DEFAULTS "*delay: 20000 \n" \
- "*showFPS: False \n" \
- "*wireframe: False \n" \
- "*suppressRotationAnimation: True\n" \
-
-# define release_lament 0
-#include "xlockmore.h"
-
-#ifdef USE_GL /* whole file */
-
-#include "gllist.h"
-
-/* #define DEBUG_MODE LAMENT_LEVIATHAN_COLLAPSE */
-
-#undef MAX
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-#undef MIN
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-
-extern const struct gllist
- *lament_model_box,
- *lament_model_iso_base_a,
- *lament_model_iso_base_b,
- *lament_model_iso_den,
- *lament_model_iso_dse,
- *lament_model_iso_dwn,
- *lament_model_iso_swd,
- *lament_model_iso_une,
- *lament_model_iso_unw,
- *lament_model_iso_use,
- *lament_model_iso_usw,
- *lament_model_leviathan,
- *lament_model_lid_a,
- *lament_model_lid_b,
- *lament_model_lid_base,
- *lament_model_lid_c,
- *lament_model_lid_d,
- *lament_model_pillar_a,
- *lament_model_pillar_b,
- *lament_model_pillar_base,
- *lament_model_star_d,
- *lament_model_star_u,
- *lament_model_taser_a,
- *lament_model_taser_b,
- *lament_model_taser_base,
- *lament_model_tetra_base,
- *lament_model_tetra_dse,
- *lament_model_tetra_dwn,
- *lament_model_tetra_une,
- *lament_model_tetra_usw;
-
-static const struct gllist * const *all_objs[] = {
- &lament_model_box,
- &lament_model_iso_base_a,
- &lament_model_iso_base_b,
- &lament_model_iso_den,
- &lament_model_iso_dse,
- &lament_model_iso_dwn,
- &lament_model_iso_swd,
- &lament_model_iso_une,
- &lament_model_iso_unw,
- &lament_model_iso_use,
- &lament_model_iso_usw,
- &lament_model_leviathan,
- &lament_model_lid_a,
- &lament_model_lid_b,
- &lament_model_lid_base,
- &lament_model_lid_c,
- &lament_model_lid_d,
- &lament_model_pillar_a,
- &lament_model_pillar_b,
- &lament_model_pillar_base,
- &lament_model_star_d,
- &lament_model_star_u,
- &lament_model_taser_a,
- &lament_model_taser_b,
- &lament_model_taser_base,
- &lament_model_tetra_base,
- &lament_model_tetra_dse,
- &lament_model_tetra_dwn,
- &lament_model_tetra_une,
- &lament_model_tetra_usw
-};
-
-typedef enum { /* must be in the same order as in `all_objs'. */
- OBJ_BOX = 0,
- OBJ_ISO_BASE_A,
- OBJ_ISO_BASE_B,
- OBJ_ISO_DEN,
- OBJ_ISO_DSE,
- OBJ_ISO_DWN,
- OBJ_ISO_SWD,
- OBJ_ISO_UNE,
- OBJ_ISO_UNW,
- OBJ_ISO_USE,
- OBJ_ISO_USW,
- OBJ_LEVIATHAN,
- OBJ_LID_A,
- OBJ_LID_B,
- OBJ_LID_BASE,
- OBJ_LID_C,
- OBJ_LID_D,
- OBJ_PILLAR_A,
- OBJ_PILLAR_B,
- OBJ_PILLAR_BASE,
- OBJ_STAR_D,
- OBJ_STAR_U,
- OBJ_TASER_A,
- OBJ_TASER_B,
- OBJ_TASER_BASE,
- OBJ_TETRA_BASE,
- OBJ_TETRA_DSE,
- OBJ_TETRA_DWN,
- OBJ_TETRA_UNE,
- OBJ_TETRA_USW
-} lament_obj_index;
-
-
-#define DEF_TEXTURE "True"
-
-static int do_texture;
-
-static XrmOptionDescRec opts[] = {
- {"-texture", ".lament.texture", XrmoptionNoArg, "true" },
- {"+texture", ".lament.texture", XrmoptionNoArg, "false" },
-};
-
-static argtype vars[] = {
- {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
-};
-
-ENTRYPOINT ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL};
-
-#include "ximage-loader.h"
-#include "rotator.h"
-#include "gltrackball.h"
-#include "normals.h"
-
-#include "images/gen/lament512_png.h"
-
-#define RANDSIGN() ((random() & 1) ? 1 : -1)
-
-typedef enum {
- LAMENT_BOX,
-
- LAMENT_STAR_OUT,
- LAMENT_STAR_ROT,
- LAMENT_STAR_ROT_IN,
- LAMENT_STAR_ROT_OUT,
- LAMENT_STAR_UNROT,
- LAMENT_STAR_IN,
-
- LAMENT_TETRA_UNE,
- LAMENT_TETRA_USW,
- LAMENT_TETRA_DWN,
- LAMENT_TETRA_DSE,
-
- LAMENT_LID_OPEN,
- LAMENT_LID_CLOSE,
- LAMENT_LID_ZOOM,
-
- LAMENT_TASER_OUT,
- LAMENT_TASER_SLIDE,
- LAMENT_TASER_SLIDE_IN,
- LAMENT_TASER_IN,
-
- LAMENT_PILLAR_OUT,
- LAMENT_PILLAR_SPIN,
- LAMENT_PILLAR_IN,
-
- LAMENT_SPHERE_OUT,
- LAMENT_SPHERE_IN,
-
- LAMENT_LEVIATHAN_SPIN,
- LAMENT_LEVIATHAN_FADE,
- LAMENT_LEVIATHAN_TWIST,
- LAMENT_LEVIATHAN_COLLAPSE,
- LAMENT_LEVIATHAN_EXPAND,
- LAMENT_LEVIATHAN_UNTWIST,
- LAMENT_LEVIATHAN_UNFADE,
- LAMENT_LEVIATHAN_UNSPIN
-
-} lament_type;
-
-static const GLfloat exterior_color[] =
- { 0.33, 0.22, 0.03, 1.00, /* ambient */
- 0.78, 0.57, 0.11, 1.00, /* specular */
- 0.99, 0.91, 0.81, 1.00, /* diffuse */
- 27.80 /* shininess */
- };
-static const GLfloat interior_color[] =
- { 0.20, 0.20, 0.15, 1.00, /* ambient */
- 0.40, 0.40, 0.32, 1.00, /* specular */
- 0.99, 0.99, 0.81, 1.00, /* diffuse */
- 50.80 /* shininess */
- };
-static const GLfloat leviathan_color[] =
- { 0.30, 0.30, 0.30, 1.00, /* ambient */
- 0.85, 0.85, 0.95, 1.00, /* specular */
- 0.99, 0.99, 0.99, 1.00, /* diffuse */
- 50.80 /* shininess */
- };
-static const GLfloat black_color[] =
- { 0.05, 0.05, 0.05, 1.00, /* ambient */
- 0.05, 0.05, 0.05, 1.00, /* specular */
- 0.05, 0.05, 0.05, 1.00, /* diffuse */
- 80.00 /* shininess */
- };
-
-
-typedef struct {
- GLXContext *glx_context;
- rotator *rot;
- double rotx, roty, rotz;
- trackball_state *trackball;
- Bool button_down_p;
- Bool ffwdp;
-
- GLuint dlists[countof(all_objs)];
- GLuint polys[countof(all_objs)];
-
- XImage *texture; /* image bits */
- GLuint texids[8]; /* texture map IDs */
- lament_type type; /* which mode of the object is current */
-
- int anim_pause; /* countdown before animating again */
- GLfloat anim_r, anim_y, anim_z; /* relative position during anims */
- Bool facing_p;
-
- int state, nstates;
- lament_type *states;
-
-} lament_configuration;
-
-static lament_configuration *lcs = NULL;
-
-
-static Bool
-facing_screen_p (ModeInfo *mi)
-{
- Bool facing_p;
- GLdouble m[16], p[16], x, y, z;
- GLint v[4];
- glGetDoublev (GL_MODELVIEW_MATRIX, m);
- glGetDoublev (GL_PROJECTION_MATRIX, p);
- glGetIntegerv (GL_VIEWPORT, v);
-
- /* See if a coordinate 5 units in front of the door is near the
- center of the screen. */
- gluProject (0, -5, 0, m, p, v, &x, &y, &z);
- x = (x / MI_WIDTH(mi)) - 0.5;
- y = (y / MI_HEIGHT(mi)) - 0.5;
-
- facing_p = (z < 0.9 &&
- x > -0.15 && x < 0.15 &&
- y > -0.15 && y < 0.15);
-
-# ifdef DEBUG_MODE
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisable (GL_LIGHTING);
- glColor3f (1, (facing_p ? 1 : 0), 0);
- glBegin (GL_LINES);
- glVertex3f (0, 0, 0);
- glVertex3f (0, -5, 0);
- glEnd();
- if (!MI_IS_WIREFRAME(mi)) glEnable (GL_LIGHTING);
-# endif /* DEBUG_MODE */
-
- return facing_p;
-}
-
-
-static void
-scale_for_window (ModeInfo *mi)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
-
- GLfloat target_size = 1.4 * (lc->texture ? lc->texture->width : 512);
- GLfloat size = MI_WIDTH(mi) < MI_HEIGHT(mi) ? MI_WIDTH(mi) : MI_HEIGHT(mi);
- GLfloat scale;
-
- /* Make it take up roughly the full width of the window. */
- scale = 20;
-
- /* But if the window is wider than tall, make it only take up the
- height of the window instead.
- */
- if (MI_WIDTH(mi) > MI_HEIGHT(mi))
- scale /= MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi);
-
- /* If the window is super wide, make it bigger. */
- if (scale < 8) scale = 8;
-
- /* Constrain it to roughly life-sized on the screen, not huge.
- */
-# ifdef HAVE_MOBILE
- if (size > 768) /* iPad retina / iPhone 6 */
- target_size *= 1.5;
- else
-# endif
- {
- GLfloat max = 500; /* 3" on my screen... */
-
- if (MI_WIDTH(mi) > 2560) { /* Retina displays */
- target_size *= 2.5;
- max *= 2.5;
- }
-
- if (target_size > max)
- target_size = max;
- }
-
- /* But if that would make the image larger than target_size, scale it
- back down again. The image-map bits we have are 512x512, so if the
- image is magnified a lot, it looks pretty blocky. It's better to
- have a 512x512 animation on a 1920x1080 screen that looks good
- than a 1024x1024 animation that looks really pixelated.
- */
- if (size > target_size)
- scale *= target_size / size;
-
- glScalef (scale, scale, scale);
-}
-
-
-static void
-set_colors (const GLfloat *color)
-{
- glMaterialfv(GL_FRONT, GL_AMBIENT, color + 0);
- glMaterialfv(GL_FRONT, GL_DIFFUSE, color + 4);
- glMaterialfv(GL_FRONT, GL_SPECULAR, color + 8);
- glMaterialfv(GL_FRONT, GL_SHININESS, color + 12);
-}
-
-static void
-set_colors_alpha (const GLfloat *color, GLfloat a)
-{
- GLfloat c[countof(leviathan_color)];
- memcpy (c, color, sizeof(c));
- c[3] = c[7] = c[11] = a;
- set_colors (c);
-}
-
-
-static void
-which_face (ModeInfo *mi, const GLfloat *f, int *face, int *outerp)
-{
- GLfloat size = 3; /* 3" square */
- const GLfloat *n = f; /* normal */
- const GLfloat *v = f + 3; /* vertex */
- GLfloat slack = 0.01;
-
- /* First look at the normal to determine which direction this triangle
- is facing (or is most-closely facing).
- It's an outer surface if it is within epsilon of the cube wall that
- it is facing. Otherwise, it's an inner surface.
- */
- if (n[1] < -0.5) *face = 1, *outerp = v[1] < slack; /* S */
- else if (n[2] > 0.5) *face = 2, *outerp = v[2] > size-slack; /* U */
- else if (n[1] > 0.5) *face = 3, *outerp = v[1] > size-slack; /* N */
- else if (n[2] < -0.5) *face = 4, *outerp = v[2] < slack; /* D */
- else if (n[0] < -0.5) *face = 5, *outerp = v[0] < slack; /* W */
- else /* (n[0] > 0.5)*/ *face = 6, *outerp = v[0] > size-slack; /* E */
-
- /* Faces that don't have normals parallel to the axes aren't external. */
- if (*outerp &&
- (n[0] > -0.95 && n[0] < 0.95 &&
- n[1] > -0.95 && n[1] < 0.95 &&
- n[2] > -0.95 && n[2] < 0.95))
- *outerp = 0;
-}
-
-
-static void
-texturize_vert (ModeInfo *mi, int which, const GLfloat *v)
-{
- GLfloat size = 3; /* 3" square */
- GLfloat s = 0, q = 0;
-
- /* Texture coordinates are surface coordinates,
- on the plane of this cube wall. */
- switch (which) {
- case 0: break;
- case 1: s = v[0], q = v[2]; break;
- case 2: s = v[0], q = v[1]; break;
- case 3: s = v[0], q = v[2]; q = size - q; break;
- case 4: s = v[0], q = v[1]; q = size - q; break;
- case 5: s = v[1], q = v[2]; break;
- case 6: s = v[1], q = v[2]; break;
- default: abort(); break;
- }
-
- glTexCoord2f (s / size, q / size);
-}
-
-
-static void
-leviathan (ModeInfo *mi, GLfloat ratio, GLfloat alpha, Bool top_p)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
- Bool wire = MI_IS_WIREFRAME(mi);
- GLfloat r = 0.34;
- GLfloat z = 2 * ratio;
- XYZ p[3];
- int i;
-
- GLfloat th = acos (2 / sqrt (6)); /* Line up with cube's diagonal */
-
- glPushMatrix();
-
- glRotatef (-45, 0, 1, 0);
- glRotatef (-th * 180 / M_PI, 0, 0, 1);
-
- if (!top_p)
- glRotatef (180, 0, 0, 1);
-
- for (i = 0; i < countof(p); i++)
- {
- GLfloat th = i * M_PI * 2 / countof(p);
- p[i].x = cos(th) * r;
- p[i].y = sin(th) * r;
- }
-
- glFrontFace (GL_CCW);
- for (i = 0; i < countof(p); i++)
- {
- int j = (i + 1) % countof(p);
-/* if (top_p)*/
- do_normal (z, 0, 0,
- 0, p[i].x, p[i].y,
- 0, p[j].x, p[j].y);
-/*
- else
- do_normal (z, 0, 0,
- 0, p[j].y, p[j].z,
- 0, p[i].y, p[i].z);
-*/
-
- if (do_texture) /* Leviathan is the final texture */
- glBindTexture (GL_TEXTURE_2D, lc->texids[countof(lc->texids) - 1]);
-
- set_colors (leviathan_color);
-
- glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
- glTexCoord2f (0.5, 1);
- glVertex3f (z, 0, 0);
-
- glTexCoord2f (0, 0);
- glVertex3f (0, p[i].x, p[i].y);
-
- glTexCoord2f (1, 0);
- glVertex3f (0, p[j].x, p[j].y);
- glEnd();
- mi->polygon_count++;
-
- /* Shield for fading */
- if (alpha < 0.9 && !wire)
- {
- GLfloat a = 0.35;
- GLfloat b = 0.69;
-
- set_colors_alpha (black_color, 1-alpha);
- glBindTexture (GL_TEXTURE_2D, 0);
- if (!wire)
- {
- glEnable (GL_BLEND);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
-
- glVertex3f (z*a, p[j].x * b, p[j].y * b);
- glVertex3f (z*a, p[i].x * b, p[i].y * b);
- glVertex3f (0, p[i].x * 1.01, p[i].y * 1.01);
- glVertex3f (0, p[j].x * 1.01, p[j].y * 1.01);
- glEnd();
- mi->polygon_count++;
- glDisable (GL_BLEND);
- }
- }
-
- glPopMatrix();
-}
-
-
-static void
-folding_walls (ModeInfo *mi, GLfloat ratio, Bool top_p)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
- Bool wire = MI_IS_WIREFRAME(mi);
- const GLfloat pa[4][2] = {{ -0.5, -0.215833 },
- { 0, 0.5 },
- { 0.5, 0 },
- { -0.215833, -0.5 }};
- const int tex[6] = { 0, 5, 1, 4, 2, 3 };
- const GLfloat top = -pa[0][1];
- GLfloat end_angle = 30.85;
- GLfloat rr = sin (ratio / 2 * M_PI);
- GLfloat offa = 0.15 * rr;
- GLfloat offb = 0.06 * rr;
- GLfloat p[4][3];
- GLfloat t[4][2];
- int i;
-
- glPushMatrix();
-
- if (top_p)
- {
- glRotatef (60, 1, -1, 1);
- glRotatef (180, 0, 1, 0);
- glRotatef (90, 1, 0, 0);
- }
- else
- {
- glRotatef (180, 1, 0, 0);
- }
-
- /* Scale down the points near the axis */
-
- p[0][0] = pa[0][0];
- p[0][1] = 0.5;
- p[0][2] = pa[0][1];
-
- p[1][0] = pa[1][0] - offb;
- p[1][1] = 0.5;
- p[1][2] = pa[1][1] - offa;
-
- p[2][0] = pa[2][0] - offa;
- p[2][1] = 0.5;
- p[2][2] = pa[2][1] - offb;
-
- p[3][0] = pa[3][0];
- p[3][1] = 0.5;
- p[3][2] = pa[3][1];
-
- if (!wire)
- {
- glEnable (GL_BLEND);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- for (i = 0; i < 3; i++)
- {
- glPushMatrix();
-
- if (i == 1)
- {
- glRotatef (-90, 1, 0, 0);
- glRotatef (180, 1, 1, 0);
- }
- else if (i == 2)
- {
- glRotatef (-90, 1, 0, 0);
- glRotatef (180, 0, 1, 0);
- glRotatef (90, 0, 1, 0);
- }
-
- glRotatef (-90, 0, 1, 0);
-
- glTranslatef (-(top/2 + 0.25), 0.5, -(top/2 + 0.25));
- glRotatef (-45, 0, 1, 0);
- glRotatef (ratio * -end_angle, 0, 0, 1);
- glRotatef (45, 0, 1, 0);
- glTranslatef (top/2 + 0.25, -0.5, top/2 + 0.25);
-
- /* Get the texture coordinates right.
- This is hairy and incomprehensible. */
-
- t[0][0] = pa[0][1] + 0.5; t[0][1] = pa[0][0] + 0.5;
- t[1][0] = pa[1][1] + 0.5; t[1][1] = pa[1][0] + 0.5;
- t[2][0] = pa[2][1] + 0.5; t[2][1] = pa[2][0] + 0.5;
- t[3][0] = pa[3][1] + 0.5; t[3][1] = pa[3][0] + 0.5;
-
- if (i == 0 && !top_p)
- {
-# define SWAP(A,B) A = 1-A, B = 1-B
- SWAP(t[0][0], t[0][1]);
- SWAP(t[1][0], t[1][1]);
- SWAP(t[2][0], t[2][1]);
- SWAP(t[3][0], t[3][1]);
-# undef SWAP
- }
- else if (i == 0 && top_p)
- {
- GLfloat ot[4][3];
- memcpy (ot, t, sizeof(t));
-# define SWAP(A,B) A = 1-A, B = 1-B
- SWAP(t[0][0], ot[2][1]);
- SWAP(t[1][0], ot[3][1]);
- SWAP(t[2][0], ot[0][1]);
- SWAP(t[3][0], ot[1][1]);
-# undef SWAP
- }
- else if (i == 1)
- {
- GLfloat f;
-# define SWAP(A,B) f = A, A = B, B = -f
- SWAP(t[0][0], t[0][1]);
- SWAP(t[1][0], t[1][1]);
- SWAP(t[2][0], t[2][1]);
- SWAP(t[3][0], t[3][1]);
-# undef SWAP
- }
-
- set_colors_alpha (exterior_color, 1-ratio);
- glBindTexture (GL_TEXTURE_2D, lc->texids[tex[i + (top_p ? 3 : 0)]]);
-
- glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
- do_normal (p[0][0], p[0][1], p[0][2],
- p[1][0], p[1][1], p[1][2],
- p[2][0], p[2][1], p[2][2]);
- glTexCoord2fv(t[0]); glVertex3fv(p[0]);
- glTexCoord2fv(t[1]); glVertex3fv(p[1]);
- glTexCoord2fv(t[2]); glVertex3fv(p[2]);
- glTexCoord2fv(t[3]); glVertex3fv(p[3]);
- glEnd();
- mi->polygon_count++;
-
- /* The triangles between the quads */
-# if 0
- /* #### There is a fucking gap between the two black triangles
- that I can't figure out! So instead of drawing the triangles,
- we build a black shield around the middle bit in leviathan()
- and count on back-face culling to have roughly the same effect.
- */
- if (!wire)
- {
- GLfloat pp[4][3];
- memcpy (pp, p, sizeof(pp));
- memcpy (pp[2], pp[1], sizeof(pp[1]));
- pp[2][0] -= 0.5 * (1-ratio);
- pp[2][1] -= 0.5 * (1-ratio);
-
- glBindTexture (GL_TEXTURE_2D, 0);
- set_colors_alpha (black_color, 1-ratio);
-
- glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
- do_normal (pp[0][0], pp[0][1], pp[0][2],
- pp[2][0], pp[2][1], pp[2][2],
- pp[1][0], pp[1][1], pp[1][2]);
- glVertex3fv(pp[0]);
- glVertex3fv(pp[2]);
- glVertex3fv(pp[1]);
- glEnd();
- mi->polygon_count++;
- }
-# endif
-
- glPopMatrix();
- }
-
- if (! wire) glDisable (GL_BLEND);
-
- glPopMatrix();
-}
-
-
-static int
-lament_sphere (ModeInfo *mi, GLfloat ratio)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
- Bool wire = MI_IS_WIREFRAME(mi);
- GLfloat size = 3; /* 3" square */
- int polys = 0;
- int facets = 16; /* NxN grid on each face */
- int face;
- static const GLfloat norms[6][3] = {{ 0, -1, 0 }, { 0, 0, 1 }, { 0, 1, 0 },
- { 0, 0, -1 }, { -1, 0, 0 }, { 1, 0, 0 }};
- GLfloat s = 1.0 / facets;
-
- /* The ratio used for the normals: linger on the square normals. */
- GLfloat ratio2 = 1 - sin ((1 - ratio) / 2 * M_PI);
- GLfloat r1 = 1 - ratio2 / 2;
- GLfloat r2 = ratio2 / 2;
-
- glPushMatrix();
- glTranslatef (-0.5, -0.5, -0.5);
- glScalef (1/size, 1/size, 1/size);
-
- set_colors (exterior_color);
-
- for (face = 0; face < 6; face++)
- {
- GLfloat x0, y0;
- for (y0 = 0; y0 < 1; y0 += s)
- for (x0 = 0; x0 < 1; x0 += s)
- {
- int i;
- GLfloat x1 = x0 + s;
- GLfloat y1 = y0 + s;
- GLfloat pa[4][3]; /* verts of the cube */
- GLfloat pb[4][3]; /* verts of the transition to the sphere */
- Bool frontp;
- GLfloat norm[4][3]; /* normals of the transitional verts */
-
- if (norms[face][0])
- frontp = norms[face][0] < 0,
- pa[0][1] = x0, pa[0][2] = y0, pa[0][0] = (frontp ? 0 : 1),
- pa[1][1] = x1, pa[1][2] = y0, pa[1][0] = pa[0][0],
- pa[2][1] = x1, pa[2][2] = y1, pa[2][0] = pa[0][0],
- pa[3][1] = x0, pa[3][2] = y1, pa[3][0] = pa[0][0];
- else if (norms[face][1])
- frontp = norms[face][1] > 0,
- pa[0][0] = x0, pa[0][2] = y0, pa[0][1] = (frontp ? 1 : 0),
- pa[1][0] = x1, pa[1][2] = y0, pa[1][1] = pa[0][1],
- pa[2][0] = x1, pa[2][2] = y1, pa[2][1] = pa[0][1],
- pa[3][0] = x0, pa[3][2] = y1, pa[3][1] = pa[0][1];
- else /* (norms[face][2]) */
- frontp = norms[face][2] < 0,
- pa[0][0] = x0, pa[0][1] = y0, pa[0][2] = (frontp ? 0 : 1),
- pa[1][0] = x1, pa[1][1] = y0, pa[1][2] = pa[0][2],
- pa[2][0] = x1, pa[2][1] = y1, pa[2][2] = pa[0][2],
- pa[3][0] = x0, pa[3][1] = y1, pa[3][2] = pa[0][2];
-
- for (i = 0; i < countof(pa); i++)
- pa[i][0] *= size, pa[i][1] *= size, pa[i][2] *= size;
-
- /* Convert square to sphere by treating as a normalized vector */
- for (i = 0; i < countof(pa); i++)
- {
- GLfloat x = (pa[i][0] / size) - 0.5;
- GLfloat y = (pa[i][1] / size) - 0.5;
- GLfloat z = (pa[i][2] / size) - 0.5;
- GLfloat d = sqrt (x*x + y*y + z*z) / 2;
- x = x/d + size/2;
- y = y/d + size/2;
- z = z/d + size/2;
-
- pb[i][0] = pa[i][0] + ((x - pa[i][0]) * ratio);
- pb[i][1] = pa[i][1] + ((y - pa[i][1]) * ratio);
- pb[i][2] = pa[i][2] + ((z - pa[i][2]) * ratio);
- }
-
- /* The normals of an intermediate point are the weighted average
- of the cube's orthogonal normals, and the sphere's radial
- normals: early in the sequence, the edges are sharp, but they
- soften as it expands. */
- {
- XYZ na, pa0, pa1, pa2;
- pa0.x = pa[0][0]; pa0.y = pa[0][1]; pa0.z = pa[0][2];
- pa1.x = pa[1][0]; pa1.y = pa[1][1]; pa1.z = pa[1][2];
- pa2.x = pa[2][0]; pa2.y = pa[2][1]; pa2.z = pa[2][2];
- na = calc_normal (pa0, pa1, pa2);
-
- for (i = 0; i < countof(pb); i++)
- {
- GLfloat d;
- XYZ nb;
-
- nb.x = pb[i][0];
- nb.y = pb[i][1];
- nb.z = pb[i][2];
- d = sqrt (nb.x*nb.x + nb.y*nb.y + nb.z*nb.z); /* normalize */
- nb.x /= d;
- nb.y /= d;
- nb.z /= d;
-
- norm[i][0] = (na.x * r1) + (nb.x * r2); /* weighted */
- norm[i][1] = (na.y * r1) + (nb.y * r2);
- norm[i][2] = (na.z * r1) + (nb.z * r2);
- }
- }
-
- if (! wire)
- glBindTexture (GL_TEXTURE_2D, lc->texids[face]);
-
- glFrontFace (frontp ? GL_CW : GL_CCW);
- glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
-
- texturize_vert (mi, face+1, pa[0]);
- glNormal3fv (norm[0]);
- glVertex3fv (pb[0]);
-
- texturize_vert (mi, face+1, pa[1]);
- glNormal3fv (norm[1]);
- glVertex3fv (pb[1]);
-
- texturize_vert (mi, face+1, pa[2]);
- glNormal3fv (norm[2]);
- glVertex3fv (pb[2]);
-
- texturize_vert (mi, face+1, pa[3]);
- glNormal3fv (norm[3]);
- glVertex3fv (pb[3]);
-
- glEnd();
- polys++;
- }
- }
-
- glPopMatrix();
-
- return polys;
-}
-
-
-static void
-draw (ModeInfo *mi)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
- Bool wire = MI_IS_WIREFRAME(mi);
-
- mi->polygon_count = 0;
-
- if (!wire)
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- else
- glClear(GL_COLOR_BUFFER_BIT);
-
- glPushMatrix();
-
- gltrackball_rotate (lc->trackball);
-
- /* Make into the screen be +Y, right be +X, and up be +Z. */
- glRotatef (-90.0, 1.0, 0.0, 0.0);
-
- scale_for_window (mi);
-
- /* Apply rotation to the object. */
- if (lc->type != LAMENT_LID_ZOOM)
- get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
- !lc->button_down_p);
-# ifdef DEBUG_MODE
- lc->rotx = 0.18;
- lc->roty = 0.22;
- lc->rotx = lc->roty = 0;
- lc->rotz = 0;
-# endif
-
- glRotatef (lc->rotx * 360, 1, 0, 0);
- glRotatef (lc->roty * 360, 0, 1, 0);
- glRotatef (lc->rotz * 360, 0, 0, 1);
-
- glScalef (0.5, 0.5, 0.5);
-
- switch (lc->type)
- {
- case LAMENT_BOX:
- glCallList (lc->dlists[OBJ_BOX]);
- mi->polygon_count += lc->polys[OBJ_BOX];
- break;
-
- case LAMENT_STAR_OUT:
- case LAMENT_STAR_ROT:
- case LAMENT_STAR_ROT_IN:
- case LAMENT_STAR_ROT_OUT:
- case LAMENT_STAR_UNROT:
- case LAMENT_STAR_IN:
- glTranslatef (0.0, 0.0, lc->anim_z/2);
- glRotatef (lc->anim_r/2, 0.0, 0.0, 1.0);
- glCallList (lc->dlists[OBJ_STAR_U]);
- mi->polygon_count += lc->polys[OBJ_STAR_U];
-
- glTranslatef (0.0, 0.0, -lc->anim_z);
- glRotatef (-lc->anim_r, 0.0, 0.0, 1.0);
- glCallList (lc->dlists[OBJ_STAR_D]);
- mi->polygon_count += lc->polys[OBJ_STAR_D];
- break;
-
- case LAMENT_TETRA_UNE:
- case LAMENT_TETRA_USW:
- case LAMENT_TETRA_DWN:
- case LAMENT_TETRA_DSE:
- {
- int magic;
- GLfloat x, y, z;
- switch (lc->type) {
- case LAMENT_TETRA_UNE: magic = OBJ_TETRA_UNE; x= 1; y= 1; z= 1; break;
- case LAMENT_TETRA_USW: magic = OBJ_TETRA_USW; x= 1; y= 1; z=-1; break;
- case LAMENT_TETRA_DWN: magic = OBJ_TETRA_DWN; x= 1; y=-1; z= 1; break;
- case LAMENT_TETRA_DSE: magic = OBJ_TETRA_DSE; x=-1; y= 1; z= 1; break;
- default: abort(); break;
- }
- glCallList(lc->dlists[OBJ_TETRA_BASE]);
- mi->polygon_count += lc->polys[OBJ_TETRA_BASE];
- if (magic != OBJ_TETRA_UNE) glCallList (lc->dlists[OBJ_TETRA_UNE]);
- if (magic != OBJ_TETRA_USW) glCallList (lc->dlists[OBJ_TETRA_USW]);
- if (magic != OBJ_TETRA_DWN) glCallList (lc->dlists[OBJ_TETRA_DWN]);
- if (magic != OBJ_TETRA_DSE) glCallList (lc->dlists[OBJ_TETRA_DSE]);
- glRotatef (lc->anim_r, x, y, z);
- glCallList (lc->dlists[magic]);
- mi->polygon_count += lc->polys[magic] * 3;
- }
- break;
-
- case LAMENT_LID_OPEN:
- case LAMENT_LID_CLOSE:
- case LAMENT_LID_ZOOM:
- {
- GLfloat d = 0.21582;
- int i;
- const int lists[4] = { OBJ_LID_A, OBJ_LID_B, OBJ_LID_C, OBJ_LID_D };
-
- lc->facing_p = facing_screen_p (mi);
-
- if (lc->anim_z < 0.5)
- glTranslatef (0, -30 * lc->anim_z, 0); /* zoom */
- else
- glTranslatef (8 * (0.5 - (lc->anim_z - 0.5)), 0, 0);
-
- glCallList (lc->dlists[OBJ_LID_BASE]);
- mi->polygon_count += lc->polys[OBJ_LID_BASE];
- for (i = 0; i < countof(lists); i++)
- {
- glPushMatrix();
- glRotatef (90 * i, 0, 1, 0);
- glTranslatef (-d, -0.5, d);
- glRotatef (-45, 0, 1, 0);
- glRotatef (-lc->anim_r, 1, 0, 0);
- glRotatef (45, 0, 1, 0);
- glTranslatef (d, 0.5, -d);
- glRotatef (-90 * i, 0, 1, 0);
- glCallList (lc->dlists[lists[i]]);
- mi->polygon_count += lc->polys[lists[i]];
- glPopMatrix();
- }
-
-# ifdef DEBUG_MODE
- if (lc->facing_p)
- {
- glColor3f(1, 0, 0);
- glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
- glVertex3f (-0.49, 0.49, -0.49);
- glVertex3f ( 0.49, 0.49, -0.49);
- glVertex3f ( 0.49, 0.49, 0.49);
- glVertex3f (-0.49, 0.49, 0.49);
- glEnd();
- mi->polygon_count++;
- }
-# endif /* DEBUG_MODE */
- }
- break;
-
- case LAMENT_TASER_OUT:
- case LAMENT_TASER_SLIDE:
- case LAMENT_TASER_SLIDE_IN:
- case LAMENT_TASER_IN:
-
- glTranslatef (0, -lc->anim_z/2, 0);
- glCallList (lc->dlists[OBJ_TASER_BASE]);
- mi->polygon_count += lc->polys[OBJ_TASER_BASE];
-
- glTranslatef (0, lc->anim_z, 0);
- glCallList (lc->dlists[OBJ_TASER_A]);
- mi->polygon_count += lc->polys[OBJ_TASER_A];
-
- glTranslatef (lc->anim_y, 0, 0);
- glCallList (lc->dlists[OBJ_TASER_B]);
- mi->polygon_count += lc->polys[OBJ_TASER_B];
- break;
-
- case LAMENT_PILLAR_OUT:
- case LAMENT_PILLAR_SPIN:
- case LAMENT_PILLAR_IN:
-
- glCallList (lc->dlists[OBJ_PILLAR_BASE]);
- mi->polygon_count += lc->polys[OBJ_PILLAR_BASE];
-
- glPushMatrix();
- if (lc->anim_z == 1 || lc->anim_z == 3)
- {
- glRotatef (lc->anim_r, 0, 0, 1);
- glTranslatef (0, 0, lc->anim_y);
- }
- glCallList (lc->dlists[OBJ_PILLAR_A]);
- mi->polygon_count += lc->polys[OBJ_PILLAR_A];
- glPopMatrix();
-
- glPushMatrix();
- if (lc->anim_z == 2 || lc->anim_z == 3)
- {
- glRotatef (lc->anim_r, 0, 0, 1);
- glTranslatef (0, 0, -lc->anim_y);
- }
- glCallList (lc->dlists[OBJ_PILLAR_B]);
- mi->polygon_count += lc->polys[OBJ_PILLAR_B];
- glPopMatrix();
- break;
-
- case LAMENT_SPHERE_OUT:
- case LAMENT_SPHERE_IN:
- mi->polygon_count += lament_sphere (mi, lc->anim_y);
- break;
-
- case LAMENT_LEVIATHAN_SPIN:
- case LAMENT_LEVIATHAN_UNSPIN:
- case LAMENT_LEVIATHAN_FADE:
- case LAMENT_LEVIATHAN_UNFADE:
- case LAMENT_LEVIATHAN_TWIST:
- case LAMENT_LEVIATHAN_UNTWIST:
- {
- /* These normals are hard to compute, so I pulled them from the
- model. */
- const GLfloat axes[6][4] =
- {{ OBJ_ISO_UNE, 0.633994, 0.442836, 0.633994 },
- { OBJ_ISO_USW, 0.442836, 0.633994, -0.633994 },
- { OBJ_ISO_DSE, -0.633994, 0.633994, 0.442836 },
- { OBJ_ISO_SWD, -0.633994, -0.442836, -0.633994 },
- { OBJ_ISO_DEN, -0.442836, -0.633994, 0.633994 },
- { OBJ_ISO_UNW, 0.633994, -0.633994, -0.442836 }};
- int i;
-
- GLfloat s = (1 - lc->anim_z);
- GLfloat s2 = MAX (0, 360 - lc->anim_r) / 360.0;
- Bool blendp = 0;
-
- switch (lc->type) {
- case LAMENT_LEVIATHAN_SPIN: break;
- case LAMENT_LEVIATHAN_UNSPIN: s2 = 1 - s2; break;
- default: s2 = 0; blendp = 1; break;
- }
-
- if (wire) blendp = 0;
-
- s = (s * 0.6) + 0.4;
-
- leviathan (mi, 1 - s2, 1, True);
- glCallList (lc->dlists[OBJ_ISO_BASE_A]);
- mi->polygon_count += lc->polys[OBJ_ISO_BASE_A];
-
- glPushMatrix();
- glScalef (s2, s2, s2);
- glCallList (lc->dlists[OBJ_ISO_USE]);
- mi->polygon_count += lc->polys[OBJ_ISO_USE];
- glPopMatrix();
-
- glPushMatrix();
- glRotatef (lc->anim_y, 1, -1, 1);
- glCallList (lc->dlists[OBJ_ISO_BASE_B]);
- mi->polygon_count += lc->polys[OBJ_ISO_BASE_B];
- leviathan (mi, 1 - s2, 1, False);
- glPopMatrix();
-
- if (blendp)
- {
-# ifndef HAVE_JWZGLES /* no glBlendColor */
- glEnable (GL_BLEND);
- glBlendFunc (GL_CONSTANT_ALPHA, GL_SRC_ALPHA);
- glBlendColor (1, 1, 1, MAX(0, 1-(lc->anim_z * 3)));
-# endif
- }
-
- for (i = 0; i < countof(axes); i++)
- {
- glPushMatrix();
- glRotatef (lc->anim_r, axes[i][1], axes[i][2], axes[i][3]);
- glScalef (s, s, s);
- glCallList (lc->dlists[(int) axes[i][0]]);
- mi->polygon_count += lc->polys[(int) axes[i][0]];
- glPopMatrix();
- if (i == 2)
- glRotatef (lc->anim_y, 1, -1, 1);
- }
-
- if (blendp) glDisable (GL_BLEND);
-
- glPushMatrix();
- glScalef (s2, s2, s2);
- glCallList (lc->dlists[OBJ_ISO_DWN]);
- mi->polygon_count += lc->polys[OBJ_ISO_DWN];
- glPopMatrix();
- }
- break;
-
- case LAMENT_LEVIATHAN_COLLAPSE:
- case LAMENT_LEVIATHAN_EXPAND:
- {
- glPushMatrix();
- leviathan (mi, 1, lc->anim_y, True);
- glRotatef (180, 1, -1, 1);
- leviathan (mi, 1, lc->anim_y, False);
- glPopMatrix();
- folding_walls (mi, lc->anim_y, True);
- folding_walls (mi, lc->anim_y, False);
- }
- break;
-
- default:
- abort();
- break;
- }
-
- glPopMatrix();
-}
-
-
-/* Rather than just picking states randomly, pick an ordering randomly, do it,
- and then re-randomize. That way one can be assured of seeing all states in
- a short time period, though not always in the same order (it's frustrating
- to see it pick the same state 5x in a row.) Though, that can still happen,
- since states are in the list multiple times as a way of giving them
- probabilities.
- */
-static void
-shuffle_states (lament_configuration *lc)
-{
- int i;
- for (i = 0; i < lc->nstates; i++)
- {
- int a = random() % lc->nstates;
- lament_type swap = lc->states[a];
- lc->states[a] = lc->states[i];
- lc->states[i] = swap;
- }
-}
-
-
-static void
-animate (ModeInfo *mi)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
- int pause = 10;
- int pause2 = 120;
- GLfloat speed = (lc->ffwdp ? 20 : 1);
-
- switch (lc->type)
- {
- case LAMENT_BOX:
- {
- lc->state++;
- if (lc->state >= lc->nstates)
- {
- shuffle_states (lc);
- lc->state = 0;
- }
- lc->type = lc->states[lc->state];
-
- if (lc->type == LAMENT_BOX)
- lc->anim_pause = pause2;
-
- lc->anim_r = 0.0;
- lc->anim_y = 0.0;
- lc->anim_z = 0.0;
- }
- break;
-
- /* -------------------------------------------------------------- */
-
- case LAMENT_STAR_OUT:
- lc->anim_z += 0.01 * speed;
- if (lc->anim_z >= 1.0)
- {
- lc->anim_z = 1.0;
- lc->type = LAMENT_STAR_ROT;
- lc->anim_pause = pause;
- }
- break;
-
- case LAMENT_STAR_ROT:
- lc->anim_r += 1.0 * speed;
- if (lc->anim_r >= 45.0)
- {
- lc->anim_r = 45.0;
- lc->type = LAMENT_STAR_ROT_IN;
- lc->anim_pause = pause;
- }
- break;
-
- case LAMENT_STAR_ROT_IN:
- lc->anim_z -= 0.01 * speed;
- if (lc->anim_z <= 0.0)
- {
- lc->anim_z = 0.0;
- lc->type = LAMENT_STAR_ROT_OUT;
- lc->anim_pause = pause2 * (1 + frand(2) + frand(2));
- }
- break;
-
- case LAMENT_STAR_ROT_OUT:
- lc->anim_z += 0.01 * speed;
- if (lc->anim_z >= 1.0)
- {
- lc->anim_z = 1.0;
- lc->type = LAMENT_STAR_UNROT;
- lc->anim_pause = pause;
- }
- break;
-
- case LAMENT_STAR_UNROT:
- lc->anim_r -= 1.0 * speed;
- if (lc->anim_r <= 0.0)
- {
- lc->anim_r = 0.0;
- lc->type = LAMENT_STAR_IN;
- lc->anim_pause = pause;
- }
- break;
-
- case LAMENT_STAR_IN:
- lc->anim_z -= 0.01 * speed;
- if (lc->anim_z <= 0.0)
- {
- lc->anim_z = 0.0;
- lc->type = LAMENT_BOX;
- lc->anim_pause = pause2;
- }
- break;
-
- /* -------------------------------------------------------------- */
-
- case LAMENT_TETRA_UNE:
- case LAMENT_TETRA_USW:
- case LAMENT_TETRA_DWN:
- case LAMENT_TETRA_DSE:
-
- lc->anim_r += 1.0 * speed;
- if (lc->anim_r >= 360.0)
- {
- lc->anim_r = 0.0;
- lc->type = LAMENT_BOX;
- lc->anim_pause = pause2;
- }
- else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
- {
- lc->anim_r = 120.0;
- lc->anim_pause = pause;
- }
- else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
- {
- lc->anim_r = 240.0;
- lc->anim_pause = pause;
- }
- break;
-
- /* -------------------------------------------------------------- */
-
- case LAMENT_LID_OPEN:
- lc->anim_r += 1.0 * speed;
-
- if (lc->anim_r >= 112.0)
- {
- lc->anim_r = 112.0;
- lc->anim_z = 0.0;
- lc->anim_pause = pause2;
- lc->type = (lc->facing_p ? LAMENT_LID_ZOOM : LAMENT_LID_CLOSE);
- }
- break;
-
- case LAMENT_LID_CLOSE:
- lc->anim_r -= 1.0 * speed;
- if (lc->anim_r <= 0.0)
- {
- lc->anim_r = 0.0;
- lc->type = LAMENT_BOX;
- lc->anim_pause = pause2;
- }
- break;
-
- case LAMENT_LID_ZOOM:
- lc->anim_z += 0.01 * speed;
- if (lc->anim_z > 1.0)
- {
- lc->anim_r = 0.0;
- lc->anim_z = 0.0;
- lc->type = LAMENT_BOX;
- }
- break;
-
- /* -------------------------------------------------------------- */
-
- case LAMENT_TASER_OUT:
- lc->anim_z += 0.005 * speed;
- if (lc->anim_z >= 0.5)
- {
- lc->anim_z = 0.5;
- lc->type = LAMENT_TASER_SLIDE;
- lc->anim_pause = pause * (1 + frand(5) + frand(5));
- }
- break;
-
- case LAMENT_TASER_SLIDE:
- lc->anim_y += 0.005 * speed;
- if (lc->anim_y >= 0.255)
- {
- lc->anim_y = 0.255;
- lc->type = LAMENT_TASER_SLIDE_IN;
- lc->anim_pause = pause2 * (1 + frand(5) + frand(5));
- }
- break;
-
- case LAMENT_TASER_SLIDE_IN:
- lc->anim_y -= 0.0025 * speed;
- if (lc->anim_y <= 0.0)
- {
- lc->anim_y = 0.0;
- lc->type = LAMENT_TASER_IN;
- lc->anim_pause = pause;
- }
- break;
-
- case LAMENT_TASER_IN:
- lc->anim_z -= 0.0025 * speed;
- if (lc->anim_z <= 0.0)
- {
- lc->anim_z = 0.0;
- lc->type = LAMENT_BOX;
- lc->anim_pause = pause2;
- }
- break;
-
- /* -------------------------------------------------------------- */
-
- case LAMENT_PILLAR_OUT:
-
- if (lc->anim_y == 0) /* mostly in */
- lc->anim_y += 0.005 * ((random() % 5) ? -1 : 1) * speed;
- else if (lc->anim_y > 0)
- lc->anim_y += 0.005 * speed;
- else
- lc->anim_y -= 0.001 * speed;
-
- if (lc->anim_z == 0)
- {
- int i = (random() % 7); /* A, B or both */
- if (i == 0) lc->anim_z = 3;
- else if (i < 5) lc->anim_z = 2;
- else lc->anim_z = 1;
-
- /* We can do quarter turns, because it's radially symmetrical. */
- lc->anim_r = 90.0 * (1 + frand(6)) * RANDSIGN();
- }
- if (lc->anim_y > 0.4)
- {
- lc->anim_y = 0.4;
- lc->type = LAMENT_PILLAR_SPIN;
- lc->anim_pause = pause;
- }
- else if (lc->anim_y < -0.03)
- {
- lc->anim_y = -0.03;
- lc->type = LAMENT_PILLAR_SPIN;
- lc->anim_pause = pause;
- }
- break;
-
- case LAMENT_PILLAR_SPIN:
- {
- Bool negp = (lc->anim_r < 0);
- lc->anim_r += (negp ? 1 : -1) * speed;
- if (negp ? lc->anim_r > 0 : lc->anim_r < 0)
- {
- lc->anim_r = 0;
- lc->type = LAMENT_PILLAR_IN;
- }
- }
- break;
-
- case LAMENT_PILLAR_IN:
- {
- Bool negp = (lc->anim_y < 0);
- lc->anim_y += (negp ? 1 : -1) * 0.005 * speed;
- if (negp ? lc->anim_y > 0 : lc->anim_y < 0)
- {
- lc->anim_y = 0;
- lc->anim_z = 0;
- lc->type = LAMENT_BOX;
- lc->anim_pause = pause;
- }
- }
- break;
-
- /* -------------------------------------------------------------- */
-
- case LAMENT_SPHERE_OUT:
- {
- lc->anim_y += 0.01 * speed;
- if (lc->anim_y >= 1)
- {
- lc->anim_y = 1;
- lc->type = LAMENT_SPHERE_IN;
- lc->anim_pause = pause2 * (1 + frand(1) + frand(1));
- }
- }
- break;
-
- case LAMENT_SPHERE_IN:
- {
- lc->anim_y -= 0.01 * speed;
- if (lc->anim_y <= 0)
- {
- lc->anim_y = 0;
- lc->type = LAMENT_BOX;
- lc->anim_pause = pause;
- }
- }
- break;
-
- /* -------------------------------------------------------------- */
-
- case LAMENT_LEVIATHAN_SPIN:
- lc->anim_r += 3.5 * speed;
- if (lc->anim_r >= 360 * 3)
- {
- lc->anim_r = 0;
- lc->type = LAMENT_LEVIATHAN_FADE;
- lc->anim_pause = 0;
- }
- break;
-
- case LAMENT_LEVIATHAN_FADE:
- lc->anim_z += 0.01 * speed;
- if (lc->anim_z >= 1)
- {
- lc->anim_z = 1;
- lc->type = LAMENT_LEVIATHAN_TWIST;
- lc->anim_pause = 0;
- }
- break;
-
- case LAMENT_LEVIATHAN_TWIST:
- lc->anim_y += 2 * speed;
- lc->anim_z = 1;
- if (lc->anim_y >= 180)
- {
- lc->anim_y = 0;
- lc->type = LAMENT_LEVIATHAN_COLLAPSE;
- lc->anim_pause = 0;
- }
- break;
-
- case LAMENT_LEVIATHAN_COLLAPSE:
- lc->anim_y += 0.01 * speed;
- if (lc->anim_y >= 1)
- {
- lc->anim_y = 1.0;
- lc->type = LAMENT_LEVIATHAN_EXPAND;
- lc->anim_pause = pause2 * 4;
- }
- break;
-
- case LAMENT_LEVIATHAN_EXPAND:
- lc->anim_y -= 0.005 * speed;
- if (lc->anim_y <= 0)
- {
- lc->anim_y = 180;
- lc->type = LAMENT_LEVIATHAN_UNTWIST;
- }
- break;
-
- case LAMENT_LEVIATHAN_UNTWIST:
- lc->anim_y -= 2 * speed;
- lc->anim_z = 1;
- if (lc->anim_y <= 0)
- {
- lc->anim_y = 0;
- lc->type = LAMENT_LEVIATHAN_UNFADE;
- lc->anim_pause = 0;
- }
- break;
-
- case LAMENT_LEVIATHAN_UNFADE:
- lc->anim_z -= 0.1 * speed;
- if (lc->anim_z <= 0)
- {
- lc->anim_z = 0;
- lc->type = LAMENT_LEVIATHAN_UNSPIN;
- lc->anim_pause = 0;
- }
- break;
-
- case LAMENT_LEVIATHAN_UNSPIN:
- lc->anim_r += 3.5 * speed;
- if (lc->anim_r >= 360 * 2)
- {
- lc->anim_r = 0;
- lc->type = LAMENT_BOX;
- lc->anim_pause = pause2;
- }
- break;
-
- default:
- abort();
- break;
- }
-
-# ifdef DEBUG_MODE
-
- lc->anim_pause = 0;
-
- if (lc->type == LAMENT_BOX)
- lc->type = DEBUG_MODE;
-
- if (lc->ffwdp)
- {
- lc->ffwdp = 0;
- while (lc->type != DEBUG_MODE)
- animate (mi);
- }
-
-# else /* !DEBUG_MODE */
-
- if (lc->ffwdp && lc->type == LAMENT_BOX)
- {
- lc->ffwdp = 0;
- while (lc->type == LAMENT_BOX)
- animate (mi);
- lc->anim_pause = 0;
- }
-
-# endif /* !DEBUG_MODE */
-}
-
-
-static void
-gl_init (ModeInfo *mi)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
- Bool wire = MI_IS_WIREFRAME(mi);
- int i;
-
- if (wire)
- do_texture = False;
-
- if (!wire)
- {
- static const GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
- static const GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
-
- static const GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
-/* static const GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
- static const GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
- static const GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
-
- glLightfv(GL_LIGHT0, GL_POSITION, pos0);
- glLightfv(GL_LIGHT1, GL_POSITION, pos1);
-
- glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
-/* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
- glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
- glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
-
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
-/* glEnable(GL_LIGHT1); */
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_NORMALIZE);
- glEnable(GL_CULL_FACE);
- }
-
- if (do_texture)
- {
- int i;
- for (i = 0; i < countof(lc->texids); i++)
- glGenTextures(1, &lc->texids[i]);
-
- lc->texture = image_data_to_ximage (mi->dpy, mi->xgwa.visual,
- lament512_png, sizeof(lament512_png));
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- /* messes up -fps */
- /* glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); */
-
- for (i = 0; i < countof(lc->texids); i++)
- {
- int height = lc->texture->width; /* assume square */
- glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
-
- clear_gl_error();
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
- lc->texture->width, height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE,
- (lc->texture->data +
- (lc->texture->bytes_per_line * height * i)));
- check_gl_error("texture");
-
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- check_gl_error("texture");
-
- /* This makes scaled pixmaps tolerable to look at. */
-# if !defined(GL_TEXTURE_LOD_BIAS) && defined(GL_TEXTURE_LOD_BIAS_EXT)
-# define GL_TEXTURE_LOD_BIAS GL_TEXTURE_LOD_BIAS_EXT
-# endif
-# ifdef GL_TEXTURE_LOD_BIAS
- glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.25);
-# endif
- clear_gl_error(); /* invalid enum on iPad 3 */
- }
- }
-
- for (i = 0; i < countof(all_objs); i++)
- {
- GLfloat s = 1/3.0; /* box is 3" square */
- const struct gllist *L = *all_objs[i];
- const GLfloat *f = (const GLfloat *) L->data;
- int j;
-
- lc->dlists[i] = glGenLists(1);
- lc->polys[i] = L->points / 3;
- glNewList(lc->dlists[i], GL_COMPILE);
- if (L->primitive != GL_TRIANGLES) abort();
- if (L->format != GL_N3F_V3F) abort();
-
- glPushMatrix();
- glTranslatef (-0.5, -0.5, -0.5);
- glScalef (s, s, s);
-
- for (j = 0; j < L->points; j += 3)
- {
- int face, outerp;
- Bool blackp = (i == OBJ_ISO_BASE_A || i == OBJ_ISO_BASE_B);
- which_face (mi, f, &face, &outerp); /* from norm of first vert */
-
- set_colors (outerp ? exterior_color :
- blackp ? black_color : interior_color);
- glBindTexture (GL_TEXTURE_2D,
- (outerp ? lc->texids[face-1] :
- blackp ? 0 : lc->texids[6]));
-
- glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
- if (face) texturize_vert (mi, face, f+3);
- glNormal3fv (f); f += 3; glVertex3fv (f); f += 3;
- if (face) texturize_vert (mi, face, f+3);
- glNormal3fv (f); f += 3; glVertex3fv (f); f += 3;
- if (face) texturize_vert (mi, face, f+3);
- glNormal3fv (f); f += 3; glVertex3fv (f); f += 3;
- glEnd();
- }
- glPopMatrix();
-
- glEndList();
- }
-}
-
-
-ENTRYPOINT Bool
-lament_handle_event (ModeInfo *mi, XEvent *event)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
-
- if (gltrackball_event_handler (event, lc->trackball,
- MI_WIDTH (mi), MI_HEIGHT (mi),
- &lc->button_down_p))
- return True;
- else if (event->xany.type == KeyPress)
- {
- KeySym keysym;
- char c = 0;
- XLookupString (&event->xkey, &c, 1, &keysym, 0);
- if (c == ' ' || c == '\t')
- {
- lc->ffwdp = True;
- return True;
- }
- }
-
- return False;
-}
-
-
-ENTRYPOINT void
-reshape_lament (ModeInfo *mi, int width, int height)
-{
- GLfloat h = (GLfloat) height / (GLfloat) width;
- glViewport(0, 0, (GLint) width, (GLint) height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0.0, 0.0, -40.0);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-
-ENTRYPOINT void
-init_lament (ModeInfo *mi)
-{
- lament_configuration *lc;
- int i;
- MI_INIT (mi, lcs);
-
- lc = &lcs[MI_SCREEN(mi)];
-
- {
- double rot_speed = 0.5;
- lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
- lc->trackball = gltrackball_init (True);
- }
-
- lc->type = LAMENT_BOX;
- lc->anim_pause = 300 + (random() % 100);
-
- if ((lc->glx_context = init_GL(mi)) != NULL)
- {
- reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
- gl_init(mi);
- }
-
- lc->states = (lament_type *) calloc (200, sizeof (*lc->states));
- lc->nstates = 0;
-
-# define PUSH(N,WHICH) \
- for (i = 0; i < N; i++) lc->states[lc->nstates++] = WHICH
-
- PUSH (4, LAMENT_TETRA_UNE); /* most common */
- PUSH (4, LAMENT_TETRA_USW);
- PUSH (4, LAMENT_TETRA_DWN);
- PUSH (4, LAMENT_TETRA_DSE);
-
- PUSH (8, LAMENT_STAR_OUT); /* pretty common */
- PUSH (8, LAMENT_TASER_OUT);
- PUSH (8, LAMENT_PILLAR_OUT);
-
- PUSH (4, LAMENT_LID_OPEN); /* rare */
- PUSH (2, LAMENT_SPHERE_OUT); /* rare */
- PUSH (1, LAMENT_LEVIATHAN_SPIN); /* very rare */
-
- PUSH (35, LAMENT_BOX); /* rest state */
-# undef PUSH
-
- shuffle_states (lc);
-
-# ifdef DEBUG_MODE
- lc->type = DEBUG_MODE;
- lc->anim_pause = 0;
-# endif
-
-}
-
-
-ENTRYPOINT void
-draw_lament (ModeInfo *mi)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
- Display *dpy = MI_DISPLAY(mi);
- Window window = MI_WINDOW(mi);
-
- if (!lc->glx_context)
- return;
-
- glDrawBuffer(GL_BACK);
-
- glXMakeCurrent(dpy, window, *lc->glx_context);
- draw(mi);
- if (mi->fps_p) do_fps (mi);
-
- glFinish();
- glXSwapBuffers(dpy, window);
-
- if (!lc->ffwdp && lc->anim_pause)
- lc->anim_pause--;
- else
- animate(mi);
-}
-
-ENTRYPOINT void
-free_lament (ModeInfo *mi)
-{
- lament_configuration *lc = &lcs[MI_SCREEN(mi)];
- int i;
- if (!lc->glx_context) return;
- glXMakeCurrent (MI_DISPLAY(mi), MI_WINDOW(mi), *lc->glx_context);
- if (lc->states) free (lc->states);
- if (lc->trackball) gltrackball_free (lc->trackball);
- if (lc->rot) free_rotator (lc->rot);
- if (lc->texture) XDestroyImage (lc->texture);
- for (i = 0; i < countof(all_objs); i++)
- if (glIsList(lc->dlists[i])) glDeleteLists(lc->dlists[i], 1);
- for (i = 0; i < countof(lc->texids); i++)
- if (lc->texids[i]) glDeleteTextures (1, &lc->texids[i]);
-}
-
-XSCREENSAVER_MODULE ("Lament", lament)
-
-#endif /* USE_GL */