http://ftp.x.org/contrib/applications/xscreensaver-3.07.tar.gz
[xscreensaver] / hacks / t3d.c
1 /* t3d -- Flying Balls Clock Demo
2    by Bernd Paysan , paysan@informatik.tu-muenchen.de
3
4    Copy, modify, and distribute T3D either under GPL  version 2 or newer, 
5    or under the standard MIT/X license notice.
6
7   partly based on flying balls demo by Georg Acher, 
8   acher@informatik.tu-muenchen.de
9   (developed on HP9000/720 (55 MIPS,20 MFLOPS) )
10   NO warranty at all ! Complaints to /dev/null !
11
12   4-Jan-99 jwz@jwz.org -- adapted to xscreensaver framework, to take advantage
13                           of the command-line options provided by screenhack.c.
14 */
15
16 #undef FASTDRAW
17 #undef USE_POLYGON
18
19 #ifdef FASTDRAW
20 # define FASTCOPY
21 #endif
22
23 #include <stdio.h>
24 #include <math.h>
25
26 #include "screenhack.h"
27
28
29 static int maxk=34;
30
31 #define   WIDTH      200
32 #define   HEIGHT     200
33 #define   norm       20.0
34
35 int timewait=40000;
36
37 #define   ROOT       0x1
38 #define PI M_PI
39 #define TWOPI 2*M_PI
40
41 #define MIN(i,j) ((i)<(j)?(i):(j))
42
43 #define kmax ((minutes?60:24))
44 /* Anzahl der Kugeln */
45 #define sines 52
46 /* Werte in der Sinus-Tabelle */
47 /*-----------------------------------------------------------------*/
48 #define setink(inkcolor) \
49         XSetForeground (dpy,gc,inkcolor)
50
51 #define drawline(xx1,yy1,xx2,yy2) \
52         XDrawLine(dpy,win,gc,xx1,yy1,xx2,yy2) 
53
54 #define drawseg(segments,nr_segments) \
55         XDrawSegments(dpy,win,gc,segments,nr_segments) 
56
57
58 #define polyfill(ppts,pcount) \
59         XFillPolygon(dpy,win,gc,ppts,pcount,Convex,CoordModeOrigin)
60
61
62 #define frac(argument) argument-floor(argument)
63
64 #define abs(x) ((x)<0.0 ? -(x) : (x))
65
66 static Colormap cmap;
67 /* static XColor gray1; */
68 static double r=1.0,g=1.0,b=1.0;
69 static double hue=0.0,sat=0.0,val=1.0;
70
71 typedef struct {
72   double x,y,z,r,d,r1;
73   int x1,y1;
74 } kugeldat;
75
76 /* Felder fuer 3D */
77
78 static kugeldat kugeln[100];
79
80 static double  a[3],/*m[3],*/am[3],x[3],y[3],v[3];
81 static double zoom,speed,zaehler,vspeed/*,AE*/;
82 static double vturn/*,aturn*/;
83 /* static XPoint track[sines]; */
84 static double sinus[sines];
85 static double cosinus[sines];
86
87 static int startx,starty;
88 static double /*magx,magy,*/mag=10;
89 /* static double lastx,lasty,lastz; */
90 /* static int lastcx,lastcy,lastcz; */
91 /* static int move=1; */
92 static int minutes=0;
93 static int cycl=0;
94 static double hsvcycl=0.0;
95 static double movef =0.5, wobber=2.0, cycle=6.0;
96
97 /* time */
98
99 /* static double sec; */
100
101 /* Windows */
102 static XWindowAttributes xgwa;
103 static GC       gc;
104 static GC orgc;
105 static GC andgc;
106 static Window   win;
107 /* static Font font; */
108 static Display  *dpy;
109 static int      screen, scrnWidth = WIDTH, scrnHeight = HEIGHT;
110 static Pixmap  buffer;
111 #define maxfast 100
112 static int fastch=50;
113 #ifdef FASTDRAW
114 #       ifdef FASTCOPY
115 #               define sum1ton(a) (((a)*(a)+1)/2)
116 #               define fastcw sum1ton(fastch)
117                 static Pixmap fastcircles;
118                 static Pixmap fastmask;
119 #       else
120                 static XImage* fastcircles[maxfast];
121                 static XImage* fastmask[maxfast];
122 #       endif
123 static int fastdraw=0;
124 #endif
125
126 static int scrnW2,scrnH2;
127 /* static unsigned short flags = 0; */
128 /* static char *text; */
129 static XColor colors[64];
130 static struct tm *zeit;
131
132 static int planes;
133 /* compute time */
134
135 static double
136 gettime (void)
137 {
138   struct timeval time1;
139   struct timezone zone1;
140   struct tm *zeit;
141   
142   gettimeofday(&time1,&zone1);
143   zeit=localtime(&time1.tv_sec);
144   
145   return (zeit->tm_sec+60*(zeit->tm_min+60*(zeit->tm_hour))
146           + time1.tv_usec*1.0E-6);
147 }
148
149 /* --------------------COLORMAP---------------------*/ 
150
151 static void
152 hsv2rgb (double h, double s, double v, double *r, double *g, double *b)
153 {
154   h/=360.0;     h=6*(h-floor(h));
155
156   if(s==0.0)
157     {
158       *r=*g=*b=v;
159     }
160   else
161     {   int i=(int)h;
162         double t,u,w;
163         
164         h=h-floor(h);
165         
166         u=v*(s*(1.0-h));
167         w=v*(1.0-s);
168         t=v*(s*h+1.0-s);
169         
170         switch(i)
171           {
172           case 0:       *r=v;   *g=t;   *b=w;   break;
173           case 1:       *r=u;   *g=v;   *b=w;   break;
174           case 2:       *r=w;   *g=v;   *b=t;   break;
175           case 3:       *r=w;   *g=u;   *b=v;   break;
176           case 4:       *r=t;   *g=w;   *b=v;   break;
177           case 5:       *r=v;   *g=w;   *b=u;   break;
178           }
179       }
180 #ifdef PRTDBX
181   printf("HSV: %f %f %f to\nRGB: %f %f %f\n",h,s,v,*r,*g,*b);
182 #endif
183 }
184
185 static void
186 changeColor (double r, double g, double b)
187 {
188   int n,n1;
189   
190   n1=0;
191   for(n=30;n<64;n+=3)
192     {
193       colors[n1].red   =1023+ n*(int)(1024.*r);
194       colors[n1].blue  =1023+ n*(int)(1024.*b);
195       colors[n1].green =1023+ n*(int)(1024.*g);
196       
197       n1++;
198     }
199   
200   XStoreColors (dpy, cmap, colors, 12);
201 }
202
203 static void 
204 initColor (double r, double g, double b)
205 {
206   int n,n1;
207   unsigned long pixels[12];
208   long dummy;
209   
210   cmap = xgwa.colormap;
211   
212   if(hsvcycl!=0.0 && XAllocColorCells(dpy, cmap, 0, &dummy, 0, pixels, 12))
213     {
214       for(n1=0;n1<12;n1++)
215         {
216           colors[n1].pixel=pixels[n1];
217           colors[n1].flags=DoRed | DoGreen | DoBlue;
218         }
219       
220       changeColor(r,g,b);
221     }
222   else
223     {
224       n1=0;
225       for(n=30;n<64;n+=3)
226         {
227           colors[n1].red   =1023+ n*(int)(1024.*r);
228           colors[n1].blue  =1023+ n*(int)(1024.*b);
229           colors[n1].green =1023+ n*(int)(1024.*g);
230           
231           if (!(XAllocColor (dpy, cmap, &colors[n1]))) {
232             (void) fprintf (stderr, "Error:  Cannot allocate colors\n");
233             exit (1);
234           }
235           
236           n1++;
237         }
238     }
239 }
240
241 /* ----------------WINDOW-------------------*/
242
243 static void
244 initialize (void)
245 {
246   XGCValues *xgc;
247   XGCValues *xorgc;
248   XGCValues *xandgc;
249
250   XGetWindowAttributes (dpy, win, &xgwa);
251   scrnWidth = xgwa.width;
252   scrnHeight = xgwa.height;
253
254   cycle = 60.0 / get_float_resource ("cycle", "Float");
255   movef = get_float_resource ("move", "Float") / 2;
256   wobber *= get_float_resource ("wobble", "Float");
257
258   {
259     double magfac = get_float_resource ("mag", "Float");
260     mag *= magfac;
261     fastch=(int)(fastch*magfac);
262   }
263
264   if (get_boolean_resource ("minutes", "Boolean")) {
265     minutes=1; maxk+=60-24;
266   }
267
268   timewait = get_integer_resource ("wait", "Integer");
269   fastch = get_integer_resource ("fast", "Integer");
270   cycl = get_boolean_resource ("colcycle", "Integer");
271   hsvcycl = get_float_resource ("hsvcycle", "Integer");
272
273   {
274     char *s = get_string_resource ("rgb", "RGB");
275     char dummy;
276     if (s && *s)
277       {
278         double rr, gg, bb;
279         if (3 == sscanf (s, "%lf %lf %lf %c", &rr, &gg, &bb, &dummy))
280           r = rr, g = gg, b = bb;
281       }
282     if (s) free (s);
283
284     s = get_string_resource ("hsv", "HSV");
285     if (s && *s)
286       {
287         double hh, ss, vv;
288         if (3 == sscanf (s, "%lf %lf %lf", &hh, &ss, &vv, &dummy)) {
289           hue = hh, sat = ss, val = vv;
290           hsv2rgb(hue,sat,val,&r,&g,&b);
291         }
292       }
293     if (s) free (s);
294   }
295
296   if (fastch>maxfast)
297                 fastch=maxfast;
298   
299 #ifdef PRTDBX
300   printf("Set options:\ndisplay: '%s'\ngeometry: '%s'\n",display,geometry);
301   printf("move\t%.2f\nwobber\t%.2f\nmag\t%.2f\ncycle\t%.4f\n",
302          movef,wobber,mag/10,cycle);
303   printf("nice\t%i\nfast\t%i\nmarks\t%i\nwait\t%i\n",niced,fastch,maxk,timewait);
304 #endif
305   
306   xgc=( XGCValues *) malloc(sizeof(XGCValues) );
307   xorgc=( XGCValues *) malloc(sizeof(XGCValues) );
308   xandgc=( XGCValues *) malloc(sizeof(XGCValues) );
309
310   screen = screen_number (xgwa.screen);
311   
312   planes=xgwa.depth;
313
314   gc = XCreateGC (dpy, win, 0,  xgc);
315   xorgc->function =GXor;
316   orgc = XCreateGC (dpy, win, GCFunction,  xorgc);
317   xandgc->function =GXandInverted;
318   andgc = XCreateGC (dpy, win, GCFunction,  xandgc);
319   
320   buffer = XCreatePixmap (dpy, win, scrnWidth, scrnHeight,
321                           xgwa.depth); 
322   
323 #ifdef DEBUG
324   printf("Time 3D drawing ");
325 #ifdef FASTDRAW
326 #       ifdef FASTCOPY
327   puts("fast by Pixmap copy");
328 #       else
329   puts("fast by XImage copy");
330 #       endif
331 #else
332   puts("slow");
333 #endif
334 #endif /* DEBUG */
335   
336 #ifdef FASTCOPY
337   fastcircles = XCreatePixmap (dpy, win, fastcw, fastch+1, xgwa.depth);
338   fastmask    = XCreatePixmap (dpy, win, fastcw, fastch+1, xgwa.depth);
339 #endif
340   
341   setink(BlackPixel (dpy, screen));
342   XFillRectangle (dpy, buffer     , gc, 0, 0, scrnWidth, scrnHeight);   
343   
344 #ifdef FASTCOPY
345   
346   setink(0);
347   XFillRectangle (dpy, fastcircles, gc, 0, 0, fastcw, fastch+1);
348   XFillRectangle (dpy, fastmask   , gc, 0, 0, fastcw, fastch+1);
349   
350 #endif
351 }
352
353 static void fill_kugel(int i, Pixmap buf, int setcol);
354
355
356 /*------------------------------------------------------------------*/
357 static void 
358 init_kugel(void)
359 {
360   
361 #ifdef FASTDRAW
362   int i;
363
364   for(i=0; i<fastch; i++)
365     {
366 #       ifdef FASTCOPY
367       kugeln[i].r1=-((double) i)/2 -1;
368       kugeln[i].x1=sum1ton(i);
369       kugeln[i].y1=((double) i)/2 +1;
370       
371       fill_kugel(i,fastcircles,1);
372       setink((1<<MIN(24,xgwa.depth))-1);
373       fill_kugel(i,fastmask,0);
374 #       else
375       kugeln[i].r1=-((double) i)/2 -1;
376       kugeln[i].x1=kugeln[i].y1=((double) i)/2 +1;
377       
378       fill_kugel(i,buffer,1);
379       fastcircles[i]=XGetImage(dpy,buffer,0,0,i+2,i+2,(1<<planes)-1,ZPixmap);
380       
381       setink((1<<MIN(24,xgwa.depth))-1);
382       fill_kugel(i,buffer,0);
383       fastmask[i]=XGetImage(dpy,buffer,0,0,i+2,i+2,(1<<planes)-1,ZPixmap);
384       
385       setink(0);
386       XFillRectangle (dpy, buffer     , gc, 0, 0, scrnWidth, scrnHeight);       
387 #       endif
388     }
389   fastdraw=1;
390 #endif
391 }
392
393 /* Zeiger zeichnen */
394
395 static void
396 zeiger(double dist,double rad, double z, double sec, int *q)
397 {
398   int i,n;
399   double gratio=sqrt(2.0/(1.0+sqrt(5.0)));
400   
401   n = *q;
402   
403   for(i=0;i<3;i++)
404     {
405       kugeln[n].x=dist*cos(sec);
406       kugeln[n].y=-dist*sin(sec);
407       kugeln[n].z=z;
408       kugeln[n].r=rad;
409       n++;
410
411       dist += rad;
412       rad = rad*gratio;
413     }
414   *q = n;
415 }
416
417 /*-----------------------------------------------------------------*
418  *                           Uhr zeichnen                          *
419  *-----------------------------------------------------------------*/
420
421 static void
422 manipulate(double k)
423 {
424   double i,l,/*xs,*/ys,zs,mod;
425   double /*persec,*/sec,min,hour;
426   int n;
427   
428   sec=TWOPI*modf(k/60,&mod);
429   min=TWOPI*modf(k/3600,&mod);
430   hour=TWOPI*modf(k/43200,&mod);
431   
432   l=TWOPI*modf(k/300,&mod);
433   i=0.0;
434   for (n=0;n<kmax;n++)
435     {
436       
437       kugeln[n].x=4.0*sin(i);
438       kugeln[n].y=4.0*cos(i);
439       kugeln[n].z=wobber* /* (sin(floor(2+2*l/(PI))*i)*sin(2*l)); */
440         cos((i-sec)*floor(2+5*l/(PI)))*sin(5*l);
441       if(minutes)
442         {
443           kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */
444             ((n % 5!=0) ? 0.3 : 0.6)*
445               ((n % 15 ==0) ? 1.25 : .75);
446         }
447       else
448         {
449           kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */
450             ((n & 1) ? 0.5 : 1.0)*
451               ((n % 6==0) ? 1.25 : .75);
452         }
453       i+=TWOPI/kmax;
454     }
455
456   kugeln[n].x=0.0;
457   kugeln[n].y=0.0;
458   kugeln[n].z=0.0;
459   kugeln[n].r=2.0+cos(TWOPI*modf(k,&mod))/2;
460   n++;
461   
462   zeiger(2.0,0.75,-2.0,sec,&n);
463   zeiger(1.0,1.0,-1.5,min,&n);
464   zeiger(0.0,1.5,-1.0,hour,&n);
465   
466   for(n=0;n<maxk;n++)
467     {
468       ys=kugeln[n].y*cos(movef*sin(cycle*sec))+
469         kugeln[n].z*sin(movef*sin(cycle*sec));
470       zs=-kugeln[n].y*sin(movef*sin(cycle*sec))+
471         kugeln[n].z*cos(movef*sin(cycle*sec));
472       kugeln[n].y=ys;
473       kugeln[n].z=zs;
474     }
475 }
476 /*------------------------------------------------------------------*/
477 static void
478 t3d_sort(int l, int r)
479 {
480   int i,j;
481   kugeldat ex;
482   double x;
483   
484   i=l;j=r;
485   x=kugeln[(l+r)/2].d;
486   while(1)
487     {
488       while(kugeln[i].d>x) i++;
489       while(x>kugeln[j].d) j--;
490       if (i<=j)
491         {
492           ex=kugeln[i];kugeln[i]=kugeln[j];kugeln[j]=ex;
493           i++;j--;
494         }
495       if (i>j) break;
496     }
497   if (l<j) t3d_sort(l,j);
498   if (i<r) t3d_sort (i,r);
499 }
500
501 /*------------------------------------------------------------------*/
502 static void
503 fill_kugel(int i, Pixmap buf, int setcol)
504 {
505   double ra;
506   int m,col,inc=1,inr=3,d;
507   d=(int)((abs(kugeln[i].r1)*2));
508   if (d==0) d=1;
509   
510 #ifdef FASTDRAW
511   if(fastdraw && d<fastch)
512     {
513 #       ifdef FASTCOPY
514       XCopyArea(dpy, fastmask, buf, andgc, sum1ton(d)-(d+1)/2, 1,d,d,
515                 (int)(kugeln[i].x1)-d/2, (int)(kugeln[i].y1)-d/2);
516       XCopyArea(dpy, fastcircles, buf, orgc, sum1ton(d)-(d+1)/2, 1,d,d,
517                 (int)(kugeln[i].x1)-d/2, (int)(kugeln[i].y1)-d/2);
518 #       else
519       XPutImage(dpy, buf, andgc, fastmask[d-1], 0, 0,
520                 (int)(kugeln[i].x1)-d/2, (int)(kugeln[i].y1)-d/2, d, d);
521       XPutImage(dpy, buf, orgc, fastcircles[d-1], 0, 0,
522                 (int)(kugeln[i].x1)-d/2, (int)(kugeln[i].y1)-d/2, d, d);
523 #       endif
524         }
525   else
526 #endif
527     {
528       if(abs(kugeln[i].r1)<6.0) inr=9;
529       
530       for (m=0;m<=28;m+=inr)
531         {
532           ra=kugeln[i].r1*sqrt(1-m*m/(28.0*28.0));
533 #ifdef PRTDBX
534           printf("Radius: %f\n",ra);
535 #endif
536           if(-ra< 3.0) inc=14;
537           else if(-ra< 6.0) inc=8;
538           else if(-ra<20.0) inc=4;
539           else if(-ra<40.0) inc=2;
540           if(setcol)
541             {
542               if (m==27) col=33;
543               else
544                 col=(int)(m);
545               if (col>33) col=33;       col/=3;
546               setink(colors[col].pixel);
547             }
548
549 #ifdef USE_POLYGON
550           {
551             int n, nr;
552           for (n=0,nr=0;n<=sines-1;n+=inc,nr++)
553             {
554               track[nr].x=kugeln[i].x1+(int)(ra*sinus[n])+(kugeln[i].r1-ra)/2;
555               track[nr].y=kugeln[i].y1+(int)(ra*cosinus[n])+(kugeln[i].r1-ra)/2;
556             }
557           XFillPolygon(dpy,buf,gc,track,nr,Convex,CoordModeOrigin);
558           }
559 #else /* Use XFillArc */
560           XFillArc(dpy, buf, gc,
561                    (int)(kugeln[i].x1+(kugeln[i].r1+ra)/2),
562                    (int)(kugeln[i].y1+(kugeln[i].r1+ra)/2),
563                    (int)-(2*ra+1), (int)-(2*ra+1), 0, 360*64);
564 #endif
565         }
566     }
567 }
568
569 /*------------------------------------------------------------------*/
570
571 static void
572 init_3d(void)
573 {
574   double i;
575   int n=0;
576   
577   a[0]=0.0;
578   a[1]=0.0;
579   a[2]=-10.0;
580   
581   x[0]=10.0;
582   x[1]=0.0;
583   x[2]=0.0;
584   
585   y[0]=0.0;
586   y[1]=10.0;
587   y[2]=0.0;
588   
589   
590   zoom=-10.0;
591   speed=.0;
592   
593   for (i=0.0;n<sines;i+=TWOPI/sines,n++)
594     {
595       sinus[n]=sin(i);
596       cosinus[n]=cos(i);
597     }
598 }
599 /*------------------------------------------------------------------*/
600
601
602 static void
603 vektorprodukt(double feld1[], double feld2[], double feld3[])
604 {
605   feld3[0]=feld1[1]*feld2[2]-feld1[2]*feld2[1];
606   feld3[1]=feld1[2]*feld2[0]-feld1[0]*feld2[2];
607   feld3[2]=feld1[0]*feld2[1]-feld1[1]*feld2[0];
608 }
609 /*------------------------------------------------------------------*/
610 static void
611 turn(double feld1[], double feld2[], double winkel)
612 {
613   double temp[3];
614   double s,ca,sa,sx1,sx2,sx3;
615   
616   vektorprodukt(feld1,feld2,temp);
617   
618   s=feld1[0]*feld2[0]+feld1[1]*feld2[1]+feld1[2]*feld2[2];
619   
620   sx1=s*feld2[0];
621   sx2=s*feld2[1];
622   sx3=s*feld2[2];
623   sa=sin(winkel);ca=cos(winkel);
624   feld1[0]=ca*(feld1[0]-sx1)+sa*temp[0]+sx1;
625   feld1[1]=ca*(feld1[1]-sx2)+sa*temp[1]+sx2;
626   feld1[2]=ca*(feld1[2]-sx3)+sa*temp[2]+sx3;
627 }
628 /*------------------------------------------------------------------*/
629
630 /* 1: Blickrichtung v;3:Ebenenmittelpunkt m 
631    double feld1[],feld3[]; */
632 static void 
633 viewpoint(void)
634 {
635   am[0]=-zoom*v[0];
636   am[1]=-zoom*v[1];
637   am[2]=-zoom*v[2];
638   
639   zaehler=norm*norm*zoom;
640 }
641 /*------------------------------------------------------------------*/
642 static void 
643 projektion(void)
644 {
645   double c1[3],c2[3],k[3],x1,y1;
646   double cno,cnorm/*,magnit*/;
647   int i;
648   
649   for (i=0;i<maxk;i++)
650     {
651       c1[0]=kugeln[i].x-a[0];
652       c1[1]=kugeln[i].y-a[1];
653       c1[2]=kugeln[i].z-a[2];
654       cnorm=sqrt(c1[0]*c1[0]+c1[1]*c1[1]+c1[2]*c1[2]);
655       
656       c2[0]=c1[0];
657       c2[1]=c1[1];
658       c2[2]=c1[2];
659       
660       cno=c2[0]*v[0]+c2[1]*v[1]+c2[2]*v[2];
661       kugeln[i].d=cnorm;
662       if (cno<0) kugeln[i].d=-20.0;
663       
664       
665       kugeln[i].r1=(mag*zoom*kugeln[i].r/cnorm);
666       
667       c2[0]=v[0]/cno;
668       c2[1]=v[1]/cno;
669       c2[2]=v[2]/cno;
670       
671       vektorprodukt(c2,c1,k);
672
673       
674       x1=(startx+(x[0]*k[0]+x[1]*k[1]+x[2]*k[2])*mag);
675       y1=(starty-(y[0]*k[0]+y[1]*k[1]+y[2]*k[2])*mag);
676       if(   (x1>-2000.0)
677          && (x1<scrnWidth+2000.0)
678          && (y1>-2000.0)
679          && (y1<scrnHeight+2000.0))
680         {
681           kugeln[i].x1=(int)x1;
682           kugeln[i].y1=(int)y1;
683         }
684       else
685         {
686           kugeln[i].x1=0;
687           kugeln[i].y1=0;
688           kugeln[i].d=-20.0;
689         }
690     }
691 }
692
693 /*---------- event-handler ----------------*/
694 static void
695 event_handler(void)
696 {
697   while (XEventsQueued (dpy, QueuedAfterReading))
698     {
699       XEvent event;
700       
701       XNextEvent (dpy, &event);
702       switch (event.type)
703         {
704         case ConfigureNotify:
705           if (event.xconfigure.width != scrnWidth ||
706               event.xconfigure.height != scrnHeight)
707             {
708               XFreePixmap (dpy, buffer); 
709               scrnWidth = event.xconfigure.width;
710               scrnHeight = event.xconfigure.height;
711               buffer = XCreatePixmap (dpy, win, scrnWidth, scrnHeight,
712                                       xgwa.depth);
713               
714               startx=scrnWidth/2;
715               starty=scrnHeight/2;
716               scrnH2=startx;
717               scrnW2=starty;
718             }; break;
719         case KeyPress:
720           {
721             KeySym kpr=XKeycodeToKeysym(dpy,event.xkey.keycode,0);
722             if (kpr=='s') /* s */
723               vspeed=0.5;
724             if (kpr=='a')
725               vspeed=-0.3;
726             if (kpr=='q')
727               {
728                 speed=0;vspeed=0;
729               }
730             /*  printf("%i\n",event.xkey.keycode);*/
731             if (kpr=='z') mag*=1.02;
732             if (kpr=='x') mag/=1.02;
733           }
734         default:
735           break;
736         }
737     }
738   /*nap(40);-Ersatz*/ 
739   {
740     struct timeval timeout;
741     timeout.tv_sec=timewait/1000000;
742     timeout.tv_usec=timewait%1000000;
743     (void)select(0,0,0,0,&timeout);
744   }
745 }
746
747
748 /*-------------------------------------------------*/
749
750 char *progclass = "T3D";
751
752 char *defaults [] = {
753   ".background: black",
754   ".foreground: white",
755   "*move:       0.5",
756   "*wobble:     2.0",
757   "*cycle:      6.0",
758   "*mag:        1",
759   "*minutes:    False",
760   "*timewait:   40000",
761   "*fast:       50",
762   "*ccycle:     False",
763   "*hsvcycle:   0.0",
764   0
765 };
766
767 XrmOptionDescRec options [] = {
768   { "-move",            ".move",        XrmoptionSepArg, 0 },
769   { "-wobble",          ".wobble",      XrmoptionSepArg, 0 },
770   { "-cycle",           ".cycle",       XrmoptionSepArg, 0 },
771   { "-mag",             ".mag",         XrmoptionSepArg, 0 },
772   { "-minutes",         ".minutes",     XrmoptionSepArg, 0 },
773   { "-timewait",        ".timewait",    XrmoptionSepArg, 0 },
774   { "-fast",            ".fast",        XrmoptionSepArg, 0 },
775   { "-colcycle",        ".colcycle",    XrmoptionSepArg, 0 },
776   { "-hsvcycle",        ".hsvcycle",    XrmoptionSepArg, 0 },
777   { "-rgb",             ".rgb",         XrmoptionSepArg, 0 },
778   { "-hsv",             ".hsv",         XrmoptionSepArg, 0 },
779   { 0, 0, 0, 0 }
780 };
781
782
783 void
784 screenhack (Display *d, Window w)
785 {
786   Window junk_win,in_win;
787   
788   int px,py,junk,kb/*,wai*/;
789 /*  int act,act1,tc;*/
790   double vnorm;
791   /* double var=0.0; */
792   int color=0/*, dir=1*/;
793   
794   dpy = d;
795   win = w;
796   initialize();
797   
798   initColor(r,g,b);
799   init_3d();
800   zeit=(struct tm *)malloc(sizeof(struct tm));
801   init_kugel();
802   
803   startx=scrnWidth/2;
804   starty=scrnHeight/2;
805   scrnH2=startx;
806   scrnW2=starty;
807   vspeed=0;
808   
809   
810   vektorprodukt(x,y,v);
811   viewpoint(/*m,v*/);
812   
813   setink (BlackPixel (dpy, screen));
814   XFillRectangle (dpy, win, gc, 0, 0, scrnWidth, scrnHeight);
815   XQueryPointer (dpy, win, &junk_win, &junk_win, &junk, &junk,
816                  &px, &py, &kb);
817   
818   for (;;)
819     {   double dtime;
820         
821         /*--------------- Zeichenteil --------------*/
822
823         event_handler();
824         
825         vektorprodukt(x,y,v);
826         
827         vnorm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
828         v[0]=v[0]*norm/vnorm;
829         v[1]=v[1]*norm/vnorm;
830         v[2]=v[2]*norm/vnorm;
831         vnorm=sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]);
832         x[0]=x[0]*norm/vnorm;
833         x[1]=x[1]*norm/vnorm;
834         x[2]=x[2]*norm/vnorm;
835         vnorm=sqrt(y[0]*y[0]+y[1]*y[1]+y[2]*y[2]);
836         y[0]=y[0]*norm/vnorm;
837         y[1]=y[1]*norm/vnorm;
838         y[2]=y[2]*norm/vnorm;
839         
840         projektion();
841         t3d_sort (0,maxk-1);
842         
843         dtime=gettime();
844         
845         if(cycl)
846           {
847             color=(int)(64.0*(dtime/60-floor(dtime/60)))-32;
848             
849             if(color<0)
850               color=-color;
851             
852             setink(colors[color/3].pixel);
853           }
854         else
855           setink(BlackPixel (dpy, screen));
856         
857         XFillRectangle(dpy,buffer,gc,0,0,scrnWidth,scrnHeight);
858         
859         {
860           int i;
861           
862           manipulate(dtime);
863           
864           for (i=0;i<maxk;i++)
865             {
866               if (kugeln[i].d>0.0)
867                 fill_kugel(i,buffer,1);
868             }
869         }
870
871         XSync(dpy,0);
872         
873         /* manipulate(gettime());
874            var+=PI/500;
875            if (var>=TWOPI) var=PI/500; */
876         
877         /*event_handler();*/
878         
879         if(hsvcycl!=0.0)
880           {
881             dtime=hsvcycl*dtime/10.0+hue/360.0;
882             dtime=360*(dtime-floor(dtime));
883             
884             hsv2rgb(dtime,sat,val,&r,&g,&b);
885             changeColor(r,g,b);
886           }
887
888         XCopyArea (dpy, buffer, win, gc, 0, 0, scrnWidth, scrnHeight, 0, 0);
889         
890         
891         /*-------------------------------------------------*/
892         XSync(dpy,0);
893         
894         event_handler();
895         
896         (void)(XQueryPointer (dpy, win, &junk_win, &in_win, &junk, &junk,
897                               &px, &py, &kb));
898         
899         if ((px>0)&&(px<scrnWidth)&&(py>0)&&(py<scrnHeight) )           
900           {
901             if ((px !=startx)&&(kb&Button2Mask))
902               {
903                 /* printf("y=(%f,%f,%f)",y[0],y[1],y[2]);*/
904                 turn(y,x,((double)(px-startx))/(8000*mag));
905                 /* printf("->(%f,%f,%f)\n",y[0],y[1],y[2]);*/
906               }
907             if ((py !=starty)&&(kb&Button2Mask)) 
908               {
909                 /* printf("x=(%f,%f,%f)",x[0],x[1],x[2]);*/
910                 turn(x,y,((double)(py-starty))/(-8000*mag));
911                 /* printf("->(%f,%f,%f)\n",x[0],x[1],x[2]);*/
912               }
913             if ((kb&Button1Mask)) 
914               {
915                 if (vturn==0.0) vturn=.005; else if (vturn<2)  vturn+=.01;
916                 turn(x,v,.002*vturn);
917                 turn(y,v,.002*vturn); 
918               }
919             if ((kb&Button3Mask)) 
920               {
921                 if (vturn==0.0) vturn=.005; else if (vturn<2) vturn+=.01;
922                 turn(x,v,-.002*vturn);
923                 turn(y,v,-.002*vturn);
924               }
925           }
926         if (!(kb&Button1Mask)&&!(kb&Button3Mask)) 
927           vturn=0;
928         
929         speed=speed+speed*vspeed;
930         if ((speed<0.0000001) &&(vspeed>0.000001)) speed=0.000001;
931         vspeed=.1*vspeed;
932         if (speed>0.01) speed=.01;
933         a[0]=a[0]+speed*v[0];
934         a[1]=a[1]+speed*v[1];
935         a[2]=a[2]+speed*v[2];
936       }
937 }