1 /* xscreensaver, Copyright (c) 1998 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* Animates Lemarchand's Box, the Lament Configuration. By jwz, 25-Jul-98.
16 * The "gold" color isn't quite right; it looks more like "yellow" than
19 * For some reason, the interior surfaces are shinier than the exterior
20 surfaces. I don't understand why, but this should be remedied.
22 * Perhaps use a slightly-bumpy or oily texture for the interior surfaces?
24 * Some of the edges don't line up perfectly (since the images are not
25 perfectly symetrical.) Something should be done about this; either
26 making the edges overlap slightly (instead of leaving gaps) or fixing
27 the images so that the edges may be symmetrical.
29 * I want the gold leaf to seem to be raised up from the surface, but I
30 think this isn't possible with OpenGL. Supposedly, OpenGL only
31 supports Gouraud shading (interpolating edge normals from face normals,
32 and shading smoothly) but bump-maps only work with Phong shading
33 (computing a normal for each rendered pixel.)
35 * As far as I can tell, OpenGL doesn't do shadows. As a result, the
36 forward-facing interior walls are drawn bright, not dark. If it was
37 casting shadows properly, it wouldn't matter so much that the edges
38 don't quite line up, because the lines would be black, and thus not
39 visible. But the edges don't match up, and so the bright interior
40 faces show through, and that sucks.
42 But apparently there are tricky ways around this:
43 http://reality.sgi.com/opengl/tips/rts/
44 I think these techniques require GLUT, however, which isn't
45 (currently) required by any other xscreensaver hacks.
47 * There should be strange lighting effects playing across the surface:
48 electric sparks, or little glittery blobs of light.
49 http://reality.sgi.com/opengl/tips/lensflare/ might provide guidance.
51 * Need to add some more modes, to effect the transition from the cube
52 shapes to the "spike" or "leviathan" shapes. I have extensive notes
53 on how these transformations occur, but unfortunately, due to camera
54 trickery, the transitions require dematerializations which do not
55 preserve object volume. But I suppose that's allowed, in
56 non-Euclidian or hyperdimensional spaces (since the extra mass could
57 simply be rotated along the axis to which one cannot point.)
59 The other hard thing about this is that the "leviathan" shapes contain
60 a much larger number of facets, and I modelled this whole thing by
61 hand, since I don't have any 3d-object-editing tools that I know how
62 to use (or that look like they would take any less than several months
63 to become even marginally proficient with...)
65 * Perhaps there should be a table top, on which it casts a shadow?
66 And then multiple light sources (for multiple shadows)?
68 * Needs music. ("Hellraiser Themes" by Coil: TORSO CD161; also
69 duplicated on the "Unnatural History 2" compilation, WORLN M04699.)
72 #include <X11/Intrinsic.h>
74 #define PROGCLASS "Lament"
75 #define HACK_INIT init_lament
76 #define HACK_DRAW draw_lament
77 #define HACK_RESHAPE reshape_lament
78 #define HACK_HANDLE_EVENT lament_handle_event
79 #define EVENT_MASK PointerMotionMask
80 #define lament_opts xlockmore_opts
81 #define DEFAULTS "*delay: 10000 \n" \
82 "*showFPS: False \n" \
83 "*wireframe: False \n" \
85 #include "xlockmore.h"
87 #ifdef USE_GL /* whole file */
90 #define countof(x) (sizeof((x))/sizeof((*x)))
92 #define DEF_TEXTURE "True"
94 static int do_texture;
95 static XrmOptionDescRec opts[] = {
96 {"-texture", ".lament.texture", XrmoptionNoArg, (caddr_t) "true" },
97 {"+texture", ".lament.texture", XrmoptionNoArg, (caddr_t) "false" },
100 static argtype vars[] = {
101 {(caddr_t *) &do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
104 ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL};
106 #include "xpm-ximage.h"
108 #include "gltrackball.h"
109 #include "../images/lament.xpm"
111 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
112 #define RANDSIGN() ((random() & 1) ? 1 : -1)
135 LAMENT_TASER_SLIDE_IN,
140 static GLfloat exterior_color[] = { 0.33, 0.22, 0.03, 1.00, /* ambient */
141 0.78, 0.57, 0.11, 1.00, /* specular */
142 0.99, 0.91, 0.81, 1.00, /* diffuse */
143 27.80 /* shininess */
145 static GLfloat interior_color[] = { 0.20, 0.20, 0.15, 1.00, /* ambient */
146 0.40, 0.40, 0.32, 1.00, /* specular */
147 0.99, 0.99, 0.81, 1.00, /* diffuse */
148 50.80 /* shininess */
153 GLXContext *glx_context;
155 double rotx, roty, rotz;
156 trackball_state *trackball;
159 GLuint box; /* display list IDs */
161 GLuint tetra_une, tetra_usw, tetra_dwn, tetra_dse, tetra_mid;
162 GLuint lid_0, lid_1, lid_2, lid_3, lid_4;
163 GLuint taser_base, taser_lifter, taser_slider;
165 XImage *texture; /* image bits */
166 GLuint texids[6]; /* texture map IDs */
167 lament_type type; /* which mode of the object is current */
169 int anim_pause; /* countdown before animating again */
170 GLfloat anim_r, anim_y, anim_z; /* relative position during anims */
172 } lament_configuration;
174 static lament_configuration *lcs = NULL;
184 parse_image_data(ModeInfo *mi)
186 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
187 lc->texture = xpm_to_ximage (mi->dpy,
194 /* Computing normal vectors (thanks to Nat Friedman <ndf@mit.edu>)
197 typedef struct vector {
201 typedef struct plane {
206 vector_set(vector *v, GLfloat x, GLfloat y, GLfloat z)
214 vector_cross(vector v1, vector v2, vector *v3)
216 v3->x = (v1.y * v2.z) - (v1.z * v2.y);
217 v3->y = (v1.z * v2.x) - (v1.x * v2.z);
218 v3->z = (v1.x * v2.y) - (v1.y * v2.x);
222 vector_subtract(vector v1, vector v2, vector *res)
224 res->x = v1.x - v2.x;
225 res->y = v1.y - v2.y;
226 res->z = v1.z - v2.z;
230 plane_normal(plane p, vector *n)
233 vector_subtract(p.p1, p.p2, &v1);
234 vector_subtract(p.p1, p.p3, &v2);
235 vector_cross(v2, v1, n);
239 do_normal(GLfloat x1, GLfloat y1, GLfloat z1,
240 GLfloat x2, GLfloat y2, GLfloat z2,
241 GLfloat x3, GLfloat y3, GLfloat z3)
245 vector_set(&plane.p1, x1, y1, z1);
246 vector_set(&plane.p2, x2, y2, z2);
247 vector_set(&plane.p3, x3, y3, z3);
248 plane_normal(plane, &n);
249 n.x = -n.x; n.y = -n.y; n.z = -n.z;
251 glNormal3f(n.x, n.y, n.z);
254 /* Draw a line in the direction of this face's normal. */
256 GLfloat ax = n.x > 0 ? n.x : -n.x;
257 GLfloat ay = n.y > 0 ? n.y : -n.y;
258 GLfloat az = n.z > 0 ? n.z : -n.z;
259 GLfloat mx = (x1 + x2 + x3) / 3;
260 GLfloat my = (y1 + y2 + y3) / 3;
261 GLfloat mz = (z1 + z2 + z3) / 3;
264 GLfloat max = ax > ay ? ax : ay;
265 if (az > max) max = az;
271 glBegin(GL_LINE_LOOP);
272 glVertex3f(mx, my, mz);
273 glVertex3f(mx+xx, my+yy, mz+zz);
281 /* Shorthand utilities for making faces, with proper normals.
285 set_colors (GLfloat *color)
287 glMaterialfv(GL_FRONT, GL_AMBIENT, color+0);
288 glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4);
289 glMaterialfv(GL_FRONT, GL_SPECULAR, color+8);
290 glMaterialfv(GL_FRONT, GL_SHININESS, color+12);
294 face3(GLint texture, GLfloat *color, Bool wire,
295 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
296 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
297 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3)
299 #ifdef HAVE_GLBINDTEXTURE
300 glBindTexture(GL_TEXTURE_2D, texture);
301 #endif /* HAVE_GLBINDTEXTURE */
304 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
305 glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
306 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
307 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
308 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
313 face4(GLint texture, GLfloat *color, Bool wire,
314 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
315 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
316 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
317 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4)
319 #ifdef HAVE_GLBINDTEXTURE
320 glBindTexture(GL_TEXTURE_2D, texture);
321 #endif /* HAVE_GLBINDTEXTURE */
323 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
324 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
325 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
326 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
327 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
328 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
333 face5(GLint texture, GLfloat *color, Bool wire,
334 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
335 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
336 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
337 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4,
338 GLfloat s5, GLfloat t5, GLfloat x5, GLfloat y5, GLfloat z5)
340 #ifdef HAVE_GLBINDTEXTURE
341 glBindTexture(GL_TEXTURE_2D, texture);
342 #endif /* HAVE_GLBINDTEXTURE */
344 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
345 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
346 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
347 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
348 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
349 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
350 glTexCoord2f(s5, t5); glVertex3f(x5, y5, z5);
356 /* Creating object models
360 box(ModeInfo *mi, Bool wire)
362 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
364 glNewList(lc->box, GL_COMPILE);
365 glShadeModel(GL_SMOOTH);
368 face4(lc->texids[FACE_N], exterior_color, wire,
369 0.0, 0.0, -0.5, 0.5, 0.5,
370 1.0, 0.0, 0.5, 0.5, 0.5,
371 1.0, 1.0, 0.5, 0.5, -0.5,
372 0.0, 1.0, -0.5, 0.5, -0.5);
375 face4(lc->texids[FACE_S], exterior_color, wire,
376 0.0, 0.0, -0.5, -0.5, -0.5,
377 1.0, 0.0, 0.5, -0.5, -0.5,
378 1.0, 1.0, 0.5, -0.5, 0.5,
379 0.0, 1.0, -0.5, -0.5, 0.5);
382 face4(lc->texids[FACE_E], exterior_color, wire,
383 0.0, 0.0, 0.5, -0.5, -0.5,
384 1.0, 0.0, 0.5, 0.5, -0.5,
385 1.0, 1.0, 0.5, 0.5, 0.5,
386 0.0, 1.0, 0.5, -0.5, 0.5);
389 face4(lc->texids[FACE_W], exterior_color, wire,
390 1.0, 1.0, -0.5, -0.5, 0.5,
391 0.0, 1.0, -0.5, 0.5, 0.5,
392 0.0, 0.0, -0.5, 0.5, -0.5,
393 1.0, 0.0, -0.5, -0.5, -0.5);
396 face4(lc->texids[FACE_U], exterior_color, wire,
397 1.0, 0.0, 0.5, -0.5, 0.5,
398 1.0, 1.0, 0.5, 0.5, 0.5,
399 0.0, 1.0, -0.5, 0.5, 0.5,
400 0.0, 0.0, -0.5, -0.5, 0.5);
403 face4(lc->texids[FACE_D], exterior_color, wire,
404 0.0, 1.0, -0.5, -0.5, -0.5,
405 0.0, 0.0, -0.5, 0.5, -0.5,
406 1.0, 0.0, 0.5, 0.5, -0.5,
407 1.0, 1.0, 0.5, -0.5, -0.5);
414 star(ModeInfo *mi, Bool top, Bool wire)
416 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
420 { 77, 74 }, { 60, 98 }, { 0, 71 }, { 0, 0 }, /* L1 */
421 { 60, 98 }, { 55, 127 }, { 0, 127 }, { 0, 71 }, /* L2 */
422 { 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */
423 { 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */
424 { 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */
425 { 100, 193 }, { 127, 198 }, { 127, 255 }, { 74, 255 }, /* B2 */
426 { 127, 198 }, { 151, 193 }, { 180, 255 }, { 127, 255 }, /* B3 */
427 { 151, 193 }, { 178, 177 }, { 255, 255 }, { 180, 255 }, /* B4 */
428 { 178, 177 }, { 193, 155 }, { 255, 181 }, { 255, 255 }, /* R4 */
429 { 193, 155 }, { 199, 127 }, { 255, 127 }, { 255, 181 }, /* R3 */
430 { 199, 127 }, { 194, 99 }, { 255, 74 }, { 255, 127 }, /* R2 */
431 { 194, 99 }, { 179, 76 }, { 255, 0 }, { 255, 74 }, /* R1 */
432 { 179, 76 }, { 155, 60 }, { 180, 0 }, { 255, 0 }, /* T4 */
433 { 155, 60 }, { 126, 55 }, { 126, 0 }, { 180, 0 }, /* T3 */
434 { 126, 55 }, { 100, 60 }, { 75, 0 }, { 126, 0 }, /* T2 */
435 { 100, 60 }, { 77, 74 }, { 0, 0 }, { 75, 0 }, /* T1 */
438 for (i = 0; i < countof(points); i++)
439 points[i][1] = 255-points[i][1];
442 glNewList(lc->star1, GL_COMPILE);
444 glNewList(lc->star2, GL_COMPILE);
447 glRotatef(-180.0, 1.0, 0.0, 0.0);
449 for (i = 0; i < countof(points)/4; i += 2)
456 GLfloat s[4], t[4], x[4], y[4], z[4];
457 for (j = 3, k = 0; j >= 0; j--, k++)
459 GLfloat xx = points[(i*4)+j][0] / 255.0L;
460 GLfloat yy = points[(i*4)+j][1] / 255.0L;
467 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
468 s[0], t[0], x[0], y[0], z[0],
469 s[1], t[1], x[1], y[1], z[1],
470 s[2], t[2], x[2], y[2], z[2],
471 s[3], t[3], x[3], y[3], z[3]);
475 for (j = 0, k = 0; j < 4; j++, k++)
477 GLfloat xx = points[(i*4)+j][0] / 255.0L;
478 GLfloat yy = points[(i*4)+j][1] / 255.0L;
485 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
486 s[0], t[0], x[0], y[0], z[0],
487 s[1], t[1], x[1], y[1], z[1],
488 s[2], t[2], x[2], y[2], z[2],
489 s[3], t[3], x[3], y[3], z[3]);
493 for (j = 3; j >= 0; j--)
495 int k = (j == 0 ? 3 : j-1);
496 Bool front_p = (j == 3);
497 GLfloat x1 = points[(i*4)+j][0] / 255.0L;
498 GLfloat y1 = points[(i*4)+j][1] / 255.0L;
499 GLfloat x2 = points[(i*4)+k][0] / 255.0L;
500 GLfloat y2 = points[(i*4)+k][1] / 255.0L;
502 GLfloat tx1=0.0, tx2=1.0, ty1=0.0, ty2=1.0;
506 facing = (facing + j + 5) % 4;
512 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
513 ty1 = 0.0; ty2 = 1.0;
516 ty1 = 1.0; ty2 = 0.0;
520 texture = top ? FACE_S : FACE_N;
522 ty1 = 0.0; ty2 = 1.0;
528 ty1 = 0.0; ty2 = 1.0;
530 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
531 ty1 = 1.0; ty2 = 0.0;
535 texture = top ? FACE_N : FACE_S;
537 ty1 = 1.0; ty2 = 0.0;
541 x1 -= 0.5; x2 -= 0.5;
542 y1 -= 0.5; y2 -= 0.5;
544 face4(front_p ? lc->texids[texture] : 0,
545 front_p ? exterior_color : interior_color,
547 tx1, ty2, x1, y1, 0.5,
548 tx1, ty1, x1, y1, -0.5,
549 tx2, ty1, x2, y2, -0.5,
550 tx2, ty2, x2, y2, 0.5);
555 /* Central core top cap.
557 #ifdef HAVE_GLBINDTEXTURE
558 glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]);
559 #endif /* HAVE_GLBINDTEXTURE */
560 set_colors(exterior_color);
563 do_normal(points[i+0][0], points[i+0][1], 0,
564 points[i+4][0], points[i+4][1], 0,
565 points[i+8][0], points[i+8][1], 0);
566 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
567 for (i = 1; i < countof(points); i += 4)
569 GLfloat x = points[i][0] / 255.0L;
570 GLfloat y = points[i][1] / 255.0L;
572 glVertex3f(x-0.5, y-0.5, 0.5);
577 /* Central core bottom cap.
579 #ifdef HAVE_GLBINDTEXTURE
580 glBindTexture(GL_TEXTURE_2D, 0);
581 #endif /* HAVE_GLBINDTEXTURE */
582 set_colors(interior_color);
584 i = countof(points) - 9;
585 do_normal(points[i+0][0], points[i+0][1], 0,
586 points[i+4][0], points[i+4][1], 0,
587 points[i+8][0], points[i+8][1], 0);
589 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
590 for (i = countof(points) - 3; i >= 0; i -= 4)
592 GLfloat x = points[i][0] / 255.0L;
593 GLfloat y = points[i][1] / 255.0L;
594 glVertex3f(x-0.5, y-0.5, 0);
599 /* Central core walls.
601 for (i = 1; i < countof(points); i += 4)
604 GLfloat x1 = points[i-1][0] / 255.0L;
605 GLfloat y1 = points[i-1][1] / 255.0L;
606 GLfloat x2 = points[i][0] / 255.0L;
607 GLfloat y2 = points[i][1] / 255.0L;
608 face4(0, interior_color, wire,
609 0.0, 0.0, x1-0.5, y1-0.5, 0.5,
610 0.0, 0.0, x1-0.5, y1-0.5, 0.0,
611 0.0, 0.0, x2-0.5, y2-0.5, 0.0,
612 0.0, 0.0, x2-0.5, y2-0.5, 0.5);
620 tetra(ModeInfo *mi, Bool wire)
622 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
624 glNewList(lc->tetra_une, GL_COMPILE);
626 glShadeModel(GL_SMOOTH);
629 face3(lc->texids[FACE_U], exterior_color, wire,
630 1.0, 0.0, 0.5, -0.5, 0.5,
631 1.0, 1.0, 0.5, 0.5, 0.5,
632 0.0, 1.0, -0.5, 0.5, 0.5);
635 face3(lc->texids[FACE_N], exterior_color, wire,
636 0.0, 0.0, -0.5, 0.5, 0.5,
637 1.0, 0.0, 0.5, 0.5, 0.5,
638 1.0, 1.0, 0.5, 0.5, -0.5);
641 face3(lc->texids[FACE_E], exterior_color, wire,
642 1.0, 0.0, 0.5, 0.5, -0.5,
643 1.0, 1.0, 0.5, 0.5, 0.5,
644 0.0, 1.0, 0.5, -0.5, 0.5);
646 face3(0, interior_color, wire,
647 0.0, 0.0, 0.5, 0.5, -0.5,
648 0.0, 0.0, 0.5, -0.5, 0.5,
649 0.0, 0.0, -0.5, 0.5, 0.5);
653 glNewList(lc->tetra_usw, GL_COMPILE);
656 face3(lc->texids[FACE_U], exterior_color, wire,
657 0.0, 1.0, -0.5, 0.5, 0.5,
658 0.0, 0.0, -0.5, -0.5, 0.5,
659 1.0, 0.0, 0.5, -0.5, 0.5);
662 face3(lc->texids[FACE_S], exterior_color, wire,
663 1.0, 1.0, 0.5, -0.5, 0.5,
664 0.0, 1.0, -0.5, -0.5, 0.5,
665 0.0, 0.0, -0.5, -0.5, -0.5);
668 face3(lc->texids[FACE_W], exterior_color, wire,
669 1.0, 0.0, -0.5, -0.5, -0.5,
670 1.0, 1.0, -0.5, -0.5, 0.5,
671 0.0, 1.0, -0.5, 0.5, 0.5);
673 face3(0, interior_color, wire,
674 0.0,0.0, -0.5, -0.5, -0.5,
675 0.0,0.0, -0.5, 0.5, 0.5,
676 0.0,0.0, 0.5, -0.5, 0.5);
680 glNewList(lc->tetra_dwn, GL_COMPILE);
683 face3(lc->texids[FACE_D], exterior_color, wire,
684 0.0, 1.0, -0.5, -0.5, -0.5,
685 0.0, 0.0, -0.5, 0.5, -0.5,
686 1.0, 0.0, 0.5, 0.5, -0.5);
689 face3(lc->texids[FACE_W], exterior_color, wire,
690 0.0, 1.0, -0.5, 0.5, 0.5,
691 0.0, 0.0, -0.5, 0.5, -0.5,
692 1.0, 0.0, -0.5, -0.5, -0.5);
695 face3(lc->texids[FACE_N], exterior_color, wire,
696 1.0, 1.0, 0.5, 0.5, -0.5,
697 0.0, 1.0, -0.5, 0.5, -0.5,
698 0.0, 0.0, -0.5, 0.5, 0.5);
700 face3(0, interior_color, wire,
701 0.0, 0.0, 0.5, 0.5, -0.5,
702 0.0, 0.0, -0.5, 0.5, 0.5,
703 0.0, 0.0, -0.5, -0.5, -0.5);
707 glNewList(lc->tetra_dse, GL_COMPILE);
710 face3(lc->texids[FACE_S], exterior_color, wire,
711 0.0, 0.0, -0.5, -0.5, -0.5,
712 1.0, 0.0, 0.5, -0.5, -0.5,
713 1.0, 1.0, 0.5, -0.5, 0.5);
716 face3(lc->texids[FACE_E], exterior_color, wire,
717 0.0, 1.0, 0.5, -0.5, 0.5,
718 0.0, 0.0, 0.5, -0.5, -0.5,
719 1.0, 0.0, 0.5, 0.5, -0.5);
722 face3(lc->texids[FACE_D], exterior_color, wire,
723 1.0, 0.0, 0.5, 0.5, -0.5,
724 1.0, 1.0, 0.5, -0.5, -0.5,
725 0.0, 1.0, -0.5, -0.5, -0.5);
727 face3(0, interior_color, wire,
728 0.0, 0.0, 0.5, -0.5, 0.5,
729 0.0, 0.0, 0.5, 0.5, -0.5,
730 0.0, 0.0, -0.5, -0.5, -0.5);
734 glNewList(lc->tetra_mid, GL_COMPILE);
736 face3(0, interior_color, wire,
737 0.0, 0.0, 0.5, -0.5, 0.5,
738 0.0, 0.0, 0.5, 0.5, -0.5,
739 0.0, 0.0, -0.5, 0.5, 0.5);
741 face3(0, interior_color, wire,
742 0.0, 0.0, -0.5, 0.5, 0.5,
743 0.0, 0.0, -0.5, -0.5, -0.5,
744 0.0, 0.0, 0.5, -0.5, 0.5);
746 face3(0, interior_color, wire,
747 0.0, 0.0, -0.5, 0.5, 0.5,
748 0.0, 0.0, 0.5, 0.5, -0.5,
749 0.0, 0.0, -0.5, -0.5, -0.5);
751 face3(0, interior_color, wire,
752 0.0, 0.0, 0.5, 0.5, -0.5,
753 0.0, 0.0, 0.5, -0.5, 0.5,
754 0.0, 0.0, -0.5, -0.5, -0.5);
756 face3(0, interior_color, wire,
757 0.0, 0.0, 0.5, -0.5, 0.5,
758 0.0, 0.0, 0.5, 0.5, -0.5,
759 0.0, 0.0, -0.5, -0.5, -0.5);
766 lid(ModeInfo *mi, Bool wire)
768 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
772 { 128, 20 },{ 21, 129 },{ 0, 129 },{ 0, 0 },{ 128, 0 }, /* L1 */
773 { 21, 129 },{ 127, 234 },{ 127, 255 },{ 0, 255 },{ 0, 129 }, /* L2 */
774 { 127, 234 },{ 233, 127 },{ 255, 127 },{ 255, 255 },{ 127, 255 }, /* R2 */
775 { 233, 127 },{ 128, 20 },{ 128, 0 },{ 255, 0 },{ 255, 127 }, /* R1 */
778 for (i = 0; i < countof(points); i++)
779 points[i][1] = 255-points[i][1];
781 glNewList(lc->lid_0, GL_COMPILE);
782 glShadeModel(GL_SMOOTH);
785 face4(lc->texids[FACE_N], exterior_color, wire,
786 0.0, 0.0, -0.5, 0.5, 0.5,
787 1.0, 0.0, 0.5, 0.5, 0.5,
788 1.0, 1.0, 0.5, 0.5, -0.5,
789 0.0, 1.0, -0.5, 0.5, -0.5);
792 face4(lc->texids[FACE_S], exterior_color, wire,
793 0.0, 0.0, -0.5, -0.5, -0.5,
794 1.0, 0.0, 0.5, -0.5, -0.5,
795 1.0, 1.0, 0.5, -0.5, 0.5,
796 0.0, 1.0, -0.5, -0.5, 0.5);
799 face4(lc->texids[FACE_E], exterior_color, wire,
800 0.0, 0.0, 0.5, -0.5, -0.5,
801 1.0, 0.0, 0.5, 0.5, -0.5,
802 1.0, 1.0, 0.5, 0.5, 0.5,
803 0.0, 1.0, 0.5, -0.5, 0.5);
806 face4(lc->texids[FACE_U], exterior_color, wire,
807 1.0, 0.0, 0.5, -0.5, 0.5,
808 1.0, 1.0, 0.5, 0.5, 0.5,
809 0.0, 1.0, -0.5, 0.5, 0.5,
810 0.0, 0.0, -0.5, -0.5, 0.5);
813 face4(lc->texids[FACE_D], exterior_color, wire,
814 0.0, 1.0, -0.5, -0.5, -0.5,
815 0.0, 0.0, -0.5, 0.5, -0.5,
816 1.0, 0.0, 0.5, 0.5, -0.5,
817 1.0, 1.0, 0.5, -0.5, -0.5);
820 for (i = 0; i < countof(points)/5; i++)
823 GLfloat s[5], t[5], x[5], y[5], z[5];
824 for (j = 0; j < 5; j++)
826 GLfloat xx = points[(i*5)+j][0] / 255.0L;
827 GLfloat yy = points[(i*5)+j][1] / 255.0L;
834 face5(lc->texids[FACE_W], exterior_color, wire,
835 s[0], t[0], x[0], y[0], z[0],
836 s[1], t[1], x[1], y[1], z[1],
837 s[2], t[2], x[2], y[2], z[2],
838 s[3], t[3], x[3], y[3], z[3],
839 s[4], t[4], x[4], y[4], z[4]);
844 /* W -- lid_1 through lid_4 */
845 for (i = 0; i < 4; i++)
847 GLfloat x1, y1, x2, y2, x3, y3;
849 glNewList(lc->lid_1 + i, GL_COMPILE);
850 glShadeModel(GL_SMOOTH);
852 x1 = points[(i*5)+1][0] / 255.0L;
853 y1 = points[(i*5)+1][1] / 255.0L;
854 x2 = points[(i*5)][0] / 255.0L;
855 y2 = points[(i*5)][1] / 255.0L;
860 face3(lc->texids[FACE_W], exterior_color, wire,
861 1.0-x1, y1, -0.5, x1-0.5, y1-0.5,
862 1.0-x2, y2, -0.5, x2-0.5, y2-0.5,
863 1.0-x3, y3, -0.5, x3-0.5, y3-0.5);
866 face3(0, interior_color, wire,
867 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
868 0.0, 0.0, -0.48, x1-0.5, y1-0.5,
869 0.0, 0.0, -0.48, x3-0.5, y3-0.5);
872 face4(0, interior_color, wire,
873 0.0, 0.0, -0.5, x1-0.5, y1-0.5,
874 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
875 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
876 0.0, 0.0, -0.48, x1-0.5, y1-0.5);
879 face4(0, interior_color, wire,
880 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
881 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
882 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
883 0.0, 0.0, -0.5, x2-0.5, y2-0.5);
890 taser(ModeInfo *mi, Bool wire)
892 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
895 int slider_face_points[][2] = {
896 { 86, 58 },{ 38, 106 },{ 70, 106 },{ 118, 58 },{ -1, -1 }, /* a */
897 { 136, 58 },{ 184, 106 },{ 216, 106 },{ 168, 58 },{ -1, -1 }, /* b */
898 { 38, 106 },{ 0, 144 },{ 0, 190 },{ 60, 190 },{ 108, 106 }, /* c */
899 { 144, 106 },{ 194, 190 },{ 254, 190 },{ 254, 144 },{ 216, 106 }, /* d */
900 { 98, 124 },{ 60, 190 },{ 92, 190 },{ 126, 158 },{ 126, 124 }, /* e */
901 { 126, 124 },{ 126, 158 },{ 160, 190 },{ 194, 190 },{ 154, 124 }, /* f */
902 { 22, 190 },{ 22, 254 },{ 60, 254 },{ 60, 190 },{ -1, -1 }, /* g */
903 { 194, 190 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ -1, -1 }, /* h */
904 { 60, 190 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ -1, -1 }, /* i */
905 { 160, 190 },{ 160, 210 },{ 194, 210 },{ 194, 190 },{ -1, -1 }, /* j */
906 { 110, 172 },{ 92, 190 },{ 110, 190 },{ -1, -1 },{ -1, -1 }, /* k */
907 { 140, 172 },{ 140, 190 },{ 160, 190 },{ -1, -1 },{ -1, -1 }, /* l */
908 { 110, 172 },{ 140, 172 },{ 126, 156 },{ -1, -1 },{ -1, -1 }, /* m */
911 int body_face_points[][2] = {
912 { 0, 0 },{ 0, 58 },{ 254, 58 },{ 254, 0 },{ -1, -1 }, /* A */
913 { 0, 58 },{ 0, 144 },{ 86, 58 },{ -1, -1 },{ -1, -1 }, /* B */
914 { 168, 58 },{ 254, 144 },{ 254, 58 },{ -1, -1 },{ -1, -1 }, /* C */
915 { 118, 58 },{ 70, 106 },{ 184, 106 },{ 136, 58 },{ -1, -1 }, /* F */
916 { 108, 106 },{ 98, 124 },{ 154, 124 },{ 144, 106 },{ -1, -1 }, /* G */
919 int lifter_face_points[][2] = {
920 { 0, 190 },{ 0, 254 },{ 22, 254 },{ 22, 190 },{ -1, -1 }, /* D */
921 { 230, 190 },{ 230, 254 },{ 254, 254 },{ 254, 190 },{ -1, -1 }, /* E */
922 { 60, 210 },{ 60, 254 },{ 194, 254 },{ 194, 210 },{ -1, -1 }, /* H */
923 { 92, 190 },{ 92, 210 },{ 160, 210 },{ 160, 190 },{ -1, -1 }, /* I */
924 { 110, 172 },{ 110, 190 },{ 140, 190 },{ 140, 172 },{ -1, -1 }, /* J */
927 int body_perimiter_points[][2] = {
928 { 0, 144 },{ 86, 59 },{ 119, 58 },{ 71, 107 },
929 { 108, 107 },{ 98, 124 },{ 155, 124 },{ 144, 107 },
930 { 185, 106 },{ 136, 59 },{ 169, 59 },{ 255, 145 },
934 int slider_perimiter_points[][2] = {
935 { 86, 58 },{ 0, 144 },{ 0, 190 },{ 22, 190 },{ 22, 254 },
936 { 60, 254 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ 110, 190 },
937 { 110, 172 },{ 140, 172 },{ 140, 190 },{ 160, 190 },{ 160, 210 },
938 { 194, 210 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ 254, 190 },
939 { 254, 144 },{ 168, 58 },{ 136, 58 },{ 184, 106 },{ 144, 106 },
940 { 154, 124 },{ 98, 124 },{ 108, 106 },{ 70, 106 },{ 118, 58 },
943 int lifter_perimiter_points_1[][2] = {
944 { 0, 189 },{ 0, 254 },{ 22, 255 },{ 23, 190 },
947 int lifter_perimiter_points_2[][2] = {
948 { 230, 254 },{ 255, 255 },{ 254, 190 },{ 230, 190 },
951 int lifter_perimiter_points_3[][2] = {
952 { 60, 254 },{ 194, 254 },{ 194, 211 },{ 160, 210 },
953 { 160, 190 },{ 140, 191 },{ 141, 172 },{ 111, 172 },
954 { 110, 190 },{ 93, 190 },{ 92, 210 },{ 60, 211 },
957 for (i = 0; i < countof(slider_face_points); i++)
958 slider_face_points[i][1] = 255-slider_face_points[i][1];
959 for (i = 0; i < countof(body_face_points); i++)
960 body_face_points[i][1] = 255-body_face_points[i][1];
961 for (i = 0; i < countof(lifter_face_points); i++)
962 lifter_face_points[i][1] = 255-lifter_face_points[i][1];
963 for (i = 0; i < countof(body_perimiter_points); i++)
964 body_perimiter_points[i][1] = 255-body_perimiter_points[i][1];
965 for (i = 0; i < countof(slider_perimiter_points); i++)
966 slider_perimiter_points[i][1] = 255-slider_perimiter_points[i][1];
967 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
968 lifter_perimiter_points_1[i][1] = 255-lifter_perimiter_points_1[i][1];
969 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
970 lifter_perimiter_points_2[i][1] = 255-lifter_perimiter_points_2[i][1];
971 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
972 lifter_perimiter_points_3[i][1] = 255-lifter_perimiter_points_3[i][1];
974 /* -------------------------------------------------------------------- */
976 glNewList(lc->taser_base, GL_COMPILE);
977 glShadeModel(GL_SMOOTH);
980 face4(lc->texids[FACE_N], exterior_color, wire,
981 0.0, 0.0, -0.5, 0.5, 0.5,
982 0.75, 0.0, 0.25, 0.5, 0.5,
983 0.75, 0.75, 0.25, 0.5, -0.25,
984 0.0, 0.75, -0.5, 0.5, -0.25);
987 face4(lc->texids[FACE_S], exterior_color, wire,
988 0.0, 0.25, -0.5, -0.5, -0.25,
989 0.75, 0.25, 0.25, -0.5, -0.25,
990 0.75, 1.0, 0.25, -0.5, 0.5,
991 0.0, 1.0, -0.5, -0.5, 0.5);
994 face4(0, interior_color, wire,
995 0.0, 0.0, 0.25, -0.5, -0.25,
996 1.0, 0.0, 0.25, 0.5, -0.25,
997 1.0, 1.0, 0.25, 0.5, 0.5,
998 0.0, 1.0, 0.25, -0.5, 0.5);
1001 face4(lc->texids[FACE_W], exterior_color, wire,
1002 1.0, 1.0, -0.5, -0.5, 0.5,
1003 0.0, 1.0, -0.5, 0.5, 0.5,
1004 0.0, 0.25, -0.5, 0.5, -0.25,
1005 1.0, 0.25, -0.5, -0.5, -0.25);
1008 face4(lc->texids[FACE_U], exterior_color, wire,
1009 0.75, 0.0, 0.25, -0.5, 0.5,
1010 0.75, 1.0, 0.25, 0.5, 0.5,
1011 0.0, 1.0, -0.5, 0.5, 0.5,
1012 0.0, 0.0, -0.5, -0.5, 0.5);
1015 face4(0, interior_color, wire,
1016 0.0, 1.0, -0.5, -0.5, -0.25,
1017 0.0, 0.0, -0.5, 0.5, -0.25,
1018 1.0, 0.0, 0.25, 0.5, -0.25,
1019 1.0, 1.0, 0.25, -0.5, -0.25);
1022 for (i = 0; i < countof(body_face_points)/5; i++)
1025 #ifdef HAVE_GLBINDTEXTURE
1026 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1027 #endif /* HAVE_GLBINDTEXTURE */
1028 set_colors(exterior_color);
1030 do_normal(0, body_face_points[(i*5)+0][0], body_face_points[(i*5)+0][1],
1031 0, body_face_points[(i*5)+1][0], body_face_points[(i*5)+1][1],
1032 0, body_face_points[(i*5)+2][0], body_face_points[(i*5)+2][1]
1034 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1035 for (j = 0; j < 5; j++)
1037 int ix = body_face_points[(i*5)+j][0];
1038 int iy = body_face_points[(i*5)+j][1];
1040 if (ix == -1) /* these are padding: ignore them */
1045 glVertex3f(0.5, x-0.5, y-0.5);
1051 for (i = 0; i < countof(body_perimiter_points); i++)
1053 int j = (i+1 >= countof(body_perimiter_points) ? 0 : i+1);
1054 GLfloat x1 = body_perimiter_points[i][0] / 255.0;
1055 GLfloat y1 = body_perimiter_points[i][1] / 255.0;
1056 GLfloat x2 = body_perimiter_points[j][0] / 255.0;
1057 GLfloat y2 = body_perimiter_points[j][1] / 255.0;
1059 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1063 texture = lc->texids[FACE_N];
1065 s2 = 1.0; t2 = 0.568;
1066 s3 = 0.75, t3 = 0.568;
1067 s4 = 0.75; t4 = 0.0;
1071 texture = lc->texids[FACE_U];
1074 s3 = 0.75, t3 = 1.0;
1075 s4 = 0.75; t4 = 0.0;
1079 texture = lc->texids[FACE_S];
1080 s1 = 1.0; t1 = 0.437;
1082 s3 = 0.75; t3 = 1.0;
1083 s4 = 0.75; t4 = 0.437;
1086 face4((texture == -1 ? 0 : texture),
1087 (texture == -1 ? interior_color : exterior_color),
1089 s1, t1, 0.5, x2-0.5, y2-0.5,
1090 s2, t2, 0.5, x1-0.5, y1-0.5,
1091 s3, t3, 0.25, x1-0.5, y1-0.5,
1092 s4, t4, 0.25, x2-0.5, y2-0.5);
1097 /* -------------------------------------------------------------------- */
1099 glNewList(lc->taser_lifter, GL_COMPILE);
1100 glShadeModel(GL_SMOOTH);
1103 face4(lc->texids[FACE_N], exterior_color, wire,
1104 0.0, 0.75, -0.5, 0.5, -0.25,
1105 0.75, 0.75, 0.25, 0.5, -0.25,
1106 0.75, 1.0, 0.25, 0.5, -0.5,
1107 0.0, 1.0, -0.5, 0.5, -0.5);
1110 face4(lc->texids[FACE_S], exterior_color, wire,
1111 0.0, 0.0, -0.5, -0.5, -0.5,
1112 0.75, 0.0, 0.25, -0.5, -0.5,
1113 0.75, 0.25, 0.25, -0.5, -0.25,
1114 0.0, 0.25, -0.5, -0.5, -0.25);
1117 face4(0, interior_color, wire,
1118 0.0, 1.0, 0.25, -0.5, -0.5,
1119 1.0, 1.0, 0.25, 0.5, -0.5,
1120 1.0, 0.0, 0.25, 0.5, -0.25,
1121 0.0, 0.0, 0.25, -0.5, -0.25);
1124 face4(lc->texids[FACE_W], exterior_color, wire,
1125 1.0, 0.25, -0.5, -0.5, -0.25,
1126 0.0, 0.25, -0.5, 0.5, -0.25,
1127 0.0, 0.0, -0.5, 0.5, -0.5,
1128 1.0, 0.0, -0.5, -0.5, -0.5);
1131 face4(0, interior_color, wire,
1132 1.0, 0.0, 0.25, -0.5, -0.25,
1133 1.0, 1.0, 0.25, 0.5, -0.25,
1134 0.0, 1.0, -0.5, 0.5, -0.25,
1135 0.0, 0.0, -0.5, -0.5, -0.25);
1138 face4(lc->texids[FACE_D], exterior_color, wire,
1139 0.0, 1.0, -0.5, -0.5, -0.5,
1140 0.0, 0.0, -0.5, 0.5, -0.5,
1141 0.75, 0.0, 0.25, 0.5, -0.5,
1142 0.75, 1.0, 0.25, -0.5, -0.5);
1146 for (i = 0; i < countof(lifter_face_points)/5; i++)
1150 #ifdef HAVE_GLBINDTEXTURE
1151 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1152 #endif /* HAVE_GLBINDTEXTURE */
1153 set_colors(exterior_color);
1156 0, lifter_face_points[(i*5)+0][0], lifter_face_points[(i*5)+0][1],
1157 0, lifter_face_points[(i*5)+1][0], lifter_face_points[(i*5)+1][1],
1158 0, lifter_face_points[(i*5)+2][0], lifter_face_points[(i*5)+2][1]);
1160 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1161 for (j = 0; j < 5; j++)
1163 int ix = lifter_face_points[(i*5)+j][0];
1164 int iy = lifter_face_points[(i*5)+j][1];
1166 if (ix == -1) /* these are padding: ignore them */
1171 glVertex3f(0.5, x-0.5, y-0.5);
1177 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
1179 int j = (i+1 >= countof(lifter_perimiter_points_1) ? 0 : i+1);
1180 GLfloat x1 = lifter_perimiter_points_1[i][0] / 255.0;
1181 GLfloat y1 = lifter_perimiter_points_1[i][1] / 255.0;
1182 GLfloat x2 = lifter_perimiter_points_1[j][0] / 255.0;
1183 GLfloat y2 = lifter_perimiter_points_1[j][1] / 255.0;
1185 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1189 texture = lc->texids[FACE_S];
1191 s2 = 1.0; t2 = 0.26;
1192 s3 = 0.75, t3 = 0.26;
1193 s4 = 0.75; t4 = 0.0;
1197 texture = lc->texids[FACE_D];
1198 s1 = 1.0; t1 = 0.914;
1200 s3 = 0.75; t3 = 1.0;
1201 s4 = 0.75; t4 = 0.914;
1204 face4((texture == -1 ? 0 : texture),
1205 (texture == -1 ? interior_color : exterior_color),
1207 s1, t1, 0.5, x2-0.5, y2-0.5,
1208 s2, t2, 0.5, x1-0.5, y1-0.5,
1209 s3, t3, 0.25, x1-0.5, y1-0.5,
1210 s4, t4, 0.25, x2-0.5, y2-0.5);
1213 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
1215 int j = (i+1 >= countof(lifter_perimiter_points_2) ? 0 : i+1);
1216 GLfloat x1 = lifter_perimiter_points_2[i][0] / 255.0;
1217 GLfloat y1 = lifter_perimiter_points_2[i][1] / 255.0;
1218 GLfloat x2 = lifter_perimiter_points_2[j][0] / 255.0;
1219 GLfloat y2 = lifter_perimiter_points_2[j][1] / 255.0;
1221 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1225 texture = lc->texids[FACE_D];
1227 s2 = 1.0; t2 = 0.095;
1228 s3 = 0.75; t3 = 0.095;
1229 s4 = 0.75; t4 = 0.0;
1233 texture = lc->texids[FACE_N];
1234 s1 = 1.0; t1 = 0.745;
1236 s3 = 0.75; t3 = 1.0;
1237 s4 = 0.75; t4 = 0.745;
1240 face4((texture == -1 ? 0 : texture),
1241 (texture == -1 ? interior_color : exterior_color),
1243 s1, t1, 0.5, x2-0.5, y2-0.5,
1244 s2, t2, 0.5, x1-0.5, y1-0.5,
1245 s3, t3, 0.25, x1-0.5, y1-0.5,
1246 s4, t4, 0.25, x2-0.5, y2-0.5);
1249 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
1251 int j = (i+1 >= countof(lifter_perimiter_points_3) ? 0 : i+1);
1252 GLfloat x1 = lifter_perimiter_points_3[i][0] / 255.0;
1253 GLfloat y1 = lifter_perimiter_points_3[i][1] / 255.0;
1254 GLfloat x2 = lifter_perimiter_points_3[j][0] / 255.0;
1255 GLfloat y2 = lifter_perimiter_points_3[j][1] / 255.0;
1257 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1261 texture = lc->texids[FACE_D];
1262 s1 = 1.0; t1 = 0.235;
1263 s2 = 1.0; t2 = 0.765;
1264 s3 = 0.75; t3 = 0.765;
1265 s4 = 0.75; t4 = 0.235;
1268 face4((texture == -1 ? 0 : texture),
1269 (texture == -1 ? interior_color : exterior_color),
1271 s1, t1, 0.5, x2-0.5, y2-0.5,
1272 s2, t2, 0.5, x1-0.5, y1-0.5,
1273 s3, t3, 0.25, x1-0.5, y1-0.5,
1274 s4, t4, 0.25, x2-0.5, y2-0.5);
1279 /* -------------------------------------------------------------------- */
1281 glNewList(lc->taser_slider, GL_COMPILE);
1282 glShadeModel(GL_SMOOTH);
1285 for (i = 0; i < countof(slider_face_points)/5; i++)
1288 #ifdef HAVE_GLBINDTEXTURE
1289 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1290 #endif /* HAVE_GLBINDTEXTURE */
1291 set_colors(exterior_color);
1294 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1],
1295 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1296 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1]);
1297 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1298 for (j = 0; j < 5; j++)
1300 int ix = slider_face_points[(i*5)+j][0];
1301 int iy = slider_face_points[(i*5)+j][1];
1303 if (ix == -1) /* these are padding: ignore them */
1308 glVertex3f(0.5, x-0.5, y-0.5);
1314 for (i = countof(slider_face_points)/5 - 1; i >= 0; i--)
1317 #ifdef HAVE_GLBINDTEXTURE
1318 glBindTexture(GL_TEXTURE_2D, 0);
1319 #endif /* HAVE_GLBINDTEXTURE */
1320 set_colors(interior_color);
1323 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1],
1324 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1325 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1]);
1326 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1327 for (j = 4; j >= 0; j--)
1329 int ix = slider_face_points[(i*5)+j][0];
1330 int iy = slider_face_points[(i*5)+j][1];
1332 if (ix == -1) /* these are padding: ignore them */
1337 glVertex3f(0.25, x-0.5, y-0.5);
1343 for (i = 0; i < countof(slider_perimiter_points); i++)
1345 int j = (i+1 >= countof(slider_perimiter_points) ? 0 : i+1);
1346 GLfloat x1 = slider_perimiter_points[i][0] / 255.0;
1347 GLfloat y1 = slider_perimiter_points[i][1] / 255.0;
1348 GLfloat x2 = slider_perimiter_points[j][0] / 255.0;
1349 GLfloat y2 = slider_perimiter_points[j][1] / 255.0;
1351 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1355 texture = lc->texids[FACE_S];
1356 s1 = 1.0; t1 = 0.255;
1357 s2 = 1.0; t2 = 0.435;
1358 s3 = 0.75; t3 = 0.435;
1359 s4 = 0.75; t4 = 0.255;
1363 texture = lc->texids[FACE_D];
1364 s1 = 1.0; t1 = 0.758;
1365 s2 = 1.0; t2 = 0.915;
1366 s3 = 0.75; t3 = 0.915;
1367 s4 = 0.75; t4 = 0.758;
1371 texture = lc->texids[FACE_D];
1372 s1 = 1.0; t1 = 0.095;
1373 s2 = 1.0; t2 = 0.24;
1374 s3 = 0.75; t3 = 0.24;
1375 s4 = 0.75; t4 = 0.095;
1379 texture = lc->texids[FACE_N];
1380 s1 = 1.0; t1 = 0.568;
1381 s2 = 1.0; t2 = 0.742;
1382 s3 = 0.75; t3 = 0.742;
1383 s4 = 0.75; t4 = 0.568;
1386 face4((texture == -1 ? 0 : texture),
1387 (texture == -1 ? interior_color : exterior_color),
1389 s1, t1, 0.5, x2-0.5, y2-0.5,
1390 s2, t2, 0.5, x1-0.5, y1-0.5,
1391 s3, t3, 0.25, x1-0.5, y1-0.5,
1392 s4, t4, 0.25, x2-0.5, y2-0.5);
1400 /* Rendering and animating object models
1404 lament_handle_event (ModeInfo *mi, XEvent *event)
1406 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1408 if (event->xany.type == ButtonPress &&
1409 event->xbutton.button & Button1)
1411 lc->button_down_p = True;
1412 gltrackball_start (lc->trackball,
1413 event->xbutton.x, event->xbutton.y,
1414 MI_WIDTH (mi), MI_HEIGHT (mi));
1417 else if (event->xany.type == ButtonRelease &&
1418 event->xbutton.button & Button1)
1420 lc->button_down_p = False;
1423 else if (event->xany.type == MotionNotify &&
1426 gltrackball_track (lc->trackball,
1427 event->xmotion.x, event->xmotion.y,
1428 MI_WIDTH (mi), MI_HEIGHT (mi));
1439 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1440 Bool wire = MI_IS_WIREFRAME(mi);
1443 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1445 glClear(GL_COLOR_BUFFER_BIT);
1449 gltrackball_rotate (lc->trackball);
1451 /* Make into the screen be +Y right be +X, and up be +Z. */
1452 glRotatef(-90.0, 1.0, 0.0, 0.0);
1455 glScalef(4.0, 4.0, 4.0);
1460 /* Shift to the upper left, and draw the vanilla box. */
1461 glTranslatef(-0.6, 0.0, 0.6);
1463 /* Apply rotation to the object. */
1464 glRotatef(x * 360, 1.0, 0.0, 0.0);
1465 glRotatef(y * 360, 0.0, 1.0, 0.0);
1466 glRotatef(z * 360, 0.0, 0.0, 1.0);
1469 glCallList(lc->box);
1473 /* Shift to the lower right, and draw the animated object. */
1474 glTranslatef(0.6, 0.0, -0.6);
1480 /* Apply rotation to the object. */
1481 if (lc->type != LAMENT_LID_ZOOM)
1482 get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
1483 !lc->button_down_p);
1484 glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
1485 glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
1486 glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
1491 glCallList(lc->box);
1494 case LAMENT_STAR_OUT:
1495 case LAMENT_STAR_ROT:
1496 case LAMENT_STAR_ROT_IN:
1497 case LAMENT_STAR_ROT_OUT:
1498 case LAMENT_STAR_UNROT:
1499 case LAMENT_STAR_IN:
1500 glTranslatef(0.0, 0.0, lc->anim_z/2);
1501 glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0);
1502 glCallList(lc->star1);
1504 glTranslatef(0.0, 0.0, -lc->anim_z);
1505 glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
1506 glCallList(lc->star2);
1509 case LAMENT_TETRA_UNE:
1510 case LAMENT_TETRA_USW:
1511 case LAMENT_TETRA_DWN:
1512 case LAMENT_TETRA_DSE:
1517 case LAMENT_TETRA_UNE: magic = lc->tetra_une;
1518 x = 1.0; y = 1.0; z = 1.0; break;
1519 case LAMENT_TETRA_USW: magic = lc->tetra_usw;
1520 x = 1.0; y = 1.0; z = -1.0; break;
1521 case LAMENT_TETRA_DWN: magic = lc->tetra_dwn;
1522 x = 1.0; y = -1.0; z = 1.0; break;
1523 case LAMENT_TETRA_DSE: magic = lc->tetra_dse;
1524 x = -1.0; y = 1.0; z = 1.0; break;
1525 default: abort(); break;
1527 glCallList(lc->tetra_mid);
1528 if (magic != lc->tetra_une) glCallList(lc->tetra_une);
1529 if (magic != lc->tetra_usw) glCallList(lc->tetra_usw);
1530 if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn);
1531 if (magic != lc->tetra_dse) glCallList(lc->tetra_dse);
1532 glRotatef(lc->anim_r, x, y, z);
1537 case LAMENT_LID_OPEN:
1538 case LAMENT_LID_CLOSE:
1539 case LAMENT_LID_ZOOM:
1543 glTranslatef(lc->anim_z, 0.0, 0.0);
1545 glCallList(lc->lid_0);
1548 glTranslatef(-0.5, -d, 0.0);
1549 glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
1550 glTranslatef( 0.5, d, 0.0);
1551 glCallList(lc->lid_1);
1554 glTranslatef(-0.5, -d, 0.0);
1555 glRotatef( lc->anim_r, 0.0, -1.0, 1.0);
1556 glTranslatef( 0.5, d, 0.0);
1557 glCallList(lc->lid_2);
1560 glTranslatef(-0.5, d, 0.0);
1561 glRotatef( lc->anim_r, 0.0, -1.0, -1.0);
1562 glTranslatef( 0.5, -d, 0.0);
1563 glCallList(lc->lid_3);
1566 glTranslatef(-0.5, d, 0.0);
1567 glRotatef(-lc->anim_r, 0.0, -1.0, 1.0);
1568 glTranslatef( 0.5, -d, 0.0);
1569 glCallList(lc->lid_4);
1574 case LAMENT_TASER_OUT:
1575 case LAMENT_TASER_SLIDE:
1576 case LAMENT_TASER_SLIDE_IN:
1577 case LAMENT_TASER_IN:
1579 glTranslatef(-lc->anim_z/2, 0.0, 0.0);
1580 glCallList(lc->taser_base);
1582 glTranslatef(lc->anim_z, 0.0, 0.0);
1583 glCallList(lc->taser_lifter);
1585 glTranslatef(0.0, 0.0, lc->anim_y);
1586 glCallList(lc->taser_slider);
1601 animate(ModeInfo *mi)
1603 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1605 /* int pause2 = 60;*/
1612 /* Rather than just picking states randomly, pick an ordering randomly,
1613 do it, and then re-randomize. That way one can be assured of seeing
1614 all states in a short time period, though not always in the same
1615 order (it's frustrating to see it pick the same state 5x in a row.)
1617 static lament_type states[] = {
1618 LAMENT_STAR_OUT, LAMENT_STAR_OUT,
1619 LAMENT_TETRA_UNE, LAMENT_TETRA_USW,
1620 LAMENT_TETRA_DWN, LAMENT_TETRA_DSE,
1621 LAMENT_LID_OPEN, LAMENT_LID_OPEN, LAMENT_LID_OPEN,
1622 LAMENT_TASER_OUT, LAMENT_TASER_OUT,
1623 LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
1624 LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
1626 static int state = countof(states);
1628 if (state < countof(states))
1630 lc->type = states[state++];
1636 for (i = 0; i < countof(states); i++)
1638 int a = random() % countof(states);
1639 lament_type swap = states[a];
1640 states[a] = states[i];
1645 if (lc->type == LAMENT_BOX)
1646 lc->anim_pause = pause3;
1654 /* -------------------------------------------------------------- */
1656 case LAMENT_STAR_OUT:
1658 if (lc->anim_z >= 1.0)
1661 lc->type = LAMENT_STAR_ROT;
1662 lc->anim_pause = pause;
1666 case LAMENT_STAR_ROT:
1668 if (lc->anim_r >= 45.0)
1671 lc->type = LAMENT_STAR_ROT_IN;
1672 lc->anim_pause = pause;
1676 case LAMENT_STAR_ROT_IN:
1678 if (lc->anim_z <= 0.0)
1681 lc->type = LAMENT_STAR_ROT_OUT;
1682 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1686 case LAMENT_STAR_ROT_OUT:
1688 if (lc->anim_z >= 1.0)
1691 lc->type = LAMENT_STAR_UNROT;
1692 lc->anim_pause = pause;
1696 case LAMENT_STAR_UNROT:
1698 if (lc->anim_r <= 0.0)
1701 lc->type = LAMENT_STAR_IN;
1702 lc->anim_pause = pause;
1706 case LAMENT_STAR_IN:
1708 if (lc->anim_z <= 0.0)
1711 lc->type = LAMENT_BOX;
1712 lc->anim_pause = pause3;
1716 /* -------------------------------------------------------------- */
1718 case LAMENT_TETRA_UNE:
1719 case LAMENT_TETRA_USW:
1720 case LAMENT_TETRA_DWN:
1721 case LAMENT_TETRA_DSE:
1724 if (lc->anim_r >= 360.0)
1727 lc->type = LAMENT_BOX;
1728 lc->anim_pause = pause3;
1730 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1733 lc->anim_pause = pause;
1735 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1738 lc->anim_pause = pause;
1742 /* -------------------------------------------------------------- */
1744 case LAMENT_LID_OPEN:
1747 if (lc->anim_r >= 112.0)
1749 GLfloat hysteresis = 0.05;
1753 lc->anim_pause = pause3;
1755 if (lc->rotx >= -hysteresis &&
1756 lc->rotx <= hysteresis &&
1757 ((lc->rotz >= (0.25 - hysteresis) &&
1758 lc->rotz <= (0.25 + hysteresis)) ||
1759 (lc->rotz >= (-0.25 - hysteresis) &&
1760 lc->rotz <= (-0.25 + hysteresis))))
1762 lc->type = LAMENT_LID_ZOOM;
1764 lc->rotz = (lc->rotz < 0 ? -0.25 : 0.25);
1768 lc->type = LAMENT_LID_CLOSE;
1773 case LAMENT_LID_CLOSE:
1775 if (lc->anim_r <= 0.0)
1778 lc->type = LAMENT_BOX;
1779 lc->anim_pause = pause3;
1783 case LAMENT_LID_ZOOM:
1785 if (lc->anim_z < -50.0)
1789 lc->type = LAMENT_BOX;
1793 /* -------------------------------------------------------------- */
1795 case LAMENT_TASER_OUT:
1796 lc->anim_z += 0.0025;
1797 if (lc->anim_z >= 0.25)
1800 lc->type = LAMENT_TASER_SLIDE;
1801 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1805 case LAMENT_TASER_SLIDE:
1806 lc->anim_y += 0.0025;
1807 if (lc->anim_y >= 0.23)
1810 lc->type = LAMENT_TASER_SLIDE_IN;
1811 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1815 case LAMENT_TASER_SLIDE_IN:
1816 lc->anim_y -= 0.0025;
1817 if (lc->anim_y <= 0.0)
1820 lc->type = LAMENT_TASER_IN;
1821 lc->anim_pause = pause;
1825 case LAMENT_TASER_IN:
1826 lc->anim_z -= 0.0025;
1827 if (lc->anim_z <= 0.0)
1830 lc->type = LAMENT_BOX;
1831 lc->anim_pause = pause3;
1843 /* Window management, etc
1847 reshape_lament(ModeInfo *mi, int width, int height)
1849 int target_size = 180;
1850 int win_size = (width > height ? height : width);
1851 GLfloat h = (GLfloat) height / (GLfloat) width;
1853 glViewport(0, 0, (GLint) width, (GLint) height);
1855 /* glViewport(-600, -600, 1800, 1800); */
1857 glMatrixMode(GL_PROJECTION);
1859 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1860 glMatrixMode(GL_MODELVIEW);
1862 glTranslatef(0.0, 0.0, -40.0);
1864 /* This scale makes the box take up most of the window */
1865 glScalef(2.0, 2.0, 2.0);
1867 /* But if the window is more than a little larger than our target size,
1868 scale the object back down, so that the bits drawn on the screen end
1869 up rougly target_size across (actually it ends up a little larger.)
1870 Note that the image-map bits we have are 128x128. Therefore, if the
1871 image is magnified a lot, it looks pretty blocky. So it's better to
1872 have a 128x128 animation on a 1280x1024 screen that looks good, than
1873 a 1024x1024 animation that looks really pixellated.
1875 if (win_size > target_size * 1.5)
1877 GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
1879 glScalef(ratio, ratio, ratio);
1882 /* The depth buffer will be cleared, if needed, before the
1883 * next frame. Right now we just want to black the screen.
1885 glClear(GL_COLOR_BUFFER_BIT);
1890 gl_init(ModeInfo *mi)
1892 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1893 Bool wire = MI_IS_WIREFRAME(mi);
1900 static GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1901 static GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1903 static GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1904 /* static GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1905 static GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1906 static GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1908 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1909 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1911 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1912 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1913 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1914 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1915 set_colors(exterior_color);
1917 glEnable(GL_LIGHTING);
1918 glEnable(GL_LIGHT0);
1919 /* glEnable(GL_LIGHT1); */
1921 glEnable(GL_DEPTH_TEST);
1922 glEnable(GL_TEXTURE_2D);
1923 glEnable(GL_NORMALIZE);
1924 glEnable(GL_CULL_FACE);
1929 #ifdef HAVE_GLBINDTEXTURE
1931 for (i = 0; i < 6; i++)
1932 glGenTextures(1, &lc->texids[i]);
1934 parse_image_data(mi);
1936 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1937 glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width);
1939 for (i = 0; i < 6; i++)
1941 int height = lc->texture->width; /* assume square */
1942 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1943 set_colors(exterior_color);
1946 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1947 lc->texture->width, height, 0,
1948 GL_RGBA, GL_UNSIGNED_BYTE,
1949 (lc->texture->data +
1950 (lc->texture->bytes_per_line * height * i)));
1951 check_gl_error("texture");
1953 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1954 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1955 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1957 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1958 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1961 #else /* !HAVE_GLBINDTEXTURE */
1963 "%s: this version of GL doesn't support multiple texture maps.\n"
1964 "\tGet OpenGL 1.1.\n",
1967 #endif /* !HAVE_GLBINDTEXTURE */
1970 lc->box = glGenLists(16);
1971 lc->star1 = lc->box+1;
1972 lc->star2 = lc->box+2;
1973 lc->tetra_une = lc->box+3;
1974 lc->tetra_usw = lc->box+4;
1975 lc->tetra_dwn = lc->box+5;
1976 lc->tetra_dse = lc->box+6;
1977 lc->tetra_mid = lc->box+7;
1978 lc->lid_0 = lc->box+8;
1979 lc->lid_1 = lc->box+9;
1980 lc->lid_2 = lc->box+10;
1981 lc->lid_3 = lc->box+11;
1982 lc->lid_4 = lc->box+12;
1983 lc->taser_base = lc->box+13;
1984 lc->taser_lifter = lc->box+14;
1985 lc->taser_slider = lc->box+15;
1988 star(mi, True, wire);
1989 star(mi, False, wire);
1996 # ifdef HAVE_MESA_GL
1998 # include <signal.h>
2001 lament_signal_kludge (int sig)
2003 signal (sig, SIG_DFL);
2006 "%s: dying with signal %d (%s).\n"
2008 "\tThis is almost certainly a bug in the Mesa GL library,\n"
2009 "\tespecially if the stack trace in the core file mentions\n"
2010 "\t`lambda_textured_triangle' or `render_quad'.\n"
2012 "\tFirst make sure that you have the latest version of Mesa.\n"
2013 "\tIf that doesn't fix it, then I encourage you to report this\n"
2014 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
2018 (sig == SIGILL ? "SIGILL" :
2019 sig == SIGFPE ? "SIGFPE" :
2020 sig == SIGBUS ? "SIGBUS" :
2021 sig == SIGSEGV ? "SIGSEGV" : "???"));
2023 kill (getpid (), sig);
2027 handle_signals (void)
2029 signal (SIGILL, lament_signal_kludge);
2030 signal (SIGFPE, lament_signal_kludge);
2031 signal (SIGBUS, lament_signal_kludge);
2032 signal (SIGSEGV, lament_signal_kludge);
2034 # endif /* HAVE_MESA_GL */
2038 init_lament(ModeInfo *mi)
2040 lament_configuration *lc;
2043 lcs = (lament_configuration *)
2044 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
2047 fprintf(stderr, "%s: out of memory\n", progname);
2052 lc = &lcs[MI_SCREEN(mi)];
2055 double rot_speed = 0.5;
2056 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
2057 lc->trackball = gltrackball_init ();
2060 lc->type = LAMENT_BOX;
2061 lc->anim_pause = 300 + (random() % 100);
2063 if ((lc->glx_context = init_GL(mi)) != NULL)
2065 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2069 # ifdef HAVE_MESA_GL
2071 # endif /* HAVE_MESA_GL */
2076 draw_lament(ModeInfo *mi)
2078 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2079 Display *dpy = MI_DISPLAY(mi);
2080 Window window = MI_WINDOW(mi);
2082 if (!lc->glx_context)
2085 glDrawBuffer(GL_BACK);
2087 glXMakeCurrent(dpy, window, *(lc->glx_context));
2089 if (mi->fps_p) do_fps (mi);
2092 glXSwapBuffers(dpy, window);