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