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 "*image: DEFAULT \n" \
75 # include "xlockmore.h" /* from the xscreensaver distribution */
76 #else /* !STANDALONE */
77 # include "xlock.h" /* from the xlockmore distribution */
78 #endif /* !STANDALONE */
84 /* acd TODO should all these be in gleidestruct? */
86 static Bool grab; /* grab images */
88 static Bool move; /* moving camera */
89 static Bool nomove; /* no moving camera */
90 static Bool rotate; /* rotate in place */
91 static Bool norotate; /* no rotate in place */
92 static int size = -1; /* size */
93 static Bool zoom; /* zooming camera */
94 static Bool nozoom; /* no zooming camera */
95 static char *image; /* name of texture to load */
96 static int duration; /* length of time to display grabbed image */
98 #define MAX_TANGLE_VEL 2.0
100 static float tangle = 0; /* texture angle */
101 static float tangle_vel = 0.0; /* texture velocity */
102 static float tangle_acc = 0.0; /* texture acceleration */
104 #define MAX_RANGLE_VEL 1.5
106 static float rangle = 0; /* rotate angle */
107 static float rangle_vel = 0.0; /* rotate velocity */
108 static float rangle_acc = 0.0; /* rotate acceleration */
110 static XrmOptionDescRec opts[] =
113 {"-grab", ".gleidescope.grab", XrmoptionNoArg, "true"},
115 {"-move", ".gleidescope.move", XrmoptionNoArg, "true"},
116 {"-no-move", ".gleidescope.nomove", XrmoptionNoArg, "true"},
117 {"-rotate", ".gleidescope.rotate", XrmoptionNoArg, "true"},
118 {"-no-rotate", ".gleidescope.norotate", XrmoptionNoArg, "true"},
119 /*{"-size", ".gleidescope.size", XrmoptionNoArg, "-1"},*/
120 {"-zoom", ".gleidescope.zoom", XrmoptionNoArg, "true"},
121 {"-no-zoom", ".gleidescope.nozoom", XrmoptionNoArg, "true"},
122 {"-image", ".gleidescope.image", XrmoptionSepArg, "DEFAULT"},
123 {"-duration", ".gleidescope.duration", XrmoptionSepArg, "30"},
127 static argtype vars[] = {
129 {&grab, "grab", "Grab", "False", t_Bool},
131 {&move, "move", "Move", "False", t_Bool},
132 {&nomove, "nomove", "noMove", "False", t_Bool},
133 {&rotate, "rotate", "Rotate", "False", t_Bool},
134 {&norotate, "norotate", "noRotate", "False", t_Bool},
135 /*{&size, "size", "Size", "-1", t_Int},*/
136 {&zoom, "zoom", "Zoom", "False", t_Bool},
137 {&nozoom, "nozoom", "noZoom", "False", t_Bool},
138 {&image, "image", "Image", "DEFAULT", t_String},
139 {&duration, "duration", "Duration", "30", t_Int},
142 static OptionStruct desc[] = {
144 {"-grab", "grab images to create animation"},
146 {"-move", "camera will move"},
147 {"-no-move", "camera won't move"},
148 {"-rotate", "camera will rotate"},
149 {"-no-rotate", "camera won't rotate"},
150 /*{"-size", "size of the hexagons (1-10)"},*/
151 {"-zoom", "camera will zoom"},
152 {"-no-zoom", "camera won't zoom"},
153 {"-image", "xpm / xbm image file to use for texture"},
154 {"-duration", "length of time texture will be used"},
157 ModeSpecOpt gleidescope_opts = {
158 sizeof opts / sizeof opts[0], opts,
159 sizeof vars / sizeof vars[0], vars,
164 ModStruct gleidescope_description = {
165 "gleidescope", "init_gleidescope", "draw_gleidescope", "release_gleidescope",
166 "draw_gleidescope", "init_gleidescope", NULL, &gleidescope_opts,
167 1000, 1, 2, 1, 4, 1.0, "",
168 "GL Kaleidescope", 0, NULL};
172 **-----------------------------------------------------------------------------
174 **-----------------------------------------------------------------------------
177 typedef struct hex_s {
178 GLfloat x, y, z; /* position */
187 #define MAX_FADE 500 /* number of fade cycles */
190 float cam_x_speed, cam_z_speed, cam_y_speed;
191 int cam_x_phase, cam_z_phase, cam_y_phase;
193 GLXContext *glx_context;
195 GLfloat max_tx, max_ty; /* maximum texture sizes */
196 GLuint textures[2]; /* texture handles */
197 GLuint visible; /* texture handle for new texture */
203 #define XOFFSET (0.8660254f) /* sin 60' */
204 #define YOFFSET (1.5000000f) /* cos 60' + 1 */
210 /* generates a grid with edges of given size */
211 /* acd TODO - replace hex[] with this and allow size and distance as parameters */
214 generate_grid(int size)
221 for (y = -size ; y <= size ; y++) {
222 for (x = -i ; x <= i ; x += 2) {
223 printf("{XOFFSET * %d, YOFFSET * %d, 0},\n", x, y);
237 /* edges of size 7 */
238 /* number of hexagons required to cover screen depends on camera distance */
239 /* at a distance of 10 this is just about enough. */
240 {XOFFSET * -6, YOFFSET * -6, 0},
241 {XOFFSET * -4, YOFFSET * -6, 0},
242 {XOFFSET * -2, YOFFSET * -6, 0},
243 {XOFFSET * 0, YOFFSET * -6, 0},
244 {XOFFSET * 2, YOFFSET * -6, 0},
245 {XOFFSET * 4, YOFFSET * -6, 0},
246 {XOFFSET * 6, YOFFSET * -6, 0},
248 {XOFFSET * -7, YOFFSET * -5, 0},
249 {XOFFSET * -5, YOFFSET * -5, 0},
250 {XOFFSET * -3, YOFFSET * -5, 0},
251 {XOFFSET * -1, YOFFSET * -5, 0},
252 {XOFFSET * 1, YOFFSET * -5, 0},
253 {XOFFSET * 3, YOFFSET * -5, 0},
254 {XOFFSET * 5, YOFFSET * -5, 0},
255 {XOFFSET * 7, YOFFSET * -5, 0},
257 {XOFFSET * -8, YOFFSET * -4, 0},
258 {XOFFSET * -6, YOFFSET * -4, 0},
259 {XOFFSET * -4, YOFFSET * -4, 0},
260 {XOFFSET * -2, YOFFSET * -4, 0},
261 {XOFFSET * 0, YOFFSET * -4, 0},
262 {XOFFSET * 2, YOFFSET * -4, 0},
263 {XOFFSET * 4, YOFFSET * -4, 0},
264 {XOFFSET * 6, YOFFSET * -4, 0},
265 {XOFFSET * 8, YOFFSET * -4, 0},
267 {XOFFSET * -9, YOFFSET * -3, 0},
268 {XOFFSET * -7, YOFFSET * -3, 0},
269 {XOFFSET * -5, YOFFSET * -3, 0},
270 {XOFFSET * -3, YOFFSET * -3, 0},
271 {XOFFSET * -1, YOFFSET * -3, 0},
272 {XOFFSET * 1, YOFFSET * -3, 0},
273 {XOFFSET * 3, YOFFSET * -3, 0},
274 {XOFFSET * 5, YOFFSET * -3, 0},
275 {XOFFSET * 7, YOFFSET * -3, 0},
276 {XOFFSET * 9, YOFFSET * -3, 0},
278 {XOFFSET * -10, YOFFSET * -2, 0},
279 {XOFFSET * -8, YOFFSET * -2, 0},
280 {XOFFSET * -6, YOFFSET * -2, 0},
281 {XOFFSET * -4, YOFFSET * -2, 0},
282 {XOFFSET * -2, YOFFSET * -2, 0},
283 {XOFFSET * 0, YOFFSET * -2, 0},
284 {XOFFSET * 2, YOFFSET * -2, 0},
285 {XOFFSET * 4, YOFFSET * -2, 0},
286 {XOFFSET * 6, YOFFSET * -2, 0},
287 {XOFFSET * 8, YOFFSET * -2, 0},
288 {XOFFSET * 10, YOFFSET * -2, 0},
290 {XOFFSET * -11, YOFFSET * -1, 0},
291 {XOFFSET * -9, YOFFSET * -1, 0},
292 {XOFFSET * -7, YOFFSET * -1, 0},
293 {XOFFSET * -5, YOFFSET * -1, 0},
294 {XOFFSET * -3, YOFFSET * -1, 0},
295 {XOFFSET * -1, YOFFSET * -1, 0},
296 {XOFFSET * 1, YOFFSET * -1, 0},
297 {XOFFSET * 3, YOFFSET * -1, 0},
298 {XOFFSET * 5, YOFFSET * -1, 0},
299 {XOFFSET * 7, YOFFSET * -1, 0},
300 {XOFFSET * 9, YOFFSET * -1, 0},
301 {XOFFSET * 11, YOFFSET * -1, 0},
303 {XOFFSET * -12, YOFFSET * 0, 0},
304 {XOFFSET * -10, YOFFSET * 0, 0},
305 {XOFFSET * -8, YOFFSET * 0, 0},
306 {XOFFSET * -6, YOFFSET * 0, 0},
307 {XOFFSET * -4, YOFFSET * 0, 0},
308 {XOFFSET * -2, YOFFSET * 0, 0},
309 {XOFFSET * 0, YOFFSET * 0, 0},
310 {XOFFSET * 2, YOFFSET * 0, 0},
311 {XOFFSET * 4, YOFFSET * 0, 0},
312 {XOFFSET * 6, YOFFSET * 0, 0},
313 {XOFFSET * 8, YOFFSET * 0, 0},
314 {XOFFSET * 10, YOFFSET * 0, 0},
315 {XOFFSET * 12, YOFFSET * 0, 0},
317 {XOFFSET * -11, YOFFSET * 1, 0},
318 {XOFFSET * -9, YOFFSET * 1, 0},
319 {XOFFSET * -7, YOFFSET * 1, 0},
320 {XOFFSET * -5, YOFFSET * 1, 0},
321 {XOFFSET * -3, YOFFSET * 1, 0},
322 {XOFFSET * -1, YOFFSET * 1, 0},
323 {XOFFSET * 1, YOFFSET * 1, 0},
324 {XOFFSET * 3, YOFFSET * 1, 0},
325 {XOFFSET * 5, YOFFSET * 1, 0},
326 {XOFFSET * 7, YOFFSET * 1, 0},
327 {XOFFSET * 9, YOFFSET * 1, 0},
328 {XOFFSET * 11, YOFFSET * 1, 0},
330 {XOFFSET * -10, YOFFSET * 2, 0},
331 {XOFFSET * -8, YOFFSET * 2, 0},
332 {XOFFSET * -6, YOFFSET * 2, 0},
333 {XOFFSET * -4, YOFFSET * 2, 0},
334 {XOFFSET * -2, YOFFSET * 2, 0},
335 {XOFFSET * 0, YOFFSET * 2, 0},
336 {XOFFSET * 2, YOFFSET * 2, 0},
337 {XOFFSET * 4, YOFFSET * 2, 0},
338 {XOFFSET * 6, YOFFSET * 2, 0},
339 {XOFFSET * 8, YOFFSET * 2, 0},
340 {XOFFSET * 10, YOFFSET * 2, 0},
342 {XOFFSET * -9, YOFFSET * 3, 0},
343 {XOFFSET * -7, YOFFSET * 3, 0},
344 {XOFFSET * -5, YOFFSET * 3, 0},
345 {XOFFSET * -3, YOFFSET * 3, 0},
346 {XOFFSET * -1, YOFFSET * 3, 0},
347 {XOFFSET * 1, YOFFSET * 3, 0},
348 {XOFFSET * 3, YOFFSET * 3, 0},
349 {XOFFSET * 5, YOFFSET * 3, 0},
350 {XOFFSET * 7, YOFFSET * 3, 0},
351 {XOFFSET * 9, YOFFSET * 3, 0},
353 {XOFFSET * -8, YOFFSET * 4, 0},
354 {XOFFSET * -6, YOFFSET * 4, 0},
355 {XOFFSET * -4, YOFFSET * 4, 0},
356 {XOFFSET * -2, YOFFSET * 4, 0},
357 {XOFFSET * 0, YOFFSET * 4, 0},
358 {XOFFSET * 2, YOFFSET * 4, 0},
359 {XOFFSET * 4, YOFFSET * 4, 0},
360 {XOFFSET * 6, YOFFSET * 4, 0},
361 {XOFFSET * 8, YOFFSET * 4, 0},
363 {XOFFSET * -7, YOFFSET * 5, 0},
364 {XOFFSET * -5, YOFFSET * 5, 0},
365 {XOFFSET * -3, YOFFSET * 5, 0},
366 {XOFFSET * -1, YOFFSET * 5, 0},
367 {XOFFSET * 1, YOFFSET * 5, 0},
368 {XOFFSET * 3, YOFFSET * 5, 0},
369 {XOFFSET * 5, YOFFSET * 5, 0},
370 {XOFFSET * 7, YOFFSET * 5, 0},
372 {XOFFSET * -6, YOFFSET * 6, 0},
373 {XOFFSET * -4, YOFFSET * 6, 0},
374 {XOFFSET * -2, YOFFSET * 6, 0},
375 {XOFFSET * 0, YOFFSET * 6, 0},
376 {XOFFSET * 2, YOFFSET * 6, 0},
377 {XOFFSET * 4, YOFFSET * 6, 0},
378 {XOFFSET * 6, YOFFSET * 6, 0},
382 **----------------------------------------------------------------------------
384 **----------------------------------------------------------------------------
387 static gleidestruct *gleidescope = NULL;
390 *load defaults in config structure
392 void setdefaultconfig(void)
405 static double xmouse = 0.0;
406 static double ymouse = 0.0;
409 gleidescope_handle_event(ModeInfo *mi, XEvent *event)
411 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
414 printf("event:%d\n", event->xany.type);
415 printf("button:%d\n", event->xbutton.button);
417 switch(event->xany.type)
421 if (event->xbutton.button == Button1 ||
422 event->xbutton.button == Button3)
424 /* store initial values of mouse */
425 xstart = event->xbutton.x;
426 ystart = event->xbutton.y;
429 gp->button_down_p = True;
433 else if (event->xbutton.button == Button4)
438 else if (event->xbutton.button == Button5)
448 if (event->xbutton.button == Button1 ||
449 event->xbutton.button == Button3)
452 gp->button_down_p = False;
459 if (gp->button_down_p)
461 /* update mouse position */
462 xmouse += (double)(event->xmotion.x - xstart) / MI_WIDTH(mi);
463 ymouse += (double)(event->xmotion.y - ystart) / MI_HEIGHT(mi);
464 xstart = event->xmotion.x;
465 ystart = event->xmotion.y;
475 #include "grab-ximage.h"
478 getSnapshot(ModeInfo *mi, GLuint name)
480 Bool mipmap_p = True;
482 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
484 if (MI_IS_WIREFRAME(mi))
487 glBindTexture (GL_TEXTURE_2D, name);
488 if (! screen_to_texture (mi->xgwa.screen, mi->window, 0, 0,
489 mipmap_p, NULL, NULL, &iw, &ih, &tw, &th))
492 gp->max_tx = (GLfloat) iw / tw;
493 gp->max_ty = (GLfloat) ih / th;
495 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
496 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
497 (mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
499 /* remember time of last image change */
500 gp->start_time = time ((time_t *) 0);
504 setup_file_texture (ModeInfo *mi, char *filename, GLuint name)
506 Display *dpy = mi->dpy;
507 Visual *visual = mi->xgwa.visual;
510 Colormap cmap = mi->xgwa.colormap;
511 XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
513 /* use this texture */
514 glBindTexture(GL_TEXTURE_2D, name);
517 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
518 image->width, image->height, 0,
519 GL_RGBA, GL_UNSIGNED_BYTE, image->data);
520 sprintf (buf, "texture: %.100s (%dx%d)",
521 filename, image->width, image->height);
524 /* setup parameters for texturing */
525 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
526 glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
528 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
529 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
530 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
531 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
532 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
536 setup_texture(ModeInfo * mi, GLuint id)
538 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
540 if (!image || !*image || !strcmp(image, "DEFAULT")) {
541 /* no image specified - grab screen */
543 /* max_tx and max_ty set in getSnapshot() */
545 /* use supplied image file */
546 setup_file_texture(mi, image, id);
548 /* set tx params to use whole image */
553 check_gl_error("texture initialization");
555 /* Need to flip the texture top for bottom for some reason. */
556 glMatrixMode (GL_TEXTURE);
558 glMatrixMode (GL_MODELVIEW);
561 #define VERTEX0 glVertex3f( 0.0000f, 0.000f, 0.0f);
562 #define VERTEX1 glVertex3f( 0.0000f, 1.000f, 0.0f);
563 #define VERTEX2 glVertex3f( XOFFSET, 0.500f, 0.0f);
564 #define VERTEX3 glVertex3f( XOFFSET, -0.500f, 0.0f);
565 #define VERTEX4 glVertex3f( 0.0000f, -1.000f, 0.0f);
566 #define VERTEX5 glVertex3f(-XOFFSET, -0.500f, 0.0f);
567 #define VERTEX6 glVertex3f(-XOFFSET, 0.500f, 0.0f);
570 draw_hexagons(ModeInfo *mi, int translucency, GLuint texture)
574 GLfloat t1x, t1y, t2x, t2y, t3x, t3y;
575 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
581 col[3] = (float)translucency / MAX_FADE;
583 /* calculate vertices of equilateral triangle within image. */
584 /* t1 is always in centre */
585 t1x = gp->max_tx / 2;
586 t1y = gp->max_ty / 2;
588 t2x = (gp->max_tx / 2) * (1 + cos((ymouse * 2 * M_PI) + (tangle * M_PI / 180)));
589 t2y = (gp->max_ty / 2) * (1 + sin((ymouse * 2 * M_PI) + (tangle * M_PI / 180)));
590 /* t3 is always 60' further around than t2 */
591 tangle2 = (ymouse * 2 * M_PI) + (tangle * M_PI / 180) + (M_PI * 2 / 6);
592 t3x = (gp->max_tx / 2) * (1 + (cos(tangle2)));
593 t3y = (gp->max_ty / 2) * (1 + (sin(tangle2)));
594 /* NB image is flipped vertically hence: */
598 /*printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t1x, t1y, t2x, t2y, gp->max_tx, gp->max_ty);*/
600 glColor4f(1.0, 1.0, 1.0, (float)translucency / MAX_FADE);
601 glEnable(GL_TEXTURE_2D);
603 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
604 glDepthMask(GL_FALSE);
605 glBindTexture(GL_TEXTURE_2D, gp->textures[texture]);
607 for (i = 0 ; i < sizeof(hex) / sizeof(hex[0]) ; i++) {
611 glTranslatef(hex[i].x, hex[i].y, 0.0);
613 glBegin(GL_TRIANGLES);
616 ** six triangles to each hexagon
619 glTexCoord2f(t1x, t1y);
621 glTexCoord2f(t2x, t2y);
623 glTexCoord2f(t3x, t3y);
626 glTexCoord2f(t1x, t1y);
628 glTexCoord2f(t3x, t3y);
630 glTexCoord2f(t2x, t2y);
633 glTexCoord2f(t1x, t1y);
635 glTexCoord2f(t2x, t2y);
637 glTexCoord2f(t3x, t3y);
640 glTexCoord2f(t1x, t1y);
642 glTexCoord2f(t3x, t3y);
644 glTexCoord2f(t2x, t2y);
647 glTexCoord2f(t1x, t1y);
649 glTexCoord2f(t2x, t2y);
651 glTexCoord2f(t3x, t3y);
654 glTexCoord2f(t1x, t1y);
656 glTexCoord2f(t3x, t3y);
658 glTexCoord2f(t2x, t2y);
666 #ifdef DISPLAY_TEXTURE
668 /* acd debug - display (bigger, centred) texture */
669 glScalef(2.0, 2.0, 2.0);
670 glTranslatef(-0.5, -0.5, 0.0);
672 glTexCoord2f(0.0, 0.0);
673 glVertex3f(0.0, 0.0, -0.1);
674 glTexCoord2f(1.0, 0.0);
675 glVertex3f(1.0, 0.0, -0.1);
676 glTexCoord2f(1.0, 1.0);
677 glVertex3f(1.0, 1.0, -0.1);
678 glTexCoord2f(0.0, 1.0);
679 glVertex3f(0.0, 1.0, -0.1);
681 /* acd debug - display texture triangle */
682 glColor4f(1.0, 1.0, 1.0, 1.0);
683 glBegin(GL_LINE_LOOP);
684 glVertex3f(t1x, t1y, -0.11);
685 glVertex3f(t2x, t2y, -0.11);
686 glVertex3f(t3x, t3y, -0.11);
691 glDisable(GL_TEXTURE_2D);
692 glDepthMask(GL_TRUE);
697 * main rendering loop
702 GLfloat x_angle, y_angle, z_angle;
703 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
707 glClearColor(0.5, 0.5, 0.5, 1.0);
708 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
713 x_angle = gp->cam_x_phase + gp->tic * gp->cam_x_speed;
714 y_angle = gp->cam_y_phase + gp->tic * gp->cam_y_speed;
715 z_angle = gp->cam_z_phase + gp->tic * gp->cam_z_speed;
718 v1.x = 2 * sin(x_angle);
719 v1.y = 2 * sin(y_angle);
725 /* size is changed in pinit() to be distance from plane */
734 /* user defined size */
737 /* max distance given by adding the constant and the multiplier */
738 v1.z = 5.0 + 4.0 * sin(z_angle);
744 /* update rotation angle (but not if mouse button down) */
745 if (rotate && !gp->button_down_p)
747 float new_rangle_vel = 0.0;
749 /* update camera rotation angle and velocity */
750 rangle += rangle_vel;
751 new_rangle_vel = rangle_vel + rangle_acc;
752 if (new_rangle_vel > -MAX_RANGLE_VEL && new_rangle_vel < MAX_RANGLE_VEL)
754 /* new velocity is within limits */
755 rangle_vel = new_rangle_vel;
758 /* randomly change twisting speed */
759 if ((random() % 1000) < 1)
761 rangle_acc = frand(0.002) - 0.001;
766 /* this makes the image wobble - requires -move and a larger grid */
767 gluLookAt(0, 0, v1.z, v1.x, v1.y, 0.0, 0.0, 1.0, 0.0);
769 /* no wobble - camera always perpendicular to grid */
771 /* rotating camera rather than entire space - smoother */
775 sin((xmouse * M_PI * 2) + rangle * M_PI / 180),
776 cos((xmouse * M_PI * 2) + rangle * M_PI / 180),
780 /* light position same as camera */
789 draw_hexagons(mi, MAX_FADE, gp->visible);
793 /* fading - show both textures with alpha */
794 draw_hexagons(mi, MAX_FADE - gp->fade, gp->visible);
795 draw_hexagons(mi, gp->fade, 1 - gp->visible);
800 /* have we faded enough? */
801 if (gp->fade > MAX_FADE)
805 gp->visible = 1 - gp->visible;
809 /* increment texture angle based on time, velocity etc */
810 /* but only if button is not down */
811 if (!gp->button_down_p)
813 float new_tangle_vel = 0.0;
815 tangle += tangle_vel;
817 /* work out new texture angle velocity */
818 new_tangle_vel = tangle_vel + tangle_acc;
819 if (new_tangle_vel > -MAX_TANGLE_VEL && new_tangle_vel < MAX_TANGLE_VEL)
821 /* new velocity is inside limits */
822 tangle_vel = new_tangle_vel;
825 /* randomly change texture angle acceleration */
826 if ((random() % 1000) < 1)
828 tangle_acc = frand(0.002) - 0.001;
836 * new window size or exposure
838 void reshape_gleidescope(ModeInfo *mi, int width, int height)
840 GLfloat h = (GLfloat) height / (GLfloat) width;
842 glViewport(0, 0, (GLint) width, (GLint) height);
843 glMatrixMode(GL_PROJECTION);
845 gluPerspective(50.0, 1/h, 0.1, 2000.0);
846 glMatrixMode (GL_MODELVIEW);
855 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
857 /* set start time - star_time = 0 implies non-dynamic texture */
858 gp->start_time = (time_t)0;
860 /* set the texture size to default */
867 glShadeModel(GL_SMOOTH);
868 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
869 glEnable(GL_DEPTH_TEST);
870 glEnable(GL_CULL_FACE);
871 glDisable(GL_LIGHTING);
873 /* space for textures */
874 glGenTextures(1, &gp->textures[0]);
875 glGenTextures(1, &gp->textures[1]);
878 setup_texture(mi, gp->textures[gp->visible]);
881 ** want to choose a value for arg randomly if neither -arg nor -no-arg
882 ** is specified. xscreensaver libraries don't seem to let you do this -
883 ** if something isn't true then it is false (pesky two-state boolean values).
884 ** so, i've defined both -arg and -no-arg to arguments and added the
886 ** (btw if both -arg and -no-arg are defined then arg is set to False)
888 if (zoom == False && nozoom == False)
890 /* no zoom preference - randomise */
891 zoom = (((random() & 0x1) == 0x1) ? True : False);
893 else if (nozoom == True)
895 /* definately no zoom */
899 if (move == False && nomove == False)
901 /* no move preference - randomise */
902 move = (((random() & 0x1) == 0x1) ? True : False);
904 else if (nomove == True)
906 /* definately no move */
910 if (rotate == False && norotate == False)
912 /* no rotate preference - randomise */
913 rotate = (((random() & 0x1) == 0x1) ? True : False);
915 else if (norotate == True)
917 /* definately no rotate */
921 /* define cam variables */
922 gp->cam_x_speed = frand(3.0) - 1.5;
923 gp->cam_x_phase = random() % 360;
924 gp->cam_y_speed = frand(3.0) - 1.5;
925 gp->cam_y_phase = random() % 360;
926 gp->cam_z_speed = frand(3.0) - 1.5;
927 gp->cam_z_phase = random() % 360;
929 /* initial angular speeds */
930 rangle_vel = frand(0.2) - 0.1;
931 tangle_vel = frand(0.2) - 0.1;
932 rangle_acc = frand(0.002) - 0.001;
933 tangle_acc = frand(0.002) - 0.001;
944 /* distance is 11 - size */
947 fprintf(stderr, "-size given. ignoring -zoom.\n");
952 } else if (size >= 10) {
959 printf("phases [%d, %d, %d]\n", gp->cam_x_phase, gp->cam_y_phase, gp->cam_z_phase);
964 init_gleidescope(ModeInfo * mi)
967 int screen = MI_SCREEN(mi);
970 if (gleidescope == NULL) {
971 gleidescope = (gleidestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (gleidestruct));
972 if (gleidescope == NULL) {
976 gp = &gleidescope[screen];
977 gp->window = MI_WINDOW(mi);
979 if ((gp->glx_context = init_GL(mi)) != NULL) {
981 reshape_gleidescope(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
983 glDrawBuffer(GL_BACK);
985 /* do initialisation */
994 draw_gleidescope(ModeInfo * mi)
996 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
997 Display *display = MI_DISPLAY(mi);
998 Window window = MI_WINDOW(mi);
1001 if (!gp->glx_context)
1004 glDrawBuffer(GL_BACK);
1006 glXMakeCurrent(display, window, *(gp->glx_context));
1014 glXSwapBuffers(display, window);
1022 /* need to change texture? */
1023 if ((gp->start_time != 0) && (duration != -1) && gp->fade == 0) {
1024 if (gp->start_time + duration <= time((time_t *)0)) {
1025 /* get new snapshot (into back buffer) and start fade count */
1026 getSnapshot(mi, gp->textures[1 - gp->visible]);
1033 release_gleidescope(ModeInfo * mi)
1035 if (gleidescope != NULL) {
1038 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
1039 gleidestruct *gp = &gleidescope[screen];
1041 /* acd - is this needed? */
1042 if (gp->glx_context) {
1043 /* Display lists MUST be freed while their glXContext is current. */
1044 glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
1046 /* acd - was code here for freeing things that are no longer in struct */
1049 (void) free((void *) gleidescope);