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)];
1382 /* No texture created in -wireframe or -no-texture, so guess. */
1383 int target_size = (lc->texture
1384 ? lc->texture->width * 1.4
1386 int win_size = (MI_WIDTH(mi) > MI_HEIGHT(mi) ? MI_HEIGHT(mi) : MI_WIDTH(mi));
1388 /* This scale makes the box take up most of the window */
1391 /* But if the window is more than a little larger than our target size,
1392 scale the object back down, so that the bits drawn on the screen end
1393 up rougly target_size across (actually it ends up a little larger.)
1394 Note that the image-map bits we have are 128x128. Therefore, if the
1395 image is magnified a lot, it looks pretty blocky. So it's better to
1396 have a 128x128 animation on a 1280x1024 screen that looks good, than
1397 a 1024x1024 animation that looks really pixelated.
1401 int max = 340; /* Let's not go larger than life-sized. */
1402 if (target_size > max)
1406 if (win_size > 640 &&
1407 win_size > target_size * 1.5)
1409 GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size);
1411 glScalef(ratio, ratio, ratio);
1419 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1420 Bool wire = MI_IS_WIREFRAME(mi);
1423 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1425 glClear(GL_COLOR_BUFFER_BIT);
1429 /* Do it twice because we don't track the device's orientation. */
1430 glRotatef( current_device_rotation(), 0, 0, 1);
1431 gltrackball_rotate (lc->trackball);
1432 glRotatef(-current_device_rotation(), 0, 0, 1);
1434 /* Make into the screen be +Y right be +X, and up be +Z. */
1435 glRotatef(-90.0, 1.0, 0.0, 0.0);
1437 scale_for_window (mi);
1442 /* Shift to the upper left, and draw the vanilla box. */
1443 glTranslatef(-0.6, 0.0, 0.6);
1445 /* Apply rotation to the object. */
1446 glRotatef(x * 360, 1.0, 0.0, 0.0);
1447 glRotatef(y * 360, 0.0, 1.0, 0.0);
1448 glRotatef(z * 360, 0.0, 0.0, 1.0);
1451 glCallList(lc->box);
1455 /* Shift to the lower right, and draw the animated object. */
1456 glTranslatef(0.6, 0.0, -0.6);
1462 /* Apply rotation to the object. */
1463 if (lc->type != LAMENT_LID_ZOOM)
1464 get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
1465 !lc->button_down_p);
1466 glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
1467 glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
1468 glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
1475 glCallList(lc->box);
1478 case LAMENT_STAR_OUT:
1479 case LAMENT_STAR_ROT:
1480 case LAMENT_STAR_ROT_IN:
1481 case LAMENT_STAR_ROT_OUT:
1482 case LAMENT_STAR_UNROT:
1483 case LAMENT_STAR_IN:
1484 glTranslatef(0.0, 0.0, lc->anim_z/2);
1485 glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0);
1486 glCallList(lc->star1);
1488 glTranslatef(0.0, 0.0, -lc->anim_z);
1489 glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
1490 glCallList(lc->star2);
1493 case LAMENT_TETRA_UNE:
1494 case LAMENT_TETRA_USW:
1495 case LAMENT_TETRA_DWN:
1496 case LAMENT_TETRA_DSE:
1501 case LAMENT_TETRA_UNE: magic = lc->tetra_une;
1502 x = 1.0; y = 1.0; z = 1.0; break;
1503 case LAMENT_TETRA_USW: magic = lc->tetra_usw;
1504 x = 1.0; y = 1.0; z = -1.0; break;
1505 case LAMENT_TETRA_DWN: magic = lc->tetra_dwn;
1506 x = 1.0; y = -1.0; z = 1.0; break;
1507 case LAMENT_TETRA_DSE: magic = lc->tetra_dse;
1508 x = -1.0; y = 1.0; z = 1.0; break;
1509 default: abort(); break;
1511 glCallList(lc->tetra_mid);
1512 if (magic != lc->tetra_une) glCallList(lc->tetra_une);
1513 if (magic != lc->tetra_usw) glCallList(lc->tetra_usw);
1514 if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn);
1515 if (magic != lc->tetra_dse) glCallList(lc->tetra_dse);
1516 glRotatef(lc->anim_r, x, y, z);
1521 case LAMENT_LID_OPEN:
1522 case LAMENT_LID_CLOSE:
1523 case LAMENT_LID_ZOOM:
1527 glTranslatef(lc->anim_z, 0.0, 0.0);
1529 glCallList(lc->lid_0);
1532 glTranslatef(-0.5, -d, 0.0);
1533 glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
1534 glTranslatef( 0.5, d, 0.0);
1535 glCallList(lc->lid_1);
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_2);
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_3);
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_4);
1558 case LAMENT_TASER_OUT:
1559 case LAMENT_TASER_SLIDE:
1560 case LAMENT_TASER_SLIDE_IN:
1561 case LAMENT_TASER_IN:
1563 glTranslatef(-lc->anim_z/2, 0.0, 0.0);
1564 glCallList(lc->taser_base);
1566 glTranslatef(lc->anim_z, 0.0, 0.0);
1567 glCallList(lc->taser_lifter);
1569 glTranslatef(0.0, 0.0, lc->anim_y);
1570 glCallList(lc->taser_slider);
1584 /* Rather than just picking states randomly, pick an ordering randomly, do it,
1585 and then re-randomize. That way one can be assured of seeing all states in
1586 a short time period, though not always in the same order (it's frustrating
1587 to see it pick the same state 5x in a row.)
1590 shuffle_states (lament_configuration *lc)
1593 for (i = 0; i < lc->nstates; i++)
1595 int a = random() % lc->nstates;
1596 lament_type swap = lc->states[a];
1597 lc->states[a] = lc->states[i];
1598 lc->states[i] = swap;
1604 animate(ModeInfo *mi)
1606 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1608 /* int pause2 = 60;*/
1616 if (lc->state >= lc->nstates)
1618 shuffle_states (lc);
1621 lc->type = lc->states[lc->state];
1623 if (lc->type == LAMENT_BOX)
1624 lc->anim_pause = pause3;
1632 /* -------------------------------------------------------------- */
1634 case LAMENT_STAR_OUT:
1636 if (lc->anim_z >= 1.0)
1639 lc->type = LAMENT_STAR_ROT;
1640 lc->anim_pause = pause;
1644 case LAMENT_STAR_ROT:
1646 if (lc->anim_r >= 45.0)
1649 lc->type = LAMENT_STAR_ROT_IN;
1650 lc->anim_pause = pause;
1654 case LAMENT_STAR_ROT_IN:
1656 if (lc->anim_z <= 0.0)
1659 lc->type = LAMENT_STAR_ROT_OUT;
1660 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1664 case LAMENT_STAR_ROT_OUT:
1666 if (lc->anim_z >= 1.0)
1669 lc->type = LAMENT_STAR_UNROT;
1670 lc->anim_pause = pause;
1674 case LAMENT_STAR_UNROT:
1676 if (lc->anim_r <= 0.0)
1679 lc->type = LAMENT_STAR_IN;
1680 lc->anim_pause = pause;
1684 case LAMENT_STAR_IN:
1686 if (lc->anim_z <= 0.0)
1689 lc->type = LAMENT_BOX;
1690 lc->anim_pause = pause3;
1694 /* -------------------------------------------------------------- */
1696 case LAMENT_TETRA_UNE:
1697 case LAMENT_TETRA_USW:
1698 case LAMENT_TETRA_DWN:
1699 case LAMENT_TETRA_DSE:
1702 if (lc->anim_r >= 360.0)
1705 lc->type = LAMENT_BOX;
1706 lc->anim_pause = pause3;
1708 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1711 lc->anim_pause = pause;
1713 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1716 lc->anim_pause = pause;
1720 /* -------------------------------------------------------------- */
1722 case LAMENT_LID_OPEN:
1725 if (lc->anim_r >= 112.0)
1729 lc->anim_pause = pause3;
1730 lc->type = (lc->facing_p ? LAMENT_LID_ZOOM : LAMENT_LID_CLOSE);
1734 case LAMENT_LID_CLOSE:
1736 if (lc->anim_r <= 0.0)
1739 lc->type = LAMENT_BOX;
1740 lc->anim_pause = pause3;
1744 case LAMENT_LID_ZOOM:
1746 if (lc->anim_z < -50.0)
1750 lc->type = LAMENT_BOX;
1754 /* -------------------------------------------------------------- */
1756 case LAMENT_TASER_OUT:
1757 lc->anim_z += 0.0025;
1758 if (lc->anim_z >= 0.25)
1761 lc->type = LAMENT_TASER_SLIDE;
1762 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1766 case LAMENT_TASER_SLIDE:
1767 lc->anim_y += 0.0025;
1768 if (lc->anim_y >= 0.23)
1771 lc->type = LAMENT_TASER_SLIDE_IN;
1772 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1776 case LAMENT_TASER_SLIDE_IN:
1777 lc->anim_y -= 0.0025;
1778 if (lc->anim_y <= 0.0)
1781 lc->type = LAMENT_TASER_IN;
1782 lc->anim_pause = pause;
1786 case LAMENT_TASER_IN:
1787 lc->anim_z -= 0.0025;
1788 if (lc->anim_z <= 0.0)
1791 lc->type = LAMENT_BOX;
1792 lc->anim_pause = pause3;
1804 /* Window management, etc
1808 reshape_lament(ModeInfo *mi, int width, int height)
1810 GLfloat h = (GLfloat) height / (GLfloat) width;
1811 glViewport(0, 0, (GLint) width, (GLint) height);
1813 glMatrixMode(GL_PROJECTION);
1815 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1816 glMatrixMode(GL_MODELVIEW);
1818 glTranslatef(0.0, 0.0, -40.0);
1819 glClear(GL_COLOR_BUFFER_BIT);
1824 gl_init(ModeInfo *mi)
1826 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1827 Bool wire = MI_IS_WIREFRAME(mi);
1834 static const GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1835 static const GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1837 static const GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1838 /* static const GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1839 static const GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1840 static const GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1842 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1843 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1845 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1846 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1847 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1848 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1849 set_colors(exterior_color);
1851 glEnable(GL_LIGHTING);
1852 glEnable(GL_LIGHT0);
1853 /* glEnable(GL_LIGHT1); */
1855 glEnable(GL_DEPTH_TEST);
1856 glEnable(GL_TEXTURE_2D);
1857 glEnable(GL_NORMALIZE);
1858 glEnable(GL_CULL_FACE);
1863 #ifdef HAVE_GLBINDTEXTURE
1865 for (i = 0; i < 6; i++)
1866 glGenTextures(1, &lc->texids[i]);
1868 parse_image_data(mi);
1870 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1871 /* messes up -fps */
1872 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); */
1874 for (i = 0; i < 6; i++)
1876 int height = lc->texture->width; /* assume square */
1877 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1878 set_colors(exterior_color);
1881 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1882 lc->texture->width, height, 0,
1884 /* GL_UNSIGNED_BYTE, */
1885 GL_UNSIGNED_INT_8_8_8_8_REV,
1886 (lc->texture->data +
1887 (lc->texture->bytes_per_line * height * i)));
1888 check_gl_error("texture");
1890 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1891 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1892 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1893 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1896 #else /* !HAVE_GLBINDTEXTURE */
1898 "%s: this version of GL doesn't support multiple texture maps.\n"
1899 "\tGet OpenGL 1.1.\n",
1902 #endif /* !HAVE_GLBINDTEXTURE */
1905 lc->box = glGenLists(16);
1906 lc->star1 = lc->box+1;
1907 lc->star2 = lc->box+2;
1908 lc->tetra_une = lc->box+3;
1909 lc->tetra_usw = lc->box+4;
1910 lc->tetra_dwn = lc->box+5;
1911 lc->tetra_dse = lc->box+6;
1912 lc->tetra_mid = lc->box+7;
1913 lc->lid_0 = lc->box+8;
1914 lc->lid_1 = lc->box+9;
1915 lc->lid_2 = lc->box+10;
1916 lc->lid_3 = lc->box+11;
1917 lc->lid_4 = lc->box+12;
1918 lc->taser_base = lc->box+13;
1919 lc->taser_lifter = lc->box+14;
1920 lc->taser_slider = lc->box+15;
1923 star(mi, True, wire);
1924 star(mi, False, wire);
1931 # ifdef HAVE_MESA_GL
1933 # include <signal.h>
1936 lament_signal_kludge (int sig)
1938 signal (sig, SIG_DFL);
1941 "%s: dying with signal %d (%s).\n"
1943 "\tThis is almost certainly a bug in the Mesa GL library,\n"
1944 "\tespecially if the stack trace in the core file mentions\n"
1945 "\t`lambda_textured_triangle' or `render_quad'.\n"
1947 "\tFirst make sure that you have the latest version of Mesa.\n"
1948 "\tIf that doesn't fix it, then I encourage you to report this\n"
1949 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
1953 (sig == SIGILL ? "SIGILL" :
1954 sig == SIGFPE ? "SIGFPE" :
1955 sig == SIGBUS ? "SIGBUS" :
1956 sig == SIGSEGV ? "SIGSEGV" : "???"));
1958 kill (getpid (), sig);
1962 handle_signals (void)
1964 signal (SIGILL, lament_signal_kludge);
1965 signal (SIGFPE, lament_signal_kludge);
1966 signal (SIGBUS, lament_signal_kludge);
1967 signal (SIGSEGV, lament_signal_kludge);
1969 # endif /* HAVE_MESA_GL */
1973 init_lament(ModeInfo *mi)
1975 lament_configuration *lc;
1978 lcs = (lament_configuration *)
1979 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
1982 fprintf(stderr, "%s: out of memory\n", progname);
1987 lc = &lcs[MI_SCREEN(mi)];
1990 double rot_speed = 0.5;
1991 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
1992 lc->trackball = gltrackball_init ();
1995 lc->type = LAMENT_BOX;
1996 lc->anim_pause = 300 + (random() % 100);
1998 if ((lc->glx_context = init_GL(mi)) != NULL)
2000 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2004 lc->states = (lament_type *) calloc (50, sizeof (*lc->states));
2006 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
2007 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
2008 lc->states[lc->nstates++] = LAMENT_TETRA_UNE;
2009 lc->states[lc->nstates++] = LAMENT_TETRA_USW;
2010 lc->states[lc->nstates++] = LAMENT_TETRA_DWN;
2011 lc->states[lc->nstates++] = LAMENT_TETRA_DSE;
2012 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2013 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2014 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2015 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2016 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
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 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 shuffle_states (lc);
2029 # ifdef HAVE_MESA_GL
2031 # endif /* HAVE_MESA_GL */
2036 draw_lament(ModeInfo *mi)
2038 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2039 Display *dpy = MI_DISPLAY(mi);
2040 Window window = MI_WINDOW(mi);
2042 if (!lc->glx_context)
2045 glDrawBuffer(GL_BACK);
2047 glXMakeCurrent(dpy, window, *(lc->glx_context));
2049 if (mi->fps_p) do_fps (mi);
2052 glXSwapBuffers(dpy, window);
2060 XSCREENSAVER_MODULE ("Lament", lament)