/* bomb - automatic interactive visual stimulation Copyright (C) 1994 Scott Draves This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* by nix@cs.cmu.edu wave simulations cell attributes: value velocity stiffness is needed to do lenses parameters: global stiffness - fixed for now damping - use "speed" */ #include "defs.h" #define SPOTS 16 typedef struct { float x,y; float cx,cy; /* center */ float a; /* current angle from center */ float r; /* radius */ float speed; /* radians/sec */ int steps; /* how many steps (of the given speed) each frame - move the spot faster without strobing */ int value; } Spot; static Spot spots[SPOTS]; void step_rule_wave(int frame, rule_t *p, image8_t *fb) { int x,y,bx,by,i,j; board_t *sboard, *dboard; board_t *svboard, *dvboard; u_char *lp0, *lp1; int stiffness = 64; sboard = &board[dbuf]; dboard = &board[1-dbuf]; svboard = &board2[dbuf]; dvboard = &board2[1-dbuf]; dbuf = 1-dbuf; /* torus */ for (y=0;y<=SMALL_YSIZE+1;y++) { (*sboard)[0][y] = (*sboard)[SMALL_XSIZE][y]; (*sboard)[SMALL_XSIZE+1][y] = (*sboard)[1][y]; (*sboard)[0][y] = (*sboard)[SMALL_XSIZE][y]; (*sboard)[SMALL_XSIZE+1][y] = (*sboard)[1][y]; (*svboard)[0][y] = (*svboard)[SMALL_XSIZE][y]; (*svboard)[SMALL_XSIZE+1][y] = (*svboard)[1][y]; (*svboard)[0][y] = (*svboard)[SMALL_XSIZE][y]; (*svboard)[SMALL_XSIZE+1][y] = (*svboard)[1][y]; } for (x=0;x<=SMALL_XSIZE+1;x++) { (*sboard)[x][0] = (*sboard)[x][SMALL_YSIZE]; (*sboard)[x][SMALL_YSIZE+1] = (*sboard)[x][1]; (*sboard)[x][0] = (*sboard)[x][SMALL_YSIZE]; (*sboard)[x][SMALL_YSIZE+1] = (*sboard)[x][1]; (*svboard)[x][0] = (*svboard)[x][SMALL_YSIZE]; (*svboard)[x][SMALL_YSIZE+1] = (*svboard)[x][1]; (*svboard)[x][0] = (*svboard)[x][SMALL_YSIZE]; (*svboard)[x][SMALL_YSIZE+1] = (*svboard)[x][1]; } for(y=1;y<=SMALL_YSIZE;y++) { lp0 = fb->p + (fb->stride * (y - 1)); lp1 = lp0 + fb->stride * SMALL_YSIZE; for(x=1;x<=SMALL_XSIZE;x++) { int dt, t; /* target is average of nearest neighbors */ dt = ((((*sboard)[x ][y-1]) + ((*sboard)[x-1][y ]) + ((*sboard)[x ][y+1]) + ((*sboard)[x+1][y ])) >> 2) - (*sboard)[x][y]; t = (*svboard)[x][y] + ((stiffness * dt) >> 8); t += (p->speed * t) >> 8; if (t > p->mask) t = p->mask; else if (t < -p->mask) t = -p->mask; (*dvboard)[x][y] = t; t = (*sboard)[x][y] + (*dvboard)[x][y]; (*dboard)[x][y] = t + ((p->speed * t) >> 8); t += (p->mask >> 2); /* if (t<0) t = 0; if (t > 255) t = 255; */ /* t &= p->mask; if (p->remap) t = remap[t]; */ t = remap[t & p->mask]; lp0[SMALL_XSIZE] = t; *lp0++ = t; lp1[SMALL_XSIZE] = t; *lp1++ = t; } } for (i=0; isteps; j++) { s->a += s->speed; s->x = s->r * cos(s->a) + s->cx; s->y = s->r * sin(s->a) + s->cy; #if 0 if (s->x > 0 && s->x < SMALL_XSIZE && s->y > 0 && s->y < SMALL_YSIZE) { int *pressure = &(*dboard)[(int)s->x][(int)s->y]; *pressure = p->mask; } #else { int tx = ((int)s->x) % SMALL_XSIZE; int ty = ((int)s->y) % SMALL_YSIZE; if (tx < 0) tx += SMALL_XSIZE; if (ty < 0) tx += SMALL_YSIZE; (*dboard)[tx][ty] = p->mask; } #endif } if (0 == R%20) { float ncx, ncy; /* printf("spot %d: x:%f y:%f cx:%f cy:%f r:%f a:%f da:%f\n", i, s->x, s->y, s->cx, s->cy, s->r, s->a, s->speed); */ /* pick a new center */ /* make it be colinear with cx,cy - x,y for G2 continuity */ /* this keeps the same radius */ ncx = s->x - s->cx + s->x; ncy = s->y - s->cy + s->y; #if 0 if (ncx > s->r/3 && ncx < (SMALL_XSIZE - s->r/3) && ncy > s->r/3 && ncy < (SMALL_YSIZE-s->r/3)) { #endif s->cx = ncx; s->cy = ncy; s->r = sqrt((s->x - s->cx)*(s->x - s->cx) + (s->y - s->cy)*(s->y - s->cy)); s->a = atan2(s->y - s->cy, s->x - s->cx); /* could make speed = c/radius to get constant velocity */ s->speed = -s->speed; #if 0 } #endif /* printf("spot %d: x:%f y:%f cx:%f cy:%f r:%f a:%f da:%f\n", i, s->x, s->y, s->cx, s->cy, s->r, s->a, s->speed); */ } } } void init_wave() { int i; for(i=0;ix = R%SMALL_XSIZE; s->y = R%SMALL_YSIZE; s->cx = R%60 - 30 + s->x; s->cy = R%60 - 30 + s->y; s->r = sqrt((s->x - s->cx)*(s->x - s->cx) + (s->y - s->cy)*(s->y - s->cy)); s->a = atan2(s->y - s->cy, s->x - s->cx); s->speed = 0.0125; s->steps = 8; } }