18f38131f4f9b3c1f5eb7d9d4c634890be5e2da4
[xscreensaver] / hacks / glx / timetunnel.c
1 /* timetunnel. Based on dangerball.c, hack by Sean Brennan <zettix@yahoo.com>*/
2 /* dangerball, Copyright (c) 2001-2004 Jamie Zawinski <jwz@jwz.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  */
12
13 #define GL_GLEXT_PROTOTYPES 1
14
15 #include <math.h> /* for log2 */
16
17 #define DEFAULTS        "*delay:        30000       \n" \
18                         "*count:        30          \n" \
19                         "*showFPS:      False       \n" \
20                         "*timeStart:     0.0       \n" \
21                         "*timeEnd:       27.79       \n" \
22                         "*wireframe:    False       \n" \
23
24
25
26 # define refresh_tunnel 0
27 # define release_tunnel 0
28 #undef countof
29 #define countof(x) (sizeof((x))/sizeof((*x)))
30
31 #include "xlockmore.h"
32 #include "colors.h"
33 #include "rotator.h"
34 #include "gltrackball.h"
35
36
37 #define DEF_START       "0.00"
38 #define DEF_DILATE      "1.00"
39 #define DEF_END         "27.79"
40 #define DEF_LOCKLOGO    "False"
41 #define DEF_DRAWLOGO    "True"
42 #define DEF_REVERSE     "False"
43 #define DEF_FOG         "True"
44 #define DEF_TEXTURE     "True"
45 #define MAX_TEXTURE 10
46 #define CYL_LEN         14.0
47 #define DIAMOND_LEN     10.0
48
49 static float start, end, dilate;
50 static Bool do_texture, drawlogo, wire, reverse, do_fog;
51 static const char *do_tx1, *do_tx2, *do_tx3, *do_tun1, *do_tun2, *do_tun3;
52
53 static XrmOptionDescRec opts[] = {
54   {"-texture"   , ".texture",   XrmoptionNoArg, "true" },
55   {"+texture"   , ".texture",   XrmoptionNoArg, "false" },
56   {"-start"     , ".start",     XrmoptionSepArg, 0 },
57   {"-end"       , ".end",       XrmoptionSepArg, 0 },
58   {"-dilate"    , ".dilate",   XrmoptionSepArg, 0 },
59   {"+logo"      , ".drawlogo",   XrmoptionNoArg, "false" },
60   {"-reverse"   , ".reverse",   XrmoptionNoArg, "true" },
61   {"+fog"       , ".fog",       XrmoptionNoArg, "false" },
62   {"-marquee"   , ".marquee", XrmoptionSepArg, 0},
63   /* {"+marquee"   , ".marquee", XrmoptionNoArg, "(none)"}, */
64   {"-tardis"   , ".tardis", XrmoptionSepArg, 0},
65   /* {"+tardis"   , ".tardis", XrmoptionNoArg, "(none)"}, */
66   {"-head"   , ".head", XrmoptionSepArg, 0},
67   /* {"+head"   , ".head", XrmoptionNoArg, "(none)"}, */
68   {"-tun1"   , ".tun1", XrmoptionSepArg, 0},
69   /* {"+tun1"   , ".tun1", XrmoptionNoArg, "(none)"}, */
70   {"-tun2"   , ".tun2", XrmoptionSepArg, 0},
71   /* {"+tun2"   , ".tun2", XrmoptionNoArg, "(none)"}, */
72   {"-tun3"   , ".tun3", XrmoptionSepArg, 0},
73   /* {"+tun3"   , ".tun3", XrmoptionNoArg, "(none)"}, */
74 };
75
76 static argtype vars[] = {
77   {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
78   {&start, "start", "Start", DEF_START, t_Float},
79   {&end,     "end",   "End", DEF_END  , t_Float},
80   {&dilate,     "dilate",   "Dilate", DEF_DILATE  , t_Float},
81   {&drawlogo,     "drawlogo",   "DrawLogo", DEF_DRAWLOGO  , t_Bool},
82   {&reverse,     "reverse",   "Reverse", DEF_REVERSE  , t_Bool},
83   {&do_fog,     "fog",  "Fog", DEF_FOG  , t_Bool},
84   {&do_tx1,     "marquee", "Marquee", "(none)", t_String},
85   {&do_tx2,     "tardis", "Tardis", "(none)", t_String},
86   {&do_tx3,     "head", "Head", "(none)", t_String},
87   {&do_tun1,    "tun1", "Tunnel 1", "(none)", t_String},
88   {&do_tun2,    "tun2", "Tunnel 2", "(none)", t_String},
89   {&do_tun3,    "tun3", "Tunnel 3", "(none)", t_String},
90 };
91
92 ENTRYPOINT ModeSpecOpt tunnel_opts = {countof(opts), opts, countof(vars), vars, NULL};
93 #include "xpm-ximage.h"
94 #include "images/logo-180.xpm"
95 #include "images/tunnelstar.xpm"
96 #include "images/timetunnel0.xpm"
97 #include "images/timetunnel1.xpm"
98 #include "images/timetunnel2.xpm"
99
100
101 #ifdef USE_GL /* whole file */
102
103 /* ANIMATION CONTROLS */
104 /* an effect is a collection of floating point variables that vary with time.
105 A knot is a timestamp with an array of floats.  State is the current values of the floats.
106 State is set by linearly interpolating between knots */
107 typedef struct {
108         float *knots, *state;
109         int numknots, knotwidth;
110         float direction;
111 } effect_t;
112
113 typedef struct {
114   GLXContext *glx_context;
115   rotator *rot;
116   trackball_state *trackball;
117   Bool button_down_p;
118
119   int time_oldusec, time_oldsec;
120
121   int num_texshifts; /* animates tunnels. Not an effect. */
122   GLfloat pos, *texshift;
123
124   GLuint texture_binds[MAX_TEXTURE], cyllist, diamondlist;
125
126   float effect_time, effect_maxsecs; /* global time controls */
127   float start_time, end_time;
128
129   int num_effects;
130   effect_t *effects; /* array of all effects */
131
132 } tunnel_configuration;
133
134 static tunnel_configuration *tconf = NULL;
135
136 /* allocate memory and populate effect with knot data */
137 static void init_effect(effect_t *e, int numk, int kwidth, 
138         float dir, float *data ) 
139 {
140         int i, j;
141
142         e->numknots = numk;     
143         e->knotwidth = kwidth;  
144         e->direction = dir;
145         e->knots = calloc(numk * kwidth, sizeof(float));
146         e->state = calloc(numk, sizeof(float));
147         for ( i = 0 ; i < e->numknots ; i++)
148                 for ( j = 0 ; j < e->knotwidth; j++)
149                         e->knots[i * kwidth + j] = data[i * kwidth + j];
150 }
151
152 /* static knot data. each effect is listed and knot data is hard coded. 
153    Knots are linerally interpolated to yield float values, depending on
154    knot width.  knot format is [time, data, data, data...].
155    Data can be alpha, zvalue, etc. */
156 static void init_effects(effect_t *e, int effectnum)
157 {
158         /* effect 1: wall tunnel. percent closed */
159         float e1d[6][2] = 
160                 {{0.0, 0.055}, 
161                  {2.77, 0.055}, 
162                  {3.07,1.0}, 
163                  {8.08, 1.0},
164                  {8.08, 0.0}, 
165                  {10.0, 0.0}};
166         /* effect 2: tardis. distance and alpha */
167         float e2d[8][3] = 
168         {       {0.0, 0.0 , 0.0}, 
169                 {3.44, 0.0 , 0.0},
170                 {3.36, 5.4 , 0.0},
171                 {4.24, 3.66, 1.0},
172                 {6.51, 2.4,  0.94},
173                 {8.08, 0.75 , 0.0}, 
174                 {8.08, 0.0 , 0.0},
175                 {10.0, 0.0, 0.0}};
176         /* effect 3: cylinder. alpha  */
177         float e3d[5][2] = 
178                 {{0.0, 0.0}, 
179                  {6.41, 0.00},
180                  {8.08, 1.0}, 
181                  {14.81, 1.0},
182                  {15.65, 0.0}};
183
184         /* effect 4: fog. color, density,  start, end  */
185         float e4d[9][5] = 
186                 {{0.0 , 1.0, 0.45, 3.0, 15.0},
187                  {6.40, 1.0, 0.45, 3.0, 14.0},
188                  {8.08, 1.0, 0.95, 1.0, 14.0},
189                  {15.17, 1.0, 0.95, 1.0, 6.0},
190                  {15.51, 1.0, 0.95, 3.0, 8.0},
191                  {23.35, 1.0, 0.95, 3.0, 8.0},
192                  {24.02, 0.0, 0.95, 2.3, 5.0},
193                  {26.02, 0.0, 0.95, 2.3, 5.0},
194                  {27.72, 0.0, 1.00, 0.3, 0.9}
195                  };
196
197         /* effect 5: logo. dist, alpha  */
198         float e5d[7][3] = 
199                 {{0.0, 0.0, 0.0}, 
200                 {16.52, 0.00, 0.0}, 
201                 {16.52, 0.80, 0.01}, 
202                 {17.18, 1.15, 1.0}, 
203                 {22.36, 5.3, 1.0}, 
204                 {22.69, 5.7, 0.0},
205                 {22.69, 0.0, 0.0}
206                 };
207         /* effect 6: diamond tunnel. alpha */
208         float e6d[3][2] = 
209                 {{0.0, 0.00}, 
210                 {15.17, 0.00},
211                 {15.51,1.0}};
212
213         /* effect 7: tardis cap draw . positive draws cap*/
214         float e7d[3][2] = 
215                 {{0.0, -1.00}, 
216                 {4.24, -1.00},
217                 {4.24, 1.00}};
218
219         /* effect 8: star/asterisk: alpha */
220         float e8d[5][2] = 
221                 {{0.0,    .00}, 
222                 {10.77,   .00},
223                 {11.48,  1.00},
224                 {15.35,  1.00},
225                 {16.12,  0.00}};
226
227         /* effect 9: whohead 1  alpha */
228         float e9d[5][2] = 
229                 {{0.0,    .00}, 
230                 {13.35,   .00},
231                 {14.48,  1.00},
232                 {15.17,  1.00},
233                 {15.97,  0.00}};
234                 /* {14.87,  1.00},
235                 {15.17,  0.00}}; */
236
237         /* effect 10: whohead-brite  alpha */
238         float e10d[5][2] = 
239                 {{0.0,    .00}, 
240                 {11.34,   .00},
241                 {12.34,   .20},
242                 {13.35,  0.60},
243                 {14.48,  0.00}}; 
244                 /* {13.95,  0.00}}; */
245
246         /* effect 11: whohead-psy  alpha */
247         float e11d[5][2] = 
248                 {{0.0,    .00}, 
249                 {14.87,   .00},
250                 {15.17,  1.00},
251                 {15.91,  0.00},
252                 {16.12,  0.00}};
253
254         /* effect 12: whohead-silhouette pos-z,  alpha */
255         float e12d[6][3] = 
256                 {{0.0,   1.0,  .00}, 
257                 {15.07,  1.0, 0.00},
258                 {15.07,  1.0, 1.00},
259                 {16.01,  1.0, 1.00},
260                 {16.78,  0.5, 1.00},
261                 {16.78,  0.1, 0.00} };
262
263         /* effect 1: wall tunnel */
264         if (effectnum == 1)
265                 init_effect(e, 6, 2,  -0.2, (float *) e1d);
266
267         /* effect 2: tardisl */
268         if (effectnum == 2)
269                 init_effect(e, 8, 3, 1.0,  (float *) e2d);
270
271         /* effect 3: cylinder tunnel  */
272         if (effectnum == 3)
273                 init_effect(e, 5, 2, 0.889  ,  (float *) e3d);
274
275         /* effect 4: fog color */
276         if (effectnum == 4)
277                 init_effect(e, 9, 5, 1.0,  (float *) e4d);
278         /* effect 5: logo distance, alpha*/
279         if (effectnum == 5)
280                 init_effect(e, 7, 3, 1.0,  (float *) e5d);
281         /* effect 6: diamond tunnel, alpha*/
282         if (effectnum == 6)
283                 init_effect(e, 3, 2, 0.24 ,  (float *) e6d);
284
285         /* effect 7: cap wall tunnel*/
286         if (effectnum == 7)
287                 init_effect(e, 3, 2, 1.0,  (float *) e7d);
288
289         /* effect 8: asterisk */
290         if (effectnum == 8)
291                 init_effect(e, 5, 2, 1.0,  (float *) e8d);
292
293         /* effect 9, 10, 11, 12: whoheads */
294         if (effectnum == 9 )
295                 init_effect(e, 5, 2, 1.0,  (float *) e9d);
296         if (effectnum == 10 )
297                 init_effect(e, 5, 2, 1.0,  (float *) e10d);
298         if (effectnum == 11 )
299                 init_effect(e, 5, 2, 1.0,  (float *) e11d);
300         if (effectnum == 12 )
301                 init_effect(e, 6, 3, 1.0,  (float *) e12d);
302 }
303
304
305 /* set fog parameters, controlled by effect */
306 static void update_fog(float color, float density, float start, float end) 
307 {
308                 GLfloat col[4];
309         
310                 col[0] = col[1] = col[2] = color;
311                 col[3] = 1.0;
312
313                 glFogi(GL_FOG_MODE, GL_LINEAR);
314                 glFogfv(GL_FOG_COLOR, col);
315                 glFogf(GL_FOG_DENSITY, density);
316                 glFogf(GL_FOG_START, start);
317                 glFogf(GL_FOG_END, end);
318 }
319
320 /* set effect's floating point data values by linearally interpolating
321 between two knots whose times bound the current time: eff_time */
322
323 static void update_knots(effect_t *e, float eff_time) 
324 {
325         int i, j;
326         float timedelta, lowknot, highknot, *curknot, *nextknot;
327
328         for ( i = 0 ; i < e->numknots ; i++)
329                 if (e->knots[i * e->knotwidth] <= eff_time) {
330                         if ( i < e->numknots - 1) 
331                                 nextknot = e->knots + (i + 1) * e->knotwidth;
332                         else
333                                 /*repeat last knot to carry knot data forward*/
334                                 nextknot = e->knots + (i) * e->knotwidth;
335                         curknot = e->knots + i * e->knotwidth;
336                         if (*nextknot - *curknot <= 0.0) timedelta = 1.0;
337                         else
338                                 timedelta = (eff_time-*curknot)/(*nextknot-*curknot);
339                         if (timedelta > 1.0) timedelta = 1.0;
340                         for (j = 1 ; j < e->knotwidth ; j++) {
341                                 highknot = (float) *(nextknot + j);
342                                 lowknot  = (float) *(curknot  + j);
343                                 e->state[j - 1 ] = lowknot+(highknot-lowknot)*timedelta;
344                         }
345                 }
346         
347 }
348
349
350 /* Window management, etc
351  */
352 ENTRYPOINT void
353 reshape_tunnel (ModeInfo *mi, int width, int height)
354 {
355   GLfloat h = (GLfloat) height / (GLfloat) width;
356
357   glViewport (0, 0, (GLint) width, (GLint) height);
358
359   glMatrixMode(GL_PROJECTION);
360   glLoadIdentity();
361   gluPerspective (90.0, 1/h, 0.2, 50.0); 
362
363   glMatrixMode(GL_MODELVIEW);
364   glLoadIdentity();
365   gluLookAt( 0.0, 0.0, 0.3,
366              0.0, 0.0, 1.0,
367              0.0, 1.0, 0.0);
368
369   glClear(GL_COLOR_BUFFER_BIT);
370 }
371
372
373
374
375 ENTRYPOINT Bool
376 tunnel_handle_event (ModeInfo *mi, XEvent *event)
377 {
378   tunnel_configuration *tc = &tconf[MI_SCREEN(mi)];
379
380   if (event->xany.type == ButtonPress &&
381       event->xbutton.button == Button1)
382     {
383       tc->button_down_p = True;
384       gltrackball_start (tc->trackball,
385                          event->xbutton.x, event->xbutton.y,
386                          MI_WIDTH (mi), MI_HEIGHT (mi));
387       return True;
388     }
389   else if (event->xany.type == ButtonRelease &&
390            event->xbutton.button == Button1)
391     {
392       tc->button_down_p = False;
393       return True;
394     }
395   else if (event->xany.type == ButtonPress &&
396            (event->xbutton.button == Button4 ||
397             event->xbutton.button == Button5))
398     {
399       gltrackball_mousewheel (tc->trackball, event->xbutton.button, 10,
400                               !!event->xbutton.state);
401       return True;
402     }
403   else if (event->xany.type == MotionNotify &&
404            tc->button_down_p)
405     {
406       gltrackball_track (tc->trackball,
407                          event->xmotion.x, event->xmotion.y,
408                          MI_WIDTH (mi), MI_HEIGHT (mi));
409       return True;
410     }
411
412   return False;
413 }
414
415 static void setTexParams(void)
416 {
417         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
418         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
419         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
420         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
421         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
422 }
423
424 static void update_animation(tunnel_configuration *tc) {
425
426         /* time based, of course*/
427         /* shift texture based on elapsed time since previous call*/
428         struct timeval tv;
429         struct timezone tz;
430         int elapsed_usecs, elapsed_secs, i;
431         float computed_timeshift;
432
433         /* get new animation time */
434         gettimeofday(&tv, &tz);
435         elapsed_secs = tv.tv_sec - tc->time_oldsec;
436         elapsed_usecs = tv.tv_usec - tc->time_oldusec;
437         /* store current time */
438         tc->time_oldsec = tv.tv_sec ;
439         tc->time_oldusec = tv.tv_usec;
440         /* elaped time. computed timeshift is tenths of a second */
441         computed_timeshift = (float) (elapsed_secs * 1000000. + elapsed_usecs)/ 
442                                                       100000.0;
443
444         /* calibrate effect time to lie between start and end times */
445         /* loop if time exceeds end time */
446         if (reverse)
447                 tc->effect_time -= computed_timeshift / 10.0 * dilate;
448         else
449                 tc->effect_time += computed_timeshift / 10.0 * dilate;
450         if ( tc->effect_time >= tc->end_time)
451                 tc->effect_time = tc->start_time;
452         if ( tc->effect_time < tc->start_time)
453                 tc->effect_time = tc->end_time;;
454
455         /* move texture shifters in effect's direction, e.g. tardis
456            tunnel moves backward, effect 1's direction */
457          if (reverse) { 
458                 tc->texshift[0] -= tc->effects[1].direction * computed_timeshift/ 10.0; 
459                 tc->texshift[1] -= tc->effects[3].direction * computed_timeshift/ 10.0; 
460                 tc->texshift[2] -= tc->effects[6].direction * computed_timeshift/ 10.0; 
461
462         } else {
463                 tc->texshift[0] += tc->effects[1].direction * computed_timeshift/ 10.0; 
464                 tc->texshift[1] += tc->effects[3].direction * computed_timeshift/ 10.0; 
465                 tc->texshift[2] += tc->effects[6].direction * computed_timeshift/ 10.0; 
466         }
467
468         /* loop texture shifters if necessary */
469         for ( i = 0 ; i < tc->num_texshifts; i++) {
470                 if (tc->texshift[i] > 1.0)
471                         tc->texshift[i] -= (int) tc->texshift[i];
472                 if (tc->texshift[i]< -1.0)
473                         tc->texshift[i] -= (int) tc->texshift[i];
474         }
475
476         /* update effect data with current time. Uses linear interpolation */   
477         for ( i = 1 ; i <= tc->num_effects ; i++)
478                 update_knots(&tc->effects[i], tc->effect_time);
479
480 } /*update_animation*/
481
482 /* draw a textured(tex) quad at a certain depth (z), and certain alpha (alpha), 
483 with aspect ratio (aspect), and blending mode (blend_mode) of either adding
484 or subtracting.  if alpha is zero or less, nothing happens */
485 static void draw_sign(ModeInfo *mi, tunnel_configuration *tc, float z,  float alpha, float aspect,
486                 GLuint tex, int blend_mode)
487 {
488
489         if (alpha > 0.0) {
490                 mi->polygon_count ++;
491                 /* glEnable(GL_BLEND); */
492                 glBlendColor(0.0, 0.0, 0.0, alpha);
493                 /*glBlendColor(0.0, 0.0, 0.0, 0.0); */
494                 if (blend_mode == 1) {
495                         glBlendFunc(GL_CONSTANT_ALPHA,
496                                     GL_ONE);
497                         glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
498                 } else if (blend_mode == 2) {
499                         glBlendFunc(GL_CONSTANT_ALPHA,
500                                     GL_ONE);
501                         glBlendEquation(GL_FUNC_ADD);
502                 } else {
503                         glBlendFunc(GL_CONSTANT_ALPHA,
504                                     GL_ONE_MINUS_CONSTANT_ALPHA);
505                         glBlendEquation(GL_FUNC_ADD);
506                 } /* blend mode switch */
507
508 #ifdef HAVE_GLBINDTEXTURE
509                 if (do_texture)
510                         glBindTexture(GL_TEXTURE_2D, tc->texture_binds[tex]);
511 #endif
512                 glBegin(GL_QUADS);
513                 glTexCoord2f(1.0, 0.0);
514                 glVertex3f(-1.0 , -1.0 * aspect , z);
515                 glTexCoord2f(1.0, 1.0);
516                 glVertex3f(-1.0 , 1.0 * aspect , z);
517                 glTexCoord2f(0.0, 1.0);
518                 glVertex3f(1.0 , 1.0 * aspect , z);
519                 glTexCoord2f(0.0, 0.0);
520                 glVertex3f(1.0 , -1.0 * aspect , z); 
521                 glEnd();
522                 if (blend_mode != 0) {
523                         glBlendFunc(GL_CONSTANT_ALPHA,
524                                     GL_ONE_MINUS_CONSTANT_ALPHA);
525                         glBlendEquation(GL_FUNC_ADD);
526                 }
527                 /* glDisable(GL_BLEND); */
528
529         }
530 } /* draw sign */
531
532
533 /* draw a time tunnel.  used for both cylinder and diamond tunnels.
534    uses texture shifter (indexed by shiftnum) to simulate motion.
535    tunnel does not move, and is acutally a display list.  if alpha = 0, skip */
536 static void draw_cyl(ModeInfo *mi, tunnel_configuration *tc, float alpha, int texnum, int listnum, int shiftnum)
537 {
538         if (alpha > 0.0) {
539                 if (listnum  ==  tc->diamondlist)
540                         mi->polygon_count += 4;
541                 if (listnum  ==  tc->cyllist)
542                         mi->polygon_count += 30;
543                 glMatrixMode(GL_TEXTURE);
544                 glLoadIdentity();
545                 glTranslatef(tc->texshift[shiftnum], 0.0, 0.0);
546                 glMatrixMode(GL_MODELVIEW);
547                 /* glEnable(GL_BLEND); */
548                 glBlendColor(0.0, 0.0, 0.0, alpha);
549                 glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
550         
551 #ifdef HAVE_GLBINDTEXTURE
552                 if (do_texture)
553                         glBindTexture(GL_TEXTURE_2D, tc->texture_binds[texnum]);
554 #endif
555                 glCallList(listnum);
556
557                 glMatrixMode(GL_TEXTURE);
558                 glLoadIdentity();
559                 glMatrixMode(GL_MODELVIEW); 
560                 /* glDisable(GL_BLEND); */
561         }
562 }
563
564
565 /* make tardis type tunnel.  Starts as walls and then
566 grows to outline of tardis.  percent is how complete
567 tardis outline is.  cap is to draw cap for nice fog effects */
568
569 static void make_wall_tunnel(ModeInfo *mi, tunnel_configuration *tc, float percent, float cap)
570 {
571         /* tardis is about 2x1, so wrap tex around, starting at the base*/
572         /* tex coords are:
573
574  _tl__tr_
575  |      |
576 l|      |r
577  |      |
578  -bl__br_  
579         that's br=bottom right, etc. ttr is top-top-right */
580
581         float   half_floor= 0.08333333333333333,
582                 full_wall = 0.33333333333333333;
583         float   br1,
584                 r0 , r1 ,
585                 tr0, tr1,
586                 tl0, tl1,
587                 l0 , l1 ,
588                 bl0, depth=0.3, zdepth=15.0;
589         /* zdepth is how far back tunnel goes */
590         /* depth is tex coord scale.  low number = fast texture shifting */
591
592         float textop, texbot;   
593         float height;
594
595         br1 = half_floor;
596         r0 = br1 ;
597         r1 = r0 + full_wall;
598         tr0 = r1;
599         tr1 = r1 + half_floor;
600         tl0 = tr1;
601         tl1 = tl0 + half_floor;
602         l0 = tr1;
603         l1 = l0 + full_wall;
604         bl0 = l1;
605
606         glMatrixMode(GL_TEXTURE);
607         glLoadIdentity();
608         glRotatef(90.0, 0.0, 0.0, 1.0);
609         glTranslatef(tc->texshift[0], 0.0, 0.0);
610         glMatrixMode(GL_MODELVIEW);
611
612 #ifdef HAVE_GLBINDTEXTURE
613         if (do_texture)
614                 glBindTexture(GL_TEXTURE_2D, tc->texture_binds[0]);
615 #endif
616         glColor3f(1.0, 1.0, 0.0);
617         if (cap > 0.0 && percent > 0.0 && drawlogo && do_fog) {
618                 mi->polygon_count += 6;
619                 glBegin(GL_TRIANGLE_FAN);
620                 glVertex3f(0.0, 0.0, zdepth);
621                 glVertex3f(-1.0, -2.0, zdepth);
622                 glVertex3f(1.0, -2.0, zdepth);
623                 glVertex3f(1.0, 2.0, zdepth);
624                 glVertex3f(0.2, 2.0, zdepth);
625                 glVertex3f(0.2, 2.2, zdepth);
626                 glVertex3f(-0.2, 2.2, zdepth);
627                 glVertex3f(-0.2, 2.0, zdepth);
628                 glVertex3f(-1.0, 2.0, zdepth);
629                 glVertex3f(-1.0, -2.0, zdepth);
630                 glEnd();
631         }
632         if (percent > ( full_wall * 2.0)) {
633                 glBegin(GL_QUADS);
634
635                 height = (percent  - full_wall * 2.0) /( 1.0 - full_wall * 2.0);
636                 if (height > 1.0) height = 1.0;
637
638
639                 if ( height > 0.8) {
640                         mi->polygon_count += 2;
641                         if ( height > 0.90) {
642                                 mi->polygon_count += 2;
643                                 /* TTTR */
644                                 texbot = tr0;
645                                 textop = tr0 + half_floor * height;
646                                 glTexCoord2f(0.0, texbot);
647                                 glVertex3f(0.2, 2.2, 0.0);
648                 
649                                 glTexCoord2f(0.0, textop);
650                                 glVertex3f(2.0 - height * 2.0, 2.2, 0.0);
651                 
652                                 glTexCoord2f(depth, textop);
653                                 glVertex3f(2.0 - height * 2.0, 2.2, zdepth);
654         
655                                 glTexCoord2f(depth, texbot);
656                                 glVertex3f(0.2, 2.2, zdepth);
657         
658                                 /* TTTL */
659                                 texbot = tl1 - half_floor * height;
660                                 textop = tl1;
661                                 glTexCoord2f(0.0, texbot);
662                                 glVertex3f(-2.0 + height * 2.0, 2.2, 0.0);
663                 
664                                 glTexCoord2f(0.0, textop);
665                                 glVertex3f(-0.2, 2.2, 0.0);
666                 
667                                 glTexCoord2f(depth, textop);
668                                 glVertex3f(-0.2, 2.2, zdepth);
669                 
670                                 glTexCoord2f(depth, texbot);
671                                 glVertex3f(-2.0 + height * 2.0, 2.2, zdepth);
672                         }
673                         if (height > 0.90) height = 0.90;
674
675                         /* TTR */
676                         texbot = tr0;
677                         textop = tr0 + half_floor * height;
678                         glTexCoord2f(0.0, texbot);
679                         glVertex3f(0.2, 2.0, 0.0);
680         
681                         glTexCoord2f(0.0, textop);
682                         glVertex3f(0.2, 0.4 + height * 2.0, 0.0);
683         
684                         glTexCoord2f(depth, textop);
685                         glVertex3f(0.2, 0.4 + height * 2.0, zdepth);
686         
687                         glTexCoord2f(depth, texbot);
688                         glVertex3f(0.2, 2.0, zdepth);
689
690                         /* TTL */
691                         texbot = tl1 - half_floor * height;
692                         textop = tl1;
693                         glTexCoord2f(0.0, texbot);
694                         /*glVertex3f(-.2, 2.0 + (0.9 - height) * 2.0, 0.0); */
695                         glVertex3f(-.2,  0.4 + height * 2.0, 0.0);
696         
697                         glTexCoord2f(0.0, textop);
698                         glVertex3f(-.2, 2.0, 0.0);
699         
700                         glTexCoord2f(depth, textop);
701                         glVertex3f(-.2, 2.0, zdepth);
702         
703                         glTexCoord2f(depth, texbot);
704                         glVertex3f(-.2, 0.4 + height * 2.0, zdepth);
705                 }
706         
707                 height = (percent  - full_wall * 2.0) /( 1.0 - full_wall * 2.0);
708                 if (height > 0.8) height = 0.8;
709
710
711                 mi->polygon_count += 2;
712                 /* TR */
713                 texbot = tr0;
714                 textop = tr0 + half_floor * height;
715                 glTexCoord2f(0.0, texbot);
716                 glVertex3f(1.0, 2.0, 0.0);
717
718                 glTexCoord2f(0.0, textop);
719                 glVertex3f(1.0 - height, 2.0, 0.0);
720
721                 glTexCoord2f(depth, textop);
722                 glVertex3f(1.0 - height, 2.0, zdepth);
723
724                 glTexCoord2f(depth, texbot);
725                 glVertex3f(1.0, 2.0, zdepth);
726
727                 /* TL */
728                 texbot = tl1 - half_floor * height;
729                 textop = tl1;
730                 glTexCoord2f(0.0, texbot);
731                 glVertex3f(-1.0 + height, 2.0, 0.0);
732
733                 glTexCoord2f(0.0, textop);
734                 glVertex3f(-1.0, 2.0, 0.0);
735
736                 glTexCoord2f(depth, textop);
737                 glVertex3f(-1.0, 2.0, zdepth);
738
739                 glTexCoord2f(depth, texbot);
740                 glVertex3f(-1.0 + height, 2.0, zdepth);
741
742                 height = (percent  - full_wall * 2.0) /( 1.0 - full_wall * 2.0);
743
744                 if (height > 1.0) height = 1.0;
745
746
747                 mi->polygon_count += 2;
748                 /* BR */
749                 texbot = tr0;
750                 textop = tr0 + half_floor * height;
751                 glTexCoord2f(0.0, texbot);
752                 glVertex3f(1.0, -2.0, 0.0);
753
754                 glTexCoord2f(0.0, textop);
755                 glVertex3f(1.0 - height, -2.0, 0.0);
756
757                 glTexCoord2f(depth, textop);
758                 glVertex3f(1.0 - height, -2.0, zdepth);
759
760                 glTexCoord2f(depth, texbot);
761                 glVertex3f(1.0, -2.0, zdepth);
762
763                 /* BL */
764                 texbot = tl1 - half_floor * height;
765                 textop = tl1;
766                 glTexCoord2f(0.0, texbot);
767                 glVertex3f(-1.0 + height, -2.0, 0.0);
768
769                 glTexCoord2f(0.0, textop);
770                 glVertex3f(-1.0, -2.0, 0.0);
771
772                 glTexCoord2f(depth, textop);
773                 glVertex3f(-1.0, -2.0, zdepth);
774
775                 glTexCoord2f(depth, texbot);
776                 glVertex3f(-1.0 + height, -2.0, zdepth);
777
778                 
779                 glEnd();
780         }
781         
782         if (percent > 0.0) {
783                 mi->polygon_count += 2;
784                 glBegin(GL_QUADS);
785                 height = percent / ( full_wall * 2.0);
786                 if (height > 1.0) height = 1.0;
787                 textop = (l0 + l1) / 2.0 - full_wall * 0.5 * height;
788                 texbot = (l0 + l1) / 2.0 + full_wall * 0.5 * height;
789
790                 glTexCoord2f(0.0, textop);
791                 glVertex3f(-1.0, height * 2, 0.0);
792
793                 glTexCoord2f(0.0, texbot);
794                 glVertex3f(-1.0, -height * 2, 0.0);
795
796                 glTexCoord2f(depth, texbot);
797                 glVertex3f(-1.0, -height * 2, zdepth);
798
799                 glTexCoord2f(depth, textop);
800                 glVertex3f(-1.0, height * 2, zdepth);
801
802                 textop = (r0 + r1) / 2.0 - full_wall * 0.5 * height;
803                 texbot = (r0 + r1) / 2.0 + full_wall * 0.5 * height;
804
805                 glTexCoord2f(0.0, texbot);
806                 glVertex3f(1.0, height * 2, 0.0);
807
808                 glTexCoord2f(0.0, textop);
809                 glVertex3f(1.0, -height * 2, 0.0);
810
811                 glTexCoord2f(depth, textop);
812                 glVertex3f(1.0, -height * 2, zdepth);
813
814                 glTexCoord2f(depth, texbot);
815                 glVertex3f(1.0, height * 2, zdepth);
816                 glEnd();
817         }
818
819
820         glMatrixMode(GL_TEXTURE);
821         glLoadIdentity();
822         glMatrixMode(GL_MODELVIEW);
823 } /* make_wall_tunnel */
824
825 /* wraps an int to between min and max.
826    Kind of like the remainder when devided by (max - min).
827    Used to create torus mapping on square array */
828 static int wrapVal(int val, int min, int max)
829 {
830         int ret;
831
832         ret = val;
833         if (val >= max)
834                 ret = min + (val - max ) % (max - min);
835         if (val < min)
836                 ret = max - (min - val) % (max - min);
837         return(ret);
838 }
839
840 /*=================== Load Texture =========================================*/
841 /* ripped from atunnel.c,  Copyright (c) E. Lassauge, 2003-2004. */
842 /* modified like so by Sean Brennan:
843   take texture object for glbind
844   removed xlock stuff
845   Added filters:
846     blur color / alpha channel [3x3 box filter, done [blur] times
847     anegative : create b/w image from zero alpha. zero alpha gets bw_color,
848                 nonzero alpha gets 1.0 - bwcolor, then alpha flipped to 1-alpha.
849
850   Inputs: xpm structure, or filename of xmp image.  if filename == NULL, use structure.
851   Outputs: texture bound to texutre Id texbind.
852
853 */
854
855 static float mylog2(float x) { return ( log(x) / log(2));}
856
857 static void LoadTexture(ModeInfo * mi, char **fn, const char *filename, GLuint texbind, int blur, float bw_color, Bool anegative, Bool onealpha)
858 {
859         /* looping and temporary array index variables */
860         int ix, iy, bx, by, indx, indy, boxsize, cchan, tmpidx, dtaidx;
861
862         float boxdiv, tmpfa, blursum ;
863         unsigned char *tmpbuf, tmpa;
864         Bool rescale;
865
866
867         XImage *teximage;    /* Texture data */
868
869         rescale = False;
870
871         boxsize = 2;
872         boxdiv = 1.0 / ( boxsize * 2.0 + 1.0) / ( boxsize * 2.0 + 1.0);
873
874
875         if (filename) 
876                 teximage = xpm_file_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
877                          MI_COLORMAP(mi), filename);
878         else 
879                 teximage = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
880                          MI_COLORMAP(mi), fn);
881         if (teximage == NULL) {
882             fprintf(stderr, "%s: error reading the texture.\n", progname);
883             glDeleteTextures(1, &texbind);
884             do_texture = False;
885             exit(0);
886         }
887
888         /* check if image is 2^kumquat, where kumquat is an integer between 1 and 10. Recale to
889            nearest power of 2. */
890         tmpfa = mylog2((float) teximage->width);
891         bx = 2 << (int) (tmpfa -1);
892         if (bx != teximage->width) {
893                 rescale = True;
894                 if ((tmpfa - (int) tmpfa) >  0.5849)
895                         bx = bx * 2;
896         }
897         tmpfa = mylog2((float) teximage->height);
898         by = 2 << (int) (tmpfa - 1);
899         if (by != teximage->height) {
900                 rescale = True;
901                 if ((tmpfa - (int) tmpfa) >  0.5849)
902                         by = by * 2;
903         }
904
905         if (rescale) {
906                 tmpbuf = calloc(bx * by * 4, sizeof(unsigned char));
907                 if (gluScaleImage(GL_RGBA, teximage->width, teximage->height, GL_UNSIGNED_BYTE, teximage->data,
908                                 bx, by, GL_UNSIGNED_BYTE, tmpbuf))
909                         check_gl_error("scale image");
910                 
911                 free(teximage->data);
912                 teximage->data = (char *) tmpbuf;
913                 teximage->width = bx;
914                 teximage->height= by;
915         }
916         /* end rescale code */
917                 
918         if (anegative ) {
919                 for (ix = 0 ; ix < teximage->height * teximage->width; ix++)
920                         {
921                                 if (!teximage->data[ ix * 4 + 3]) {
922                                         teximage->data[ ix * 4 + 3]  = (unsigned char) 0xff;
923                                         tmpa = (unsigned char) (bw_color * 0xff);
924                                 } else  {
925                                         if (onealpha)
926                                                 teximage->data[ ix * 4 + 3]  = (unsigned char) 0xff;
927                                         else
928                                                 teximage->data[ ix * 4 + 3]  = (unsigned char)  0xff - 
929                                                                 teximage->data[ ix * 4 + 3];
930                                         tmpa = (unsigned char) ((1.0 - bw_color) * 0xff);
931                                 }
932                                 /* make texture uniform b/w color */
933                                 teximage->data[ ix * 4 + 0]  =
934                                         (unsigned char) ( tmpa);
935                                 teximage->data[ ix * 4 + 1]  =
936                                         (unsigned char) ( tmpa);
937                                 teximage->data[ ix * 4 + 2]  =
938                                         (unsigned char) ( tmpa);
939                                 /* negate alpha */
940                         }
941         }
942                 
943         if (blur > 0) {
944                 if (! anegative ) /* anegative alread b/w's the whole image */
945                         for (ix = 0 ; ix < teximage->height * teximage->width; ix++)
946                                 if (!teximage->data[ ix * 4 + 3])
947                                 {
948                                         teximage->data[ ix * 4 + 0]  =
949                                                 (unsigned char) ( 255.0 * bw_color);
950                                         teximage->data[ ix * 4 + 1]  =
951                                                 (unsigned char) ( 255.0 * bw_color);
952                                         teximage->data[ ix * 4 + 2]  =
953                                                 (unsigned char) ( 255.0 * bw_color);
954                                 }
955                 ;
956                 tmpbuf = calloc(teximage->height * teximage->width * 4, sizeof(unsigned char)  )        ;
957                 while (blur--) {
958                         /* zero out tmp alpha buffer */
959                         for (iy = 0 ; iy <teximage->height * teximage->width * 4 ; iy++)
960                                 tmpbuf[iy] = 0;
961                         for (cchan = 0; cchan < 4 ; cchan++) {
962                                 for (iy = 0 ; iy < teximage->height ; iy++) {
963                                         for (ix = 0 ; ix < teximage->width ; ix++) {
964                                                 dtaidx = (teximage->width * iy + ix) * 4;
965                                                 tmpa =  teximage->data[dtaidx + cchan];
966                                                 tmpfa = (float) tmpa * boxdiv;
967                                                 /* box filter */
968                                                 blursum = 0.0;
969                                                 for (by = -boxsize ; by <= boxsize; by++) {
970                                                         for (bx = -boxsize ; bx <= boxsize; bx++) {
971                                                                 indx = wrapVal(ix + bx, 0, teximage->width);
972                                                                 indy = wrapVal(iy + by, 0, teximage->height);
973                                                                 tmpidx = (teximage->width * indy + indx) * 4;
974                                                                 blursum = tmpfa;
975                                                                 tmpbuf[tmpidx + cchan] += (unsigned char) blursum;
976                                                         } /* for bx */
977                                                 } /* for by  */
978                                         } /* for ix  */
979                                 } /* for iy */
980                         } /* for cchan */
981                         /* copy back buffer */
982                         for (ix = 0 ; ix < teximage->height * teximage->width * 4; ix++)
983                                 teximage->data[ix] = tmpbuf[ix];
984                 } /*while blur */
985                 free(tmpbuf); /*tidy*/
986         } /* if blur */
987
988                         
989         
990
991         clear_gl_error();
992 #ifdef HAVE_GLBINDTEXTURE
993         glBindTexture(GL_TEXTURE_2D, texbind);
994 #endif
995         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
996         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, teximage->width, teximage->height,
997                         0, GL_RGBA, GL_UNSIGNED_BYTE, teximage->data);
998         check_gl_error("texture");
999         setTexParams(); 
1000         XDestroyImage(teximage);
1001 }
1002
1003 /* creates cylinder for time tunnel. sides, zmin, zmax, rad(ius) obvious.
1004    stretch scales texture coords; makes tunnel go slower the larger it is.
1005    not drawn, but put into display list. */
1006 static void makecyl(int sides, float zmin, float zmax, float rad, float stretch) 
1007 {
1008         int i;
1009         float theta;
1010
1011         /* cap */
1012         if (do_fog) {
1013                 glBegin(GL_TRIANGLE_FAN);
1014                 glTexCoord2f(1.0, 0.0);
1015                 glVertex3f(0.0 , 0.0 , zmax); 
1016                 for (i = 0 ; i <= sides; i++) {  
1017                         theta = 2.0 * M_PI * ((float) i / (float) sides);
1018                         glVertex3f(cos(theta) * rad, sin(theta) * rad, zmax);
1019                 }
1020                 glVertex3f(cos(0.0) * rad, sin(0.0) * rad, zmax);
1021                 glEnd(); 
1022         }
1023         
1024         glBegin(GL_QUAD_STRIP);
1025         for (i = 0 ; i <= sides; i++)
1026         {
1027                 if ( i != sides) {
1028                         theta = 2.0 * M_PI * ((float) i / (float) sides);
1029                         glTexCoord2f(0.0, 1.0 * (float) i / (float) sides); 
1030                         glVertex3f(cos(theta) * rad, sin(theta) * rad, zmin);
1031                         glTexCoord2f(stretch, 1.0 * (float) i / (float) sides); 
1032                         glVertex3f(cos(theta) * rad, sin(theta) * rad, zmax);
1033                 } else {
1034                         theta = 0.0;
1035                         glTexCoord2f(0.0, 1.0);
1036                         glVertex3f(cos(theta) * rad, sin(theta) * rad, zmin);
1037                         glTexCoord2f(stretch, 1.0);
1038                         glVertex3f(cos(theta) * rad, sin(theta) * rad, zmax);
1039                 }
1040         }
1041         glEnd();
1042 }
1043
1044 ENTRYPOINT void 
1045 init_tunnel (ModeInfo *mi)
1046 {
1047   int i;
1048
1049   tunnel_configuration *tc;
1050   
1051   wire = MI_IS_WIREFRAME(mi);
1052
1053   if (!tconf) {
1054     tconf = (tunnel_configuration *)
1055       calloc (MI_NUM_SCREENS(mi), sizeof (tunnel_configuration));
1056     if (!tconf) {
1057       fprintf(stderr, "%s: out of memory\n", progname);
1058       exit(1);
1059     }
1060
1061     tc = &tconf[MI_SCREEN(mi)];
1062   }
1063
1064   tc = &tconf[MI_SCREEN(mi)];
1065
1066   tc->glx_context = init_GL(mi);
1067
1068   tc->cyllist = glGenLists(1);
1069   tc->diamondlist = glGenLists(1);
1070   tc->num_effects = 12;
1071   tc->num_texshifts = 3;
1072   tc->effect_time = 0.0;
1073   tc->effect_maxsecs = 30.00;
1074   /* check bounds on cmd line opts */
1075   if (start > tc->effect_maxsecs) start = tc->effect_maxsecs;
1076   if (end > tc->effect_maxsecs) end = tc->effect_maxsecs;
1077   if (start < tc->effect_time) start = tc->effect_time;
1078   if (end < tc->effect_time) end = tc->effect_time;
1079
1080   /* set loop times, in seconds */
1081   tc->start_time = start;
1082   tc->end_time = end;
1083
1084   /* reset animation knots, effect 0 not defined. */
1085   tc->effects = malloc(sizeof(effect_t) * ( tc->num_effects + 1));
1086   for ( i = 1; i <= tc->num_effects ; i++)
1087         init_effects(&tc->effects[i], i);
1088
1089   if (wire) {
1090         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1091         do_texture = False;
1092   }
1093
1094   if (do_texture)
1095   {
1096           /* the following textures are loaded, and possible overridden:
1097                 tunnel 1, tunnel 2, tunnel 3, marquee, tardis, head */
1098           glGenTextures(MAX_TEXTURE, tc->texture_binds);
1099           
1100           /*LoadTexture(*mi, **fn, *filename, texbind, bluralpha, bw_color,  anegative, onealpha)*/
1101           if (strcasecmp (do_tun1, "(none)")) /* tunnel 1 */
1102                 LoadTexture(mi, NULL, do_tun1, tc->texture_binds[0],  0,0.0, False, False);
1103           else
1104                 LoadTexture(mi, timetunnel0_xpm, NULL, tc->texture_binds[0], 0, 0.0, False, False);
1105           if (strcasecmp (do_tun2, "(none)")) /* tunnel 2 */
1106                 LoadTexture(mi, NULL, do_tun2, tc->texture_binds[2],  0,0.0, False, False);
1107           else
1108                 LoadTexture(mi, timetunnel1_xpm, NULL, tc->texture_binds[2], 0, 0.0, False, False);
1109           if (strcasecmp (do_tun3, "(none)")) /* tunnel 3 */
1110                 LoadTexture(mi, NULL, do_tun3, tc->texture_binds[5],  0,0.0, False, False);
1111           else
1112                 LoadTexture(mi, timetunnel2_xpm, NULL, tc->texture_binds[5], 0, 0.0, False, False);
1113           LoadTexture(mi, tunnelstar_xpm, NULL, tc->texture_binds[4], 0, 0.0, False, False);
1114           if (strcasecmp (do_tx1, "(none)")) /* marquee */
1115                 LoadTexture(mi, NULL, do_tx1, tc->texture_binds[3],  0,0.0, False, False);
1116           else
1117                 LoadTexture(mi, (char **) logo_180_xpm, NULL, tc->texture_binds[3],  0,0.0, False, False);
1118           if (strcasecmp (do_tx2, "(none)")) /* tardis */
1119                 LoadTexture(mi, NULL, do_tx2, tc->texture_binds[1], 0, 0.0 ,False, False);
1120           else
1121                 LoadTexture(mi, (char **) logo_180_xpm, NULL, tc->texture_binds[1],  0,0.0, False, False);
1122           if (strcasecmp (do_tx3, "(none)")) { /* head */
1123                 LoadTexture(mi,  NULL, do_tx3, tc->texture_binds[6], 0, 0.0 ,False, False);
1124                 /* negative */
1125                 LoadTexture(mi,  NULL, do_tx3, tc->texture_binds[9],  2,1.0, True, True);
1126           } else {
1127                 LoadTexture(mi, (char **) logo_180_xpm, NULL, tc->texture_binds[6],  0,0.0, False, False);
1128                 /* negative */
1129                 LoadTexture(mi, (char **) logo_180_xpm, NULL, tc->texture_binds[9],  2,1.0, True, True);
1130           }
1131           glEnable(GL_TEXTURE_2D);
1132           check_gl_error("tex");
1133   }
1134
1135   reshape_tunnel (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1136
1137   glDisable(GL_DEPTH_TEST);  /* who needs it? ;-) */
1138
1139   if (do_fog)
1140         glEnable(GL_FOG);
1141
1142   if (!wire)
1143     {
1144       glEnable(GL_ALPHA_TEST);
1145       glAlphaFunc(GL_GREATER, 0.5);
1146     }
1147
1148     tc->trackball = gltrackball_init ();
1149
1150
1151   tc->texshift = calloc(tc->num_texshifts, sizeof(GLfloat));
1152   for ( i = 0 ; i < tc->num_texshifts; i++)
1153         tc->texshift[i] = 0.0;
1154
1155   glNewList(tc->cyllist, GL_COMPILE);
1156   makecyl(30, -0.1, CYL_LEN, 1., 10. / 40.0 * CYL_LEN);  
1157   /*makecyl(30, -0.5, DIAMOND_LEN, 1., 4. / 40 * DIAMOND_LEN); */
1158   glEndList();
1159
1160   glNewList(tc->diamondlist, GL_COMPILE);
1161   makecyl(4, -0.5, DIAMOND_LEN, 1., 4. / 40 * DIAMOND_LEN);
1162   glEndList();
1163 }
1164
1165
1166 ENTRYPOINT void
1167 draw_tunnel (ModeInfo *mi)
1168 {
1169   tunnel_configuration *tc = &tconf[MI_SCREEN(mi)];
1170   Display *dpy = MI_DISPLAY(mi);
1171   Window window = MI_WINDOW(mi);
1172
1173
1174   if (!tc->glx_context)
1175     return;
1176
1177   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(tc->glx_context));
1178
1179   glShadeModel(GL_SMOOTH);
1180
1181   glEnable(GL_NORMALIZE);
1182   /* glEnable(GL_CULL_FACE); */
1183
1184   glClear(GL_COLOR_BUFFER_BIT );
1185
1186   update_animation(tc);
1187
1188
1189   glPushMatrix ();
1190
1191         glRotatef(180., 0., 1., 0.);
1192     gltrackball_rotate (tc->trackball);
1193         glRotatef(180., 0., 1., 0.);
1194
1195
1196
1197   mi->polygon_count = 0;
1198
1199   update_fog(tc->effects[4].state[0],  /*color*/
1200              tc->effects[4].state[1],  /*density*/
1201              tc->effects[4].state[2],  /*start*/
1202              tc->effects[4].state[3]); /*end*/
1203
1204   /* --- begin composite image assembly --- */
1205
1206   /* head mask and draw diamond tunnel */
1207
1208   glEnable(GL_BLEND);
1209   draw_cyl(mi, tc, tc->effects[6].state[0], 5, tc->diamondlist, 2); 
1210   if (drawlogo)
1211         draw_sign(mi, tc,tc->effects[12].state[0], tc->effects[12].state[1],  1.0 / 1.33, 9, 1); 
1212   glDisable(GL_BLEND);
1213   /* then tardis tunnel */
1214   make_wall_tunnel(mi, tc, tc->effects[1].state[0], tc->effects[7].state[0]);
1215
1216   /* then cylinder tunnel */
1217   glEnable(GL_BLEND);
1218   draw_cyl(mi, tc, tc->effects[3].state[0], 2, tc->cyllist, 1); 
1219
1220        /*void draw_sign(mi, tc,z,alpha,aspect,tex,blendmode)*/
1221   /* tardis */
1222   if (drawlogo)
1223         draw_sign(mi, tc, tc->effects[2].state[0], tc->effects[2].state[1], 2.0, 1, 0);
1224   /* marquee */
1225   if (drawlogo)
1226         draw_sign(mi, tc, tc->effects[5].state[0], tc->effects[5].state[1], 1.0, 3, 0);
1227   /*who head brite*/
1228   if (drawlogo)
1229         draw_sign(mi, tc,1.0, tc->effects[10].state[0],  1.0 / 1.33, 6, 2);
1230   /*who head psychadelic REMOVED*/
1231   /* draw_sign(mi, tc,1.0, tc->effects[11].state[0],  1.0 / 1.33, 8, 0); */
1232
1233   /* star */
1234   /* draw_sign(mi, tc, tc->effects[8].state[0]tc->effects[8].state[0], 1.0 , 1.0, 4, 1); */
1235   draw_sign(mi, tc,  tc->effects[8].state[0],  tc->effects[8].state[0],  1.0, 4, 1);
1236  
1237   /* normal head */
1238   if (drawlogo)
1239         draw_sign(mi, tc,1.0, tc->effects[9].state[0], 1.0 /  1.33, 6, 0);
1240
1241   /* --- end composite image assembly --- */
1242
1243
1244   glPopMatrix ();
1245
1246   if (mi->fps_p) do_fps (mi);
1247   glFinish();
1248
1249   check_gl_error("drawing done, calling swap buffers");
1250   glXSwapBuffers(dpy, window);
1251 }
1252
1253 XSCREENSAVER_MODULE_2 ("TimeTunnel", timetunnel, tunnel)
1254
1255 #endif /* USE_GL */