+ // move existing particles
+ Particle *p = plist;
+ while(p) {
+ // calculate the field gradient at the particle position
+ int gidx = pos_to_grid(p->pos.x, p->pos.y);
+ Vec2 grad = calc_field_grad(gidx);
+
+ p->vel += grad * SIM_DT;
+ p->pos += p->vel * SIM_DT;
+
+ // find the grid cell it's moving to
+ int gidx_next = pos_to_grid(p->pos.x, p->pos.y);
+ p->vis_height = 0.0f;//-grid[gidx_next] * field_scale;
+
+ if(gidx_next == gidx) {
+ p = p->next;
+ continue;
+ }
+
+ Particle *destp = grid_part[gidx_next];
+ if(destp) {
+ assert(destp != p);
+ // another particle at the destination, merge them
+ destp->vel += p->vel;
+ destp->mass += p->mass;
+ destp->radius = MASS_TO_RADIUS(destp->mass);
+
+ // ... and remove it
+ grid_part[gidx] = 0;
+ Particle *next = p->next;
+ remove_particle(p);
+ free_particle(p);
+ p = next;
+ } else {
+ // destination is empty, go there
+ if(gidx != gidx_next) {
+ grid_part[gidx] = 0;
+ grid_part[gidx_next] = p;
+ }
+
+ p = p->next;
+ }
+ }
+
+ // TODO destroy particles which left the simulation field
+