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 #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 */
171 } lament_configuration;
173 static lament_configuration *lcs = NULL;
183 parse_image_data(ModeInfo *mi)
185 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
186 lc->texture = xpm_to_ximage (mi->dpy,
193 /* Shorthand utilities for making faces, with proper normals.
197 set_colors (const GLfloat *color)
199 glMaterialfv(GL_FRONT, GL_AMBIENT, color+0);
200 glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4);
201 glMaterialfv(GL_FRONT, GL_SPECULAR, color+8);
202 glMaterialfv(GL_FRONT, GL_SHININESS, color+12);
206 face3(GLint texture, const GLfloat *color, Bool wire,
207 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
208 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
209 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3)
211 #ifdef HAVE_GLBINDTEXTURE
212 glBindTexture(GL_TEXTURE_2D, texture);
213 #endif /* HAVE_GLBINDTEXTURE */
216 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
217 glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
218 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
219 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
220 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
225 face4(GLint texture, const GLfloat *color, Bool wire,
226 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
227 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
228 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
229 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4)
231 #ifdef HAVE_GLBINDTEXTURE
232 glBindTexture(GL_TEXTURE_2D, texture);
233 #endif /* HAVE_GLBINDTEXTURE */
235 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
236 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
237 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
238 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
239 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
240 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
245 face5(GLint texture, const GLfloat *color, Bool wire,
246 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
247 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
248 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
249 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4,
250 GLfloat s5, GLfloat t5, GLfloat x5, GLfloat y5, GLfloat z5)
252 #ifdef HAVE_GLBINDTEXTURE
253 glBindTexture(GL_TEXTURE_2D, texture);
254 #endif /* HAVE_GLBINDTEXTURE */
256 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
257 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
258 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
259 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
260 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
261 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
262 glTexCoord2f(s5, t5); glVertex3f(x5, y5, z5);
268 /* Creating object models
272 box(ModeInfo *mi, Bool wire)
274 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
276 glNewList(lc->box, GL_COMPILE);
277 glShadeModel(GL_SMOOTH);
280 face4(lc->texids[FACE_N], exterior_color, wire,
281 0.0, 0.0, -0.5, 0.5, 0.5,
282 1.0, 0.0, 0.5, 0.5, 0.5,
283 1.0, 1.0, 0.5, 0.5, -0.5,
284 0.0, 1.0, -0.5, 0.5, -0.5);
287 face4(lc->texids[FACE_S], exterior_color, wire,
288 0.0, 0.0, -0.5, -0.5, -0.5,
289 1.0, 0.0, 0.5, -0.5, -0.5,
290 1.0, 1.0, 0.5, -0.5, 0.5,
291 0.0, 1.0, -0.5, -0.5, 0.5);
294 face4(lc->texids[FACE_E], exterior_color, wire,
295 0.0, 0.0, 0.5, -0.5, -0.5,
296 1.0, 0.0, 0.5, 0.5, -0.5,
297 1.0, 1.0, 0.5, 0.5, 0.5,
298 0.0, 1.0, 0.5, -0.5, 0.5);
301 face4(lc->texids[FACE_W], exterior_color, wire,
302 1.0, 1.0, -0.5, -0.5, 0.5,
303 0.0, 1.0, -0.5, 0.5, 0.5,
304 0.0, 0.0, -0.5, 0.5, -0.5,
305 1.0, 0.0, -0.5, -0.5, -0.5);
308 face4(lc->texids[FACE_U], exterior_color, wire,
309 1.0, 0.0, 0.5, -0.5, 0.5,
310 1.0, 1.0, 0.5, 0.5, 0.5,
311 0.0, 1.0, -0.5, 0.5, 0.5,
312 0.0, 0.0, -0.5, -0.5, 0.5);
315 face4(lc->texids[FACE_D], exterior_color, wire,
316 0.0, 1.0, -0.5, -0.5, -0.5,
317 0.0, 0.0, -0.5, 0.5, -0.5,
318 1.0, 0.0, 0.5, 0.5, -0.5,
319 1.0, 1.0, 0.5, -0.5, -0.5);
326 star(ModeInfo *mi, Bool top, Bool wire)
328 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
332 { 77, 74 }, { 60, 98 }, { 0, 71 }, { 0, 0 }, /* L1 */
333 { 60, 98 }, { 55, 127 }, { 0, 127 }, { 0, 71 }, /* L2 */
334 { 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */
335 { 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */
336 { 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */
337 { 100, 193 }, { 127, 198 }, { 127, 255 }, { 74, 255 }, /* B2 */
338 { 127, 198 }, { 151, 193 }, { 180, 255 }, { 127, 255 }, /* B3 */
339 { 151, 193 }, { 178, 177 }, { 255, 255 }, { 180, 255 }, /* B4 */
340 { 178, 177 }, { 193, 155 }, { 255, 181 }, { 255, 255 }, /* R4 */
341 { 193, 155 }, { 199, 127 }, { 255, 127 }, { 255, 181 }, /* R3 */
342 { 199, 127 }, { 194, 99 }, { 255, 74 }, { 255, 127 }, /* R2 */
343 { 194, 99 }, { 179, 76 }, { 255, 0 }, { 255, 74 }, /* R1 */
344 { 179, 76 }, { 155, 60 }, { 180, 0 }, { 255, 0 }, /* T4 */
345 { 155, 60 }, { 126, 55 }, { 126, 0 }, { 180, 0 }, /* T3 */
346 { 126, 55 }, { 100, 60 }, { 75, 0 }, { 126, 0 }, /* T2 */
347 { 100, 60 }, { 77, 74 }, { 0, 0 }, { 75, 0 }, /* T1 */
350 for (i = 0; i < countof(points); i++)
351 points[i][1] = 255-points[i][1];
354 glNewList(lc->star1, GL_COMPILE);
356 glNewList(lc->star2, GL_COMPILE);
359 glRotatef(-180.0, 1.0, 0.0, 0.0);
361 for (i = 0; i < countof(points)/4; i += 2)
368 GLfloat s[4], t[4], x[4], y[4], z[4];
369 for (j = 3, k = 0; j >= 0; j--, k++)
371 GLfloat xx = points[(i*4)+j][0] / 255.0L;
372 GLfloat yy = points[(i*4)+j][1] / 255.0L;
379 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
380 s[0], t[0], x[0], y[0], z[0],
381 s[1], t[1], x[1], y[1], z[1],
382 s[2], t[2], x[2], y[2], z[2],
383 s[3], t[3], x[3], y[3], z[3]);
387 for (j = 0, k = 0; j < 4; j++, k++)
389 GLfloat xx = points[(i*4)+j][0] / 255.0L;
390 GLfloat yy = points[(i*4)+j][1] / 255.0L;
397 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
398 s[0], t[0], x[0], y[0], z[0],
399 s[1], t[1], x[1], y[1], z[1],
400 s[2], t[2], x[2], y[2], z[2],
401 s[3], t[3], x[3], y[3], z[3]);
405 for (j = 3; j >= 0; j--)
407 int k = (j == 0 ? 3 : j-1);
408 Bool front_p = (j == 3);
409 GLfloat x1 = points[(i*4)+j][0] / 255.0L;
410 GLfloat y1 = points[(i*4)+j][1] / 255.0L;
411 GLfloat x2 = points[(i*4)+k][0] / 255.0L;
412 GLfloat y2 = points[(i*4)+k][1] / 255.0L;
414 GLfloat tx1=0.0, tx2=1.0, ty1=0.0, ty2=1.0;
418 facing = (facing + j + 5) % 4;
424 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
425 ty1 = 0.0; ty2 = 1.0;
428 ty1 = 1.0; ty2 = 0.0;
432 texture = top ? FACE_S : FACE_N;
434 ty1 = 0.0; ty2 = 1.0;
440 ty1 = 0.0; ty2 = 1.0;
442 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
443 ty1 = 1.0; ty2 = 0.0;
447 texture = top ? FACE_N : FACE_S;
449 ty1 = 1.0; ty2 = 0.0;
453 x1 -= 0.5; x2 -= 0.5;
454 y1 -= 0.5; y2 -= 0.5;
456 face4(front_p ? lc->texids[texture] : 0,
457 front_p ? exterior_color : interior_color,
459 tx1, ty2, x1, y1, 0.5,
460 tx1, ty1, x1, y1, -0.5,
461 tx2, ty1, x2, y2, -0.5,
462 tx2, ty2, x2, y2, 0.5);
467 /* Central core top cap.
469 #ifdef HAVE_GLBINDTEXTURE
470 glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]);
471 #endif /* HAVE_GLBINDTEXTURE */
472 set_colors(exterior_color);
475 do_normal(points[i+0][0], points[i+0][1], 0,
476 points[i+4][0], points[i+4][1], 0,
477 points[i+8][0], points[i+8][1], 0);
478 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
479 for (i = 1; i < countof(points); i += 4)
481 GLfloat x = points[i][0] / 255.0L;
482 GLfloat y = points[i][1] / 255.0L;
484 glVertex3f(x-0.5, y-0.5, 0.5);
489 /* Central core bottom cap.
491 #ifdef HAVE_GLBINDTEXTURE
492 glBindTexture(GL_TEXTURE_2D, 0);
493 #endif /* HAVE_GLBINDTEXTURE */
494 set_colors(interior_color);
496 i = countof(points) - 9;
497 do_normal(points[i+0][0], points[i+0][1], 0,
498 points[i+4][0], points[i+4][1], 0,
499 points[i+8][0], points[i+8][1], 0);
501 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
502 for (i = countof(points) - 3; i >= 0; i -= 4)
504 GLfloat x = points[i][0] / 255.0L;
505 GLfloat y = points[i][1] / 255.0L;
506 glVertex3f(x-0.5, y-0.5, 0);
511 /* Central core walls.
513 for (i = 1; i < countof(points); i += 4)
516 GLfloat x1 = points[i-1][0] / 255.0L;
517 GLfloat y1 = points[i-1][1] / 255.0L;
518 GLfloat x2 = points[i][0] / 255.0L;
519 GLfloat y2 = points[i][1] / 255.0L;
520 face4(0, interior_color, wire,
521 0.0, 0.0, x1-0.5, y1-0.5, 0.5,
522 0.0, 0.0, x1-0.5, y1-0.5, 0.0,
523 0.0, 0.0, x2-0.5, y2-0.5, 0.0,
524 0.0, 0.0, x2-0.5, y2-0.5, 0.5);
532 tetra(ModeInfo *mi, Bool wire)
534 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
536 glNewList(lc->tetra_une, GL_COMPILE);
538 glShadeModel(GL_SMOOTH);
541 face3(lc->texids[FACE_U], exterior_color, wire,
542 1.0, 0.0, 0.5, -0.5, 0.5,
543 1.0, 1.0, 0.5, 0.5, 0.5,
544 0.0, 1.0, -0.5, 0.5, 0.5);
547 face3(lc->texids[FACE_N], exterior_color, wire,
548 0.0, 0.0, -0.5, 0.5, 0.5,
549 1.0, 0.0, 0.5, 0.5, 0.5,
550 1.0, 1.0, 0.5, 0.5, -0.5);
553 face3(lc->texids[FACE_E], exterior_color, wire,
554 1.0, 0.0, 0.5, 0.5, -0.5,
555 1.0, 1.0, 0.5, 0.5, 0.5,
556 0.0, 1.0, 0.5, -0.5, 0.5);
558 face3(0, interior_color, wire,
559 0.0, 0.0, 0.5, 0.5, -0.5,
560 0.0, 0.0, 0.5, -0.5, 0.5,
561 0.0, 0.0, -0.5, 0.5, 0.5);
565 glNewList(lc->tetra_usw, GL_COMPILE);
568 face3(lc->texids[FACE_U], exterior_color, wire,
569 0.0, 1.0, -0.5, 0.5, 0.5,
570 0.0, 0.0, -0.5, -0.5, 0.5,
571 1.0, 0.0, 0.5, -0.5, 0.5);
574 face3(lc->texids[FACE_S], exterior_color, wire,
575 1.0, 1.0, 0.5, -0.5, 0.5,
576 0.0, 1.0, -0.5, -0.5, 0.5,
577 0.0, 0.0, -0.5, -0.5, -0.5);
580 face3(lc->texids[FACE_W], exterior_color, wire,
581 1.0, 0.0, -0.5, -0.5, -0.5,
582 1.0, 1.0, -0.5, -0.5, 0.5,
583 0.0, 1.0, -0.5, 0.5, 0.5);
585 face3(0, interior_color, wire,
586 0.0,0.0, -0.5, -0.5, -0.5,
587 0.0,0.0, -0.5, 0.5, 0.5,
588 0.0,0.0, 0.5, -0.5, 0.5);
592 glNewList(lc->tetra_dwn, GL_COMPILE);
595 face3(lc->texids[FACE_D], exterior_color, wire,
596 0.0, 1.0, -0.5, -0.5, -0.5,
597 0.0, 0.0, -0.5, 0.5, -0.5,
598 1.0, 0.0, 0.5, 0.5, -0.5);
601 face3(lc->texids[FACE_W], exterior_color, wire,
602 0.0, 1.0, -0.5, 0.5, 0.5,
603 0.0, 0.0, -0.5, 0.5, -0.5,
604 1.0, 0.0, -0.5, -0.5, -0.5);
607 face3(lc->texids[FACE_N], exterior_color, wire,
608 1.0, 1.0, 0.5, 0.5, -0.5,
609 0.0, 1.0, -0.5, 0.5, -0.5,
610 0.0, 0.0, -0.5, 0.5, 0.5);
612 face3(0, interior_color, wire,
613 0.0, 0.0, 0.5, 0.5, -0.5,
614 0.0, 0.0, -0.5, 0.5, 0.5,
615 0.0, 0.0, -0.5, -0.5, -0.5);
619 glNewList(lc->tetra_dse, GL_COMPILE);
622 face3(lc->texids[FACE_S], exterior_color, wire,
623 0.0, 0.0, -0.5, -0.5, -0.5,
624 1.0, 0.0, 0.5, -0.5, -0.5,
625 1.0, 1.0, 0.5, -0.5, 0.5);
628 face3(lc->texids[FACE_E], exterior_color, wire,
629 0.0, 1.0, 0.5, -0.5, 0.5,
630 0.0, 0.0, 0.5, -0.5, -0.5,
631 1.0, 0.0, 0.5, 0.5, -0.5);
634 face3(lc->texids[FACE_D], exterior_color, wire,
635 1.0, 0.0, 0.5, 0.5, -0.5,
636 1.0, 1.0, 0.5, -0.5, -0.5,
637 0.0, 1.0, -0.5, -0.5, -0.5);
639 face3(0, interior_color, wire,
640 0.0, 0.0, 0.5, -0.5, 0.5,
641 0.0, 0.0, 0.5, 0.5, -0.5,
642 0.0, 0.0, -0.5, -0.5, -0.5);
646 glNewList(lc->tetra_mid, GL_COMPILE);
648 face3(0, interior_color, wire,
649 0.0, 0.0, 0.5, -0.5, 0.5,
650 0.0, 0.0, 0.5, 0.5, -0.5,
651 0.0, 0.0, -0.5, 0.5, 0.5);
653 face3(0, interior_color, wire,
654 0.0, 0.0, -0.5, 0.5, 0.5,
655 0.0, 0.0, -0.5, -0.5, -0.5,
656 0.0, 0.0, 0.5, -0.5, 0.5);
658 face3(0, interior_color, wire,
659 0.0, 0.0, -0.5, 0.5, 0.5,
660 0.0, 0.0, 0.5, 0.5, -0.5,
661 0.0, 0.0, -0.5, -0.5, -0.5);
663 face3(0, interior_color, wire,
664 0.0, 0.0, 0.5, 0.5, -0.5,
665 0.0, 0.0, 0.5, -0.5, 0.5,
666 0.0, 0.0, -0.5, -0.5, -0.5);
668 face3(0, interior_color, wire,
669 0.0, 0.0, 0.5, -0.5, 0.5,
670 0.0, 0.0, 0.5, 0.5, -0.5,
671 0.0, 0.0, -0.5, -0.5, -0.5);
678 lid(ModeInfo *mi, Bool wire)
680 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
684 { 128, 20 },{ 21, 129 },{ 0, 129 },{ 0, 0 },{ 128, 0 }, /* L1 */
685 { 21, 129 },{ 127, 234 },{ 127, 255 },{ 0, 255 },{ 0, 129 }, /* L2 */
686 { 127, 234 },{ 233, 127 },{ 255, 127 },{ 255, 255 },{ 127, 255 }, /* R2 */
687 { 233, 127 },{ 128, 20 },{ 128, 0 },{ 255, 0 },{ 255, 127 }, /* R1 */
690 for (i = 0; i < countof(points); i++)
691 points[i][1] = 255-points[i][1];
693 glNewList(lc->lid_0, GL_COMPILE);
694 glShadeModel(GL_SMOOTH);
697 face4(lc->texids[FACE_N], exterior_color, wire,
698 0.0, 0.0, -0.5, 0.5, 0.5,
699 1.0, 0.0, 0.5, 0.5, 0.5,
700 1.0, 1.0, 0.5, 0.5, -0.5,
701 0.0, 1.0, -0.5, 0.5, -0.5);
704 face4(lc->texids[FACE_S], exterior_color, wire,
705 0.0, 0.0, -0.5, -0.5, -0.5,
706 1.0, 0.0, 0.5, -0.5, -0.5,
707 1.0, 1.0, 0.5, -0.5, 0.5,
708 0.0, 1.0, -0.5, -0.5, 0.5);
711 face4(lc->texids[FACE_E], exterior_color, wire,
712 0.0, 0.0, 0.5, -0.5, -0.5,
713 1.0, 0.0, 0.5, 0.5, -0.5,
714 1.0, 1.0, 0.5, 0.5, 0.5,
715 0.0, 1.0, 0.5, -0.5, 0.5);
718 face4(lc->texids[FACE_U], exterior_color, wire,
719 1.0, 0.0, 0.5, -0.5, 0.5,
720 1.0, 1.0, 0.5, 0.5, 0.5,
721 0.0, 1.0, -0.5, 0.5, 0.5,
722 0.0, 0.0, -0.5, -0.5, 0.5);
725 face4(lc->texids[FACE_D], exterior_color, wire,
726 0.0, 1.0, -0.5, -0.5, -0.5,
727 0.0, 0.0, -0.5, 0.5, -0.5,
728 1.0, 0.0, 0.5, 0.5, -0.5,
729 1.0, 1.0, 0.5, -0.5, -0.5);
732 for (i = 0; i < countof(points)/5; i++)
735 GLfloat s[5], t[5], x[5], y[5], z[5];
736 for (j = 0; j < 5; j++)
738 GLfloat xx = points[(i*5)+j][0] / 255.0L;
739 GLfloat yy = points[(i*5)+j][1] / 255.0L;
746 face5(lc->texids[FACE_W], exterior_color, wire,
747 s[0], t[0], x[0], y[0], z[0],
748 s[1], t[1], x[1], y[1], z[1],
749 s[2], t[2], x[2], y[2], z[2],
750 s[3], t[3], x[3], y[3], z[3],
751 s[4], t[4], x[4], y[4], z[4]);
756 /* W -- lid_1 through lid_4 */
757 for (i = 0; i < 4; i++)
759 GLfloat x1, y1, x2, y2, x3, y3;
761 glNewList(lc->lid_1 + i, GL_COMPILE);
762 glShadeModel(GL_SMOOTH);
764 x1 = points[(i*5)+1][0] / 255.0L;
765 y1 = points[(i*5)+1][1] / 255.0L;
766 x2 = points[(i*5)][0] / 255.0L;
767 y2 = points[(i*5)][1] / 255.0L;
772 face3(lc->texids[FACE_W], exterior_color, wire,
773 1.0-x1, y1, -0.5, x1-0.5, y1-0.5,
774 1.0-x2, y2, -0.5, x2-0.5, y2-0.5,
775 1.0-x3, y3, -0.5, x3-0.5, y3-0.5);
778 face3(0, interior_color, wire,
779 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
780 0.0, 0.0, -0.48, x1-0.5, y1-0.5,
781 0.0, 0.0, -0.48, x3-0.5, y3-0.5);
784 face4(0, interior_color, wire,
785 0.0, 0.0, -0.5, x1-0.5, y1-0.5,
786 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
787 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
788 0.0, 0.0, -0.48, x1-0.5, y1-0.5);
791 face4(0, interior_color, wire,
792 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
793 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
794 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
795 0.0, 0.0, -0.5, x2-0.5, y2-0.5);
802 taser(ModeInfo *mi, Bool wire)
804 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
807 int slider_face_points[][2] = {
808 { 86, 58 },{ 38, 106 },{ 70, 106 },{ 118, 58 },{ -1, -1 }, /* a */
809 { 136, 58 },{ 184, 106 },{ 216, 106 },{ 168, 58 },{ -1, -1 }, /* b */
810 { 38, 106 },{ 0, 144 },{ 0, 190 },{ 60, 190 },{ 108, 106 }, /* c */
811 { 144, 106 },{ 194, 190 },{ 254, 190 },{ 254, 144 },{ 216, 106 }, /* d */
812 { 98, 124 },{ 60, 190 },{ 92, 190 },{ 126, 158 },{ 126, 124 }, /* e */
813 { 126, 124 },{ 126, 158 },{ 160, 190 },{ 194, 190 },{ 154, 124 }, /* f */
814 { 22, 190 },{ 22, 254 },{ 60, 254 },{ 60, 190 },{ -1, -1 }, /* g */
815 { 194, 190 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ -1, -1 }, /* h */
816 { 60, 190 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ -1, -1 }, /* i */
817 { 160, 190 },{ 160, 210 },{ 194, 210 },{ 194, 190 },{ -1, -1 }, /* j */
818 { 110, 172 },{ 92, 190 },{ 110, 190 },{ -1, -1 },{ -1, -1 }, /* k */
819 { 140, 172 },{ 140, 190 },{ 160, 190 },{ -1, -1 },{ -1, -1 }, /* l */
820 { 110, 172 },{ 140, 172 },{ 126, 156 },{ -1, -1 },{ -1, -1 }, /* m */
823 int body_face_points[][2] = {
824 { 0, 0 },{ 0, 58 },{ 254, 58 },{ 254, 0 },{ -1, -1 }, /* A */
825 { 0, 58 },{ 0, 144 },{ 86, 58 },{ -1, -1 },{ -1, -1 }, /* B */
826 { 168, 58 },{ 254, 144 },{ 254, 58 },{ -1, -1 },{ -1, -1 }, /* C */
827 { 118, 58 },{ 70, 106 },{ 184, 106 },{ 136, 58 },{ -1, -1 }, /* F */
828 { 108, 106 },{ 98, 124 },{ 154, 124 },{ 144, 106 },{ -1, -1 }, /* G */
831 int lifter_face_points[][2] = {
832 { 0, 190 },{ 0, 254 },{ 22, 254 },{ 22, 190 },{ -1, -1 }, /* D */
833 { 230, 190 },{ 230, 254 },{ 254, 254 },{ 254, 190 },{ -1, -1 }, /* E */
834 { 60, 210 },{ 60, 254 },{ 194, 254 },{ 194, 210 },{ -1, -1 }, /* H */
835 { 92, 190 },{ 92, 210 },{ 160, 210 },{ 160, 190 },{ -1, -1 }, /* I */
836 { 110, 172 },{ 110, 190 },{ 140, 190 },{ 140, 172 },{ -1, -1 }, /* J */
839 int body_perimiter_points[][2] = {
840 { 0, 144 },{ 86, 59 },{ 119, 58 },{ 71, 107 },
841 { 108, 107 },{ 98, 124 },{ 155, 124 },{ 144, 107 },
842 { 185, 106 },{ 136, 59 },{ 169, 59 },{ 255, 145 },
846 int slider_perimiter_points[][2] = {
847 { 86, 58 },{ 0, 144 },{ 0, 190 },{ 22, 190 },{ 22, 254 },
848 { 60, 254 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ 110, 190 },
849 { 110, 172 },{ 140, 172 },{ 140, 190 },{ 160, 190 },{ 160, 210 },
850 { 194, 210 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ 254, 190 },
851 { 254, 144 },{ 168, 58 },{ 136, 58 },{ 184, 106 },{ 144, 106 },
852 { 154, 124 },{ 98, 124 },{ 108, 106 },{ 70, 106 },{ 118, 58 },
855 int lifter_perimiter_points_1[][2] = {
856 { 0, 189 },{ 0, 254 },{ 22, 255 },{ 23, 190 },
859 int lifter_perimiter_points_2[][2] = {
860 { 230, 254 },{ 255, 255 },{ 254, 190 },{ 230, 190 },
863 int lifter_perimiter_points_3[][2] = {
864 { 60, 254 },{ 194, 254 },{ 194, 211 },{ 160, 210 },
865 { 160, 190 },{ 140, 191 },{ 141, 172 },{ 111, 172 },
866 { 110, 190 },{ 93, 190 },{ 92, 210 },{ 60, 211 },
869 for (i = 0; i < countof(slider_face_points); i++)
870 slider_face_points[i][1] = 255-slider_face_points[i][1];
871 for (i = 0; i < countof(body_face_points); i++)
872 body_face_points[i][1] = 255-body_face_points[i][1];
873 for (i = 0; i < countof(lifter_face_points); i++)
874 lifter_face_points[i][1] = 255-lifter_face_points[i][1];
875 for (i = 0; i < countof(body_perimiter_points); i++)
876 body_perimiter_points[i][1] = 255-body_perimiter_points[i][1];
877 for (i = 0; i < countof(slider_perimiter_points); i++)
878 slider_perimiter_points[i][1] = 255-slider_perimiter_points[i][1];
879 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
880 lifter_perimiter_points_1[i][1] = 255-lifter_perimiter_points_1[i][1];
881 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
882 lifter_perimiter_points_2[i][1] = 255-lifter_perimiter_points_2[i][1];
883 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
884 lifter_perimiter_points_3[i][1] = 255-lifter_perimiter_points_3[i][1];
886 /* -------------------------------------------------------------------- */
888 glNewList(lc->taser_base, GL_COMPILE);
889 glShadeModel(GL_SMOOTH);
892 face4(lc->texids[FACE_N], exterior_color, wire,
893 0.0, 0.0, -0.5, 0.5, 0.5,
894 0.75, 0.0, 0.25, 0.5, 0.5,
895 0.75, 0.75, 0.25, 0.5, -0.25,
896 0.0, 0.75, -0.5, 0.5, -0.25);
899 face4(lc->texids[FACE_S], exterior_color, wire,
900 0.0, 0.25, -0.5, -0.5, -0.25,
901 0.75, 0.25, 0.25, -0.5, -0.25,
902 0.75, 1.0, 0.25, -0.5, 0.5,
903 0.0, 1.0, -0.5, -0.5, 0.5);
906 face4(0, interior_color, wire,
907 0.0, 0.0, 0.25, -0.5, -0.25,
908 1.0, 0.0, 0.25, 0.5, -0.25,
909 1.0, 1.0, 0.25, 0.5, 0.5,
910 0.0, 1.0, 0.25, -0.5, 0.5);
913 face4(lc->texids[FACE_W], exterior_color, wire,
914 1.0, 1.0, -0.5, -0.5, 0.5,
915 0.0, 1.0, -0.5, 0.5, 0.5,
916 0.0, 0.25, -0.5, 0.5, -0.25,
917 1.0, 0.25, -0.5, -0.5, -0.25);
920 face4(lc->texids[FACE_U], exterior_color, wire,
921 0.75, 0.0, 0.25, -0.5, 0.5,
922 0.75, 1.0, 0.25, 0.5, 0.5,
923 0.0, 1.0, -0.5, 0.5, 0.5,
924 0.0, 0.0, -0.5, -0.5, 0.5);
927 face4(0, interior_color, wire,
928 0.0, 1.0, -0.5, -0.5, -0.25,
929 0.0, 0.0, -0.5, 0.5, -0.25,
930 1.0, 0.0, 0.25, 0.5, -0.25,
931 1.0, 1.0, 0.25, -0.5, -0.25);
934 for (i = 0; i < countof(body_face_points)/5; i++)
937 #ifdef HAVE_GLBINDTEXTURE
938 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
939 #endif /* HAVE_GLBINDTEXTURE */
940 set_colors(exterior_color);
942 do_normal(0, body_face_points[(i*5)+0][0], body_face_points[(i*5)+0][1],
943 0, body_face_points[(i*5)+1][0], body_face_points[(i*5)+1][1],
944 0, body_face_points[(i*5)+2][0], body_face_points[(i*5)+2][1]
946 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
947 for (j = 0; j < 5; j++)
949 int ix = body_face_points[(i*5)+j][0];
950 int iy = body_face_points[(i*5)+j][1];
952 if (ix == -1) /* these are padding: ignore them */
957 glVertex3f(0.5, x-0.5, y-0.5);
963 for (i = 0; i < countof(body_perimiter_points); i++)
965 int j = (i+1 >= countof(body_perimiter_points) ? 0 : i+1);
966 GLfloat x1 = body_perimiter_points[i][0] / 255.0;
967 GLfloat y1 = body_perimiter_points[i][1] / 255.0;
968 GLfloat x2 = body_perimiter_points[j][0] / 255.0;
969 GLfloat y2 = body_perimiter_points[j][1] / 255.0;
971 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
975 texture = lc->texids[FACE_N];
977 s2 = 1.0; t2 = 0.568;
978 s3 = 0.75, t3 = 0.568;
983 texture = lc->texids[FACE_U];
991 texture = lc->texids[FACE_S];
992 s1 = 1.0; t1 = 0.437;
995 s4 = 0.75; t4 = 0.437;
998 face4((texture == -1 ? 0 : texture),
999 (texture == -1 ? interior_color : exterior_color),
1001 s1, t1, 0.5, x2-0.5, y2-0.5,
1002 s2, t2, 0.5, x1-0.5, y1-0.5,
1003 s3, t3, 0.25, x1-0.5, y1-0.5,
1004 s4, t4, 0.25, x2-0.5, y2-0.5);
1009 /* -------------------------------------------------------------------- */
1011 glNewList(lc->taser_lifter, GL_COMPILE);
1012 glShadeModel(GL_SMOOTH);
1015 face4(lc->texids[FACE_N], exterior_color, wire,
1016 0.0, 0.75, -0.5, 0.5, -0.25,
1017 0.75, 0.75, 0.25, 0.5, -0.25,
1018 0.75, 1.0, 0.25, 0.5, -0.5,
1019 0.0, 1.0, -0.5, 0.5, -0.5);
1022 face4(lc->texids[FACE_S], exterior_color, wire,
1023 0.0, 0.0, -0.5, -0.5, -0.5,
1024 0.75, 0.0, 0.25, -0.5, -0.5,
1025 0.75, 0.25, 0.25, -0.5, -0.25,
1026 0.0, 0.25, -0.5, -0.5, -0.25);
1029 face4(0, interior_color, wire,
1030 0.0, 1.0, 0.25, -0.5, -0.5,
1031 1.0, 1.0, 0.25, 0.5, -0.5,
1032 1.0, 0.0, 0.25, 0.5, -0.25,
1033 0.0, 0.0, 0.25, -0.5, -0.25);
1036 face4(lc->texids[FACE_W], exterior_color, wire,
1037 1.0, 0.25, -0.5, -0.5, -0.25,
1038 0.0, 0.25, -0.5, 0.5, -0.25,
1039 0.0, 0.0, -0.5, 0.5, -0.5,
1040 1.0, 0.0, -0.5, -0.5, -0.5);
1043 face4(0, interior_color, wire,
1044 1.0, 0.0, 0.25, -0.5, -0.25,
1045 1.0, 1.0, 0.25, 0.5, -0.25,
1046 0.0, 1.0, -0.5, 0.5, -0.25,
1047 0.0, 0.0, -0.5, -0.5, -0.25);
1050 face4(lc->texids[FACE_D], exterior_color, wire,
1051 0.0, 1.0, -0.5, -0.5, -0.5,
1052 0.0, 0.0, -0.5, 0.5, -0.5,
1053 0.75, 0.0, 0.25, 0.5, -0.5,
1054 0.75, 1.0, 0.25, -0.5, -0.5);
1058 for (i = 0; i < countof(lifter_face_points)/5; i++)
1062 #ifdef HAVE_GLBINDTEXTURE
1063 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1064 #endif /* HAVE_GLBINDTEXTURE */
1065 set_colors(exterior_color);
1068 0, lifter_face_points[(i*5)+0][0], lifter_face_points[(i*5)+0][1],
1069 0, lifter_face_points[(i*5)+1][0], lifter_face_points[(i*5)+1][1],
1070 0, lifter_face_points[(i*5)+2][0], lifter_face_points[(i*5)+2][1]);
1072 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1073 for (j = 0; j < 5; j++)
1075 int ix = lifter_face_points[(i*5)+j][0];
1076 int iy = lifter_face_points[(i*5)+j][1];
1078 if (ix == -1) /* these are padding: ignore them */
1083 glVertex3f(0.5, x-0.5, y-0.5);
1089 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
1091 int j = (i+1 >= countof(lifter_perimiter_points_1) ? 0 : i+1);
1092 GLfloat x1 = lifter_perimiter_points_1[i][0] / 255.0;
1093 GLfloat y1 = lifter_perimiter_points_1[i][1] / 255.0;
1094 GLfloat x2 = lifter_perimiter_points_1[j][0] / 255.0;
1095 GLfloat y2 = lifter_perimiter_points_1[j][1] / 255.0;
1097 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1101 texture = lc->texids[FACE_S];
1103 s2 = 1.0; t2 = 0.26;
1104 s3 = 0.75, t3 = 0.26;
1105 s4 = 0.75; t4 = 0.0;
1109 texture = lc->texids[FACE_D];
1110 s1 = 1.0; t1 = 0.914;
1112 s3 = 0.75; t3 = 1.0;
1113 s4 = 0.75; t4 = 0.914;
1116 face4((texture == -1 ? 0 : texture),
1117 (texture == -1 ? interior_color : exterior_color),
1119 s1, t1, 0.5, x2-0.5, y2-0.5,
1120 s2, t2, 0.5, x1-0.5, y1-0.5,
1121 s3, t3, 0.25, x1-0.5, y1-0.5,
1122 s4, t4, 0.25, x2-0.5, y2-0.5);
1125 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
1127 int j = (i+1 >= countof(lifter_perimiter_points_2) ? 0 : i+1);
1128 GLfloat x1 = lifter_perimiter_points_2[i][0] / 255.0;
1129 GLfloat y1 = lifter_perimiter_points_2[i][1] / 255.0;
1130 GLfloat x2 = lifter_perimiter_points_2[j][0] / 255.0;
1131 GLfloat y2 = lifter_perimiter_points_2[j][1] / 255.0;
1133 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1137 texture = lc->texids[FACE_D];
1139 s2 = 1.0; t2 = 0.095;
1140 s3 = 0.75; t3 = 0.095;
1141 s4 = 0.75; t4 = 0.0;
1145 texture = lc->texids[FACE_N];
1146 s1 = 1.0; t1 = 0.745;
1148 s3 = 0.75; t3 = 1.0;
1149 s4 = 0.75; t4 = 0.745;
1152 face4((texture == -1 ? 0 : texture),
1153 (texture == -1 ? interior_color : exterior_color),
1155 s1, t1, 0.5, x2-0.5, y2-0.5,
1156 s2, t2, 0.5, x1-0.5, y1-0.5,
1157 s3, t3, 0.25, x1-0.5, y1-0.5,
1158 s4, t4, 0.25, x2-0.5, y2-0.5);
1161 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
1163 int j = (i+1 >= countof(lifter_perimiter_points_3) ? 0 : i+1);
1164 GLfloat x1 = lifter_perimiter_points_3[i][0] / 255.0;
1165 GLfloat y1 = lifter_perimiter_points_3[i][1] / 255.0;
1166 GLfloat x2 = lifter_perimiter_points_3[j][0] / 255.0;
1167 GLfloat y2 = lifter_perimiter_points_3[j][1] / 255.0;
1169 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1173 texture = lc->texids[FACE_D];
1174 s1 = 1.0; t1 = 0.235;
1175 s2 = 1.0; t2 = 0.765;
1176 s3 = 0.75; t3 = 0.765;
1177 s4 = 0.75; t4 = 0.235;
1180 face4((texture == -1 ? 0 : texture),
1181 (texture == -1 ? interior_color : exterior_color),
1183 s1, t1, 0.5, x2-0.5, y2-0.5,
1184 s2, t2, 0.5, x1-0.5, y1-0.5,
1185 s3, t3, 0.25, x1-0.5, y1-0.5,
1186 s4, t4, 0.25, x2-0.5, y2-0.5);
1191 /* -------------------------------------------------------------------- */
1193 glNewList(lc->taser_slider, GL_COMPILE);
1194 glShadeModel(GL_SMOOTH);
1197 for (i = 0; i < countof(slider_face_points)/5; i++)
1200 #ifdef HAVE_GLBINDTEXTURE
1201 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1202 #endif /* HAVE_GLBINDTEXTURE */
1203 set_colors(exterior_color);
1206 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1],
1207 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1208 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1]);
1209 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1210 for (j = 0; j < 5; j++)
1212 int ix = slider_face_points[(i*5)+j][0];
1213 int iy = slider_face_points[(i*5)+j][1];
1215 if (ix == -1) /* these are padding: ignore them */
1220 glVertex3f(0.5, x-0.5, y-0.5);
1226 for (i = countof(slider_face_points)/5 - 1; i >= 0; i--)
1229 #ifdef HAVE_GLBINDTEXTURE
1230 glBindTexture(GL_TEXTURE_2D, 0);
1231 #endif /* HAVE_GLBINDTEXTURE */
1232 set_colors(interior_color);
1235 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1],
1236 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1237 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1]);
1238 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1239 for (j = 4; j >= 0; j--)
1241 int ix = slider_face_points[(i*5)+j][0];
1242 int iy = slider_face_points[(i*5)+j][1];
1244 if (ix == -1) /* these are padding: ignore them */
1249 glVertex3f(0.25, x-0.5, y-0.5);
1255 for (i = 0; i < countof(slider_perimiter_points); i++)
1257 int j = (i+1 >= countof(slider_perimiter_points) ? 0 : i+1);
1258 GLfloat x1 = slider_perimiter_points[i][0] / 255.0;
1259 GLfloat y1 = slider_perimiter_points[i][1] / 255.0;
1260 GLfloat x2 = slider_perimiter_points[j][0] / 255.0;
1261 GLfloat y2 = slider_perimiter_points[j][1] / 255.0;
1263 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1267 texture = lc->texids[FACE_S];
1268 s1 = 1.0; t1 = 0.255;
1269 s2 = 1.0; t2 = 0.435;
1270 s3 = 0.75; t3 = 0.435;
1271 s4 = 0.75; t4 = 0.255;
1275 texture = lc->texids[FACE_D];
1276 s1 = 1.0; t1 = 0.758;
1277 s2 = 1.0; t2 = 0.915;
1278 s3 = 0.75; t3 = 0.915;
1279 s4 = 0.75; t4 = 0.758;
1283 texture = lc->texids[FACE_D];
1284 s1 = 1.0; t1 = 0.095;
1285 s2 = 1.0; t2 = 0.24;
1286 s3 = 0.75; t3 = 0.24;
1287 s4 = 0.75; t4 = 0.095;
1291 texture = lc->texids[FACE_N];
1292 s1 = 1.0; t1 = 0.568;
1293 s2 = 1.0; t2 = 0.742;
1294 s3 = 0.75; t3 = 0.742;
1295 s4 = 0.75; t4 = 0.568;
1298 face4((texture == -1 ? 0 : texture),
1299 (texture == -1 ? interior_color : exterior_color),
1301 s1, t1, 0.5, x2-0.5, y2-0.5,
1302 s2, t2, 0.5, x1-0.5, y1-0.5,
1303 s3, t3, 0.25, x1-0.5, y1-0.5,
1304 s4, t4, 0.25, x2-0.5, y2-0.5);
1312 /* Rendering and animating object models
1316 lament_handle_event (ModeInfo *mi, XEvent *event)
1318 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1320 if (event->xany.type == ButtonPress &&
1321 event->xbutton.button == Button1)
1323 lc->button_down_p = True;
1324 gltrackball_start (lc->trackball,
1325 event->xbutton.x, event->xbutton.y,
1326 MI_WIDTH (mi), MI_HEIGHT (mi));
1329 else if (event->xany.type == ButtonRelease &&
1330 event->xbutton.button == Button1)
1332 lc->button_down_p = False;
1335 else if (event->xany.type == ButtonPress &&
1336 (event->xbutton.button == Button4 ||
1337 event->xbutton.button == Button5 ||
1338 event->xbutton.button == Button6 ||
1339 event->xbutton.button == Button7))
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);
1522 /* Rather than just picking states randomly, pick an ordering randomly, do it,
1523 and then re-randomize. That way one can be assured of seeing all states in
1524 a short time period, though not always in the same order (it's frustrating
1525 to see it pick the same state 5x in a row.)
1528 shuffle_states (lament_configuration *lc)
1531 for (i = 0; i < lc->nstates; i++)
1533 int a = random() % lc->nstates;
1534 lament_type swap = lc->states[a];
1535 lc->states[a] = lc->states[i];
1536 lc->states[i] = swap;
1542 animate(ModeInfo *mi)
1544 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1546 /* int pause2 = 60;*/
1554 if (lc->state >= lc->nstates)
1556 shuffle_states (lc);
1559 lc->type = lc->states[lc->state];
1561 if (lc->type == LAMENT_BOX)
1562 lc->anim_pause = pause3;
1570 /* -------------------------------------------------------------- */
1572 case LAMENT_STAR_OUT:
1574 if (lc->anim_z >= 1.0)
1577 lc->type = LAMENT_STAR_ROT;
1578 lc->anim_pause = pause;
1582 case LAMENT_STAR_ROT:
1584 if (lc->anim_r >= 45.0)
1587 lc->type = LAMENT_STAR_ROT_IN;
1588 lc->anim_pause = pause;
1592 case LAMENT_STAR_ROT_IN:
1594 if (lc->anim_z <= 0.0)
1597 lc->type = LAMENT_STAR_ROT_OUT;
1598 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1602 case LAMENT_STAR_ROT_OUT:
1604 if (lc->anim_z >= 1.0)
1607 lc->type = LAMENT_STAR_UNROT;
1608 lc->anim_pause = pause;
1612 case LAMENT_STAR_UNROT:
1614 if (lc->anim_r <= 0.0)
1617 lc->type = LAMENT_STAR_IN;
1618 lc->anim_pause = pause;
1622 case LAMENT_STAR_IN:
1624 if (lc->anim_z <= 0.0)
1627 lc->type = LAMENT_BOX;
1628 lc->anim_pause = pause3;
1632 /* -------------------------------------------------------------- */
1634 case LAMENT_TETRA_UNE:
1635 case LAMENT_TETRA_USW:
1636 case LAMENT_TETRA_DWN:
1637 case LAMENT_TETRA_DSE:
1640 if (lc->anim_r >= 360.0)
1643 lc->type = LAMENT_BOX;
1644 lc->anim_pause = pause3;
1646 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1649 lc->anim_pause = pause;
1651 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1654 lc->anim_pause = pause;
1658 /* -------------------------------------------------------------- */
1660 case LAMENT_LID_OPEN:
1663 if (lc->anim_r >= 112.0)
1665 GLfloat hysteresis = 0.05;
1669 lc->anim_pause = pause3;
1671 if (lc->rotx >= -hysteresis &&
1672 lc->rotx <= hysteresis &&
1673 ((lc->rotz >= (0.25 - hysteresis) &&
1674 lc->rotz <= (0.25 + hysteresis)) ||
1675 (lc->rotz >= (-0.25 - hysteresis) &&
1676 lc->rotz <= (-0.25 + hysteresis))))
1678 lc->type = LAMENT_LID_ZOOM;
1680 lc->rotz = (lc->rotz < 0 ? -0.25 : 0.25);
1684 lc->type = LAMENT_LID_CLOSE;
1689 case LAMENT_LID_CLOSE:
1691 if (lc->anim_r <= 0.0)
1694 lc->type = LAMENT_BOX;
1695 lc->anim_pause = pause3;
1699 case LAMENT_LID_ZOOM:
1701 if (lc->anim_z < -50.0)
1705 lc->type = LAMENT_BOX;
1709 /* -------------------------------------------------------------- */
1711 case LAMENT_TASER_OUT:
1712 lc->anim_z += 0.0025;
1713 if (lc->anim_z >= 0.25)
1716 lc->type = LAMENT_TASER_SLIDE;
1717 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1721 case LAMENT_TASER_SLIDE:
1722 lc->anim_y += 0.0025;
1723 if (lc->anim_y >= 0.23)
1726 lc->type = LAMENT_TASER_SLIDE_IN;
1727 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1731 case LAMENT_TASER_SLIDE_IN:
1732 lc->anim_y -= 0.0025;
1733 if (lc->anim_y <= 0.0)
1736 lc->type = LAMENT_TASER_IN;
1737 lc->anim_pause = pause;
1741 case LAMENT_TASER_IN:
1742 lc->anim_z -= 0.0025;
1743 if (lc->anim_z <= 0.0)
1746 lc->type = LAMENT_BOX;
1747 lc->anim_pause = pause3;
1759 /* Window management, etc
1763 reshape_lament(ModeInfo *mi, int width, int height)
1765 int target_size = 180;
1766 int win_size = (width > height ? height : width);
1767 GLfloat h = (GLfloat) height / (GLfloat) width;
1769 glViewport(0, 0, (GLint) width, (GLint) height);
1771 /* glViewport(-600, -600, 1800, 1800); */
1773 glMatrixMode(GL_PROJECTION);
1775 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1776 glMatrixMode(GL_MODELVIEW);
1778 glTranslatef(0.0, 0.0, -40.0);
1780 /* This scale makes the box take up most of the window */
1781 glScalef(2.0, 2.0, 2.0);
1783 /* But if the window is more than a little larger than our target size,
1784 scale the object back down, so that the bits drawn on the screen end
1785 up rougly target_size across (actually it ends up a little larger.)
1786 Note that the image-map bits we have are 128x128. Therefore, if the
1787 image is magnified a lot, it looks pretty blocky. So it's better to
1788 have a 128x128 animation on a 1280x1024 screen that looks good, than
1789 a 1024x1024 animation that looks really pixelated.
1791 if (win_size > target_size * 1.5)
1793 GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
1795 glScalef(ratio, ratio, ratio);
1798 /* The depth buffer will be cleared, if needed, before the
1799 * next frame. Right now we just want to black the screen.
1801 glClear(GL_COLOR_BUFFER_BIT);
1806 gl_init(ModeInfo *mi)
1808 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1809 Bool wire = MI_IS_WIREFRAME(mi);
1816 static const GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1817 static const GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1819 static const GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1820 /* static const GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1821 static const GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1822 static const GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1824 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1825 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1827 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1828 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1829 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1830 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1831 set_colors(exterior_color);
1833 glEnable(GL_LIGHTING);
1834 glEnable(GL_LIGHT0);
1835 /* glEnable(GL_LIGHT1); */
1837 glEnable(GL_DEPTH_TEST);
1838 glEnable(GL_TEXTURE_2D);
1839 glEnable(GL_NORMALIZE);
1840 glEnable(GL_CULL_FACE);
1845 #ifdef HAVE_GLBINDTEXTURE
1847 for (i = 0; i < 6; i++)
1848 glGenTextures(1, &lc->texids[i]);
1850 parse_image_data(mi);
1852 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1853 glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width);
1855 for (i = 0; i < 6; i++)
1857 int height = lc->texture->width; /* assume square */
1858 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1859 set_colors(exterior_color);
1862 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1863 lc->texture->width, height, 0,
1865 /* GL_UNSIGNED_BYTE, */
1866 GL_UNSIGNED_INT_8_8_8_8_REV,
1867 (lc->texture->data +
1868 (lc->texture->bytes_per_line * height * i)));
1869 check_gl_error("texture");
1871 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1872 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1873 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1874 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1875 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1876 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1879 #else /* !HAVE_GLBINDTEXTURE */
1881 "%s: this version of GL doesn't support multiple texture maps.\n"
1882 "\tGet OpenGL 1.1.\n",
1885 #endif /* !HAVE_GLBINDTEXTURE */
1888 lc->box = glGenLists(16);
1889 lc->star1 = lc->box+1;
1890 lc->star2 = lc->box+2;
1891 lc->tetra_une = lc->box+3;
1892 lc->tetra_usw = lc->box+4;
1893 lc->tetra_dwn = lc->box+5;
1894 lc->tetra_dse = lc->box+6;
1895 lc->tetra_mid = lc->box+7;
1896 lc->lid_0 = lc->box+8;
1897 lc->lid_1 = lc->box+9;
1898 lc->lid_2 = lc->box+10;
1899 lc->lid_3 = lc->box+11;
1900 lc->lid_4 = lc->box+12;
1901 lc->taser_base = lc->box+13;
1902 lc->taser_lifter = lc->box+14;
1903 lc->taser_slider = lc->box+15;
1906 star(mi, True, wire);
1907 star(mi, False, wire);
1914 # ifdef HAVE_MESA_GL
1916 # include <signal.h>
1919 lament_signal_kludge (int sig)
1921 signal (sig, SIG_DFL);
1924 "%s: dying with signal %d (%s).\n"
1926 "\tThis is almost certainly a bug in the Mesa GL library,\n"
1927 "\tespecially if the stack trace in the core file mentions\n"
1928 "\t`lambda_textured_triangle' or `render_quad'.\n"
1930 "\tFirst make sure that you have the latest version of Mesa.\n"
1931 "\tIf that doesn't fix it, then I encourage you to report this\n"
1932 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
1936 (sig == SIGILL ? "SIGILL" :
1937 sig == SIGFPE ? "SIGFPE" :
1938 sig == SIGBUS ? "SIGBUS" :
1939 sig == SIGSEGV ? "SIGSEGV" : "???"));
1941 kill (getpid (), sig);
1945 handle_signals (void)
1947 signal (SIGILL, lament_signal_kludge);
1948 signal (SIGFPE, lament_signal_kludge);
1949 signal (SIGBUS, lament_signal_kludge);
1950 signal (SIGSEGV, lament_signal_kludge);
1952 # endif /* HAVE_MESA_GL */
1956 init_lament(ModeInfo *mi)
1958 lament_configuration *lc;
1961 lcs = (lament_configuration *)
1962 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
1965 fprintf(stderr, "%s: out of memory\n", progname);
1970 lc = &lcs[MI_SCREEN(mi)];
1973 double rot_speed = 0.5;
1974 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
1975 lc->trackball = gltrackball_init ();
1978 lc->type = LAMENT_BOX;
1979 lc->anim_pause = 300 + (random() % 100);
1981 if ((lc->glx_context = init_GL(mi)) != NULL)
1983 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1987 lc->states = (lament_type *) calloc (50, sizeof (*lc->states));
1989 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
1990 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
1991 lc->states[lc->nstates++] = LAMENT_TETRA_UNE;
1992 lc->states[lc->nstates++] = LAMENT_TETRA_USW;
1993 lc->states[lc->nstates++] = LAMENT_TETRA_DWN;
1994 lc->states[lc->nstates++] = LAMENT_TETRA_DSE;
1995 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
1996 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
1997 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
1998 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
1999 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2000 lc->states[lc->nstates++] = LAMENT_BOX;
2001 lc->states[lc->nstates++] = LAMENT_BOX;
2002 lc->states[lc->nstates++] = LAMENT_BOX;
2003 lc->states[lc->nstates++] = LAMENT_BOX;
2004 lc->states[lc->nstates++] = LAMENT_BOX;
2005 lc->states[lc->nstates++] = LAMENT_BOX;
2006 lc->states[lc->nstates++] = LAMENT_BOX;
2007 lc->states[lc->nstates++] = LAMENT_BOX;
2008 lc->states[lc->nstates++] = LAMENT_BOX;
2009 lc->states[lc->nstates++] = LAMENT_BOX;
2010 shuffle_states (lc);
2012 # ifdef HAVE_MESA_GL
2014 # endif /* HAVE_MESA_GL */
2019 draw_lament(ModeInfo *mi)
2021 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2022 Display *dpy = MI_DISPLAY(mi);
2023 Window window = MI_WINDOW(mi);
2025 if (!lc->glx_context)
2028 glDrawBuffer(GL_BACK);
2030 glXMakeCurrent(dpy, window, *(lc->glx_context));
2032 if (mi->fps_p) do_fps (mi);
2035 glXSwapBuffers(dpy, window);
2043 XSCREENSAVER_MODULE ("Lament", lament)