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