1 /* xscreensaver, Copyright (c) 1998-2004 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: 20000 \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, "true" },
97 {"+texture", ".lament.texture", XrmoptionNoArg, "false" },
100 static argtype vars[] = {
101 {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
104 ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL};
107 #include "xpm-ximage.h"
109 #include "gltrackball.h"
110 #include "../images/lament.xpm"
112 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
113 #define RANDSIGN() ((random() & 1) ? 1 : -1)
136 LAMENT_TASER_SLIDE_IN,
141 static GLfloat exterior_color[] = { 0.33, 0.22, 0.03, 1.00, /* ambient */
142 0.78, 0.57, 0.11, 1.00, /* specular */
143 0.99, 0.91, 0.81, 1.00, /* diffuse */
144 27.80 /* shininess */
146 static GLfloat interior_color[] = { 0.20, 0.20, 0.15, 1.00, /* ambient */
147 0.40, 0.40, 0.32, 1.00, /* specular */
148 0.99, 0.99, 0.81, 1.00, /* diffuse */
149 50.80 /* shininess */
154 GLXContext *glx_context;
156 double rotx, roty, rotz;
157 trackball_state *trackball;
160 GLuint box; /* display list IDs */
162 GLuint tetra_une, tetra_usw, tetra_dwn, tetra_dse, tetra_mid;
163 GLuint lid_0, lid_1, lid_2, lid_3, lid_4;
164 GLuint taser_base, taser_lifter, taser_slider;
166 XImage *texture; /* image bits */
167 GLuint texids[6]; /* texture map IDs */
168 lament_type type; /* which mode of the object is current */
170 int anim_pause; /* countdown before animating again */
171 GLfloat anim_r, anim_y, anim_z; /* relative position during anims */
173 } lament_configuration;
175 static lament_configuration *lcs = NULL;
185 parse_image_data(ModeInfo *mi)
187 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
188 lc->texture = xpm_to_ximage (mi->dpy,
195 /* Shorthand utilities for making faces, with proper normals.
199 set_colors (GLfloat *color)
201 glMaterialfv(GL_FRONT, GL_AMBIENT, color+0);
202 glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4);
203 glMaterialfv(GL_FRONT, GL_SPECULAR, color+8);
204 glMaterialfv(GL_FRONT, GL_SHININESS, color+12);
208 face3(GLint texture, GLfloat *color, Bool wire,
209 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
210 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
211 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3)
213 #ifdef HAVE_GLBINDTEXTURE
214 glBindTexture(GL_TEXTURE_2D, texture);
215 #endif /* HAVE_GLBINDTEXTURE */
218 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
219 glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
220 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
221 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
222 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
227 face4(GLint texture, GLfloat *color, Bool wire,
228 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
229 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
230 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
231 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4)
233 #ifdef HAVE_GLBINDTEXTURE
234 glBindTexture(GL_TEXTURE_2D, texture);
235 #endif /* HAVE_GLBINDTEXTURE */
237 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
238 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
239 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
240 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
241 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
242 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
247 face5(GLint texture, GLfloat *color, Bool wire,
248 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
249 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
250 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
251 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4,
252 GLfloat s5, GLfloat t5, GLfloat x5, GLfloat y5, GLfloat z5)
254 #ifdef HAVE_GLBINDTEXTURE
255 glBindTexture(GL_TEXTURE_2D, texture);
256 #endif /* HAVE_GLBINDTEXTURE */
258 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
259 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
260 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
261 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
262 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
263 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
264 glTexCoord2f(s5, t5); glVertex3f(x5, y5, z5);
270 /* Creating object models
274 box(ModeInfo *mi, Bool wire)
276 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
278 glNewList(lc->box, GL_COMPILE);
279 glShadeModel(GL_SMOOTH);
282 face4(lc->texids[FACE_N], exterior_color, wire,
283 0.0, 0.0, -0.5, 0.5, 0.5,
284 1.0, 0.0, 0.5, 0.5, 0.5,
285 1.0, 1.0, 0.5, 0.5, -0.5,
286 0.0, 1.0, -0.5, 0.5, -0.5);
289 face4(lc->texids[FACE_S], exterior_color, wire,
290 0.0, 0.0, -0.5, -0.5, -0.5,
291 1.0, 0.0, 0.5, -0.5, -0.5,
292 1.0, 1.0, 0.5, -0.5, 0.5,
293 0.0, 1.0, -0.5, -0.5, 0.5);
296 face4(lc->texids[FACE_E], exterior_color, wire,
297 0.0, 0.0, 0.5, -0.5, -0.5,
298 1.0, 0.0, 0.5, 0.5, -0.5,
299 1.0, 1.0, 0.5, 0.5, 0.5,
300 0.0, 1.0, 0.5, -0.5, 0.5);
303 face4(lc->texids[FACE_W], exterior_color, wire,
304 1.0, 1.0, -0.5, -0.5, 0.5,
305 0.0, 1.0, -0.5, 0.5, 0.5,
306 0.0, 0.0, -0.5, 0.5, -0.5,
307 1.0, 0.0, -0.5, -0.5, -0.5);
310 face4(lc->texids[FACE_U], exterior_color, wire,
311 1.0, 0.0, 0.5, -0.5, 0.5,
312 1.0, 1.0, 0.5, 0.5, 0.5,
313 0.0, 1.0, -0.5, 0.5, 0.5,
314 0.0, 0.0, -0.5, -0.5, 0.5);
317 face4(lc->texids[FACE_D], exterior_color, wire,
318 0.0, 1.0, -0.5, -0.5, -0.5,
319 0.0, 0.0, -0.5, 0.5, -0.5,
320 1.0, 0.0, 0.5, 0.5, -0.5,
321 1.0, 1.0, 0.5, -0.5, -0.5);
328 star(ModeInfo *mi, Bool top, Bool wire)
330 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
334 { 77, 74 }, { 60, 98 }, { 0, 71 }, { 0, 0 }, /* L1 */
335 { 60, 98 }, { 55, 127 }, { 0, 127 }, { 0, 71 }, /* L2 */
336 { 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */
337 { 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */
338 { 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */
339 { 100, 193 }, { 127, 198 }, { 127, 255 }, { 74, 255 }, /* B2 */
340 { 127, 198 }, { 151, 193 }, { 180, 255 }, { 127, 255 }, /* B3 */
341 { 151, 193 }, { 178, 177 }, { 255, 255 }, { 180, 255 }, /* B4 */
342 { 178, 177 }, { 193, 155 }, { 255, 181 }, { 255, 255 }, /* R4 */
343 { 193, 155 }, { 199, 127 }, { 255, 127 }, { 255, 181 }, /* R3 */
344 { 199, 127 }, { 194, 99 }, { 255, 74 }, { 255, 127 }, /* R2 */
345 { 194, 99 }, { 179, 76 }, { 255, 0 }, { 255, 74 }, /* R1 */
346 { 179, 76 }, { 155, 60 }, { 180, 0 }, { 255, 0 }, /* T4 */
347 { 155, 60 }, { 126, 55 }, { 126, 0 }, { 180, 0 }, /* T3 */
348 { 126, 55 }, { 100, 60 }, { 75, 0 }, { 126, 0 }, /* T2 */
349 { 100, 60 }, { 77, 74 }, { 0, 0 }, { 75, 0 }, /* T1 */
352 for (i = 0; i < countof(points); i++)
353 points[i][1] = 255-points[i][1];
356 glNewList(lc->star1, GL_COMPILE);
358 glNewList(lc->star2, GL_COMPILE);
361 glRotatef(-180.0, 1.0, 0.0, 0.0);
363 for (i = 0; i < countof(points)/4; i += 2)
370 GLfloat s[4], t[4], x[4], y[4], z[4];
371 for (j = 3, k = 0; j >= 0; j--, k++)
373 GLfloat xx = points[(i*4)+j][0] / 255.0L;
374 GLfloat yy = points[(i*4)+j][1] / 255.0L;
381 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
382 s[0], t[0], x[0], y[0], z[0],
383 s[1], t[1], x[1], y[1], z[1],
384 s[2], t[2], x[2], y[2], z[2],
385 s[3], t[3], x[3], y[3], z[3]);
389 for (j = 0, k = 0; j < 4; j++, k++)
391 GLfloat xx = points[(i*4)+j][0] / 255.0L;
392 GLfloat yy = points[(i*4)+j][1] / 255.0L;
399 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
400 s[0], t[0], x[0], y[0], z[0],
401 s[1], t[1], x[1], y[1], z[1],
402 s[2], t[2], x[2], y[2], z[2],
403 s[3], t[3], x[3], y[3], z[3]);
407 for (j = 3; j >= 0; j--)
409 int k = (j == 0 ? 3 : j-1);
410 Bool front_p = (j == 3);
411 GLfloat x1 = points[(i*4)+j][0] / 255.0L;
412 GLfloat y1 = points[(i*4)+j][1] / 255.0L;
413 GLfloat x2 = points[(i*4)+k][0] / 255.0L;
414 GLfloat y2 = points[(i*4)+k][1] / 255.0L;
416 GLfloat tx1=0.0, tx2=1.0, ty1=0.0, ty2=1.0;
420 facing = (facing + j + 5) % 4;
426 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
427 ty1 = 0.0; ty2 = 1.0;
430 ty1 = 1.0; ty2 = 0.0;
434 texture = top ? FACE_S : FACE_N;
436 ty1 = 0.0; ty2 = 1.0;
442 ty1 = 0.0; ty2 = 1.0;
444 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
445 ty1 = 1.0; ty2 = 0.0;
449 texture = top ? FACE_N : FACE_S;
451 ty1 = 1.0; ty2 = 0.0;
455 x1 -= 0.5; x2 -= 0.5;
456 y1 -= 0.5; y2 -= 0.5;
458 face4(front_p ? lc->texids[texture] : 0,
459 front_p ? exterior_color : interior_color,
461 tx1, ty2, x1, y1, 0.5,
462 tx1, ty1, x1, y1, -0.5,
463 tx2, ty1, x2, y2, -0.5,
464 tx2, ty2, x2, y2, 0.5);
469 /* Central core top cap.
471 #ifdef HAVE_GLBINDTEXTURE
472 glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]);
473 #endif /* HAVE_GLBINDTEXTURE */
474 set_colors(exterior_color);
477 do_normal(points[i+0][0], points[i+0][1], 0,
478 points[i+4][0], points[i+4][1], 0,
479 points[i+8][0], points[i+8][1], 0);
480 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
481 for (i = 1; i < countof(points); i += 4)
483 GLfloat x = points[i][0] / 255.0L;
484 GLfloat y = points[i][1] / 255.0L;
486 glVertex3f(x-0.5, y-0.5, 0.5);
491 /* Central core bottom cap.
493 #ifdef HAVE_GLBINDTEXTURE
494 glBindTexture(GL_TEXTURE_2D, 0);
495 #endif /* HAVE_GLBINDTEXTURE */
496 set_colors(interior_color);
498 i = countof(points) - 9;
499 do_normal(points[i+0][0], points[i+0][1], 0,
500 points[i+4][0], points[i+4][1], 0,
501 points[i+8][0], points[i+8][1], 0);
503 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
504 for (i = countof(points) - 3; i >= 0; i -= 4)
506 GLfloat x = points[i][0] / 255.0L;
507 GLfloat y = points[i][1] / 255.0L;
508 glVertex3f(x-0.5, y-0.5, 0);
513 /* Central core walls.
515 for (i = 1; i < countof(points); i += 4)
518 GLfloat x1 = points[i-1][0] / 255.0L;
519 GLfloat y1 = points[i-1][1] / 255.0L;
520 GLfloat x2 = points[i][0] / 255.0L;
521 GLfloat y2 = points[i][1] / 255.0L;
522 face4(0, interior_color, wire,
523 0.0, 0.0, x1-0.5, y1-0.5, 0.5,
524 0.0, 0.0, x1-0.5, y1-0.5, 0.0,
525 0.0, 0.0, x2-0.5, y2-0.5, 0.0,
526 0.0, 0.0, x2-0.5, y2-0.5, 0.5);
534 tetra(ModeInfo *mi, Bool wire)
536 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
538 glNewList(lc->tetra_une, GL_COMPILE);
540 glShadeModel(GL_SMOOTH);
543 face3(lc->texids[FACE_U], exterior_color, wire,
544 1.0, 0.0, 0.5, -0.5, 0.5,
545 1.0, 1.0, 0.5, 0.5, 0.5,
546 0.0, 1.0, -0.5, 0.5, 0.5);
549 face3(lc->texids[FACE_N], exterior_color, wire,
550 0.0, 0.0, -0.5, 0.5, 0.5,
551 1.0, 0.0, 0.5, 0.5, 0.5,
552 1.0, 1.0, 0.5, 0.5, -0.5);
555 face3(lc->texids[FACE_E], exterior_color, wire,
556 1.0, 0.0, 0.5, 0.5, -0.5,
557 1.0, 1.0, 0.5, 0.5, 0.5,
558 0.0, 1.0, 0.5, -0.5, 0.5);
560 face3(0, interior_color, wire,
561 0.0, 0.0, 0.5, 0.5, -0.5,
562 0.0, 0.0, 0.5, -0.5, 0.5,
563 0.0, 0.0, -0.5, 0.5, 0.5);
567 glNewList(lc->tetra_usw, GL_COMPILE);
570 face3(lc->texids[FACE_U], exterior_color, wire,
571 0.0, 1.0, -0.5, 0.5, 0.5,
572 0.0, 0.0, -0.5, -0.5, 0.5,
573 1.0, 0.0, 0.5, -0.5, 0.5);
576 face3(lc->texids[FACE_S], exterior_color, wire,
577 1.0, 1.0, 0.5, -0.5, 0.5,
578 0.0, 1.0, -0.5, -0.5, 0.5,
579 0.0, 0.0, -0.5, -0.5, -0.5);
582 face3(lc->texids[FACE_W], exterior_color, wire,
583 1.0, 0.0, -0.5, -0.5, -0.5,
584 1.0, 1.0, -0.5, -0.5, 0.5,
585 0.0, 1.0, -0.5, 0.5, 0.5);
587 face3(0, interior_color, wire,
588 0.0,0.0, -0.5, -0.5, -0.5,
589 0.0,0.0, -0.5, 0.5, 0.5,
590 0.0,0.0, 0.5, -0.5, 0.5);
594 glNewList(lc->tetra_dwn, GL_COMPILE);
597 face3(lc->texids[FACE_D], exterior_color, wire,
598 0.0, 1.0, -0.5, -0.5, -0.5,
599 0.0, 0.0, -0.5, 0.5, -0.5,
600 1.0, 0.0, 0.5, 0.5, -0.5);
603 face3(lc->texids[FACE_W], exterior_color, wire,
604 0.0, 1.0, -0.5, 0.5, 0.5,
605 0.0, 0.0, -0.5, 0.5, -0.5,
606 1.0, 0.0, -0.5, -0.5, -0.5);
609 face3(lc->texids[FACE_N], exterior_color, wire,
610 1.0, 1.0, 0.5, 0.5, -0.5,
611 0.0, 1.0, -0.5, 0.5, -0.5,
612 0.0, 0.0, -0.5, 0.5, 0.5);
614 face3(0, interior_color, wire,
615 0.0, 0.0, 0.5, 0.5, -0.5,
616 0.0, 0.0, -0.5, 0.5, 0.5,
617 0.0, 0.0, -0.5, -0.5, -0.5);
621 glNewList(lc->tetra_dse, GL_COMPILE);
624 face3(lc->texids[FACE_S], exterior_color, wire,
625 0.0, 0.0, -0.5, -0.5, -0.5,
626 1.0, 0.0, 0.5, -0.5, -0.5,
627 1.0, 1.0, 0.5, -0.5, 0.5);
630 face3(lc->texids[FACE_E], exterior_color, wire,
631 0.0, 1.0, 0.5, -0.5, 0.5,
632 0.0, 0.0, 0.5, -0.5, -0.5,
633 1.0, 0.0, 0.5, 0.5, -0.5);
636 face3(lc->texids[FACE_D], exterior_color, wire,
637 1.0, 0.0, 0.5, 0.5, -0.5,
638 1.0, 1.0, 0.5, -0.5, -0.5,
639 0.0, 1.0, -0.5, -0.5, -0.5);
641 face3(0, interior_color, wire,
642 0.0, 0.0, 0.5, -0.5, 0.5,
643 0.0, 0.0, 0.5, 0.5, -0.5,
644 0.0, 0.0, -0.5, -0.5, -0.5);
648 glNewList(lc->tetra_mid, GL_COMPILE);
650 face3(0, interior_color, wire,
651 0.0, 0.0, 0.5, -0.5, 0.5,
652 0.0, 0.0, 0.5, 0.5, -0.5,
653 0.0, 0.0, -0.5, 0.5, 0.5);
655 face3(0, interior_color, wire,
656 0.0, 0.0, -0.5, 0.5, 0.5,
657 0.0, 0.0, -0.5, -0.5, -0.5,
658 0.0, 0.0, 0.5, -0.5, 0.5);
660 face3(0, interior_color, wire,
661 0.0, 0.0, -0.5, 0.5, 0.5,
662 0.0, 0.0, 0.5, 0.5, -0.5,
663 0.0, 0.0, -0.5, -0.5, -0.5);
665 face3(0, interior_color, wire,
666 0.0, 0.0, 0.5, 0.5, -0.5,
667 0.0, 0.0, 0.5, -0.5, 0.5,
668 0.0, 0.0, -0.5, -0.5, -0.5);
670 face3(0, interior_color, wire,
671 0.0, 0.0, 0.5, -0.5, 0.5,
672 0.0, 0.0, 0.5, 0.5, -0.5,
673 0.0, 0.0, -0.5, -0.5, -0.5);
680 lid(ModeInfo *mi, Bool wire)
682 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
686 { 128, 20 },{ 21, 129 },{ 0, 129 },{ 0, 0 },{ 128, 0 }, /* L1 */
687 { 21, 129 },{ 127, 234 },{ 127, 255 },{ 0, 255 },{ 0, 129 }, /* L2 */
688 { 127, 234 },{ 233, 127 },{ 255, 127 },{ 255, 255 },{ 127, 255 }, /* R2 */
689 { 233, 127 },{ 128, 20 },{ 128, 0 },{ 255, 0 },{ 255, 127 }, /* R1 */
692 for (i = 0; i < countof(points); i++)
693 points[i][1] = 255-points[i][1];
695 glNewList(lc->lid_0, GL_COMPILE);
696 glShadeModel(GL_SMOOTH);
699 face4(lc->texids[FACE_N], exterior_color, wire,
700 0.0, 0.0, -0.5, 0.5, 0.5,
701 1.0, 0.0, 0.5, 0.5, 0.5,
702 1.0, 1.0, 0.5, 0.5, -0.5,
703 0.0, 1.0, -0.5, 0.5, -0.5);
706 face4(lc->texids[FACE_S], exterior_color, wire,
707 0.0, 0.0, -0.5, -0.5, -0.5,
708 1.0, 0.0, 0.5, -0.5, -0.5,
709 1.0, 1.0, 0.5, -0.5, 0.5,
710 0.0, 1.0, -0.5, -0.5, 0.5);
713 face4(lc->texids[FACE_E], exterior_color, wire,
714 0.0, 0.0, 0.5, -0.5, -0.5,
715 1.0, 0.0, 0.5, 0.5, -0.5,
716 1.0, 1.0, 0.5, 0.5, 0.5,
717 0.0, 1.0, 0.5, -0.5, 0.5);
720 face4(lc->texids[FACE_U], exterior_color, wire,
721 1.0, 0.0, 0.5, -0.5, 0.5,
722 1.0, 1.0, 0.5, 0.5, 0.5,
723 0.0, 1.0, -0.5, 0.5, 0.5,
724 0.0, 0.0, -0.5, -0.5, 0.5);
727 face4(lc->texids[FACE_D], exterior_color, wire,
728 0.0, 1.0, -0.5, -0.5, -0.5,
729 0.0, 0.0, -0.5, 0.5, -0.5,
730 1.0, 0.0, 0.5, 0.5, -0.5,
731 1.0, 1.0, 0.5, -0.5, -0.5);
734 for (i = 0; i < countof(points)/5; i++)
737 GLfloat s[5], t[5], x[5], y[5], z[5];
738 for (j = 0; j < 5; j++)
740 GLfloat xx = points[(i*5)+j][0] / 255.0L;
741 GLfloat yy = points[(i*5)+j][1] / 255.0L;
748 face5(lc->texids[FACE_W], exterior_color, wire,
749 s[0], t[0], x[0], y[0], z[0],
750 s[1], t[1], x[1], y[1], z[1],
751 s[2], t[2], x[2], y[2], z[2],
752 s[3], t[3], x[3], y[3], z[3],
753 s[4], t[4], x[4], y[4], z[4]);
758 /* W -- lid_1 through lid_4 */
759 for (i = 0; i < 4; i++)
761 GLfloat x1, y1, x2, y2, x3, y3;
763 glNewList(lc->lid_1 + i, GL_COMPILE);
764 glShadeModel(GL_SMOOTH);
766 x1 = points[(i*5)+1][0] / 255.0L;
767 y1 = points[(i*5)+1][1] / 255.0L;
768 x2 = points[(i*5)][0] / 255.0L;
769 y2 = points[(i*5)][1] / 255.0L;
774 face3(lc->texids[FACE_W], exterior_color, wire,
775 1.0-x1, y1, -0.5, x1-0.5, y1-0.5,
776 1.0-x2, y2, -0.5, x2-0.5, y2-0.5,
777 1.0-x3, y3, -0.5, x3-0.5, y3-0.5);
780 face3(0, interior_color, wire,
781 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
782 0.0, 0.0, -0.48, x1-0.5, y1-0.5,
783 0.0, 0.0, -0.48, x3-0.5, y3-0.5);
786 face4(0, interior_color, wire,
787 0.0, 0.0, -0.5, x1-0.5, y1-0.5,
788 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
789 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
790 0.0, 0.0, -0.48, x1-0.5, y1-0.5);
793 face4(0, interior_color, wire,
794 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
795 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
796 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
797 0.0, 0.0, -0.5, x2-0.5, y2-0.5);
804 taser(ModeInfo *mi, Bool wire)
806 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
809 int slider_face_points[][2] = {
810 { 86, 58 },{ 38, 106 },{ 70, 106 },{ 118, 58 },{ -1, -1 }, /* a */
811 { 136, 58 },{ 184, 106 },{ 216, 106 },{ 168, 58 },{ -1, -1 }, /* b */
812 { 38, 106 },{ 0, 144 },{ 0, 190 },{ 60, 190 },{ 108, 106 }, /* c */
813 { 144, 106 },{ 194, 190 },{ 254, 190 },{ 254, 144 },{ 216, 106 }, /* d */
814 { 98, 124 },{ 60, 190 },{ 92, 190 },{ 126, 158 },{ 126, 124 }, /* e */
815 { 126, 124 },{ 126, 158 },{ 160, 190 },{ 194, 190 },{ 154, 124 }, /* f */
816 { 22, 190 },{ 22, 254 },{ 60, 254 },{ 60, 190 },{ -1, -1 }, /* g */
817 { 194, 190 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ -1, -1 }, /* h */
818 { 60, 190 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ -1, -1 }, /* i */
819 { 160, 190 },{ 160, 210 },{ 194, 210 },{ 194, 190 },{ -1, -1 }, /* j */
820 { 110, 172 },{ 92, 190 },{ 110, 190 },{ -1, -1 },{ -1, -1 }, /* k */
821 { 140, 172 },{ 140, 190 },{ 160, 190 },{ -1, -1 },{ -1, -1 }, /* l */
822 { 110, 172 },{ 140, 172 },{ 126, 156 },{ -1, -1 },{ -1, -1 }, /* m */
825 int body_face_points[][2] = {
826 { 0, 0 },{ 0, 58 },{ 254, 58 },{ 254, 0 },{ -1, -1 }, /* A */
827 { 0, 58 },{ 0, 144 },{ 86, 58 },{ -1, -1 },{ -1, -1 }, /* B */
828 { 168, 58 },{ 254, 144 },{ 254, 58 },{ -1, -1 },{ -1, -1 }, /* C */
829 { 118, 58 },{ 70, 106 },{ 184, 106 },{ 136, 58 },{ -1, -1 }, /* F */
830 { 108, 106 },{ 98, 124 },{ 154, 124 },{ 144, 106 },{ -1, -1 }, /* G */
833 int lifter_face_points[][2] = {
834 { 0, 190 },{ 0, 254 },{ 22, 254 },{ 22, 190 },{ -1, -1 }, /* D */
835 { 230, 190 },{ 230, 254 },{ 254, 254 },{ 254, 190 },{ -1, -1 }, /* E */
836 { 60, 210 },{ 60, 254 },{ 194, 254 },{ 194, 210 },{ -1, -1 }, /* H */
837 { 92, 190 },{ 92, 210 },{ 160, 210 },{ 160, 190 },{ -1, -1 }, /* I */
838 { 110, 172 },{ 110, 190 },{ 140, 190 },{ 140, 172 },{ -1, -1 }, /* J */
841 int body_perimiter_points[][2] = {
842 { 0, 144 },{ 86, 59 },{ 119, 58 },{ 71, 107 },
843 { 108, 107 },{ 98, 124 },{ 155, 124 },{ 144, 107 },
844 { 185, 106 },{ 136, 59 },{ 169, 59 },{ 255, 145 },
848 int slider_perimiter_points[][2] = {
849 { 86, 58 },{ 0, 144 },{ 0, 190 },{ 22, 190 },{ 22, 254 },
850 { 60, 254 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ 110, 190 },
851 { 110, 172 },{ 140, 172 },{ 140, 190 },{ 160, 190 },{ 160, 210 },
852 { 194, 210 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ 254, 190 },
853 { 254, 144 },{ 168, 58 },{ 136, 58 },{ 184, 106 },{ 144, 106 },
854 { 154, 124 },{ 98, 124 },{ 108, 106 },{ 70, 106 },{ 118, 58 },
857 int lifter_perimiter_points_1[][2] = {
858 { 0, 189 },{ 0, 254 },{ 22, 255 },{ 23, 190 },
861 int lifter_perimiter_points_2[][2] = {
862 { 230, 254 },{ 255, 255 },{ 254, 190 },{ 230, 190 },
865 int lifter_perimiter_points_3[][2] = {
866 { 60, 254 },{ 194, 254 },{ 194, 211 },{ 160, 210 },
867 { 160, 190 },{ 140, 191 },{ 141, 172 },{ 111, 172 },
868 { 110, 190 },{ 93, 190 },{ 92, 210 },{ 60, 211 },
871 for (i = 0; i < countof(slider_face_points); i++)
872 slider_face_points[i][1] = 255-slider_face_points[i][1];
873 for (i = 0; i < countof(body_face_points); i++)
874 body_face_points[i][1] = 255-body_face_points[i][1];
875 for (i = 0; i < countof(lifter_face_points); i++)
876 lifter_face_points[i][1] = 255-lifter_face_points[i][1];
877 for (i = 0; i < countof(body_perimiter_points); i++)
878 body_perimiter_points[i][1] = 255-body_perimiter_points[i][1];
879 for (i = 0; i < countof(slider_perimiter_points); i++)
880 slider_perimiter_points[i][1] = 255-slider_perimiter_points[i][1];
881 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
882 lifter_perimiter_points_1[i][1] = 255-lifter_perimiter_points_1[i][1];
883 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
884 lifter_perimiter_points_2[i][1] = 255-lifter_perimiter_points_2[i][1];
885 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
886 lifter_perimiter_points_3[i][1] = 255-lifter_perimiter_points_3[i][1];
888 /* -------------------------------------------------------------------- */
890 glNewList(lc->taser_base, GL_COMPILE);
891 glShadeModel(GL_SMOOTH);
894 face4(lc->texids[FACE_N], exterior_color, wire,
895 0.0, 0.0, -0.5, 0.5, 0.5,
896 0.75, 0.0, 0.25, 0.5, 0.5,
897 0.75, 0.75, 0.25, 0.5, -0.25,
898 0.0, 0.75, -0.5, 0.5, -0.25);
901 face4(lc->texids[FACE_S], exterior_color, wire,
902 0.0, 0.25, -0.5, -0.5, -0.25,
903 0.75, 0.25, 0.25, -0.5, -0.25,
904 0.75, 1.0, 0.25, -0.5, 0.5,
905 0.0, 1.0, -0.5, -0.5, 0.5);
908 face4(0, interior_color, wire,
909 0.0, 0.0, 0.25, -0.5, -0.25,
910 1.0, 0.0, 0.25, 0.5, -0.25,
911 1.0, 1.0, 0.25, 0.5, 0.5,
912 0.0, 1.0, 0.25, -0.5, 0.5);
915 face4(lc->texids[FACE_W], exterior_color, wire,
916 1.0, 1.0, -0.5, -0.5, 0.5,
917 0.0, 1.0, -0.5, 0.5, 0.5,
918 0.0, 0.25, -0.5, 0.5, -0.25,
919 1.0, 0.25, -0.5, -0.5, -0.25);
922 face4(lc->texids[FACE_U], exterior_color, wire,
923 0.75, 0.0, 0.25, -0.5, 0.5,
924 0.75, 1.0, 0.25, 0.5, 0.5,
925 0.0, 1.0, -0.5, 0.5, 0.5,
926 0.0, 0.0, -0.5, -0.5, 0.5);
929 face4(0, interior_color, wire,
930 0.0, 1.0, -0.5, -0.5, -0.25,
931 0.0, 0.0, -0.5, 0.5, -0.25,
932 1.0, 0.0, 0.25, 0.5, -0.25,
933 1.0, 1.0, 0.25, -0.5, -0.25);
936 for (i = 0; i < countof(body_face_points)/5; i++)
939 #ifdef HAVE_GLBINDTEXTURE
940 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
941 #endif /* HAVE_GLBINDTEXTURE */
942 set_colors(exterior_color);
944 do_normal(0, body_face_points[(i*5)+0][0], body_face_points[(i*5)+0][1],
945 0, body_face_points[(i*5)+1][0], body_face_points[(i*5)+1][1],
946 0, body_face_points[(i*5)+2][0], body_face_points[(i*5)+2][1]
948 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
949 for (j = 0; j < 5; j++)
951 int ix = body_face_points[(i*5)+j][0];
952 int iy = body_face_points[(i*5)+j][1];
954 if (ix == -1) /* these are padding: ignore them */
959 glVertex3f(0.5, x-0.5, y-0.5);
965 for (i = 0; i < countof(body_perimiter_points); i++)
967 int j = (i+1 >= countof(body_perimiter_points) ? 0 : i+1);
968 GLfloat x1 = body_perimiter_points[i][0] / 255.0;
969 GLfloat y1 = body_perimiter_points[i][1] / 255.0;
970 GLfloat x2 = body_perimiter_points[j][0] / 255.0;
971 GLfloat y2 = body_perimiter_points[j][1] / 255.0;
973 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
977 texture = lc->texids[FACE_N];
979 s2 = 1.0; t2 = 0.568;
980 s3 = 0.75, t3 = 0.568;
985 texture = lc->texids[FACE_U];
993 texture = lc->texids[FACE_S];
994 s1 = 1.0; t1 = 0.437;
997 s4 = 0.75; t4 = 0.437;
1000 face4((texture == -1 ? 0 : texture),
1001 (texture == -1 ? interior_color : exterior_color),
1003 s1, t1, 0.5, x2-0.5, y2-0.5,
1004 s2, t2, 0.5, x1-0.5, y1-0.5,
1005 s3, t3, 0.25, x1-0.5, y1-0.5,
1006 s4, t4, 0.25, x2-0.5, y2-0.5);
1011 /* -------------------------------------------------------------------- */
1013 glNewList(lc->taser_lifter, GL_COMPILE);
1014 glShadeModel(GL_SMOOTH);
1017 face4(lc->texids[FACE_N], exterior_color, wire,
1018 0.0, 0.75, -0.5, 0.5, -0.25,
1019 0.75, 0.75, 0.25, 0.5, -0.25,
1020 0.75, 1.0, 0.25, 0.5, -0.5,
1021 0.0, 1.0, -0.5, 0.5, -0.5);
1024 face4(lc->texids[FACE_S], exterior_color, wire,
1025 0.0, 0.0, -0.5, -0.5, -0.5,
1026 0.75, 0.0, 0.25, -0.5, -0.5,
1027 0.75, 0.25, 0.25, -0.5, -0.25,
1028 0.0, 0.25, -0.5, -0.5, -0.25);
1031 face4(0, interior_color, wire,
1032 0.0, 1.0, 0.25, -0.5, -0.5,
1033 1.0, 1.0, 0.25, 0.5, -0.5,
1034 1.0, 0.0, 0.25, 0.5, -0.25,
1035 0.0, 0.0, 0.25, -0.5, -0.25);
1038 face4(lc->texids[FACE_W], exterior_color, wire,
1039 1.0, 0.25, -0.5, -0.5, -0.25,
1040 0.0, 0.25, -0.5, 0.5, -0.25,
1041 0.0, 0.0, -0.5, 0.5, -0.5,
1042 1.0, 0.0, -0.5, -0.5, -0.5);
1045 face4(0, interior_color, wire,
1046 1.0, 0.0, 0.25, -0.5, -0.25,
1047 1.0, 1.0, 0.25, 0.5, -0.25,
1048 0.0, 1.0, -0.5, 0.5, -0.25,
1049 0.0, 0.0, -0.5, -0.5, -0.25);
1052 face4(lc->texids[FACE_D], exterior_color, wire,
1053 0.0, 1.0, -0.5, -0.5, -0.5,
1054 0.0, 0.0, -0.5, 0.5, -0.5,
1055 0.75, 0.0, 0.25, 0.5, -0.5,
1056 0.75, 1.0, 0.25, -0.5, -0.5);
1060 for (i = 0; i < countof(lifter_face_points)/5; i++)
1064 #ifdef HAVE_GLBINDTEXTURE
1065 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1066 #endif /* HAVE_GLBINDTEXTURE */
1067 set_colors(exterior_color);
1070 0, lifter_face_points[(i*5)+0][0], lifter_face_points[(i*5)+0][1],
1071 0, lifter_face_points[(i*5)+1][0], lifter_face_points[(i*5)+1][1],
1072 0, lifter_face_points[(i*5)+2][0], lifter_face_points[(i*5)+2][1]);
1074 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1075 for (j = 0; j < 5; j++)
1077 int ix = lifter_face_points[(i*5)+j][0];
1078 int iy = lifter_face_points[(i*5)+j][1];
1080 if (ix == -1) /* these are padding: ignore them */
1085 glVertex3f(0.5, x-0.5, y-0.5);
1091 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
1093 int j = (i+1 >= countof(lifter_perimiter_points_1) ? 0 : i+1);
1094 GLfloat x1 = lifter_perimiter_points_1[i][0] / 255.0;
1095 GLfloat y1 = lifter_perimiter_points_1[i][1] / 255.0;
1096 GLfloat x2 = lifter_perimiter_points_1[j][0] / 255.0;
1097 GLfloat y2 = lifter_perimiter_points_1[j][1] / 255.0;
1099 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1103 texture = lc->texids[FACE_S];
1105 s2 = 1.0; t2 = 0.26;
1106 s3 = 0.75, t3 = 0.26;
1107 s4 = 0.75; t4 = 0.0;
1111 texture = lc->texids[FACE_D];
1112 s1 = 1.0; t1 = 0.914;
1114 s3 = 0.75; t3 = 1.0;
1115 s4 = 0.75; t4 = 0.914;
1118 face4((texture == -1 ? 0 : texture),
1119 (texture == -1 ? interior_color : exterior_color),
1121 s1, t1, 0.5, x2-0.5, y2-0.5,
1122 s2, t2, 0.5, x1-0.5, y1-0.5,
1123 s3, t3, 0.25, x1-0.5, y1-0.5,
1124 s4, t4, 0.25, x2-0.5, y2-0.5);
1127 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
1129 int j = (i+1 >= countof(lifter_perimiter_points_2) ? 0 : i+1);
1130 GLfloat x1 = lifter_perimiter_points_2[i][0] / 255.0;
1131 GLfloat y1 = lifter_perimiter_points_2[i][1] / 255.0;
1132 GLfloat x2 = lifter_perimiter_points_2[j][0] / 255.0;
1133 GLfloat y2 = lifter_perimiter_points_2[j][1] / 255.0;
1135 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1139 texture = lc->texids[FACE_D];
1141 s2 = 1.0; t2 = 0.095;
1142 s3 = 0.75; t3 = 0.095;
1143 s4 = 0.75; t4 = 0.0;
1147 texture = lc->texids[FACE_N];
1148 s1 = 1.0; t1 = 0.745;
1150 s3 = 0.75; t3 = 1.0;
1151 s4 = 0.75; t4 = 0.745;
1154 face4((texture == -1 ? 0 : texture),
1155 (texture == -1 ? interior_color : exterior_color),
1157 s1, t1, 0.5, x2-0.5, y2-0.5,
1158 s2, t2, 0.5, x1-0.5, y1-0.5,
1159 s3, t3, 0.25, x1-0.5, y1-0.5,
1160 s4, t4, 0.25, x2-0.5, y2-0.5);
1163 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
1165 int j = (i+1 >= countof(lifter_perimiter_points_3) ? 0 : i+1);
1166 GLfloat x1 = lifter_perimiter_points_3[i][0] / 255.0;
1167 GLfloat y1 = lifter_perimiter_points_3[i][1] / 255.0;
1168 GLfloat x2 = lifter_perimiter_points_3[j][0] / 255.0;
1169 GLfloat y2 = lifter_perimiter_points_3[j][1] / 255.0;
1171 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1175 texture = lc->texids[FACE_D];
1176 s1 = 1.0; t1 = 0.235;
1177 s2 = 1.0; t2 = 0.765;
1178 s3 = 0.75; t3 = 0.765;
1179 s4 = 0.75; t4 = 0.235;
1182 face4((texture == -1 ? 0 : texture),
1183 (texture == -1 ? interior_color : exterior_color),
1185 s1, t1, 0.5, x2-0.5, y2-0.5,
1186 s2, t2, 0.5, x1-0.5, y1-0.5,
1187 s3, t3, 0.25, x1-0.5, y1-0.5,
1188 s4, t4, 0.25, x2-0.5, y2-0.5);
1193 /* -------------------------------------------------------------------- */
1195 glNewList(lc->taser_slider, GL_COMPILE);
1196 glShadeModel(GL_SMOOTH);
1199 for (i = 0; i < countof(slider_face_points)/5; i++)
1202 #ifdef HAVE_GLBINDTEXTURE
1203 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1204 #endif /* HAVE_GLBINDTEXTURE */
1205 set_colors(exterior_color);
1208 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1],
1209 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1210 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1]);
1211 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1212 for (j = 0; j < 5; j++)
1214 int ix = slider_face_points[(i*5)+j][0];
1215 int iy = slider_face_points[(i*5)+j][1];
1217 if (ix == -1) /* these are padding: ignore them */
1222 glVertex3f(0.5, x-0.5, y-0.5);
1228 for (i = countof(slider_face_points)/5 - 1; i >= 0; i--)
1231 #ifdef HAVE_GLBINDTEXTURE
1232 glBindTexture(GL_TEXTURE_2D, 0);
1233 #endif /* HAVE_GLBINDTEXTURE */
1234 set_colors(interior_color);
1237 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1],
1238 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1239 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1]);
1240 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1241 for (j = 4; j >= 0; j--)
1243 int ix = slider_face_points[(i*5)+j][0];
1244 int iy = slider_face_points[(i*5)+j][1];
1246 if (ix == -1) /* these are padding: ignore them */
1251 glVertex3f(0.25, x-0.5, y-0.5);
1257 for (i = 0; i < countof(slider_perimiter_points); i++)
1259 int j = (i+1 >= countof(slider_perimiter_points) ? 0 : i+1);
1260 GLfloat x1 = slider_perimiter_points[i][0] / 255.0;
1261 GLfloat y1 = slider_perimiter_points[i][1] / 255.0;
1262 GLfloat x2 = slider_perimiter_points[j][0] / 255.0;
1263 GLfloat y2 = slider_perimiter_points[j][1] / 255.0;
1265 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1269 texture = lc->texids[FACE_S];
1270 s1 = 1.0; t1 = 0.255;
1271 s2 = 1.0; t2 = 0.435;
1272 s3 = 0.75; t3 = 0.435;
1273 s4 = 0.75; t4 = 0.255;
1277 texture = lc->texids[FACE_D];
1278 s1 = 1.0; t1 = 0.758;
1279 s2 = 1.0; t2 = 0.915;
1280 s3 = 0.75; t3 = 0.915;
1281 s4 = 0.75; t4 = 0.758;
1285 texture = lc->texids[FACE_D];
1286 s1 = 1.0; t1 = 0.095;
1287 s2 = 1.0; t2 = 0.24;
1288 s3 = 0.75; t3 = 0.24;
1289 s4 = 0.75; t4 = 0.095;
1293 texture = lc->texids[FACE_N];
1294 s1 = 1.0; t1 = 0.568;
1295 s2 = 1.0; t2 = 0.742;
1296 s3 = 0.75; t3 = 0.742;
1297 s4 = 0.75; t4 = 0.568;
1300 face4((texture == -1 ? 0 : texture),
1301 (texture == -1 ? interior_color : exterior_color),
1303 s1, t1, 0.5, x2-0.5, y2-0.5,
1304 s2, t2, 0.5, x1-0.5, y1-0.5,
1305 s3, t3, 0.25, x1-0.5, y1-0.5,
1306 s4, t4, 0.25, x2-0.5, y2-0.5);
1314 /* Rendering and animating object models
1318 lament_handle_event (ModeInfo *mi, XEvent *event)
1320 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1322 if (event->xany.type == ButtonPress &&
1323 event->xbutton.button == Button1)
1325 lc->button_down_p = True;
1326 gltrackball_start (lc->trackball,
1327 event->xbutton.x, event->xbutton.y,
1328 MI_WIDTH (mi), MI_HEIGHT (mi));
1331 else if (event->xany.type == ButtonRelease &&
1332 event->xbutton.button == Button1)
1334 lc->button_down_p = False;
1337 else if (event->xany.type == ButtonPress &&
1338 (event->xbutton.button == Button4 ||
1339 event->xbutton.button == Button5))
1341 gltrackball_mousewheel (lc->trackball, event->xbutton.button, 5,
1342 !!event->xbutton.state);
1345 else if (event->xany.type == MotionNotify &&
1348 gltrackball_track (lc->trackball,
1349 event->xmotion.x, event->xmotion.y,
1350 MI_WIDTH (mi), MI_HEIGHT (mi));
1361 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1362 Bool wire = MI_IS_WIREFRAME(mi);
1365 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1367 glClear(GL_COLOR_BUFFER_BIT);
1371 gltrackball_rotate (lc->trackball);
1373 /* Make into the screen be +Y right be +X, and up be +Z. */
1374 glRotatef(-90.0, 1.0, 0.0, 0.0);
1377 glScalef(4.0, 4.0, 4.0);
1382 /* Shift to the upper left, and draw the vanilla box. */
1383 glTranslatef(-0.6, 0.0, 0.6);
1385 /* Apply rotation to the object. */
1386 glRotatef(x * 360, 1.0, 0.0, 0.0);
1387 glRotatef(y * 360, 0.0, 1.0, 0.0);
1388 glRotatef(z * 360, 0.0, 0.0, 1.0);
1391 glCallList(lc->box);
1395 /* Shift to the lower right, and draw the animated object. */
1396 glTranslatef(0.6, 0.0, -0.6);
1402 /* Apply rotation to the object. */
1403 if (lc->type != LAMENT_LID_ZOOM)
1404 get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
1405 !lc->button_down_p);
1406 glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
1407 glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
1408 glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
1413 glCallList(lc->box);
1416 case LAMENT_STAR_OUT:
1417 case LAMENT_STAR_ROT:
1418 case LAMENT_STAR_ROT_IN:
1419 case LAMENT_STAR_ROT_OUT:
1420 case LAMENT_STAR_UNROT:
1421 case LAMENT_STAR_IN:
1422 glTranslatef(0.0, 0.0, lc->anim_z/2);
1423 glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0);
1424 glCallList(lc->star1);
1426 glTranslatef(0.0, 0.0, -lc->anim_z);
1427 glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
1428 glCallList(lc->star2);
1431 case LAMENT_TETRA_UNE:
1432 case LAMENT_TETRA_USW:
1433 case LAMENT_TETRA_DWN:
1434 case LAMENT_TETRA_DSE:
1439 case LAMENT_TETRA_UNE: magic = lc->tetra_une;
1440 x = 1.0; y = 1.0; z = 1.0; break;
1441 case LAMENT_TETRA_USW: magic = lc->tetra_usw;
1442 x = 1.0; y = 1.0; z = -1.0; break;
1443 case LAMENT_TETRA_DWN: magic = lc->tetra_dwn;
1444 x = 1.0; y = -1.0; z = 1.0; break;
1445 case LAMENT_TETRA_DSE: magic = lc->tetra_dse;
1446 x = -1.0; y = 1.0; z = 1.0; break;
1447 default: abort(); break;
1449 glCallList(lc->tetra_mid);
1450 if (magic != lc->tetra_une) glCallList(lc->tetra_une);
1451 if (magic != lc->tetra_usw) glCallList(lc->tetra_usw);
1452 if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn);
1453 if (magic != lc->tetra_dse) glCallList(lc->tetra_dse);
1454 glRotatef(lc->anim_r, x, y, z);
1459 case LAMENT_LID_OPEN:
1460 case LAMENT_LID_CLOSE:
1461 case LAMENT_LID_ZOOM:
1465 glTranslatef(lc->anim_z, 0.0, 0.0);
1467 glCallList(lc->lid_0);
1470 glTranslatef(-0.5, -d, 0.0);
1471 glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
1472 glTranslatef( 0.5, d, 0.0);
1473 glCallList(lc->lid_1);
1476 glTranslatef(-0.5, -d, 0.0);
1477 glRotatef( lc->anim_r, 0.0, -1.0, 1.0);
1478 glTranslatef( 0.5, d, 0.0);
1479 glCallList(lc->lid_2);
1482 glTranslatef(-0.5, d, 0.0);
1483 glRotatef( lc->anim_r, 0.0, -1.0, -1.0);
1484 glTranslatef( 0.5, -d, 0.0);
1485 glCallList(lc->lid_3);
1488 glTranslatef(-0.5, d, 0.0);
1489 glRotatef(-lc->anim_r, 0.0, -1.0, 1.0);
1490 glTranslatef( 0.5, -d, 0.0);
1491 glCallList(lc->lid_4);
1496 case LAMENT_TASER_OUT:
1497 case LAMENT_TASER_SLIDE:
1498 case LAMENT_TASER_SLIDE_IN:
1499 case LAMENT_TASER_IN:
1501 glTranslatef(-lc->anim_z/2, 0.0, 0.0);
1502 glCallList(lc->taser_base);
1504 glTranslatef(lc->anim_z, 0.0, 0.0);
1505 glCallList(lc->taser_lifter);
1507 glTranslatef(0.0, 0.0, lc->anim_y);
1508 glCallList(lc->taser_slider);
1523 animate(ModeInfo *mi)
1525 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1527 /* int pause2 = 60;*/
1534 /* Rather than just picking states randomly, pick an ordering randomly,
1535 do it, and then re-randomize. That way one can be assured of seeing
1536 all states in a short time period, though not always in the same
1537 order (it's frustrating to see it pick the same state 5x in a row.)
1539 static lament_type states[] = {
1540 LAMENT_STAR_OUT, LAMENT_STAR_OUT,
1541 LAMENT_TETRA_UNE, LAMENT_TETRA_USW,
1542 LAMENT_TETRA_DWN, LAMENT_TETRA_DSE,
1543 LAMENT_LID_OPEN, LAMENT_LID_OPEN, LAMENT_LID_OPEN,
1544 LAMENT_TASER_OUT, LAMENT_TASER_OUT,
1545 LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
1546 LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
1548 static int state = countof(states);
1550 if (state < countof(states))
1552 lc->type = states[state++];
1558 for (i = 0; i < countof(states); i++)
1560 int a = random() % countof(states);
1561 lament_type swap = states[a];
1562 states[a] = states[i];
1567 if (lc->type == LAMENT_BOX)
1568 lc->anim_pause = pause3;
1576 /* -------------------------------------------------------------- */
1578 case LAMENT_STAR_OUT:
1580 if (lc->anim_z >= 1.0)
1583 lc->type = LAMENT_STAR_ROT;
1584 lc->anim_pause = pause;
1588 case LAMENT_STAR_ROT:
1590 if (lc->anim_r >= 45.0)
1593 lc->type = LAMENT_STAR_ROT_IN;
1594 lc->anim_pause = pause;
1598 case LAMENT_STAR_ROT_IN:
1600 if (lc->anim_z <= 0.0)
1603 lc->type = LAMENT_STAR_ROT_OUT;
1604 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1608 case LAMENT_STAR_ROT_OUT:
1610 if (lc->anim_z >= 1.0)
1613 lc->type = LAMENT_STAR_UNROT;
1614 lc->anim_pause = pause;
1618 case LAMENT_STAR_UNROT:
1620 if (lc->anim_r <= 0.0)
1623 lc->type = LAMENT_STAR_IN;
1624 lc->anim_pause = pause;
1628 case LAMENT_STAR_IN:
1630 if (lc->anim_z <= 0.0)
1633 lc->type = LAMENT_BOX;
1634 lc->anim_pause = pause3;
1638 /* -------------------------------------------------------------- */
1640 case LAMENT_TETRA_UNE:
1641 case LAMENT_TETRA_USW:
1642 case LAMENT_TETRA_DWN:
1643 case LAMENT_TETRA_DSE:
1646 if (lc->anim_r >= 360.0)
1649 lc->type = LAMENT_BOX;
1650 lc->anim_pause = pause3;
1652 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1655 lc->anim_pause = pause;
1657 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1660 lc->anim_pause = pause;
1664 /* -------------------------------------------------------------- */
1666 case LAMENT_LID_OPEN:
1669 if (lc->anim_r >= 112.0)
1671 GLfloat hysteresis = 0.05;
1675 lc->anim_pause = pause3;
1677 if (lc->rotx >= -hysteresis &&
1678 lc->rotx <= hysteresis &&
1679 ((lc->rotz >= (0.25 - hysteresis) &&
1680 lc->rotz <= (0.25 + hysteresis)) ||
1681 (lc->rotz >= (-0.25 - hysteresis) &&
1682 lc->rotz <= (-0.25 + hysteresis))))
1684 lc->type = LAMENT_LID_ZOOM;
1686 lc->rotz = (lc->rotz < 0 ? -0.25 : 0.25);
1690 lc->type = LAMENT_LID_CLOSE;
1695 case LAMENT_LID_CLOSE:
1697 if (lc->anim_r <= 0.0)
1700 lc->type = LAMENT_BOX;
1701 lc->anim_pause = pause3;
1705 case LAMENT_LID_ZOOM:
1707 if (lc->anim_z < -50.0)
1711 lc->type = LAMENT_BOX;
1715 /* -------------------------------------------------------------- */
1717 case LAMENT_TASER_OUT:
1718 lc->anim_z += 0.0025;
1719 if (lc->anim_z >= 0.25)
1722 lc->type = LAMENT_TASER_SLIDE;
1723 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1727 case LAMENT_TASER_SLIDE:
1728 lc->anim_y += 0.0025;
1729 if (lc->anim_y >= 0.23)
1732 lc->type = LAMENT_TASER_SLIDE_IN;
1733 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1737 case LAMENT_TASER_SLIDE_IN:
1738 lc->anim_y -= 0.0025;
1739 if (lc->anim_y <= 0.0)
1742 lc->type = LAMENT_TASER_IN;
1743 lc->anim_pause = pause;
1747 case LAMENT_TASER_IN:
1748 lc->anim_z -= 0.0025;
1749 if (lc->anim_z <= 0.0)
1752 lc->type = LAMENT_BOX;
1753 lc->anim_pause = pause3;
1765 /* Window management, etc
1769 reshape_lament(ModeInfo *mi, int width, int height)
1771 int target_size = 180;
1772 int win_size = (width > height ? height : width);
1773 GLfloat h = (GLfloat) height / (GLfloat) width;
1775 glViewport(0, 0, (GLint) width, (GLint) height);
1777 /* glViewport(-600, -600, 1800, 1800); */
1779 glMatrixMode(GL_PROJECTION);
1781 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1782 glMatrixMode(GL_MODELVIEW);
1784 glTranslatef(0.0, 0.0, -40.0);
1786 /* This scale makes the box take up most of the window */
1787 glScalef(2.0, 2.0, 2.0);
1789 /* But if the window is more than a little larger than our target size,
1790 scale the object back down, so that the bits drawn on the screen end
1791 up rougly target_size across (actually it ends up a little larger.)
1792 Note that the image-map bits we have are 128x128. Therefore, if the
1793 image is magnified a lot, it looks pretty blocky. So it's better to
1794 have a 128x128 animation on a 1280x1024 screen that looks good, than
1795 a 1024x1024 animation that looks really pixelated.
1797 if (win_size > target_size * 1.5)
1799 GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
1801 glScalef(ratio, ratio, ratio);
1804 /* The depth buffer will be cleared, if needed, before the
1805 * next frame. Right now we just want to black the screen.
1807 glClear(GL_COLOR_BUFFER_BIT);
1812 gl_init(ModeInfo *mi)
1814 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1815 Bool wire = MI_IS_WIREFRAME(mi);
1822 static GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1823 static GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1825 static GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1826 /* static GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1827 static GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1828 static GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1830 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1831 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1833 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1834 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1835 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1836 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1837 set_colors(exterior_color);
1839 glEnable(GL_LIGHTING);
1840 glEnable(GL_LIGHT0);
1841 /* glEnable(GL_LIGHT1); */
1843 glEnable(GL_DEPTH_TEST);
1844 glEnable(GL_TEXTURE_2D);
1845 glEnable(GL_NORMALIZE);
1846 glEnable(GL_CULL_FACE);
1851 #ifdef HAVE_GLBINDTEXTURE
1853 for (i = 0; i < 6; i++)
1854 glGenTextures(1, &lc->texids[i]);
1856 parse_image_data(mi);
1858 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1859 glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width);
1861 for (i = 0; i < 6; i++)
1863 int height = lc->texture->width; /* assume square */
1864 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1865 set_colors(exterior_color);
1868 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1869 lc->texture->width, height, 0,
1871 /* GL_UNSIGNED_BYTE, */
1872 GL_UNSIGNED_INT_8_8_8_8_REV,
1873 (lc->texture->data +
1874 (lc->texture->bytes_per_line * height * i)));
1875 check_gl_error("texture");
1877 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1878 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1879 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1880 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1881 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1882 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1885 #else /* !HAVE_GLBINDTEXTURE */
1887 "%s: this version of GL doesn't support multiple texture maps.\n"
1888 "\tGet OpenGL 1.1.\n",
1891 #endif /* !HAVE_GLBINDTEXTURE */
1894 lc->box = glGenLists(16);
1895 lc->star1 = lc->box+1;
1896 lc->star2 = lc->box+2;
1897 lc->tetra_une = lc->box+3;
1898 lc->tetra_usw = lc->box+4;
1899 lc->tetra_dwn = lc->box+5;
1900 lc->tetra_dse = lc->box+6;
1901 lc->tetra_mid = lc->box+7;
1902 lc->lid_0 = lc->box+8;
1903 lc->lid_1 = lc->box+9;
1904 lc->lid_2 = lc->box+10;
1905 lc->lid_3 = lc->box+11;
1906 lc->lid_4 = lc->box+12;
1907 lc->taser_base = lc->box+13;
1908 lc->taser_lifter = lc->box+14;
1909 lc->taser_slider = lc->box+15;
1912 star(mi, True, wire);
1913 star(mi, False, wire);
1920 # ifdef HAVE_MESA_GL
1922 # include <signal.h>
1925 lament_signal_kludge (int sig)
1927 signal (sig, SIG_DFL);
1930 "%s: dying with signal %d (%s).\n"
1932 "\tThis is almost certainly a bug in the Mesa GL library,\n"
1933 "\tespecially if the stack trace in the core file mentions\n"
1934 "\t`lambda_textured_triangle' or `render_quad'.\n"
1936 "\tFirst make sure that you have the latest version of Mesa.\n"
1937 "\tIf that doesn't fix it, then I encourage you to report this\n"
1938 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
1942 (sig == SIGILL ? "SIGILL" :
1943 sig == SIGFPE ? "SIGFPE" :
1944 sig == SIGBUS ? "SIGBUS" :
1945 sig == SIGSEGV ? "SIGSEGV" : "???"));
1947 kill (getpid (), sig);
1951 handle_signals (void)
1953 signal (SIGILL, lament_signal_kludge);
1954 signal (SIGFPE, lament_signal_kludge);
1955 signal (SIGBUS, lament_signal_kludge);
1956 signal (SIGSEGV, lament_signal_kludge);
1958 # endif /* HAVE_MESA_GL */
1962 init_lament(ModeInfo *mi)
1964 lament_configuration *lc;
1967 lcs = (lament_configuration *)
1968 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
1971 fprintf(stderr, "%s: out of memory\n", progname);
1976 lc = &lcs[MI_SCREEN(mi)];
1979 double rot_speed = 0.5;
1980 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
1981 lc->trackball = gltrackball_init ();
1984 lc->type = LAMENT_BOX;
1985 lc->anim_pause = 300 + (random() % 100);
1987 if ((lc->glx_context = init_GL(mi)) != NULL)
1989 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1993 # ifdef HAVE_MESA_GL
1995 # endif /* HAVE_MESA_GL */
2000 draw_lament(ModeInfo *mi)
2002 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2003 Display *dpy = MI_DISPLAY(mi);
2004 Window window = MI_WINDOW(mi);
2006 if (!lc->glx_context)
2009 glDrawBuffer(GL_BACK);
2011 glXMakeCurrent(dpy, window, *(lc->glx_context));
2013 if (mi->fps_p) do_fps (mi);
2016 glXSwapBuffers(dpy, window);