+ // calculate gravitational field - assume field within radius constant: m / r^2
+
+ // first clear the field, and then add contributions
+ memset(grid, 0, sizeof grid);
+
+ // contribution of emitters
+ int num_emitters = emitters.size();
+ for(int i=0; i<num_emitters; i++) {
+ Emitter *em = emitters[i];
+ Rect cbox;
+ calc_contrib_bounds(em, &cbox);
+ float emradius = MASS_TO_RAD(em->mass);
+
+ 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 - em->pos;
+ float dsq = dot(dir, dir);
+ float radsq = emradius * emradius;
+ if(dsq < radsq) {
+ dsq = radsq;
+ }
+
+ gptr[x] -= em->mass / dsq;
+ }
+
+ startpos.y += GRID_DELTA;
+ gptr += GRID_SIZE;
+ }
+ }
+
+ // update texture
+ assert(glGetError() == GL_NO_ERROR);
+ grid_tex->bind();
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GRID_SIZE, GRID_SIZE, GL_LUMINANCE,
+ GL_FLOAT, grid);
+ assert(glGetError() == GL_NO_ERROR);