1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* t3d --- Flying Balls Clock Demo */
3
4 #if 0
5 static const char sccsid[] = "@(#)t3d.c 5.0 2000/11/01 xlockmore";
6
7 #endif
8
9 /*-
10 * Copyright (c) 1998 Bernd Paysan , paysan@informatik.tu-muenchen.de.
11 *
12 * Copy, modify, and distribute T3D either under GPL version 2 or newer,
13 * or under the standard MIT/X license notice.
14 *
15 * This file is provided AS IS with no warranties of any kind. The author
16 * shall have no liability with respect to the infringement of copyrights,
17 * trade secrets or any patents by this file or any part thereof. In no
18 * event will the author be liable for any lost revenue or profits or
19 * other special, indirect and consequential damages.
20 *
21 * partly based on flying balls demo by Georg Acher,
22 * acher@informatik.tu-muenchen.de
23 * (developed on HP9000/720 (55 MIPS,20 MFLOPS) )
24 *
25 * Todo for xlock:
26 * -Set default options right and make it more "random"
27 * -Add original colour scheme
28 * -Get trackmouse is working
29 * -Add some more options which were handled in the original by the XEvents.
30 * -Get working better in password window.
31 *
32 * Revision History:
33 * 01-Nov-2000: Allocation checks
34 * 26-Jan-2000: joukj AT hrem.nano.tudelft.nl (Jouk Jansen) : adapted for
35 * xlockmore. Modified colour-schemes.
36 * 04-Jan-1999: jwz AT jwz.org -- adapted to xscreensaver framework,
37 * to take advantage of the command-line options
38 * provided by screenhack.c.
39 */
40 #ifdef WIN32
41 #include <sys/time.h>
42 #else
43 #include <time.h>
44 #endif /* WIN32 */
45
46 #define FASTDRAW
47 #define FASTCOPY
48 #undef USE_POLYGON
49
50 #ifdef STANDALONE
51 #define MODE_t3d
52 #define DEFAULTS "*delay: 10000 \n" \
53 "*cycles: 60000 \n" \
54 "*ncolors: 200 \n" \
55 "*mouse: False \n" \
56
57 # define free_t3d 0
58 # define reshape_t3d 0
59 # define t3d_handle_event 0
60 #define UNIFORM_COLORS
61 #include "xlockmore.h" /* in xscreensaver distribution */
62
63 #else /* STANDALONE */
64 #include "xlock.h" /* in xlockmore distribution */
65 #include "color.h"
66 #endif /* STANDALONE */
67
68 #include <time.h>
69 #ifdef TIME_WITH_SYS_TIME /* for sco */
70 #include <sys/time.h>
71 #endif
72
73 #ifdef MODE_t3d
74
75 #define DEF_TRACKMOUSE "False"
76 #define DEF_MOVE "0.5"
77 #define DEF_WOBBLE "2.0"
78 #define DEF_MAG "10.0"
79 #define DEF_FAST "50"
80 #define DEF_MINUTES "False"
81 #define DEF_CYCLE "True"
82
83 #define PI M_PI
84 #define TWOPI 2*M_PI
85
86 #define MAXFAST 100
87
88 #define norm 20.0
89
90 #ifdef FASTCOPY
91 #define sum1ton(a) (((a)*(a)+1)/2)
92 #define fastcw sum1ton(fastch)
93 #endif
94
95 #undef ABS
96 #define ABS(x) ((x)<0.0 ? -(x) : (x))
97
98 /* Anzahl der Kugeln */
99 #define kmax ((t3dp->minutes?60:24))
100
101 /* Werte in der Sinus-Tabelle */
102 #define sines 52
103
104 #define setink(inkcolor) XSetForeground(display,t3dp->gc,inkcolor)
105
106 static Bool trackmouse , minutes , cycle_p;
107
108 static float move, wobble , mag;
109
110 static int fastch;
111
112 static XrmOptionDescRec opts[] =
113 {
114 {(char *) "-cycle", (char *) ".t3d.cycle", XrmoptionNoArg, (caddr_t) "on"},
115 {(char *) "+cycle", (char *) ".t3d.cycle", XrmoptionNoArg, (caddr_t) "off"},
116 {(char *) "-move", (char *) ".t3d.move", XrmoptionSepArg, (caddr_t) NULL},
117 {(char *) "-wobble", (char *) ".t3d.wobble", XrmoptionSepArg, (caddr_t) NULL},
118 {(char *) "-mag", (char *) ".t3d.mag", XrmoptionSepArg, (caddr_t) NULL},
119 {(char *) "-fast", (char *) ".t3d.fast", XrmoptionSepArg, (caddr_t) NULL},
120 {(char *) "-minutes", (char *) ".t3d.minutes", XrmoptionNoArg, (caddr_t) "on"},
121 {(char *) "+minutes", (char *) ".t3d.minutes", XrmoptionNoArg, (caddr_t) "off"},
122 {(char *) "-trackmouse", (char *) ".t3d.trackmouse", XrmoptionNoArg, (caddr_t) "on"},
123 {(char *) "+trackmouse", (char *) ".t3d.trackmouse", XrmoptionNoArg, (caddr_t) "off"}
124 };
125
126 static argtype vars[] =
127 {
128 {(void *) & cycle_p, (char *) "cycle", (char *) "Cycle", (char *) DEF_CYCLE, t_Bool},
129 {(void *) & move, (char *) "move", (char *) "Move", (char *) DEF_MOVE, t_Float},
130 {(void *) & wobble, (char *) "wobble", (char *) "Wobble", (char *) DEF_WOBBLE, t_Float},
131 {(void *) & mag, (char *) "mag", (char *) "Magnification", (char *) DEF_MAG, t_Float},
132 {(void *) & fastch, (char *) "fast", (char *) "Fast", (char *) DEF_FAST, t_Int},
133 {(void *) & minutes, (char *) "minutes", (char *) "Minutes", (char *) DEF_MINUTES, t_Bool},
134 {(void *) & trackmouse, (char *) "trackmouse", (char *) "TrackMouse", (char *) DEF_TRACKMOUSE, t_Bool}
135 };
136
137 static OptionStruct desc[] =
138 {
139 {(char *) "-/+cycle", (char *) "turn on/off colour cycling"},
140 {(char *) "-move num", (char *) "Move speed"},
141 {(char *) "-wobble num", (char *) "Wobble speed"},
142 {(char *) "-mag num", (char *) "Magnification factor"},
143 {(char *) "-fast num", (char *) "Fast"},
144 {(char *) "-/+minutes", (char *) "turn on/off minutes"},
145 {(char *) "-/+trackmouse", (char *) "turn on/off the tracking of the mouse"}
146 };
147
148 ENTRYPOINT ModeSpecOpt t3d_opts =
149 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
150
151
152 #ifdef USE_MODULES
153 ModStruct t3d_description =
154 {"t3d", "init_t3d", "draw_t3d", "release_t3d",
155 "refresh_t3d", "init_t3d", (char *) NULL, &t3d_opts,
156 250000, 1000, 60000 , 1, 64, 1.0, "",
157 "Flying Balls Clock Demo", 0, NULL};
158
159 #endif
160
161 typedef struct {
162 double x,y,z,r,d,r1;
163 int x1,y1;
164 } kugeldat;
165
166 typedef struct {
167 Cursor cursor;
168 double cycles , movef , wobber , a[3] , x[3] , y[3] , zoom , speed , vspeed;
169 double sinus[sines] , cosinus[sines] , v[3] , am[3] , zaehler , vnorm;
170 double vturn;
171 int fastch , minutes , maxk;
172 GC gc;
173 Pixmap buffer;
174 #ifdef FASTCOPY
175 GC orgc , andgc;
176 Pixmap fastcircles , fastmask;
177 #else
178 XImage* fastcircles[maxfast] , fastmask[maxfast];
179 #endif
180 Colormap cmap;
181 XColor *colors;
182 int width, height, depth;
183 int ncolors , fastdraw , scrnW2, scrnH2, startx , starty , px , py;
184 Bool cycle_p, mono_p, no_colors;
185 unsigned long blackpixel, whitepixel, fg, bg;
186 int direction;
187 struct tm *zeit;
188 kugeldat kugeln[100];
189 int color_offset;
190 } t3dstruct;
191
192 static t3dstruct *t3ds = (t3dstruct *) NULL;
193
194 static void
t3d_zeiger(ModeInfo * mi,double dist,double rad,double z,double sec,int * q)195 t3d_zeiger( ModeInfo* mi , double dist,double rad, double z, double sec,
196 int *q)
197 /* Zeiger zeichnen */
198 {
199 int i,n;
200 double gratio=sqrt(2.0/(1.0+sqrt(5.0)));
201 t3dstruct *t3dp;
202
203 t3dp = &t3ds[MI_SCREEN(mi)];
204
205 n = *q;
206
207 for(i=0;i<3;i++)
208 {
209 t3dp->kugeln[n].x=dist*cos(sec);
210 t3dp->kugeln[n].y=-dist*sin(sec);
211 t3dp->kugeln[n].z=z;
212 t3dp->kugeln[n].r=rad;
213 n++;
214
215 dist += rad;
216 rad = rad*gratio;
217 }
218 *q = n;
219 }
220
221 static void
t3d_manipulate(ModeInfo * mi,double k)222 t3d_manipulate( ModeInfo* mi , double k)
223 /*-----------------------------------------------------------------*
224 * Uhr zeichnen *
225 *-----------------------------------------------------------------*/
226 {
227 double i,l,/*xs,*/ys,zs,mod;
228 double /*persec,*/sec,min,hour;
229 int n;
230 t3dstruct *t3dp;
231
232 t3dp = &t3ds[MI_SCREEN(mi)];
233
234 sec=TWOPI*modf(k/60,&mod);
235 min=TWOPI*modf(k/3600,&mod);
236 hour=TWOPI*modf(k/43200,&mod);
237
238 l=TWOPI*modf(k/300,&mod);
239 i=0.0;
240 for (n=0;n<kmax;n++)
241 {
242
243 t3dp->kugeln[n].x=4.0*sin(i);
244 t3dp->kugeln[n].y=4.0*cos(i);
245 t3dp->kugeln[n].z=t3dp->wobber* /* (sin(floor(2+2*l/(PI))*i)*sin(2*l)); */
246 cos((i-sec)*floor(2+5*l/(PI)))*sin(5*l);
247 if(t3dp->minutes)
248 {
249 t3dp->kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */
250 ((n % 5!=0) ? 0.3 : 0.6)*
251 ((n % 15 ==0) ? 1.25 : .75);
252 }
253 else
254 {
255 t3dp->kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */
256 ((n & 1) ? 0.5 : 1.0)*
257 ((n % 6==0) ? 1.25 : .75);
258 }
259 i+=TWOPI/kmax;
260 }
261
262 t3dp->kugeln[n].x=0.0;
263 t3dp->kugeln[n].y=0.0;
264 t3dp->kugeln[n].z=0.0;
265 t3dp->kugeln[n].r=2.0+cos(TWOPI*modf(k,&mod))/2;
266 n++;
267
268 t3d_zeiger( mi , 2.0,0.75,-2.0,sec,&n);
269 t3d_zeiger( mi , 1.0,1.0,-1.5,min,&n);
270 t3d_zeiger( mi , 0.0,1.5,-1.0,hour,&n);
271
272 for(n=0;n<t3dp->maxk;n++)
273 {
274 double cycle = (double) MI_CYCLES( mi );
275
276 ys=t3dp->kugeln[n].y*cos(t3dp->movef*sin(cycle*sec))+
277 t3dp->kugeln[n].z*sin(t3dp->movef*sin(cycle*sec));
278 zs=-t3dp->kugeln[n].y*sin(t3dp->movef*sin(cycle*sec))+
279 t3dp->kugeln[n].z*cos(t3dp->movef*sin(cycle*sec));
280 t3dp->kugeln[n].y=ys;
281 t3dp->kugeln[n].z=zs;
282 }
283 }
284
285 static double
t3d_gettime(void)286 t3d_gettime (void)
287 {
288 struct timeval time1;
289 struct tm *zeit;
290 time_t lt;
291
292 #if HAVE_GETTIMEOFDAY
293 GETTIMEOFDAY(&time1);
294 lt = time1.tv_sec; /* avoid type cast lossage */
295 #else
296 lt = NULL;
297 time1.tv_sec = 0;
298 #endif
299 zeit = localtime((const time_t *) <);
300
301 return (zeit->tm_sec+60*(zeit->tm_min+60*(zeit->tm_hour))
302 + time1.tv_usec*1.0E-6);
303 }
304
305
306 static void
t3d__sort(ModeInfo * mi,int l,int r)307 t3d__sort( ModeInfo* mi , int l, int r)
308 {
309 int i,j;
310 kugeldat ex;
311 double x;
312 t3dstruct *t3dp;
313
314 t3dp = &t3ds[MI_SCREEN(mi)];
315
316 i=l;j=r;
317 x=t3dp->kugeln[(l+r)/2].d;
318 for (;;) {
319 while(t3dp->kugeln[i].d>x) i++;
320 while(x>t3dp->kugeln[j].d) j--;
321 if (i<=j)
322 {
323 ex=t3dp->kugeln[i];
324 t3dp->kugeln[i]=t3dp->kugeln[j];
325 t3dp->kugeln[j]=ex;
326 i++;j--;
327 }
328 if (i>j) break;
329 }
330 if (l<j) t3d__sort( mi , l,j);
331 if (i<r) t3d__sort ( mi , i,r);
332 }
333
334 static void
t3d_vektorprodukt(double feld1[],double feld2[],double feld3[])335 t3d_vektorprodukt(double feld1[], double feld2[], double feld3[])
336 {
337 feld3[0]=feld1[1]*feld2[2]-feld1[2]*feld2[1];
338 feld3[1]=feld1[2]*feld2[0]-feld1[0]*feld2[2];
339 feld3[2]=feld1[0]*feld2[1]-feld1[1]*feld2[0];
340 }
341
342 static void
t3d_turn(double feld1[],double feld2[],double winkel)343 t3d_turn(double feld1[], double feld2[], double winkel)
344 {
345 double temp[3];
346 double s,ca,sa,sx1,sx2,sx3;
347
348 t3d_vektorprodukt(feld1,feld2,temp);
349
350 s=feld1[0]*feld2[0]+feld1[1]*feld2[1]+feld1[2]*feld2[2];
351
352 sx1=s*feld2[0];
353 sx2=s*feld2[1];
354 sx3=s*feld2[2];
355 sa=sin(winkel);ca=cos(winkel);
356 feld1[0]=ca*(feld1[0]-sx1)+sa*temp[0]+sx1;
357 feld1[1]=ca*(feld1[1]-sx2)+sa*temp[1]+sx2;
358 feld1[2]=ca*(feld1[2]-sx3)+sa*temp[2]+sx3;
359 }
360
361 static void
t3d_projektion(ModeInfo * mi)362 t3d_projektion( ModeInfo* mi)
363 {
364 double c1[3],c2[3],k[3],x_1,y_1;
365 double cno,cnorm/*,magnit*/;
366 int i;
367 t3dstruct *t3dp;
368
369 t3dp = &t3ds[MI_SCREEN(mi)];
370
371 for (i=0;i<t3dp->maxk;i++)
372 {
373 c1[0]=t3dp->kugeln[i].x-t3dp->a[0];
374 c1[1]=t3dp->kugeln[i].y-t3dp->a[1];
375 c1[2]=t3dp->kugeln[i].z-t3dp->a[2];
376 cnorm=sqrt(c1[0]*c1[0]+c1[1]*c1[1]+c1[2]*c1[2]);
377
378 c2[0]=c1[0];
379 c2[1]=c1[1];
380 c2[2]=c1[2];
381
382 cno=c2[0]*t3dp->v[0]+c2[1]*t3dp->v[1]+c2[2]*t3dp->v[2];
383 t3dp->kugeln[i].d=cnorm;
384 if (cno<0) t3dp->kugeln[i].d=-20.0;
385
386
387 t3dp->kugeln[i].r1=(mag*t3dp->zoom*t3dp->kugeln[i].r/cnorm);
388
389 c2[0]=t3dp->v[0]/cno;
390 c2[1]=t3dp->v[1]/cno;
391 c2[2]=t3dp->v[2]/cno;
392
393 t3d_vektorprodukt(c2,c1,k);
394
395
396 x_1=(t3dp->startx+(t3dp->x[0]*k[0]+t3dp->x[1]*k[1]+t3dp->x[2]*k[2])*mag);
397 y_1=(t3dp->starty-(t3dp->y[0]*k[0]+t3dp->y[1]*k[1]+t3dp->y[2]*k[2])*mag);
398 if( (x_1>-2000.0)
399 && (x_1<t3dp->width+2000.0)
400 && (y_1>-2000.0)
401 && (y_1<t3dp->height+2000.0))
402 {
403 t3dp->kugeln[i].x1=(int)x_1;
404 t3dp->kugeln[i].y1=(int)y_1;
405 }
406 else
407 {
408 t3dp->kugeln[i].x1=0;
409 t3dp->kugeln[i].y1=0;
410 t3dp->kugeln[i].d=-20.0;
411 }
412 }
413 }
414
415
416 static void
t3d_viewpoint(ModeInfo * mi)417 t3d_viewpoint( ModeInfo* mi)
418 /* 1: Blickrichtung v;3:Ebenenmittelpunkt m
419 double feld1[],feld3[]; */
420 {
421 t3dstruct *t3dp;
422
423 t3dp = &t3ds[MI_SCREEN(mi)];
424
425 t3dp->am[0]=-t3dp->zoom*t3dp->v[0];
426 t3dp->am[1]=-t3dp->zoom*t3dp->v[1];
427 t3dp->am[2]=-t3dp->zoom*t3dp->v[2];
428
429 t3dp->zaehler=norm*norm* t3dp->zoom;
430 }
431
432 static void
t3d_fill_kugel(int i,Pixmap buf,int setcol,ModeInfo * mi)433 t3d_fill_kugel(int i, Pixmap buf, int setcol , ModeInfo* mi )
434 {
435 t3dstruct *t3dp;
436 Display *display = MI_DISPLAY(mi);
437 double ra;
438 int m,inr=3,d;
439 #ifdef USE_POLYGON
440 int inc = 1;
441 #endif
442
443 t3dp = &t3ds[MI_SCREEN(mi)];
444
445 d=(int)((ABS(t3dp->kugeln[i].r1)*2));
446 if (d==0) d=1;
447
448 # ifdef FASTDRAW
449 if(t3dp->fastdraw && d<t3dp->fastch)
450 {
451 # ifdef FASTCOPY
452 XCopyArea(display, t3dp->fastmask, buf, t3dp->andgc, sum1ton(d)-(d+1)/2,
453 1,d,d, (int)(t3dp->kugeln[i].x1)-d/2,
454 (int)(t3dp->kugeln[i].y1)-d/2);
455 XCopyArea(display, t3dp->fastcircles, buf, t3dp->orgc,
456 sum1ton(d)-(d+1)/2, 1,d,d, (int)(t3dp->kugeln[i].x1)-d/2,
457 (int)(t3dp->kugeln[i].y1)-d/2);
458 #else
459 XPutImage(display, buf, t3dp->andgc, t3dp->fastmask[d-1], 0, 0,
460 (int)(t3dp->kugeln[i].x1)-d/2, (int)(t3dp->kugeln[i].y1)-d/2,
461 d, d);
462 XPutImage(display, buf, t3dp->orgc, t3dp->fastcircles[d-1], 0, 0,
463 (int)(t3dp->kugeln[i].x1)-d/2, (int)(t3dp->kugeln[i].y1)-d/2,
464 d, d);
465 # endif
466 }
467 else
468 #endif
469 {
470 if(ABS(t3dp->kugeln[i].r1)<6.0) inr=9;
471
472 for (m=0;m<=28;m+=inr)
473 {
474 ra=t3dp->kugeln[i].r1*sqrt(1-m*m/(28.0*28.0));
475 #ifdef USE_POLYGON
476 if(-ra< 3.0) inc=14;
477 else if(-ra< 6.0) inc=8;
478 else if(-ra<20.0) inc=4;
479 else if(-ra<40.0) inc=2;
480 #endif
481 if(setcol)
482 {
483 if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
484 setink(t3dp->colors[m].pixel);
485 } else if (MI_NPIXELS(mi) <= 2) {
486 if ((m + t3dp->color_offset) % 2)
487 setink(MI_WHITE_PIXEL(mi));
488 else
489 setink(MI_BLACK_PIXEL(mi));
490 } else {
491 setink(MI_PIXEL(mi, ((m + t3dp->color_offset) % 29) * MI_NPIXELS(mi) / 29));
492 }
493 }
494
495 #ifdef USE_POLYGON
496 {
497 int n, nr;
498 for (n=0,nr=0;n<=sines-1;n+=inc,nr++)
499 {
500 track[nr].x=t3dp->kugeln[i].x1+(int)(ra*t3dp->sinus[n])+
501 (t3dp->kugeln[i].r1-ra)/2;
502 track[nr].y=t3dp->kugeln[i].y1+(int)(ra*t3dp->cosinus[n])+
503 (t3dp->kugeln[i].r1-ra)/2;
504 }
505 XFillPolygon(display,buf,t3dp->gc,track,nr,Convex,CoordModeOrigin);
506 }
507 #else /* Use XFillArc */
508 XFillArc(display, buf, t3dp->gc,
509 (int)(t3dp->kugeln[i].x1+(t3dp->kugeln[i].r1+ra)/2),
510 (int)(t3dp->kugeln[i].y1+(t3dp->kugeln[i].r1+ra)/2),
511 (int)-(2*ra+1), (int)-(2*ra+1), 0, 360*64);
512 #endif
513 }
514 }
515 }
516
517
518 static void
t3d_init_kugel(ModeInfo * mi)519 t3d_init_kugel( ModeInfo* mi )
520 {
521 t3dstruct *t3dp;
522
523 #ifdef FASTDRAW
524 Display *display = MI_DISPLAY(mi);
525 int i;
526
527 t3dp = &t3ds[MI_SCREEN(mi)];
528
529 for(i=0; i<t3dp->fastch; i++)
530 {
531 # ifdef FASTCOPY
532 t3dp->kugeln[i].r1=-((double) i)/2 -1;
533 t3dp->kugeln[i].x1=sum1ton(i);
534 t3dp->kugeln[i].y1=i/2 +1;
535
536 t3d_fill_kugel(i,t3dp->fastcircles,1 , mi );
537 /* setink((1<<MIN(24,t3dp->depth))-1);*/
538 setink(MI_BLACK_PIXEL(mi));
539 t3d_fill_kugel(i,t3dp->fastmask,0 , mi );
540 # else
541 t3dp->kugeln[i].r1=-((double) i)/2 -1;
542 t3dp->kugeln[i].x1=t3dp->kugeln[i].y1=i/2 +1;
543
544 t3d_fill_kugel(i,t3dp->buffer,1 , mi );
545 t3dp->fastcircles[i]=XGetImage(display,t3dp->buffer,0,0,i+2,i+2,
546 (1<<t3dp->depth)-1, ZPixmap);
547 /* setink((1<<MIN(24,t3dp->depth))-1); */
548 setink(MI_WHITE_PIXEL(mi));
549 t3d_fill_kugel(i,t3dp->buffer,0 , mi );
550 t3dp->fastmask[i]=XGetImage(display,t3dp->buffer,0,0,i+2,i+2,
551 (1<<t3dp->depth)-1,ZPixmap);
552 setink(MI_BLACK_PIXEL(mi));
553 XFillRectangle (display, t3dp->buffer , t3dp->gc, 0, 0,
554 t3dp->width, t3dp->height);
555 # endif
556 }
557 t3dp->fastdraw=1;
558 #endif
559 }
560
561 static void
t3d_init_3d(ModeInfo * mi)562 t3d_init_3d( ModeInfo* mi )
563 {
564 t3dstruct *t3dp;
565 double i;
566 int n=0;
567
568 t3dp = &t3ds[MI_SCREEN(mi)];
569
570 t3dp->a[0]=0.0;
571 t3dp->a[1]=0.0;
572 t3dp->a[2]=-10.0;
573
574 t3dp->x[0]=10.0;
575 t3dp->x[1]=0.0;
576 t3dp->x[2]=0.0;
577
578 t3dp->y[0]=0.0;
579 t3dp->y[1]=10.0;
580 t3dp->y[2]=0.0;
581
582 t3dp->zoom=-10.0;
583 t3dp->speed=.0;
584
585 for (i=0.0;n<sines;i+=TWOPI/sines,n++)
586 {
587 t3dp->sinus[n]=sin(i);
588 t3dp->cosinus[n]=cos(i);
589 }
590
591 }
592
593 static void
free_t3d_screen(ModeInfo * mi,t3dstruct * t3dp)594 free_t3d_screen(ModeInfo *mi, t3dstruct *t3dp)
595 {
596 Display *display = MI_DISPLAY(mi);
597 if (t3dp == NULL) {
598 return;
599 }
600 if (t3dp->cursor != None) {
601 XFreeCursor(display, t3dp->cursor);
602 t3dp->cursor = None;
603 }
604 if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
605 MI_WHITE_PIXEL(mi) = t3dp->whitepixel;
606 MI_BLACK_PIXEL(mi) = t3dp->blackpixel;
607 #ifndef STANDALONE
608 MI_FG_PIXEL(mi) = t3dp->fg;
609 MI_BG_PIXEL(mi) = t3dp->bg;
610 #endif
611 if (t3dp->colors != NULL) {
612 if (t3dp->ncolors && !t3dp->no_colors)
613 free_colors(
614 #ifdef STANDALONE
615 MI_SCREENPTR(mi),
616 #else
617 display,
618 #endif
619 t3dp->cmap, t3dp->colors, t3dp->ncolors);
620 free(t3dp->colors);
621 t3dp->colors = (XColor *) NULL;
622 }
623 if (t3dp->cmap != None) {
624 XFreeColormap(display, t3dp->cmap);
625 t3dp->cmap = None;
626 }
627 }
628 if (t3dp->buffer != None) {
629 XFreePixmap(display, t3dp->buffer);
630 t3dp->buffer = None;
631 }
632 if (t3dp->gc != None) {
633 XFreeGC(display, t3dp->gc);
634 t3dp->gc = None;
635 }
636 #ifdef FASTCOPY
637 if (t3dp->orgc != None) {
638 XFreeGC(display, t3dp->orgc);
639 t3dp->orgc = None;
640 }
641 if (t3dp->andgc != None) {
642 XFreeGC(display, t3dp->andgc);
643 t3dp->andgc = None;
644 }
645 if (t3dp->fastcircles != None) {
646 XFreePixmap(display, t3dp->fastcircles);
647 t3dp->fastcircles = None;
648 }
649 if (t3dp->fastmask != None) {
650 XFreePixmap(display, t3dp->fastmask);
651 t3dp->fastmask = None;
652 }
653 #endif
654 if (t3dp->zeit != NULL) {
655 free(t3dp->zeit);
656 t3dp->zeit = (struct tm *) NULL;
657 }
658 t3dp = NULL;
659 }
660
661 static Bool
t3d_initialize(ModeInfo * mi)662 t3d_initialize( ModeInfo* mi )
663 {
664 Display *display = MI_DISPLAY(mi);
665 Window window = MI_WINDOW(mi);
666 t3dstruct *t3dp;
667 XGCValues xgcv;
668
669 t3dp = &t3ds[MI_SCREEN(mi)];
670
671 t3dp->cycles = MI_CYCLES( mi ) / 6000.0;
672 if ( t3dp->cycles <= 1.0 )
673 t3dp->cycles = 10.0;
674
675 t3dp->movef = (double) move;
676 t3dp->wobber = (double) wobble;
677 t3dp->fastch = (int) (fastch * mag);
678 if ( t3dp->fastch > MAXFAST )
679 t3dp->fastch = MAXFAST;
680
681 if ( minutes )
682 {
683 t3dp->minutes = 1;
684 t3dp->maxk = 70;
685 }
686 else
687 {
688 t3dp->minutes = 0;
689 t3dp->maxk = 34;
690 }
691 xgcv.foreground = MI_WHITE_PIXEL(mi);
692 if ((t3dp->gc = XCreateGC (display, window, GCForeground, &xgcv)) == None) {
693 free_t3d_screen(mi, t3dp);
694 return False;
695 }
696 #ifdef FASTDRAW
697 xgcv.function = GXor;
698 if ((t3dp->orgc = XCreateGC (display, window, GCFunction | GCForeground,
699 &xgcv)) == None) {
700 free_t3d_screen(mi, t3dp);
701 return False;
702 }
703 xgcv.function = GXandInverted;
704 if ((t3dp->andgc = XCreateGC (display, window, GCFunction | GCForeground,
705 &xgcv)) == None) {
706 free_t3d_screen(mi, t3dp);
707 return False;
708 }
709 #endif
710 if (MI_IS_VERBOSE(mi))
711 {
712 (void) printf("Time 3D drawing ");
713 #ifdef FASTDRAW
714 # ifdef FASTCOPY
715 (void) puts("fast by Pixmap copy");
716 # else
717 (void) puts("fast by XImage copy");
718 # endif
719 #else
720 (void) puts("slow");
721 #endif
722 }
723
724 #ifdef FASTCOPY
725 if (((t3dp->fastcircles = XCreatePixmap (display, window,
726 fastcw, t3dp->fastch+1, t3dp->depth)) == None) ||
727 ((t3dp->fastmask = XCreatePixmap (display, window,
728 fastcw, t3dp->fastch+1, t3dp->depth)) == None)) {
729 free_t3d_screen(mi, t3dp);
730 return False;
731 }
732 #endif
733
734 setink(MI_BLACK_PIXEL(mi));
735 XFillRectangle (display, t3dp->buffer , t3dp->gc, 0, 0, t3dp->width,
736 t3dp->height);
737
738 #ifdef FASTCOPY
739 setink(MI_BLACK_PIXEL(mi));
740 XFillRectangle (display, t3dp->fastcircles, t3dp->gc, 0, 0, fastcw,
741 t3dp->fastch+1);
742 XFillRectangle (display, t3dp->fastmask , t3dp->gc, 0, 0, fastcw,
743 t3dp->fastch+1);
744 #endif
745
746 if (MI_IS_VERBOSE(mi))
747 {
748 (void) printf("move\t%.2f\nwobber\t%.2f\nmag\t%.2f\n",
749 t3dp->movef, t3dp->wobber, mag );
750 (void) printf("fast\t%i\nmarks\t%i\n", t3dp->fastch, t3dp->maxk);
751 }
752 return True;
753 }
754
755 #ifndef STANDALONE
756 extern char *background;
757 extern char *foreground;
758 #endif
759
760 ENTRYPOINT void
init_t3d(ModeInfo * mi)761 init_t3d(ModeInfo * mi)
762 {
763 Display *display = MI_DISPLAY(mi);
764 Window window = MI_WINDOW(mi);
765 t3dstruct *t3dp;
766
767 MI_INIT(mi, t3ds);
768 t3dp = &t3ds[MI_SCREEN(mi)];
769
770 if (trackmouse && !t3dp->cursor) { /* Create an invisible cursor */
771 Pixmap bit;
772 XColor black;
773
774 black.red = 0;
775 black.green = 0;
776 black.blue = 0;
777 black.flags = DoRed | DoGreen | DoBlue;
778 if ((bit = XCreatePixmapFromBitmapData(display, window,
779 (char *) "\000", 1, 1, MI_BLACK_PIXEL(mi),
780 MI_BLACK_PIXEL(mi), 1)) == None) {
781 free_t3d_screen(mi, t3dp);
782 return;
783 }
784 if ((t3dp->cursor = XCreatePixmapCursor(display, bit, bit,
785 &black, &black, 0, 0)) == None) {
786 XFreePixmap(display, bit);
787 free_t3d_screen(mi, t3dp);
788 return;
789 }
790 XFreePixmap(display, bit);
791 }
792 XDefineCursor(display, window, t3dp->cursor);
793
794 t3dp->width = MI_WIDTH(mi);
795 t3dp->height = MI_HEIGHT(mi);
796 t3dp->depth = MI_DEPTH(mi);
797 if (t3dp->buffer != None) {
798 XFreePixmap(display, t3dp->buffer);
799 t3dp->buffer = None;
800 }
801 if ((t3dp->buffer = XCreatePixmap (display, window,
802 t3dp->width, t3dp->height, t3dp->depth)) == None) {
803 free_t3d_screen(mi, t3dp);
804 return;
805 }
806
807 /* Initialization */
808 if (t3dp->gc == None) {
809 if (!t3d_initialize(mi))
810 return;
811
812 if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2)
813 {
814 XColor color;
815
816 #ifndef STANDALONE
817 t3dp->fg = MI_FG_PIXEL(mi);
818 t3dp->bg = MI_BG_PIXEL(mi);
819 #endif
820 t3dp->blackpixel = MI_BLACK_PIXEL(mi);
821 t3dp->whitepixel = MI_WHITE_PIXEL(mi);
822 if ((t3dp->cmap = XCreateColormap(display, window, MI_VISUAL(mi),
823 AllocNone)) == None) {
824 free_t3d_screen(mi, t3dp);
825 return;
826 }
827 XSetWindowColormap(display, window, t3dp->cmap);
828 (void) XParseColor(display, t3dp->cmap, "black", &color);
829 (void) XAllocColor(display, t3dp->cmap, &color);
830 MI_BLACK_PIXEL(mi) = color.pixel;
831 (void) XParseColor(display, t3dp->cmap, "white", &color);
832 (void) XAllocColor(display, t3dp->cmap, &color);
833 MI_WHITE_PIXEL(mi) = color.pixel;
834 #ifndef STANDALONE
835 (void) XParseColor(display, t3dp->cmap, background, &color);
836 (void) XAllocColor(display, t3dp->cmap, &color);
837 MI_BG_PIXEL(mi) = color.pixel;
838 (void) XParseColor(display, t3dp->cmap, foreground, &color);
839 (void) XAllocColor(display, t3dp->cmap, &color);
840 MI_FG_PIXEL(mi) = color.pixel;
841 #endif
842 t3dp->colors = (XColor *) NULL;
843 t3dp->ncolors = 0;
844 }
845 }
846 t3dp->color_offset = NRAND(29);
847
848 /*Set up t2d data */
849 t3dp->direction = (LRAND() & 1) ? 1 : -1;
850 t3dp->fastdraw = 0;
851 t3dp->vturn = 0.0;
852
853 if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
854 #ifdef STANDALONE
855 Screen *screen = MI_SCREENPTR(mi);
856 #endif
857 /* Set up colour map */
858 if (t3dp->colors != NULL) {
859 if (t3dp->ncolors && !t3dp->no_colors)
860 free_colors(
861 #ifdef STANDALONE
862 screen,
863 #else
864 display,
865 #endif
866 t3dp->cmap, t3dp->colors, t3dp->ncolors);
867 free(t3dp->colors);
868 t3dp->colors = (XColor *) NULL;
869 }
870 t3dp->ncolors = MI_NCOLORS(mi);
871 if (t3dp->ncolors < 2)
872 t3dp->ncolors = 2;
873 if (t3dp->ncolors <= 2)
874 t3dp->mono_p = True;
875 else
876 t3dp->mono_p = False;
877
878 if (t3dp->mono_p)
879 t3dp->colors = (XColor *) NULL;
880 else
881 if ((t3dp->colors = (XColor *) malloc(sizeof (*t3dp->colors) *
882 (t3dp->ncolors + 1))) == NULL) {
883 free_t3d_screen(mi, t3dp);
884 return;
885 }
886 t3dp->cycle_p = has_writable_cells(
887 #ifdef STANDALONE
888 screen, MI_VISUAL(mi)
889 #else
890 mi
891 #endif
892 );
893 if (t3dp->cycle_p) {
894 if (MI_IS_FULLRANDOM(mi)) {
895 if (!NRAND(8))
896 t3dp->cycle_p = False;
897 else
898 t3dp->cycle_p = True;
899 } else {
900 t3dp->cycle_p = cycle_p;
901 }
902 }
903 if (!t3dp->mono_p) {
904 if (!(LRAND() % 10))
905 make_random_colormap(
906 #ifdef STANDALONE
907 screen, MI_VISUAL(mi),
908 t3dp->cmap, t3dp->colors, &t3dp->ncolors,
909 True, True, &t3dp->cycle_p, True
910 #else
911 mi,
912 t3dp->cmap, t3dp->colors, &t3dp->ncolors,
913 True, True, &t3dp->cycle_p
914 #endif
915 );
916 else if (!(LRAND() % 2))
917 make_uniform_colormap(
918 #ifdef STANDALONE
919 screen, MI_VISUAL(mi),
920 t3dp->cmap, t3dp->colors, &t3dp->ncolors,
921 True, &t3dp->cycle_p, True
922 #else
923 mi,
924 t3dp->cmap, t3dp->colors, &t3dp->ncolors,
925 True, &t3dp->cycle_p
926 #endif
927 );
928 else
929 make_smooth_colormap(
930 #ifdef STANDALONE
931 screen, MI_VISUAL(mi),
932 t3dp->cmap, t3dp->colors, &t3dp->ncolors,
933 True, &t3dp->cycle_p, True
934 #else
935 mi,
936 t3dp->cmap, t3dp->colors, &t3dp->ncolors,
937 True, &t3dp->cycle_p
938 #endif
939 );
940 }
941 XInstallColormap(display, t3dp->cmap);
942 if (t3dp->ncolors < 2) {
943 t3dp->ncolors = 2;
944 t3dp->no_colors = True;
945 } else
946 t3dp->no_colors = False;
947 if (t3dp->ncolors <= 2)
948 t3dp->mono_p = True;
949
950 if (t3dp->mono_p)
951 t3dp->cycle_p = False;
952
953 }
954
955 t3d_init_3d( mi );
956
957 if (t3dp->zeit == NULL)
958 if ((t3dp->zeit = (struct tm *) malloc(sizeof(struct tm))) == NULL) {
959 free_t3d_screen(mi, t3dp);
960 return;
961 }
962
963 t3d_init_kugel( mi );
964
965 t3dp->startx = t3dp->width / 2;
966 t3dp->starty = t3dp->height / 2;
967 t3dp->scrnH2 = t3dp->startx;
968 t3dp->scrnW2 = t3dp->starty;
969 t3dp->vspeed=0;
970
971 t3d_vektorprodukt( t3dp->x, t3dp->y, t3dp->v);
972 t3d_viewpoint( mi );
973
974 MI_CLEARWINDOW(mi);
975 }
976
977 ENTRYPOINT void
release_t3d(ModeInfo * mi)978 release_t3d(ModeInfo * mi)
979 {
980 if (t3ds != NULL) {
981 int screen;
982
983 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
984 free_t3d_screen(mi, &t3ds[screen]);
985 free(t3ds);
986 t3ds = (t3dstruct *) NULL;
987 }
988 }
989
990 ENTRYPOINT void
draw_t3d(ModeInfo * mi)991 draw_t3d(ModeInfo * mi)
992 {
993 Display *display = MI_DISPLAY(mi);
994 Window window = MI_WINDOW(mi);
995 double dtime;
996 int button;
997 t3dstruct *t3dp;
998
999 if (t3ds == NULL)
1000 return;
1001 t3dp = &t3ds[MI_SCREEN(mi)];
1002 if (t3dp->zeit == NULL)
1003 return;
1004
1005 if (t3dp->no_colors) {
1006 free_t3d_screen(mi, t3dp);
1007 init_t3d(mi);
1008 return;
1009 }
1010
1011 MI_IS_DRAWN(mi) = True;
1012
1013 /* Rotate colours */
1014 if (t3dp->cycle_p)
1015 {
1016 rotate_colors(
1017 #ifdef STANDALONE
1018 MI_SCREENPTR(mi),
1019 #else
1020 display,
1021 #endif
1022 t3dp->cmap, t3dp->colors, t3dp->ncolors, t3dp->direction);
1023 if (!(LRAND() % 1000))
1024 t3dp->direction = -t3dp->direction;
1025 }
1026
1027 t3d_vektorprodukt( t3dp->x, t3dp->y , t3dp->v);
1028
1029 t3dp->vnorm=sqrt(t3dp->v[0]*t3dp->v[0]+t3dp->v[1]*t3dp->v[1]+
1030 t3dp->v[2]*t3dp->v[2]);
1031 t3dp->v[0]=t3dp->v[0]*norm/t3dp->vnorm;
1032 t3dp->v[1]=t3dp->v[1]*norm/t3dp->vnorm;
1033 t3dp->v[2]=t3dp->v[2]*norm/t3dp->vnorm;
1034 t3dp->vnorm=sqrt(t3dp->x[0]*t3dp->x[0]+t3dp->x[1]*t3dp->x[1]+
1035 t3dp->x[2]*t3dp->x[2]);
1036 t3dp->x[0]=t3dp->x[0]*norm/t3dp->vnorm;
1037 t3dp->x[1]=t3dp->x[1]*norm/t3dp->vnorm;
1038 t3dp->x[2]=t3dp->x[2]*norm/t3dp->vnorm;
1039 t3dp->vnorm=sqrt(t3dp->y[0]*t3dp->y[0]+t3dp->y[1]*t3dp->y[1]+
1040 t3dp->y[2]*t3dp->y[2]);
1041 t3dp->y[0]=t3dp->y[0]*norm/t3dp->vnorm;
1042 t3dp->y[1]=t3dp->y[1]*norm/t3dp->vnorm;
1043 t3dp->y[2]=t3dp->y[2]*norm/t3dp->vnorm;
1044
1045 t3d_projektion( mi );
1046 t3d__sort ( mi , 0,t3dp->maxk-1);
1047
1048 dtime= t3d_gettime();
1049
1050 setink(MI_BLACK_PIXEL(mi));
1051 XFillRectangle(display, t3dp->buffer,t3dp->gc,0,0,t3dp->width,
1052 t3dp->height);
1053
1054 {
1055 int i;
1056
1057 t3d_manipulate( mi , dtime);
1058
1059 for (i=0;i<t3dp->maxk;i++)
1060 {
1061 if (t3dp->kugeln[i].d>0.0)
1062 t3d_fill_kugel(i,t3dp->buffer,1 , mi );
1063 }
1064 }
1065
1066 XFlush(display);
1067
1068 XCopyArea (display, t3dp->buffer, window, t3dp->gc, 0, 0, t3dp->width,
1069 t3dp->height, 0, 0);
1070
1071 XFlush(display);
1072
1073 if ( trackmouse )
1074 {
1075 Window junk_win,in_win;
1076 int junk;
1077 unsigned int kb;
1078
1079 (void)(XQueryPointer (display, window, &junk_win, &in_win, &junk,
1080 &junk, &t3dp->px, &t3dp->py, &kb));
1081 /* The following may have to much interference with the Xlockmore
1082 * event handling (JJ) */
1083 if ( (kb&Button2Mask) )
1084 {
1085 button = 2;
1086 }
1087 else
1088 {
1089 if (kb&Button1Mask)
1090 {
1091 button = 1;
1092 }
1093 else
1094 {
1095 if (kb&Button3Mask)
1096 {
1097 button = 3;
1098 }
1099 else
1100 {
1101 button = 0;
1102 }
1103 }
1104 }
1105 }
1106 else
1107 {
1108 t3dp->px = NRAND( t3dp->width );
1109 t3dp->py = NRAND( t3dp->height );
1110 button = NRAND( 50 );
1111 if ( button > 3 ) button = 0;
1112 }
1113
1114 if ((t3dp->px>0)&&(t3dp->px<t3dp->width)&&(t3dp->py>0)&&
1115 (t3dp->py<t3dp->height) )
1116 {
1117 if ((t3dp->px !=t3dp->startx)&&( button == 2 ))
1118 {
1119 t3d_turn(t3dp->y,t3dp->x,((double)(t3dp->px-t3dp->startx))/
1120 (8000*mag));
1121 }
1122 if ((t3dp->py !=t3dp->starty)&&( button == 2 ))
1123 {
1124 t3d_turn(t3dp->x,t3dp->y,((double)(t3dp->py-t3dp->starty))/
1125 (-8000*mag));
1126 }
1127 if ( button == 1 )
1128 {
1129 if (t3dp->vturn==0.0) t3dp->vturn=.005;
1130 else if (t3dp->vturn<2) t3dp->vturn+=.01;
1131 t3d_turn(t3dp->x,t3dp->v,.002*t3dp->vturn);
1132 t3d_turn(t3dp->y,t3dp->v,.002*t3dp->vturn);
1133 }
1134 if ( button == 3 )
1135 {
1136 if (t3dp->vturn==0.0) t3dp->vturn=.005;
1137 else if (t3dp->vturn<2) t3dp->vturn+=.01;
1138 t3d_turn(t3dp->x,t3dp->v,-.002*t3dp->vturn);
1139 t3d_turn(t3dp->y,t3dp->v,-.002*t3dp->vturn);
1140 }
1141 }
1142 if (!( button == 1 )&&!( button == 3 ))
1143 t3dp->vturn=0;
1144
1145 t3dp->speed=t3dp->speed+t3dp->speed*t3dp->vspeed;
1146 if ((t3dp->speed<0.0000001) &&(t3dp->vspeed>0.000001)) t3dp->speed=0.000001;
1147 t3dp->vspeed=.1*t3dp->vspeed;
1148 if (t3dp->speed>0.01) t3dp->speed=.01;
1149 t3dp->a[0]=t3dp->a[0]+t3dp->speed*t3dp->v[0];
1150 t3dp->a[1]=t3dp->a[1]+t3dp->speed*t3dp->v[1];
1151 t3dp->a[2]=t3dp->a[2]+t3dp->speed*t3dp->v[2];
1152 }
1153
1154 #ifndef STANDALONE
1155 ENTRYPOINT void
refresh_t3d(ModeInfo * mi)1156 refresh_t3d(ModeInfo * mi)
1157 {
1158 MI_CLEARWINDOW(mi);
1159 }
1160 #endif
1161
1162 XSCREENSAVER_MODULE ("T3d", t3d)
1163
1164 #endif /* MODE_t3d */
1165