1 /* xscreensaver, Copyright (c) 1998-2014 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. Not sure why.
22 * Should use a dark wood-grain texture for the interior surfaces.
24 * Building a face out of multiple adjacent triangles was a terrible
25 idea and leads to visible seams. Should re-do the face generation
26 to make all of them out of a single triangle strip instead.
28 * The coordinates are slightly off from the image. lament512.gif is the
29 "right" one, and "lament512b.gif" is the image corrected to line up
30 with what the code is actually doing.
32 * The "star" slices really don't line up well.
34 * I want the gold leaf to seem to be raised up from the surface, but I
35 think this isn't possible with OpenGL. Supposedly, OpenGL only
36 supports Gouraud shading (interpolating edge normals from face normals,
37 and shading smoothly) but bump-maps only work with Phong shading
38 (computing a normal for each rendered pixel.)
40 * There should be strange lighting effects playing across the surface:
41 electric sparks, or little glittery blobs of light.
42 http://reality.sgi.com/opengl/tips/lensflare/ might provide guidance.
44 * Need to add some more modes, to effect the transition from the cube
45 shapes to the "spike" or "leviathan" shapes. I have extensive notes
46 on how these transformations occur, but unfortunately, due to camera
47 trickery, the transitions require dematerializations which do not
48 preserve object volume. But I suppose that's allowed, in
49 non-Euclidian or hyperdimensional spaces (since the extra mass could
50 simply be rotated along the axis to which one cannot point.)
52 The other hard thing about this is that the "leviathan" shapes contain
53 a much larger number of facets, and I modelled this whole thing by
54 hand, since I don't have any 3d-object-editing tools that I know how
55 to use (or that look like they would take any less than several months
56 to become even marginally proficient with...)
58 * Needs music. ("Hellraiser Themes" by Coil: TORSO CD161; also
59 duplicated on the "Unnatural History 2" compilation, WORLN M04699.)
62 #define DEFAULTS "*delay: 20000 \n" \
63 "*showFPS: False \n" \
64 "*wireframe: False \n"
65 # define refresh_lament 0
66 # define release_lament 0
67 #include "xlockmore.h"
69 #ifdef USE_GL /* whole file */
72 #define countof(x) (sizeof((x))/sizeof((*x)))
74 #define DEF_TEXTURE "True"
76 static int do_texture;
78 static XrmOptionDescRec opts[] = {
79 {"-texture", ".lament.texture", XrmoptionNoArg, "true" },
80 {"+texture", ".lament.texture", XrmoptionNoArg, "false" },
83 static argtype vars[] = {
84 {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
87 ENTRYPOINT ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL};
90 #include "xpm-ximage.h"
92 #include "gltrackball.h"
95 __extension__ /* don't warn about "string length is greater than the length
96 ISO C89 compilers are required to support" when including
97 the following XPM file... */
100 # include "../images/lament128.xpm"
102 # include "../images/lament512.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, 99 }, { 0, 74 }, { 0, 0 }, /* L1 */
334 { 60, 99 }, { 55, 127 }, { 0, 127 }, { 0, 74 }, /* 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 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1388 /* No texture created in -wireframe or -no-texture, so guess. */
1389 int target_size = (lc->texture
1390 ? lc->texture->width * 1.4
1392 int win_size = (MI_WIDTH(mi) > MI_HEIGHT(mi) ? MI_HEIGHT(mi) : MI_WIDTH(mi));
1394 /* This scale makes the box take up most of the window */
1397 /* But if the window is more than a little larger than our target size,
1398 scale the object back down, so that the bits drawn on the screen end
1399 up rougly target_size across (actually it ends up a little larger.)
1400 Note that the image-map bits we have are 128x128. Therefore, if the
1401 image is magnified a lot, it looks pretty blocky. So it's better to
1402 have a 128x128 animation on a 1280x1024 screen that looks good, than
1403 a 1024x1024 animation that looks really pixelated.
1407 int max = 340; /* Let's not go larger than life-sized. */
1408 if (target_size > max)
1412 if (win_size > 640 &&
1413 win_size > target_size * 1.5)
1415 GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
1417 glScalef(ratio, ratio, ratio);
1425 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1426 Bool wire = MI_IS_WIREFRAME(mi);
1429 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1431 glClear(GL_COLOR_BUFFER_BIT);
1435 /* Do it twice because we don't track the device's orientation. */
1436 glRotatef( current_device_rotation(), 0, 0, 1);
1437 gltrackball_rotate (lc->trackball);
1438 glRotatef(-current_device_rotation(), 0, 0, 1);
1440 /* Make into the screen be +Y right be +X, and up be +Z. */
1441 glRotatef(-90.0, 1.0, 0.0, 0.0);
1443 scale_for_window (mi);
1448 /* Shift to the upper left, and draw the vanilla box. */
1449 glTranslatef(-0.6, 0.0, 0.6);
1451 /* Apply rotation to the object. */
1452 glRotatef(x * 360, 1.0, 0.0, 0.0);
1453 glRotatef(y * 360, 0.0, 1.0, 0.0);
1454 glRotatef(z * 360, 0.0, 0.0, 1.0);
1457 glCallList(lc->box);
1461 /* Shift to the lower right, and draw the animated object. */
1462 glTranslatef(0.6, 0.0, -0.6);
1468 /* Apply rotation to the object. */
1469 if (lc->type != LAMENT_LID_ZOOM)
1470 get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
1471 !lc->button_down_p);
1472 glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
1473 glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
1474 glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
1481 glCallList(lc->box);
1484 case LAMENT_STAR_OUT:
1485 case LAMENT_STAR_ROT:
1486 case LAMENT_STAR_ROT_IN:
1487 case LAMENT_STAR_ROT_OUT:
1488 case LAMENT_STAR_UNROT:
1489 case LAMENT_STAR_IN:
1490 glTranslatef(0.0, 0.0, lc->anim_z/2);
1491 glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0);
1492 glCallList(lc->star1);
1494 glTranslatef(0.0, 0.0, -lc->anim_z);
1495 glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
1496 glCallList(lc->star2);
1499 case LAMENT_TETRA_UNE:
1500 case LAMENT_TETRA_USW:
1501 case LAMENT_TETRA_DWN:
1502 case LAMENT_TETRA_DSE:
1507 case LAMENT_TETRA_UNE: magic = lc->tetra_une;
1508 x = 1.0; y = 1.0; z = 1.0; break;
1509 case LAMENT_TETRA_USW: magic = lc->tetra_usw;
1510 x = 1.0; y = 1.0; z = -1.0; break;
1511 case LAMENT_TETRA_DWN: magic = lc->tetra_dwn;
1512 x = 1.0; y = -1.0; z = 1.0; break;
1513 case LAMENT_TETRA_DSE: magic = lc->tetra_dse;
1514 x = -1.0; y = 1.0; z = 1.0; break;
1515 default: abort(); break;
1517 glCallList(lc->tetra_mid);
1518 if (magic != lc->tetra_une) glCallList(lc->tetra_une);
1519 if (magic != lc->tetra_usw) glCallList(lc->tetra_usw);
1520 if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn);
1521 if (magic != lc->tetra_dse) glCallList(lc->tetra_dse);
1522 glRotatef(lc->anim_r, x, y, z);
1527 case LAMENT_LID_OPEN:
1528 case LAMENT_LID_CLOSE:
1529 case LAMENT_LID_ZOOM:
1533 glTranslatef(lc->anim_z, 0.0, 0.0);
1535 glCallList(lc->lid_0);
1538 glTranslatef(-0.5, -d, 0.0);
1539 glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
1540 glTranslatef( 0.5, d, 0.0);
1541 glCallList(lc->lid_1);
1544 glTranslatef(-0.5, -d, 0.0);
1545 glRotatef( lc->anim_r, 0.0, -1.0, 1.0);
1546 glTranslatef( 0.5, d, 0.0);
1547 glCallList(lc->lid_2);
1550 glTranslatef(-0.5, d, 0.0);
1551 glRotatef( lc->anim_r, 0.0, -1.0, -1.0);
1552 glTranslatef( 0.5, -d, 0.0);
1553 glCallList(lc->lid_3);
1556 glTranslatef(-0.5, d, 0.0);
1557 glRotatef(-lc->anim_r, 0.0, -1.0, 1.0);
1558 glTranslatef( 0.5, -d, 0.0);
1559 glCallList(lc->lid_4);
1564 case LAMENT_TASER_OUT:
1565 case LAMENT_TASER_SLIDE:
1566 case LAMENT_TASER_SLIDE_IN:
1567 case LAMENT_TASER_IN:
1569 glTranslatef(-lc->anim_z/2, 0.0, 0.0);
1570 glCallList(lc->taser_base);
1572 glTranslatef(lc->anim_z, 0.0, 0.0);
1573 glCallList(lc->taser_lifter);
1575 glTranslatef(0.0, 0.0, lc->anim_y);
1576 glCallList(lc->taser_slider);
1590 /* Rather than just picking states randomly, pick an ordering randomly, do it,
1591 and then re-randomize. That way one can be assured of seeing all states in
1592 a short time period, though not always in the same order (it's frustrating
1593 to see it pick the same state 5x in a row.)
1596 shuffle_states (lament_configuration *lc)
1599 for (i = 0; i < lc->nstates; i++)
1601 int a = random() % lc->nstates;
1602 lament_type swap = lc->states[a];
1603 lc->states[a] = lc->states[i];
1604 lc->states[i] = swap;
1610 animate(ModeInfo *mi)
1612 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1614 /* int pause2 = 60;*/
1622 if (lc->state >= lc->nstates)
1624 shuffle_states (lc);
1627 lc->type = lc->states[lc->state];
1629 if (lc->type == LAMENT_BOX)
1630 lc->anim_pause = pause3;
1638 /* -------------------------------------------------------------- */
1640 case LAMENT_STAR_OUT:
1642 if (lc->anim_z >= 1.0)
1645 lc->type = LAMENT_STAR_ROT;
1646 lc->anim_pause = pause;
1650 case LAMENT_STAR_ROT:
1652 if (lc->anim_r >= 45.0)
1655 lc->type = LAMENT_STAR_ROT_IN;
1656 lc->anim_pause = pause;
1660 case LAMENT_STAR_ROT_IN:
1662 if (lc->anim_z <= 0.0)
1665 lc->type = LAMENT_STAR_ROT_OUT;
1666 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1670 case LAMENT_STAR_ROT_OUT:
1672 if (lc->anim_z >= 1.0)
1675 lc->type = LAMENT_STAR_UNROT;
1676 lc->anim_pause = pause;
1680 case LAMENT_STAR_UNROT:
1682 if (lc->anim_r <= 0.0)
1685 lc->type = LAMENT_STAR_IN;
1686 lc->anim_pause = pause;
1690 case LAMENT_STAR_IN:
1692 if (lc->anim_z <= 0.0)
1695 lc->type = LAMENT_BOX;
1696 lc->anim_pause = pause3;
1700 /* -------------------------------------------------------------- */
1702 case LAMENT_TETRA_UNE:
1703 case LAMENT_TETRA_USW:
1704 case LAMENT_TETRA_DWN:
1705 case LAMENT_TETRA_DSE:
1708 if (lc->anim_r >= 360.0)
1711 lc->type = LAMENT_BOX;
1712 lc->anim_pause = pause3;
1714 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1717 lc->anim_pause = pause;
1719 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1722 lc->anim_pause = pause;
1726 /* -------------------------------------------------------------- */
1728 case LAMENT_LID_OPEN:
1731 if (lc->anim_r >= 112.0)
1735 lc->anim_pause = pause3;
1736 lc->type = (lc->facing_p ? LAMENT_LID_ZOOM : LAMENT_LID_CLOSE);
1740 case LAMENT_LID_CLOSE:
1742 if (lc->anim_r <= 0.0)
1745 lc->type = LAMENT_BOX;
1746 lc->anim_pause = pause3;
1750 case LAMENT_LID_ZOOM:
1752 if (lc->anim_z < -50.0)
1756 lc->type = LAMENT_BOX;
1760 /* -------------------------------------------------------------- */
1762 case LAMENT_TASER_OUT:
1763 lc->anim_z += 0.0025;
1764 if (lc->anim_z >= 0.25)
1767 lc->type = LAMENT_TASER_SLIDE;
1768 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1772 case LAMENT_TASER_SLIDE:
1773 lc->anim_y += 0.0025;
1774 if (lc->anim_y >= 0.23)
1777 lc->type = LAMENT_TASER_SLIDE_IN;
1778 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1782 case LAMENT_TASER_SLIDE_IN:
1783 lc->anim_y -= 0.0025;
1784 if (lc->anim_y <= 0.0)
1787 lc->type = LAMENT_TASER_IN;
1788 lc->anim_pause = pause;
1792 case LAMENT_TASER_IN:
1793 lc->anim_z -= 0.0025;
1794 if (lc->anim_z <= 0.0)
1797 lc->type = LAMENT_BOX;
1798 lc->anim_pause = pause3;
1810 /* Window management, etc
1814 reshape_lament(ModeInfo *mi, int width, int height)
1816 GLfloat h = (GLfloat) height / (GLfloat) width;
1817 glViewport(0, 0, (GLint) width, (GLint) height);
1819 glMatrixMode(GL_PROJECTION);
1821 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1822 glMatrixMode(GL_MODELVIEW);
1824 glTranslatef(0.0, 0.0, -40.0);
1825 glClear(GL_COLOR_BUFFER_BIT);
1830 gl_init(ModeInfo *mi)
1832 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1833 Bool wire = MI_IS_WIREFRAME(mi);
1840 static const GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1841 static const GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1843 static const GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1844 /* static const GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1845 static const GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1846 static const GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1848 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1849 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1851 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1852 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1853 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1854 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1855 set_colors(exterior_color);
1857 glEnable(GL_LIGHTING);
1858 glEnable(GL_LIGHT0);
1859 /* glEnable(GL_LIGHT1); */
1861 glEnable(GL_DEPTH_TEST);
1862 glEnable(GL_TEXTURE_2D);
1863 glEnable(GL_NORMALIZE);
1864 glEnable(GL_CULL_FACE);
1869 #ifdef HAVE_GLBINDTEXTURE
1871 for (i = 0; i < 6; i++)
1872 glGenTextures(1, &lc->texids[i]);
1874 parse_image_data(mi);
1876 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1877 /* messes up -fps */
1878 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); */
1880 for (i = 0; i < 6; i++)
1882 int height = lc->texture->width; /* assume square */
1883 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1884 set_colors(exterior_color);
1887 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1888 lc->texture->width, height, 0,
1890 /* GL_UNSIGNED_BYTE, */
1891 GL_UNSIGNED_INT_8_8_8_8_REV,
1892 (lc->texture->data +
1893 (lc->texture->bytes_per_line * height * i)));
1894 check_gl_error("texture");
1896 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1897 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1898 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1902 #else /* !HAVE_GLBINDTEXTURE */
1904 "%s: this version of GL doesn't support multiple texture maps.\n"
1905 "\tGet OpenGL 1.1.\n",
1908 #endif /* !HAVE_GLBINDTEXTURE */
1911 lc->box = glGenLists(16);
1912 lc->star1 = lc->box+1;
1913 lc->star2 = lc->box+2;
1914 lc->tetra_une = lc->box+3;
1915 lc->tetra_usw = lc->box+4;
1916 lc->tetra_dwn = lc->box+5;
1917 lc->tetra_dse = lc->box+6;
1918 lc->tetra_mid = lc->box+7;
1919 lc->lid_0 = lc->box+8;
1920 lc->lid_1 = lc->box+9;
1921 lc->lid_2 = lc->box+10;
1922 lc->lid_3 = lc->box+11;
1923 lc->lid_4 = lc->box+12;
1924 lc->taser_base = lc->box+13;
1925 lc->taser_lifter = lc->box+14;
1926 lc->taser_slider = lc->box+15;
1929 star(mi, True, wire);
1930 star(mi, False, wire);
1937 # ifdef HAVE_MESA_GL
1939 # include <signal.h>
1942 lament_signal_kludge (int sig)
1944 signal (sig, SIG_DFL);
1947 "%s: dying with signal %d (%s).\n"
1949 "\tThis is almost certainly a bug in the Mesa GL library,\n"
1950 "\tespecially if the stack trace in the core file mentions\n"
1951 "\t`lambda_textured_triangle' or `render_quad'.\n"
1953 "\tFirst make sure that you have the latest version of Mesa.\n"
1954 "\tIf that doesn't fix it, then I encourage you to report this\n"
1955 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
1959 (sig == SIGILL ? "SIGILL" :
1960 sig == SIGFPE ? "SIGFPE" :
1961 sig == SIGBUS ? "SIGBUS" :
1962 sig == SIGSEGV ? "SIGSEGV" : "???"));
1964 kill (getpid (), sig);
1968 handle_signals (void)
1970 signal (SIGILL, lament_signal_kludge);
1971 signal (SIGFPE, lament_signal_kludge);
1972 signal (SIGBUS, lament_signal_kludge);
1973 signal (SIGSEGV, lament_signal_kludge);
1975 # endif /* HAVE_MESA_GL */
1979 init_lament(ModeInfo *mi)
1981 lament_configuration *lc;
1984 lcs = (lament_configuration *)
1985 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
1988 fprintf(stderr, "%s: out of memory\n", progname);
1993 lc = &lcs[MI_SCREEN(mi)];
1996 double rot_speed = 0.5;
1997 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
1998 lc->trackball = gltrackball_init ();
2001 lc->type = LAMENT_BOX;
2002 lc->anim_pause = 300 + (random() % 100);
2004 if ((lc->glx_context = init_GL(mi)) != NULL)
2006 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2010 lc->states = (lament_type *) calloc (50, sizeof (*lc->states));
2012 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
2013 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
2014 lc->states[lc->nstates++] = LAMENT_TETRA_UNE;
2015 lc->states[lc->nstates++] = LAMENT_TETRA_USW;
2016 lc->states[lc->nstates++] = LAMENT_TETRA_DWN;
2017 lc->states[lc->nstates++] = LAMENT_TETRA_DSE;
2018 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2019 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2020 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2021 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2022 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2023 lc->states[lc->nstates++] = LAMENT_BOX;
2024 lc->states[lc->nstates++] = LAMENT_BOX;
2025 lc->states[lc->nstates++] = LAMENT_BOX;
2026 lc->states[lc->nstates++] = LAMENT_BOX;
2027 lc->states[lc->nstates++] = LAMENT_BOX;
2028 lc->states[lc->nstates++] = LAMENT_BOX;
2029 lc->states[lc->nstates++] = LAMENT_BOX;
2030 lc->states[lc->nstates++] = LAMENT_BOX;
2031 lc->states[lc->nstates++] = LAMENT_BOX;
2032 lc->states[lc->nstates++] = LAMENT_BOX;
2033 shuffle_states (lc);
2035 # ifdef HAVE_MESA_GL
2037 # endif /* HAVE_MESA_GL */
2042 draw_lament(ModeInfo *mi)
2044 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2045 Display *dpy = MI_DISPLAY(mi);
2046 Window window = MI_WINDOW(mi);
2048 if (!lc->glx_context)
2051 glDrawBuffer(GL_BACK);
2053 glXMakeCurrent(dpy, window, *(lc->glx_context));
2055 if (mi->fps_p) do_fps (mi);
2058 glXSwapBuffers(dpy, window);
2066 XSCREENSAVER_MODULE ("Lament", lament)