+static void calc_contrib_bounds(const Vec2 &pos, float mass, Rect *rect)
+{
+ int gidx = pos_to_grid(pos.x, pos.y);
+ int gx = GRID_X(gidx);
+ int gy = GRID_Y(gidx);
+ int maxrange = (int)ceil(CONTRIB_RANGE(mass));
+
+ int sx = gx - maxrange;
+ int sy = gy - maxrange;
+ int ex = gx + maxrange;
+ int ey = gy + maxrange;
+
+ if(ex > GRID_SIZE) ex = GRID_SIZE;
+ if(ey > GRID_SIZE) ey = GRID_SIZE;
+
+ rect->x = sx < 0 ? 0 : sx;
+ rect->y = sy < 0 ? 0 : sy;
+ rect->width = ex - sx;
+ rect->height = ey - sy;
+}
+
+static void add_influence(const Vec2 &pos, float mass, float radius, const Rect &cbox)
+{
+ float *gptr = grid + cbox.y * GRID_SIZE + cbox.x;
+ Vec2 startpos = grid_to_pos(cbox.x, cbox.y);
+
+ for(int y=0; y<cbox.height; y++) {
+ for(int x=0; x<cbox.width; x++) {
+ Vec2 cellpos = Vec2(startpos.x + (float)x * GRID_DELTA, startpos.y);
+
+ Vec2 dir = cellpos - pos;
+ float dsq = dot(dir, dir);
+ float radsq = radius * radius;
+ if(dsq < radsq) {
+ dsq = radsq;
+ }
+
+ gptr[x] += mass / dsq;
+ }
+
+ startpos.y += GRID_DELTA;
+ gptr += GRID_SIZE;
+ }
+}
+
+