1 /* -*- Mode: C; tab-width: 4 -*- */
3 #if !defined( lint ) && !defined( SABER )
4 /*static const char sccsid[] = "@(#)gleidescope.c 1.0 03/06/27 xlockmore";*/
7 /* enable -grab switch */
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
17 * This file is provided AS IS with no warranties of any kind. The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof. In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
25 * 20030627 1.0 acd First Release.
26 * Texture loading code from 'glplanet'
27 * by Jamie Zawinski <jwz@jwz.org>
28 * 20030810 1.1 acd Added size flag.
29 * Now grabs screen / video / picture
30 * (uses code from 'glslideshow' by
31 * Mike Oliphant, Ben Buxton, Jamie Zawinski).
34 * Added fade code (also from glslideshow).
35 * 20031013 1.2 acd Migrated to compile without warnings under
37 * 20031023 1.3 acd Better code to limit twisting speeds.
38 * Tweaked initial rotation values.
39 * Move, Rotate, Zoom now chosen at random if
40 * no preference is given.
41 * Made grid slightly bigger so you can't see
42 * the edge when zooming and moving.
45 #include <X11/Intrinsic.h>
48 #include "xpm-ximage.h"
51 **----------------------------------------------------------------------------
53 **----------------------------------------------------------------------------
57 # define PROGCLASS "gleidescope"
58 # define HACK_INIT init_gleidescope
59 # define HACK_DRAW draw_gleidescope
60 # define HACK_RESHAPE reshape_gleidescope
61 # define HACK_HANDLE_EVENT gleidescope_handle_event
62 # define EVENT_MASK PointerMotionMask
63 # define gleidescope_opts xlockmore_opts
66 "*showFPS: False \n" \
70 # include "xlockmore.h" /* from the xscreensaver distribution */
71 #else /* !STANDALONE */
72 # include "xlock.h" /* from the xlockmore distribution */
73 #endif /* !STANDALONE */
79 /* acd TODO should all these be in gleidestruct? */
81 static Bool grab; /* grab images */
83 static Bool move; /* moving camera */
84 static Bool nomove; /* no moving camera */
85 static Bool rotate; /* rotate in place */
86 static Bool norotate; /* no rotate in place */
87 static int size = -1; /* size */
88 static Bool zoom; /* zooming camera */
89 static Bool nozoom; /* no zooming camera */
90 static char *image; /* name of texture to load */
91 static int duration; /* length of time to display grabbed image */
93 #define MAX_TANGLE_VEL 2.0
95 static float tangle = 0; /* texture angle */
96 static float tangle_vel = 0.0; /* texture velocity */
97 static float tangle_acc = 0.0; /* texture acceleration */
99 #define MAX_RANGLE_VEL 1.5
101 static float rangle = 0; /* rotate angle */
102 static float rangle_vel = 0.0; /* rotate velocity */
103 static float rangle_acc = 0.0; /* rotate acceleration */
105 static XrmOptionDescRec opts[] =
108 {"-grab", ".gleidescope.grab", XrmoptionNoArg, "true"},
110 {"-move", ".gleidescope.move", XrmoptionNoArg, "true"},
111 {"-no-move", ".gleidescope.nomove", XrmoptionNoArg, "true"},
112 {"-rotate", ".gleidescope.rotate", XrmoptionNoArg, "true"},
113 {"-no-rotate", ".gleidescope.norotate", XrmoptionNoArg, "true"},
114 /*{"-size", ".gleidescope.size", XrmoptionNoArg, "-1"},*/
115 {"-zoom", ".gleidescope.zoom", XrmoptionNoArg, "true"},
116 {"-no-zoom", ".gleidescope.nozoom", XrmoptionNoArg, "true"},
117 {"-image", ".gleidescope.image", XrmoptionSepArg, "DEFAULT"},
118 {"-duration", ".gleidescope.duration", XrmoptionSepArg, "30"},
122 static argtype vars[] = {
124 {&grab, "grab", "Grab", "False", t_Bool},
126 {&move, "move", "Move", "False", t_Bool},
127 {&nomove, "nomove", "noMove", "False", t_Bool},
128 {&rotate, "rotate", "Rotate", "False", t_Bool},
129 {&norotate, "norotate", "noRotate", "False", t_Bool},
130 /*{&size, "size", "Size", "-1", t_Int},*/
131 {&zoom, "zoom", "Zoom", "False", t_Bool},
132 {&nozoom, "nozoom", "noZoom", "False", t_Bool},
133 {&image, "image", "Image", "DEFAULT", t_String},
134 {&duration, "duration", "Duration", "30", t_Int},
137 static OptionStruct desc[] = {
139 {"-grab", "grab images to create animation"},
141 {"-move", "camera will move"},
142 {"-no-move", "camera won't move"},
143 {"-rotate", "camera will rotate"},
144 {"-no-rotate", "camera won't rotate"},
145 /*{"-size", "size of the hexagons (1-10)"},*/
146 {"-zoom", "camera will zoom"},
147 {"-no-zoom", "camera won't zoom"},
148 {"-image", "xpm / xbm image file to use for texture"},
149 {"-duration", "length of time texture will be used"},
152 ModeSpecOpt gleidescope_opts = {
153 sizeof opts / sizeof opts[0], opts,
154 sizeof vars / sizeof vars[0], vars,
159 ModStruct gleidescope_description = {
160 "gleidescope", "init_gleidescope", "draw_gleidescope", "release_gleidescope",
161 "draw_gleidescope", "init_gleidescope", NULL, &gleidescope_opts,
162 1000, 1, 2, 1, 4, 1.0, "",
163 "GL Kaleidescope", 0, NULL};
167 **-----------------------------------------------------------------------------
169 **-----------------------------------------------------------------------------
172 typedef struct hex_s {
173 GLfloat x, y, z; /* position */
182 #define MAX_FADE 500 /* number of fade cycles */
185 float cam_x_speed, cam_z_speed, cam_y_speed;
186 int cam_x_phase, cam_z_phase, cam_y_phase;
188 GLXContext *glx_context;
190 GLfloat max_tx, max_ty; /* maximum texture sizes */
191 GLuint textures[2]; /* texture handles */
192 GLuint visible; /* texture handle for new texture */
198 #define XOFFSET (0.8660254f) /* sin 60' */
199 #define YOFFSET (1.5000000f) /* cos 60' + 1 */
205 /* generates a grid with edges of given size */
206 /* acd TODO - replace hex[] with this and allow size and distance as parameters */
209 generate_grid(int size)
216 for (y = -size ; y <= size ; y++) {
217 for (x = -i ; x <= i ; x += 2) {
218 printf("{XOFFSET * %d, YOFFSET * %d, 0},\n", x, y);
232 /* edges of size 7 */
233 /* number of hexagons required to cover screen depends on camera distance */
234 /* at a distance of 10 this is just about enough. */
235 {XOFFSET * -6, YOFFSET * -6, 0},
236 {XOFFSET * -4, YOFFSET * -6, 0},
237 {XOFFSET * -2, YOFFSET * -6, 0},
238 {XOFFSET * 0, YOFFSET * -6, 0},
239 {XOFFSET * 2, YOFFSET * -6, 0},
240 {XOFFSET * 4, YOFFSET * -6, 0},
241 {XOFFSET * 6, YOFFSET * -6, 0},
243 {XOFFSET * -7, YOFFSET * -5, 0},
244 {XOFFSET * -5, YOFFSET * -5, 0},
245 {XOFFSET * -3, YOFFSET * -5, 0},
246 {XOFFSET * -1, YOFFSET * -5, 0},
247 {XOFFSET * 1, YOFFSET * -5, 0},
248 {XOFFSET * 3, YOFFSET * -5, 0},
249 {XOFFSET * 5, YOFFSET * -5, 0},
250 {XOFFSET * 7, YOFFSET * -5, 0},
252 {XOFFSET * -8, YOFFSET * -4, 0},
253 {XOFFSET * -6, YOFFSET * -4, 0},
254 {XOFFSET * -4, YOFFSET * -4, 0},
255 {XOFFSET * -2, YOFFSET * -4, 0},
256 {XOFFSET * 0, YOFFSET * -4, 0},
257 {XOFFSET * 2, YOFFSET * -4, 0},
258 {XOFFSET * 4, YOFFSET * -4, 0},
259 {XOFFSET * 6, YOFFSET * -4, 0},
260 {XOFFSET * 8, YOFFSET * -4, 0},
262 {XOFFSET * -9, YOFFSET * -3, 0},
263 {XOFFSET * -7, YOFFSET * -3, 0},
264 {XOFFSET * -5, YOFFSET * -3, 0},
265 {XOFFSET * -3, YOFFSET * -3, 0},
266 {XOFFSET * -1, YOFFSET * -3, 0},
267 {XOFFSET * 1, YOFFSET * -3, 0},
268 {XOFFSET * 3, YOFFSET * -3, 0},
269 {XOFFSET * 5, YOFFSET * -3, 0},
270 {XOFFSET * 7, YOFFSET * -3, 0},
271 {XOFFSET * 9, YOFFSET * -3, 0},
273 {XOFFSET * -10, YOFFSET * -2, 0},
274 {XOFFSET * -8, YOFFSET * -2, 0},
275 {XOFFSET * -6, YOFFSET * -2, 0},
276 {XOFFSET * -4, YOFFSET * -2, 0},
277 {XOFFSET * -2, YOFFSET * -2, 0},
278 {XOFFSET * 0, YOFFSET * -2, 0},
279 {XOFFSET * 2, YOFFSET * -2, 0},
280 {XOFFSET * 4, YOFFSET * -2, 0},
281 {XOFFSET * 6, YOFFSET * -2, 0},
282 {XOFFSET * 8, YOFFSET * -2, 0},
283 {XOFFSET * 10, YOFFSET * -2, 0},
285 {XOFFSET * -11, YOFFSET * -1, 0},
286 {XOFFSET * -9, YOFFSET * -1, 0},
287 {XOFFSET * -7, YOFFSET * -1, 0},
288 {XOFFSET * -5, YOFFSET * -1, 0},
289 {XOFFSET * -3, YOFFSET * -1, 0},
290 {XOFFSET * -1, YOFFSET * -1, 0},
291 {XOFFSET * 1, YOFFSET * -1, 0},
292 {XOFFSET * 3, YOFFSET * -1, 0},
293 {XOFFSET * 5, YOFFSET * -1, 0},
294 {XOFFSET * 7, YOFFSET * -1, 0},
295 {XOFFSET * 9, YOFFSET * -1, 0},
296 {XOFFSET * 11, YOFFSET * -1, 0},
298 {XOFFSET * -12, YOFFSET * 0, 0},
299 {XOFFSET * -10, YOFFSET * 0, 0},
300 {XOFFSET * -8, YOFFSET * 0, 0},
301 {XOFFSET * -6, YOFFSET * 0, 0},
302 {XOFFSET * -4, YOFFSET * 0, 0},
303 {XOFFSET * -2, YOFFSET * 0, 0},
304 {XOFFSET * 0, YOFFSET * 0, 0},
305 {XOFFSET * 2, YOFFSET * 0, 0},
306 {XOFFSET * 4, YOFFSET * 0, 0},
307 {XOFFSET * 6, YOFFSET * 0, 0},
308 {XOFFSET * 8, YOFFSET * 0, 0},
309 {XOFFSET * 10, YOFFSET * 0, 0},
310 {XOFFSET * 12, YOFFSET * 0, 0},
312 {XOFFSET * -11, YOFFSET * 1, 0},
313 {XOFFSET * -9, YOFFSET * 1, 0},
314 {XOFFSET * -7, YOFFSET * 1, 0},
315 {XOFFSET * -5, YOFFSET * 1, 0},
316 {XOFFSET * -3, YOFFSET * 1, 0},
317 {XOFFSET * -1, YOFFSET * 1, 0},
318 {XOFFSET * 1, YOFFSET * 1, 0},
319 {XOFFSET * 3, YOFFSET * 1, 0},
320 {XOFFSET * 5, YOFFSET * 1, 0},
321 {XOFFSET * 7, YOFFSET * 1, 0},
322 {XOFFSET * 9, YOFFSET * 1, 0},
323 {XOFFSET * 11, YOFFSET * 1, 0},
325 {XOFFSET * -10, YOFFSET * 2, 0},
326 {XOFFSET * -8, YOFFSET * 2, 0},
327 {XOFFSET * -6, YOFFSET * 2, 0},
328 {XOFFSET * -4, YOFFSET * 2, 0},
329 {XOFFSET * -2, YOFFSET * 2, 0},
330 {XOFFSET * 0, YOFFSET * 2, 0},
331 {XOFFSET * 2, YOFFSET * 2, 0},
332 {XOFFSET * 4, YOFFSET * 2, 0},
333 {XOFFSET * 6, YOFFSET * 2, 0},
334 {XOFFSET * 8, YOFFSET * 2, 0},
335 {XOFFSET * 10, YOFFSET * 2, 0},
337 {XOFFSET * -9, YOFFSET * 3, 0},
338 {XOFFSET * -7, YOFFSET * 3, 0},
339 {XOFFSET * -5, YOFFSET * 3, 0},
340 {XOFFSET * -3, YOFFSET * 3, 0},
341 {XOFFSET * -1, YOFFSET * 3, 0},
342 {XOFFSET * 1, YOFFSET * 3, 0},
343 {XOFFSET * 3, YOFFSET * 3, 0},
344 {XOFFSET * 5, YOFFSET * 3, 0},
345 {XOFFSET * 7, YOFFSET * 3, 0},
346 {XOFFSET * 9, YOFFSET * 3, 0},
348 {XOFFSET * -8, YOFFSET * 4, 0},
349 {XOFFSET * -6, YOFFSET * 4, 0},
350 {XOFFSET * -4, YOFFSET * 4, 0},
351 {XOFFSET * -2, YOFFSET * 4, 0},
352 {XOFFSET * 0, YOFFSET * 4, 0},
353 {XOFFSET * 2, YOFFSET * 4, 0},
354 {XOFFSET * 4, YOFFSET * 4, 0},
355 {XOFFSET * 6, YOFFSET * 4, 0},
356 {XOFFSET * 8, YOFFSET * 4, 0},
358 {XOFFSET * -7, YOFFSET * 5, 0},
359 {XOFFSET * -5, YOFFSET * 5, 0},
360 {XOFFSET * -3, YOFFSET * 5, 0},
361 {XOFFSET * -1, YOFFSET * 5, 0},
362 {XOFFSET * 1, YOFFSET * 5, 0},
363 {XOFFSET * 3, YOFFSET * 5, 0},
364 {XOFFSET * 5, YOFFSET * 5, 0},
365 {XOFFSET * 7, YOFFSET * 5, 0},
367 {XOFFSET * -6, YOFFSET * 6, 0},
368 {XOFFSET * -4, YOFFSET * 6, 0},
369 {XOFFSET * -2, YOFFSET * 6, 0},
370 {XOFFSET * 0, YOFFSET * 6, 0},
371 {XOFFSET * 2, YOFFSET * 6, 0},
372 {XOFFSET * 4, YOFFSET * 6, 0},
373 {XOFFSET * 6, YOFFSET * 6, 0},
377 **----------------------------------------------------------------------------
379 **----------------------------------------------------------------------------
382 static gleidestruct *gleidescope = NULL;
385 *load defaults in config structure
387 void setdefaultconfig(void)
400 static double xmouse = 0.0;
401 static double ymouse = 0.0;
404 gleidescope_handle_event(ModeInfo *mi, XEvent *event)
406 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
409 printf("event:%d\n", event->xany.type);
410 printf("button:%d\n", event->xbutton.button);
412 switch(event->xany.type)
416 if (event->xbutton.button == Button1 ||
417 event->xbutton.button == Button3)
419 /* store initial values of mouse */
420 xstart = event->xbutton.x;
421 ystart = event->xbutton.y;
424 gp->button_down_p = True;
428 else if (event->xbutton.button == Button4)
433 else if (event->xbutton.button == Button5)
443 if (event->xbutton.button == Button1 ||
444 event->xbutton.button == Button3)
447 gp->button_down_p = False;
454 if (gp->button_down_p)
456 /* update mouse position */
457 xmouse += (double)(event->xmotion.x - xstart) / MI_WIDTH(mi);
458 ymouse += (double)(event->xmotion.y - ystart) / MI_HEIGHT(mi);
459 xstart = event->xmotion.x;
460 ystart = event->xmotion.y;
470 #include "grab-ximage.h"
473 getSnapshot(ModeInfo *mi, GLuint name)
475 Bool mipmap_p = True;
477 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
479 if (MI_IS_WIREFRAME(mi))
482 glBindTexture (GL_TEXTURE_2D, name);
483 if (! screen_to_texture (mi->xgwa.screen, mi->window, 0, 0,
484 mipmap_p, NULL, NULL, &iw, &ih, &tw, &th))
487 gp->max_tx = (GLfloat) iw / tw;
488 gp->max_ty = (GLfloat) ih / th;
490 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
491 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
492 (mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
494 /* remember time of last image change */
495 gp->start_time = time ((time_t *) 0);
499 setup_file_texture (ModeInfo *mi, char *filename, GLuint name)
501 Display *dpy = mi->dpy;
502 Visual *visual = mi->xgwa.visual;
505 Colormap cmap = mi->xgwa.colormap;
506 XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
508 /* use this texture */
509 glBindTexture(GL_TEXTURE_2D, name);
512 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
513 image->width, image->height, 0,
514 GL_RGBA, GL_UNSIGNED_BYTE, image->data);
515 sprintf (buf, "texture: %.100s (%dx%d)",
516 filename, image->width, image->height);
519 /* setup parameters for texturing */
520 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
521 glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
523 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
524 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
525 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
526 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
527 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
531 setup_texture(ModeInfo * mi, GLuint id)
533 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
535 if (!image || !*image || !strcmp(image, "DEFAULT")) {
536 /* no image specified - grab screen */
538 /* max_tx and max_ty set in getSnapshot() */
540 /* use supplied image file */
541 setup_file_texture(mi, image, id);
543 /* set tx params to use whole image */
548 check_gl_error("texture initialization");
550 /* Need to flip the texture top for bottom for some reason. */
551 glMatrixMode (GL_TEXTURE);
553 glMatrixMode (GL_MODELVIEW);
556 #define VERTEX0 glVertex3f( 0.0000f, 0.000f, 0.0f);
557 #define VERTEX1 glVertex3f( 0.0000f, 1.000f, 0.0f);
558 #define VERTEX2 glVertex3f( XOFFSET, 0.500f, 0.0f);
559 #define VERTEX3 glVertex3f( XOFFSET, -0.500f, 0.0f);
560 #define VERTEX4 glVertex3f( 0.0000f, -1.000f, 0.0f);
561 #define VERTEX5 glVertex3f(-XOFFSET, -0.500f, 0.0f);
562 #define VERTEX6 glVertex3f(-XOFFSET, 0.500f, 0.0f);
565 draw_hexagons(ModeInfo *mi, int translucency, GLuint texture)
569 GLfloat t1x, t1y, t2x, t2y, t3x, t3y;
570 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
576 col[3] = (float)translucency / MAX_FADE;
578 /* calculate vertices of equilateral triangle within image. */
579 /* t1 is always in centre */
580 t1x = gp->max_tx / 2;
581 t1y = gp->max_ty / 2;
583 t2x = (gp->max_tx / 2) * (1 + cos((ymouse * 2 * M_PI) + (tangle * M_PI / 180)));
584 t2y = (gp->max_ty / 2) * (1 + sin((ymouse * 2 * M_PI) + (tangle * M_PI / 180)));
585 /* t3 is always 60' further around than t2 */
586 tangle2 = (ymouse * 2 * M_PI) + (tangle * M_PI / 180) + (M_PI * 2 / 6);
587 t3x = (gp->max_tx / 2) * (1 + (cos(tangle2)));
588 t3y = (gp->max_ty / 2) * (1 + (sin(tangle2)));
589 /* NB image is flipped vertically hence: */
593 /*printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t1x, t1y, t2x, t2y, gp->max_tx, gp->max_ty);*/
595 glColor4f(1.0, 1.0, 1.0, (float)translucency / MAX_FADE);
596 glEnable(GL_TEXTURE_2D);
598 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
599 glDepthMask(GL_FALSE);
600 glBindTexture(GL_TEXTURE_2D, gp->textures[texture]);
602 for (i = 0 ; i < sizeof(hex) / sizeof(hex[0]) ; i++) {
606 glTranslatef(hex[i].x, hex[i].y, 0.0);
608 glBegin(GL_TRIANGLES);
611 ** six triangles to each hexagon
614 glTexCoord2f(t1x, t1y);
616 glTexCoord2f(t2x, t2y);
618 glTexCoord2f(t3x, t3y);
621 glTexCoord2f(t1x, t1y);
623 glTexCoord2f(t3x, t3y);
625 glTexCoord2f(t2x, t2y);
628 glTexCoord2f(t1x, t1y);
630 glTexCoord2f(t2x, t2y);
632 glTexCoord2f(t3x, t3y);
635 glTexCoord2f(t1x, t1y);
637 glTexCoord2f(t3x, t3y);
639 glTexCoord2f(t2x, t2y);
642 glTexCoord2f(t1x, t1y);
644 glTexCoord2f(t2x, t2y);
646 glTexCoord2f(t3x, t3y);
649 glTexCoord2f(t1x, t1y);
651 glTexCoord2f(t3x, t3y);
653 glTexCoord2f(t2x, t2y);
661 #ifdef DISPLAY_TEXTURE
663 /* acd debug - display (bigger, centred) texture */
664 glScalef(2.0, 2.0, 2.0);
665 glTranslatef(-0.5, -0.5, 0.0);
667 glTexCoord2f(0.0, 0.0);
668 glVertex3f(0.0, 0.0, -0.1);
669 glTexCoord2f(1.0, 0.0);
670 glVertex3f(1.0, 0.0, -0.1);
671 glTexCoord2f(1.0, 1.0);
672 glVertex3f(1.0, 1.0, -0.1);
673 glTexCoord2f(0.0, 1.0);
674 glVertex3f(0.0, 1.0, -0.1);
676 /* acd debug - display texture triangle */
677 glColor4f(1.0, 1.0, 1.0, 1.0);
678 glBegin(GL_LINE_LOOP);
679 glVertex3f(t1x, t1y, -0.11);
680 glVertex3f(t2x, t2y, -0.11);
681 glVertex3f(t3x, t3y, -0.11);
686 glDisable(GL_TEXTURE_2D);
687 glDepthMask(GL_TRUE);
692 * main rendering loop
697 GLfloat x_angle, y_angle, z_angle;
698 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
702 glClearColor(0.5, 0.5, 0.5, 1.0);
703 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
708 x_angle = gp->cam_x_phase + gp->tic * gp->cam_x_speed;
709 y_angle = gp->cam_y_phase + gp->tic * gp->cam_y_speed;
710 z_angle = gp->cam_z_phase + gp->tic * gp->cam_z_speed;
713 v1.x = 2 * sin(x_angle);
714 v1.y = 2 * sin(y_angle);
720 /* size is changed in pinit() to be distance from plane */
729 /* user defined size */
732 /* max distance given by adding the constant and the multiplier */
733 v1.z = 5.0 + 4.0 * sin(z_angle);
739 /* update rotation angle (but not if mouse button down) */
740 if (rotate && !gp->button_down_p)
742 float new_rangle_vel = 0.0;
744 /* update camera rotation angle and velocity */
745 rangle += rangle_vel;
746 new_rangle_vel = rangle_vel + rangle_acc;
747 if (new_rangle_vel > -MAX_RANGLE_VEL && new_rangle_vel < MAX_RANGLE_VEL)
749 /* new velocity is within limits */
750 rangle_vel = new_rangle_vel;
753 /* randomly change twisting speed */
754 if ((random() % 1000) < 1)
756 rangle_acc = frand(0.002) - 0.001;
761 /* this makes the image wobble - requires -move and a larger grid */
762 gluLookAt(0, 0, v1.z, v1.x, v1.y, 0.0, 0.0, 1.0, 0.0);
764 /* no wobble - camera always perpendicular to grid */
766 /* rotating camera rather than entire space - smoother */
770 sin((xmouse * M_PI * 2) + rangle * M_PI / 180),
771 cos((xmouse * M_PI * 2) + rangle * M_PI / 180),
775 /* light position same as camera */
784 draw_hexagons(mi, MAX_FADE, gp->visible);
788 /* fading - show both textures with alpha */
789 draw_hexagons(mi, MAX_FADE - gp->fade, gp->visible);
790 draw_hexagons(mi, gp->fade, 1 - gp->visible);
795 /* have we faded enough? */
796 if (gp->fade > MAX_FADE)
800 gp->visible = 1 - gp->visible;
804 /* increment texture angle based on time, velocity etc */
805 /* but only if button is not down */
806 if (!gp->button_down_p)
808 float new_tangle_vel = 0.0;
810 tangle += tangle_vel;
812 /* work out new texture angle velocity */
813 new_tangle_vel = tangle_vel + tangle_acc;
814 if (new_tangle_vel > -MAX_TANGLE_VEL && new_tangle_vel < MAX_TANGLE_VEL)
816 /* new velocity is inside limits */
817 tangle_vel = new_tangle_vel;
820 /* randomly change texture angle acceleration */
821 if ((random() % 1000) < 1)
823 tangle_acc = frand(0.002) - 0.001;
831 * new window size or exposure
833 void reshape_gleidescope(ModeInfo *mi, int width, int height)
835 GLfloat h = (GLfloat) height / (GLfloat) width;
837 glViewport(0, 0, (GLint) width, (GLint) height);
838 glMatrixMode(GL_PROJECTION);
840 gluPerspective(50.0, 1/h, 0.1, 2000.0);
841 glMatrixMode (GL_MODELVIEW);
850 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
852 /* set start time - star_time = 0 implies non-dynamic texture */
853 gp->start_time = (time_t)0;
855 /* set the texture size to default */
862 glShadeModel(GL_SMOOTH);
863 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
864 glEnable(GL_DEPTH_TEST);
865 glEnable(GL_CULL_FACE);
866 glDisable(GL_LIGHTING);
868 /* space for textures */
869 glGenTextures(1, &gp->textures[0]);
870 glGenTextures(1, &gp->textures[1]);
873 setup_texture(mi, gp->textures[gp->visible]);
876 ** want to choose a value for arg randomly if neither -arg nor -no-arg
877 ** is specified. xscreensaver libraries don't seem to let you do this -
878 ** if something isn't true then it is false (pesky two-state boolean values).
879 ** so, i've defined both -arg and -no-arg to arguments and added the
881 ** (btw if both -arg and -no-arg are defined then arg is set to False)
883 if (zoom == False && nozoom == False)
885 /* no zoom preference - randomise */
886 zoom = (((random() & 0x1) == 0x1) ? True : False);
888 else if (nozoom == True)
890 /* definately no zoom */
894 if (move == False && nomove == False)
896 /* no move preference - randomise */
897 move = (((random() & 0x1) == 0x1) ? True : False);
899 else if (nomove == True)
901 /* definately no move */
905 if (rotate == False && norotate == False)
907 /* no rotate preference - randomise */
908 rotate = (((random() & 0x1) == 0x1) ? True : False);
910 else if (norotate == True)
912 /* definately no rotate */
916 /* define cam variables */
917 gp->cam_x_speed = frand(3.0) - 1.5;
918 gp->cam_x_phase = random() % 360;
919 gp->cam_y_speed = frand(3.0) - 1.5;
920 gp->cam_y_phase = random() % 360;
921 gp->cam_z_speed = frand(3.0) - 1.5;
922 gp->cam_z_phase = random() % 360;
924 /* initial angular speeds */
925 rangle_vel = frand(0.2) - 0.1;
926 tangle_vel = frand(0.2) - 0.1;
927 rangle_acc = frand(0.002) - 0.001;
928 tangle_acc = frand(0.002) - 0.001;
939 /* distance is 11 - size */
942 fprintf(stderr, "-size given. ignoring -zoom.\n");
947 } else if (size >= 10) {
954 printf("phases [%d, %d, %d]\n", gp->cam_x_phase, gp->cam_y_phase, gp->cam_z_phase);
959 init_gleidescope(ModeInfo * mi)
962 int screen = MI_SCREEN(mi);
965 if (gleidescope == NULL) {
966 gleidescope = (gleidestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (gleidestruct));
967 if (gleidescope == NULL) {
971 gp = &gleidescope[screen];
972 gp->window = MI_WINDOW(mi);
974 if ((gp->glx_context = init_GL(mi)) != NULL) {
976 reshape_gleidescope(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
978 glDrawBuffer(GL_BACK);
980 /* do initialisation */
989 draw_gleidescope(ModeInfo * mi)
991 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
992 Display *display = MI_DISPLAY(mi);
993 Window window = MI_WINDOW(mi);
996 if (!gp->glx_context)
999 glDrawBuffer(GL_BACK);
1001 glXMakeCurrent(display, window, *(gp->glx_context));
1009 glXSwapBuffers(display, window);
1017 /* need to change texture? */
1018 if ((gp->start_time != 0) && (duration != -1) && gp->fade == 0) {
1019 if (gp->start_time + duration <= time((time_t *)0)) {
1020 /* get new snapshot (into back buffer) and start fade count */
1021 getSnapshot(mi, gp->textures[1 - gp->visible]);
1028 release_gleidescope(ModeInfo * mi)
1030 if (gleidescope != NULL) {
1033 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
1034 gleidestruct *gp = &gleidescope[screen];
1036 /* acd - is this needed? */
1037 if (gp->glx_context) {
1038 /* Display lists MUST be freed while their glXContext is current. */
1039 glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
1041 /* acd - was code here for freeing things that are no longer in struct */
1044 (void) free((void *) gleidescope);