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,
202 length = sqrt (p->x * p->x +
219 /* Calculate the unit normal at p given two other points p1,p2 on the
220 surface. The normal points in the direction of p1 crossproduct p2
223 calc_normal (XYZ p, XYZ p1, XYZ p2)
232 n.x = pa.y * pb.z - pa.z * pb.y;
233 n.y = pa.z * pb.x - pa.x * pb.z;
234 n.z = pa.x * pb.y - pa.y * pb.x;
241 do_normal(GLfloat x1, GLfloat y1, GLfloat z1,
242 GLfloat x2, GLfloat y2, GLfloat z2,
243 GLfloat x3, GLfloat y3, GLfloat z3)
246 p1.x = x1; p1.y = y1; p1.z = z1;
247 p2.x = x2; p2.y = y2; p2.z = z2;
248 p3.x = x3; p3.y = y3; p3.z = z3;
250 p = calc_normal (p1, p2, p3);
252 glNormal3f (p.x, p.y, p.z);
255 /* Draw a line in the direction of this face's normal. */
258 glTranslatef ((x1 + x2 + x3) / 3,
261 glScalef (0.5, 0.5, 0.5);
262 glBegin(GL_LINE_LOOP);
264 glVertex3f(p.x, p.y, p.z);
272 /* Shorthand utilities for making faces, with proper normals.
276 set_colors (GLfloat *color)
278 glMaterialfv(GL_FRONT, GL_AMBIENT, color+0);
279 glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4);
280 glMaterialfv(GL_FRONT, GL_SPECULAR, color+8);
281 glMaterialfv(GL_FRONT, GL_SHININESS, color+12);
285 face3(GLint texture, GLfloat *color, Bool wire,
286 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
287 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
288 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3)
290 #ifdef HAVE_GLBINDTEXTURE
291 glBindTexture(GL_TEXTURE_2D, texture);
292 #endif /* HAVE_GLBINDTEXTURE */
295 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
296 glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
297 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
298 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
299 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
304 face4(GLint texture, GLfloat *color, Bool wire,
305 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
306 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
307 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
308 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4)
310 #ifdef HAVE_GLBINDTEXTURE
311 glBindTexture(GL_TEXTURE_2D, texture);
312 #endif /* HAVE_GLBINDTEXTURE */
314 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
315 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
316 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
317 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
318 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
319 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
324 face5(GLint texture, GLfloat *color, Bool wire,
325 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
326 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
327 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
328 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4,
329 GLfloat s5, GLfloat t5, GLfloat x5, GLfloat y5, GLfloat z5)
331 #ifdef HAVE_GLBINDTEXTURE
332 glBindTexture(GL_TEXTURE_2D, texture);
333 #endif /* HAVE_GLBINDTEXTURE */
335 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
336 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
337 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
338 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
339 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
340 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
341 glTexCoord2f(s5, t5); glVertex3f(x5, y5, z5);
347 /* Creating object models
351 box(ModeInfo *mi, Bool wire)
353 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
355 glNewList(lc->box, GL_COMPILE);
356 glShadeModel(GL_SMOOTH);
359 face4(lc->texids[FACE_N], exterior_color, wire,
360 0.0, 0.0, -0.5, 0.5, 0.5,
361 1.0, 0.0, 0.5, 0.5, 0.5,
362 1.0, 1.0, 0.5, 0.5, -0.5,
363 0.0, 1.0, -0.5, 0.5, -0.5);
366 face4(lc->texids[FACE_S], exterior_color, wire,
367 0.0, 0.0, -0.5, -0.5, -0.5,
368 1.0, 0.0, 0.5, -0.5, -0.5,
369 1.0, 1.0, 0.5, -0.5, 0.5,
370 0.0, 1.0, -0.5, -0.5, 0.5);
373 face4(lc->texids[FACE_E], exterior_color, wire,
374 0.0, 0.0, 0.5, -0.5, -0.5,
375 1.0, 0.0, 0.5, 0.5, -0.5,
376 1.0, 1.0, 0.5, 0.5, 0.5,
377 0.0, 1.0, 0.5, -0.5, 0.5);
380 face4(lc->texids[FACE_W], exterior_color, wire,
381 1.0, 1.0, -0.5, -0.5, 0.5,
382 0.0, 1.0, -0.5, 0.5, 0.5,
383 0.0, 0.0, -0.5, 0.5, -0.5,
384 1.0, 0.0, -0.5, -0.5, -0.5);
387 face4(lc->texids[FACE_U], exterior_color, wire,
388 1.0, 0.0, 0.5, -0.5, 0.5,
389 1.0, 1.0, 0.5, 0.5, 0.5,
390 0.0, 1.0, -0.5, 0.5, 0.5,
391 0.0, 0.0, -0.5, -0.5, 0.5);
394 face4(lc->texids[FACE_D], exterior_color, wire,
395 0.0, 1.0, -0.5, -0.5, -0.5,
396 0.0, 0.0, -0.5, 0.5, -0.5,
397 1.0, 0.0, 0.5, 0.5, -0.5,
398 1.0, 1.0, 0.5, -0.5, -0.5);
405 star(ModeInfo *mi, Bool top, Bool wire)
407 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
411 { 77, 74 }, { 60, 98 }, { 0, 71 }, { 0, 0 }, /* L1 */
412 { 60, 98 }, { 55, 127 }, { 0, 127 }, { 0, 71 }, /* L2 */
413 { 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */
414 { 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */
415 { 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */
416 { 100, 193 }, { 127, 198 }, { 127, 255 }, { 74, 255 }, /* B2 */
417 { 127, 198 }, { 151, 193 }, { 180, 255 }, { 127, 255 }, /* B3 */
418 { 151, 193 }, { 178, 177 }, { 255, 255 }, { 180, 255 }, /* B4 */
419 { 178, 177 }, { 193, 155 }, { 255, 181 }, { 255, 255 }, /* R4 */
420 { 193, 155 }, { 199, 127 }, { 255, 127 }, { 255, 181 }, /* R3 */
421 { 199, 127 }, { 194, 99 }, { 255, 74 }, { 255, 127 }, /* R2 */
422 { 194, 99 }, { 179, 76 }, { 255, 0 }, { 255, 74 }, /* R1 */
423 { 179, 76 }, { 155, 60 }, { 180, 0 }, { 255, 0 }, /* T4 */
424 { 155, 60 }, { 126, 55 }, { 126, 0 }, { 180, 0 }, /* T3 */
425 { 126, 55 }, { 100, 60 }, { 75, 0 }, { 126, 0 }, /* T2 */
426 { 100, 60 }, { 77, 74 }, { 0, 0 }, { 75, 0 }, /* T1 */
429 for (i = 0; i < countof(points); i++)
430 points[i][1] = 255-points[i][1];
433 glNewList(lc->star1, GL_COMPILE);
435 glNewList(lc->star2, GL_COMPILE);
438 glRotatef(-180.0, 1.0, 0.0, 0.0);
440 for (i = 0; i < countof(points)/4; i += 2)
447 GLfloat s[4], t[4], x[4], y[4], z[4];
448 for (j = 3, k = 0; j >= 0; j--, k++)
450 GLfloat xx = points[(i*4)+j][0] / 255.0L;
451 GLfloat yy = points[(i*4)+j][1] / 255.0L;
458 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
459 s[0], t[0], x[0], y[0], z[0],
460 s[1], t[1], x[1], y[1], z[1],
461 s[2], t[2], x[2], y[2], z[2],
462 s[3], t[3], x[3], y[3], z[3]);
466 for (j = 0, k = 0; j < 4; j++, k++)
468 GLfloat xx = points[(i*4)+j][0] / 255.0L;
469 GLfloat yy = points[(i*4)+j][1] / 255.0L;
476 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
477 s[0], t[0], x[0], y[0], z[0],
478 s[1], t[1], x[1], y[1], z[1],
479 s[2], t[2], x[2], y[2], z[2],
480 s[3], t[3], x[3], y[3], z[3]);
484 for (j = 3; j >= 0; j--)
486 int k = (j == 0 ? 3 : j-1);
487 Bool front_p = (j == 3);
488 GLfloat x1 = points[(i*4)+j][0] / 255.0L;
489 GLfloat y1 = points[(i*4)+j][1] / 255.0L;
490 GLfloat x2 = points[(i*4)+k][0] / 255.0L;
491 GLfloat y2 = points[(i*4)+k][1] / 255.0L;
493 GLfloat tx1=0.0, tx2=1.0, ty1=0.0, ty2=1.0;
497 facing = (facing + j + 5) % 4;
503 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
504 ty1 = 0.0; ty2 = 1.0;
507 ty1 = 1.0; ty2 = 0.0;
511 texture = top ? FACE_S : FACE_N;
513 ty1 = 0.0; ty2 = 1.0;
519 ty1 = 0.0; ty2 = 1.0;
521 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
522 ty1 = 1.0; ty2 = 0.0;
526 texture = top ? FACE_N : FACE_S;
528 ty1 = 1.0; ty2 = 0.0;
532 x1 -= 0.5; x2 -= 0.5;
533 y1 -= 0.5; y2 -= 0.5;
535 face4(front_p ? lc->texids[texture] : 0,
536 front_p ? exterior_color : interior_color,
538 tx1, ty2, x1, y1, 0.5,
539 tx1, ty1, x1, y1, -0.5,
540 tx2, ty1, x2, y2, -0.5,
541 tx2, ty2, x2, y2, 0.5);
546 /* Central core top cap.
548 #ifdef HAVE_GLBINDTEXTURE
549 glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]);
550 #endif /* HAVE_GLBINDTEXTURE */
551 set_colors(exterior_color);
554 do_normal(points[i+0][0], points[i+0][1], 0,
555 points[i+4][0], points[i+4][1], 0,
556 points[i+8][0], points[i+8][1], 0);
557 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
558 for (i = 1; i < countof(points); i += 4)
560 GLfloat x = points[i][0] / 255.0L;
561 GLfloat y = points[i][1] / 255.0L;
563 glVertex3f(x-0.5, y-0.5, 0.5);
568 /* Central core bottom cap.
570 #ifdef HAVE_GLBINDTEXTURE
571 glBindTexture(GL_TEXTURE_2D, 0);
572 #endif /* HAVE_GLBINDTEXTURE */
573 set_colors(interior_color);
575 i = countof(points) - 9;
576 do_normal(points[i+0][0], points[i+0][1], 0,
577 points[i+4][0], points[i+4][1], 0,
578 points[i+8][0], points[i+8][1], 0);
580 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
581 for (i = countof(points) - 3; i >= 0; i -= 4)
583 GLfloat x = points[i][0] / 255.0L;
584 GLfloat y = points[i][1] / 255.0L;
585 glVertex3f(x-0.5, y-0.5, 0);
590 /* Central core walls.
592 for (i = 1; i < countof(points); i += 4)
595 GLfloat x1 = points[i-1][0] / 255.0L;
596 GLfloat y1 = points[i-1][1] / 255.0L;
597 GLfloat x2 = points[i][0] / 255.0L;
598 GLfloat y2 = points[i][1] / 255.0L;
599 face4(0, interior_color, wire,
600 0.0, 0.0, x1-0.5, y1-0.5, 0.5,
601 0.0, 0.0, x1-0.5, y1-0.5, 0.0,
602 0.0, 0.0, x2-0.5, y2-0.5, 0.0,
603 0.0, 0.0, x2-0.5, y2-0.5, 0.5);
611 tetra(ModeInfo *mi, Bool wire)
613 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
615 glNewList(lc->tetra_une, GL_COMPILE);
617 glShadeModel(GL_SMOOTH);
620 face3(lc->texids[FACE_U], exterior_color, wire,
621 1.0, 0.0, 0.5, -0.5, 0.5,
622 1.0, 1.0, 0.5, 0.5, 0.5,
623 0.0, 1.0, -0.5, 0.5, 0.5);
626 face3(lc->texids[FACE_N], exterior_color, wire,
627 0.0, 0.0, -0.5, 0.5, 0.5,
628 1.0, 0.0, 0.5, 0.5, 0.5,
629 1.0, 1.0, 0.5, 0.5, -0.5);
632 face3(lc->texids[FACE_E], exterior_color, wire,
633 1.0, 0.0, 0.5, 0.5, -0.5,
634 1.0, 1.0, 0.5, 0.5, 0.5,
635 0.0, 1.0, 0.5, -0.5, 0.5);
637 face3(0, interior_color, wire,
638 0.0, 0.0, 0.5, 0.5, -0.5,
639 0.0, 0.0, 0.5, -0.5, 0.5,
640 0.0, 0.0, -0.5, 0.5, 0.5);
644 glNewList(lc->tetra_usw, GL_COMPILE);
647 face3(lc->texids[FACE_U], exterior_color, wire,
648 0.0, 1.0, -0.5, 0.5, 0.5,
649 0.0, 0.0, -0.5, -0.5, 0.5,
650 1.0, 0.0, 0.5, -0.5, 0.5);
653 face3(lc->texids[FACE_S], exterior_color, wire,
654 1.0, 1.0, 0.5, -0.5, 0.5,
655 0.0, 1.0, -0.5, -0.5, 0.5,
656 0.0, 0.0, -0.5, -0.5, -0.5);
659 face3(lc->texids[FACE_W], exterior_color, wire,
660 1.0, 0.0, -0.5, -0.5, -0.5,
661 1.0, 1.0, -0.5, -0.5, 0.5,
662 0.0, 1.0, -0.5, 0.5, 0.5);
664 face3(0, interior_color, wire,
665 0.0,0.0, -0.5, -0.5, -0.5,
666 0.0,0.0, -0.5, 0.5, 0.5,
667 0.0,0.0, 0.5, -0.5, 0.5);
671 glNewList(lc->tetra_dwn, GL_COMPILE);
674 face3(lc->texids[FACE_D], exterior_color, wire,
675 0.0, 1.0, -0.5, -0.5, -0.5,
676 0.0, 0.0, -0.5, 0.5, -0.5,
677 1.0, 0.0, 0.5, 0.5, -0.5);
680 face3(lc->texids[FACE_W], exterior_color, wire,
681 0.0, 1.0, -0.5, 0.5, 0.5,
682 0.0, 0.0, -0.5, 0.5, -0.5,
683 1.0, 0.0, -0.5, -0.5, -0.5);
686 face3(lc->texids[FACE_N], exterior_color, wire,
687 1.0, 1.0, 0.5, 0.5, -0.5,
688 0.0, 1.0, -0.5, 0.5, -0.5,
689 0.0, 0.0, -0.5, 0.5, 0.5);
691 face3(0, interior_color, wire,
692 0.0, 0.0, 0.5, 0.5, -0.5,
693 0.0, 0.0, -0.5, 0.5, 0.5,
694 0.0, 0.0, -0.5, -0.5, -0.5);
698 glNewList(lc->tetra_dse, GL_COMPILE);
701 face3(lc->texids[FACE_S], exterior_color, wire,
702 0.0, 0.0, -0.5, -0.5, -0.5,
703 1.0, 0.0, 0.5, -0.5, -0.5,
704 1.0, 1.0, 0.5, -0.5, 0.5);
707 face3(lc->texids[FACE_E], exterior_color, wire,
708 0.0, 1.0, 0.5, -0.5, 0.5,
709 0.0, 0.0, 0.5, -0.5, -0.5,
710 1.0, 0.0, 0.5, 0.5, -0.5);
713 face3(lc->texids[FACE_D], exterior_color, wire,
714 1.0, 0.0, 0.5, 0.5, -0.5,
715 1.0, 1.0, 0.5, -0.5, -0.5,
716 0.0, 1.0, -0.5, -0.5, -0.5);
718 face3(0, interior_color, wire,
719 0.0, 0.0, 0.5, -0.5, 0.5,
720 0.0, 0.0, 0.5, 0.5, -0.5,
721 0.0, 0.0, -0.5, -0.5, -0.5);
725 glNewList(lc->tetra_mid, GL_COMPILE);
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);
732 face3(0, interior_color, wire,
733 0.0, 0.0, -0.5, 0.5, 0.5,
734 0.0, 0.0, -0.5, -0.5, -0.5,
735 0.0, 0.0, 0.5, -0.5, 0.5);
737 face3(0, interior_color, wire,
738 0.0, 0.0, -0.5, 0.5, 0.5,
739 0.0, 0.0, 0.5, 0.5, -0.5,
740 0.0, 0.0, -0.5, -0.5, -0.5);
742 face3(0, interior_color, wire,
743 0.0, 0.0, 0.5, 0.5, -0.5,
744 0.0, 0.0, 0.5, -0.5, 0.5,
745 0.0, 0.0, -0.5, -0.5, -0.5);
747 face3(0, interior_color, wire,
748 0.0, 0.0, 0.5, -0.5, 0.5,
749 0.0, 0.0, 0.5, 0.5, -0.5,
750 0.0, 0.0, -0.5, -0.5, -0.5);
757 lid(ModeInfo *mi, Bool wire)
759 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
763 { 128, 20 },{ 21, 129 },{ 0, 129 },{ 0, 0 },{ 128, 0 }, /* L1 */
764 { 21, 129 },{ 127, 234 },{ 127, 255 },{ 0, 255 },{ 0, 129 }, /* L2 */
765 { 127, 234 },{ 233, 127 },{ 255, 127 },{ 255, 255 },{ 127, 255 }, /* R2 */
766 { 233, 127 },{ 128, 20 },{ 128, 0 },{ 255, 0 },{ 255, 127 }, /* R1 */
769 for (i = 0; i < countof(points); i++)
770 points[i][1] = 255-points[i][1];
772 glNewList(lc->lid_0, GL_COMPILE);
773 glShadeModel(GL_SMOOTH);
776 face4(lc->texids[FACE_N], exterior_color, wire,
777 0.0, 0.0, -0.5, 0.5, 0.5,
778 1.0, 0.0, 0.5, 0.5, 0.5,
779 1.0, 1.0, 0.5, 0.5, -0.5,
780 0.0, 1.0, -0.5, 0.5, -0.5);
783 face4(lc->texids[FACE_S], exterior_color, wire,
784 0.0, 0.0, -0.5, -0.5, -0.5,
785 1.0, 0.0, 0.5, -0.5, -0.5,
786 1.0, 1.0, 0.5, -0.5, 0.5,
787 0.0, 1.0, -0.5, -0.5, 0.5);
790 face4(lc->texids[FACE_E], exterior_color, wire,
791 0.0, 0.0, 0.5, -0.5, -0.5,
792 1.0, 0.0, 0.5, 0.5, -0.5,
793 1.0, 1.0, 0.5, 0.5, 0.5,
794 0.0, 1.0, 0.5, -0.5, 0.5);
797 face4(lc->texids[FACE_U], exterior_color, wire,
798 1.0, 0.0, 0.5, -0.5, 0.5,
799 1.0, 1.0, 0.5, 0.5, 0.5,
800 0.0, 1.0, -0.5, 0.5, 0.5,
801 0.0, 0.0, -0.5, -0.5, 0.5);
804 face4(lc->texids[FACE_D], exterior_color, wire,
805 0.0, 1.0, -0.5, -0.5, -0.5,
806 0.0, 0.0, -0.5, 0.5, -0.5,
807 1.0, 0.0, 0.5, 0.5, -0.5,
808 1.0, 1.0, 0.5, -0.5, -0.5);
811 for (i = 0; i < countof(points)/5; i++)
814 GLfloat s[5], t[5], x[5], y[5], z[5];
815 for (j = 0; j < 5; j++)
817 GLfloat xx = points[(i*5)+j][0] / 255.0L;
818 GLfloat yy = points[(i*5)+j][1] / 255.0L;
825 face5(lc->texids[FACE_W], exterior_color, wire,
826 s[0], t[0], x[0], y[0], z[0],
827 s[1], t[1], x[1], y[1], z[1],
828 s[2], t[2], x[2], y[2], z[2],
829 s[3], t[3], x[3], y[3], z[3],
830 s[4], t[4], x[4], y[4], z[4]);
835 /* W -- lid_1 through lid_4 */
836 for (i = 0; i < 4; i++)
838 GLfloat x1, y1, x2, y2, x3, y3;
840 glNewList(lc->lid_1 + i, GL_COMPILE);
841 glShadeModel(GL_SMOOTH);
843 x1 = points[(i*5)+1][0] / 255.0L;
844 y1 = points[(i*5)+1][1] / 255.0L;
845 x2 = points[(i*5)][0] / 255.0L;
846 y2 = points[(i*5)][1] / 255.0L;
851 face3(lc->texids[FACE_W], exterior_color, wire,
852 1.0-x1, y1, -0.5, x1-0.5, y1-0.5,
853 1.0-x2, y2, -0.5, x2-0.5, y2-0.5,
854 1.0-x3, y3, -0.5, x3-0.5, y3-0.5);
857 face3(0, interior_color, wire,
858 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
859 0.0, 0.0, -0.48, x1-0.5, y1-0.5,
860 0.0, 0.0, -0.48, x3-0.5, y3-0.5);
863 face4(0, interior_color, wire,
864 0.0, 0.0, -0.5, x1-0.5, y1-0.5,
865 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
866 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
867 0.0, 0.0, -0.48, x1-0.5, y1-0.5);
870 face4(0, interior_color, wire,
871 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
872 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
873 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
874 0.0, 0.0, -0.5, x2-0.5, y2-0.5);
881 taser(ModeInfo *mi, Bool wire)
883 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
886 int slider_face_points[][2] = {
887 { 86, 58 },{ 38, 106 },{ 70, 106 },{ 118, 58 },{ -1, -1 }, /* a */
888 { 136, 58 },{ 184, 106 },{ 216, 106 },{ 168, 58 },{ -1, -1 }, /* b */
889 { 38, 106 },{ 0, 144 },{ 0, 190 },{ 60, 190 },{ 108, 106 }, /* c */
890 { 144, 106 },{ 194, 190 },{ 254, 190 },{ 254, 144 },{ 216, 106 }, /* d */
891 { 98, 124 },{ 60, 190 },{ 92, 190 },{ 126, 158 },{ 126, 124 }, /* e */
892 { 126, 124 },{ 126, 158 },{ 160, 190 },{ 194, 190 },{ 154, 124 }, /* f */
893 { 22, 190 },{ 22, 254 },{ 60, 254 },{ 60, 190 },{ -1, -1 }, /* g */
894 { 194, 190 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ -1, -1 }, /* h */
895 { 60, 190 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ -1, -1 }, /* i */
896 { 160, 190 },{ 160, 210 },{ 194, 210 },{ 194, 190 },{ -1, -1 }, /* j */
897 { 110, 172 },{ 92, 190 },{ 110, 190 },{ -1, -1 },{ -1, -1 }, /* k */
898 { 140, 172 },{ 140, 190 },{ 160, 190 },{ -1, -1 },{ -1, -1 }, /* l */
899 { 110, 172 },{ 140, 172 },{ 126, 156 },{ -1, -1 },{ -1, -1 }, /* m */
902 int body_face_points[][2] = {
903 { 0, 0 },{ 0, 58 },{ 254, 58 },{ 254, 0 },{ -1, -1 }, /* A */
904 { 0, 58 },{ 0, 144 },{ 86, 58 },{ -1, -1 },{ -1, -1 }, /* B */
905 { 168, 58 },{ 254, 144 },{ 254, 58 },{ -1, -1 },{ -1, -1 }, /* C */
906 { 118, 58 },{ 70, 106 },{ 184, 106 },{ 136, 58 },{ -1, -1 }, /* F */
907 { 108, 106 },{ 98, 124 },{ 154, 124 },{ 144, 106 },{ -1, -1 }, /* G */
910 int lifter_face_points[][2] = {
911 { 0, 190 },{ 0, 254 },{ 22, 254 },{ 22, 190 },{ -1, -1 }, /* D */
912 { 230, 190 },{ 230, 254 },{ 254, 254 },{ 254, 190 },{ -1, -1 }, /* E */
913 { 60, 210 },{ 60, 254 },{ 194, 254 },{ 194, 210 },{ -1, -1 }, /* H */
914 { 92, 190 },{ 92, 210 },{ 160, 210 },{ 160, 190 },{ -1, -1 }, /* I */
915 { 110, 172 },{ 110, 190 },{ 140, 190 },{ 140, 172 },{ -1, -1 }, /* J */
918 int body_perimiter_points[][2] = {
919 { 0, 144 },{ 86, 59 },{ 119, 58 },{ 71, 107 },
920 { 108, 107 },{ 98, 124 },{ 155, 124 },{ 144, 107 },
921 { 185, 106 },{ 136, 59 },{ 169, 59 },{ 255, 145 },
925 int slider_perimiter_points[][2] = {
926 { 86, 58 },{ 0, 144 },{ 0, 190 },{ 22, 190 },{ 22, 254 },
927 { 60, 254 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ 110, 190 },
928 { 110, 172 },{ 140, 172 },{ 140, 190 },{ 160, 190 },{ 160, 210 },
929 { 194, 210 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ 254, 190 },
930 { 254, 144 },{ 168, 58 },{ 136, 58 },{ 184, 106 },{ 144, 106 },
931 { 154, 124 },{ 98, 124 },{ 108, 106 },{ 70, 106 },{ 118, 58 },
934 int lifter_perimiter_points_1[][2] = {
935 { 0, 189 },{ 0, 254 },{ 22, 255 },{ 23, 190 },
938 int lifter_perimiter_points_2[][2] = {
939 { 230, 254 },{ 255, 255 },{ 254, 190 },{ 230, 190 },
942 int lifter_perimiter_points_3[][2] = {
943 { 60, 254 },{ 194, 254 },{ 194, 211 },{ 160, 210 },
944 { 160, 190 },{ 140, 191 },{ 141, 172 },{ 111, 172 },
945 { 110, 190 },{ 93, 190 },{ 92, 210 },{ 60, 211 },
948 for (i = 0; i < countof(slider_face_points); i++)
949 slider_face_points[i][1] = 255-slider_face_points[i][1];
950 for (i = 0; i < countof(body_face_points); i++)
951 body_face_points[i][1] = 255-body_face_points[i][1];
952 for (i = 0; i < countof(lifter_face_points); i++)
953 lifter_face_points[i][1] = 255-lifter_face_points[i][1];
954 for (i = 0; i < countof(body_perimiter_points); i++)
955 body_perimiter_points[i][1] = 255-body_perimiter_points[i][1];
956 for (i = 0; i < countof(slider_perimiter_points); i++)
957 slider_perimiter_points[i][1] = 255-slider_perimiter_points[i][1];
958 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
959 lifter_perimiter_points_1[i][1] = 255-lifter_perimiter_points_1[i][1];
960 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
961 lifter_perimiter_points_2[i][1] = 255-lifter_perimiter_points_2[i][1];
962 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
963 lifter_perimiter_points_3[i][1] = 255-lifter_perimiter_points_3[i][1];
965 /* -------------------------------------------------------------------- */
967 glNewList(lc->taser_base, GL_COMPILE);
968 glShadeModel(GL_SMOOTH);
971 face4(lc->texids[FACE_N], exterior_color, wire,
972 0.0, 0.0, -0.5, 0.5, 0.5,
973 0.75, 0.0, 0.25, 0.5, 0.5,
974 0.75, 0.75, 0.25, 0.5, -0.25,
975 0.0, 0.75, -0.5, 0.5, -0.25);
978 face4(lc->texids[FACE_S], exterior_color, wire,
979 0.0, 0.25, -0.5, -0.5, -0.25,
980 0.75, 0.25, 0.25, -0.5, -0.25,
981 0.75, 1.0, 0.25, -0.5, 0.5,
982 0.0, 1.0, -0.5, -0.5, 0.5);
985 face4(0, interior_color, wire,
986 0.0, 0.0, 0.25, -0.5, -0.25,
987 1.0, 0.0, 0.25, 0.5, -0.25,
988 1.0, 1.0, 0.25, 0.5, 0.5,
989 0.0, 1.0, 0.25, -0.5, 0.5);
992 face4(lc->texids[FACE_W], exterior_color, wire,
993 1.0, 1.0, -0.5, -0.5, 0.5,
994 0.0, 1.0, -0.5, 0.5, 0.5,
995 0.0, 0.25, -0.5, 0.5, -0.25,
996 1.0, 0.25, -0.5, -0.5, -0.25);
999 face4(lc->texids[FACE_U], exterior_color, wire,
1000 0.75, 0.0, 0.25, -0.5, 0.5,
1001 0.75, 1.0, 0.25, 0.5, 0.5,
1002 0.0, 1.0, -0.5, 0.5, 0.5,
1003 0.0, 0.0, -0.5, -0.5, 0.5);
1006 face4(0, interior_color, wire,
1007 0.0, 1.0, -0.5, -0.5, -0.25,
1008 0.0, 0.0, -0.5, 0.5, -0.25,
1009 1.0, 0.0, 0.25, 0.5, -0.25,
1010 1.0, 1.0, 0.25, -0.5, -0.25);
1013 for (i = 0; i < countof(body_face_points)/5; i++)
1016 #ifdef HAVE_GLBINDTEXTURE
1017 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1018 #endif /* HAVE_GLBINDTEXTURE */
1019 set_colors(exterior_color);
1021 do_normal(0, body_face_points[(i*5)+0][0], body_face_points[(i*5)+0][1],
1022 0, body_face_points[(i*5)+1][0], body_face_points[(i*5)+1][1],
1023 0, body_face_points[(i*5)+2][0], body_face_points[(i*5)+2][1]
1025 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1026 for (j = 0; j < 5; j++)
1028 int ix = body_face_points[(i*5)+j][0];
1029 int iy = body_face_points[(i*5)+j][1];
1031 if (ix == -1) /* these are padding: ignore them */
1036 glVertex3f(0.5, x-0.5, y-0.5);
1042 for (i = 0; i < countof(body_perimiter_points); i++)
1044 int j = (i+1 >= countof(body_perimiter_points) ? 0 : i+1);
1045 GLfloat x1 = body_perimiter_points[i][0] / 255.0;
1046 GLfloat y1 = body_perimiter_points[i][1] / 255.0;
1047 GLfloat x2 = body_perimiter_points[j][0] / 255.0;
1048 GLfloat y2 = body_perimiter_points[j][1] / 255.0;
1050 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1054 texture = lc->texids[FACE_N];
1056 s2 = 1.0; t2 = 0.568;
1057 s3 = 0.75, t3 = 0.568;
1058 s4 = 0.75; t4 = 0.0;
1062 texture = lc->texids[FACE_U];
1065 s3 = 0.75, t3 = 1.0;
1066 s4 = 0.75; t4 = 0.0;
1070 texture = lc->texids[FACE_S];
1071 s1 = 1.0; t1 = 0.437;
1073 s3 = 0.75; t3 = 1.0;
1074 s4 = 0.75; t4 = 0.437;
1077 face4((texture == -1 ? 0 : texture),
1078 (texture == -1 ? interior_color : exterior_color),
1080 s1, t1, 0.5, x2-0.5, y2-0.5,
1081 s2, t2, 0.5, x1-0.5, y1-0.5,
1082 s3, t3, 0.25, x1-0.5, y1-0.5,
1083 s4, t4, 0.25, x2-0.5, y2-0.5);
1088 /* -------------------------------------------------------------------- */
1090 glNewList(lc->taser_lifter, GL_COMPILE);
1091 glShadeModel(GL_SMOOTH);
1094 face4(lc->texids[FACE_N], exterior_color, wire,
1095 0.0, 0.75, -0.5, 0.5, -0.25,
1096 0.75, 0.75, 0.25, 0.5, -0.25,
1097 0.75, 1.0, 0.25, 0.5, -0.5,
1098 0.0, 1.0, -0.5, 0.5, -0.5);
1101 face4(lc->texids[FACE_S], exterior_color, wire,
1102 0.0, 0.0, -0.5, -0.5, -0.5,
1103 0.75, 0.0, 0.25, -0.5, -0.5,
1104 0.75, 0.25, 0.25, -0.5, -0.25,
1105 0.0, 0.25, -0.5, -0.5, -0.25);
1108 face4(0, interior_color, wire,
1109 0.0, 1.0, 0.25, -0.5, -0.5,
1110 1.0, 1.0, 0.25, 0.5, -0.5,
1111 1.0, 0.0, 0.25, 0.5, -0.25,
1112 0.0, 0.0, 0.25, -0.5, -0.25);
1115 face4(lc->texids[FACE_W], exterior_color, wire,
1116 1.0, 0.25, -0.5, -0.5, -0.25,
1117 0.0, 0.25, -0.5, 0.5, -0.25,
1118 0.0, 0.0, -0.5, 0.5, -0.5,
1119 1.0, 0.0, -0.5, -0.5, -0.5);
1122 face4(0, interior_color, wire,
1123 1.0, 0.0, 0.25, -0.5, -0.25,
1124 1.0, 1.0, 0.25, 0.5, -0.25,
1125 0.0, 1.0, -0.5, 0.5, -0.25,
1126 0.0, 0.0, -0.5, -0.5, -0.25);
1129 face4(lc->texids[FACE_D], exterior_color, wire,
1130 0.0, 1.0, -0.5, -0.5, -0.5,
1131 0.0, 0.0, -0.5, 0.5, -0.5,
1132 0.75, 0.0, 0.25, 0.5, -0.5,
1133 0.75, 1.0, 0.25, -0.5, -0.5);
1137 for (i = 0; i < countof(lifter_face_points)/5; i++)
1141 #ifdef HAVE_GLBINDTEXTURE
1142 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1143 #endif /* HAVE_GLBINDTEXTURE */
1144 set_colors(exterior_color);
1147 0, lifter_face_points[(i*5)+0][0], lifter_face_points[(i*5)+0][1],
1148 0, lifter_face_points[(i*5)+1][0], lifter_face_points[(i*5)+1][1],
1149 0, lifter_face_points[(i*5)+2][0], lifter_face_points[(i*5)+2][1]);
1151 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1152 for (j = 0; j < 5; j++)
1154 int ix = lifter_face_points[(i*5)+j][0];
1155 int iy = lifter_face_points[(i*5)+j][1];
1157 if (ix == -1) /* these are padding: ignore them */
1162 glVertex3f(0.5, x-0.5, y-0.5);
1168 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
1170 int j = (i+1 >= countof(lifter_perimiter_points_1) ? 0 : i+1);
1171 GLfloat x1 = lifter_perimiter_points_1[i][0] / 255.0;
1172 GLfloat y1 = lifter_perimiter_points_1[i][1] / 255.0;
1173 GLfloat x2 = lifter_perimiter_points_1[j][0] / 255.0;
1174 GLfloat y2 = lifter_perimiter_points_1[j][1] / 255.0;
1176 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1180 texture = lc->texids[FACE_S];
1182 s2 = 1.0; t2 = 0.26;
1183 s3 = 0.75, t3 = 0.26;
1184 s4 = 0.75; t4 = 0.0;
1188 texture = lc->texids[FACE_D];
1189 s1 = 1.0; t1 = 0.914;
1191 s3 = 0.75; t3 = 1.0;
1192 s4 = 0.75; t4 = 0.914;
1195 face4((texture == -1 ? 0 : texture),
1196 (texture == -1 ? interior_color : exterior_color),
1198 s1, t1, 0.5, x2-0.5, y2-0.5,
1199 s2, t2, 0.5, x1-0.5, y1-0.5,
1200 s3, t3, 0.25, x1-0.5, y1-0.5,
1201 s4, t4, 0.25, x2-0.5, y2-0.5);
1204 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
1206 int j = (i+1 >= countof(lifter_perimiter_points_2) ? 0 : i+1);
1207 GLfloat x1 = lifter_perimiter_points_2[i][0] / 255.0;
1208 GLfloat y1 = lifter_perimiter_points_2[i][1] / 255.0;
1209 GLfloat x2 = lifter_perimiter_points_2[j][0] / 255.0;
1210 GLfloat y2 = lifter_perimiter_points_2[j][1] / 255.0;
1212 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1216 texture = lc->texids[FACE_D];
1218 s2 = 1.0; t2 = 0.095;
1219 s3 = 0.75; t3 = 0.095;
1220 s4 = 0.75; t4 = 0.0;
1224 texture = lc->texids[FACE_N];
1225 s1 = 1.0; t1 = 0.745;
1227 s3 = 0.75; t3 = 1.0;
1228 s4 = 0.75; t4 = 0.745;
1231 face4((texture == -1 ? 0 : texture),
1232 (texture == -1 ? interior_color : exterior_color),
1234 s1, t1, 0.5, x2-0.5, y2-0.5,
1235 s2, t2, 0.5, x1-0.5, y1-0.5,
1236 s3, t3, 0.25, x1-0.5, y1-0.5,
1237 s4, t4, 0.25, x2-0.5, y2-0.5);
1240 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
1242 int j = (i+1 >= countof(lifter_perimiter_points_3) ? 0 : i+1);
1243 GLfloat x1 = lifter_perimiter_points_3[i][0] / 255.0;
1244 GLfloat y1 = lifter_perimiter_points_3[i][1] / 255.0;
1245 GLfloat x2 = lifter_perimiter_points_3[j][0] / 255.0;
1246 GLfloat y2 = lifter_perimiter_points_3[j][1] / 255.0;
1248 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1252 texture = lc->texids[FACE_D];
1253 s1 = 1.0; t1 = 0.235;
1254 s2 = 1.0; t2 = 0.765;
1255 s3 = 0.75; t3 = 0.765;
1256 s4 = 0.75; t4 = 0.235;
1259 face4((texture == -1 ? 0 : texture),
1260 (texture == -1 ? interior_color : exterior_color),
1262 s1, t1, 0.5, x2-0.5, y2-0.5,
1263 s2, t2, 0.5, x1-0.5, y1-0.5,
1264 s3, t3, 0.25, x1-0.5, y1-0.5,
1265 s4, t4, 0.25, x2-0.5, y2-0.5);
1270 /* -------------------------------------------------------------------- */
1272 glNewList(lc->taser_slider, GL_COMPILE);
1273 glShadeModel(GL_SMOOTH);
1276 for (i = 0; i < countof(slider_face_points)/5; i++)
1279 #ifdef HAVE_GLBINDTEXTURE
1280 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1281 #endif /* HAVE_GLBINDTEXTURE */
1282 set_colors(exterior_color);
1285 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1],
1286 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1287 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1]);
1288 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1289 for (j = 0; j < 5; j++)
1291 int ix = slider_face_points[(i*5)+j][0];
1292 int iy = slider_face_points[(i*5)+j][1];
1294 if (ix == -1) /* these are padding: ignore them */
1299 glVertex3f(0.5, x-0.5, y-0.5);
1305 for (i = countof(slider_face_points)/5 - 1; i >= 0; i--)
1308 #ifdef HAVE_GLBINDTEXTURE
1309 glBindTexture(GL_TEXTURE_2D, 0);
1310 #endif /* HAVE_GLBINDTEXTURE */
1311 set_colors(interior_color);
1314 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1],
1315 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1316 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1]);
1317 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1318 for (j = 4; j >= 0; j--)
1320 int ix = slider_face_points[(i*5)+j][0];
1321 int iy = slider_face_points[(i*5)+j][1];
1323 if (ix == -1) /* these are padding: ignore them */
1328 glVertex3f(0.25, x-0.5, y-0.5);
1334 for (i = 0; i < countof(slider_perimiter_points); i++)
1336 int j = (i+1 >= countof(slider_perimiter_points) ? 0 : i+1);
1337 GLfloat x1 = slider_perimiter_points[i][0] / 255.0;
1338 GLfloat y1 = slider_perimiter_points[i][1] / 255.0;
1339 GLfloat x2 = slider_perimiter_points[j][0] / 255.0;
1340 GLfloat y2 = slider_perimiter_points[j][1] / 255.0;
1342 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1346 texture = lc->texids[FACE_S];
1347 s1 = 1.0; t1 = 0.255;
1348 s2 = 1.0; t2 = 0.435;
1349 s3 = 0.75; t3 = 0.435;
1350 s4 = 0.75; t4 = 0.255;
1354 texture = lc->texids[FACE_D];
1355 s1 = 1.0; t1 = 0.758;
1356 s2 = 1.0; t2 = 0.915;
1357 s3 = 0.75; t3 = 0.915;
1358 s4 = 0.75; t4 = 0.758;
1362 texture = lc->texids[FACE_D];
1363 s1 = 1.0; t1 = 0.095;
1364 s2 = 1.0; t2 = 0.24;
1365 s3 = 0.75; t3 = 0.24;
1366 s4 = 0.75; t4 = 0.095;
1370 texture = lc->texids[FACE_N];
1371 s1 = 1.0; t1 = 0.568;
1372 s2 = 1.0; t2 = 0.742;
1373 s3 = 0.75; t3 = 0.742;
1374 s4 = 0.75; t4 = 0.568;
1377 face4((texture == -1 ? 0 : texture),
1378 (texture == -1 ? interior_color : exterior_color),
1380 s1, t1, 0.5, x2-0.5, y2-0.5,
1381 s2, t2, 0.5, x1-0.5, y1-0.5,
1382 s3, t3, 0.25, x1-0.5, y1-0.5,
1383 s4, t4, 0.25, x2-0.5, y2-0.5);
1391 /* Rendering and animating object models
1395 lament_handle_event (ModeInfo *mi, XEvent *event)
1397 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1399 if (event->xany.type == ButtonPress &&
1400 event->xbutton.button & Button1)
1402 lc->button_down_p = True;
1403 gltrackball_start (lc->trackball,
1404 event->xbutton.x, event->xbutton.y,
1405 MI_WIDTH (mi), MI_HEIGHT (mi));
1408 else if (event->xany.type == ButtonRelease &&
1409 event->xbutton.button & Button1)
1411 lc->button_down_p = False;
1414 else if (event->xany.type == MotionNotify &&
1417 gltrackball_track (lc->trackball,
1418 event->xmotion.x, event->xmotion.y,
1419 MI_WIDTH (mi), MI_HEIGHT (mi));
1430 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1431 Bool wire = MI_IS_WIREFRAME(mi);
1434 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1436 glClear(GL_COLOR_BUFFER_BIT);
1440 gltrackball_rotate (lc->trackball);
1442 /* Make into the screen be +Y right be +X, and up be +Z. */
1443 glRotatef(-90.0, 1.0, 0.0, 0.0);
1446 glScalef(4.0, 4.0, 4.0);
1451 /* Shift to the upper left, and draw the vanilla box. */
1452 glTranslatef(-0.6, 0.0, 0.6);
1454 /* Apply rotation to the object. */
1455 glRotatef(x * 360, 1.0, 0.0, 0.0);
1456 glRotatef(y * 360, 0.0, 1.0, 0.0);
1457 glRotatef(z * 360, 0.0, 0.0, 1.0);
1460 glCallList(lc->box);
1464 /* Shift to the lower right, and draw the animated object. */
1465 glTranslatef(0.6, 0.0, -0.6);
1471 /* Apply rotation to the object. */
1472 if (lc->type != LAMENT_LID_ZOOM)
1473 get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
1474 !lc->button_down_p);
1475 glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
1476 glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
1477 glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
1482 glCallList(lc->box);
1485 case LAMENT_STAR_OUT:
1486 case LAMENT_STAR_ROT:
1487 case LAMENT_STAR_ROT_IN:
1488 case LAMENT_STAR_ROT_OUT:
1489 case LAMENT_STAR_UNROT:
1490 case LAMENT_STAR_IN:
1491 glTranslatef(0.0, 0.0, lc->anim_z/2);
1492 glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0);
1493 glCallList(lc->star1);
1495 glTranslatef(0.0, 0.0, -lc->anim_z);
1496 glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
1497 glCallList(lc->star2);
1500 case LAMENT_TETRA_UNE:
1501 case LAMENT_TETRA_USW:
1502 case LAMENT_TETRA_DWN:
1503 case LAMENT_TETRA_DSE:
1508 case LAMENT_TETRA_UNE: magic = lc->tetra_une;
1509 x = 1.0; y = 1.0; z = 1.0; break;
1510 case LAMENT_TETRA_USW: magic = lc->tetra_usw;
1511 x = 1.0; y = 1.0; z = -1.0; break;
1512 case LAMENT_TETRA_DWN: magic = lc->tetra_dwn;
1513 x = 1.0; y = -1.0; z = 1.0; break;
1514 case LAMENT_TETRA_DSE: magic = lc->tetra_dse;
1515 x = -1.0; y = 1.0; z = 1.0; break;
1516 default: abort(); break;
1518 glCallList(lc->tetra_mid);
1519 if (magic != lc->tetra_une) glCallList(lc->tetra_une);
1520 if (magic != lc->tetra_usw) glCallList(lc->tetra_usw);
1521 if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn);
1522 if (magic != lc->tetra_dse) glCallList(lc->tetra_dse);
1523 glRotatef(lc->anim_r, x, y, z);
1528 case LAMENT_LID_OPEN:
1529 case LAMENT_LID_CLOSE:
1530 case LAMENT_LID_ZOOM:
1534 glTranslatef(lc->anim_z, 0.0, 0.0);
1536 glCallList(lc->lid_0);
1539 glTranslatef(-0.5, -d, 0.0);
1540 glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
1541 glTranslatef( 0.5, d, 0.0);
1542 glCallList(lc->lid_1);
1545 glTranslatef(-0.5, -d, 0.0);
1546 glRotatef( lc->anim_r, 0.0, -1.0, 1.0);
1547 glTranslatef( 0.5, d, 0.0);
1548 glCallList(lc->lid_2);
1551 glTranslatef(-0.5, d, 0.0);
1552 glRotatef( lc->anim_r, 0.0, -1.0, -1.0);
1553 glTranslatef( 0.5, -d, 0.0);
1554 glCallList(lc->lid_3);
1557 glTranslatef(-0.5, d, 0.0);
1558 glRotatef(-lc->anim_r, 0.0, -1.0, 1.0);
1559 glTranslatef( 0.5, -d, 0.0);
1560 glCallList(lc->lid_4);
1565 case LAMENT_TASER_OUT:
1566 case LAMENT_TASER_SLIDE:
1567 case LAMENT_TASER_SLIDE_IN:
1568 case LAMENT_TASER_IN:
1570 glTranslatef(-lc->anim_z/2, 0.0, 0.0);
1571 glCallList(lc->taser_base);
1573 glTranslatef(lc->anim_z, 0.0, 0.0);
1574 glCallList(lc->taser_lifter);
1576 glTranslatef(0.0, 0.0, lc->anim_y);
1577 glCallList(lc->taser_slider);
1592 animate(ModeInfo *mi)
1594 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1596 /* int pause2 = 60;*/
1603 /* Rather than just picking states randomly, pick an ordering randomly,
1604 do it, and then re-randomize. That way one can be assured of seeing
1605 all states in a short time period, though not always in the same
1606 order (it's frustrating to see it pick the same state 5x in a row.)
1608 static lament_type states[] = {
1609 LAMENT_STAR_OUT, LAMENT_STAR_OUT,
1610 LAMENT_TETRA_UNE, LAMENT_TETRA_USW,
1611 LAMENT_TETRA_DWN, LAMENT_TETRA_DSE,
1612 LAMENT_LID_OPEN, LAMENT_LID_OPEN, LAMENT_LID_OPEN,
1613 LAMENT_TASER_OUT, LAMENT_TASER_OUT,
1614 LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
1615 LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
1617 static int state = countof(states);
1619 if (state < countof(states))
1621 lc->type = states[state++];
1627 for (i = 0; i < countof(states); i++)
1629 int a = random() % countof(states);
1630 lament_type swap = states[a];
1631 states[a] = states[i];
1636 if (lc->type == LAMENT_BOX)
1637 lc->anim_pause = pause3;
1645 /* -------------------------------------------------------------- */
1647 case LAMENT_STAR_OUT:
1649 if (lc->anim_z >= 1.0)
1652 lc->type = LAMENT_STAR_ROT;
1653 lc->anim_pause = pause;
1657 case LAMENT_STAR_ROT:
1659 if (lc->anim_r >= 45.0)
1662 lc->type = LAMENT_STAR_ROT_IN;
1663 lc->anim_pause = pause;
1667 case LAMENT_STAR_ROT_IN:
1669 if (lc->anim_z <= 0.0)
1672 lc->type = LAMENT_STAR_ROT_OUT;
1673 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1677 case LAMENT_STAR_ROT_OUT:
1679 if (lc->anim_z >= 1.0)
1682 lc->type = LAMENT_STAR_UNROT;
1683 lc->anim_pause = pause;
1687 case LAMENT_STAR_UNROT:
1689 if (lc->anim_r <= 0.0)
1692 lc->type = LAMENT_STAR_IN;
1693 lc->anim_pause = pause;
1697 case LAMENT_STAR_IN:
1699 if (lc->anim_z <= 0.0)
1702 lc->type = LAMENT_BOX;
1703 lc->anim_pause = pause3;
1707 /* -------------------------------------------------------------- */
1709 case LAMENT_TETRA_UNE:
1710 case LAMENT_TETRA_USW:
1711 case LAMENT_TETRA_DWN:
1712 case LAMENT_TETRA_DSE:
1715 if (lc->anim_r >= 360.0)
1718 lc->type = LAMENT_BOX;
1719 lc->anim_pause = pause3;
1721 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1724 lc->anim_pause = pause;
1726 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1729 lc->anim_pause = pause;
1733 /* -------------------------------------------------------------- */
1735 case LAMENT_LID_OPEN:
1738 if (lc->anim_r >= 112.0)
1740 GLfloat hysteresis = 0.05;
1744 lc->anim_pause = pause3;
1746 if (lc->rotx >= -hysteresis &&
1747 lc->rotx <= hysteresis &&
1748 ((lc->rotz >= (0.25 - hysteresis) &&
1749 lc->rotz <= (0.25 + hysteresis)) ||
1750 (lc->rotz >= (-0.25 - hysteresis) &&
1751 lc->rotz <= (-0.25 + hysteresis))))
1753 lc->type = LAMENT_LID_ZOOM;
1755 lc->rotz = (lc->rotz < 0 ? -0.25 : 0.25);
1759 lc->type = LAMENT_LID_CLOSE;
1764 case LAMENT_LID_CLOSE:
1766 if (lc->anim_r <= 0.0)
1769 lc->type = LAMENT_BOX;
1770 lc->anim_pause = pause3;
1774 case LAMENT_LID_ZOOM:
1776 if (lc->anim_z < -50.0)
1780 lc->type = LAMENT_BOX;
1784 /* -------------------------------------------------------------- */
1786 case LAMENT_TASER_OUT:
1787 lc->anim_z += 0.0025;
1788 if (lc->anim_z >= 0.25)
1791 lc->type = LAMENT_TASER_SLIDE;
1792 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1796 case LAMENT_TASER_SLIDE:
1797 lc->anim_y += 0.0025;
1798 if (lc->anim_y >= 0.23)
1801 lc->type = LAMENT_TASER_SLIDE_IN;
1802 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1806 case LAMENT_TASER_SLIDE_IN:
1807 lc->anim_y -= 0.0025;
1808 if (lc->anim_y <= 0.0)
1811 lc->type = LAMENT_TASER_IN;
1812 lc->anim_pause = pause;
1816 case LAMENT_TASER_IN:
1817 lc->anim_z -= 0.0025;
1818 if (lc->anim_z <= 0.0)
1821 lc->type = LAMENT_BOX;
1822 lc->anim_pause = pause3;
1834 /* Window management, etc
1838 reshape_lament(ModeInfo *mi, int width, int height)
1840 int target_size = 180;
1841 int win_size = (width > height ? height : width);
1842 GLfloat h = (GLfloat) height / (GLfloat) width;
1844 glViewport(0, 0, (GLint) width, (GLint) height);
1846 /* glViewport(-600, -600, 1800, 1800); */
1848 glMatrixMode(GL_PROJECTION);
1850 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1851 glMatrixMode(GL_MODELVIEW);
1853 glTranslatef(0.0, 0.0, -40.0);
1855 /* This scale makes the box take up most of the window */
1856 glScalef(2.0, 2.0, 2.0);
1858 /* But if the window is more than a little larger than our target size,
1859 scale the object back down, so that the bits drawn on the screen end
1860 up rougly target_size across (actually it ends up a little larger.)
1861 Note that the image-map bits we have are 128x128. Therefore, if the
1862 image is magnified a lot, it looks pretty blocky. So it's better to
1863 have a 128x128 animation on a 1280x1024 screen that looks good, than
1864 a 1024x1024 animation that looks really pixellated.
1866 if (win_size > target_size * 1.5)
1868 GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
1870 glScalef(ratio, ratio, ratio);
1873 /* The depth buffer will be cleared, if needed, before the
1874 * next frame. Right now we just want to black the screen.
1876 glClear(GL_COLOR_BUFFER_BIT);
1881 gl_init(ModeInfo *mi)
1883 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1884 Bool wire = MI_IS_WIREFRAME(mi);
1891 static GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1892 static GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1894 static GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1895 /* static GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1896 static GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1897 static GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1899 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1900 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1902 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1903 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1904 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1905 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1906 set_colors(exterior_color);
1908 glEnable(GL_LIGHTING);
1909 glEnable(GL_LIGHT0);
1910 /* glEnable(GL_LIGHT1); */
1912 glEnable(GL_DEPTH_TEST);
1913 glEnable(GL_TEXTURE_2D);
1914 glEnable(GL_NORMALIZE);
1915 glEnable(GL_CULL_FACE);
1920 #ifdef HAVE_GLBINDTEXTURE
1922 for (i = 0; i < 6; i++)
1923 glGenTextures(1, &lc->texids[i]);
1925 parse_image_data(mi);
1927 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1928 glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width);
1930 for (i = 0; i < 6; i++)
1932 int height = lc->texture->width; /* assume square */
1933 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1934 set_colors(exterior_color);
1937 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1938 lc->texture->width, height, 0,
1940 /* GL_UNSIGNED_BYTE, */
1941 GL_UNSIGNED_INT_8_8_8_8_REV,
1942 (lc->texture->data +
1943 (lc->texture->bytes_per_line * height * i)));
1944 check_gl_error("texture");
1946 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1947 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1948 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1949 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1950 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1951 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1954 #else /* !HAVE_GLBINDTEXTURE */
1956 "%s: this version of GL doesn't support multiple texture maps.\n"
1957 "\tGet OpenGL 1.1.\n",
1960 #endif /* !HAVE_GLBINDTEXTURE */
1963 lc->box = glGenLists(16);
1964 lc->star1 = lc->box+1;
1965 lc->star2 = lc->box+2;
1966 lc->tetra_une = lc->box+3;
1967 lc->tetra_usw = lc->box+4;
1968 lc->tetra_dwn = lc->box+5;
1969 lc->tetra_dse = lc->box+6;
1970 lc->tetra_mid = lc->box+7;
1971 lc->lid_0 = lc->box+8;
1972 lc->lid_1 = lc->box+9;
1973 lc->lid_2 = lc->box+10;
1974 lc->lid_3 = lc->box+11;
1975 lc->lid_4 = lc->box+12;
1976 lc->taser_base = lc->box+13;
1977 lc->taser_lifter = lc->box+14;
1978 lc->taser_slider = lc->box+15;
1981 star(mi, True, wire);
1982 star(mi, False, wire);
1989 # ifdef HAVE_MESA_GL
1991 # include <signal.h>
1994 lament_signal_kludge (int sig)
1996 signal (sig, SIG_DFL);
1999 "%s: dying with signal %d (%s).\n"
2001 "\tThis is almost certainly a bug in the Mesa GL library,\n"
2002 "\tespecially if the stack trace in the core file mentions\n"
2003 "\t`lambda_textured_triangle' or `render_quad'.\n"
2005 "\tFirst make sure that you have the latest version of Mesa.\n"
2006 "\tIf that doesn't fix it, then I encourage you to report this\n"
2007 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
2011 (sig == SIGILL ? "SIGILL" :
2012 sig == SIGFPE ? "SIGFPE" :
2013 sig == SIGBUS ? "SIGBUS" :
2014 sig == SIGSEGV ? "SIGSEGV" : "???"));
2016 kill (getpid (), sig);
2020 handle_signals (void)
2022 signal (SIGILL, lament_signal_kludge);
2023 signal (SIGFPE, lament_signal_kludge);
2024 signal (SIGBUS, lament_signal_kludge);
2025 signal (SIGSEGV, lament_signal_kludge);
2027 # endif /* HAVE_MESA_GL */
2031 init_lament(ModeInfo *mi)
2033 lament_configuration *lc;
2036 lcs = (lament_configuration *)
2037 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
2040 fprintf(stderr, "%s: out of memory\n", progname);
2045 lc = &lcs[MI_SCREEN(mi)];
2048 double rot_speed = 0.5;
2049 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
2050 lc->trackball = gltrackball_init ();
2053 lc->type = LAMENT_BOX;
2054 lc->anim_pause = 300 + (random() % 100);
2056 if ((lc->glx_context = init_GL(mi)) != NULL)
2058 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2062 # ifdef HAVE_MESA_GL
2064 # endif /* HAVE_MESA_GL */
2069 draw_lament(ModeInfo *mi)
2071 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2072 Display *dpy = MI_DISPLAY(mi);
2073 Window window = MI_WINDOW(mi);
2075 if (!lc->glx_context)
2078 glDrawBuffer(GL_BACK);
2080 glXMakeCurrent(dpy, window, *(lc->glx_context));
2082 if (mi->fps_p) do_fps (mi);
2085 glXSwapBuffers(dpy, window);