1 //
2 // XMover: Modul zur Optimierten Ball-Darstellung unter XWindows
3 // - flackerfreies Bewegen der B�lle durch Hilfspixmaps
4 // - Beleuchtungseffekt durch Raytracing-Bitmaps
5 // - Darstellung halber Kugeln durch vorberechnete Pixmaps
6 //
7
8 #ifndef _vec3_h
9 # include "vec3.h"
10 #endif
11
12 #define LEFT_RIGHT_OPT
13 #define USE_STUFFER
14
15 /*----------------------------------------------------------------------------*/
16
PixmapCache()17 PixmapCache::PixmapCache() {
18 count = 0;
19 }
20
~PixmapCache()21 PixmapCache::~PixmapCache() {
22 }
23
Lock(int id_in,int size_in)24 Pixmap PixmapCache::Lock( int id_in, int size_in ) {
25 for (int i=0;i<count;i++) {
26 if (id_in==id[i]&&size_in==size[i]) {
27 lockcount[i]++;
28 return pmap[i];
29 }
30 }
31 return 0;
32 }
33
Unlock(Display * dpy,Pixmap pix)34 void PixmapCache::Unlock( Display *dpy, Pixmap pix ) {
35 //
36 // free the given pixmap, if nobody else will use it.
37 //
38 for (int i=0;i<count;i++) {
39 if (pix==pmap[i]) {
40 if (--lockcount[i]==0) {
41 XFreePixmap(dpy,pix);
42 count--;
43 while( i<count ) {
44 pmap[i] = pmap[i+1];
45 size[i] = size[i+1];
46 id[i] = id[i+1];
47 lockcount[i] = lockcount[i+1];
48 i++;
49 }
50 }
51 return;
52 }
53 }
54 }
55
InsertAndLock(Display *,Pixmap pix,int id_in,int size_in)56 void PixmapCache::InsertAndLock( Display * /*dpy*/, Pixmap pix, int id_in, int size_in ) {
57 if (Lock(id_in,size_in)) {
58 fprintf(stderr,"internal error 1 in PixmapCache::InsertAndLock\n" );
59 return;
60 }
61 if (count>=PCACHE_MAX) {
62 fprintf(stderr,"internal error 2 in PixmapCache::InsertAndLock\n" );
63 return;
64 }
65 pmap[count] = pix;
66 size[count] = size_in;
67 id[count] = id_in;
68 lockcount[count] = 1;
69 count++;
70 }
71
72 PixmapCache PixmapCache::pcache;
73
74 /*----------------------------------------------------------------------------*/
75
76 //
77 // Klasse zur Komprimierung der RingState-Felder
78 //
79 class Stuffer {
80 public:
Stuffer()81 Stuffer() : ws(0), wl(sizeof(RingState)) {}
82
Init(int ws_in,int wl_in)83 void Init( int ws_in, int wl_in ) {
84 ws = ws_in;
85 if (wl!=wl_in) {
86 printf( "ERROR: Stuffer used with illegal input size !\n" );
87 exit(0);
88 }
89 }
90 void Shrink( RingState *addr, int len );
91 void Expand( RingState *addr, int len );
SSize(int len)92 int SSize( int len )
93 #ifdef USE_STUFFER
94 { return ((len*ws+7)/8); }
95 #else
96 { return ((len*wl+7)/8); }
97 #endif
LSize(int len)98 int LSize( int len )
99 { return ((len*wl+7)/8); }
100
101 private:
102 int ws; // Bits klein
103 const int wl; // Bits gross
104 static int mtab[9];
105 };
106
107 int Stuffer::mtab[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
108
109 #ifdef USE_STUFFER
Shrink(RingState * addr,int len)110 void Stuffer::Shrink( RingState *addr, int len ) {
111 RingState *r_p;
112 RingState r_val;
113 int r_len;
114 unsigned char *w_p;
115 unsigned char w_val;
116 int w_space;
117
118 r_p = addr;
119 w_p = (unsigned char*)addr;
120 w_space = 8;
121 w_val = 0;
122 while( len-- ) {
123 r_val = *r_p++;
124 r_len = ws;
125
126 while (r_len>=w_space) {
127 w_val |= ((unsigned char)r_val)&mtab[w_space];
128 *w_p++ = w_val;
129 w_val = 0;
130 r_val >>= w_space;
131 r_len -= w_space;
132 w_space = 8;
133 }
134
135 if (r_len) {
136 w_val |= (((unsigned char)r_val)&mtab[w_space])<<(w_space-r_len);
137 w_space -= r_len;
138 }
139 }
140 *w_p++ = w_val;
141 }
142
Expand(RingState * addr,int len)143 void Stuffer::Expand( RingState *addr, int len ) {
144 RingState *w_p; // Schreibzeiger - expandiertes Ende
145 RingState w_val;
146 int w_space; // fehlende Bits zum Gesamtwort
147 unsigned char *r_p; // Lesezeiger - komprimiertes Ende
148 unsigned char r_val; // gueltige Bits
149 int r_len; // Zahl gueltige Bits an Lesezeigerposition
150
151 r_p = (unsigned char*)addr + len*ws/8; // Adresse des letzten Byte
152 r_len = (len*ws)%8; // g�ltige Bits im letzen Byte
153 if (r_len) r_val = *r_p; // letzte Bits holen
154 else { r_val = *--r_p;
155 r_len = 8;
156 }
157 w_p = addr + len;
158
159 while( len-- ) {
160 w_space = ws;
161 w_val = 0;
162 while( r_len<=w_space ) {
163 w_val <<= r_len;
164 w_val |= r_val>>(8-r_len);
165 w_space-= r_len;
166 r_val = *--r_p; // ABR: liest 1 Byte ueber die Untergrenze
167 r_len = 8;
168 }
169 if (w_space) {
170 w_val <<= w_space;
171 w_val |= r_val&mtab[w_space];
172 r_len -= w_space;
173 }
174 *--w_p = w_val;
175 }
176 }
177
178 #else
Shrink(RingState *,int)179 void Stuffer::Shrink( RingState *, int ) {}
Expand(RingState *,int)180 void Stuffer::Expand( RingState *, int ) {}
181 #endif
182
183 /*----------------------------------------------------------------------------*/
184
185 class Bitmap {
186 public:
Clear()187 void Clear() { memset( bits, 0, bytes_per_line*height ); }
188
Init(int w,int h,char * bmap)189 void Init( int w, int h, char *bmap ) {
190 width = w;
191 bytes_per_line = (width+7)/8;
192 height = h;
193 bits = bmap;
194 }
Bitmap(int w,int h,char * bmap)195 Bitmap( int w, int h, char *bmap ) { Init(w,h,bmap); }
Bitmap()196 Bitmap() {}
197
GetPixel(int x,int y)198 int GetPixel( int x, int y ) {
199 if ((x<0)||(x>=width)||(y<0)||(y>=height)) return 0;
200 else {
201 unsigned char mask = 1<<(x&7);
202 return (bits[bytes_per_line*y+(x>>3)]&mask)?1:0;
203 }
204 }
SetPixel(int x,int y)205 void SetPixel( int x, int y ) {
206 unsigned char mask = 1<<(x&7);
207 bits[bytes_per_line*y+(x>>3)] |= mask;
208 }
ClrPixel(int x,int y)209 void ClrPixel( int x, int y ) {
210 unsigned char mask = 1<<(x&7);
211 bits[bytes_per_line*y+(x>>3)] &= ~mask;
212 }
213
214
Create()215 Pixmap Create() {
216 return XCreatePixmapFromBitmapData(dpy,win,bits,width,height,1,0,1 );
217 }
218 void Print();
219
220 int width;
221 int height;
222 protected:
223 int bytes_per_line;
224 char *bits;
225 };
226
227 class LocBitmap : public Bitmap {
228 public:
Init(int w,int h)229 void Init( int w, int h ) {
230 Bitmap::Init(w,h,0);
231 bits = new char[bytes_per_line*height];
232 Clear();
233 }
Init(int w,int h,FILE * fp)234 void Init( int w, int h, FILE *fp ) {
235 Bitmap::Init(w,h,0);
236 bits = new char[bytes_per_line*height];
237 fread(bits,sizeof(char),bytes_per_line*height,fp);
238 }
Write(FILE * fp)239 void Write( FILE *fp ) {
240 fwrite(bits,sizeof(char),bytes_per_line*height,fp);
241 }
LocBitmap(int w,int h)242 LocBitmap( int w, int h ) { Init(w,h); }
243
LocBitmap()244 LocBitmap() {}
~LocBitmap()245 ~LocBitmap() { delete bits; }
246
247 // change for a sun sparc-station runing 4.1.3 that thinks:
248 // xmover.c:463: no non-hidden member function 'LocBitmap::create' defined
Create()249 Pixmap Create() { return Bitmap::Create(); }
250 };
251
252
Print()253 void Bitmap::Print() {
254 for(int y=0;y<height;y++) {
255 for(int x=0;x<width;x++) printf( "%d", GetPixel(x,y) );
256 printf( "\n" );
257 }
258 }
259
260 /*----------------------------------------------------------------------------*/
261
262 #ifdef STATISTICS
263 unsigned long BallMover::moves = 0l;
264 #endif
265
BallMover(const Real & r_in)266 BallMover::BallMover( const Real &r_in ) {
267 r = (int)(r_in*w2n); // Radius als Member festhalten
268 d = 2*r; // Bem: Durchmesser immer gerade
269
270 bpix = help = 0;
271 }
272
273
~BallMover()274 BallMover::~BallMover() {
275 if (help) XFreePixmap( dpy, help );
276 if (bpix) XFreePixmap( dpy, bpix );
277 }
278
279
Init()280 void BallMover::Init() {
281 LocBitmap *bit; // Kugelbitmap
282 int x,y;
283 double dr=r-0.5; // tats�chlicher (Welt-)Radius
284
285 bit = new LocBitmap( d, d );
286 max_rad = r-0.25+EPS;
287 max_rad2 = max_rad * max_rad;
288 for (y=0;y<d;y++) {
289 for (x=0;x<d;x++) {
290 double dx = x-dr; // X-Abstand zur Kreismitte
291 double dy = y-dr; // Y-Abstand zur Kreismitte
292 double dist2 = dx*dx + dy*dy;
293 if (dist2<max_rad2) {
294 bit->SetPixel(x,y);
295 }
296 }
297 }
298
299 bpix = bit->Create();
300
301 d_help = 2*d-1;
302 help = XCreatePixmap(dpy,win,d_help,d_help,DefaultDepth(dpy,0));
303
304 delete bit;
305 }
306
DrawBallAt(int x,int y,int col_x)307 void BallMover::DrawBallAt( int x, int y, int col_x )
308 {
309 #ifndef NODRAW
310 XFillRectangle(dpy,help,gc_bclear,0,0,d,d);
311 XCopyPlane(dpy,bpix,help,gc_ball[col_x],0,0,d,d,0,0,1);
312 Pixmap shadow = GetShadowMap(x,y);
313 if (shadow) XCopyPlane(dpy,shadow,help,gc_lay2,0,0,d,d,0,0,1);
314 XCopyArea(dpy,help,win,gc_bxor,0,0,d,d,x-r, y-r );
315 #endif
316 }
317
318
MoveBallOnScreen(int oldx,int oldy,int newx,int newy,int col_x)319 void BallMover::MoveBallOnScreen( int oldx, int oldy, int newx, int newy, int col_x ) {
320
321 int dx = newx-oldx;
322 int dy = newy-oldy;
323 int absx = (dx>0)?dx:-dx;
324 int absy = (dy>0)?dy:-dy;
325
326 #ifndef NODRAW
327 if ( (absx<d_help-d) && (absy<d_help-d) ) {
328 Pixmap shadow;
329
330 int width = d+absx; // tats�chlicher Ausschnittgr��e der Pixmap
331 int height= d+absy;
332 int ox = (dx>0)?0:absx; // relativer Abstand alte Position
333 int oy = (dy>0)?0:absy;
334 int nx = (dx>0)?absx:0; // relativer Abstand neue Position
335 int ny = (dy>0)?absy:0;
336
337 XFillRectangle(dpy,help,gc_bclear,0,0,width,height);
338
339 XCopyPlane(dpy,bpix,help,gc_ball[col_x],0,0,d,d,ox,oy,1);
340 shadow = GetShadowMap(oldx,oldy);
341 if (shadow) XCopyPlane(dpy,shadow,help,gc_lay2,0,0,d,d,ox,oy,1);
342
343 XCopyPlane(dpy,bpix,help,gc_ball[col_x],0,0,d,d,nx,ny,1);
344 shadow = GetShadowMap(newx,newy);
345 if (shadow) XCopyPlane(dpy,shadow,help,gc_lay2,0,0,d,d,nx,ny,1);
346
347 XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,oldx-ox-r, oldy-oy-r );
348 }
349 else {
350 DrawBallAt(oldx,oldy,col_x);
351 DrawBallAt(newx,newy,col_x);
352 }
353 #endif
354
355 #ifdef STATISTICS
356 moves++;
357 #endif
358 }
359
GetShadowMap(int,int)360 Pixmap BallMover::GetShadowMap( int /*x*/, int /*y*/ ) { return 0; }
361
362 // -------------------------------------------------------------------------
363
DiscMover(const Real & r)364 DiscMover::DiscMover( const Real &r ) :
365 BallMover( r )
366 {
367 lpix = 0;
368 }
369
~DiscMover()370 DiscMover::~DiscMover()
371 {
372 if (lpix) XFreePixmap(dpy,lpix);
373 }
374
Init()375 void DiscMover::Init() {
376 LocBitmap *lbit; // Kreisbitmap
377 int x,y;
378 double dr=r-0.5; // tats�chlicher (Welt-)Radius
379
380 BallMover::Init();
381
382 lbit = new LocBitmap( d, d );
383 double shade_rad = 1.2; // Pixelbreite in WS-umgerechnet
384 double inner1 = r*1/4;
385 double inner2 = r*2/4;
386
387 for (y=0;y<d;y++) {
388 for (x=0;x<d;x++) {
389 double dx = x-dr; // X-Abstand zur Kreismitte
390 double dy = y-dr; // Y-Abstand zur Kreismitte
391 double dist = sqrt(dx*dx + dy*dy);
392 if (dist<max_rad) {
393 if ( (dist>max_rad-shade_rad)
394 || (dist>inner1-shade_rad)&&(dist<inner1)
395 || (dist>inner2-shade_rad)&&(dist<inner2) ) {
396 lbit->SetPixel(x,y);
397 }
398 }
399 }
400 }
401
402 lpix = lbit->Create();
403 delete lbit;
404 }
405
GetShadowMap(int,int)406 Pixmap DiscMover::GetShadowMap( int /*x*/, int /*y*/ ) { return lpix; }
407
408 // -------------------------------------------------------------------------
409
ShadedBallMover(const Real & r)410 ShadedBallMover::ShadedBallMover( const Real &r ) :
411 BallMover( r )
412 {
413 lpix=0;
414 }
415
~ShadedBallMover()416 ShadedBallMover::~ShadedBallMover()
417 {
418 if (lpix) {
419 for (int i=0;i<lpixs_all;i++) {
420 XFreePixmap( dpy, lpix[i] );
421 }
422 delete [] lpix;
423 lpix = 0;
424 }
425 }
426
427 #if (0)
428 const double circ_x = -50.0;
429 const double circ_y = -50.0;
430 const double circ_r1 = 150.0;
431 const double circ_r2 = 300.0;
432 #endif
433
434
Init()435 void ShadedBallMover::Init() {
436 int x,y,i;
437
438 LocBitmap *lbit; // Feld der Hilfbitmaps
439
440 double dr=r-0.5; // tats�chlicher (Welt-)Radius
441
442 int ncircs; // number of lamps
443 double circ_z; // hight of lamps
444 struct lightdata {
445 double x,y; // position of lamps
446 double r1, r2; // size (inner/outer) of lamps
447 } circ[3];
448
449 BallMover::Init();
450
451 if (light_flag) {
452 lpixs_x = 24; // Zahl der Bitmaps in X-Richtung
453 lpixs_y = 12; // Zahl der Bitmaps in Y-Richtung
454 }
455 else {
456 lpixs_x = 0;
457 lpixs_y = 0;
458 }
459 lpixs_all = lpixs_x * lpixs_y; // Gesamtzahl
460 distx = max_x / lpixs_x; // Weltkoordinatenraster X
461 disty = max_y / lpixs_y; // Weltkoordinatenraster Y
462 lbit = new LocBitmap[lpixs_all]; // Anlegen der Bitmaps
463 for (i=0;i<lpixs_all;i++) lbit[i].Init(d,d);
464
465 if (light_flag<=1) {
466 ncircs = 1; // single light, far far away
467 circ_z = 2000.0;
468 circ[0].x= -50.0; circ[0].y= -50.0; circ[0].r1= 150.0; circ[0].r2 = 300.0;
469 }
470 else {
471 ncircs = 3;
472 circ_z = MaxX() * 2.0 / 3.0; // einfach 'mal so angenommen
473 for (int l=0;l<ncircs;l++) {
474 circ[l].x = MaxX() * (double)(l+1) / 4.0;
475 circ[l].y = MaxY() / 2.0;
476 circ[l].r1 = MaxX() / 16.0;
477 circ[l].r2 = MaxX() / 8.0;
478 }
479 }
480
481
482 DBG1( UnixTrace, "Starting image processing with ball size %d pixel:\n", d );
483 DBG1( UnixTrace, "BitmapData: >%d bytes\n", (d+7)/8*d*lpixs_all );
484
485 for (y=0;y<d;y++) { // F�r alle Punkte der Bitmaps
486 for (x=0;x<d;x++) {
487 double dx = x-dr; // X-Abstand zur Kreismitte
488 double dy = y-dr; // Y-Abstand zur Kreismitte
489 double dist2 = dx*dx + dy*dy;
490 if (dist2<max_rad2) {
491
492 double dz = dr*dr-dist2; // quadratischer Z-Abstand
493 if (dz>=0) {
494 double f = circ_z/sqrt(dz); // Multiplikator zur Decke
495 dx *= f; // XPos an Decke
496 dy *= f; // YPos an Decke
497
498 for (int px=0;px<lpixs_x;px++) { // f�r alle Bitmaps
499 for (int py=0;py<lpixs_y;py++) {
500 int lflag=0; // 0-dark, 1-medium, 2-light
501 for (int l=0;l<ncircs;l++) {
502 // Weltposition relativ zu Kreislicht
503 double wx = (px*distx+(distx>>1)+dx)/w2n-circ[l].x;
504 double wy = (py*disty+(disty>>1)+dy)/w2n-circ[l].y;
505 double d = wx*wx+wy*wy;
506 if (d<circ[l].r2*circ[l].r2) {
507 if (d<circ[l].r1*circ[l].r1) {
508 // inner circle
509 lflag=2; break;
510 }
511 else lflag=1;
512 }
513 }
514 if ( (lflag==2) || (lflag&&((x^y)&1)) ) {
515 lbit[px+py*lpixs_x].SetPixel(x,y);
516 }
517 }
518 }
519 }
520 }
521 }
522 }
523
524 lpix = new Pixmap[lpixs_all];
525 for (i=0;i<lpixs_all;i++) {
526 lpix[i] = lbit[i].Create();
527 }
528 delete [] lbit;
529 }
530
531
GetShadowMap(int x,int y)532 Pixmap ShadedBallMover::GetShadowMap( int x, int y ) {
533 int xp = x/distx;
534 if (xp<0) xp=0;
535 if (xp>=lpixs_x) xp=lpixs_x-1;
536 int yp = y/disty;
537 if (yp<0) yp=0;
538 if (yp>=lpixs_y) yp=lpixs_y-1;
539
540 return lpix[xp+yp*lpixs_x];
541 }
542
543
CreateLightWindow()544 void ShadedBallMover::CreateLightWindow() {
545 Window help;
546 const int o=2;
547
548 help=CreateWindow( "Beleuchtung", lpixs_x*(d+o)+1 , lpixs_y*(d+o)+1 );
549 for (int px=0;px<lpixs_x;px++) {
550 for (int py=0;py<lpixs_y;py++) {
551 XCopyPlane(dpy,bpix,help,gc_ball[2],0,0,d,d,o/2+px*(d+o),o/2+py*(d+o),1);
552 XCopyPlane(dpy,lpix[px+py*lpixs_x],help,gc_lay2,0,0,d,d,o/2+px*(d+o),o/2+py*(d+o),1);
553
554 }
555 }
556 }
557
558 // -------------------------------------------------------------------------
559
560 const int HalfBallMover::o=4;
561
HalfBallMover(const Real & r,int mode_in)562 HalfBallMover::HalfBallMover( const Real &r, int mode_in ) :
563 ShadedBallMover( r )
564 {
565 rpix = 0; // Ring-Pixmap-Feld
566 nbpix = 0; // negative Pixmap zum Debuggen
567 tw = 0;
568 mode = mode_in;
569
570 right = left = up = down = 0;
571 }
572
Create(const Real & r,int mode_in)573 HalfBallMover* HalfBallMover::Create( const Real &r, int mode_in ) {
574 switch (enhanced_mover) {
575 case 2: return new HiEnhancedHalfBallMover(r,mode_in);
576 case 1: return new LoEnhancedHalfBallMover(r,mode_in);
577 default: return new HalfBallMover(r,mode_in);
578 }
579 }
580
~HalfBallMover()581 HalfBallMover::~HalfBallMover()
582 {
583 if (rpix) {
584 for (int i=0;i<rpixs_all;i++) {
585 XFreePixmap( dpy, rpix[i] );
586 }
587 delete [] rpix;
588 rpix = 0;
589 }
590 if (nbpix) XFreePixmap( dpy, nbpix );
591
592 if (right) delete [] right;
593 if (left) delete [] left;
594 if (up) delete [] up;
595 if (down) delete [] down;
596 }
597
Init()598 void HalfBallMover::Init() {
599 int x,y,i,l,b;
600
601 LocBitmap *rbit; // Feld der Ring-Bitmaps
602 Vec3 *pv; // Vec2 zum Pol der Kugel der entsprechenden Bitmap
603
604 ShadedBallMover::Init();
605
606 //
607 // Zahl der Pixmap's, Gr��e der Felder bestimmen
608 //
609 sym = (mode>1)?2.0:1.0;
610 //sym = 1.0;
611
612 if (mode) {
613 rpixs_l = (int)(3.14*d/sym); // Zahl der Bitmaps in L�ngen-Richtung
614 rpixs_b = (int)(3.14*d/2.0); // Zahl der Bitmaps in Breiten-Richtung
615 mult = 6; // Internes Raster
616 }
617 else {
618 rpixs_l = rpixs_b = 1;
619 mult = 1;
620 }
621 mult2 = mult/2;
622 rpixs_all = rpixs_l * rpixs_b; // Gesamtzahl
623
624 vecs_l = rpixs_l * mult; // Hilfsraster feiner als Bitmap-Raster
625 vecs_b = rpixs_b * mult;
626
627 vecs_all = vecs_l * vecs_b; // Gesamtgr��e des Rasters
628 for (i=0;i<(int)sizeof(RingState);i++) vecs_all/=256;
629 if (vecs_all>0) {
630 printf( "too many RingStates (%d) -> switch type to unsigned long (in xmover.h)\n",
631 vecs_l * vecs_b );
632 exit(0);
633 }
634 vecs_all = vecs_l * vecs_b; // Gesamtgr��e des Rasters
635
636 char fname[80];
637 sprintf(fname,"%s/fly%d-%d.dta",DATA_DIRECTORY,mode,d);
638 FILE *fp;
639
640 #ifdef DEBUG
641 fp = (debug&ForceCalc)?0:fopen( fname, "r" );
642 #else
643 fp = fopen( fname, "r" );
644 #endif
645
646 rbit = new LocBitmap[rpixs_all]; // Anlegen der Bitmaps
647 for (l=0;l<rpixs_l;l++) { // f�r alle Bitmaps
648 for (b=0;b<rpixs_b;b++) {
649 if (!fp) rbit[PixIndex(l,b)].Init(d,d);
650 else rbit[PixIndex(l,b)].Init(d,d,fp);
651 }
652 }
653
654 pv = new Vec3[d*d];
655 for (y=0;y<d;y++) {
656 for (x=0;x<d;x++) {
657 double dx = x-r+0.5; // X-Abstand zur Kreismitte
658 double dy = y-r+0.5; // Y-Abstand zur Kreismitte
659 double dist2 = dx*dx + dy*dy; // Dist. zur sichtbaren Mitte
660 if (dist2<max_rad2) {
661 // double dzr = sqrt(dr*dr-dy*dy); // Kugel-Radius auf H�he z
662 // double dz = sqrt(dzr*dzr-dx*dx); // fehlende Tiefenkoordinate
663 double dz = sqrt(r*r-dist2);
664 pv[x+y*d] = Vec3( dx, dz, dy );
665 }
666 else {
667 pv[x+y*d] = Vec3( 0.0, 0.0, 0.0 );
668 }
669 }
670 }
671
672 #ifdef DEBUG
673 double start_time = GetCurrentTime();
674 #endif
675
676 if (!fp) {
677 DBG3( UnixTrace, "Rings need %dx%d=%d Bitmaps\n",rpixs_l,rpixs_b,rpixs_all);
678 DBG1( UnixTrace, "BitmapData: >%7d Bytes\n", (d+7)/8*d*rpixs_all );
679 DBG1( UnixTrace, "+ temporary: >%7d Bytes\n",
680 d*d*(sizeof(Vec3)+sizeof(Bitmap)+(d*(d+7)/8) ) );
681
682 //
683 // Bitmaps ausrechen
684 //
685 printf( "image processing: 00%%" ); fflush(stdout);
686
687 for (l=0;l<rpixs_l;l++) { // f�r alle Bitmaps
688 printf( "\b\b\b%02d%%", (int)100*l/rpixs_l ); fflush(stdout);
689 for (b=0;b<rpixs_b;b++) {
690 Vec3 v = Vec3( lToDeg(l*mult+mult2), bToDeg(b*mult+mult2) )*Real(r);
691 switch(mode) {
692 case 1: for (y=0;y<d;y++) { // Volle Kugeln
693 for (x=0;x<d;x++) {
694 if (!pv[x+y*d].IsZero()) {
695 Real ang = v.AngleRadTo( pv[x+y*d] );
696 if (ang>0.35) rbit[PixIndex(l,b)].SetPixel(x,y);
697 }
698 }
699 }
700 break;
701 case 2: for (y=0;y<d;y++) { // Halbe Kugeln
702 for (x=0;x<d;x++) {
703 if (!pv[x+y*d].IsZero()) {
704 Real ang = v.AngleRadTo( pv[x+y*d] );
705 if (ang>1.0708 && ang<2.0708)
706 rbit[PixIndex(l,b)].SetPixel(x,y);
707 }
708 }
709 }
710 break;
711 case 3: for (y=0;y<d;y++) { // Volle Kugeln 2
712 for (x=0;x<d;x++) {
713 if (!pv[x+y*d].IsZero()) {
714 Real ang = v.AngleRadTo( pv[x+y*d] );
715 if (ang>0.35) rbit[PixIndex(l,b)].SetPixel(x,y);
716 }
717 }
718 }
719 break;
720 case 4: for (y=0;y<d;y++) { // Halbe Kugeln 2
721 for (x=0;x<d;x++) {
722 if (!pv[x+y*d].IsZero()) {
723 Real ang = v.AngleRadTo( pv[x+y*d] );
724 if ((ang>0.35&&ang<1.27)||(ang>1.87&&ang<2.79))
725 rbit[PixIndex(l,b)].SetPixel(x,y);
726 }
727 }
728 }
729 break;
730 default: for (y=0;y<d;y++) {
731 for (x=0;x<d;x++) {
732 if (!pv[x+y*d].IsZero()) {
733 rbit[PixIndex(l,b)].SetPixel(x,y);
734 }
735 }
736 }
737 break;
738 }
739 }
740 }
741
742 printf( "\b\b\bdone\n" );
743 }
744
745
746
747 //
748 // RingState-Felder anfordern und initialisieren
749 // - zu jeder Pixmap existiert dabei in ein Eintrage mit einer
750 // Folgepixmap in Feldern zu jeder Himmelsrichtung.
751 //
752 DBG4( UnixTrace, "RingStateData:>%7d Bytes (for %dx%d=%d States)\n",
753 4*vecs_all*sizeof(RingState), vecs_l, vecs_b, vecs_all );
754
755 right = new RingState[vecs_all];
756 left = new RingState[vecs_all];
757 up = new RingState[vecs_all];
758 down = new RingState[vecs_all];
759
760 //
761 // Stuffer anlegen und initialisieren
762 //
763 Stuffer stuff;
764 for (i=0,l=vecs_all;l;l>>=1) i++; // Bits in vecs_all zaehlen
765 stuff.Init(i,sizeof(RingState));
766
767 if (fp) {
768 printf( "reading %s\n", fname );
769
770 #ifndef LEFT_RIGHT_OPT
771 fread( right,1,stuff.SSize(vecs_all), fp );
772 stuff.Expand( right, vecs_all );
773 fread( left, 1,stuff.SSize(vecs_all), fp );
774 stuff.Expand( left, vecs_all );
775 #endif
776 fread( up, 1,stuff.SSize(vecs_all), fp );
777 stuff.Expand( up, vecs_all );
778 fread( down, 1,stuff.SSize(vecs_all), fp );
779 stuff.Expand( down, vecs_all );
780 }
781 else {
782 Real b_ang = (double)mult*M_PI/vecs_b; // Rotationswinkel pro Pixel
783
784 printf( "state processing: 00%%" ); fflush(stdout);
785
786 for (l=0;l<vecs_l;l++) {
787 printf( "\b\b\b%02d%%", (int)100*l/vecs_l ); fflush(stdout);
788
789 for (int b=0;b<vecs_b;b++) {
790 RingState st = AngVec2St(l,b); // aktueller Index
791 RingState nst; // auszurechnender State
792 Real newl, newb;
793
794 Vec3 v( lToDeg(l), bToDeg(b) );
795
796 v.XTurnAngleRad(b_ang).GetPolarRad(&newl,&newb);
797 nst = AngRad2St( newl, newb );
798 if (st==nst) DBG2( Loops, "Loop-Warning Up: %03d/%03d\n",l,b );
799 up[st] = nst;
800
801
802 v.XTurnAngleRad(-b_ang).GetPolarRad(&newl,&newb);
803 nst = AngRad2St( newl, newb );
804 if (st==nst) DBG2( Loops, "Loop-Warning Down: %03d/%03d\n",l,b );
805 down[st] = nst;
806
807 #ifndef LEFT_RIGHT_OPT
808 v.ZTurnAngleRad(-b_ang).GetPolarRad(&newl,&newb);
809 nst = AngRad2St( newl, newb );
810 if (st==nst) DBG2( Loops, "Loop-Warning Right: %03d/%03d\n",l,b );
811 right[st] = nst;
812
813 v.ZTurnAngleRad(b_ang).GetPolarRad(&newl,&newb);
814 nst = AngRad2St( newl, newb );
815 if (st==nst) DBG2( Loops, "Loop-Warning Left: %03d/%03d\n",l,b );
816 left[st] = nst;
817 #endif
818 }
819 }
820
821 printf( "\b\b\bdone\n" );
822
823 DBG1( UnixTrace, "Time: %g secs.\n", GetCurrentTime()-start_time );
824 }
825
826 #ifdef LEFT_RIGHT_OPT
827 for (l=0;l<vecs_l;l++) {
828 for (int b=0;b<vecs_b;b++) {
829 RingState st = AngVec2St(l,b); // aktueller Index
830 right[st] = AngVec2StBnd((l+(vecs_l*(int)sym)-mult)%(vecs_l*(int)sym),b);
831 left[st] = AngVec2StBnd((l+mult)%(vecs_l*(int)sym),b);
832 }
833 }
834 #endif
835
836 #ifdef DEBUG
837 if (debug&ShowRings) {
838 //
839 // Eine spezielle Pixmap wird erzeugt, die eine Negation der Balldarstellung
840 // ist, um in dem Trace-Window einzelne Pixmap's herzuheben.
841 //
842 nbpix = XCreatePixmap(dpy,bpix,d+o,d+o,1);
843 GC gc = XCreateGC( dpy, nbpix, 0, 0l );
844 XSetFunction(dpy,gc,GXset);
845 XFillRectangle(dpy,nbpix,gc,0,0,d+o,d+o); // alle Pixmap setzen
846 XSetFunction(dpy,gc,GXxor);
847 XCopyArea(dpy,bpix,nbpix,gc,0,0,d,d,o/2,o/2); // Ball l�schen
848 XFreeGC(dpy,gc);
849 }
850 #endif
851
852 if (fp) {
853 fclose(fp);
854 fp = 0;
855 }
856 else {
857 fp = fopen( fname, "w" );
858 }
859 //
860 // Bitmaps in Pixmaps wandeln und interne Strukturen freigeben
861 //
862 rpix = new Pixmap[rpixs_all];
863 for (i=0;i<rpixs_all;i++) {
864 rpix[i] = rbit[i].Create();
865 if (fp) rbit[i].Write( fp );
866 }
867 delete [] rbit;
868 delete [] pv;
869
870 if (fp) {
871 printf( "writing %s\n", fname );
872
873 #ifndef LEFT_RIGHT_OPT
874 stuff.Shrink( right, vecs_all );
875 fwrite( right,1,stuff.SSize(vecs_all), fp );
876 stuff.Expand( right, vecs_all );
877 stuff.Shrink( left, vecs_all );
878 fwrite( left, 1,stuff.SSize(vecs_all), fp );
879 stuff.Expand( left, vecs_all );
880 #endif
881 stuff.Shrink( up, vecs_all );
882 fwrite( up, 1,stuff.SSize(vecs_all), fp );
883 stuff.Expand( up, vecs_all );
884 stuff.Shrink( down, vecs_all );
885 fwrite( down, 1,stuff.SSize(vecs_all), fp );
886 stuff.Expand( down, vecs_all );
887 fclose(fp);
888 }
889 }
890
891
892
CreateRingWindow()893 void HalfBallMover::CreateRingWindow() {
894 tw=CreateWindow( "Ringverteilung", rpixs_l*(d+o)+1 , rpixs_b*(d+o)+1 );
895 for (int l=0;l<rpixs_l;l++) {
896 for (int b=0;b<rpixs_b;b++) {
897 XCopyPlane(dpy,bpix,tw,gc_ballwhite,0,0,d,d,o/2+l*(d+o),o/2+b*(d+o),1);
898 XCopyPlane(dpy,lpix[(l*lpixs_x/rpixs_l)+(b*lpixs_y/rpixs_b)*lpixs_x],tw,gc_lay2,0,0,d,d,o/2+l*(d+o),o/2+b*(d+o),1);
899 XCopyPlane(dpy,rpix[PixIndex(rpixs_l-1-l,b)],tw,gc_ball[7],0,0,d,d,o/2+l*(d+o),o/2+b*(d+o),1);
900 }
901 }
902 #ifdef DEBUG
903 if (debug&xwd) {
904 char command[200];
905 XSync(dpy,0);
906 sprintf( command, "/usr/bin/X11/xwd -id %ld -frame > XWD/rings", tw );
907 system(command);
908 }
909 #endif
910 }
911
912
913 #define _INFO
914
CreateTurnWindow()915 void HalfBallMover::CreateTurnWindow() {
916 Window win;
917
918 win=CreateWindow( "Senkrecht-Rotation", rpixs_b*(d+o)+1,2*rpixs_b*(d+o)+1 );
919 for (int b=0;b<rpixs_b;b++) {
920 #ifdef INFO
921 printf( "Row %d: angle: %f\n", b, (double)bToDeg(b*mult+mult2) );
922 #endif
923 RingState st = AngPix2St(0,b);
924 for (int y=0;y<2*rpixs_b;y++) {
925 #ifdef INFO
926 int lp,bp;
927 int lv,bv;
928 //
929 // Ausgabe der Tabellenerte
930 //
931 St2AngVec(st,&lv,&bv);
932 St2AngPix(st,&lp,&bp);
933 printf( " Line %2d: Vec2: %03d/%03d, Pixmap: %02d/%02d",
934 y, lv, bv, lp, bp );
935
936 //
937 // Berechnung der direkten Werte zum Vergleich
938 //
939 Real b_ang=(double)mult*M_PI/vecs_b; // Rotationswinkel pro Pixel
940 Vec3 v( lToDeg(mult2), bToDeg(b*mult+mult2) );
941 Real newl, newb;
942 v.XTurnAngleRad((y*b_ang)).GetPolarRad(&newl,&newb);
943 RingState nst = AngRad2St( newl, newb );
944 // Ausgabe
945 St2AngVec(nst,&lv,&bv);
946 St2AngPix(nst,&lp,&bp);
947 printf( " <=> Vec2: %03d/%03d, Pixmap: %02d/%02d\n",
948 lv, bv, lp, bp );
949
950 if (((b^y)&1)) {
951 XCopyPlane(dpy,bpix,win,gc_ballwhite,0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
952 XCopyPlane(dpy,lpix[(b*lpixs_x/rpixs_b)+(y/2*lpixs_y/rpixs_b)*lpixs_x],win,gc_lay2,0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
953 XCopyPlane(dpy,rpix[PixIndex(nst)],win,gc_ball[7],0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
954 }
955 else
956 #endif
957 {
958 XCopyPlane(dpy,bpix,win,gc_ballwhite,0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
959 XCopyPlane(dpy,lpix[(b*lpixs_x/rpixs_b)+(y/2*lpixs_y/rpixs_b)*lpixs_x],win,gc_lay2,0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
960 XCopyPlane(dpy,rpix[PixIndex(st)],win,gc_ball[8],0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
961 }
962 st = Turn(st,0,1);
963 }
964 }
965 #ifdef DEBUG
966 if (debug&xwd) {
967 char command[200];
968 XSync(dpy,0);
969 sprintf( command, "/usr/bin/X11/xwd -id %ld -frame > XWD/turns", win );
970 system(command);
971 }
972 #endif
973 }
974
975
976
977 #if (1)
978
979 #define LINE(DY,YDEC,YADDOP,YTAB,DX,XLESS,XTAB) \
980 int dy_c = DY; \
981 int c = 0; \
982 while(DY) { \
983 st = YTAB [st]; \
984 DY YDEC; \
985 c -= DX; \
986 if (c XLESS 0) { \
987 c YADDOP dy_c; \
988 st = XTAB [st]; \
989 }; \
990 }
991
992
Turn(RingState st,int dx,int dy)993 RingState HalfBallMover::Turn( RingState st, int dx, int dy ) {
994
995 if (dx>0) {
996 if (dy>0) {
997 if (dy>dx) { LINE(dy,--,+=,up, dx,<,right); }
998 else { LINE(dx,--,+=,right,dy,<,up); }
999 }
1000 else { // dy negativ => alle DY-Parameter umkehren
1001 if (-dy>dx) { LINE(dy,++,-=,down, dx,<,right); }
1002 else { LINE(dx,--,+=,right,dy,>,down); }
1003 }
1004 }
1005 else { // dx negativ => alle DX-Parameter umkehren
1006 if (dy>0) {
1007 if (dy>-dx) { LINE(dy,--,+=,up, dx,>,left); }
1008 else { LINE(dx,++,-=,left ,dy,<,up); }
1009 }
1010 else { // dy negativ => alle DY-Parameter umkehren
1011 if (-dy>-dx){ LINE(dy,++,-=,down, dx,>,left); }
1012 else { LINE(dx,++,-=,left ,dy,>,down); }
1013 }
1014 }
1015
1016 return st;
1017 }
1018
1019 #else
Turn(RingState st,int dx,int dy)1020 RingState HalfBallMover::Turn( RingState st, int dx, int dy ) {
1021 while( dx && dy ) {
1022 if (dx>0) { dx--; st = right[st]; }
1023 else if (dx<0) { dx++; st = left[st]; }
1024 if (dy>0) { dy--; st = up[st]; }
1025 else if (dy<0) { dy++; st = down[st]; }
1026 }
1027 if (dx>0) { while(dx--) st = right[st]; }
1028 else if (dx<0) { while(dx++) st = left[st]; }
1029 if (dy>0) { while(dy--) st = up[st]; }
1030 else if (dy<0) { while(dy++) st = down[st]; }
1031 return st;
1032 }
1033 #endif
1034
1035
1036 #ifdef DEBUG
ShowDebugRing(RingState st,int col_x)1037 void HalfBallMover::ShowDebugRing(RingState st, int col_x) {
1038 int l,b;
1039 St2AngPix(st,&l,&b);
1040 XCopyPlane(dpy,nbpix,tw,gc_ballwhite, 0,0,d+o,d+o,(rpixs_l-1-l)*(d+o),b*(d+o),1);
1041 XCopyPlane(dpy,nbpix,tw,gc_ball[col_x],0,0,d+o,d+o,(rpixs_l-1-l)*(d+o),b*(d+o),1);
1042 }
1043 #endif
1044
RollBallAt(int x,int y,RingState st,int col_x)1045 void HalfBallMover::RollBallAt( int x, int y, RingState st, int col_x )
1046 {
1047 #ifndef NODRAW
1048 XFillRectangle(dpy,help,gc_bclear,0,0,d,d);
1049 XCopyPlane(dpy,bpix,help,gc_ballwhite,0,0,d,d,0,0,1);
1050 XCopyPlane(dpy,GetShadowMap(x,y),help,gc_lay2,0,0,d,d,0,0,1);
1051 XCopyPlane(dpy,rpix[PixIndex(st)],help,gc_ball[col_x],0,0,d,d,0,0,1);
1052 XCopyArea(dpy,help,win,gc_bxor,0,0,d,d,x-r, y-r );
1053
1054 #ifdef DEBUG
1055 if ((tw)&&(debug&ShowRings)) ShowDebugRing(st,col_x);
1056 #endif
1057 #endif
1058 }
1059
1060
RollBallOnScreen(int oldx,int oldy,RingState ost,int newx,int newy,RingState * nst,int col_x)1061 void HalfBallMover::RollBallOnScreen( int oldx, int oldy, RingState ost,
1062 int newx, int newy, RingState *nst, int col_x ) {
1063
1064 int dx = newx-oldx;
1065 int dy = newy-oldy;
1066
1067 *nst = Turn( ost, dx, dy );
1068
1069 int absx = (dx>0)?dx:-dx;
1070 int absy = (dy>0)?dy:-dy;
1071
1072 #ifndef NODRAW
1073 if ( (absx<d_help-d) && (absy<d_help-d) ) {
1074 int width = d+absx; // tats�chlicher Ausschnittgr��e der Pixmap
1075 int height= d+absy;
1076 int ox = (dx>0)?0:absx; // relativer Abstand alte Position
1077 int oy = (dy>0)?0:absy;
1078 int nx = (dx>0)?absx:0; // relativer Abstand neue Position
1079 int ny = (dy>0)?absy:0;
1080
1081 XFillRectangle(dpy,help,gc_bclear,0,0,width,height);
1082
1083 XCopyPlane(dpy,bpix,help,gc_ballwhite,0,0,d,d,ox,oy,1);
1084 XCopyPlane(dpy,GetShadowMap(oldx,oldy),help,gc_lay2,0,0,d,d,ox,oy,1);
1085 XCopyPlane(dpy,rpix[PixIndex(ost)],help,gc_ball[col_x],0,0,d,d,ox,oy,1);
1086
1087 XCopyPlane(dpy,bpix,help,gc_ballwhite,0,0,d,d,nx,ny,1);
1088 XCopyPlane(dpy,GetShadowMap(newx,newy),help,gc_lay2,0,0,d,d,nx,ny,1);
1089 XCopyPlane(dpy,rpix[PixIndex(*nst)],help,gc_ball[col_x],0,0,d,d,nx,ny,1);
1090
1091 XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,oldx-ox-r, oldy-oy-r );
1092
1093 #ifdef DEBUG
1094 if ((tw)&&(debug&ShowRings)) {
1095 ShowDebugRing(ost,col_x);
1096 ShowDebugRing(*nst,col_x);
1097 }
1098 #endif
1099
1100 }
1101 else {
1102 RollBallAt(oldx,oldy,ost,col_x);
1103 RollBallAt(newx,newy,*nst,col_x);
1104 }
1105 #endif
1106
1107 #ifdef STATISTICS
1108 moves++;
1109 #endif
1110 }
1111
1112
1113 // ---------------------------------------------------------------------------
1114 // LoEnhancedHalfBallMover
1115 // ---------------------------------------------------------------------------
1116
1117
LoEnhancedHalfBallMover(const Real & r,int mode_in)1118 LoEnhancedHalfBallMover::LoEnhancedHalfBallMover( const Real &r, int mode_in )
1119 : HalfBallMover( r, mode_in ) {
1120 lbpix = 0;
1121 boffset = 0;
1122 lb_dist = boffset+d;
1123 }
1124
~LoEnhancedHalfBallMover()1125 LoEnhancedHalfBallMover::~LoEnhancedHalfBallMover() {
1126 if (lbpix) {
1127 PixmapCache::pcache.Unlock( dpy, lbpix );
1128 lbpix = 0;
1129 }
1130 }
1131
Init()1132 void LoEnhancedHalfBallMover::Init() {
1133 HalfBallMover::Init();
1134
1135 // create initialisation pixmap for all possible shades, which
1136 // can directly be used as presets in the RollBall() functions
1137 // A large Pixmap is created that contains all neccessary background-presets
1138 // in a certain distance, so that a direct copy can be done, which presets
1139 // the whole background help-pixmap.
1140
1141 lbpix = PixmapCache::pcache.Lock( d, ENHANCED_LBPIX_ID );
1142 if (!lbpix ) {
1143
1144 // create map and clear it
1145
1146 DBG1( UnixTrace, "EnhancedData: >%d bytes\n",
1147 (lb_dist*lpixs_x+d-1)*(lb_dist*lpixs_y+d-1) );
1148 lbpix = XCreatePixmap(dpy,win,
1149 lb_dist*lpixs_x+d-1,lb_dist*lpixs_y+d-1,DefaultDepth(dpy,0));
1150 XFillRectangle(dpy,lbpix,gc_bclear, 0,0,
1151 lb_dist*lpixs_x+d-1,lb_dist*lpixs_y+d-1);
1152
1153 // copy the balls & shades into the map
1154
1155 for (int x=0;x<lpixs_x;x++) {
1156 for (int y=0;y<lpixs_y;y++) {
1157 XCopyPlane(dpy,bpix, lbpix,gc_ballwhite,
1158 0,0,d,d,boffset+x*lb_dist,boffset+y*lb_dist,1);
1159 XCopyPlane(dpy,lpix[x+y*lpixs_x],lbpix,gc_lay2,
1160 0,0,d,d,boffset+x*lb_dist,boffset+y*lb_dist,1);
1161 }
1162 }
1163 PixmapCache::pcache.InsertAndLock(dpy,lbpix,d,ENHANCED_LBPIX_ID);
1164 }
1165 }
1166
1167
RollBallAt(int x,int y,RingState st,int col_x)1168 void LoEnhancedHalfBallMover::RollBallAt( int x, int y, RingState st, int col_x )
1169 {
1170 #ifdef DEBUG
1171 if (enhanced_mover<1) {
1172 HalfBallMover::RollBallAt(x,y,st,col_x);
1173 return;
1174 }
1175 #endif
1176
1177 #ifndef NODRAW
1178 int xp,yp;
1179 WC2Index(x,y,&xp,&yp);
1180 XCopyArea(dpy,lbpix,help,gc_default,boffset+xp*lb_dist,boffset+yp*lb_dist,d,d,0,0);
1181 XCopyPlane(dpy,rpix[PixIndex(st)],help,gc_ball[col_x],0,0,d,d,0,0,1);
1182 XCopyArea(dpy,help,win,gc_bxor,0,0,d,d,x-r, y-r );
1183
1184 #ifdef DEBUG
1185 if ((tw)&&(debug&ShowRings)) ShowDebugRing(st,col_x);
1186 #endif
1187 #endif
1188 }
1189
1190
RollBallOnScreen(int oldx,int oldy,RingState ost,int newx,int newy,RingState * nst,int col_x)1191 void LoEnhancedHalfBallMover::RollBallOnScreen( int oldx, int oldy, RingState ost,
1192 int newx, int newy, RingState *nst, int col_x ) {
1193 #ifdef DEBUG
1194 if (enhanced_mover<1) {
1195 HalfBallMover::RollBallOnScreen(oldx,oldy,ost,newx,newy,nst,col_x);
1196 return;
1197 }
1198 #endif
1199
1200 int dx = newx-oldx;
1201 int dy = newy-oldy;
1202
1203 *nst = Turn( ost, dx, dy );
1204
1205 int absx = (dx>0)?dx:-dx;
1206 int absy = (dy>0)?dy:-dy;
1207
1208 #ifndef NODRAW
1209 if ( (absx<d_help-d) && (absy<d_help-d) ) {
1210 int width = d+absx; // tats�chlicher Ausschnittgr��e der Pixmap
1211 int height= d+absy;
1212 int ox = (dx>0)?0:absx; // relativer Abstand alte Position
1213 int oy = (dy>0)?0:absy;
1214 int nx = (dx>0)?absx:0; // relativer Abstand neue Position
1215 int ny = (dy>0)?absy:0;
1216
1217 int xp,yp;
1218 WC2Index(oldx,oldy,&xp,&yp);
1219 XFillRectangle(dpy,help,gc_bclear,0,0,width,height);
1220
1221 XCopyArea(dpy,lbpix,help,gc_bxor,
1222 boffset-ox+xp*lb_dist,boffset-oy+yp*lb_dist,d_help,d_help,0,0);
1223 XCopyPlane(dpy,rpix[PixIndex(ost)],help,gc_ball[col_x],0,0,d,d,ox,oy,1);
1224
1225 WC2Index(newx,newy,&xp,&yp);
1226 XCopyArea(dpy,lbpix,help,gc_bxor,
1227 boffset+xp*lb_dist,boffset+yp*lb_dist,d,d,nx,ny);
1228 XCopyPlane(dpy,rpix[PixIndex(*nst)],help,gc_ball[col_x],0,0,d,d,nx,ny,1);
1229
1230 XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,oldx-ox-r, oldy-oy-r );
1231
1232 #ifdef DEBUG
1233 if ((tw)&&(debug&ShowRings)) {
1234 ShowDebugRing(ost,col_x);
1235 ShowDebugRing(*nst,col_x);
1236 }
1237 #endif
1238 }
1239 else {
1240 RollBallAt(oldx,oldy,ost,col_x);
1241 RollBallAt(newx,newy,*nst,col_x);
1242 }
1243 #endif
1244
1245 #ifdef STATISTICS
1246 moves++;
1247 #endif
1248 }
1249
1250 // ---------------------------------------------------------------------------
1251 // HiEnhancedHalfBallMover
1252 // ---------------------------------------------------------------------------
1253
1254
HiEnhancedHalfBallMover(const Real & r,int mode_in)1255 HiEnhancedHalfBallMover::HiEnhancedHalfBallMover( const Real &r, int mode_in )
1256 : LoEnhancedHalfBallMover( r, mode_in ) {
1257 boffset = d-1;
1258 lb_dist = 2*d-1;
1259 }
1260
~HiEnhancedHalfBallMover()1261 HiEnhancedHalfBallMover::~HiEnhancedHalfBallMover() {
1262 }
1263
RollBallOnScreen(int oldx,int oldy,RingState ost,int newx,int newy,RingState * nst,int col_x)1264 void HiEnhancedHalfBallMover::RollBallOnScreen( int oldx, int oldy, RingState ost,
1265 int newx, int newy, RingState *nst, int col_x ) {
1266 #ifdef DEBUG
1267 if (enhanced_mover<2) {
1268 LoEnhancedHalfBallMover::RollBallOnScreen(oldx,oldy,ost,newx,newy,nst,col_x);
1269 return;
1270 }
1271 #endif
1272
1273 int dx = newx-oldx;
1274 int dy = newy-oldy;
1275
1276 *nst = Turn( ost, dx, dy );
1277
1278 int absx = (dx>0)?dx:-dx;
1279 int absy = (dy>0)?dy:-dy;
1280
1281 #ifndef NODRAW
1282 if ( (absx<d_help-d) && (absy<d_help-d) ) {
1283 int width = d+absx; // tats�chlicher Ausschnittgr��e der Pixmap
1284 int height= d+absy;
1285 int ox = (dx>0)?0:absx; // relativer Abstand alte Position
1286 int oy = (dy>0)?0:absy;
1287 int nx = (dx>0)?absx:0; // relativer Abstand neue Position
1288 int ny = (dy>0)?absy:0;
1289
1290 int xp,yp;
1291 WC2Index(oldx,oldy,&xp,&yp);
1292 XCopyArea(dpy,lbpix,help,gc_default,
1293 boffset-ox+xp*lb_dist,boffset-oy+yp*lb_dist,d_help,d_help,0,0);
1294 XCopyPlane(dpy,rpix[PixIndex(ost)],help,gc_ball[col_x],0,0,d,d,ox,oy,1);
1295
1296 WC2Index(newx,newy,&xp,&yp);
1297 XCopyArea(dpy,lbpix,help,gc_bxor,
1298 boffset+xp*lb_dist,boffset+yp*lb_dist,d,d,nx,ny);
1299 XCopyPlane(dpy,rpix[PixIndex(*nst)],help,gc_ball[col_x],0,0,d,d,nx,ny,1);
1300
1301 XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,oldx-ox-r, oldy-oy-r );
1302
1303 #ifdef DEBUG
1304 if ((tw)&&(debug&ShowRings)) {
1305 ShowDebugRing(ost,col_x);
1306 ShowDebugRing(*nst,col_x);
1307 }
1308 #endif
1309 }
1310 else {
1311 RollBallAt(oldx,oldy,ost,col_x);
1312 RollBallAt(newx,newy,*nst,col_x);
1313 }
1314 #endif
1315
1316 #ifdef STATISTICS
1317 moves++;
1318 #endif
1319 }
1320
1321