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