Dictionary <int, ParticleAggregate> PartitionParticles(PhysicalParticle[] particles, Vector3 cell_size) { Dictionary <int, ParticleAggregate> spatial_hash = new Dictionary <int, ParticleAggregate>(); for (int i = 0; i < particles.Length; i++) { PhysicalParticle p = particles[i]; int x_ind = Mathf.FloorToInt(p.position.x / cell_size.x); int y_ind = Mathf.FloorToInt(p.position.y / cell_size.y); int z_ind = Mathf.FloorToInt(p.position.z / cell_size.z); int hash = x_ind * 113 + y_ind * 12769 + z_ind * 1442897; ParticleAggregate bucket; if (!spatial_hash.TryGetValue(hash, out bucket)) { bucket = new ParticleAggregate(); spatial_hash[hash] = bucket; } bucket.particles.Add(p); bucket.center_of_mass += p.position * p.mass; bucket.total_mass += p.mass; } foreach (KeyValuePair <int, ParticleAggregate> pair in spatial_hash) { pair.Value.center_of_mass /= pair.Value.total_mass; } return(spatial_hash); }
Vector3 HashingForce(Dictionary <int, ParticleAggregate> spatial_hash, ParticleAggregate curr_bucket, PhysicalParticle particle, float deltaT) { ParticleAggregate other_bucket; Vector3 total_force = Vector3.zero; foreach (KeyValuePair <int, ParticleAggregate> other_cell in spatial_hash) { other_bucket = other_cell.Value; if (curr_bucket == other_bucket) { continue; } Vector3 position_difference = other_bucket.center_of_mass - particle.position; float distance = position_difference.magnitude; if (distance < MIN_DISTANCE) { continue; } float pd_cubed = distance * distance * distance; total_force += other_bucket.total_mass * particle.mass / pd_cubed * position_difference; } foreach (PhysicalParticle other_particle in curr_bucket.particles) { if (other_particle == particle) { continue; } Vector3 position_difference = other_particle.position - particle.position; float distance = position_difference.magnitude; if (distance < MIN_DISTANCE) { continue; } float pd_cubed = distance * distance * distance; total_force += other_particle.mass * particle.mass / pd_cubed * position_difference; } total_force *= GRAVITATIONAL_CONSTANT; //Debug.Log(total_force); return(total_force); }
void hash_gravity_worker_func() { KeyValuePair <int, ParticleAggregate> curr_item; while (!should_stop) { if (!need_updating || (curr_spatial_hash == null && next_spatial_hash == null)) { continue; } lock (hash_lock) { if (curr_spatial_hash == null) { curr_spatial_hash = next_spatial_hash; iter = curr_spatial_hash.GetEnumerator(); } curr_item = iter.Current; if (!iter.MoveNext()) { need_updating = false; if (next_spatial_hash != null) { curr_spatial_hash = next_spatial_hash; } iter = curr_spatial_hash.GetEnumerator(); } } ParticleAggregate curr_bucket = curr_item.Value; if (curr_bucket == null) { continue; } foreach (PhysicalParticle particle in curr_bucket.particles) { particle.totalForce = HashingForce(curr_spatial_hash, curr_bucket, particle, this.deltaT); //Debug.Log("Force: " + total_force + "\t Velocity: " + particle.velocity + "\t dt: " + this.deltaT); } } }