1 /* xscreensaver, Copyright (c) 1998-2012 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* Animates Lemarchand's Box, the Lament Configuration. By jwz, 25-Jul-98.
16 * The "gold" color isn't quite right; it looks more like "yellow" than
19 * For some reason, the interior surfaces are shinier than the exterior
20 surfaces. 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"
94 # include "../images/lament128.xpm"
96 # include "../images/lament512.xpm"
99 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
100 #define RANDSIGN() ((random() & 1) ? 1 : -1)
123 LAMENT_TASER_SLIDE_IN,
128 static const GLfloat exterior_color[] =
129 { 0.33, 0.22, 0.03, 1.00, /* ambient */
130 0.78, 0.57, 0.11, 1.00, /* specular */
131 0.99, 0.91, 0.81, 1.00, /* diffuse */
132 27.80 /* shininess */
134 static const GLfloat interior_color[] =
135 { 0.20, 0.20, 0.15, 1.00, /* ambient */
136 0.40, 0.40, 0.32, 1.00, /* specular */
137 0.99, 0.99, 0.81, 1.00, /* diffuse */
138 50.80 /* shininess */
143 GLXContext *glx_context;
145 double rotx, roty, rotz;
146 trackball_state *trackball;
149 GLuint box; /* display list IDs */
151 GLuint tetra_une, tetra_usw, tetra_dwn, tetra_dse, tetra_mid;
152 GLuint lid_0, lid_1, lid_2, lid_3, lid_4;
153 GLuint taser_base, taser_lifter, taser_slider;
155 XImage *texture; /* image bits */
156 GLuint texids[6]; /* texture map IDs */
157 lament_type type; /* which mode of the object is current */
159 int anim_pause; /* countdown before animating again */
160 GLfloat anim_r, anim_y, anim_z; /* relative position during anims */
166 } lament_configuration;
168 static lament_configuration *lcs = NULL;
178 parse_image_data(ModeInfo *mi)
180 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
181 lc->texture = xpm_to_ximage (mi->dpy,
188 /* Shorthand utilities for making faces, with proper normals.
192 set_colors (const GLfloat *color)
194 glMaterialfv(GL_FRONT, GL_AMBIENT, color+0);
195 glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4);
196 glMaterialfv(GL_FRONT, GL_SPECULAR, color+8);
197 glMaterialfv(GL_FRONT, GL_SHININESS, color+12);
201 face3(GLint texture, const GLfloat *color, Bool wire,
202 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
203 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
204 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3)
206 #ifdef HAVE_GLBINDTEXTURE
207 glBindTexture(GL_TEXTURE_2D, texture);
208 #endif /* HAVE_GLBINDTEXTURE */
211 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
212 glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
213 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
214 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
215 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
220 face4(GLint texture, const GLfloat *color, Bool wire,
221 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
222 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
223 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
224 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4)
226 #ifdef HAVE_GLBINDTEXTURE
227 glBindTexture(GL_TEXTURE_2D, texture);
228 #endif /* HAVE_GLBINDTEXTURE */
230 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
231 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
232 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
233 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
234 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
235 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
240 face5(GLint texture, const GLfloat *color, Bool wire,
241 GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
242 GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
243 GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
244 GLfloat s4, GLfloat t4, GLfloat x4, GLfloat y4, GLfloat z4,
245 GLfloat s5, GLfloat t5, GLfloat x5, GLfloat y5, GLfloat z5)
247 #ifdef HAVE_GLBINDTEXTURE
248 glBindTexture(GL_TEXTURE_2D, texture);
249 #endif /* HAVE_GLBINDTEXTURE */
251 do_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3);
252 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
253 glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
254 glTexCoord2f(s2, t2); glVertex3f(x2, y2, z2);
255 glTexCoord2f(s3, t3); glVertex3f(x3, y3, z3);
256 glTexCoord2f(s4, t4); glVertex3f(x4, y4, z4);
257 glTexCoord2f(s5, t5); glVertex3f(x5, y5, z5);
263 /* Creating object models
267 box(ModeInfo *mi, Bool wire)
269 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
271 glNewList(lc->box, GL_COMPILE);
272 glShadeModel(GL_SMOOTH);
275 face4(lc->texids[FACE_N], exterior_color, wire,
276 0.0, 0.0, -0.5, 0.5, 0.5,
277 1.0, 0.0, 0.5, 0.5, 0.5,
278 1.0, 1.0, 0.5, 0.5, -0.5,
279 0.0, 1.0, -0.5, 0.5, -0.5);
282 face4(lc->texids[FACE_S], exterior_color, wire,
283 0.0, 0.0, -0.5, -0.5, -0.5,
284 1.0, 0.0, 0.5, -0.5, -0.5,
285 1.0, 1.0, 0.5, -0.5, 0.5,
286 0.0, 1.0, -0.5, -0.5, 0.5);
289 face4(lc->texids[FACE_E], exterior_color, wire,
290 0.0, 0.0, 0.5, -0.5, -0.5,
291 1.0, 0.0, 0.5, 0.5, -0.5,
292 1.0, 1.0, 0.5, 0.5, 0.5,
293 0.0, 1.0, 0.5, -0.5, 0.5);
296 face4(lc->texids[FACE_W], exterior_color, wire,
297 1.0, 1.0, -0.5, -0.5, 0.5,
298 0.0, 1.0, -0.5, 0.5, 0.5,
299 0.0, 0.0, -0.5, 0.5, -0.5,
300 1.0, 0.0, -0.5, -0.5, -0.5);
303 face4(lc->texids[FACE_U], exterior_color, wire,
304 1.0, 0.0, 0.5, -0.5, 0.5,
305 1.0, 1.0, 0.5, 0.5, 0.5,
306 0.0, 1.0, -0.5, 0.5, 0.5,
307 0.0, 0.0, -0.5, -0.5, 0.5);
310 face4(lc->texids[FACE_D], exterior_color, wire,
311 0.0, 1.0, -0.5, -0.5, -0.5,
312 0.0, 0.0, -0.5, 0.5, -0.5,
313 1.0, 0.0, 0.5, 0.5, -0.5,
314 1.0, 1.0, 0.5, -0.5, -0.5);
321 star(ModeInfo *mi, Bool top, Bool wire)
323 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
327 { 77, 74 }, { 60, 99 }, { 0, 74 }, { 0, 0 }, /* L1 */
328 { 60, 99 }, { 55, 127 }, { 0, 127 }, { 0, 74 }, /* L2 */
329 { 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */
330 { 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */
331 { 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */
332 { 100, 193 }, { 127, 198 }, { 127, 255 }, { 74, 255 }, /* B2 */
333 { 127, 198 }, { 151, 193 }, { 180, 255 }, { 127, 255 }, /* B3 */
334 { 151, 193 }, { 178, 177 }, { 255, 255 }, { 180, 255 }, /* B4 */
335 { 178, 177 }, { 193, 155 }, { 255, 181 }, { 255, 255 }, /* R4 */
336 { 193, 155 }, { 199, 127 }, { 255, 127 }, { 255, 181 }, /* R3 */
337 { 199, 127 }, { 194, 99 }, { 255, 74 }, { 255, 127 }, /* R2 */
338 { 194, 99 }, { 179, 76 }, { 255, 0 }, { 255, 74 }, /* R1 */
339 { 179, 76 }, { 155, 60 }, { 180, 0 }, { 255, 0 }, /* T4 */
340 { 155, 60 }, { 126, 55 }, { 126, 0 }, { 180, 0 }, /* T3 */
341 { 126, 55 }, { 100, 60 }, { 75, 0 }, { 126, 0 }, /* T2 */
342 { 100, 60 }, { 77, 74 }, { 0, 0 }, { 75, 0 }, /* T1 */
345 for (i = 0; i < countof(points); i++)
346 points[i][1] = 255-points[i][1];
349 glNewList(lc->star1, GL_COMPILE);
351 glNewList(lc->star2, GL_COMPILE);
354 glRotatef(-180.0, 1.0, 0.0, 0.0);
356 for (i = 0; i < countof(points)/4; i += 2)
363 GLfloat s[4], t[4], x[4], y[4], z[4];
364 for (j = 3, k = 0; j >= 0; j--, k++)
366 GLfloat xx = points[(i*4)+j][0] / 255.0L;
367 GLfloat yy = points[(i*4)+j][1] / 255.0L;
374 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
375 s[0], t[0], x[0], y[0], z[0],
376 s[1], t[1], x[1], y[1], z[1],
377 s[2], t[2], x[2], y[2], z[2],
378 s[3], t[3], x[3], y[3], z[3]);
382 for (j = 0, k = 0; j < 4; j++, k++)
384 GLfloat xx = points[(i*4)+j][0] / 255.0L;
385 GLfloat yy = points[(i*4)+j][1] / 255.0L;
392 face4(lc->texids[top ? FACE_U : FACE_D], exterior_color, wire,
393 s[0], t[0], x[0], y[0], z[0],
394 s[1], t[1], x[1], y[1], z[1],
395 s[2], t[2], x[2], y[2], z[2],
396 s[3], t[3], x[3], y[3], z[3]);
400 for (j = 3; j >= 0; j--)
402 int k = (j == 0 ? 3 : j-1);
403 Bool front_p = (j == 3);
404 GLfloat x1 = points[(i*4)+j][0] / 255.0L;
405 GLfloat y1 = points[(i*4)+j][1] / 255.0L;
406 GLfloat x2 = points[(i*4)+k][0] / 255.0L;
407 GLfloat y2 = points[(i*4)+k][1] / 255.0L;
409 GLfloat tx1=0.0, tx2=1.0, ty1=0.0, ty2=1.0;
413 facing = (facing + j + 5) % 4;
419 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
420 ty1 = 0.0; ty2 = 1.0;
423 ty1 = 1.0; ty2 = 0.0;
427 texture = top ? FACE_S : FACE_N;
429 ty1 = 0.0; ty2 = 1.0;
435 ty1 = 0.0; ty2 = 1.0;
437 tx1 = 1.0 - y1; tx2 = 1.0 - y2;
438 ty1 = 1.0; ty2 = 0.0;
442 texture = top ? FACE_N : FACE_S;
444 ty1 = 1.0; ty2 = 0.0;
448 x1 -= 0.5; x2 -= 0.5;
449 y1 -= 0.5; y2 -= 0.5;
451 face4(front_p ? lc->texids[texture] : 0,
452 front_p ? exterior_color : interior_color,
454 tx1, ty2, x1, y1, 0.5,
455 tx1, ty1, x1, y1, -0.5,
456 tx2, ty1, x2, y2, -0.5,
457 tx2, ty2, x2, y2, 0.5);
462 /* Central core top cap.
464 #ifdef HAVE_GLBINDTEXTURE
465 glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]);
466 #endif /* HAVE_GLBINDTEXTURE */
467 set_colors(exterior_color);
470 do_normal(points[i+0][0], points[i+0][1], 0,
471 points[i+4][0], points[i+4][1], 0,
472 points[i+8][0], points[i+8][1], 0);
473 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
474 for (i = 1; i < countof(points); i += 4)
476 GLfloat x = points[i][0] / 255.0L;
477 GLfloat y = points[i][1] / 255.0L;
479 glVertex3f(x-0.5, y-0.5, 0.5);
484 /* Central core bottom cap.
486 #ifdef HAVE_GLBINDTEXTURE
487 glBindTexture(GL_TEXTURE_2D, 0);
488 #endif /* HAVE_GLBINDTEXTURE */
489 set_colors(interior_color);
491 i = countof(points) - 9;
492 do_normal(points[i+0][0], points[i+0][1], 0,
493 points[i+4][0], points[i+4][1], 0,
494 points[i+8][0], points[i+8][1], 0);
496 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
497 for (i = countof(points) - 3; i >= 0; i -= 4)
499 GLfloat x = points[i][0] / 255.0L;
500 GLfloat y = points[i][1] / 255.0L;
501 glVertex3f(x-0.5, y-0.5, 0);
506 /* Central core walls.
508 for (i = 1; i < countof(points); i += 4)
511 GLfloat x1 = points[i-1][0] / 255.0L;
512 GLfloat y1 = points[i-1][1] / 255.0L;
513 GLfloat x2 = points[i][0] / 255.0L;
514 GLfloat y2 = points[i][1] / 255.0L;
515 face4(0, interior_color, wire,
516 0.0, 0.0, x1-0.5, y1-0.5, 0.5,
517 0.0, 0.0, x1-0.5, y1-0.5, 0.0,
518 0.0, 0.0, x2-0.5, y2-0.5, 0.0,
519 0.0, 0.0, x2-0.5, y2-0.5, 0.5);
527 tetra(ModeInfo *mi, Bool wire)
529 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
531 glNewList(lc->tetra_une, GL_COMPILE);
533 glShadeModel(GL_SMOOTH);
536 face3(lc->texids[FACE_U], exterior_color, wire,
537 1.0, 0.0, 0.5, -0.5, 0.5,
538 1.0, 1.0, 0.5, 0.5, 0.5,
539 0.0, 1.0, -0.5, 0.5, 0.5);
542 face3(lc->texids[FACE_N], exterior_color, wire,
543 0.0, 0.0, -0.5, 0.5, 0.5,
544 1.0, 0.0, 0.5, 0.5, 0.5,
545 1.0, 1.0, 0.5, 0.5, -0.5);
548 face3(lc->texids[FACE_E], exterior_color, wire,
549 1.0, 0.0, 0.5, 0.5, -0.5,
550 1.0, 1.0, 0.5, 0.5, 0.5,
551 0.0, 1.0, 0.5, -0.5, 0.5);
553 face3(0, interior_color, wire,
554 0.0, 0.0, 0.5, 0.5, -0.5,
555 0.0, 0.0, 0.5, -0.5, 0.5,
556 0.0, 0.0, -0.5, 0.5, 0.5);
560 glNewList(lc->tetra_usw, GL_COMPILE);
563 face3(lc->texids[FACE_U], exterior_color, wire,
564 0.0, 1.0, -0.5, 0.5, 0.5,
565 0.0, 0.0, -0.5, -0.5, 0.5,
566 1.0, 0.0, 0.5, -0.5, 0.5);
569 face3(lc->texids[FACE_S], exterior_color, wire,
570 1.0, 1.0, 0.5, -0.5, 0.5,
571 0.0, 1.0, -0.5, -0.5, 0.5,
572 0.0, 0.0, -0.5, -0.5, -0.5);
575 face3(lc->texids[FACE_W], exterior_color, wire,
576 1.0, 0.0, -0.5, -0.5, -0.5,
577 1.0, 1.0, -0.5, -0.5, 0.5,
578 0.0, 1.0, -0.5, 0.5, 0.5);
580 face3(0, interior_color, wire,
581 0.0,0.0, -0.5, -0.5, -0.5,
582 0.0,0.0, -0.5, 0.5, 0.5,
583 0.0,0.0, 0.5, -0.5, 0.5);
587 glNewList(lc->tetra_dwn, GL_COMPILE);
590 face3(lc->texids[FACE_D], exterior_color, wire,
591 0.0, 1.0, -0.5, -0.5, -0.5,
592 0.0, 0.0, -0.5, 0.5, -0.5,
593 1.0, 0.0, 0.5, 0.5, -0.5);
596 face3(lc->texids[FACE_W], 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_N], exterior_color, wire,
603 1.0, 1.0, 0.5, 0.5, -0.5,
604 0.0, 1.0, -0.5, 0.5, -0.5,
605 0.0, 0.0, -0.5, 0.5, 0.5);
607 face3(0, interior_color, wire,
608 0.0, 0.0, 0.5, 0.5, -0.5,
609 0.0, 0.0, -0.5, 0.5, 0.5,
610 0.0, 0.0, -0.5, -0.5, -0.5);
614 glNewList(lc->tetra_dse, GL_COMPILE);
617 face3(lc->texids[FACE_S], exterior_color, wire,
618 0.0, 0.0, -0.5, -0.5, -0.5,
619 1.0, 0.0, 0.5, -0.5, -0.5,
620 1.0, 1.0, 0.5, -0.5, 0.5);
623 face3(lc->texids[FACE_E], exterior_color, wire,
624 0.0, 1.0, 0.5, -0.5, 0.5,
625 0.0, 0.0, 0.5, -0.5, -0.5,
626 1.0, 0.0, 0.5, 0.5, -0.5);
629 face3(lc->texids[FACE_D], exterior_color, wire,
630 1.0, 0.0, 0.5, 0.5, -0.5,
631 1.0, 1.0, 0.5, -0.5, -0.5,
632 0.0, 1.0, -0.5, -0.5, -0.5);
634 face3(0, interior_color, wire,
635 0.0, 0.0, 0.5, -0.5, 0.5,
636 0.0, 0.0, 0.5, 0.5, -0.5,
637 0.0, 0.0, -0.5, -0.5, -0.5);
641 glNewList(lc->tetra_mid, GL_COMPILE);
643 face3(0, interior_color, wire,
644 0.0, 0.0, 0.5, -0.5, 0.5,
645 0.0, 0.0, 0.5, 0.5, -0.5,
646 0.0, 0.0, -0.5, 0.5, 0.5);
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);
673 lid(ModeInfo *mi, Bool wire)
675 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
679 { 128, 20 },{ 21, 129 },{ 0, 129 },{ 0, 0 },{ 128, 0 }, /* L1 */
680 { 21, 129 },{ 127, 234 },{ 127, 255 },{ 0, 255 },{ 0, 129 }, /* L2 */
681 { 127, 234 },{ 233, 127 },{ 255, 127 },{ 255, 255 },{ 127, 255 }, /* R2 */
682 { 233, 127 },{ 128, 20 },{ 128, 0 },{ 255, 0 },{ 255, 127 }, /* R1 */
685 for (i = 0; i < countof(points); i++)
686 points[i][1] = 255-points[i][1];
688 glNewList(lc->lid_0, GL_COMPILE);
689 glShadeModel(GL_SMOOTH);
692 face4(lc->texids[FACE_N], exterior_color, wire,
693 0.0, 0.0, -0.5, 0.5, 0.5,
694 1.0, 0.0, 0.5, 0.5, 0.5,
695 1.0, 1.0, 0.5, 0.5, -0.5,
696 0.0, 1.0, -0.5, 0.5, -0.5);
699 face4(lc->texids[FACE_S], exterior_color, wire,
700 0.0, 0.0, -0.5, -0.5, -0.5,
701 1.0, 0.0, 0.5, -0.5, -0.5,
702 1.0, 1.0, 0.5, -0.5, 0.5,
703 0.0, 1.0, -0.5, -0.5, 0.5);
706 face4(lc->texids[FACE_E], exterior_color, wire,
707 0.0, 0.0, 0.5, -0.5, -0.5,
708 1.0, 0.0, 0.5, 0.5, -0.5,
709 1.0, 1.0, 0.5, 0.5, 0.5,
710 0.0, 1.0, 0.5, -0.5, 0.5);
713 face4(lc->texids[FACE_U], exterior_color, wire,
714 1.0, 0.0, 0.5, -0.5, 0.5,
715 1.0, 1.0, 0.5, 0.5, 0.5,
716 0.0, 1.0, -0.5, 0.5, 0.5,
717 0.0, 0.0, -0.5, -0.5, 0.5);
720 face4(lc->texids[FACE_D], exterior_color, wire,
721 0.0, 1.0, -0.5, -0.5, -0.5,
722 0.0, 0.0, -0.5, 0.5, -0.5,
723 1.0, 0.0, 0.5, 0.5, -0.5,
724 1.0, 1.0, 0.5, -0.5, -0.5);
727 for (i = 0; i < countof(points)/5; i++)
730 GLfloat s[5], t[5], x[5], y[5], z[5];
731 for (j = 0; j < 5; j++)
733 GLfloat xx = points[(i*5)+j][0] / 255.0L;
734 GLfloat yy = points[(i*5)+j][1] / 255.0L;
741 face5(lc->texids[FACE_W], exterior_color, wire,
742 s[0], t[0], x[0], y[0], z[0],
743 s[1], t[1], x[1], y[1], z[1],
744 s[2], t[2], x[2], y[2], z[2],
745 s[3], t[3], x[3], y[3], z[3],
746 s[4], t[4], x[4], y[4], z[4]);
751 /* W -- lid_1 through lid_4 */
752 for (i = 0; i < 4; i++)
754 GLfloat x1, y1, x2, y2, x3, y3;
756 glNewList(lc->lid_1 + i, GL_COMPILE);
757 glShadeModel(GL_SMOOTH);
759 x1 = points[(i*5)+1][0] / 255.0L;
760 y1 = points[(i*5)+1][1] / 255.0L;
761 x2 = points[(i*5)][0] / 255.0L;
762 y2 = points[(i*5)][1] / 255.0L;
767 face3(lc->texids[FACE_W], exterior_color, wire,
768 1.0-x1, y1, -0.5, x1-0.5, y1-0.5,
769 1.0-x2, y2, -0.5, x2-0.5, y2-0.5,
770 1.0-x3, y3, -0.5, x3-0.5, y3-0.5);
773 face3(0, interior_color, wire,
774 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
775 0.0, 0.0, -0.48, x1-0.5, y1-0.5,
776 0.0, 0.0, -0.48, x3-0.5, y3-0.5);
779 face4(0, interior_color, wire,
780 0.0, 0.0, -0.5, x1-0.5, y1-0.5,
781 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
782 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
783 0.0, 0.0, -0.48, x1-0.5, y1-0.5);
786 face4(0, interior_color, wire,
787 0.0, 0.0, -0.48, x2-0.5, y2-0.5,
788 0.0, 0.0, -0.48, x3-0.5, y3-0.5,
789 0.0, 0.0, -0.5, x3-0.5, y3-0.5,
790 0.0, 0.0, -0.5, x2-0.5, y2-0.5);
797 taser(ModeInfo *mi, Bool wire)
799 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
802 int slider_face_points[][2] = {
803 { 86, 58 },{ 38, 106 },{ 70, 106 },{ 118, 58 },{ -1, -1 }, /* a */
804 { 136, 58 },{ 184, 106 },{ 216, 106 },{ 168, 58 },{ -1, -1 }, /* b */
805 { 38, 106 },{ 0, 144 },{ 0, 190 },{ 60, 190 },{ 108, 106 }, /* c */
806 { 144, 106 },{ 194, 190 },{ 254, 190 },{ 254, 144 },{ 216, 106 }, /* d */
807 { 98, 124 },{ 60, 190 },{ 92, 190 },{ 126, 158 },{ 126, 124 }, /* e */
808 { 126, 124 },{ 126, 158 },{ 160, 190 },{ 194, 190 },{ 154, 124 }, /* f */
809 { 22, 190 },{ 22, 254 },{ 60, 254 },{ 60, 190 },{ -1, -1 }, /* g */
810 { 194, 190 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ -1, -1 }, /* h */
811 { 60, 190 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ -1, -1 }, /* i */
812 { 160, 190 },{ 160, 210 },{ 194, 210 },{ 194, 190 },{ -1, -1 }, /* j */
813 { 110, 172 },{ 92, 190 },{ 110, 190 },{ -1, -1 },{ -1, -1 }, /* k */
814 { 140, 172 },{ 140, 190 },{ 160, 190 },{ -1, -1 },{ -1, -1 }, /* l */
815 { 110, 172 },{ 140, 172 },{ 126, 156 },{ -1, -1 },{ -1, -1 }, /* m */
818 int body_face_points[][2] = {
819 { 0, 0 },{ 0, 58 },{ 254, 58 },{ 254, 0 },{ -1, -1 }, /* A */
820 { 0, 58 },{ 0, 144 },{ 86, 58 },{ -1, -1 },{ -1, -1 }, /* B */
821 { 168, 58 },{ 254, 144 },{ 254, 58 },{ -1, -1 },{ -1, -1 }, /* C */
822 { 118, 58 },{ 70, 106 },{ 184, 106 },{ 136, 58 },{ -1, -1 }, /* F */
823 { 108, 106 },{ 98, 124 },{ 154, 124 },{ 144, 106 },{ -1, -1 }, /* G */
826 int lifter_face_points[][2] = {
827 { 0, 190 },{ 0, 254 },{ 22, 254 },{ 22, 190 },{ -1, -1 }, /* D */
828 { 230, 190 },{ 230, 254 },{ 254, 254 },{ 254, 190 },{ -1, -1 }, /* E */
829 { 60, 210 },{ 60, 254 },{ 194, 254 },{ 194, 210 },{ -1, -1 }, /* H */
830 { 92, 190 },{ 92, 210 },{ 160, 210 },{ 160, 190 },{ -1, -1 }, /* I */
831 { 110, 172 },{ 110, 190 },{ 140, 190 },{ 140, 172 },{ -1, -1 }, /* J */
834 int body_perimiter_points[][2] = {
835 { 0, 144 },{ 86, 59 },{ 119, 58 },{ 71, 107 },
836 { 108, 107 },{ 98, 124 },{ 155, 124 },{ 144, 107 },
837 { 185, 106 },{ 136, 59 },{ 169, 59 },{ 255, 145 },
841 int slider_perimiter_points[][2] = {
842 { 86, 58 },{ 0, 144 },{ 0, 190 },{ 22, 190 },{ 22, 254 },
843 { 60, 254 },{ 60, 210 },{ 92, 210 },{ 92, 190 },{ 110, 190 },
844 { 110, 172 },{ 140, 172 },{ 140, 190 },{ 160, 190 },{ 160, 210 },
845 { 194, 210 },{ 194, 254 },{ 230, 254 },{ 230, 190 },{ 254, 190 },
846 { 254, 144 },{ 168, 58 },{ 136, 58 },{ 184, 106 },{ 144, 106 },
847 { 154, 124 },{ 98, 124 },{ 108, 106 },{ 70, 106 },{ 118, 58 },
850 int lifter_perimiter_points_1[][2] = {
851 { 0, 189 },{ 0, 254 },{ 22, 255 },{ 23, 190 },
854 int lifter_perimiter_points_2[][2] = {
855 { 230, 254 },{ 255, 255 },{ 254, 190 },{ 230, 190 },
858 int lifter_perimiter_points_3[][2] = {
859 { 60, 254 },{ 194, 254 },{ 194, 211 },{ 160, 210 },
860 { 160, 190 },{ 140, 191 },{ 141, 172 },{ 111, 172 },
861 { 110, 190 },{ 93, 190 },{ 92, 210 },{ 60, 211 },
864 for (i = 0; i < countof(slider_face_points); i++)
865 slider_face_points[i][1] = 255-slider_face_points[i][1];
866 for (i = 0; i < countof(body_face_points); i++)
867 body_face_points[i][1] = 255-body_face_points[i][1];
868 for (i = 0; i < countof(lifter_face_points); i++)
869 lifter_face_points[i][1] = 255-lifter_face_points[i][1];
870 for (i = 0; i < countof(body_perimiter_points); i++)
871 body_perimiter_points[i][1] = 255-body_perimiter_points[i][1];
872 for (i = 0; i < countof(slider_perimiter_points); i++)
873 slider_perimiter_points[i][1] = 255-slider_perimiter_points[i][1];
874 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
875 lifter_perimiter_points_1[i][1] = 255-lifter_perimiter_points_1[i][1];
876 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
877 lifter_perimiter_points_2[i][1] = 255-lifter_perimiter_points_2[i][1];
878 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
879 lifter_perimiter_points_3[i][1] = 255-lifter_perimiter_points_3[i][1];
881 /* -------------------------------------------------------------------- */
883 glNewList(lc->taser_base, GL_COMPILE);
884 glShadeModel(GL_SMOOTH);
887 face4(lc->texids[FACE_N], exterior_color, wire,
888 0.0, 0.0, -0.5, 0.5, 0.5,
889 0.75, 0.0, 0.25, 0.5, 0.5,
890 0.75, 0.75, 0.25, 0.5, -0.25,
891 0.0, 0.75, -0.5, 0.5, -0.25);
894 face4(lc->texids[FACE_S], exterior_color, wire,
895 0.0, 0.25, -0.5, -0.5, -0.25,
896 0.75, 0.25, 0.25, -0.5, -0.25,
897 0.75, 1.0, 0.25, -0.5, 0.5,
898 0.0, 1.0, -0.5, -0.5, 0.5);
901 face4(0, interior_color, wire,
902 0.0, 0.0, 0.25, -0.5, -0.25,
903 1.0, 0.0, 0.25, 0.5, -0.25,
904 1.0, 1.0, 0.25, 0.5, 0.5,
905 0.0, 1.0, 0.25, -0.5, 0.5);
908 face4(lc->texids[FACE_W], exterior_color, wire,
909 1.0, 1.0, -0.5, -0.5, 0.5,
910 0.0, 1.0, -0.5, 0.5, 0.5,
911 0.0, 0.25, -0.5, 0.5, -0.25,
912 1.0, 0.25, -0.5, -0.5, -0.25);
915 face4(lc->texids[FACE_U], exterior_color, wire,
916 0.75, 0.0, 0.25, -0.5, 0.5,
917 0.75, 1.0, 0.25, 0.5, 0.5,
918 0.0, 1.0, -0.5, 0.5, 0.5,
919 0.0, 0.0, -0.5, -0.5, 0.5);
922 face4(0, interior_color, wire,
923 0.0, 1.0, -0.5, -0.5, -0.25,
924 0.0, 0.0, -0.5, 0.5, -0.25,
925 1.0, 0.0, 0.25, 0.5, -0.25,
926 1.0, 1.0, 0.25, -0.5, -0.25);
929 for (i = 0; i < countof(body_face_points)/5; i++)
932 #ifdef HAVE_GLBINDTEXTURE
933 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
934 #endif /* HAVE_GLBINDTEXTURE */
935 set_colors(exterior_color);
937 do_normal(0, body_face_points[(i*5)+0][0], body_face_points[(i*5)+0][1],
938 0, body_face_points[(i*5)+1][0], body_face_points[(i*5)+1][1],
939 0, body_face_points[(i*5)+2][0], body_face_points[(i*5)+2][1]
941 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
942 for (j = 0; j < 5; j++)
944 int ix = body_face_points[(i*5)+j][0];
945 int iy = body_face_points[(i*5)+j][1];
947 if (ix == -1) /* these are padding: ignore them */
952 glVertex3f(0.5, x-0.5, y-0.5);
958 for (i = 0; i < countof(body_perimiter_points); i++)
960 int j = (i+1 >= countof(body_perimiter_points) ? 0 : i+1);
961 GLfloat x1 = body_perimiter_points[i][0] / 255.0;
962 GLfloat y1 = body_perimiter_points[i][1] / 255.0;
963 GLfloat x2 = body_perimiter_points[j][0] / 255.0;
964 GLfloat y2 = body_perimiter_points[j][1] / 255.0;
966 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
970 texture = lc->texids[FACE_N];
972 s2 = 1.0; t2 = 0.568;
973 s3 = 0.75, t3 = 0.568;
978 texture = lc->texids[FACE_U];
986 texture = lc->texids[FACE_S];
987 s1 = 1.0; t1 = 0.437;
990 s4 = 0.75; t4 = 0.437;
993 face4((texture == -1 ? 0 : texture),
994 (texture == -1 ? interior_color : exterior_color),
996 s1, t1, 0.5, x2-0.5, y2-0.5,
997 s2, t2, 0.5, x1-0.5, y1-0.5,
998 s3, t3, 0.25, x1-0.5, y1-0.5,
999 s4, t4, 0.25, x2-0.5, y2-0.5);
1004 /* -------------------------------------------------------------------- */
1006 glNewList(lc->taser_lifter, GL_COMPILE);
1007 glShadeModel(GL_SMOOTH);
1010 face4(lc->texids[FACE_N], exterior_color, wire,
1011 0.0, 0.75, -0.5, 0.5, -0.25,
1012 0.75, 0.75, 0.25, 0.5, -0.25,
1013 0.75, 1.0, 0.25, 0.5, -0.5,
1014 0.0, 1.0, -0.5, 0.5, -0.5);
1017 face4(lc->texids[FACE_S], exterior_color, wire,
1018 0.0, 0.0, -0.5, -0.5, -0.5,
1019 0.75, 0.0, 0.25, -0.5, -0.5,
1020 0.75, 0.25, 0.25, -0.5, -0.25,
1021 0.0, 0.25, -0.5, -0.5, -0.25);
1024 face4(0, interior_color, wire,
1025 0.0, 1.0, 0.25, -0.5, -0.5,
1026 1.0, 1.0, 0.25, 0.5, -0.5,
1027 1.0, 0.0, 0.25, 0.5, -0.25,
1028 0.0, 0.0, 0.25, -0.5, -0.25);
1031 face4(lc->texids[FACE_W], exterior_color, wire,
1032 1.0, 0.25, -0.5, -0.5, -0.25,
1033 0.0, 0.25, -0.5, 0.5, -0.25,
1034 0.0, 0.0, -0.5, 0.5, -0.5,
1035 1.0, 0.0, -0.5, -0.5, -0.5);
1038 face4(0, interior_color, wire,
1039 1.0, 0.0, 0.25, -0.5, -0.25,
1040 1.0, 1.0, 0.25, 0.5, -0.25,
1041 0.0, 1.0, -0.5, 0.5, -0.25,
1042 0.0, 0.0, -0.5, -0.5, -0.25);
1045 face4(lc->texids[FACE_D], exterior_color, wire,
1046 0.0, 1.0, -0.5, -0.5, -0.5,
1047 0.0, 0.0, -0.5, 0.5, -0.5,
1048 0.75, 0.0, 0.25, 0.5, -0.5,
1049 0.75, 1.0, 0.25, -0.5, -0.5);
1053 for (i = 0; i < countof(lifter_face_points)/5; i++)
1057 #ifdef HAVE_GLBINDTEXTURE
1058 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1059 #endif /* HAVE_GLBINDTEXTURE */
1060 set_colors(exterior_color);
1063 0, lifter_face_points[(i*5)+0][0], lifter_face_points[(i*5)+0][1],
1064 0, lifter_face_points[(i*5)+1][0], lifter_face_points[(i*5)+1][1],
1065 0, lifter_face_points[(i*5)+2][0], lifter_face_points[(i*5)+2][1]);
1067 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1068 for (j = 0; j < 5; j++)
1070 int ix = lifter_face_points[(i*5)+j][0];
1071 int iy = lifter_face_points[(i*5)+j][1];
1073 if (ix == -1) /* these are padding: ignore them */
1078 glVertex3f(0.5, x-0.5, y-0.5);
1084 for (i = 0; i < countof(lifter_perimiter_points_1); i++)
1086 int j = (i+1 >= countof(lifter_perimiter_points_1) ? 0 : i+1);
1087 GLfloat x1 = lifter_perimiter_points_1[i][0] / 255.0;
1088 GLfloat y1 = lifter_perimiter_points_1[i][1] / 255.0;
1089 GLfloat x2 = lifter_perimiter_points_1[j][0] / 255.0;
1090 GLfloat y2 = lifter_perimiter_points_1[j][1] / 255.0;
1092 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1096 texture = lc->texids[FACE_S];
1098 s2 = 1.0; t2 = 0.26;
1099 s3 = 0.75, t3 = 0.26;
1100 s4 = 0.75; t4 = 0.0;
1104 texture = lc->texids[FACE_D];
1105 s1 = 1.0; t1 = 0.914;
1107 s3 = 0.75; t3 = 1.0;
1108 s4 = 0.75; t4 = 0.914;
1111 face4((texture == -1 ? 0 : texture),
1112 (texture == -1 ? interior_color : exterior_color),
1114 s1, t1, 0.5, x2-0.5, y2-0.5,
1115 s2, t2, 0.5, x1-0.5, y1-0.5,
1116 s3, t3, 0.25, x1-0.5, y1-0.5,
1117 s4, t4, 0.25, x2-0.5, y2-0.5);
1120 for (i = 0; i < countof(lifter_perimiter_points_2); i++)
1122 int j = (i+1 >= countof(lifter_perimiter_points_2) ? 0 : i+1);
1123 GLfloat x1 = lifter_perimiter_points_2[i][0] / 255.0;
1124 GLfloat y1 = lifter_perimiter_points_2[i][1] / 255.0;
1125 GLfloat x2 = lifter_perimiter_points_2[j][0] / 255.0;
1126 GLfloat y2 = lifter_perimiter_points_2[j][1] / 255.0;
1128 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1132 texture = lc->texids[FACE_D];
1134 s2 = 1.0; t2 = 0.095;
1135 s3 = 0.75; t3 = 0.095;
1136 s4 = 0.75; t4 = 0.0;
1140 texture = lc->texids[FACE_N];
1141 s1 = 1.0; t1 = 0.745;
1143 s3 = 0.75; t3 = 1.0;
1144 s4 = 0.75; t4 = 0.745;
1147 face4((texture == -1 ? 0 : texture),
1148 (texture == -1 ? interior_color : exterior_color),
1150 s1, t1, 0.5, x2-0.5, y2-0.5,
1151 s2, t2, 0.5, x1-0.5, y1-0.5,
1152 s3, t3, 0.25, x1-0.5, y1-0.5,
1153 s4, t4, 0.25, x2-0.5, y2-0.5);
1156 for (i = 0; i < countof(lifter_perimiter_points_3); i++)
1158 int j = (i+1 >= countof(lifter_perimiter_points_3) ? 0 : i+1);
1159 GLfloat x1 = lifter_perimiter_points_3[i][0] / 255.0;
1160 GLfloat y1 = lifter_perimiter_points_3[i][1] / 255.0;
1161 GLfloat x2 = lifter_perimiter_points_3[j][0] / 255.0;
1162 GLfloat y2 = lifter_perimiter_points_3[j][1] / 255.0;
1164 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1168 texture = lc->texids[FACE_D];
1169 s1 = 1.0; t1 = 0.235;
1170 s2 = 1.0; t2 = 0.765;
1171 s3 = 0.75; t3 = 0.765;
1172 s4 = 0.75; t4 = 0.235;
1175 face4((texture == -1 ? 0 : texture),
1176 (texture == -1 ? interior_color : exterior_color),
1178 s1, t1, 0.5, x2-0.5, y2-0.5,
1179 s2, t2, 0.5, x1-0.5, y1-0.5,
1180 s3, t3, 0.25, x1-0.5, y1-0.5,
1181 s4, t4, 0.25, x2-0.5, y2-0.5);
1186 /* -------------------------------------------------------------------- */
1188 glNewList(lc->taser_slider, GL_COMPILE);
1189 glShadeModel(GL_SMOOTH);
1192 for (i = 0; i < countof(slider_face_points)/5; i++)
1195 #ifdef HAVE_GLBINDTEXTURE
1196 glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
1197 #endif /* HAVE_GLBINDTEXTURE */
1198 set_colors(exterior_color);
1201 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1],
1202 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1203 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1]);
1204 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1205 for (j = 0; j < 5; j++)
1207 int ix = slider_face_points[(i*5)+j][0];
1208 int iy = slider_face_points[(i*5)+j][1];
1210 if (ix == -1) /* these are padding: ignore them */
1215 glVertex3f(0.5, x-0.5, y-0.5);
1221 for (i = countof(slider_face_points)/5 - 1; i >= 0; i--)
1224 #ifdef HAVE_GLBINDTEXTURE
1225 glBindTexture(GL_TEXTURE_2D, 0);
1226 #endif /* HAVE_GLBINDTEXTURE */
1227 set_colors(interior_color);
1230 0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1],
1231 0, slider_face_points[(i*5)+1][0], slider_face_points[(i*5)+1][1],
1232 0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1]);
1233 glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
1234 for (j = 4; j >= 0; j--)
1236 int ix = slider_face_points[(i*5)+j][0];
1237 int iy = slider_face_points[(i*5)+j][1];
1239 if (ix == -1) /* these are padding: ignore them */
1244 glVertex3f(0.25, x-0.5, y-0.5);
1250 for (i = 0; i < countof(slider_perimiter_points); i++)
1252 int j = (i+1 >= countof(slider_perimiter_points) ? 0 : i+1);
1253 GLfloat x1 = slider_perimiter_points[i][0] / 255.0;
1254 GLfloat y1 = slider_perimiter_points[i][1] / 255.0;
1255 GLfloat x2 = slider_perimiter_points[j][0] / 255.0;
1256 GLfloat y2 = slider_perimiter_points[j][1] / 255.0;
1258 GLfloat s1=0, t1=0, s2=0, t2=0, s3=0, t3=0, s4=0, t4=0;
1262 texture = lc->texids[FACE_S];
1263 s1 = 1.0; t1 = 0.255;
1264 s2 = 1.0; t2 = 0.435;
1265 s3 = 0.75; t3 = 0.435;
1266 s4 = 0.75; t4 = 0.255;
1270 texture = lc->texids[FACE_D];
1271 s1 = 1.0; t1 = 0.758;
1272 s2 = 1.0; t2 = 0.915;
1273 s3 = 0.75; t3 = 0.915;
1274 s4 = 0.75; t4 = 0.758;
1278 texture = lc->texids[FACE_D];
1279 s1 = 1.0; t1 = 0.095;
1280 s2 = 1.0; t2 = 0.24;
1281 s3 = 0.75; t3 = 0.24;
1282 s4 = 0.75; t4 = 0.095;
1286 texture = lc->texids[FACE_N];
1287 s1 = 1.0; t1 = 0.568;
1288 s2 = 1.0; t2 = 0.742;
1289 s3 = 0.75; t3 = 0.742;
1290 s4 = 0.75; t4 = 0.568;
1293 face4((texture == -1 ? 0 : texture),
1294 (texture == -1 ? interior_color : exterior_color),
1296 s1, t1, 0.5, x2-0.5, y2-0.5,
1297 s2, t2, 0.5, x1-0.5, y1-0.5,
1298 s3, t3, 0.25, x1-0.5, y1-0.5,
1299 s4, t4, 0.25, x2-0.5, y2-0.5);
1307 /* Rendering and animating object models
1311 lament_handle_event (ModeInfo *mi, XEvent *event)
1313 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1315 if (event->xany.type == ButtonPress &&
1316 event->xbutton.button == Button1)
1318 lc->button_down_p = True;
1319 gltrackball_start (lc->trackball,
1320 event->xbutton.x, event->xbutton.y,
1321 MI_WIDTH (mi), MI_HEIGHT (mi));
1324 else if (event->xany.type == ButtonRelease &&
1325 event->xbutton.button == Button1)
1327 lc->button_down_p = False;
1330 else if (event->xany.type == ButtonPress &&
1331 (event->xbutton.button == Button4 ||
1332 event->xbutton.button == Button5 ||
1333 event->xbutton.button == Button6 ||
1334 event->xbutton.button == Button7))
1336 gltrackball_mousewheel (lc->trackball, event->xbutton.button, 5,
1337 !!event->xbutton.state);
1340 else if (event->xany.type == MotionNotify &&
1343 gltrackball_track (lc->trackball,
1344 event->xmotion.x, event->xmotion.y,
1345 MI_WIDTH (mi), MI_HEIGHT (mi));
1354 check_facing(ModeInfo *mi)
1356 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1358 GLdouble m[16], p[16], x, y, z;
1360 glGetDoublev (GL_MODELVIEW_MATRIX, m);
1361 glGetDoublev (GL_PROJECTION_MATRIX, p);
1362 glGetIntegerv (GL_VIEWPORT, v);
1364 /* See if a coordinate 5 units in front of the door is near the
1365 center of the screen. */
1367 gluProject (-5, 0, 0, m, p, v, &x, &y, &z);
1368 x = (x / MI_WIDTH(mi)) - 0.5;
1369 y = (y / MI_HEIGHT(mi)) - 0.5;
1370 lc->facing_p = (z < 0.9 &&
1371 x > -0.02 && x < 0.02 &&
1372 y > -0.02 && y < 0.02);
1378 scale_for_window(ModeInfo *mi)
1380 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1381 int target_size = lc->texture->width * 1.4;
1382 int win_size = (MI_WIDTH(mi) > MI_HEIGHT(mi) ? MI_HEIGHT(mi) : MI_WIDTH(mi));
1384 /* This scale makes the box take up most of the window */
1387 /* But if the window is more than a little larger than our target size,
1388 scale the object back down, so that the bits drawn on the screen end
1389 up rougly target_size across (actually it ends up a little larger.)
1390 Note that the image-map bits we have are 128x128. Therefore, if the
1391 image is magnified a lot, it looks pretty blocky. So it's better to
1392 have a 128x128 animation on a 1280x1024 screen that looks good, than
1393 a 1024x1024 animation that looks really pixelated.
1397 int max = 340; /* Let's not go larger than life-sized. */
1398 if (target_size > max)
1402 if (win_size > 640 &&
1403 win_size > target_size * 1.5)
1405 GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
1407 glScalef(ratio, ratio, ratio);
1415 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1416 Bool wire = MI_IS_WIREFRAME(mi);
1419 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1421 glClear(GL_COLOR_BUFFER_BIT);
1425 /* Do it twice because we don't track the device's orientation. */
1426 glRotatef( current_device_rotation(), 0, 0, 1);
1427 gltrackball_rotate (lc->trackball);
1428 glRotatef(-current_device_rotation(), 0, 0, 1);
1430 /* Make into the screen be +Y right be +X, and up be +Z. */
1431 glRotatef(-90.0, 1.0, 0.0, 0.0);
1433 scale_for_window (mi);
1438 /* Shift to the upper left, and draw the vanilla box. */
1439 glTranslatef(-0.6, 0.0, 0.6);
1441 /* Apply rotation to the object. */
1442 glRotatef(x * 360, 1.0, 0.0, 0.0);
1443 glRotatef(y * 360, 0.0, 1.0, 0.0);
1444 glRotatef(z * 360, 0.0, 0.0, 1.0);
1447 glCallList(lc->box);
1451 /* Shift to the lower right, and draw the animated object. */
1452 glTranslatef(0.6, 0.0, -0.6);
1458 /* Apply rotation to the object. */
1459 if (lc->type != LAMENT_LID_ZOOM)
1460 get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
1461 !lc->button_down_p);
1462 glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
1463 glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
1464 glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
1471 glCallList(lc->box);
1474 case LAMENT_STAR_OUT:
1475 case LAMENT_STAR_ROT:
1476 case LAMENT_STAR_ROT_IN:
1477 case LAMENT_STAR_ROT_OUT:
1478 case LAMENT_STAR_UNROT:
1479 case LAMENT_STAR_IN:
1480 glTranslatef(0.0, 0.0, lc->anim_z/2);
1481 glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0);
1482 glCallList(lc->star1);
1484 glTranslatef(0.0, 0.0, -lc->anim_z);
1485 glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
1486 glCallList(lc->star2);
1489 case LAMENT_TETRA_UNE:
1490 case LAMENT_TETRA_USW:
1491 case LAMENT_TETRA_DWN:
1492 case LAMENT_TETRA_DSE:
1497 case LAMENT_TETRA_UNE: magic = lc->tetra_une;
1498 x = 1.0; y = 1.0; z = 1.0; break;
1499 case LAMENT_TETRA_USW: magic = lc->tetra_usw;
1500 x = 1.0; y = 1.0; z = -1.0; break;
1501 case LAMENT_TETRA_DWN: magic = lc->tetra_dwn;
1502 x = 1.0; y = -1.0; z = 1.0; break;
1503 case LAMENT_TETRA_DSE: magic = lc->tetra_dse;
1504 x = -1.0; y = 1.0; z = 1.0; break;
1505 default: abort(); break;
1507 glCallList(lc->tetra_mid);
1508 if (magic != lc->tetra_une) glCallList(lc->tetra_une);
1509 if (magic != lc->tetra_usw) glCallList(lc->tetra_usw);
1510 if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn);
1511 if (magic != lc->tetra_dse) glCallList(lc->tetra_dse);
1512 glRotatef(lc->anim_r, x, y, z);
1517 case LAMENT_LID_OPEN:
1518 case LAMENT_LID_CLOSE:
1519 case LAMENT_LID_ZOOM:
1523 glTranslatef(lc->anim_z, 0.0, 0.0);
1525 glCallList(lc->lid_0);
1528 glTranslatef(-0.5, -d, 0.0);
1529 glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
1530 glTranslatef( 0.5, d, 0.0);
1531 glCallList(lc->lid_1);
1534 glTranslatef(-0.5, -d, 0.0);
1535 glRotatef( lc->anim_r, 0.0, -1.0, 1.0);
1536 glTranslatef( 0.5, d, 0.0);
1537 glCallList(lc->lid_2);
1540 glTranslatef(-0.5, d, 0.0);
1541 glRotatef( lc->anim_r, 0.0, -1.0, -1.0);
1542 glTranslatef( 0.5, -d, 0.0);
1543 glCallList(lc->lid_3);
1546 glTranslatef(-0.5, d, 0.0);
1547 glRotatef(-lc->anim_r, 0.0, -1.0, 1.0);
1548 glTranslatef( 0.5, -d, 0.0);
1549 glCallList(lc->lid_4);
1554 case LAMENT_TASER_OUT:
1555 case LAMENT_TASER_SLIDE:
1556 case LAMENT_TASER_SLIDE_IN:
1557 case LAMENT_TASER_IN:
1559 glTranslatef(-lc->anim_z/2, 0.0, 0.0);
1560 glCallList(lc->taser_base);
1562 glTranslatef(lc->anim_z, 0.0, 0.0);
1563 glCallList(lc->taser_lifter);
1565 glTranslatef(0.0, 0.0, lc->anim_y);
1566 glCallList(lc->taser_slider);
1580 /* Rather than just picking states randomly, pick an ordering randomly, do it,
1581 and then re-randomize. That way one can be assured of seeing all states in
1582 a short time period, though not always in the same order (it's frustrating
1583 to see it pick the same state 5x in a row.)
1586 shuffle_states (lament_configuration *lc)
1589 for (i = 0; i < lc->nstates; i++)
1591 int a = random() % lc->nstates;
1592 lament_type swap = lc->states[a];
1593 lc->states[a] = lc->states[i];
1594 lc->states[i] = swap;
1600 animate(ModeInfo *mi)
1602 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1604 /* int pause2 = 60;*/
1612 if (lc->state >= lc->nstates)
1614 shuffle_states (lc);
1617 lc->type = lc->states[lc->state];
1619 if (lc->type == LAMENT_BOX)
1620 lc->anim_pause = pause3;
1628 /* -------------------------------------------------------------- */
1630 case LAMENT_STAR_OUT:
1632 if (lc->anim_z >= 1.0)
1635 lc->type = LAMENT_STAR_ROT;
1636 lc->anim_pause = pause;
1640 case LAMENT_STAR_ROT:
1642 if (lc->anim_r >= 45.0)
1645 lc->type = LAMENT_STAR_ROT_IN;
1646 lc->anim_pause = pause;
1650 case LAMENT_STAR_ROT_IN:
1652 if (lc->anim_z <= 0.0)
1655 lc->type = LAMENT_STAR_ROT_OUT;
1656 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1660 case LAMENT_STAR_ROT_OUT:
1662 if (lc->anim_z >= 1.0)
1665 lc->type = LAMENT_STAR_UNROT;
1666 lc->anim_pause = pause;
1670 case LAMENT_STAR_UNROT:
1672 if (lc->anim_r <= 0.0)
1675 lc->type = LAMENT_STAR_IN;
1676 lc->anim_pause = pause;
1680 case LAMENT_STAR_IN:
1682 if (lc->anim_z <= 0.0)
1685 lc->type = LAMENT_BOX;
1686 lc->anim_pause = pause3;
1690 /* -------------------------------------------------------------- */
1692 case LAMENT_TETRA_UNE:
1693 case LAMENT_TETRA_USW:
1694 case LAMENT_TETRA_DWN:
1695 case LAMENT_TETRA_DSE:
1698 if (lc->anim_r >= 360.0)
1701 lc->type = LAMENT_BOX;
1702 lc->anim_pause = pause3;
1704 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1707 lc->anim_pause = pause;
1709 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1712 lc->anim_pause = pause;
1716 /* -------------------------------------------------------------- */
1718 case LAMENT_LID_OPEN:
1721 if (lc->anim_r >= 112.0)
1725 lc->anim_pause = pause3;
1726 lc->type = (lc->facing_p ? LAMENT_LID_ZOOM : LAMENT_LID_CLOSE);
1730 case LAMENT_LID_CLOSE:
1732 if (lc->anim_r <= 0.0)
1735 lc->type = LAMENT_BOX;
1736 lc->anim_pause = pause3;
1740 case LAMENT_LID_ZOOM:
1742 if (lc->anim_z < -50.0)
1746 lc->type = LAMENT_BOX;
1750 /* -------------------------------------------------------------- */
1752 case LAMENT_TASER_OUT:
1753 lc->anim_z += 0.0025;
1754 if (lc->anim_z >= 0.25)
1757 lc->type = LAMENT_TASER_SLIDE;
1758 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1762 case LAMENT_TASER_SLIDE:
1763 lc->anim_y += 0.0025;
1764 if (lc->anim_y >= 0.23)
1767 lc->type = LAMENT_TASER_SLIDE_IN;
1768 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1772 case LAMENT_TASER_SLIDE_IN:
1773 lc->anim_y -= 0.0025;
1774 if (lc->anim_y <= 0.0)
1777 lc->type = LAMENT_TASER_IN;
1778 lc->anim_pause = pause;
1782 case LAMENT_TASER_IN:
1783 lc->anim_z -= 0.0025;
1784 if (lc->anim_z <= 0.0)
1787 lc->type = LAMENT_BOX;
1788 lc->anim_pause = pause3;
1800 /* Window management, etc
1804 reshape_lament(ModeInfo *mi, int width, int height)
1806 GLfloat h = (GLfloat) height / (GLfloat) width;
1807 glViewport(0, 0, (GLint) width, (GLint) height);
1809 glMatrixMode(GL_PROJECTION);
1811 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1812 glMatrixMode(GL_MODELVIEW);
1814 glTranslatef(0.0, 0.0, -40.0);
1815 glClear(GL_COLOR_BUFFER_BIT);
1820 gl_init(ModeInfo *mi)
1822 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1823 Bool wire = MI_IS_WIREFRAME(mi);
1830 static const GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1831 static const GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1833 static const GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1834 /* static const GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1835 static const GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1836 static const GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1838 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1839 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1841 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1842 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1843 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1844 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1845 set_colors(exterior_color);
1847 glEnable(GL_LIGHTING);
1848 glEnable(GL_LIGHT0);
1849 /* glEnable(GL_LIGHT1); */
1851 glEnable(GL_DEPTH_TEST);
1852 glEnable(GL_TEXTURE_2D);
1853 glEnable(GL_NORMALIZE);
1854 glEnable(GL_CULL_FACE);
1859 #ifdef HAVE_GLBINDTEXTURE
1861 for (i = 0; i < 6; i++)
1862 glGenTextures(1, &lc->texids[i]);
1864 parse_image_data(mi);
1866 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1867 /* messes up -fps */
1868 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); */
1870 for (i = 0; i < 6; i++)
1872 int height = lc->texture->width; /* assume square */
1873 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1874 set_colors(exterior_color);
1877 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1878 lc->texture->width, height, 0,
1880 /* GL_UNSIGNED_BYTE, */
1881 GL_UNSIGNED_INT_8_8_8_8_REV,
1882 (lc->texture->data +
1883 (lc->texture->bytes_per_line * height * i)));
1884 check_gl_error("texture");
1886 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1887 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1888 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1889 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1892 #else /* !HAVE_GLBINDTEXTURE */
1894 "%s: this version of GL doesn't support multiple texture maps.\n"
1895 "\tGet OpenGL 1.1.\n",
1898 #endif /* !HAVE_GLBINDTEXTURE */
1901 lc->box = glGenLists(16);
1902 lc->star1 = lc->box+1;
1903 lc->star2 = lc->box+2;
1904 lc->tetra_une = lc->box+3;
1905 lc->tetra_usw = lc->box+4;
1906 lc->tetra_dwn = lc->box+5;
1907 lc->tetra_dse = lc->box+6;
1908 lc->tetra_mid = lc->box+7;
1909 lc->lid_0 = lc->box+8;
1910 lc->lid_1 = lc->box+9;
1911 lc->lid_2 = lc->box+10;
1912 lc->lid_3 = lc->box+11;
1913 lc->lid_4 = lc->box+12;
1914 lc->taser_base = lc->box+13;
1915 lc->taser_lifter = lc->box+14;
1916 lc->taser_slider = lc->box+15;
1919 star(mi, True, wire);
1920 star(mi, False, wire);
1927 # ifdef HAVE_MESA_GL
1929 # include <signal.h>
1932 lament_signal_kludge (int sig)
1934 signal (sig, SIG_DFL);
1937 "%s: dying with signal %d (%s).\n"
1939 "\tThis is almost certainly a bug in the Mesa GL library,\n"
1940 "\tespecially if the stack trace in the core file mentions\n"
1941 "\t`lambda_textured_triangle' or `render_quad'.\n"
1943 "\tFirst make sure that you have the latest version of Mesa.\n"
1944 "\tIf that doesn't fix it, then I encourage you to report this\n"
1945 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
1949 (sig == SIGILL ? "SIGILL" :
1950 sig == SIGFPE ? "SIGFPE" :
1951 sig == SIGBUS ? "SIGBUS" :
1952 sig == SIGSEGV ? "SIGSEGV" : "???"));
1954 kill (getpid (), sig);
1958 handle_signals (void)
1960 signal (SIGILL, lament_signal_kludge);
1961 signal (SIGFPE, lament_signal_kludge);
1962 signal (SIGBUS, lament_signal_kludge);
1963 signal (SIGSEGV, lament_signal_kludge);
1965 # endif /* HAVE_MESA_GL */
1969 init_lament(ModeInfo *mi)
1971 lament_configuration *lc;
1974 lcs = (lament_configuration *)
1975 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
1978 fprintf(stderr, "%s: out of memory\n", progname);
1983 lc = &lcs[MI_SCREEN(mi)];
1986 double rot_speed = 0.5;
1987 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
1988 lc->trackball = gltrackball_init ();
1991 lc->type = LAMENT_BOX;
1992 lc->anim_pause = 300 + (random() % 100);
1994 if ((lc->glx_context = init_GL(mi)) != NULL)
1996 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2000 lc->states = (lament_type *) calloc (50, sizeof (*lc->states));
2002 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
2003 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
2004 lc->states[lc->nstates++] = LAMENT_TETRA_UNE;
2005 lc->states[lc->nstates++] = LAMENT_TETRA_USW;
2006 lc->states[lc->nstates++] = LAMENT_TETRA_DWN;
2007 lc->states[lc->nstates++] = LAMENT_TETRA_DSE;
2008 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2009 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2010 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2011 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2012 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2013 lc->states[lc->nstates++] = LAMENT_BOX;
2014 lc->states[lc->nstates++] = LAMENT_BOX;
2015 lc->states[lc->nstates++] = LAMENT_BOX;
2016 lc->states[lc->nstates++] = LAMENT_BOX;
2017 lc->states[lc->nstates++] = LAMENT_BOX;
2018 lc->states[lc->nstates++] = LAMENT_BOX;
2019 lc->states[lc->nstates++] = LAMENT_BOX;
2020 lc->states[lc->nstates++] = LAMENT_BOX;
2021 lc->states[lc->nstates++] = LAMENT_BOX;
2022 lc->states[lc->nstates++] = LAMENT_BOX;
2023 shuffle_states (lc);
2025 # ifdef HAVE_MESA_GL
2027 # endif /* HAVE_MESA_GL */
2032 draw_lament(ModeInfo *mi)
2034 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2035 Display *dpy = MI_DISPLAY(mi);
2036 Window window = MI_WINDOW(mi);
2038 if (!lc->glx_context)
2041 glDrawBuffer(GL_BACK);
2043 glXMakeCurrent(dpy, window, *(lc->glx_context));
2045 if (mi->fps_p) do_fps (mi);
2048 glXSwapBuffers(dpy, window);
2056 XSCREENSAVER_MODULE ("Lament", lament)