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 gltrackball_rotate (lc->trackball);
1427 /* Make into the screen be +Y right be +X, and up be +Z. */
1428 glRotatef(-90.0, 1.0, 0.0, 0.0);
1430 scale_for_window (mi);
1435 /* Shift to the upper left, and draw the vanilla box. */
1436 glTranslatef(-0.6, 0.0, 0.6);
1438 /* Apply rotation to the object. */
1439 glRotatef(x * 360, 1.0, 0.0, 0.0);
1440 glRotatef(y * 360, 0.0, 1.0, 0.0);
1441 glRotatef(z * 360, 0.0, 0.0, 1.0);
1444 glCallList(lc->box);
1448 /* Shift to the lower right, and draw the animated object. */
1449 glTranslatef(0.6, 0.0, -0.6);
1455 /* Apply rotation to the object. */
1456 if (lc->type != LAMENT_LID_ZOOM)
1457 get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
1458 !lc->button_down_p);
1459 glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
1460 glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
1461 glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
1468 glCallList(lc->box);
1471 case LAMENT_STAR_OUT:
1472 case LAMENT_STAR_ROT:
1473 case LAMENT_STAR_ROT_IN:
1474 case LAMENT_STAR_ROT_OUT:
1475 case LAMENT_STAR_UNROT:
1476 case LAMENT_STAR_IN:
1477 glTranslatef(0.0, 0.0, lc->anim_z/2);
1478 glRotatef(lc->anim_r/2, 0.0, 0.0, 1.0);
1479 glCallList(lc->star1);
1481 glTranslatef(0.0, 0.0, -lc->anim_z);
1482 glRotatef(-lc->anim_r, 0.0, 0.0, 1.0);
1483 glCallList(lc->star2);
1486 case LAMENT_TETRA_UNE:
1487 case LAMENT_TETRA_USW:
1488 case LAMENT_TETRA_DWN:
1489 case LAMENT_TETRA_DSE:
1494 case LAMENT_TETRA_UNE: magic = lc->tetra_une;
1495 x = 1.0; y = 1.0; z = 1.0; break;
1496 case LAMENT_TETRA_USW: magic = lc->tetra_usw;
1497 x = 1.0; y = 1.0; z = -1.0; break;
1498 case LAMENT_TETRA_DWN: magic = lc->tetra_dwn;
1499 x = 1.0; y = -1.0; z = 1.0; break;
1500 case LAMENT_TETRA_DSE: magic = lc->tetra_dse;
1501 x = -1.0; y = 1.0; z = 1.0; break;
1502 default: abort(); break;
1504 glCallList(lc->tetra_mid);
1505 if (magic != lc->tetra_une) glCallList(lc->tetra_une);
1506 if (magic != lc->tetra_usw) glCallList(lc->tetra_usw);
1507 if (magic != lc->tetra_dwn) glCallList(lc->tetra_dwn);
1508 if (magic != lc->tetra_dse) glCallList(lc->tetra_dse);
1509 glRotatef(lc->anim_r, x, y, z);
1514 case LAMENT_LID_OPEN:
1515 case LAMENT_LID_CLOSE:
1516 case LAMENT_LID_ZOOM:
1520 glTranslatef(lc->anim_z, 0.0, 0.0);
1522 glCallList(lc->lid_0);
1525 glTranslatef(-0.5, -d, 0.0);
1526 glRotatef(-lc->anim_r, 0.0, -1.0, -1.0);
1527 glTranslatef( 0.5, d, 0.0);
1528 glCallList(lc->lid_1);
1531 glTranslatef(-0.5, -d, 0.0);
1532 glRotatef( lc->anim_r, 0.0, -1.0, 1.0);
1533 glTranslatef( 0.5, d, 0.0);
1534 glCallList(lc->lid_2);
1537 glTranslatef(-0.5, d, 0.0);
1538 glRotatef( lc->anim_r, 0.0, -1.0, -1.0);
1539 glTranslatef( 0.5, -d, 0.0);
1540 glCallList(lc->lid_3);
1543 glTranslatef(-0.5, d, 0.0);
1544 glRotatef(-lc->anim_r, 0.0, -1.0, 1.0);
1545 glTranslatef( 0.5, -d, 0.0);
1546 glCallList(lc->lid_4);
1551 case LAMENT_TASER_OUT:
1552 case LAMENT_TASER_SLIDE:
1553 case LAMENT_TASER_SLIDE_IN:
1554 case LAMENT_TASER_IN:
1556 glTranslatef(-lc->anim_z/2, 0.0, 0.0);
1557 glCallList(lc->taser_base);
1559 glTranslatef(lc->anim_z, 0.0, 0.0);
1560 glCallList(lc->taser_lifter);
1562 glTranslatef(0.0, 0.0, lc->anim_y);
1563 glCallList(lc->taser_slider);
1577 /* Rather than just picking states randomly, pick an ordering randomly, do it,
1578 and then re-randomize. That way one can be assured of seeing all states in
1579 a short time period, though not always in the same order (it's frustrating
1580 to see it pick the same state 5x in a row.)
1583 shuffle_states (lament_configuration *lc)
1586 for (i = 0; i < lc->nstates; i++)
1588 int a = random() % lc->nstates;
1589 lament_type swap = lc->states[a];
1590 lc->states[a] = lc->states[i];
1591 lc->states[i] = swap;
1597 animate(ModeInfo *mi)
1599 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1601 /* int pause2 = 60;*/
1609 if (lc->state >= lc->nstates)
1611 shuffle_states (lc);
1614 lc->type = lc->states[lc->state];
1616 if (lc->type == LAMENT_BOX)
1617 lc->anim_pause = pause3;
1625 /* -------------------------------------------------------------- */
1627 case LAMENT_STAR_OUT:
1629 if (lc->anim_z >= 1.0)
1632 lc->type = LAMENT_STAR_ROT;
1633 lc->anim_pause = pause;
1637 case LAMENT_STAR_ROT:
1639 if (lc->anim_r >= 45.0)
1642 lc->type = LAMENT_STAR_ROT_IN;
1643 lc->anim_pause = pause;
1647 case LAMENT_STAR_ROT_IN:
1649 if (lc->anim_z <= 0.0)
1652 lc->type = LAMENT_STAR_ROT_OUT;
1653 lc->anim_pause = pause3 * (1 + (random() % 4) + (random() % 4));
1657 case LAMENT_STAR_ROT_OUT:
1659 if (lc->anim_z >= 1.0)
1662 lc->type = LAMENT_STAR_UNROT;
1663 lc->anim_pause = pause;
1667 case LAMENT_STAR_UNROT:
1669 if (lc->anim_r <= 0.0)
1672 lc->type = LAMENT_STAR_IN;
1673 lc->anim_pause = pause;
1677 case LAMENT_STAR_IN:
1679 if (lc->anim_z <= 0.0)
1682 lc->type = LAMENT_BOX;
1683 lc->anim_pause = pause3;
1687 /* -------------------------------------------------------------- */
1689 case LAMENT_TETRA_UNE:
1690 case LAMENT_TETRA_USW:
1691 case LAMENT_TETRA_DWN:
1692 case LAMENT_TETRA_DSE:
1695 if (lc->anim_r >= 360.0)
1698 lc->type = LAMENT_BOX;
1699 lc->anim_pause = pause3;
1701 else if (lc->anim_r > 119.0 && lc->anim_r <= 120.0)
1704 lc->anim_pause = pause;
1706 else if (lc->anim_r > 239.0 && lc->anim_r <= 240.0)
1709 lc->anim_pause = pause;
1713 /* -------------------------------------------------------------- */
1715 case LAMENT_LID_OPEN:
1718 if (lc->anim_r >= 112.0)
1722 lc->anim_pause = pause3;
1723 lc->type = (lc->facing_p ? LAMENT_LID_ZOOM : LAMENT_LID_CLOSE);
1727 case LAMENT_LID_CLOSE:
1729 if (lc->anim_r <= 0.0)
1732 lc->type = LAMENT_BOX;
1733 lc->anim_pause = pause3;
1737 case LAMENT_LID_ZOOM:
1739 if (lc->anim_z < -50.0)
1743 lc->type = LAMENT_BOX;
1747 /* -------------------------------------------------------------- */
1749 case LAMENT_TASER_OUT:
1750 lc->anim_z += 0.0025;
1751 if (lc->anim_z >= 0.25)
1754 lc->type = LAMENT_TASER_SLIDE;
1755 lc->anim_pause = pause * (1 + (random() % 5) + (random() % 5));
1759 case LAMENT_TASER_SLIDE:
1760 lc->anim_y += 0.0025;
1761 if (lc->anim_y >= 0.23)
1764 lc->type = LAMENT_TASER_SLIDE_IN;
1765 lc->anim_pause = pause3 * (1 + (random() % 5) + (random() % 5));
1769 case LAMENT_TASER_SLIDE_IN:
1770 lc->anim_y -= 0.0025;
1771 if (lc->anim_y <= 0.0)
1774 lc->type = LAMENT_TASER_IN;
1775 lc->anim_pause = pause;
1779 case LAMENT_TASER_IN:
1780 lc->anim_z -= 0.0025;
1781 if (lc->anim_z <= 0.0)
1784 lc->type = LAMENT_BOX;
1785 lc->anim_pause = pause3;
1797 /* Window management, etc
1801 reshape_lament(ModeInfo *mi, int width, int height)
1803 GLfloat h = (GLfloat) height / (GLfloat) width;
1804 glViewport(0, 0, (GLint) width, (GLint) height);
1806 glMatrixMode(GL_PROJECTION);
1808 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1809 glMatrixMode(GL_MODELVIEW);
1811 glTranslatef(0.0, 0.0, -40.0);
1812 glClear(GL_COLOR_BUFFER_BIT);
1817 gl_init(ModeInfo *mi)
1819 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
1820 Bool wire = MI_IS_WIREFRAME(mi);
1827 static const GLfloat pos0[] = { -4.0, 2.0, 5.0, 1.0 };
1828 static const GLfloat pos1[] = { 6.0, -1.0, 3.0, 1.0 };
1830 static const GLfloat amb0[] = { 0.7, 0.7, 0.7, 1.0 };
1831 /* static const GLfloat amb1[] = { 0.7, 0.0, 0.0, 1.0 }; */
1832 static const GLfloat dif0[] = { 1.0, 1.0, 1.0, 1.0 };
1833 static const GLfloat dif1[] = { 0.3, 0.1, 0.1, 1.0 };
1835 glLightfv(GL_LIGHT0, GL_POSITION, pos0);
1836 glLightfv(GL_LIGHT1, GL_POSITION, pos1);
1838 glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
1839 /* glLightfv(GL_LIGHT1, GL_AMBIENT, amb1); */
1840 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif0);
1841 glLightfv(GL_LIGHT1, GL_DIFFUSE, dif1);
1842 set_colors(exterior_color);
1844 glEnable(GL_LIGHTING);
1845 glEnable(GL_LIGHT0);
1846 /* glEnable(GL_LIGHT1); */
1848 glEnable(GL_DEPTH_TEST);
1849 glEnable(GL_TEXTURE_2D);
1850 glEnable(GL_NORMALIZE);
1851 glEnable(GL_CULL_FACE);
1856 #ifdef HAVE_GLBINDTEXTURE
1858 for (i = 0; i < 6; i++)
1859 glGenTextures(1, &lc->texids[i]);
1861 parse_image_data(mi);
1863 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1864 /* messes up -fps */
1865 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); */
1867 for (i = 0; i < 6; i++)
1869 int height = lc->texture->width; /* assume square */
1870 glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
1871 set_colors(exterior_color);
1874 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1875 lc->texture->width, height, 0,
1877 /* GL_UNSIGNED_BYTE, */
1878 GL_UNSIGNED_INT_8_8_8_8_REV,
1879 (lc->texture->data +
1880 (lc->texture->bytes_per_line * height * i)));
1881 check_gl_error("texture");
1883 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1884 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1885 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1886 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1889 #else /* !HAVE_GLBINDTEXTURE */
1891 "%s: this version of GL doesn't support multiple texture maps.\n"
1892 "\tGet OpenGL 1.1.\n",
1895 #endif /* !HAVE_GLBINDTEXTURE */
1898 lc->box = glGenLists(16);
1899 lc->star1 = lc->box+1;
1900 lc->star2 = lc->box+2;
1901 lc->tetra_une = lc->box+3;
1902 lc->tetra_usw = lc->box+4;
1903 lc->tetra_dwn = lc->box+5;
1904 lc->tetra_dse = lc->box+6;
1905 lc->tetra_mid = lc->box+7;
1906 lc->lid_0 = lc->box+8;
1907 lc->lid_1 = lc->box+9;
1908 lc->lid_2 = lc->box+10;
1909 lc->lid_3 = lc->box+11;
1910 lc->lid_4 = lc->box+12;
1911 lc->taser_base = lc->box+13;
1912 lc->taser_lifter = lc->box+14;
1913 lc->taser_slider = lc->box+15;
1916 star(mi, True, wire);
1917 star(mi, False, wire);
1924 # ifdef HAVE_MESA_GL
1926 # include <signal.h>
1929 lament_signal_kludge (int sig)
1931 signal (sig, SIG_DFL);
1934 "%s: dying with signal %d (%s).\n"
1936 "\tThis is almost certainly a bug in the Mesa GL library,\n"
1937 "\tespecially if the stack trace in the core file mentions\n"
1938 "\t`lambda_textured_triangle' or `render_quad'.\n"
1940 "\tFirst make sure that you have the latest version of Mesa.\n"
1941 "\tIf that doesn't fix it, then I encourage you to report this\n"
1942 "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
1946 (sig == SIGILL ? "SIGILL" :
1947 sig == SIGFPE ? "SIGFPE" :
1948 sig == SIGBUS ? "SIGBUS" :
1949 sig == SIGSEGV ? "SIGSEGV" : "???"));
1951 kill (getpid (), sig);
1955 handle_signals (void)
1957 signal (SIGILL, lament_signal_kludge);
1958 signal (SIGFPE, lament_signal_kludge);
1959 signal (SIGBUS, lament_signal_kludge);
1960 signal (SIGSEGV, lament_signal_kludge);
1962 # endif /* HAVE_MESA_GL */
1966 init_lament(ModeInfo *mi)
1968 lament_configuration *lc;
1971 lcs = (lament_configuration *)
1972 calloc(MI_NUM_SCREENS(mi), sizeof (lament_configuration));
1975 fprintf(stderr, "%s: out of memory\n", progname);
1980 lc = &lcs[MI_SCREEN(mi)];
1983 double rot_speed = 0.5;
1984 lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
1985 lc->trackball = gltrackball_init ();
1988 lc->type = LAMENT_BOX;
1989 lc->anim_pause = 300 + (random() % 100);
1991 if ((lc->glx_context = init_GL(mi)) != NULL)
1993 reshape_lament(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1997 lc->states = (lament_type *) calloc (50, sizeof (*lc->states));
1999 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
2000 lc->states[lc->nstates++] = LAMENT_STAR_OUT;
2001 lc->states[lc->nstates++] = LAMENT_TETRA_UNE;
2002 lc->states[lc->nstates++] = LAMENT_TETRA_USW;
2003 lc->states[lc->nstates++] = LAMENT_TETRA_DWN;
2004 lc->states[lc->nstates++] = LAMENT_TETRA_DSE;
2005 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2006 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2007 lc->states[lc->nstates++] = LAMENT_LID_OPEN;
2008 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2009 lc->states[lc->nstates++] = LAMENT_TASER_OUT;
2010 lc->states[lc->nstates++] = LAMENT_BOX;
2011 lc->states[lc->nstates++] = LAMENT_BOX;
2012 lc->states[lc->nstates++] = LAMENT_BOX;
2013 lc->states[lc->nstates++] = LAMENT_BOX;
2014 lc->states[lc->nstates++] = LAMENT_BOX;
2015 lc->states[lc->nstates++] = LAMENT_BOX;
2016 lc->states[lc->nstates++] = LAMENT_BOX;
2017 lc->states[lc->nstates++] = LAMENT_BOX;
2018 lc->states[lc->nstates++] = LAMENT_BOX;
2019 lc->states[lc->nstates++] = LAMENT_BOX;
2020 shuffle_states (lc);
2022 # ifdef HAVE_MESA_GL
2024 # endif /* HAVE_MESA_GL */
2029 draw_lament(ModeInfo *mi)
2031 lament_configuration *lc = &lcs[MI_SCREEN(mi)];
2032 Display *dpy = MI_DISPLAY(mi);
2033 Window window = MI_WINDOW(mi);
2035 if (!lc->glx_context)
2038 glDrawBuffer(GL_BACK);
2040 glXMakeCurrent(dpy, window, *(lc->glx_context));
2042 if (mi->fps_p) do_fps (mi);
2045 glXSwapBuffers(dpy, window);
2053 XSCREENSAVER_MODULE ("Lament", lament)