1 /* xscreensaver, Copyright (c) 1998-2012 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 #define DEFAULTS "*delay: 20000 \n" \
73 "*showFPS: False \n" \
74 "*wireframe: False \n"
75 # define refresh_lament 0
76 # define release_lament 0
77 #include "xlockmore.h"
79 #ifdef USE_GL /* whole file */
82 #define countof(x) (sizeof((x))/sizeof((*x)))
84 #define DEF_TEXTURE "True"
86 static int do_texture;
88 static XrmOptionDescRec opts[] = {
89 {"-texture", ".lament.texture", XrmoptionNoArg, "true" },
90 {"+texture", ".lament.texture", XrmoptionNoArg, "false" },
93 static argtype vars[] = {
94 {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
97 ENTRYPOINT ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL};
100 #include "xpm-ximage.h"
102 #include "gltrackball.h"
103 #include "../images/lament.xpm"
105 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
106 #define RANDSIGN() ((random() & 1) ? 1 : -1)
129 LAMENT_TASER_SLIDE_IN,
134 static const GLfloat exterior_color[] =
135 { 0.33, 0.22, 0.03, 1.00, /* ambient */
136 0.78, 0.57, 0.11, 1.00, /* specular */
137 0.99, 0.91, 0.81, 1.00, /* diffuse */
138 27.80 /* shininess */
140 static const GLfloat interior_color[] =
141 { 0.20, 0.20, 0.15, 1.00, /* ambient */
142 0.40, 0.40, 0.32, 1.00, /* specular */
143 0.99, 0.99, 0.81, 1.00, /* diffuse */
144 50.80 /* shininess */
149 GLXContext *glx_context;
151 double rotx, roty, rotz;
152 trackball_state *trackball;
155 GLuint box; /* display list IDs */
157 GLuint tetra_une, tetra_usw, tetra_dwn, tetra_dse, tetra_mid;
158 GLuint lid_0, lid_1, lid_2, lid_3, lid_4;
159 GLuint taser_base, taser_lifter, taser_slider;
161 XImage *texture; /* image bits */
162 GLuint texids[6]; /* texture map IDs */
163 lament_type type; /* which mode of the object is current */
165 int anim_pause; /* countdown before animating again */
166 GLfloat anim_r, anim_y, anim_z; /* relative position during anims */
172 } lament_configuration;
174 static lament_configuration *lcs = NULL;
184 parse_image_data(ModeInfo *mi)
186 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
187 lc->texture = xpm_to_ximage (mi->dpy,
194 /* Shorthand utilities for making faces, with proper normals.
198 set_colors (const GLfloat *color)
200 glMaterialfv(GL_FRONT, GL_AMBIENT, color+0);
201 glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4);
202 glMaterialfv(GL_FRONT, GL_SPECULAR, color+8);
203 glMaterialfv(GL_FRONT, GL_SHININESS, color+12);
207 face3(GLint texture, const GLfloat *color, Bool wire,
208 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
209 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
210 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3)
212 #ifdef HAVE_GLBINDTEXTURE
213 glBindTexture(GL_TEXTURE_2D, texture);
214 #endif /* HAVE_GLBINDTEXTURE */
217 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
218 glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
219 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
220 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
221 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
226 face4(GLint texture, const GLfloat *color, Bool wire,
227 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
228 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
229 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
230 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4)
232 #ifdef HAVE_GLBINDTEXTURE
233 glBindTexture(GL_TEXTURE_2D, texture);
234 #endif /* HAVE_GLBINDTEXTURE */
236 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
237 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
238 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
239 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
240 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
241 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
246 face5(GLint texture, const GLfloat *color, Bool wire,
247 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
248 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
249 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
250 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4,
251 GLfloat s5, GLfloat t5, GLfloat x5, GLfloat y5, GLfloat z5)
253 #ifdef HAVE_GLBINDTEXTURE
254 glBindTexture(GL_TEXTURE_2D, texture);
255 #endif /* HAVE_GLBINDTEXTURE */
257 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
258 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
259 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
260 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
261 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
262 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
263 glTexCoord2f(s5, t5); glVertex3f(x5, y5, z5);
269 /* Creating object models
273 box(ModeInfo *mi, Bool wire)
275 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
277 glNewList(lc->box, GL_COMPILE);
278 glShadeModel(GL_SMOOTH);
281 face4(lc->texids[FACE_N], exterior_color, wire,
282 0.0, 0.0, -0.5, 0.5, 0.5,
283 1.0, 0.0, 0.5, 0.5, 0.5,
284 1.0, 1.0, 0.5, 0.5, -0.5,
285 0.0, 1.0, -0.5, 0.5, -0.5);
288 face4(lc->texids[FACE_S], exterior_color, wire,
289 0.0, 0.0, -0.5, -0.5, -0.5,
290 1.0, 0.0, 0.5, -0.5, -0.5,
291 1.0, 1.0, 0.5, -0.5, 0.5,
292 0.0, 1.0, -0.5, -0.5, 0.5);
295 face4(lc->texids[FACE_E], exterior_color, wire,
296 0.0, 0.0, 0.5, -0.5, -0.5,
297 1.0, 0.0, 0.5, 0.5, -0.5,
298 1.0, 1.0, 0.5, 0.5, 0.5,
299 0.0, 1.0, 0.5, -0.5, 0.5);
302 face4(lc->texids[FACE_W], exterior_color, wire,
303 1.0, 1.0, -0.5, -0.5, 0.5,
304 0.0, 1.0, -0.5, 0.5, 0.5,
305 0.0, 0.0, -0.5, 0.5, -0.5,
306 1.0, 0.0, -0.5, -0.5, -0.5);
309 face4(lc->texids[FACE_U], exterior_color, wire,
310 1.0, 0.0, 0.5, -0.5, 0.5,
311 1.0, 1.0, 0.5, 0.5, 0.5,
312 0.0, 1.0, -0.5, 0.5, 0.5,
313 0.0, 0.0, -0.5, -0.5, 0.5);
316 face4(lc->texids[FACE_D], exterior_color, wire,
317 0.0, 1.0, -0.5, -0.5, -0.5,
318 0.0, 0.0, -0.5, 0.5, -0.5,
319 1.0, 0.0, 0.5, 0.5, -0.5,
320 1.0, 1.0, 0.5, -0.5, -0.5);
327 star(ModeInfo *mi, Bool top, Bool wire)
329 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
333 { 77, 74 }, { 60, 98 }, { 0, 71 }, { 0, 0 }, /* L1 */
334 { 60, 98 }, { 55, 127 }, { 0, 127 }, { 0, 71 }, /* L2 */
335 { 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */
336 { 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */
337 { 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */
338 { 100, 193 }, { 127, 198 }, { 127, 255 }, { 74, 255 }, /* B2 */
339 { 127, 198 }, { 151, 193 }, { 180, 255 }, { 127, 255 }, /* B3 */
340 { 151, 193 }, { 178, 177 }, { 255, 255 }, { 180, 255 }, /* B4 */
341 { 178, 177 }, { 193, 155 }, { 255, 181 }, { 255, 255 }, /* R4 */
342 { 193, 155 }, { 199, 127 }, { 255, 127 }, { 255, 181 }, /* R3 */
343 { 199, 127 }, { 194, 99 }, { 255, 74 }, { 255, 127 }, /* R2 */
344 { 194, 99 }, { 179, 76 }, { 255, 0 }, { 255, 74 }, /* R1 */
345 { 179, 76 }, { 155, 60 }, { 180, 0 }, { 255, 0 }, /* T4 */
346 { 155, 60 }, { 126, 55 }, { 126, 0 }, { 180, 0 }, /* T3 */
347 { 126, 55 }, { 100, 60 }, { 75, 0 }, { 126, 0 }, /* T2 */
348 { 100, 60 }, { 77, 74 }, { 0, 0 }, { 75, 0 }, /* T1 */
351 for (i = 0; i < countof(points); i++)
352 points[i][1] = 255-points[i][1];
355 glNewList(lc->star1, GL_COMPILE);
357 glNewList(lc->star2, GL_COMPILE);
360 glRotatef(-180.0, 1.0, 0.0, 0.0);
362 for (i = 0; i < countof(points)/4; i += 2)
369 GLfloat s[4], t[4], x[4], y[4], z[4];
370 for (j = 3, k = 0; j >= 0; j--, k++)
372 GLfloat xx = points[(i*4)+j][0] / 255.0L;
373 GLfloat yy = points[(i*4)+j][1] / 255.0L;
380 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
381 s[0], t[0], x[0], y[0], z[0],
382 s[1], t[1], x[1], y[1], z[1],
383 s[2], t[2], x[2], y[2], z[2],
384 s[3], t[3], x[3], y[3], z[3]);
388 for (j = 0, k = 0; j < 4; j++, k++)
390 GLfloat xx = points[(i*4)+j][0] / 255.0L;
391 GLfloat yy = points[(i*4)+j][1] / 255.0L;
398 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
399 s[0], t[0], x[0], y[0], z[0],
400 s[1], t[1], x[1], y[1], z[1],
401 s[2], t[2], x[2], y[2], z[2],
402 s[3], t[3], x[3], y[3], z[3]);
406 for (j = 3; j >= 0; j--)
408 int k = (j == 0 ? 3 : j-1);
409 Bool front_p = (j == 3);
410 GLfloat x1 = points[(i*4)+j][0] / 255.0L;
411 GLfloat y1 = points[(i*4)+j][1] / 255.0L;
412 GLfloat x2 = points[(i*4)+k][0] / 255.0L;
413 GLfloat y2 = points[(i*4)+k][1] / 255.0L;
415 GLfloat tx1=0.0, tx2=1.0, ty1=0.0, ty2=1.0;
419 facing = (facing + j + 5) % 4;
425 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
426 ty1 = 0.0; ty2 = 1.0;
429 ty1 = 1.0; ty2 = 0.0;
433 texture = top ? FACE_S : FACE_N;
435 ty1 = 0.0; ty2 = 1.0;
441 ty1 = 0.0; ty2 = 1.0;
443 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
444 ty1 = 1.0; ty2 = 0.0;
448 texture = top ? FACE_N : FACE_S;
450 ty1 = 1.0; ty2 = 0.0;
454 x1 -= 0.5; x2 -= 0.5;
455 y1 -= 0.5; y2 -= 0.5;
457 face4(front_p ? lc->texids[texture] : 0,
458 front_p ? exterior_color : interior_color,
460 tx1, ty2, x1, y1, 0.5,
461 tx1, ty1, x1, y1, -0.5,
462 tx2, ty1, x2, y2, -0.5,
463 tx2, ty2, x2, y2, 0.5);
468 /* Central core top cap.
470 #ifdef HAVE_GLBINDTEXTURE
471 glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]);
472 #endif /* HAVE_GLBINDTEXTURE */
473 set_colors(exterior_color);
476 do_normal(points[i+0][0], points[i+0][1], 0,
477 points[i+4][0], points[i+4][1], 0,
478 points[i+8][0], points[i+8][1], 0);
479 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
480 for (i = 1; i < countof(points); i += 4)
482 GLfloat x = points[i][0] / 255.0L;
483 GLfloat y = points[i][1] / 255.0L;
485 glVertex3f(x-0.5, y-0.5, 0.5);
490 /* Central core bottom cap.
492 #ifdef HAVE_GLBINDTEXTURE
493 glBindTexture(GL_TEXTURE_2D, 0);
494 #endif /* HAVE_GLBINDTEXTURE */
495 set_colors(interior_color);
497 i = countof(points) - 9;
498 do_normal(points[i+0][0], points[i+0][1], 0,
499 points[i+4][0], points[i+4][1], 0,
500 points[i+8][0], points[i+8][1], 0);
502 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
503 for (i = countof(points) - 3; i >= 0; i -= 4)
505 GLfloat x = points[i][0] / 255.0L;
506 GLfloat y = points[i][1] / 255.0L;
507 glVertex3f(x-0.5, y-0.5, 0);
512 /* Central core walls.
514 for (i = 1; i < countof(points); i += 4)
517 GLfloat x1 = points[i-1][0] / 255.0L;
518 GLfloat y1 = points[i-1][1] / 255.0L;
519 GLfloat x2 = points[i][0] / 255.0L;
520 GLfloat y2 = points[i][1] / 255.0L;
521 face4(0, interior_color, wire,
522 0.0, 0.0, x1-0.5, y1-0.5, 0.5,
523 0.0, 0.0, x1-0.5, y1-0.5, 0.0,
524 0.0, 0.0, x2-0.5, y2-0.5, 0.0,
525 0.0, 0.0, x2-0.5, y2-0.5, 0.5);
533 tetra(ModeInfo *mi, Bool wire)
535 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
537 glNewList(lc->tetra_une, GL_COMPILE);
539 glShadeModel(GL_SMOOTH);
542 face3(lc->texids[FACE_U], exterior_color, wire,
543 1.0, 0.0, 0.5, -0.5, 0.5,
544 1.0, 1.0, 0.5, 0.5, 0.5,
545 0.0, 1.0, -0.5, 0.5, 0.5);
548 face3(lc->texids[FACE_N], exterior_color, wire,
549 0.0, 0.0, -0.5, 0.5, 0.5,
550 1.0, 0.0, 0.5, 0.5, 0.5,
551 1.0, 1.0, 0.5, 0.5, -0.5);
554 face3(lc->texids[FACE_E], exterior_color, wire,
555 1.0, 0.0, 0.5, 0.5, -0.5,
556 1.0, 1.0, 0.5, 0.5, 0.5,
557 0.0, 1.0, 0.5, -0.5, 0.5);
559 face3(0, interior_color, wire,
560 0.0, 0.0, 0.5, 0.5, -0.5,
561 0.0, 0.0, 0.5, -0.5, 0.5,
562 0.0, 0.0, -0.5, 0.5, 0.5);
566 glNewList(lc->tetra_usw, GL_COMPILE);
569 face3(lc->texids[FACE_U], exterior_color, wire,
570 0.0, 1.0, -0.5, 0.5, 0.5,
571 0.0, 0.0, -0.5, -0.5, 0.5,
572 1.0, 0.0, 0.5, -0.5, 0.5);
575 face3(lc->texids[FACE_S], exterior_color, wire,
576 1.0, 1.0, 0.5, -0.5, 0.5,
577 0.0, 1.0, -0.5, -0.5, 0.5,
578 0.0, 0.0, -0.5, -0.5, -0.5);
581 face3(lc->texids[FACE_W], exterior_color, wire,
582 1.0, 0.0, -0.5, -0.5, -0.5,
583 1.0, 1.0, -0.5, -0.5, 0.5,
584 0.0, 1.0, -0.5, 0.5, 0.5);
586 face3(0, interior_color, wire,
587 0.0,0.0, -0.5, -0.5, -0.5,
588 0.0,0.0, -0.5, 0.5, 0.5,
589 0.0,0.0, 0.5, -0.5, 0.5);
593 glNewList(lc->tetra_dwn, GL_COMPILE);
596 face3(lc->texids[FACE_D], exterior_color, wire,
597 0.0, 1.0, -0.5, -0.5, -0.5,
598 0.0, 0.0, -0.5, 0.5, -0.5,
599 1.0, 0.0, 0.5, 0.5, -0.5);
602 face3(lc->texids[FACE_W], exterior_color, wire,
603 0.0, 1.0, -0.5, 0.5, 0.5,
604 0.0, 0.0, -0.5, 0.5, -0.5,
605 1.0, 0.0, -0.5, -0.5, -0.5);
608 face3(lc->texids[FACE_N], exterior_color, wire,
609 1.0, 1.0, 0.5, 0.5, -0.5,
610 0.0, 1.0, -0.5, 0.5, -0.5,
611 0.0, 0.0, -0.5, 0.5, 0.5);
613 face3(0, interior_color, wire,
614 0.0, 0.0, 0.5, 0.5, -0.5,
615 0.0, 0.0, -0.5, 0.5, 0.5,
616 0.0, 0.0, -0.5, -0.5, -0.5);
620 glNewList(lc->tetra_dse, GL_COMPILE);
623 face3(lc->texids[FACE_S], exterior_color, wire,
624 0.0, 0.0, -0.5, -0.5, -0.5,
625 1.0, 0.0, 0.5, -0.5, -0.5,
626 1.0, 1.0, 0.5, -0.5, 0.5);
629 face3(lc->texids[FACE_E], exterior_color, wire,
630 0.0, 1.0, 0.5, -0.5, 0.5,
631 0.0, 0.0, 0.5, -0.5, -0.5,
632 1.0, 0.0, 0.5, 0.5, -0.5);
635 face3(lc->texids[FACE_D], exterior_color, wire,
636 1.0, 0.0, 0.5, 0.5, -0.5,
637 1.0, 1.0, 0.5, -0.5, -0.5,
638 0.0, 1.0, -0.5, -0.5, -0.5);
640 face3(0, interior_color, wire,
641 0.0, 0.0, 0.5, -0.5, 0.5,
642 0.0, 0.0, 0.5, 0.5, -0.5,
643 0.0, 0.0, -0.5, -0.5, -0.5);
647 glNewList(lc->tetra_mid, GL_COMPILE);
649 face3(0, interior_color, wire,
650 0.0, 0.0, 0.5, -0.5, 0.5,
651 0.0, 0.0, 0.5, 0.5, -0.5,
652 0.0, 0.0, -0.5, 0.5, 0.5);
654 face3(0, interior_color, wire,
655 0.0, 0.0, -0.5, 0.5, 0.5,
656 0.0, 0.0, -0.5, -0.5, -0.5,
657 0.0, 0.0, 0.5, -0.5, 0.5);
659 face3(0, interior_color, wire,
660 0.0, 0.0, -0.5, 0.5, 0.5,
661 0.0, 0.0, 0.5, 0.5, -0.5,
662 0.0, 0.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);
669 face3(0, interior_color, wire,
670 0.0, 0.0, 0.5, -0.5, 0.5,
671 0.0, 0.0, 0.5, 0.5, -0.5,
672 0.0, 0.0, -0.5, -0.5, -0.5);
679 lid(ModeInfo *mi, Bool wire)
681 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
685 { 128, 20 },{ 21, 129 },{ 0, 129 },{ 0, 0 },{ 128, 0 }, /* L1 */
686 { 21, 129 },{ 127, 234 },{ 127, 255 },{ 0, 255 },{ 0, 129 }, /* L2 */
687 { 127, 234 },{ 233, 127 },{ 255, 127 },{ 255, 255 },{ 127, 255 }, /* R2 */
688 { 233, 127 },{ 128, 20 },{ 128, 0 },{ 255, 0 },{ 255, 127 }, /* R1 */
691 for (i = 0; i < countof(points); i++)
692 points[i][1] = 255-points[i][1];
694 glNewList(lc->lid_0, GL_COMPILE);
695 glShadeModel(GL_SMOOTH);
698 face4(lc->texids[FACE_N], exterior_color, wire,
699 0.0, 0.0, -0.5, 0.5, 0.5,
700 1.0, 0.0, 0.5, 0.5, 0.5,
701 1.0, 1.0, 0.5, 0.5, -0.5,
702 0.0, 1.0, -0.5, 0.5, -0.5);
705 face4(lc->texids[FACE_S], exterior_color, wire,
706 0.0, 0.0, -0.5, -0.5, -0.5,
707 1.0, 0.0, 0.5, -0.5, -0.5,
708 1.0, 1.0, 0.5, -0.5, 0.5,
709 0.0, 1.0, -0.5, -0.5, 0.5);
712 face4(lc->texids[FACE_E], exterior_color, wire,
713 0.0, 0.0, 0.5, -0.5, -0.5,
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);
719 face4(lc->texids[FACE_U], exterior_color, wire,
720 1.0, 0.0, 0.5, -0.5, 0.5,
721 1.0, 1.0, 0.5, 0.5, 0.5,
722 0.0, 1.0, -0.5, 0.5, 0.5,
723 0.0, 0.0, -0.5, -0.5, 0.5);
726 face4(lc->texids[FACE_D], exterior_color, wire,
727 0.0, 1.0, -0.5, -0.5, -0.5,
728 0.0, 0.0, -0.5, 0.5, -0.5,
729 1.0, 0.0, 0.5, 0.5, -0.5,
730 1.0, 1.0, 0.5, -0.5, -0.5);
733 for (i = 0; i < countof(points)/5; i++)
736 GLfloat s[5], t[5], x[5], y[5], z[5];
737 for (j = 0; j < 5; j++)
739 GLfloat xx = points[(i*5)+j][0] / 255.0L;
740 GLfloat yy = points[(i*5)+j][1] / 255.0L;
747 face5(lc->texids[FACE_W], exterior_color, wire,
748 s[0], t[0], x[0], y[0], z[0],
749 s[1], t[1], x[1], y[1], z[1],
750 s[2], t[2], x[2], y[2], z[2],
751 s[3], t[3], x[3], y[3], z[3],
752 s[4], t[4], x[4], y[4], z[4]);
757 /* W -- lid_1 through lid_4 */
758 for (i = 0; i < 4; i++)
760 GLfloat x1, y1, x2, y2, x3, y3;
762 glNewList(lc->lid_1 + i, GL_COMPILE);
763 glShadeModel(GL_SMOOTH);
765 x1 = points[(i*5)+1][0] / 255.0L;
766 y1 = points[(i*5)+1][1] / 255.0L;
767 x2 = points[(i*5)][0] / 255.0L;
768 y2 = points[(i*5)][1] / 255.0L;
773 face3(lc->texids[FACE_W], exterior_color, wire,
774 1.0-x1, y1, -0.5, x1-0.5, y1-0.5,
775 1.0-x2, y2, -0.5, x2-0.5, y2-0.5,
776 1.0-x3, y3, -0.5, x3-0.5, y3-0.5);
779 face3(0, interior_color, wire,
780 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
781 0.0, 0.0, -0.48, x1-0.5, y1-0.5,
782 0.0, 0.0, -0.48, x3-0.5, y3-0.5);
785 face4(0, interior_color, wire,
786 0.0, 0.0, -0.5, x1-0.5, y1-0.5,
787 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
788 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
789 0.0, 0.0, -0.48, x1-0.5, y1-0.5);
792 face4(0, interior_color, wire,
793 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
794 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
795 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
796 0.0, 0.0, -0.5, x2-0.5, y2-0.5);
803 taser(ModeInfo *mi, Bool wire)
805 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
808 int slider_face_points[][2] = {
809 { 86, 58 },{ 38, 106 },{ 70, 106 },{ 118, 58 },{ -1, -1 }, /* a */
810 { 136, 58 },{ 184, 106 },{ 216, 106 },{ 168, 58 },{ -1, -1 }, /* b */
811 { 38, 106 },{ 0, 144 },{ 0, 190 },{ 60, 190 },{ 108, 106 }, /* c */
812 { 144, 106 },{ 194, 190 },{ 254, 190 },{ 254, 144 },{ 216, 106 }, /* d */
813 { 98, 124 },{ 60, 190 },{ 92, 190 },{ 126, 158 },{ 126, 124 }, /* e */
814 { 126, 124 },{ 126, 158 },{ 160, 190 },{ 194, 190 },{ 154, 124 }, /* f */
815 { 22, 190 },{ 22, 254 },{ 60, 254 },{ 60, 190 },{ -1, -1 }, /* g */
816 { 194, 190 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ -1, -1 }, /* h */
817 { 60, 190 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ -1, -1 }, /* i */
818 { 160, 190 },{ 160, 210 },{ 194, 210 },{ 194, 190 },{ -1, -1 }, /* j */
819 { 110, 172 },{ 92, 190 },{ 110, 190 },{ -1, -1 },{ -1, -1 }, /* k */
820 { 140, 172 },{ 140, 190 },{ 160, 190 },{ -1, -1 },{ -1, -1 }, /* l */
821 { 110, 172 },{ 140, 172 },{ 126, 156 },{ -1, -1 },{ -1, -1 }, /* m */
824 int body_face_points[][2] = {
825 { 0, 0 },{ 0, 58 },{ 254, 58 },{ 254, 0 },{ -1, -1 }, /* A */
826 { 0, 58 },{ 0, 144 },{ 86, 58 },{ -1, -1 },{ -1, -1 }, /* B */
827 { 168, 58 },{ 254, 144 },{ 254, 58 },{ -1, -1 },{ -1, -1 }, /* C */
828 { 118, 58 },{ 70, 106 },{ 184, 106 },{ 136, 58 },{ -1, -1 }, /* F */
829 { 108, 106 },{ 98, 124 },{ 154, 124 },{ 144, 106 },{ -1, -1 }, /* G */
832 int lifter_face_points[][2] = {
833 { 0, 190 },{ 0, 254 },{ 22, 254 },{ 22, 190 },{ -1, -1 }, /* D */
834 { 230, 190 },{ 230, 254 },{ 254, 254 },{ 254, 190 },{ -1, -1 }, /* E */
835 { 60, 210 },{ 60, 254 },{ 194, 254 },{ 194, 210 },{ -1, -1 }, /* H */
836 { 92, 190 },{ 92, 210 },{ 160, 210 },{ 160, 190 },{ -1, -1 }, /* I */
837 { 110, 172 },{ 110, 190 },{ 140, 190 },{ 140, 172 },{ -1, -1 }, /* J */
840 int body_perimiter_points[][2] = {
841 { 0, 144 },{ 86, 59 },{ 119, 58 },{ 71, 107 },
842 { 108, 107 },{ 98, 124 },{ 155, 124 },{ 144, 107 },
843 { 185, 106 },{ 136, 59 },{ 169, 59 },{ 255, 145 },
847 int slider_perimiter_points[][2] = {
848 { 86, 58 },{ 0, 144 },{ 0, 190 },{ 22, 190 },{ 22, 254 },
849 { 60, 254 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ 110, 190 },
850 { 110, 172 },{ 140, 172 },{ 140, 190 },{ 160, 190 },{ 160, 210 },
851 { 194, 210 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ 254, 190 },
852 { 254, 144 },{ 168, 58 },{ 136, 58 },{ 184, 106 },{ 144, 106 },
853 { 154, 124 },{ 98, 124 },{ 108, 106 },{ 70, 106 },{ 118, 58 },
856 int lifter_perimiter_points_1[][2] = {
857 { 0, 189 },{ 0, 254 },{ 22, 255 },{ 23, 190 },
860 int lifter_perimiter_points_2[][2] = {
861 { 230, 254 },{ 255, 255 },{ 254, 190 },{ 230, 190 },
864 int lifter_perimiter_points_3[][2] = {
865 { 60, 254 },{ 194, 254 },{ 194, 211 },{ 160, 210 },
866 { 160, 190 },{ 140, 191 },{ 141, 172 },{ 111, 172 },
867 { 110, 190 },{ 93, 190 },{ 92, 210 },{ 60, 211 },
870 for (i = 0; i < countof(slider_face_points); i++)
871 slider_face_points[i][1] = 255-slider_face_points[i][1];
872 for (i = 0; i < countof(body_face_points); i++)
873 body_face_points[i][1] = 255-body_face_points[i][1];
874 for (i = 0; i < countof(lifter_face_points); i++)
875 lifter_face_points[i][1] = 255-lifter_face_points[i][1];
876 for (i = 0; i < countof(body_perimiter_points); i++)
877 body_perimiter_points[i][1] = 255-body_perimiter_points[i][1];
878 for (i = 0; i < countof(slider_perimiter_points); i++)
879 slider_perimiter_points[i][1] = 255-slider_perimiter_points[i][1];
880 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
881 lifter_perimiter_points_1[i][1] = 255-lifter_perimiter_points_1[i][1];
882 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
883 lifter_perimiter_points_2[i][1] = 255-lifter_perimiter_points_2[i][1];
884 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
885 lifter_perimiter_points_3[i][1] = 255-lifter_perimiter_points_3[i][1];
887 /* -------------------------------------------------------------------- */
889 glNewList(lc->taser_base, GL_COMPILE);
890 glShadeModel(GL_SMOOTH);
893 face4(lc->texids[FACE_N], exterior_color, wire,
894 0.0, 0.0, -0.5, 0.5, 0.5,
895 0.75, 0.0, 0.25, 0.5, 0.5,
896 0.75, 0.75, 0.25, 0.5, -0.25,
897 0.0, 0.75, -0.5, 0.5, -0.25);
900 face4(lc->texids[FACE_S], exterior_color, wire,
901 0.0, 0.25, -0.5, -0.5, -0.25,
902 0.75, 0.25, 0.25, -0.5, -0.25,
903 0.75, 1.0, 0.25, -0.5, 0.5,
904 0.0, 1.0, -0.5, -0.5, 0.5);
907 face4(0, interior_color, wire,
908 0.0, 0.0, 0.25, -0.5, -0.25,
909 1.0, 0.0, 0.25, 0.5, -0.25,
910 1.0, 1.0, 0.25, 0.5, 0.5,
911 0.0, 1.0, 0.25, -0.5, 0.5);
914 face4(lc->texids[FACE_W], exterior_color, wire,
915 1.0, 1.0, -0.5, -0.5, 0.5,
916 0.0, 1.0, -0.5, 0.5, 0.5,
917 0.0, 0.25, -0.5, 0.5, -0.25,
918 1.0, 0.25, -0.5, -0.5, -0.25);
921 face4(lc->texids[FACE_U], exterior_color, wire,
922 0.75, 0.0, 0.25, -0.5, 0.5,
923 0.75, 1.0, 0.25, 0.5, 0.5,
924 0.0, 1.0, -0.5, 0.5, 0.5,
925 0.0, 0.0, -0.5, -0.5, 0.5);
928 face4(0, interior_color, wire,
929 0.0, 1.0, -0.5, -0.5, -0.25,
930 0.0, 0.0, -0.5, 0.5, -0.25,
931 1.0, 0.0, 0.25, 0.5, -0.25,
932 1.0, 1.0, 0.25, -0.5, -0.25);
935 for (i = 0; i < countof(body_face_points)/5; i++)
938 #ifdef HAVE_GLBINDTEXTURE
939 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
940 #endif /* HAVE_GLBINDTEXTURE */
941 set_colors(exterior_color);
943 do_normal(0, body_face_points[(i*5)+0][0], body_face_points[(i*5)+0][1],
944 0, body_face_points[(i*5)+1][0], body_face_points[(i*5)+1][1],
945 0, body_face_points[(i*5)+2][0], body_face_points[(i*5)+2][1]
947 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
948 for (j = 0; j < 5; j++)
950 int ix = body_face_points[(i*5)+j][0];
951 int iy = body_face_points[(i*5)+j][1];
953 if (ix == -1) /* these are padding: ignore them */
958 glVertex3f(0.5, x-0.5, y-0.5);
964 for (i = 0; i < countof(body_perimiter_points); i++)
966 int j = (i+1 >= countof(body_perimiter_points) ? 0 : i+1);
967 GLfloat x1 = body_perimiter_points[i][0] / 255.0;
968 GLfloat y1 = body_perimiter_points[i][1] / 255.0;
969 GLfloat x2 = body_perimiter_points[j][0] / 255.0;
970 GLfloat y2 = body_perimiter_points[j][1] / 255.0;
972 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
976 texture = lc->texids[FACE_N];
978 s2 = 1.0; t2 = 0.568;
979 s3 = 0.75, t3 = 0.568;
984 texture = lc->texids[FACE_U];
992 texture = lc->texids[FACE_S];
993 s1 = 1.0; t1 = 0.437;
996 s4 = 0.75; t4 = 0.437;
999 face4((texture == -1 ? 0 : texture),
1000 (texture == -1 ? interior_color : exterior_color),
1002 s1, t1, 0.5, x2-0.5, y2-0.5,
1003 s2, t2, 0.5, x1-0.5, y1-0.5,
1004 s3, t3, 0.25, x1-0.5, y1-0.5,
1005 s4, t4, 0.25, x2-0.5, y2-0.5);
1010 /* -------------------------------------------------------------------- */
1012 glNewList(lc->taser_lifter, GL_COMPILE);
1013 glShadeModel(GL_SMOOTH);
1016 face4(lc->texids[FACE_N], exterior_color, wire,
1017 0.0, 0.75, -0.5, 0.5, -0.25,
1018 0.75, 0.75, 0.25, 0.5, -0.25,
1019 0.75, 1.0, 0.25, 0.5, -0.5,
1020 0.0, 1.0, -0.5, 0.5, -0.5);
1023 face4(lc->texids[FACE_S], exterior_color, wire,
1024 0.0, 0.0, -0.5, -0.5, -0.5,
1025 0.75, 0.0, 0.25, -0.5, -0.5,
1026 0.75, 0.25, 0.25, -0.5, -0.25,
1027 0.0, 0.25, -0.5, -0.5, -0.25);
1030 face4(0, interior_color, wire,
1031 0.0, 1.0, 0.25, -0.5, -0.5,
1032 1.0, 1.0, 0.25, 0.5, -0.5,
1033 1.0, 0.0, 0.25, 0.5, -0.25,
1034 0.0, 0.0, 0.25, -0.5, -0.25);
1037 face4(lc->texids[FACE_W], exterior_color, wire,
1038 1.0, 0.25, -0.5, -0.5, -0.25,
1039 0.0, 0.25, -0.5, 0.5, -0.25,
1040 0.0, 0.0, -0.5, 0.5, -0.5,
1041 1.0, 0.0, -0.5, -0.5, -0.5);
1044 face4(0, interior_color, wire,
1045 1.0, 0.0, 0.25, -0.5, -0.25,
1046 1.0, 1.0, 0.25, 0.5, -0.25,
1047 0.0, 1.0, -0.5, 0.5, -0.25,
1048 0.0, 0.0, -0.5, -0.5, -0.25);
1051 face4(lc->texids[FACE_D], exterior_color, wire,
1052 0.0, 1.0, -0.5, -0.5, -0.5,
1053 0.0, 0.0, -0.5, 0.5, -0.5,
1054 0.75, 0.0, 0.25, 0.5, -0.5,
1055 0.75, 1.0, 0.25, -0.5, -0.5);
1059 for (i = 0; i < countof(lifter_face_points)/5; i++)
1063 #ifdef HAVE_GLBINDTEXTURE
1064 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1065 #endif /* HAVE_GLBINDTEXTURE */
1066 set_colors(exterior_color);
1069 0, lifter_face_points[(i*5)+0][0], lifter_face_points[(i*5)+0][1],
1070 0, lifter_face_points[(i*5)+1][0], lifter_face_points[(i*5)+1][1],
1071 0, lifter_face_points[(i*5)+2][0], lifter_face_points[(i*5)+2][1]);
1073 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1074 for (j = 0; j < 5; j++)
1076 int ix = lifter_face_points[(i*5)+j][0];
1077 int iy = lifter_face_points[(i*5)+j][1];
1079 if (ix == -1) /* these are padding: ignore them */
1084 glVertex3f(0.5, x-0.5, y-0.5);
1090 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
1092 int j = (i+1 >= countof(lifter_perimiter_points_1) ? 0 : i+1);
1093 GLfloat x1 = lifter_perimiter_points_1[i][0] / 255.0;
1094 GLfloat y1 = lifter_perimiter_points_1[i][1] / 255.0;
1095 GLfloat x2 = lifter_perimiter_points_1[j][0] / 255.0;
1096 GLfloat y2 = lifter_perimiter_points_1[j][1] / 255.0;
1098 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1102 texture = lc->texids[FACE_S];
1104 s2 = 1.0; t2 = 0.26;
1105 s3 = 0.75, t3 = 0.26;
1106 s4 = 0.75; t4 = 0.0;
1110 texture = lc->texids[FACE_D];
1111 s1 = 1.0; t1 = 0.914;
1113 s3 = 0.75; t3 = 1.0;
1114 s4 = 0.75; t4 = 0.914;
1117 face4((texture == -1 ? 0 : texture),
1118 (texture == -1 ? interior_color : exterior_color),
1120 s1, t1, 0.5, x2-0.5, y2-0.5,
1121 s2, t2, 0.5, x1-0.5, y1-0.5,
1122 s3, t3, 0.25, x1-0.5, y1-0.5,
1123 s4, t4, 0.25, x2-0.5, y2-0.5);
1126 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
1128 int j = (i+1 >= countof(lifter_perimiter_points_2) ? 0 : i+1);
1129 GLfloat x1 = lifter_perimiter_points_2[i][0] / 255.0;
1130 GLfloat y1 = lifter_perimiter_points_2[i][1] / 255.0;
1131 GLfloat x2 = lifter_perimiter_points_2[j][0] / 255.0;
1132 GLfloat y2 = lifter_perimiter_points_2[j][1] / 255.0;
1134 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1138 texture = lc->texids[FACE_D];
1140 s2 = 1.0; t2 = 0.095;
1141 s3 = 0.75; t3 = 0.095;
1142 s4 = 0.75; t4 = 0.0;
1146 texture = lc->texids[FACE_N];
1147 s1 = 1.0; t1 = 0.745;
1149 s3 = 0.75; t3 = 1.0;
1150 s4 = 0.75; t4 = 0.745;
1153 face4((texture == -1 ? 0 : texture),
1154 (texture == -1 ? interior_color : exterior_color),
1156 s1, t1, 0.5, x2-0.5, y2-0.5,
1157 s2, t2, 0.5, x1-0.5, y1-0.5,
1158 s3, t3, 0.25, x1-0.5, y1-0.5,
1159 s4, t4, 0.25, x2-0.5, y2-0.5);
1162 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
1164 int j = (i+1 >= countof(lifter_perimiter_points_3) ? 0 : i+1);
1165 GLfloat x1 = lifter_perimiter_points_3[i][0] / 255.0;
1166 GLfloat y1 = lifter_perimiter_points_3[i][1] / 255.0;
1167 GLfloat x2 = lifter_perimiter_points_3[j][0] / 255.0;
1168 GLfloat y2 = lifter_perimiter_points_3[j][1] / 255.0;
1170 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1174 texture = lc->texids[FACE_D];
1175 s1 = 1.0; t1 = 0.235;
1176 s2 = 1.0; t2 = 0.765;
1177 s3 = 0.75; t3 = 0.765;
1178 s4 = 0.75; t4 = 0.235;
1181 face4((texture == -1 ? 0 : texture),
1182 (texture == -1 ? interior_color : exterior_color),
1184 s1, t1, 0.5, x2-0.5, y2-0.5,
1185 s2, t2, 0.5, x1-0.5, y1-0.5,
1186 s3, t3, 0.25, x1-0.5, y1-0.5,
1187 s4, t4, 0.25, x2-0.5, y2-0.5);
1192 /* -------------------------------------------------------------------- */
1194 glNewList(lc->taser_slider, GL_COMPILE);
1195 glShadeModel(GL_SMOOTH);
1198 for (i = 0; i < countof(slider_face_points)/5; i++)
1201 #ifdef HAVE_GLBINDTEXTURE
1202 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1203 #endif /* HAVE_GLBINDTEXTURE */
1204 set_colors(exterior_color);
1207 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1],
1208 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1209 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1]);
1210 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1211 for (j = 0; j < 5; j++)
1213 int ix = slider_face_points[(i*5)+j][0];
1214 int iy = slider_face_points[(i*5)+j][1];
1216 if (ix == -1) /* these are padding: ignore them */
1221 glVertex3f(0.5, x-0.5, y-0.5);
1227 for (i = countof(slider_face_points)/5 - 1; i >= 0; i--)
1230 #ifdef HAVE_GLBINDTEXTURE
1231 glBindTexture(GL_TEXTURE_2D, 0);
1232 #endif /* HAVE_GLBINDTEXTURE */
1233 set_colors(interior_color);
1236 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1],
1237 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1238 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1]);
1239 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1240 for (j = 4; j >= 0; j--)
1242 int ix = slider_face_points[(i*5)+j][0];
1243 int iy = slider_face_points[(i*5)+j][1];
1245 if (ix == -1) /* these are padding: ignore them */
1250 glVertex3f(0.25, x-0.5, y-0.5);
1256 for (i = 0; i < countof(slider_perimiter_points); i++)
1258 int j = (i+1 >= countof(slider_perimiter_points) ? 0 : i+1);
1259 GLfloat x1 = slider_perimiter_points[i][0] / 255.0;
1260 GLfloat y1 = slider_perimiter_points[i][1] / 255.0;
1261 GLfloat x2 = slider_perimiter_points[j][0] / 255.0;
1262 GLfloat y2 = slider_perimiter_points[j][1] / 255.0;
1264 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1268 texture = lc->texids[FACE_S];
1269 s1 = 1.0; t1 = 0.255;
1270 s2 = 1.0; t2 = 0.435;
1271 s3 = 0.75; t3 = 0.435;
1272 s4 = 0.75; t4 = 0.255;
1276 texture = lc->texids[FACE_D];
1277 s1 = 1.0; t1 = 0.758;
1278 s2 = 1.0; t2 = 0.915;
1279 s3 = 0.75; t3 = 0.915;
1280 s4 = 0.75; t4 = 0.758;
1284 texture = lc->texids[FACE_D];
1285 s1 = 1.0; t1 = 0.095;
1286 s2 = 1.0; t2 = 0.24;
1287 s3 = 0.75; t3 = 0.24;
1288 s4 = 0.75; t4 = 0.095;
1292 texture = lc->texids[FACE_N];
1293 s1 = 1.0; t1 = 0.568;
1294 s2 = 1.0; t2 = 0.742;
1295 s3 = 0.75; t3 = 0.742;
1296 s4 = 0.75; t4 = 0.568;
1299 face4((texture == -1 ? 0 : texture),
1300 (texture == -1 ? interior_color : exterior_color),
1302 s1, t1, 0.5, x2-0.5, y2-0.5,
1303 s2, t2, 0.5, x1-0.5, y1-0.5,
1304 s3, t3, 0.25, x1-0.5, y1-0.5,
1305 s4, t4, 0.25, x2-0.5, y2-0.5);
1313 /* Rendering and animating object models
1317 lament_handle_event (ModeInfo *mi, XEvent *event)
1319 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1321 if (event->xany.type == ButtonPress &&
1322 event->xbutton.button == Button1)
1324 lc->button_down_p = True;
1325 gltrackball_start (lc->trackball,
1326 event->xbutton.x, event->xbutton.y,
1327 MI_WIDTH (mi), MI_HEIGHT (mi));
1330 else if (event->xany.type == ButtonRelease &&
1331 event->xbutton.button == Button1)
1333 lc->button_down_p = False;
1336 else if (event->xany.type == ButtonPress &&
1337 (event->xbutton.button == Button4 ||
1338 event->xbutton.button == Button5 ||
1339 event->xbutton.button == Button6 ||
1340 event->xbutton.button == Button7))
1342 gltrackball_mousewheel (lc->trackball, event->xbutton.button, 5,
1343 !!event->xbutton.state);
1346 else if (event->xany.type == MotionNotify &&
1349 gltrackball_track (lc->trackball,
1350 event->xmotion.x, event->xmotion.y,
1351 MI_WIDTH (mi), MI_HEIGHT (mi));
1360 check_facing(ModeInfo *mi)
1362 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1364 GLdouble m[16], p[16], x, y, z;
1366 glGetDoublev (GL_MODELVIEW_MATRIX, m);
1367 glGetDoublev (GL_PROJECTION_MATRIX, p);
1368 glGetIntegerv (GL_VIEWPORT, v);
1370 /* See if a coordinate 5 units in front of the door is near the
1371 center of the screen. */
1373 gluProject (-5, 0, 0, m, p, v, &x, &y, &z);
1374 x = (x / MI_WIDTH(mi)) - 0.5;
1375 y = (y / MI_HEIGHT(mi)) - 0.5;
1376 lc->facing_p = (z < 0.9 &&
1377 x > -0.02 && x < 0.02 &&
1378 y > -0.02 && y < 0.02);
1384 scale_for_window(ModeInfo *mi)
1386 int target_size = 180;
1387 int win_size = (MI_WIDTH(mi) > MI_HEIGHT(mi) ? MI_HEIGHT(mi) : MI_WIDTH(mi));
1389 /* This scale makes the box take up most of the window */
1392 /* But if the window is more than a little larger than our target size,
1393 scale the object back down, so that the bits drawn on the screen end
1394 up rougly target_size across (actually it ends up a little larger.)
1395 Note that the image-map bits we have are 128x128. Therefore, if the
1396 image is magnified a lot, it looks pretty blocky. So it's better to
1397 have a 128x128 animation on a 1280x1024 screen that looks good, than
1398 a 1024x1024 animation that looks really pixelated.
1400 if (win_size > 640 &&
1401 win_size > target_size * 1.5)
1403 GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
1405 glScalef(ratio, ratio, ratio);
1413 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1414 Bool wire = MI_IS_WIREFRAME(mi);
1417 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1419 glClear(GL_COLOR_BUFFER_BIT);
1423 gltrackball_rotate (lc->trackball);
1425 /* Make into the screen be +Y right be +X, and up be +Z. */
1426 glRotatef(-90.0, 1.0, 0.0, 0.0);
1428 scale_for_window (mi);
1433 /* Shift to the upper left, and draw the vanilla box. */
1434 glTranslatef(-0.6, 0.0, 0.6);
1436 /* Apply rotation to the object. */
1437 glRotatef(x * 360, 1.0, 0.0, 0.0);
1438 glRotatef(y * 360, 0.0, 1.0, 0.0);
1439 glRotatef(z * 360, 0.0, 0.0, 1.0);
1442 glCallList(lc->box);
1446 /* Shift to the lower right, and draw the animated object. */
1447 glTranslatef(0.6, 0.0, -0.6);
1453 /* Apply rotation to the object. */
1454 if (lc->type != LAMENT_LID_ZOOM)
1455 get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
1456 !lc->button_down_p);
1457 glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
1458 glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
1459 glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
1466 glCallList(lc->box);
1469 case LAMENT_STAR_OUT:
1470 case LAMENT_STAR_ROT:
1471 case LAMENT_STAR_ROT_IN:
1472 case LAMENT_STAR_ROT_OUT:
1473 case LAMENT_STAR_UNROT:
1474 case LAMENT_STAR_IN:
1475 glTranslatef(0.0, 0.0, lc->anim_z/2);
1476 glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0);
1477 glCallList(lc->star1);
1479 glTranslatef(0.0, 0.0, -lc->anim_z);
1480 glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
1481 glCallList(lc->star2);
1484 case LAMENT_TETRA_UNE:
1485 case LAMENT_TETRA_USW:
1486 case LAMENT_TETRA_DWN:
1487 case LAMENT_TETRA_DSE:
1492 case LAMENT_TETRA_UNE: magic = lc->tetra_une;
1493 x = 1.0; y = 1.0; z = 1.0; break;
1494 case LAMENT_TETRA_USW: magic = lc->tetra_usw;
1495 x = 1.0; y = 1.0; z = -1.0; break;
1496 case LAMENT_TETRA_DWN: magic = lc->tetra_dwn;
1497 x = 1.0; y = -1.0; z = 1.0; break;
1498 case LAMENT_TETRA_DSE: magic = lc->tetra_dse;
1499 x = -1.0; y = 1.0; z = 1.0; break;
1500 default: abort(); break;
1502 glCallList(lc->tetra_mid);
1503 if (magic != lc->tetra_une) glCallList(lc->tetra_une);
1504 if (magic != lc->tetra_usw) glCallList(lc->tetra_usw);
1505 if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn);
1506 if (magic != lc->tetra_dse) glCallList(lc->tetra_dse);
1507 glRotatef(lc->anim_r, x, y, z);
1512 case LAMENT_LID_OPEN:
1513 case LAMENT_LID_CLOSE:
1514 case LAMENT_LID_ZOOM:
1518 glTranslatef(lc->anim_z, 0.0, 0.0);
1520 glCallList(lc->lid_0);
1523 glTranslatef(-0.5, -d, 0.0);
1524 glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
1525 glTranslatef( 0.5, d, 0.0);
1526 glCallList(lc->lid_1);
1529 glTranslatef(-0.5, -d, 0.0);
1530 glRotatef( lc->anim_r, 0.0, -1.0, 1.0);
1531 glTranslatef( 0.5, d, 0.0);
1532 glCallList(lc->lid_2);
1535 glTranslatef(-0.5, d, 0.0);
1536 glRotatef( lc->anim_r, 0.0, -1.0, -1.0);
1537 glTranslatef( 0.5, -d, 0.0);
1538 glCallList(lc->lid_3);
1541 glTranslatef(-0.5, d, 0.0);
1542 glRotatef(-lc->anim_r, 0.0, -1.0, 1.0);
1543 glTranslatef( 0.5, -d, 0.0);
1544 glCallList(lc->lid_4);
1549 case LAMENT_TASER_OUT:
1550 case LAMENT_TASER_SLIDE:
1551 case LAMENT_TASER_SLIDE_IN:
1552 case LAMENT_TASER_IN:
1554 glTranslatef(-lc->anim_z/2, 0.0, 0.0);
1555 glCallList(lc->taser_base);
1557 glTranslatef(lc->anim_z, 0.0, 0.0);
1558 glCallList(lc->taser_lifter);
1560 glTranslatef(0.0, 0.0, lc->anim_y);
1561 glCallList(lc->taser_slider);
1575 /* Rather than just picking states randomly, pick an ordering randomly, do it,
1576 and then re-randomize. That way one can be assured of seeing all states in
1577 a short time period, though not always in the same order (it's frustrating
1578 to see it pick the same state 5x in a row.)
1581 shuffle_states (lament_configuration *lc)
1584 for (i = 0; i < lc->nstates; i++)
1586 int a = random() % lc->nstates;
1587 lament_type swap = lc->states[a];
1588 lc->states[a] = lc->states[i];
1589 lc->states[i] = swap;
1595 animate(ModeInfo *mi)
1597 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1599 /* int pause2 = 60;*/
1607 if (lc->state >= lc->nstates)
1609 shuffle_states (lc);
1612 lc->type = lc->states[lc->state];
1614 if (lc->type == LAMENT_BOX)
1615 lc->anim_pause = pause3;
1623 /* -------------------------------------------------------------- */
1625 case LAMENT_STAR_OUT:
1627 if (lc->anim_z >= 1.0)
1630 lc->type = LAMENT_STAR_ROT;
1631 lc->anim_pause = pause;
1635 case LAMENT_STAR_ROT:
1637 if (lc->anim_r >= 45.0)
1640 lc->type = LAMENT_STAR_ROT_IN;
1641 lc->anim_pause = pause;
1645 case LAMENT_STAR_ROT_IN:
1647 if (lc->anim_z <= 0.0)
1650 lc->type = LAMENT_STAR_ROT_OUT;
1651 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1655 case LAMENT_STAR_ROT_OUT:
1657 if (lc->anim_z >= 1.0)
1660 lc->type = LAMENT_STAR_UNROT;
1661 lc->anim_pause = pause;
1665 case LAMENT_STAR_UNROT:
1667 if (lc->anim_r <= 0.0)
1670 lc->type = LAMENT_STAR_IN;
1671 lc->anim_pause = pause;
1675 case LAMENT_STAR_IN:
1677 if (lc->anim_z <= 0.0)
1680 lc->type = LAMENT_BOX;
1681 lc->anim_pause = pause3;
1685 /* -------------------------------------------------------------- */
1687 case LAMENT_TETRA_UNE:
1688 case LAMENT_TETRA_USW:
1689 case LAMENT_TETRA_DWN:
1690 case LAMENT_TETRA_DSE:
1693 if (lc->anim_r >= 360.0)
1696 lc->type = LAMENT_BOX;
1697 lc->anim_pause = pause3;
1699 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1702 lc->anim_pause = pause;
1704 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1707 lc->anim_pause = pause;
1711 /* -------------------------------------------------------------- */
1713 case LAMENT_LID_OPEN:
1716 if (lc->anim_r >= 112.0)
1720 lc->anim_pause = pause3;
1721 lc->type = (lc->facing_p ? LAMENT_LID_ZOOM : LAMENT_LID_CLOSE);
1725 case LAMENT_LID_CLOSE:
1727 if (lc->anim_r <= 0.0)
1730 lc->type = LAMENT_BOX;
1731 lc->anim_pause = pause3;
1735 case LAMENT_LID_ZOOM:
1737 if (lc->anim_z < -50.0)
1741 lc->type = LAMENT_BOX;
1745 /* -------------------------------------------------------------- */
1747 case LAMENT_TASER_OUT:
1748 lc->anim_z += 0.0025;
1749 if (lc->anim_z >= 0.25)
1752 lc->type = LAMENT_TASER_SLIDE;
1753 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1757 case LAMENT_TASER_SLIDE:
1758 lc->anim_y += 0.0025;
1759 if (lc->anim_y >= 0.23)
1762 lc->type = LAMENT_TASER_SLIDE_IN;
1763 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1767 case LAMENT_TASER_SLIDE_IN:
1768 lc->anim_y -= 0.0025;
1769 if (lc->anim_y <= 0.0)
1772 lc->type = LAMENT_TASER_IN;
1773 lc->anim_pause = pause;
1777 case LAMENT_TASER_IN:
1778 lc->anim_z -= 0.0025;
1779 if (lc->anim_z <= 0.0)
1782 lc->type = LAMENT_BOX;
1783 lc->anim_pause = pause3;
1795 /* Window management, etc
1799 reshape_lament(ModeInfo *mi, int width, int height)
1801 GLfloat h = (GLfloat) height / (GLfloat) width;
1802 glViewport(0, 0, (GLint) width, (GLint) height);
1804 glMatrixMode(GL_PROJECTION);
1806 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1807 glMatrixMode(GL_MODELVIEW);
1809 glTranslatef(0.0, 0.0, -40.0);
1810 glClear(GL_COLOR_BUFFER_BIT);
1815 gl_init(ModeInfo *mi)
1817 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1818 Bool wire = MI_IS_WIREFRAME(mi);
1825 static const GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1826 static const GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1828 static const GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1829 /* static const GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1830 static const GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1831 static const GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1833 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1834 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1836 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1837 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1838 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1839 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1840 set_colors(exterior_color);
1842 glEnable(GL_LIGHTING);
1843 glEnable(GL_LIGHT0);
1844 /* glEnable(GL_LIGHT1); */
1846 glEnable(GL_DEPTH_TEST);
1847 glEnable(GL_TEXTURE_2D);
1848 glEnable(GL_NORMALIZE);
1849 glEnable(GL_CULL_FACE);
1854 #ifdef HAVE_GLBINDTEXTURE
1856 for (i = 0; i < 6; i++)
1857 glGenTextures(1, &lc->texids[i]);
1859 parse_image_data(mi);
1861 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1862 /* messes up -fps */
1863 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); */
1865 for (i = 0; i < 6; i++)
1867 int height = lc->texture->width; /* assume square */
1868 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1869 set_colors(exterior_color);
1872 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1873 lc->texture->width, height, 0,
1875 /* GL_UNSIGNED_BYTE, */
1876 GL_UNSIGNED_INT_8_8_8_8_REV,
1877 (lc->texture->data +
1878 (lc->texture->bytes_per_line * height * i)));
1879 check_gl_error("texture");
1881 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1882 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1883 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1884 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1887 #else /* !HAVE_GLBINDTEXTURE */
1889 "%s: this version of GL doesn't support multiple texture maps.\n"
1890 "\tGet OpenGL 1.1.\n",
1893 #endif /* !HAVE_GLBINDTEXTURE */
1896 lc->box = glGenLists(16);
1897 lc->star1 = lc->box+1;
1898 lc->star2 = lc->box+2;
1899 lc->tetra_une = lc->box+3;
1900 lc->tetra_usw = lc->box+4;
1901 lc->tetra_dwn = lc->box+5;
1902 lc->tetra_dse = lc->box+6;
1903 lc->tetra_mid = lc->box+7;
1904 lc->lid_0 = lc->box+8;
1905 lc->lid_1 = lc->box+9;
1906 lc->lid_2 = lc->box+10;
1907 lc->lid_3 = lc->box+11;
1908 lc->lid_4 = lc->box+12;
1909 lc->taser_base = lc->box+13;
1910 lc->taser_lifter = lc->box+14;
1911 lc->taser_slider = lc->box+15;
1914 star(mi, True, wire);
1915 star(mi, False, wire);
1922 # ifdef HAVE_MESA_GL
1924 # include <signal.h>
1927 lament_signal_kludge (int sig)
1929 signal (sig, SIG_DFL);
1932 "%s: dying with signal %d (%s).\n"
1934 "\tThis is almost certainly a bug in the Mesa GL library,\n"
1935 "\tespecially if the stack trace in the core file mentions\n"
1936 "\t`lambda_textured_triangle' or `render_quad'.\n"
1938 "\tFirst make sure that you have the latest version of Mesa.\n"
1939 "\tIf that doesn't fix it, then I encourage you to report this\n"
1940 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
1944 (sig == SIGILL ? "SIGILL" :
1945 sig == SIGFPE ? "SIGFPE" :
1946 sig == SIGBUS ? "SIGBUS" :
1947 sig == SIGSEGV ? "SIGSEGV" : "???"));
1949 kill (getpid (), sig);
1953 handle_signals (void)
1955 signal (SIGILL, lament_signal_kludge);
1956 signal (SIGFPE, lament_signal_kludge);
1957 signal (SIGBUS, lament_signal_kludge);
1958 signal (SIGSEGV, lament_signal_kludge);
1960 # endif /* HAVE_MESA_GL */
1964 init_lament(ModeInfo *mi)
1966 lament_configuration *lc;
1969 lcs = (lament_configuration *)
1970 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
1973 fprintf(stderr, "%s: out of memory\n", progname);
1978 lc = &lcs[MI_SCREEN(mi)];
1981 double rot_speed = 0.5;
1982 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
1983 lc->trackball = gltrackball_init ();
1986 lc->type = LAMENT_BOX;
1987 lc->anim_pause = 300 + (random() % 100);
1989 if ((lc->glx_context = init_GL(mi)) != NULL)
1991 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1995 lc->states = (lament_type *) calloc (50, sizeof (*lc->states));
1997 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
1998 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
1999 lc->states[lc->nstates++] = LAMENT_TETRA_UNE;
2000 lc->states[lc->nstates++] = LAMENT_TETRA_USW;
2001 lc->states[lc->nstates++] = LAMENT_TETRA_DWN;
2002 lc->states[lc->nstates++] = LAMENT_TETRA_DSE;
2003 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2004 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2005 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2006 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2007 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2008 lc->states[lc->nstates++] = LAMENT_BOX;
2009 lc->states[lc->nstates++] = LAMENT_BOX;
2010 lc->states[lc->nstates++] = LAMENT_BOX;
2011 lc->states[lc->nstates++] = LAMENT_BOX;
2012 lc->states[lc->nstates++] = LAMENT_BOX;
2013 lc->states[lc->nstates++] = LAMENT_BOX;
2014 lc->states[lc->nstates++] = LAMENT_BOX;
2015 lc->states[lc->nstates++] = LAMENT_BOX;
2016 lc->states[lc->nstates++] = LAMENT_BOX;
2017 lc->states[lc->nstates++] = LAMENT_BOX;
2018 shuffle_states (lc);
2020 # ifdef HAVE_MESA_GL
2022 # endif /* HAVE_MESA_GL */
2027 draw_lament(ModeInfo *mi)
2029 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2030 Display *dpy = MI_DISPLAY(mi);
2031 Window window = MI_WINDOW(mi);
2033 if (!lc->glx_context)
2036 glDrawBuffer(GL_BACK);
2038 glXMakeCurrent(dpy, window, *(lc->glx_context));
2040 if (mi->fps_p) do_fps (mi);
2043 glXSwapBuffers(dpy, window);
2051 XSCREENSAVER_MODULE ("Lament", lament)