xenocara/app/xlockmore/modes/glx/lament.c
2006-11-26 11:07:42 +00:00

2486 lines
62 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* -*- Mode: C; tab-width: 4 -*- */
/* lament --- Shows Lemarchand's Box */
#if !defined( lint ) && !defined( SABER )
static const char sccsid[] = "@(#)lament.c 5.03 2001/11/28 xlockmore";
#endif
/* xscreensaver, Copyright (c) 1998 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.
*
* Revisions:
* 28-Nov-2001: Integrated diffs from xscreensaver-3.34 - E. Lassauge <lassauge AT users.sourceforge.net>
* 01-Mar-2001: Added FPS stuff - Eric Lassauge <lassauge AT users.sourceforge.net>
* 28-Nov-2000: modified release part to add freeing of GL objects
* 21-Nov-2000: use new common xpm_to_ximage function - E.Lassauge
* 01-Nov-2000: Allocation checks
* 25-Jul-1998: Written by jwz
*/
/* Animates Lemarchand's Box, the Lament Configuration. By jwz, 25-Jul-98.
TODO:
* The "gold" color isn't quite right; it looks more like "yellow" than
"gold" to me.
* For some reason, the interior surfaces are shinier than the exterior
surfaces. I don't understand why, but this should be remedied.
* Perhaps use a slightly-bumpy or oily texture for the interior surfaces?
* Some of the edges don't line up perfectly (since the images are not
perfectly symetrical.) Something should be done about this; either
making the edges overlap slightly (instead of leaving gaps) or fixing
the images so that the edges may be symmetrical.
* I want the gold leaf to seem to be raised up from the surface, but I
think this isn't possible with OpenGL. Supposedly, OpenGL only
supports Gouraud shading (interpolating edge normals from face normals,
and shading smoothly) but bump-maps only work with Phong shading
(computing a normal for each rendered pixel.)
* As far as I can tell, OpenGL doesn't do shadows. As a result, the
forward-facing interior walls are drawn bright, not dark. If it was
casting shadows properly, it wouldn't matter so much that the edges
don't quite line up, because the lines would be black, and thus not
visible. But the edges don't match up, and so the bright interior
faces show through, and that sucks.
But apparently there are tricky ways around this:
http://reality.sgi.com/opengl/tips/rts/
I think these techniques require GLUT, however, which isn't
(currently) required by any other xscreensaver hacks.
* There should be strange lighting effects playing across the surface:
electric sparks, or little glittery blobs of light.
http://reality.sgi.com/opengl/tips/lensflare/ might provide guidance.
* Need to add some more modes, to effect the transition from the cube
shapes to the "spike" or "leviathan" shapes. I have extensive notes
on how these transformations occur, but unfortunately, due to camera
trickery, the transitions require dematerializations which do not
preserve object volume. But I suppose that's allowed, in
non-Euclidian or hyperdimensional spaces (since the extra mass could
simply be rotated along the axis to which one cannot point.)
The other hard thing about this is that the "leviathan" shapes contain
a much larger number of facets, and I modelled this whole thing by
hand, since I don't have any 3d-object-editing tools that I know how
to use (or that look like they would take any less than several months
to become even marginally proficient with...)
* Perhaps there should be a table top, on which it casts a shadow?
And then multiple light sources (for multiple shadows)?
* Needs music. ("Hellraiser Themes" by Coil: TORSO CD161; also
duplicated on the "Unnatural History 2" compilation, WORLN M04699.)
* I'm not totally happy with the spinning motion; I like the
acceleration and deceleration, but it often feels like it's going too
fast, or not naturally enough, or something.
* However, the motion is better than that used by gears, superquadrics,
etc.; so maybe I should make them all share the same motion code.
*/
#ifdef VMS
#include "vms_x_fix.h"
#include <X11/Intrinsic.h>
#endif
#ifdef STANDALONE
#define MODE_lament
#define PROGCLASS "Lament"
#define HACK_INIT init_lament
#define HACK_DRAW draw_lament
#define HACK_RESHAPE reshape_lament
#define lament_opts xlockmore_opts
#define DEFAULTS "*delay: 10000 \n" \
"*showFps: False \n" \
"*wireframe: False \n" \
"*texture: True \n"
#include "xlockmore.h"
#else /* !STANDALONE */
#include "xlock.h" /* from the xlockmore distribution */
#include "visgl.h"
#endif /* !STANDALONE */
#ifdef MODE_lament
#undef countof
#define countof(x) ((int)(sizeof((x))/sizeof((*x))))
#define DEF_TEXTURE "True"
static Bool do_texture;
static XrmOptionDescRec opts[] =
{
{(char *) "-texture", (char *) ".lament.texture", XrmoptionNoArg, (caddr_t) "on"},
{(char *) "+texture", (char *) ".lament.texture", XrmoptionNoArg, (caddr_t) "off"},
};
static argtype vars[] =
{
{(void *) & do_texture, (char *) "texture", (char *) "Texture", (char *) DEF_TEXTURE, t_Bool},
};
static OptionStruct desc[] =
{
{(char *) "-/+texture", (char *) "turn on/off texturing"}
};
ModeSpecOpt lament_opts =
{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
#ifdef USE_MODULES
ModStruct lament_description =
{"lament", "init_lament", "draw_lament", "release_lament",
"draw_lament", "change_lament", (char *) NULL, &lament_opts,
10000, 1, 1, 1, 64, 1.0, "",
"Shows Lemarchand's Box", 0, NULL};
#endif
#ifdef HAVE_XPM
#include "xpm-ximage.h"
#ifdef STANDALONE
#include "../images/lament.xpm"
#else
#include "pixmaps/lament.xpm"
#endif
#endif
#define RANDSIGN() ((LRAND() & 1) ? 1 : -1)
#define FLOATRAND(a) (((double)LRAND() / (double)MAXRAND) * a)
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_type;
static 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 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 */
};
typedef struct {
GLXContext *glx_context;
GLuint box; /* display list IDs */
GLuint star1, star2;
GLuint tetra_une, tetra_usw, tetra_dwn, tetra_dse, tetra_mid;
GLuint lid_0, lid_1, lid_2, lid_3, lid_4;
GLuint taser_base, taser_lifter, taser_slider;
GLfloat rotx, roty, rotz; /* current object rotation */
GLfloat dx, dy, dz; /* current rotational velocity */
GLfloat ddx, ddy, ddz; /* current rotational acceleration */
GLfloat d_max; /* max velocity */
XImage *texture; /* image bits */
GLuint texids[6]; /* 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 */
Window window;
} lament_configuration;
static lament_configuration *lcs = (lament_configuration *) NULL;
#define FACE_N 3
#define FACE_S 2
#define FACE_E 0
#define FACE_W 4
#define FACE_U 5
#define FACE_D 1
/* Computing normal vectors (thanks to Nat Friedman <ndf@mit.edu>)
*/
typedef struct vector {
GLfloat x, y, z;
} vector;
typedef struct plane {
vector p1, p2, p3;
} plane;
static void
vector_set(vector * v, GLfloat x, GLfloat y, GLfloat z)
{
v->x = x;
v->y = y;
v->z = z;
}
static void
vector_cross(vector v1, vector v2, vector * v3)
{
v3->x = (v1.y * v2.z) - (v1.z * v2.y);
v3->y = (v1.z * v2.x) - (v1.x * v2.z);
v3->z = (v1.x * v2.y) - (v1.y * v2.x);
}
static void
vector_subtract(vector v1, vector v2, vector * res)
{
res->x = v1.x - v2.x;
res->y = v1.y - v2.y;
res->z = v1.z - v2.z;
}
static void
plane_normal(plane p, vector * n)
{
vector v1, v2;
vector_subtract(p.p1, p.p2, &v1);
vector_subtract(p.p1, p.p3, &v2);
vector_cross(v2, v1, n);
}
static void
do_normal(GLfloat x1, GLfloat y1, GLfloat z1,
GLfloat x2, GLfloat y2, GLfloat z2,
GLfloat x3, GLfloat y3, GLfloat z3)
{
plane plane;
vector n;
vector_set(&plane.p1, x1, y1, z1);
vector_set(&plane.p2, x2, y2, z2);
vector_set(&plane.p3, x3, y3, z3);
plane_normal(plane, &n);
n.x = -n.x;
n.y = -n.y;
n.z = -n.z;
glNormal3f(n.x, n.y, n.z);
#ifdef DEBUG
/* Draw a line in the direction of this face's normal. */
{
GLfloat ax = n.x > 0 ? n.x : -n.x;
GLfloat ay = n.y > 0 ? n.y : -n.y;
GLfloat az = n.z > 0 ? n.z : -n.z;
GLfloat mx = (x1 + x2 + x3) / 3;
GLfloat my = (y1 + y2 + y3) / 3;
GLfloat mz = (z1 + z2 + z3) / 3;
GLfloat xx, yy, zz;
GLfloat max = ax > ay ? ax : ay;
if (az > max)
max = az;
max *= 2;
xx = n.x / max;
yy = n.y / max;
zz = n.z / max;
glBegin(GL_LINE_LOOP);
glVertex3f(mx, my, mz);
glVertex3f(mx + xx, my + yy, mz + zz);
glEnd();
}
#endif /* DEBUG */
}
/* Shorthand utilities for making faces, with proper normals.
*/
static void
set_colors (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
face3(GLint texture, GLfloat * color, Bool wire,
GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3)
{
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, texture);
#endif /* HAVE_GLBINDTEXTURE */
set_colors(color);
do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
glTexCoord2f(s1, t1);
glVertex3f(x1, y1, z1);
glTexCoord2f(s2, t2);
glVertex3f(x2, y2, z2);
glTexCoord2f(s3, t3);
glVertex3f(x3, y3, z3);
glEnd();
}
static void
face4(GLint texture, GLfloat * color, Bool wire,
GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4)
{
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, texture);
#endif /* HAVE_GLBINDTEXTURE */
set_colors(color);
do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
glTexCoord2f(s1, t1);
glVertex3f(x1, y1, z1);
glTexCoord2f(s2, t2);
glVertex3f(x2, y2, z2);
glTexCoord2f(s3, t3);
glVertex3f(x3, y3, z3);
glTexCoord2f(s4, t4);
glVertex3f(x4, y4, z4);
glEnd();
}
static void
face5(GLint texture, GLfloat * color, Bool wire,
GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4,
GLfloat s5, GLfloat t5, GLfloat x5, GLfloat y5, GLfloat z5)
{
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, texture);
#endif /* HAVE_GLBINDTEXTURE */
set_colors(color);
do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
glTexCoord2f(s1, t1);
glVertex3f(x1, y1, z1);
glTexCoord2f(s2, t2);
glVertex3f(x2, y2, z2);
glTexCoord2f(s3, t3);
glVertex3f(x3, y3, z3);
glTexCoord2f(s4, t4);
glVertex3f(x4, y4, z4);
glTexCoord2f(s5, t5);
glVertex3f(x5, y5, z5);
glEnd();
}
/* Creating object models
*/
static void
box(ModeInfo * mi, Bool wire)
{
lament_configuration *lc = &lcs[MI_SCREEN(mi)];
glNewList(lc->box, GL_COMPILE);
glShadeModel(GL_SMOOTH);
/* N */
face4(lc->texids[FACE_N], exterior_color, wire,
0.0, 0.0, -0.5, 0.5, 0.5,
1.0, 0.0, 0.5, 0.5, 0.5,
1.0, 1.0, 0.5, 0.5, -0.5,
0.0, 1.0, -0.5, 0.5, -0.5);
/* S */
face4(lc->texids[FACE_S], exterior_color, wire,
0.0, 0.0, -0.5, -0.5, -0.5,
1.0, 0.0, 0.5, -0.5, -0.5,
1.0, 1.0, 0.5, -0.5, 0.5,
0.0, 1.0, -0.5, -0.5, 0.5);
/* E */
face4(lc->texids[FACE_E], exterior_color, wire,
0.0, 0.0, 0.5, -0.5, -0.5,
1.0, 0.0, 0.5, 0.5, -0.5,
1.0, 1.0, 0.5, 0.5, 0.5,
0.0, 1.0, 0.5, -0.5, 0.5);
/* W */
face4(lc->texids[FACE_W], exterior_color, wire,
1.0, 1.0, -0.5, -0.5, 0.5,
0.0, 1.0, -0.5, 0.5, 0.5,
0.0, 0.0, -0.5, 0.5, -0.5,
1.0, 0.0, -0.5, -0.5, -0.5);
/* U */
face4(lc->texids[FACE_U], exterior_color, wire,
1.0, 0.0, 0.5, -0.5, 0.5,
1.0, 1.0, 0.5, 0.5, 0.5,
0.0, 1.0, -0.5, 0.5, 0.5,
0.0, 0.0, -0.5, -0.5, 0.5);
/* D */
face4(lc->texids[FACE_D], exterior_color, wire,
0.0, 1.0, -0.5, -0.5, -0.5,
0.0, 0.0, -0.5, 0.5, -0.5,
1.0, 0.0, 0.5, 0.5, -0.5,
1.0, 1.0, 0.5, -0.5, -0.5);
glEndList();
}
static void
star(ModeInfo * mi, Bool top, Bool wire)
{
lament_configuration *lc = &lcs[MI_SCREEN(mi)];
int i;
int points[][2] =
{
{ 77, 74 }, { 60, 98 }, { 0, 71 }, { 0, 0 }, /* L1 */
{ 60, 98 }, { 55, 127 }, { 0, 127 }, { 0, 71 }, /* L2 */
{ 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */
{ 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */
{ 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */
{ 100, 193 }, { 127, 198 }, { 127, 255 }, { 74, 255 }, /* B2 */
{ 127, 198 }, { 151, 193 }, { 180, 255 }, { 127, 255 }, /* B3 */
{ 151, 193 }, { 178, 177 }, { 255, 255 }, { 180, 255 }, /* B4 */
{ 178, 177 }, { 193, 155 }, { 255, 181 }, { 255, 255 }, /* R4 */
{ 193, 155 }, { 199, 127 }, { 255, 127 }, { 255, 181 }, /* R3 */
{ 199, 127 }, { 194, 99 }, { 255, 74 }, { 255, 127 }, /* R2 */
{ 194, 99 }, { 179, 76 }, { 255, 0 }, { 255, 74 }, /* R1 */
{ 179, 76 }, { 155, 60 }, { 180, 0 }, { 255, 0 }, /* T4 */
{ 155, 60 }, { 126, 55 }, { 126, 0 }, { 180, 0 }, /* T3 */
{ 126, 55 }, { 100, 60 }, { 75, 0 }, { 126, 0 }, /* T2 */
{ 100, 60 }, { 77, 74 }, { 0, 0 }, { 75, 0 }, /* T1 */
};
for (i = 0; i < countof(points); i++)
points[i][1] = 255 - points[i][1];
if (top)
glNewList(lc->star1, GL_COMPILE);
else
glNewList(lc->star2, GL_COMPILE);
if (!top)
glRotatef(-180.0, 1.0, 0.0, 0.0);
for (i = 0; i < countof(points) / 4; i += 2) {
int j, k;
/* Top face.
*/
GLfloat s[4], t[4], x[4], y[4], z[4];
for (j = 3, k = 0; j >= 0; j--, k++) {
GLfloat xx = points[(i * 4) + j][0] / 255.0L;
GLfloat yy = points[(i * 4) + j][1] / 255.0L;
s[k] = xx;
t[k] = yy;
x[k] = xx - 0.5;
y[k] = yy - 0.5;
z[k] = 0.5;
}
face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
s[0], t[0], x[0], y[0], z[0],
s[1], t[1], x[1], y[1], z[1],
s[2], t[2], x[2], y[2], z[2],
s[3], t[3], x[3], y[3], z[3]);
/* Bottom face.
*/
for (j = 0, k = 0; j < 4; j++, k++) {
GLfloat xx = points[(i * 4) + j][0] / 255.0L;
GLfloat yy = points[(i * 4) + j][1] / 255.0L;
s[k] = xx;
t[k] = 1.0 - yy;
x[k] = xx - 0.5;
y[k] = yy - 0.5;
z[k] = -0.5;
}
face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
s[0], t[0], x[0], y[0], z[0],
s[1], t[1], x[1], y[1], z[1],
s[2], t[2], x[2], y[2], z[2],
s[3], t[3], x[3], y[3], z[3]);
/* Connecting faces.
*/
for (j = 3; j >= 0; j--) {
int l = (j == 0 ? 3 : j - 1);
Bool front_p = (j == 3);
GLfloat x1 = points[(i * 4) + j][0] / 255.0L;
GLfloat y1 = points[(i * 4) + j][1] / 255.0L;
GLfloat x2 = points[(i * 4) + l][0] / 255.0L;
GLfloat y2 = points[(i * 4) + l][1] / 255.0L;
GLfloat tx1 = 0.0, tx2 = 1.0, ty1 = 0.0, ty2 = 1.0;
int texture = 0;
int facing = i / 4;
facing = (facing + j + 5) % 4;
switch (facing) {
case 0:
texture = FACE_W;
if (top) {
tx1 = 1.0 - y1;
tx2 = 1.0 - y2;
ty1 = 0.0;
ty2 = 1.0;
} else {
tx1 = y1;
tx2 = y2;
ty1 = 1.0;
ty2 = 0.0;
}
break;
case 1:
texture = top ? FACE_S : FACE_N;
tx1 = x1;
tx2 = x2;
ty1 = 0.0;
ty2 = 1.0;
break;
case 2:
texture = FACE_E;
if (top) {
tx1 = y1;
tx2 = y2;
ty1 = 0.0;
ty2 = 1.0;
} else {
tx1 = 1.0 - y1;
tx2 = 1.0 - y2;
ty1 = 1.0;
ty2 = 0.0;
}
break;
case 3:
texture = top ? FACE_N : FACE_S;
tx1 = x1;
tx2 = x2;
ty1 = 1.0;
ty2 = 0.0;
break;
}
x1 -= 0.5;
x2 -= 0.5;
y1 -= 0.5;
y2 -= 0.5;
face4(front_p ? lc->texids[texture] : 0,
front_p ? exterior_color : interior_color,
wire,
tx1, ty2, x1, y1, 0.5,
tx1, ty1, x1, y1, -0.5,
tx2, ty1, x2, y2, -0.5,
tx2, ty2, x2, y2, 0.5);
}
}
/* Central core top cap.
*/
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]);
#endif /* HAVE_GLBINDTEXTURE */
set_colors(exterior_color);
i = 1;
do_normal(points[i + 0][0], points[i + 0][1], 0,
points[i + 4][0], points[i + 4][1], 0,
points[i + 8][0], points[i + 8][1], 0);
glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
for (i = 1; i < countof(points); i += 4) {
GLfloat x = points[i][0] / 255.0L;
GLfloat y = points[i][1] / 255.0L;
glTexCoord2f(x, y);
glVertex3f(x - 0.5, y - 0.5, 0.5);
}
glEnd();
/* Central core bottom cap.
*/
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, 0);
#endif /* HAVE_GLBINDTEXTURE */
set_colors(interior_color);
/* Range changed from "countof(points) - 3" to avoid Stack array bounds read */
i = countof(points) - 9;
do_normal(points[i + 0][0], points[i + 0][1], 0,
points[i + 4][0], points[i + 4][1], 0,
points[i + 8][0], points[i + 8][1], 0);
glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
for (i = countof(points) - 3; i >= 0; i -= 4) {
GLfloat x = points[i][0] / 255.0L;
GLfloat y = points[i][1] / 255.0L;
glVertex3f(x - 0.5, y - 0.5, 0);
}
glEnd();
/* Central core walls.
*/
for (i = 1; i < countof(points); i += 4) {
GLfloat x1 = points[i - 1][0] / 255.0L;
GLfloat y1 = points[i - 1][1] / 255.0L;
GLfloat x2 = points[i][0] / 255.0L;
GLfloat y2 = points[i][1] / 255.0L;
face4(0, interior_color, wire,
0.0, 0.0, x1 - 0.5, y1 - 0.5, 0.5,
0.0, 0.0, x1 - 0.5, y1 - 0.5, 0.0,
0.0, 0.0, x2 - 0.5, y2 - 0.5, 0.0,
0.0, 0.0, x2 - 0.5, y2 - 0.5, 0.5);
}
glEndList();
}
static void
tetra(ModeInfo * mi, Bool wire)
{
lament_configuration *lc = &lcs[MI_SCREEN(mi)];
glNewList(lc->tetra_une, GL_COMPILE);
{
glShadeModel(GL_SMOOTH);
/* Ua */
face3(lc->texids[FACE_U], exterior_color, wire,
1.0, 0.0, 0.5, -0.5, 0.5,
1.0, 1.0, 0.5, 0.5, 0.5,
0.0, 1.0, -0.5, 0.5, 0.5);
/* Na */
face3(lc->texids[FACE_N], exterior_color, wire,
0.0, 0.0, -0.5, 0.5, 0.5,
1.0, 0.0, 0.5, 0.5, 0.5,
1.0, 1.0, 0.5, 0.5, -0.5);
/* Eb */
face3(lc->texids[FACE_E], exterior_color, wire,
1.0, 0.0, 0.5, 0.5, -0.5,
1.0, 1.0, 0.5, 0.5, 0.5,
0.0, 1.0, 0.5, -0.5, 0.5);
face3(0, interior_color, wire,
0.0, 0.0, 0.5, 0.5, -0.5,
0.0, 0.0, 0.5, -0.5, 0.5,
0.0, 0.0, -0.5, 0.5, 0.5);
}
glEndList();
glNewList(lc->tetra_usw, GL_COMPILE);
{
/* Ub */
face3(lc->texids[FACE_U], exterior_color, wire,
0.0, 1.0, -0.5, 0.5, 0.5,
0.0, 0.0, -0.5, -0.5, 0.5,
1.0, 0.0, 0.5, -0.5, 0.5);
/* Sb */
face3(lc->texids[FACE_S], exterior_color, wire,
1.0, 1.0, 0.5, -0.5, 0.5,
0.0, 1.0, -0.5, -0.5, 0.5,
0.0, 0.0, -0.5, -0.5, -0.5);
/* Wb */
face3(lc->texids[FACE_W], exterior_color, wire,
1.0, 0.0, -0.5, -0.5, -0.5,
1.0, 1.0, -0.5, -0.5, 0.5,
0.0, 1.0, -0.5, 0.5, 0.5);
face3(0, interior_color, wire,
0.0, 0.0, -0.5, -0.5, -0.5,
0.0, 0.0, -0.5, 0.5, 0.5,
0.0, 0.0, 0.5, -0.5, 0.5);
}
glEndList();
glNewList(lc->tetra_dwn, GL_COMPILE);
{
/* Db */
face3(lc->texids[FACE_D], exterior_color, wire,
0.0, 1.0, -0.5, -0.5, -0.5,
0.0, 0.0, -0.5, 0.5, -0.5,
1.0, 0.0, 0.5, 0.5, -0.5);
/* Wa */
face3(lc->texids[FACE_W], exterior_color, wire,
0.0, 1.0, -0.5, 0.5, 0.5,
0.0, 0.0, -0.5, 0.5, -0.5,
1.0, 0.0, -0.5, -0.5, -0.5);
/* Nb */
face3(lc->texids[FACE_N], exterior_color, wire,
1.0, 1.0, 0.5, 0.5, -0.5,
0.0, 1.0, -0.5, 0.5, -0.5,
0.0, 0.0, -0.5, 0.5, 0.5);
face3(0, interior_color, wire,
0.0, 0.0, 0.5, 0.5, -0.5,
0.0, 0.0, -0.5, 0.5, 0.5,
0.0, 0.0, -0.5, -0.5, -0.5);
}
glEndList();
glNewList(lc->tetra_dse, GL_COMPILE);
{
/* Sa */
face3(lc->texids[FACE_S], exterior_color, wire,
0.0, 0.0, -0.5, -0.5, -0.5,
1.0, 0.0, 0.5, -0.5, -0.5,
1.0, 1.0, 0.5, -0.5, 0.5);
/* Ea */
face3(lc->texids[FACE_E], exterior_color, wire,
0.0, 1.0, 0.5, -0.5, 0.5,
0.0, 0.0, 0.5, -0.5, -0.5,
1.0, 0.0, 0.5, 0.5, -0.5);
/* Da */
face3(lc->texids[FACE_D], exterior_color, wire,
1.0, 0.0, 0.5, 0.5, -0.5,
1.0, 1.0, 0.5, -0.5, -0.5,
0.0, 1.0, -0.5, -0.5, -0.5);
face3(0, interior_color, wire,
0.0, 0.0, 0.5, -0.5, 0.5,
0.0, 0.0, 0.5, 0.5, -0.5,
0.0, 0.0, -0.5, -0.5, -0.5);
}
glEndList();
glNewList(lc->tetra_mid, GL_COMPILE);
{
face3(0, interior_color, wire,
0.0, 0.0, 0.5, -0.5, 0.5,
0.0, 0.0, 0.5, 0.5, -0.5,
0.0, 0.0, -0.5, 0.5, 0.5);
face3(0, interior_color, wire,
0.0, 0.0, -0.5, 0.5, 0.5,
0.0, 0.0, -0.5, -0.5, -0.5,
0.0, 0.0, 0.5, -0.5, 0.5);
face3(0, interior_color, wire,
0.0, 0.0, -0.5, 0.5, 0.5,
0.0, 0.0, 0.5, 0.5, -0.5,
0.0, 0.0, -0.5, -0.5, -0.5);
face3(0, interior_color, wire,
0.0, 0.0, 0.5, 0.5, -0.5,
0.0, 0.0, 0.5, -0.5, 0.5,
0.0, 0.0, -0.5, -0.5, -0.5);
face3(0, interior_color, wire,
0.0, 0.0, 0.5, -0.5, 0.5,
0.0, 0.0, 0.5, 0.5, -0.5,
0.0, 0.0, -0.5, -0.5, -0.5);
}
glEndList();
}
static void
lid(ModeInfo * mi, Bool wire)
{
lament_configuration *lc = &lcs[MI_SCREEN(mi)];
int i;
int points[][2] =
{
{128, 20},
{21, 129},
{0, 129},
{0, 0},
{128, 0}, /* L1 */
{21, 129},
{127, 234},
{127, 255},
{0, 255},
{0, 129}, /* L2 */
{127, 234},
{233, 127},
{255, 127},
{255, 255},
{127, 255}, /* R2 */
{233, 127},
{128, 20},
{128, 0},
{255, 0},
{255, 127}, /* R1 */
};
for (i = 0; i < countof(points); i++)
points[i][1] = 255 - points[i][1];
glNewList(lc->lid_0, GL_COMPILE);
glShadeModel(GL_SMOOTH);
/* N */
face4(lc->texids[FACE_N], exterior_color, wire,
0.0, 0.0, -0.5, 0.5, 0.5,
1.0, 0.0, 0.5, 0.5, 0.5,
1.0, 1.0, 0.5, 0.5, -0.5,
0.0, 1.0, -0.5, 0.5, -0.5);
/* S */
face4(lc->texids[FACE_S], exterior_color, wire,
0.0, 0.0, -0.5, -0.5, -0.5,
1.0, 0.0, 0.5, -0.5, -0.5,
1.0, 1.0, 0.5, -0.5, 0.5,
0.0, 1.0, -0.5, -0.5, 0.5);
/* E */
face4(lc->texids[FACE_E], exterior_color, wire,
0.0, 0.0, 0.5, -0.5, -0.5,
1.0, 0.0, 0.5, 0.5, -0.5,
1.0, 1.0, 0.5, 0.5, 0.5,
0.0, 1.0, 0.5, -0.5, 0.5);
/* U */
face4(lc->texids[FACE_U], exterior_color, wire,
1.0, 0.0, 0.5, -0.5, 0.5,
1.0, 1.0, 0.5, 0.5, 0.5,
0.0, 1.0, -0.5, 0.5, 0.5,
0.0, 0.0, -0.5, -0.5, 0.5);
/* D */
face4(lc->texids[FACE_D], exterior_color, wire,
0.0, 1.0, -0.5, -0.5, -0.5,
0.0, 0.0, -0.5, 0.5, -0.5,
1.0, 0.0, 0.5, 0.5, -0.5,
1.0, 1.0, 0.5, -0.5, -0.5);
/* W -- lid_0 */
for (i = 0; i < countof(points) / 5; i++) {
int j;
GLfloat s[5], t[5], x[5], y[5], z[5];
for (j = 0; j < 5; j++) {
GLfloat xx = points[(i * 5) + j][0] / 255.0L;
GLfloat yy = points[(i * 5) + j][1] / 255.0L;
s[j] = 1.0 - xx;
t[j] = yy;
x[j] = -0.5;
y[j] = xx - 0.5;
z[j] = yy - 0.5;
}
face5(lc->texids[FACE_W], exterior_color, wire,
s[0], t[0], x[0], y[0], z[0],
s[1], t[1], x[1], y[1], z[1],
s[2], t[2], x[2], y[2], z[2],
s[3], t[3], x[3], y[3], z[3],
s[4], t[4], x[4], y[4], z[4]);
}
glEndList();
/* W -- lid_1 through lid_4 */
for (i = 0; i < 4; i++) {
GLfloat x1, y1, x2, y2, x3, y3;
glNewList(lc->lid_1 + i, GL_COMPILE);
glShadeModel(GL_SMOOTH);
x1 = points[(i * 5) + 1][0] / 255.0L;
y1 = points[(i * 5) + 1][1] / 255.0L;
x2 = points[(i * 5)][0] / 255.0L;
y2 = points[(i * 5)][1] / 255.0L;
x3 = 0.5;
y3 = 0.5;
/* Outer surface */
face3(lc->texids[FACE_W], exterior_color, wire,
1.0 - x1, y1, -0.5, x1 - 0.5, y1 - 0.5,
1.0 - x2, y2, -0.5, x2 - 0.5, y2 - 0.5,
1.0 - x3, y3, -0.5, x3 - 0.5, y3 - 0.5);
/* Inner surface */
face3(0, interior_color, wire,
0.0, 0.0, -0.48, x2 - 0.5, y2 - 0.5,
0.0, 0.0, -0.48, x1 - 0.5, y1 - 0.5,
0.0, 0.0, -0.48, x3 - 0.5, y3 - 0.5);
/* Lip 1 */
face4(0, interior_color, wire,
0.0, 0.0, -0.5, x1 - 0.5, y1 - 0.5,
0.0, 0.0, -0.5, x3 - 0.5, y3 - 0.5,
0.0, 0.0, -0.48, x3 - 0.5, y3 - 0.5,
0.0, 0.0, -0.48, x1 - 0.5, y1 - 0.5);
/* Lip 2 */
face4(0, interior_color, wire,
0.0, 0.0, -0.48, x2 - 0.5, y2 - 0.5,
0.0, 0.0, -0.48, x3 - 0.5, y3 - 0.5,
0.0, 0.0, -0.5, x3 - 0.5, y3 - 0.5,
0.0, 0.0, -0.5, x2 - 0.5, y2 - 0.5);
glEndList();
}
}
static void
taser(ModeInfo * mi, Bool wire)
{
lament_configuration *lc = &lcs[MI_SCREEN(mi)];
int i;
int slider_face_points[][2] =
{
{86, 58},
{38, 106},
{70, 106},
{118, 58},
{-1, -1}, /* a */
{136, 58},
{184, 106},
{216, 106},
{168, 58},
{-1, -1}, /* b */
{38, 106},
{0, 144},
{0, 190},
{60, 190},
{108, 106}, /* c */
{144, 106},
{194, 190},
{254, 190},
{254, 144},
{216, 106}, /* d */
{98, 124},
{60, 190},
{92, 190},
{126, 158},
{126, 124}, /* e */
{126, 124},
{126, 158},
{160, 190},
{194, 190},
{154, 124}, /* f */
{22, 190},
{22, 254},
{60, 254},
{60, 190},
{-1, -1}, /* g */
{194, 190},
{194, 254},
{230, 254},
{230, 190},
{-1, -1}, /* h */
{60, 190},
{60, 210},
{92, 210},
{92, 190},
{-1, -1}, /* i */
{160, 190},
{160, 210},
{194, 210},
{194, 190},
{-1, -1}, /* j */
{110, 172},
{92, 190},
{110, 190},
{-1, -1},
{-1, -1}, /* k */
{140, 172},
{140, 190},
{160, 190},
{-1, -1},
{-1, -1}, /* l */
{110, 172},
{140, 172},
{126, 156},
{-1, -1},
{-1, -1}, /* m */
};
int body_face_points[][2] =
{
{0, 0},
{0, 58},
{254, 58},
{254, 0},
{-1, -1}, /* A */
{0, 58},
{0, 144},
{86, 58},
{-1, -1},
{-1, -1}, /* B */
{168, 58},
{254, 144},
{254, 58},
{-1, -1},
{-1, -1}, /* C */
{118, 58},
{70, 106},
{184, 106},
{136, 58},
{-1, -1}, /* F */
{108, 106},
{98, 124},
{154, 124},
{144, 106},
{-1, -1}, /* G */
};
int lifter_face_points[][2] =
{
{0, 190},
{0, 254},
{22, 254},
{22, 190},
{-1, -1}, /* D */
{230, 190},
{230, 254},
{254, 254},
{254, 190},
{-1, -1}, /* E */
{60, 210},
{60, 254},
{194, 254},
{194, 210},
{-1, -1}, /* H */
{92, 190},
{92, 210},
{160, 210},
{160, 190},
{-1, -1}, /* I */
{110, 172},
{110, 190},
{140, 190},
{140, 172},
{-1, -1}, /* J */
};
int body_perimiter_points[][2] =
{
{0, 144},
{86, 59},
{119, 58},
{71, 107},
{108, 107},
{98, 124},
{155, 124},
{144, 107},
{185, 106},
{136, 59},
{169, 59},
{255, 145},
{255, 0},
{0, 0},
};
int slider_perimiter_points[][2] =
{
{86, 58},
{0, 144},
{0, 190},
{22, 190},
{22, 254},
{60, 254},
{60, 210},
{92, 210},
{92, 190},
{110, 190},
{110, 172},
{140, 172},
{140, 190},
{160, 190},
{160, 210},
{194, 210},
{194, 254},
{230, 254},
{230, 190},
{254, 190},
{254, 144},
{168, 58},
{136, 58},
{184, 106},
{144, 106},
{154, 124},
{98, 124},
{108, 106},
{70, 106},
{118, 58},
};
int lifter_perimiter_points_1[][2] =
{
{0, 189},
{0, 254},
{22, 255},
{23, 190},
};
int lifter_perimiter_points_2[][2] =
{
{230, 254},
{255, 255},
{254, 190},
{230, 190},
};
int lifter_perimiter_points_3[][2] =
{
{60, 254},
{194, 254},
{194, 211},
{160, 210},
{160, 190},
{140, 191},
{141, 172},
{111, 172},
{110, 190},
{93, 190},
{92, 210},
{60, 211},
};
for (i = 0; i < countof(slider_face_points); i++)
slider_face_points[i][1] = 255 - slider_face_points[i][1];
for (i = 0; i < countof(body_face_points); i++)
body_face_points[i][1] = 255 - body_face_points[i][1];
for (i = 0; i < countof(lifter_face_points); i++)
lifter_face_points[i][1] = 255 - lifter_face_points[i][1];
for (i = 0; i < countof(body_perimiter_points); i++)
body_perimiter_points[i][1] = 255 - body_perimiter_points[i][1];
for (i = 0; i < countof(slider_perimiter_points); i++)
slider_perimiter_points[i][1] = 255 - slider_perimiter_points[i][1];
for (i = 0; i < countof(lifter_perimiter_points_1); i++)
lifter_perimiter_points_1[i][1] = 255 - lifter_perimiter_points_1[i][1];
for (i = 0; i < countof(lifter_perimiter_points_2); i++)
lifter_perimiter_points_2[i][1] = 255 - lifter_perimiter_points_2[i][1];
for (i = 0; i < countof(lifter_perimiter_points_3); i++)
lifter_perimiter_points_3[i][1] = 255 - lifter_perimiter_points_3[i][1];
/* -------------------------------------------------------------------- */
glNewList(lc->taser_base, GL_COMPILE);
glShadeModel(GL_SMOOTH);
/* N */
face4(lc->texids[FACE_N], exterior_color, wire,
0.0, 0.0, -0.5, 0.5, 0.5,
0.75, 0.0, 0.25, 0.5, 0.5,
0.75, 0.75, 0.25, 0.5, -0.25,
0.0, 0.75, -0.5, 0.5, -0.25);
/* S */
face4(lc->texids[FACE_S], exterior_color, wire,
0.0, 0.25, -0.5, -0.5, -0.25,
0.75, 0.25, 0.25, -0.5, -0.25,
0.75, 1.0, 0.25, -0.5, 0.5,
0.0, 1.0, -0.5, -0.5, 0.5);
/* interior E */
face4(0, interior_color, wire,
0.0, 0.0, 0.25, -0.5, -0.25,
1.0, 0.0, 0.25, 0.5, -0.25,
1.0, 1.0, 0.25, 0.5, 0.5,
0.0, 1.0, 0.25, -0.5, 0.5);
/* W */
face4(lc->texids[FACE_W], exterior_color, wire,
1.0, 1.0, -0.5, -0.5, 0.5,
0.0, 1.0, -0.5, 0.5, 0.5,
0.0, 0.25, -0.5, 0.5, -0.25,
1.0, 0.25, -0.5, -0.5, -0.25);
/* U */
face4(lc->texids[FACE_U], exterior_color, wire,
0.75, 0.0, 0.25, -0.5, 0.5,
0.75, 1.0, 0.25, 0.5, 0.5,
0.0, 1.0, -0.5, 0.5, 0.5,
0.0, 0.0, -0.5, -0.5, 0.5);
/* interior D */
face4(0, interior_color, wire,
0.0, 1.0, -0.5, -0.5, -0.25,
0.0, 0.0, -0.5, 0.5, -0.25,
1.0, 0.0, 0.25, 0.5, -0.25,
1.0, 1.0, 0.25, -0.5, -0.25);
/* Top face */
for (i = 0; i < countof(body_face_points) / 5; i++) {
int j;
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
#endif /* HAVE_GLBINDTEXTURE */
set_colors(exterior_color);
do_normal(0, body_face_points[(i * 5) + 0][0], body_face_points[(i * 5) + 0][1],
0, body_face_points[(i * 5) + 1][0], body_face_points[(i * 5) + 1][1],
0, body_face_points[(i * 5) + 2][0], body_face_points[(i * 5) + 2][1]
);
glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
for (j = 0; j < 5; j++) {
int ix = body_face_points[(i * 5) + j][0];
int iy = body_face_points[(i * 5) + j][1];
GLfloat x, y;
if (ix == -1) /* these are padding: ignore them */
continue;
x = ix / 255.0L;
y = iy / 255.0L;
glTexCoord2f(x, y);
glVertex3f(0.5, x - 0.5, y - 0.5);
}
glEnd();
}
/* Side walls */
for (i = 0; i < countof(body_perimiter_points); i++) {
int j = (i + 1 >= countof(body_perimiter_points) ? 0 : i + 1);
GLfloat x1 = body_perimiter_points[i][0] / 255.0;
GLfloat y1 = body_perimiter_points[i][1] / 255.0;
GLfloat x2 = body_perimiter_points[j][0] / 255.0;
GLfloat y2 = body_perimiter_points[j][1] / 255.0;
int texture = -1;
GLfloat s1 = 0, t1 = 0, s2 = 0, t2 = 0, s3 = 0, t3 = 0,
s4 = 0, t4 = 0;
if (i == 11) {
texture = lc->texids[FACE_N];
s1 = 1.0;
t1 = 0.0;
s2 = 1.0;
t2 = 0.568;
s3 = 0.75, t3 = 0.568;
s4 = 0.75;
t4 = 0.0;
} else if (i == 12) {
texture = lc->texids[FACE_U];
s1 = 1.0;
t1 = 0.0;
s2 = 1.0;
t2 = 1.0;
s3 = 0.75, t3 = 1.0;
s4 = 0.75;
t4 = 0.0;
} else if (i == 13) {
texture = lc->texids[FACE_S];
s1 = 1.0;
t1 = 0.437;
s2 = 1.0;
t2 = 1.0;
s3 = 0.75;
t3 = 1.0;
s4 = 0.75;
t4 = 0.437;
}
face4((texture == -1 ? 0 : texture),
(texture == -1 ? interior_color : exterior_color),
wire,
s1, t1, 0.5, x2 - 0.5, y2 - 0.5,
s2, t2, 0.5, x1 - 0.5, y1 - 0.5,
s3, t3, 0.25, x1 - 0.5, y1 - 0.5,
s4, t4, 0.25, x2 - 0.5, y2 - 0.5);
}
glEndList();
/* -------------------------------------------------------------------- */
glNewList(lc->taser_lifter, GL_COMPILE);
glShadeModel(GL_SMOOTH);
/* N */
face4(lc->texids[FACE_N], exterior_color, wire,
0.0, 0.75, -0.5, 0.5, -0.25,
0.75, 0.75, 0.25, 0.5, -0.25,
0.75, 1.0, 0.25, 0.5, -0.5,
0.0, 1.0, -0.5, 0.5, -0.5);
/* S */
face4(lc->texids[FACE_S], exterior_color, wire,
0.0, 0.0, -0.5, -0.5, -0.5,
0.75, 0.0, 0.25, -0.5, -0.5,
0.75, 0.25, 0.25, -0.5, -0.25,
0.0, 0.25, -0.5, -0.5, -0.25);
/* interior E */
face4(0, interior_color, wire,
0.0, 1.0, 0.25, -0.5, -0.5,
1.0, 1.0, 0.25, 0.5, -0.5,
1.0, 0.0, 0.25, 0.5, -0.25,
0.0, 0.0, 0.25, -0.5, -0.25);
/* W */
face4(lc->texids[FACE_W], exterior_color, wire,
1.0, 0.25, -0.5, -0.5, -0.25,
0.0, 0.25, -0.5, 0.5, -0.25,
0.0, 0.0, -0.5, 0.5, -0.5,
1.0, 0.0, -0.5, -0.5, -0.5);
/* interior U */
face4(0, interior_color, wire,
1.0, 0.0, 0.25, -0.5, -0.25,
1.0, 1.0, 0.25, 0.5, -0.25,
0.0, 1.0, -0.5, 0.5, -0.25,
0.0, 0.0, -0.5, -0.5, -0.25);
/* D */
face4(lc->texids[FACE_D], exterior_color, wire,
0.0, 1.0, -0.5, -0.5, -0.5,
0.0, 0.0, -0.5, 0.5, -0.5,
0.75, 0.0, 0.25, 0.5, -0.5,
0.75, 1.0, 0.25, -0.5, -0.5);
/* Top face */
for (i = 0; i < countof(lifter_face_points) / 5; i++) {
int j;
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
#endif /* HAVE_GLBINDTEXTURE */
set_colors(exterior_color);
do_normal(
0, lifter_face_points[(i * 5) + 0][0], lifter_face_points[(i * 5) + 0][1],
0, lifter_face_points[(i * 5) + 1][0], lifter_face_points[(i * 5) + 1][1],
0, lifter_face_points[(i * 5) + 2][0], lifter_face_points[(i * 5) + 2][1]);
glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
for (j = 0; j < 5; j++) {
int ix = lifter_face_points[(i * 5) + j][0];
int iy = lifter_face_points[(i * 5) + j][1];
GLfloat x, y;
if (ix == -1) /* these are padding: ignore them */
continue;
x = ix / 255.0L;
y = iy / 255.0L;
glTexCoord2f(x, y);
glVertex3f(0.5, x - 0.5, y - 0.5);
}
glEnd();
}
/* Side walls */
for (i = 0; i < countof(lifter_perimiter_points_1); i++) {
int j = (i + 1 >= countof(lifter_perimiter_points_1) ? 0 : i + 1);
GLfloat x1 = lifter_perimiter_points_1[i][0] / 255.0;
GLfloat y1 = lifter_perimiter_points_1[i][1] / 255.0;
GLfloat x2 = lifter_perimiter_points_1[j][0] / 255.0;
GLfloat y2 = lifter_perimiter_points_1[j][1] / 255.0;
int texture = -1;
GLfloat s1 = 0, t1 = 0, s2 = 0, t2 = 0, s3 = 0, t3 = 0,
s4 = 0, t4 = 0;
if (i == 0) {
texture = lc->texids[FACE_S];
s1 = 1.0;
t1 = 0.0;
s2 = 1.0;
t2 = 0.26;
s3 = 0.75, t3 = 0.26;
s4 = 0.75;
t4 = 0.0;
} else if (i == 1) {
texture = lc->texids[FACE_D];
s1 = 1.0;
t1 = 0.914;
s2 = 1.0;
t2 = 1.0;
s3 = 0.75;
t3 = 1.0;
s4 = 0.75;
t4 = 0.914;
}
face4((texture == -1 ? 0 : texture),
(texture == -1 ? interior_color : exterior_color),
wire,
s1, t1, 0.5, x2 - 0.5, y2 - 0.5,
s2, t2, 0.5, x1 - 0.5, y1 - 0.5,
s3, t3, 0.25, x1 - 0.5, y1 - 0.5,
s4, t4, 0.25, x2 - 0.5, y2 - 0.5);
}
for (i = 0; i < countof(lifter_perimiter_points_2); i++) {
int j = (i + 1 >= countof(lifter_perimiter_points_2) ? 0 : i + 1);
GLfloat x1 = lifter_perimiter_points_2[i][0] / 255.0;
GLfloat y1 = lifter_perimiter_points_2[i][1] / 255.0;
GLfloat x2 = lifter_perimiter_points_2[j][0] / 255.0;
GLfloat y2 = lifter_perimiter_points_2[j][1] / 255.0;
int texture = -1;
GLfloat s1 = 0, t1 = 0, s2 = 0, t2 = 0, s3 = 0, t3 = 0,
s4 = 0, t4 = 0;
if (i == 0) {
texture = lc->texids[FACE_D];
s1 = 1.0;
t1 = 0.0;
s2 = 1.0;
t2 = 0.095;
s3 = 0.75;
t3 = 0.095;
s4 = 0.75;
t4 = 0.0;
} else if (i == 1) {
texture = lc->texids[FACE_N];
s1 = 1.0;
t1 = 0.745;
s2 = 1.0;
t2 = 1.0;
s3 = 0.75;
t3 = 1.0;
s4 = 0.75;
t4 = 0.745;
}
face4((texture == -1 ? 0 : texture),
(texture == -1 ? interior_color : exterior_color),
wire,
s1, t1, 0.5, x2 - 0.5, y2 - 0.5,
s2, t2, 0.5, x1 - 0.5, y1 - 0.5,
s3, t3, 0.25, x1 - 0.5, y1 - 0.5,
s4, t4, 0.25, x2 - 0.5, y2 - 0.5);
}
for (i = 0; i < countof(lifter_perimiter_points_3); i++) {
int j = (i + 1 >= countof(lifter_perimiter_points_3) ? 0 : i + 1);
GLfloat x1 = lifter_perimiter_points_3[i][0] / 255.0;
GLfloat y1 = lifter_perimiter_points_3[i][1] / 255.0;
GLfloat x2 = lifter_perimiter_points_3[j][0] / 255.0;
GLfloat y2 = lifter_perimiter_points_3[j][1] / 255.0;
int texture = -1;
GLfloat s1 = 0, t1 = 0, s2 = 0, t2 = 0, s3 = 0, t3 = 0,
s4 = 0, t4 = 0;
if (i == 0) {
texture = lc->texids[FACE_D];
s1 = 1.0;
t1 = 0.235;
s2 = 1.0;
t2 = 0.765;
s3 = 0.75;
t3 = 0.765;
s4 = 0.75;
t4 = 0.235;
}
face4((texture == -1 ? 0 : texture),
(texture == -1 ? interior_color : exterior_color),
wire,
s1, t1, 0.5, x2 - 0.5, y2 - 0.5,
s2, t2, 0.5, x1 - 0.5, y1 - 0.5,
s3, t3, 0.25, x1 - 0.5, y1 - 0.5,
s4, t4, 0.25, x2 - 0.5, y2 - 0.5);
}
glEndList();
/* -------------------------------------------------------------------- */
glNewList(lc->taser_slider, GL_COMPILE);
glShadeModel(GL_SMOOTH);
/* Top face */
for (i = 0; i < countof(slider_face_points) / 5; i++) {
int j;
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
#endif /* HAVE_GLBINDTEXTURE */
set_colors(exterior_color);
do_normal(
0, slider_face_points[(i * 5) + 0][0], slider_face_points[(i * 5) + 0][1],
0, slider_face_points[(i * 5) + 1][0], slider_face_points[(i * 5) + 1][1],
0, slider_face_points[(i * 5) + 2][0], slider_face_points[(i * 5) + 2][1]);
glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
for (j = 0; j < 5; j++) {
int ix = slider_face_points[(i * 5) + j][0];
int iy = slider_face_points[(i * 5) + j][1];
GLfloat x, y;
if (ix == -1) /* these are padding: ignore them */
continue;
x = ix / 255.0L;
y = iy / 255.0L;
glTexCoord2f(x, y);
glVertex3f(0.5, x - 0.5, y - 0.5);
}
glEnd();
}
/* Bottom face */
for (i = countof(slider_face_points) / 5 - 1; i >= 0; i--) {
int j;
#ifdef HAVE_GLBINDTEXTURE
glBindTexture(GL_TEXTURE_2D, 0);
#endif /* HAVE_GLBINDTEXTURE */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, interior_color);
do_normal(
0, slider_face_points[(i * 5) + 2][0], slider_face_points[(i * 5) + 2][1],
0, slider_face_points[(i * 5) + 1][0], slider_face_points[(i * 5) + 1][1],
0, slider_face_points[(i * 5) + 0][0], slider_face_points[(i * 5) + 0][1]);
glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
for (j = 4; j >= 0; j--) {
int ix = slider_face_points[(i * 5) + j][0];
int iy = slider_face_points[(i * 5) + j][1];
GLfloat x, y;
if (ix == -1) /* these are padding: ignore them */
continue;
x = ix / 255.0L;
y = iy / 255.0L;
glTexCoord2f(x, y);
glVertex3f(0.25, x - 0.5, y - 0.5);
}
glEnd();
}
/* Side walls */
for (i = 0; i < countof(slider_perimiter_points); i++) {
int j = (i + 1 >= countof(slider_perimiter_points) ? 0 : i + 1);
GLfloat x1 = slider_perimiter_points[i][0] / 255.0;
GLfloat y1 = slider_perimiter_points[i][1] / 255.0;
GLfloat x2 = slider_perimiter_points[j][0] / 255.0;
GLfloat y2 = slider_perimiter_points[j][1] / 255.0;
int texture = -1;
GLfloat s1 = 0, t1 = 0, s2 = 0, t2 = 0, s3 = 0, t3 = 0,
s4 = 0, t4 = 0;
if (i == 1) {
texture = lc->texids[FACE_S];
s1 = 1.0;
t1 = 0.255;
s2 = 1.0;
t2 = 0.435;
s3 = 0.75;
t3 = 0.435;
s4 = 0.75;
t4 = 0.255;
} else if (i == 4) {
texture = lc->texids[FACE_D];
s1 = 1.0;
t1 = 0.758;
s2 = 1.0;
t2 = 0.915;
s3 = 0.75;
t3 = 0.915;
s4 = 0.75;
t4 = 0.758;
} else if (i == 16) {
texture = lc->texids[FACE_D];
s1 = 1.0;
t1 = 0.095;
s2 = 1.0;
t2 = 0.24;
s3 = 0.75;
t3 = 0.24;
s4 = 0.75;
t4 = 0.095;
} else if (i == 19) {
texture = lc->texids[FACE_N];
s1 = 1.0;
t1 = 0.568;
s2 = 1.0;
t2 = 0.742;
s3 = 0.75;
t3 = 0.742;
s4 = 0.75;
t4 = 0.568;
}
face4((texture == -1 ? 0 : texture),
(texture == -1 ? interior_color : exterior_color),
wire,
s1, t1, 0.5, x2 - 0.5, y2 - 0.5,
s2, t2, 0.5, x1 - 0.5, y1 - 0.5,
s3, t3, 0.25, x1 - 0.5, y1 - 0.5,
s4, t4, 0.25, x2 - 0.5, y2 - 0.5);
}
glEndList();
}
/* Rendering and animating object models
*/
static void
draw(ModeInfo * mi)
{
lament_configuration *lc = &lcs[MI_SCREEN(mi)];
Bool wire = MI_IS_WIREFRAME(mi);
if (!wire)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
{
GLfloat x = lc->rotx;
GLfloat y = lc->roty;
GLfloat z = lc->rotz;
#if 0
x = 0.75;
y = 0;
z = 0;
#endif
if (x < 0)
x = 1 - (x + 1);
if (y < 0)
y = 1 - (y + 1);
if (z < 0)
z = 1 - (z + 1);
/* Make into the screen be +Y right be +X, and up be +Z. */
glRotatef(-90.0, 1.0, 0.0, 0.0);
/* Scale it up. */
glScalef(4.0, 4.0, 4.0);
#ifdef DEBUG
glPushMatrix();
{
/* Shift to the upper left, and draw the vanilla box. */
glTranslatef(-0.6, 0.0, 0.6);
/* Apply rotation to the object. */
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);
/* Draw it. */
glCallList(lc->box);
}
glPopMatrix();
/* Shift to the lower right, and draw the animated object. */
glTranslatef(0.6, 0.0, -0.6);
#endif /* DEBUG */
glPushMatrix();
{
/* Apply rotation to the object. */
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);
switch (lc->type) {
case LAMENT_BOX:
glCallList(lc->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->star1);
glTranslatef(0.0, 0.0, -lc->anim_z);
glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
glCallList(lc->star2);
break;
case LAMENT_TETRA_UNE:
case LAMENT_TETRA_USW:
case LAMENT_TETRA_DWN:
case LAMENT_TETRA_DSE:
{
unsigned int magic;
GLfloat tx, ty, tz;
switch (lc->type) {
case LAMENT_TETRA_UNE:
magic = lc->tetra_une;
tx = 1.0;
ty = 1.0;
tz = 1.0;
break;
case LAMENT_TETRA_USW:
magic = lc->tetra_usw;
tx = 1.0;
ty = 1.0;
tz = -1.0;
break;
case LAMENT_TETRA_DWN:
magic = lc->tetra_dwn;
tx = 1.0;
ty = -1.0;
tz = 1.0;
break;
case LAMENT_TETRA_DSE:
magic = lc->tetra_dse;
tx = -1.0;
ty = 1.0;
tz = 1.0;
break;
default:
magic = lc->tetra_une;
tx = 1.0;
ty = 1.0;
tz = 1.0;
if (MI_IS_VERBOSE(mi)) {
(void) fprintf(stderr, "Weirdness in draw()\n");
(void) fprintf(stderr, "type = %d\n", lc->type);
}
break;
}
glCallList(lc->tetra_mid);
if (magic != lc->tetra_une)
glCallList(lc->tetra_une);
if (magic != lc->tetra_usw)
glCallList(lc->tetra_usw);
if (magic != lc->tetra_dwn)
glCallList(lc->tetra_dwn);
if (magic != lc->tetra_dse)
glCallList(lc->tetra_dse);
glRotatef(lc->anim_r, tx, ty, tz);
glCallList(magic);
}
break;
case LAMENT_LID_OPEN:
case LAMENT_LID_CLOSE:
case LAMENT_LID_ZOOM:
{
GLfloat d = 0.417;
glTranslatef(lc->anim_z, 0.0, 0.0);
glCallList(lc->lid_0);
glPushMatrix();
glTranslatef(-0.5, -d, 0.0);
glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
glTranslatef(0.5, d, 0.0);
glCallList(lc->lid_1);
glPopMatrix();
glPushMatrix();
glTranslatef(-0.5, -d, 0.0);
glRotatef(lc->anim_r, 0.0, -1.0, 1.0);
glTranslatef(0.5, d, 0.0);
glCallList(lc->lid_2);
glPopMatrix();
glPushMatrix();
glTranslatef(-0.5, d, 0.0);
glRotatef(lc->anim_r, 0.0, -1.0, -1.0);
glTranslatef(0.5, -d, 0.0);
glCallList(lc->lid_3);
glPopMatrix();
glPushMatrix();
glTranslatef(-0.5, d, 0.0);
glRotatef(-lc->anim_r, 0.0, -1.0, 1.0);
glTranslatef(0.5, -d, 0.0);
glCallList(lc->lid_4);
glPopMatrix();
}
break;
case LAMENT_TASER_OUT:
case LAMENT_TASER_SLIDE:
case LAMENT_TASER_SLIDE_IN:
case LAMENT_TASER_IN:
glTranslatef(-lc->anim_z / 2, 0.0, 0.0);
glCallList(lc->taser_base);
glTranslatef(lc->anim_z, 0.0, 0.0);
glCallList(lc->taser_lifter);
glTranslatef(0.0, 0.0, lc->anim_y);
glCallList(lc->taser_slider);
break;
default:
if (MI_IS_VERBOSE(mi)) {
(void) fprintf(stderr, "Weirdness in draw()\n");
(void) fprintf(stderr, "type = %d\n", lc->type);
}
break;
}
}
glPopMatrix();
}
glPopMatrix();
}
static void
animate(ModeInfo * mi)
{
lament_configuration *lc = &lcs[MI_SCREEN(mi)];
int pause1 = 10;
/* int pause2 = 60; */
int pause3 = 120;
switch (lc->type) {
case LAMENT_BOX:
{
/* 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.)
*/
static lament_type states[] =
{
LAMENT_STAR_OUT, LAMENT_STAR_OUT,
LAMENT_TETRA_UNE, LAMENT_TETRA_USW,
LAMENT_TETRA_DWN, LAMENT_TETRA_DSE,
LAMENT_LID_OPEN, LAMENT_LID_OPEN, LAMENT_LID_OPEN,
LAMENT_TASER_OUT, LAMENT_TASER_OUT,
LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
};
static int state = countof(states);
if (state < countof(states)) {
lc->type = states[state++];
} else {
int i;
state = 0;
for (i = 0; i < countof(states); i++) {
int a = LRAND() % countof(states);
lament_type swap = states[a];
states[a] = states[i];
states[i] = swap;
}
}
if (lc->type == LAMENT_BOX)
lc->anim_pause = pause3;
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;
if (lc->anim_z >= 1.0) {
lc->anim_z = 1.0;
lc->type = LAMENT_STAR_ROT;
lc->anim_pause = pause1;
}
break;
case LAMENT_STAR_ROT:
lc->anim_r += 1.0;
if (lc->anim_r >= 45.0) {
lc->anim_r = 45.0;
lc->type = LAMENT_STAR_ROT_IN;
lc->anim_pause = pause1;
}
break;
case LAMENT_STAR_ROT_IN:
lc->anim_z -= 0.01;
if (lc->anim_z <= 0.0) {
lc->anim_z = 0.0;
lc->type = LAMENT_STAR_ROT_OUT;
lc->anim_pause = pause3 * (1 + (LRAND() % 4) + (LRAND() % 4));
}
break;
case LAMENT_STAR_ROT_OUT:
lc->anim_z += 0.01;
if (lc->anim_z >= 1.0) {
lc->anim_z = 1.0;
lc->type = LAMENT_STAR_UNROT;
lc->anim_pause = pause1;
}
break;
case LAMENT_STAR_UNROT:
lc->anim_r -= 1.0;
if (lc->anim_r <= 0.0) {
lc->anim_r = 0.0;
lc->type = LAMENT_STAR_IN;
lc->anim_pause = pause1;
}
break;
case LAMENT_STAR_IN:
lc->anim_z -= 0.01;
if (lc->anim_z <= 0.0) {
lc->anim_z = 0.0;
lc->type = LAMENT_BOX;
lc->anim_pause = pause3;
}
break;
/* -------------------------------------------------------------- */
case LAMENT_TETRA_UNE:
case LAMENT_TETRA_USW:
case LAMENT_TETRA_DWN:
case LAMENT_TETRA_DSE:
lc->anim_r += 1.0;
if (lc->anim_r >= 360.0) {
lc->anim_r = 0.0;
lc->type = LAMENT_BOX;
lc->anim_pause = pause3;
} else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0) {
lc->anim_r = 120.0;
lc->anim_pause = pause1;
} else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0) {
lc->anim_r = 240.0;
lc->anim_pause = pause1;
}
break;
/* -------------------------------------------------------------- */
case LAMENT_LID_OPEN:
lc->anim_r += 1.0;
if (lc->anim_r >= 112.0) {
GLfloat hysteresis = 0.05;
lc->anim_r = 112.0;
lc->anim_z = 0.0;
lc->anim_pause = pause3;
if (lc->rotx >= -hysteresis &&
lc->rotx <= hysteresis &&
((lc->rotz >= (0.25 - hysteresis) &&
lc->rotz <= (0.25 + hysteresis)) ||
(lc->rotz >= (-0.25 - hysteresis) &&
lc->rotz <= (-0.25 + hysteresis)))) {
lc->type = LAMENT_LID_ZOOM;
lc->rotx = 0.00;
lc->rotz = (lc->rotz < 0 ? -0.25 : 0.25);
} else {
lc->type = LAMENT_LID_CLOSE;
}
}
break;
case LAMENT_LID_CLOSE:
lc->anim_r -= 1.0;
if (lc->anim_r <= 0.0) {
lc->anim_r = 0.0;
lc->type = LAMENT_BOX;
lc->anim_pause = pause3;
}
break;
case LAMENT_LID_ZOOM:
lc->anim_z -= 0.1;
if (lc->anim_z < -50.0) {
lc->anim_r = 0.0;
lc->anim_z = 0.0;
lc->rotx = FLOATRAND(1.0) * RANDSIGN();
lc->roty = FLOATRAND(1.0) * RANDSIGN();
lc->rotz = FLOATRAND(1.0) * RANDSIGN();
lc->type = LAMENT_BOX;
}
break;
/* -------------------------------------------------------------- */
case LAMENT_TASER_OUT:
lc->anim_z += 0.0025;
if (lc->anim_z >= 0.25) {
lc->anim_z = 0.25;
lc->type = LAMENT_TASER_SLIDE;
lc->anim_pause = pause1 * (1 + (LRAND() % 5) + (LRAND() % 5));
}
break;
case LAMENT_TASER_SLIDE:
lc->anim_y += 0.0025;
if (lc->anim_y >= 0.23) {
lc->anim_y = 0.23;
lc->type = LAMENT_TASER_SLIDE_IN;
lc->anim_pause = pause3 * (1 + (LRAND() % 5) + (LRAND() % 5));
}
break;
case LAMENT_TASER_SLIDE_IN:
lc->anim_y -= 0.0025;
if (lc->anim_y <= 0.0) {
lc->anim_y = 0.0;
lc->type = LAMENT_TASER_IN;
lc->anim_pause = pause1;
}
break;
case LAMENT_TASER_IN:
lc->anim_z -= 0.0025;
if (lc->anim_z <= 0.0) {
lc->anim_z = 0.0;
lc->type = LAMENT_BOX;
lc->anim_pause = pause3;
}
break;
default:
if (MI_IS_VERBOSE(mi)) {
(void) fprintf(stderr, "Weirdness in animate()\n");
(void) fprintf(stderr, "type = %d\n", lc->type);
}
break;
}
}
static void
rotate(GLfloat * pos, GLfloat * v, GLfloat * dv, GLfloat max_v, Bool verbose)
{
double ppos = *pos;
/* tick position */
if (ppos < 0)
ppos = -(ppos + *v);
else
ppos += *v;
if (ppos > 1.0)
ppos -= 1.0;
else if (ppos < 0)
ppos += 1.0;
if ((ppos < 0) || (ppos > 1.0)) {
if (verbose) {
(void) fprintf(stderr, "Weirdness in rotate()\n");
(void) fprintf(stderr, "ppos = %g\n", ppos);
}
return;
}
*pos = (*pos > 0 ? ppos : -ppos);
/* accelerate */
*v += *dv;
/* clamp velocity */
if (*v > max_v || *v < -max_v) {
*dv = -*dv;
}
/* If it stops, start it going in the other direction. */
else if (*v < 0) {
if (LRAND() % 4) {
*v = 0;
/* keep going in the same direction */
if (LRAND() % 2)
*dv = 0;
else if (*dv < 0)
*dv = -*dv;
} else {
/* reverse gears */
*v = -*v;
*dv = -*dv;
*pos = -*pos;
}
}
/* Alter direction of rotational acceleration randomly. */
if (!(LRAND() % 120))
*dv = -*dv;
/* Change acceleration very occasionally. */
if (!(LRAND() % 200)) {
if (*dv == 0)
*dv = 0.00001;
else if (LRAND() & 1)
*dv *= 1.2;
else
*dv *= 0.8;
}
}
/* Window management, etc
*/
static void
reshape_lament(int width, int height)
{
int target_size = 180;
int win_size = (width > height ? height : width);
GLfloat h = (GLfloat) height / (GLfloat) width;
glViewport(0, 0, (GLint) width, (GLint) height);
/* glViewport(-600, -600, 1800, 1800); */
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);
/* This scale makes the box take up most of the window */
glScalef(2.0, 2.0, 2.0);
/* But if the window is more than a little larger than our target size,
scale the object back down, so that the bits drawn on the screen end
up rougly target_size across (actually it ends up a little larger.)
Note that the image-map bits we have are 128x128. Therefore, if the
image is magnified a lot, it looks pretty blocky. So it's better to
have a 128x128 animation on a 1280x1024 screen that looks good, than
a 1024x1024 animation that looks really pixellated.
*/
if (win_size > target_size * 1.5) {
GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
ratio *= 2.0;
glScalef(ratio, ratio, ratio);
}
/* The depth buffer will be cleared, if needed, before the
* next frame. Right now we just want to black the screen.
*/
glClear(GL_COLOR_BUFFER_BIT);
}
static void
free_lament(Display *display, lament_configuration *lc)
{
if (lc->glx_context) {
glXMakeCurrent(display, lc->window, *(lc->glx_context));
if (glIsList(lc->box)) {
glDeleteLists(lc->box, 16);
lc->box = 0;
}
}
if (lc->texture != NULL) {
int i;
for (i = 0; i < 6; i++)
glDeleteTextures(1, &lc->texids[i]);
XDestroyImage(lc->texture);
lc->texture = None;
}
}
static Bool
gl_init(ModeInfo * mi)
{
lament_configuration *lc = &lcs[MI_SCREEN(mi)];
Bool wire = MI_IS_WIREFRAME(mi);
if (wire)
do_texture = False;
if (!wire) {
static GLfloat pos0[] = {-4.0, 2.0, 5.0, 1.0};
static GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0};
static GLfloat amb0[] = {0.7, 0.7, 0.7, 1.0};
/* static GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
static GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
static 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);
set_colors(exterior_color);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
/* glEnable(GL_LIGHT1); */
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_NORMALIZE);
glEnable(GL_CULL_FACE);
}
#ifdef HAVE_XPM
if (do_texture) {
#ifdef HAVE_GLBINDTEXTURE
int i;
#if ((XMESA_MAJOR_VERSION < 3 ) || (( XMESA_MAJOR_VERSION == 3 ) && (XMESA_MINOR_VERSION == 0 )))
/* E.Lassauge - 11/23/98
* It looks like there's a bug in MESA (up to 3.1beta1) for the
* "Default" texture (named '0'). For this texture
* I added a glBindTexture and the same glTexParameteri
* as for the specific textures. Now it does'nt core
* anymore.
*
* 22-mar-99 for latest version of Mesa this codes wipes
* out the structure on the sides of the cube. Leaving the code
* out did not crash the mode on my VMS system.
* Jouk
*/
glBindTexture(GL_TEXTURE_2D, 0);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, interior_color);
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);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
#endif /* MESA */
for (i = 0; i < 6; i++)
glGenTextures(1, &lc->texids[i]);
if ((lc->texture = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
MI_COLORMAP(mi), lament_faces)) == None) {
(void) fprintf(stderr, "unable to parse xpm data.\n");
for (i = 0; i < 6; i++)
glDeleteTextures(1, &lc->texids[i]);
do_texture = False;
}
else
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width);
for (i = 0; i < 6; i++) {
int height = lc->texture->width; /* assume square */
glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, exterior_color);
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)));
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);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
}
}
#else /* !HAVE_GLBINDTEXTURE */
(void) fprintf(stderr,
"this version of GL does not support multiple texture maps.\n"
"\tGet OpenGL 1.1.\n");
return True;
#endif /* !HAVE_GLBINDTEXTURE */
}
#endif
if ((lc->box = glGenLists(16)) == 0) {
free_lament(MI_DISPLAY(mi), lc);
return False;
}
lc->star1 = lc->box + 1;
lc->star2 = lc->box + 2;
lc->tetra_une = lc->box + 3;
lc->tetra_usw = lc->box + 4;
lc->tetra_dwn = lc->box + 5;
lc->tetra_dse = lc->box + 6;
lc->tetra_mid = lc->box + 7;
lc->lid_0 = lc->box + 8;
lc->lid_1 = lc->box + 9;
lc->lid_2 = lc->box + 10;
lc->lid_3 = lc->box + 11;
lc->lid_4 = lc->box + 12;
lc->taser_base = lc->box + 13;
lc->taser_lifter = lc->box + 14;
lc->taser_slider = lc->box + 15;
box(mi, wire);
star(mi, True, wire);
star(mi, False, wire);
tetra(mi, wire);
lid(mi, wire);
taser(mi, wire);
return True;
}
void
init_lament(ModeInfo * mi)
{
lament_configuration *lc;
if (lcs == NULL) {
if ((lcs = (lament_configuration *) calloc(MI_NUM_SCREENS(mi),
sizeof (lament_configuration))) == NULL) {
(void) fprintf(stderr, "out of memory\n");
return;
}
}
lc = &lcs[MI_SCREEN(mi)];
lc->window = MI_WINDOW(mi);
lc->rotx = FLOATRAND(1.0) * RANDSIGN();
lc->roty = FLOATRAND(1.0) * RANDSIGN();
lc->rotz = FLOATRAND(1.0) * RANDSIGN();
/* bell curve from 0-1.5 degrees, avg 0.75 */
lc->dx = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360 * 2);
lc->dy = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360 * 2);
lc->dz = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360 * 2);
lc->d_max = lc->dx * 2;
lc->ddx = 0.00006 + FLOATRAND(0.00003);
lc->ddy = 0.00006 + FLOATRAND(0.00003);
lc->ddz = 0.00006 + FLOATRAND(0.00003);
lc->ddx = 0.00001;
lc->ddy = 0.00001;
lc->ddz = 0.00001;
lc->type = LAMENT_BOX;
lc->anim_pause = 300 + (LRAND() % 100);
if ((lc->glx_context = init_GL(mi)) != NULL) {
reshape_lament(MI_WIDTH(mi), MI_HEIGHT(mi));
if (!gl_init(mi)) {
MI_CLEARWINDOW(mi);
}
} else {
MI_CLEARWINDOW(mi);
}
}
void
draw_lament(ModeInfo * mi)
{
static int tick = 0;
Display *display = MI_DISPLAY(mi);
Window window = MI_WINDOW(mi);
lament_configuration *lc;
if (lcs == NULL)
return;
lc = &lcs[MI_SCREEN(mi)];
if (!lc->glx_context)
return;
MI_IS_DRAWN(mi) = True;
glDrawBuffer(GL_BACK);
glXMakeCurrent(display, window, *(lc->glx_context));
draw(mi);
if (MI_IS_FPS(mi)) do_fps (mi);
glFinish();
glXSwapBuffers(display, window);
if (lc->type != LAMENT_LID_ZOOM) {
rotate(&lc->rotx, &lc->dx, &lc->ddx, lc->d_max, MI_IS_VERBOSE(mi));
rotate(&lc->roty, &lc->dy, &lc->ddy, lc->d_max, MI_IS_VERBOSE(mi));
rotate(&lc->rotz, &lc->dz, &lc->ddz, lc->d_max, MI_IS_VERBOSE(mi));
}
if (lc->anim_pause)
lc->anim_pause--;
else
animate(mi);
if (++tick > 500) {
tick = 0;
reshape_lament(MI_WIDTH(mi), MI_HEIGHT(mi));
}
}
void
change_lament(ModeInfo * mi)
{
lament_configuration *lc;
if (lcs == NULL)
return;
lc = &lcs[MI_SCREEN(mi)];
if (!lc->glx_context)
return;
/* probably something needs to be added here */
}
void
release_lament(ModeInfo * mi)
{
if (lcs != NULL) {
int screen;
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
free_lament(MI_DISPLAY(mi), &lcs[screen]);
free(lcs);
lcs = (lament_configuration *) NULL;
}
FreeAllGL(mi);
}
#endif