~ubuntu-branches/ubuntu/dapper/xscreensaver/dapper-updates

« back to all changes in this revision

Viewing changes to hacks/glx/gleidescope.c

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Hildebrandt
  • Date: 2005-04-09 00:06:43 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20050409000643-z0abtifbt9s20pcc
Tags: 4.21-3
Patch by Joachim Breitner to check more frequently if DPMS kicked in (closes: #303374, #286664).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 4 -*- */
 
2
 
 
3
#if !defined( lint ) && !defined( SABER )
 
4
/*static const char sccsid[] = "@(#)gleidescope.c       1.0 03/06/27 xlockmore";*/
 
5
#endif
 
6
 
 
7
/* enable -grab switch */
 
8
/*#define       GRAB*/
 
9
 
 
10
/*-
 
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.
 
16
 *
 
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.
 
22
 *
 
23
 *      Revision History:
 
24
 *
 
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).
 
32
 *                                                              Added -duration.
 
33
 *                                                              Added mouse code.
 
34
 *                                                              Added fade code (also from glslideshow).
 
35
 *      20031013        1.2             acd             Migrated to compile without warnings under
 
36
 *                                                                      xscreensaver 4.13.
 
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.
 
43
 */
 
44
 
 
45
#include <X11/Intrinsic.h>
 
46
#include "colors.h"
 
47
 
 
48
#include "xpm-ximage.h"
 
49
 
 
50
/*
 
51
**----------------------------------------------------------------------------
 
52
** Defines
 
53
**----------------------------------------------------------------------------
 
54
*/
 
55
 
 
56
#ifdef STANDALONE
 
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
 
64
# define DEFAULTS \
 
65
                "*delay:                20000           \n"     \
 
66
                "*showFPS:              False           \n"     \
 
67
                "*size:                 -1                      \n"     \
 
68
                "*useSHM:               True            \n"
 
69
 
 
70
# include "xlockmore.h"                         /* from the xscreensaver distribution */
 
71
#else  /* !STANDALONE */
 
72
# include "xlock.h"                                     /* from the xlockmore distribution */
 
73
#endif /* !STANDALONE */
 
74
 
 
75
#ifdef USE_GL
 
76
 
 
77
#include <GL/glu.h>
 
78
 
 
79
/* acd TODO should all these be in gleidestruct? */
 
80
#ifdef GRAB
 
81
static Bool             grab;                   /* grab images */
 
82
#endif
 
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 */
 
92
 
 
93
#define MAX_TANGLE_VEL  2.0
 
94
 
 
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 */
 
98
 
 
99
#define MAX_RANGLE_VEL  1.5
 
100
 
 
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 */
 
104
 
 
105
static XrmOptionDescRec opts[] =
 
106
{
 
107
#ifdef GRAB
 
108
        {"-grab",               ".gleidescope.grab",            XrmoptionNoArg,         "true"},
 
109
#endif
 
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"},
 
119
};
 
120
 
 
121
 
 
122
static argtype vars[] = {
 
123
#ifdef GRAB
 
124
        {&grab,                 "grab",         "Grab",         "False",        t_Bool},
 
125
#endif
 
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},
 
135
};
 
136
 
 
137
static OptionStruct desc[] = {
 
138
#ifdef GRAB
 
139
        {"-grab",               "grab images to create animation"},
 
140
#endif
 
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"},
 
150
};
 
151
 
 
152
ModeSpecOpt gleidescope_opts = {
 
153
        sizeof opts / sizeof opts[0], opts,
 
154
        sizeof vars / sizeof vars[0], vars,
 
155
        desc
 
156
};
 
157
 
 
158
#ifdef USE_MODULES
 
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};
 
164
#endif
 
165
 
 
166
/*
 
167
**-----------------------------------------------------------------------------
 
168
**      Typedefs
 
169
**-----------------------------------------------------------------------------
 
170
*/
 
171
 
 
172
typedef struct hex_s {
 
173
        GLfloat x, y, z;                /* position */
 
174
} hex_t;
 
175
 
 
176
typedef struct {
 
177
        GLfloat x;
 
178
        GLfloat y;
 
179
        GLfloat z;
 
180
} vectorf;
 
181
 
 
182
#define MAX_FADE        500     /* number of fade cycles */
 
183
 
 
184
typedef struct {
 
185
        float                   cam_x_speed, cam_z_speed, cam_y_speed;
 
186
        int                             cam_x_phase, cam_z_phase, cam_y_phase;
 
187
        float                   tic;
 
188
        GLXContext              *glx_context;
 
189
        Window                  window;
 
190
        GLfloat                 max_tx, max_ty; /* maximum texture sizes */
 
191
        GLuint                  textures[2];    /* texture handles */
 
192
        GLuint                  visible;                /* texture handle for new texture */
 
193
        GLint                   fade;
 
194
        time_t                  start_time;
 
195
        Bool                    button_down_p;
 
196
} gleidestruct;
 
197
 
 
198
#define XOFFSET (0.8660254f)    /* sin 60' */
 
199
#define YOFFSET (1.5000000f)    /* cos 60' + 1 */
 
200
 
 
201
#if 0
 
202
 
 
203
#define SIZE    3
 
204
 
 
205
/* generates a grid with edges of given size */
 
206
/* acd TODO - replace hex[] with this and allow size and distance as parameters */
 
207
 
 
208
int
 
209
generate_grid(int size)
 
210
 
 
211
        int     i, x, y;
 
212
 
 
213
        size--;
 
214
 
 
215
        i = 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);
 
219
                }
 
220
                printf("\n");
 
221
                if (y < 0) {
 
222
                        i++;
 
223
                } else {
 
224
                        i--;
 
225
                }
 
226
        }
 
227
        return 0;
 
228
}
 
229
#endif
 
230
 
 
231
hex_t hex[] = {
 
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},
 
242
 
 
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},
 
251
 
 
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},
 
261
 
 
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},
 
272
 
 
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},
 
284
 
 
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},
 
297
 
 
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},
 
311
 
 
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},
 
324
 
 
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},
 
336
 
 
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},
 
347
 
 
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},
 
357
 
 
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},
 
366
 
 
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},
 
374
};
 
375
 
 
376
/*
 
377
**----------------------------------------------------------------------------
 
378
** Local Variables
 
379
**----------------------------------------------------------------------------
 
380
*/
 
381
 
 
382
static  gleidestruct *gleidescope = NULL;
 
383
 
 
384
/*
 
385
 *load defaults in config structure
 
386
 */
 
387
void setdefaultconfig(void)
 
388
{
 
389
#ifdef GRAB
 
390
        grab = False;
 
391
#endif
 
392
        move = False;
 
393
        rotate = False;
 
394
        zoom = False;
 
395
        image = NULL;
 
396
}
 
397
 
 
398
static int xstart;
 
399
static int ystart;
 
400
static double xmouse = 0.0;
 
401
static double ymouse = 0.0;
 
402
 
 
403
Bool
 
404
gleidescope_handle_event(ModeInfo *mi, XEvent *event)
 
405
{
 
406
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
407
 
 
408
        /*
 
409
        printf("event:%d\n", event->xany.type);
 
410
        printf("button:%d\n", event->xbutton.button);
 
411
        */
 
412
        switch(event->xany.type)
 
413
        {
 
414
                case ButtonPress:
 
415
 
 
416
                        if (event->xbutton.button == Button1 ||
 
417
                event->xbutton.button == Button3)
 
418
                        {
 
419
                                /* store initial values of mouse */
 
420
                                xstart = event->xbutton.x;
 
421
                                ystart = event->xbutton.y;
 
422
 
 
423
                                /* button is down */
 
424
                                gp->button_down_p = True;
 
425
                                return True;
 
426
                        }
 
427
#if 0   /* TODO */
 
428
                        else if (event->xbutton.button == Button4)
 
429
                        {
 
430
                                /* zoom in */
 
431
                                return True;
 
432
                        }
 
433
                        else if (event->xbutton.button == Button5)
 
434
                        {
 
435
                                /* zoom out */
 
436
                                return True;
 
437
                        }
 
438
#endif
 
439
                        break;
 
440
 
 
441
                case ButtonRelease:
 
442
 
 
443
                        if (event->xbutton.button == Button1 ||
 
444
                event->xbutton.button == Button3)
 
445
                        {
 
446
                                /* button is up */
 
447
                                gp->button_down_p = False;
 
448
                                return True;
 
449
                        }
 
450
                        break;
 
451
 
 
452
                case MotionNotify:
 
453
 
 
454
                        if (gp->button_down_p)
 
455
                        {
 
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;
 
461
 
 
462
                                return True;
 
463
                        }
 
464
                        break;
 
465
        }
 
466
 
 
467
        return False;
 
468
}
 
469
 
 
470
#include "grab-ximage.h"
 
471
 
 
472
static void
 
473
getSnapshot(ModeInfo *mi, GLuint name)
 
474
{
 
475
    Bool mipmap_p = True;
 
476
        int     iw, ih, tw, th;
 
477
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
478
 
 
479
        if (MI_IS_WIREFRAME(mi))
 
480
                return;
 
481
 
 
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))
 
485
      exit (1);
 
486
 
 
487
    gp->max_tx = (GLfloat) iw / tw;
 
488
    gp->max_ty = (GLfloat) ih / th;
 
489
 
 
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));
 
493
 
 
494
        /* remember time of last image change */
 
495
        gp->start_time = time ((time_t *) 0);
 
496
}
 
497
 
 
498
static void
 
499
setup_file_texture (ModeInfo *mi, char *filename, GLuint name)
 
500
{
 
501
        Display *dpy = mi->dpy;
 
502
        Visual *visual = mi->xgwa.visual;
 
503
        char buf[1024];
 
504
 
 
505
        Colormap cmap = mi->xgwa.colormap;
 
506
        XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
 
507
 
 
508
        /* use this texture */
 
509
        glBindTexture(GL_TEXTURE_2D, name);
 
510
 
 
511
        clear_gl_error();
 
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);
 
517
        check_gl_error(buf);
 
518
 
 
519
        /* setup parameters for texturing */
 
520
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
521
        glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
 
522
 
 
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);
 
528
}
 
529
 
 
530
static void
 
531
setup_texture(ModeInfo * mi, GLuint id)
 
532
{
 
533
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
534
 
 
535
        if (!image || !*image || !strcmp(image, "DEFAULT")) {
 
536
                /* no image specified - grab screen */
 
537
                getSnapshot(mi, id);
 
538
                /* max_tx and max_ty set in getSnapshot() */
 
539
        } else {
 
540
                /* use supplied image file */
 
541
                setup_file_texture(mi, image, id);
 
542
 
 
543
                /* set tx params to use whole image */
 
544
                gp->max_tx = 1.0f;
 
545
                gp->max_ty = 1.0f;
 
546
        }
 
547
 
 
548
        check_gl_error("texture initialization");
 
549
 
 
550
        /* Need to flip the texture top for bottom for some reason. */
 
551
        glMatrixMode (GL_TEXTURE);
 
552
        glScalef (1, -1, 1);
 
553
        glMatrixMode (GL_MODELVIEW);
 
554
}
 
555
 
 
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);
 
563
 
 
564
static void
 
565
draw_hexagons(ModeInfo *mi, int translucency, GLuint texture)
 
566
{
 
567
        int             i;
 
568
        GLfloat col[4];
 
569
        GLfloat t1x, t1y, t2x, t2y, t3x, t3y;
 
570
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
571
        GLfloat tangle2;
 
572
 
 
573
        col[0] = 1.0;
 
574
        col[1] = 1.0;
 
575
        col[2] = 1.0;
 
576
        col[3] = (float)translucency / MAX_FADE;
 
577
 
 
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;
 
582
        /* t2 rotates */
 
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: */
 
590
        t1y = 1 - t1y;
 
591
        t2y = 1 - t2y;
 
592
        t3y = 1 - t3y;
 
593
        /*printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t1x, t1y, t2x, t2y, gp->max_tx, gp->max_ty);*/
 
594
 
 
595
        glColor4f(1.0, 1.0, 1.0, (float)translucency / MAX_FADE);
 
596
        glEnable(GL_TEXTURE_2D);
 
597
        glEnable(GL_BLEND);
 
598
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
599
        glDepthMask(GL_FALSE);
 
600
        glBindTexture(GL_TEXTURE_2D, gp->textures[texture]);
 
601
 
 
602
        for (i = 0 ; i < sizeof(hex) / sizeof(hex[0]) ; i++) {
 
603
 
 
604
                glPushMatrix();
 
605
 
 
606
                glTranslatef(hex[i].x, hex[i].y, 0.0);
 
607
 
 
608
                glBegin(GL_TRIANGLES);
 
609
 
 
610
                /*
 
611
                ** six triangles to each hexagon
 
612
                */
 
613
 
 
614
                glTexCoord2f(t1x, t1y);
 
615
                VERTEX0;
 
616
                glTexCoord2f(t2x, t2y);
 
617
                VERTEX1;
 
618
                glTexCoord2f(t3x, t3y);
 
619
                VERTEX6;
 
620
 
 
621
                glTexCoord2f(t1x, t1y);
 
622
                VERTEX0;
 
623
                glTexCoord2f(t3x, t3y);
 
624
                VERTEX6;
 
625
                glTexCoord2f(t2x, t2y);
 
626
                VERTEX5;
 
627
 
 
628
                glTexCoord2f(t1x, t1y);
 
629
                VERTEX0;
 
630
                glTexCoord2f(t2x, t2y);
 
631
                VERTEX5;
 
632
                glTexCoord2f(t3x, t3y);
 
633
                VERTEX4;
 
634
 
 
635
                glTexCoord2f(t1x, t1y);
 
636
                VERTEX0;
 
637
                glTexCoord2f(t3x, t3y);
 
638
                VERTEX4;
 
639
                glTexCoord2f(t2x, t2y);
 
640
                VERTEX3;
 
641
 
 
642
                glTexCoord2f(t1x, t1y);
 
643
                VERTEX0;
 
644
                glTexCoord2f(t2x, t2y);
 
645
                VERTEX3;
 
646
                glTexCoord2f(t3x, t3y);
 
647
                VERTEX2;
 
648
 
 
649
                glTexCoord2f(t1x, t1y);
 
650
                VERTEX0;
 
651
                glTexCoord2f(t3x, t3y);
 
652
                VERTEX2;
 
653
                glTexCoord2f(t2x, t2y);
 
654
                VERTEX1;
 
655
 
 
656
                glEnd();
 
657
 
 
658
                glPopMatrix();
 
659
        }
 
660
        
 
661
#ifdef DISPLAY_TEXTURE
 
662
        glPushMatrix();
 
663
        /* acd debug - display (bigger, centred) texture */
 
664
        glScalef(2.0, 2.0, 2.0);
 
665
        glTranslatef(-0.5, -0.5, 0.0);
 
666
        glBegin(GL_QUADS);
 
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);
 
675
        glEnd();
 
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);
 
682
        glEnd();
 
683
        glPopMatrix();
 
684
#endif
 
685
 
 
686
        glDisable(GL_TEXTURE_2D);
 
687
        glDepthMask(GL_TRUE);
 
688
        glDisable(GL_BLEND);
 
689
}
 
690
 
 
691
/*
 
692
 * main rendering loop
 
693
 */
 
694
static void
 
695
draw(ModeInfo * mi)
 
696
{
 
697
        GLfloat x_angle, y_angle, z_angle;
 
698
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
699
        vectorf v1;
 
700
        GLfloat pos[4];
 
701
 
 
702
        glClearColor(0.5, 0.5, 0.5, 1.0);
 
703
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
704
        glLoadIdentity();
 
705
 
 
706
        gp->tic += 0.005f;
 
707
 
 
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;
 
711
 
 
712
        if (move) {
 
713
                v1.x = 2 * sin(x_angle);
 
714
                v1.y = 2 * sin(y_angle);
 
715
        } else {
 
716
                v1.x = 0;
 
717
                v1.y = 0;
 
718
        }
 
719
 
 
720
        /* size is changed in pinit() to be distance from plane */
 
721
        size = MI_SIZE(mi);
 
722
        if (size > 10) {
 
723
                size = 10;
 
724
        }
 
725
        if (size < -1) {
 
726
                size = -1;
 
727
        }
 
728
        if (size != -1) {
 
729
                /* user defined size */
 
730
                v1.z = size;
 
731
        } else if (zoom) {
 
732
                /* max distance given by adding the constant and the multiplier */
 
733
                v1.z = 5.0 + 4.0 * sin(z_angle);
 
734
        } else {
 
735
                /* default */
 
736
                v1.z = 7.0;
 
737
        }
 
738
 
 
739
        /* update rotation angle (but not if mouse button down) */
 
740
        if (rotate && !gp->button_down_p)
 
741
        {
 
742
                float   new_rangle_vel = 0.0;
 
743
 
 
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)
 
748
                {
 
749
                        /* new velocity is within limits */
 
750
                        rangle_vel = new_rangle_vel;
 
751
                }
 
752
 
 
753
                /* randomly change twisting speed */
 
754
                if ((random() % 1000) < 1)
 
755
                {
 
756
                        rangle_acc = frand(0.002) - 0.001;
 
757
                }
 
758
        }
 
759
 
 
760
#ifdef WOBBLE
 
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);
 
763
#else
 
764
        /* no wobble - camera always perpendicular to grid */
 
765
 
 
766
        /* rotating camera rather than entire space - smoother */
 
767
        gluLookAt(
 
768
                        v1.x, v1.y, v1.z,
 
769
                        v1.x, v1.y, 0.0,
 
770
                        sin((xmouse * M_PI * 2) + rangle * M_PI / 180),
 
771
                        cos((xmouse * M_PI * 2) + rangle * M_PI / 180),
 
772
                        0.0);
 
773
#endif
 
774
 
 
775
        /* light position same as camera */
 
776
        pos[0] = v1.x;
 
777
        pos[1] = v1.y;
 
778
        pos[2] = v1.z;
 
779
        pos[3] = 0;
 
780
 
 
781
        if (gp->fade == 0)
 
782
        {
 
783
                /* not fading */
 
784
                draw_hexagons(mi, MAX_FADE, gp->visible);
 
785
        }
 
786
        else
 
787
        {
 
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);
 
791
 
 
792
                /* fade some more */
 
793
                gp->fade++;
 
794
 
 
795
                /* have we faded enough? */
 
796
                if (gp->fade > MAX_FADE)
 
797
                {
 
798
                        /* stop fading */
 
799
                        gp->fade = 0;
 
800
                        gp->visible = 1 - gp->visible;
 
801
                }
 
802
        }
 
803
 
 
804
        /* increment texture angle based on time, velocity etc */
 
805
        /* but only if button is not down */
 
806
        if (!gp->button_down_p)
 
807
        {
 
808
                float           new_tangle_vel = 0.0;
 
809
 
 
810
                tangle += tangle_vel;
 
811
 
 
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)
 
815
                {
 
816
                        /* new velocity is inside limits */
 
817
                        tangle_vel = new_tangle_vel;
 
818
                }
 
819
 
 
820
                /* randomly change texture angle acceleration */
 
821
                if ((random() % 1000) < 1)
 
822
                {
 
823
                        tangle_acc = frand(0.002) - 0.001;
 
824
                }
 
825
        }
 
826
 
 
827
        glFlush();
 
828
}
 
829
 
 
830
/* 
 
831
 * new window size or exposure 
 
832
 */
 
833
void reshape_gleidescope(ModeInfo *mi, int width, int height)
 
834
{
 
835
        GLfloat         h = (GLfloat) height / (GLfloat) width;
 
836
 
 
837
        glViewport(0, 0, (GLint) width, (GLint) height);
 
838
        glMatrixMode(GL_PROJECTION);
 
839
        glLoadIdentity();
 
840
        gluPerspective(50.0, 1/h, 0.1, 2000.0);
 
841
        glMatrixMode (GL_MODELVIEW);
 
842
 
 
843
        glLineWidth(1);
 
844
        glPointSize(1);   
 
845
}
 
846
 
 
847
static void
 
848
pinit(ModeInfo * mi)
 
849
{
 
850
        gleidestruct    *gp = &gleidescope[MI_SCREEN(mi)];
 
851
 
 
852
        /* set start time - star_time = 0 implies non-dynamic texture */
 
853
        gp->start_time = (time_t)0;
 
854
 
 
855
        /* set the texture size to default */
 
856
        gp->max_tx = 1.0;
 
857
        gp->max_ty = 1.0;
 
858
 
 
859
        /* no fading */
 
860
        gp->fade = 0;
 
861
 
 
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);
 
867
 
 
868
        /* space for textures */
 
869
        glGenTextures(1, &gp->textures[0]);
 
870
        glGenTextures(1, &gp->textures[1]);
 
871
        gp->visible = 0;
 
872
 
 
873
        setup_texture(mi, gp->textures[gp->visible]);
 
874
 
 
875
        /*
 
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 
 
880
        **      following logic.
 
881
        **      (btw if both -arg and -no-arg are defined then arg is set to False)
 
882
        */
 
883
        if (zoom == False && nozoom == False)
 
884
        {
 
885
                /* no zoom preference - randomise */
 
886
                zoom = (((random() & 0x1) == 0x1) ? True : False);
 
887
        }
 
888
        else if (nozoom == True)
 
889
        {
 
890
                /* definately no zoom */
 
891
                zoom = False;
 
892
        }
 
893
 
 
894
        if (move == False && nomove == False)
 
895
        {
 
896
                /* no move preference - randomise */
 
897
                move = (((random() & 0x1) == 0x1) ? True : False);
 
898
        }
 
899
        else if (nomove == True)
 
900
        {
 
901
                /* definately no move */
 
902
                move = False;
 
903
        }
 
904
 
 
905
        if (rotate == False && norotate == False)
 
906
        {
 
907
                /* no rotate preference - randomise */
 
908
                rotate = (((random() & 0x1) == 0x1) ? True : False);
 
909
        }
 
910
        else if (norotate == True)
 
911
        {
 
912
                /* definately no rotate */
 
913
                rotate = False;
 
914
        }
 
915
 
 
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;
 
923
 
 
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;
 
929
 
 
930
    /* jwz */
 
931
    {
 
932
      GLfloat speed = 15;
 
933
      rangle_vel *= speed;
 
934
      tangle_vel *= speed;
 
935
      rangle_acc *= speed;
 
936
      tangle_acc *= speed;
 
937
    }
 
938
 
 
939
        /* distance is 11 - size */
 
940
        if (size != -1) {
 
941
                if (zoom) {
 
942
                        fprintf(stderr, "-size given. ignoring -zoom.\n");
 
943
                        zoom = False;
 
944
                }
 
945
                if (size < 1) {
 
946
                        size = 1;
 
947
                } else if (size >= 10) {
 
948
                        size = 10;
 
949
                }
 
950
                size = 11 - size;
 
951
        }
 
952
 
 
953
#ifdef DEBUG
 
954
printf("phases [%d, %d, %d]\n", gp->cam_x_phase, gp->cam_y_phase, gp->cam_z_phase);
 
955
#endif
 
956
}
 
957
 
 
958
void
 
959
init_gleidescope(ModeInfo * mi)
 
960
{
 
961
        gleidestruct *gp;
 
962
        int screen = MI_SCREEN(mi);
 
963
 
 
964
 
 
965
        if (gleidescope == NULL) {
 
966
                gleidescope = (gleidestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (gleidestruct));
 
967
                if (gleidescope == NULL) {
 
968
                        return;
 
969
                }
 
970
        }
 
971
        gp = &gleidescope[screen];
 
972
        gp->window = MI_WINDOW(mi);
 
973
 
 
974
        if ((gp->glx_context = init_GL(mi)) != NULL) {
 
975
 
 
976
                reshape_gleidescope(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
 
977
 
 
978
                glDrawBuffer(GL_BACK);
 
979
 
 
980
                /* do initialisation */
 
981
                pinit(mi);
 
982
 
 
983
        } else {
 
984
                MI_CLEARWINDOW(mi);
 
985
        }
 
986
}
 
987
 
 
988
void
 
989
draw_gleidescope(ModeInfo * mi)
 
990
{
 
991
        gleidestruct    *gp = &gleidescope[MI_SCREEN(mi)];
 
992
        Display         *display = MI_DISPLAY(mi);
 
993
        Window          window = MI_WINDOW(mi);
 
994
 
 
995
 
 
996
        if (!gp->glx_context)
 
997
                return;
 
998
 
 
999
        glDrawBuffer(GL_BACK);
 
1000
 
 
1001
        glXMakeCurrent(display, window, *(gp->glx_context));
 
1002
        draw(mi);
 
1003
 
 
1004
        if (mi->fps_p) {
 
1005
                do_fps (mi);
 
1006
        }
 
1007
 
 
1008
        glFinish();
 
1009
        glXSwapBuffers(display, window);
 
1010
 
 
1011
#ifdef GRAB
 
1012
        if (grab) {
 
1013
                grab_frame(mi);
 
1014
        }
 
1015
#endif
 
1016
 
 
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]);
 
1022
                        gp->fade = 1;
 
1023
                }
 
1024
        }
 
1025
}
 
1026
 
 
1027
void
 
1028
release_gleidescope(ModeInfo * mi)
 
1029
{
 
1030
        if (gleidescope != NULL) {
 
1031
                int screen;
 
1032
 
 
1033
                for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
 
1034
                        gleidestruct *gp = &gleidescope[screen];
 
1035
 
 
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));
 
1040
 
 
1041
                                /* acd - was code here for freeing things that are no longer in struct */
 
1042
                        }
 
1043
                }
 
1044
                (void) free((void *) gleidescope);
 
1045
                gleidescope = NULL;
 
1046
        }
 
1047
        
 
1048
        FreeAllGL(mi);
 
1049
}
 
1050
 
 
1051
#endif