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