public void Draw(Graphics g) { foreach (ParticleGroup x in particle_groups) { x.Draw(g); if (draw_aabb) { AABBox a = x.aabb(); g.DrawRectangle(Pens.BurlyWood, (float)a.x1, (float)a.y1, (float)(a.x2 - a.x1), (float)(a.y2 - a.y1)); } } g.DrawLine(Pens.Black, 0, (float)limit_Y, g.VisibleClipBounds.Width, (float)limit_Y); }
public void Update() { system_step = (system_step + 1) % system_step_mod; if (autospawn && (system_step % particle_spawn_mod == 1)) { Spawn(spring_size); } // 1: Remove old particles List <ParticleGroup> to_remove = new List <ParticleGroup>(); foreach (ParticleGroup x in particle_groups) { if (Math.Abs((System_step - x.born) % system_step_mod) > lifetime) { to_remove.Add(x); } } foreach (ParticleGroup x in to_remove) { particle_groups.Remove(x); } for (int ti = 0; (ti < 1) || (normal_time && (ti) * dt < (presentation_interval / 1000.0)); ti++) //normalize for human time //3: external forces { foreach (ParticleGroup x in particle_groups) { foreach (Particle p in x.particles) { p.velocity += dt * g_acceleration; } } //4: damp velocities foreach (ParticleGroup x in particle_groups) { foreach (Particle p in x.particles) { //p.velocity += kd * x.velocity + - p.velocity; p.velocity = kd * p.velocity; } } //5: predict positions (simple explicit euler) foreach (ParticleGroup x in particle_groups) { foreach (Particle p in x.particles) { p.q = p.position + dt * p.velocity; } } List <CollisionPair> collisions = new List <CollisionPair>(); //6: detect and construct collision constraints if (compute_collisions) { foreach (ParticleGroup pg1 in particle_groups) { AABBox aabb = pg1.aabb(); foreach (ParticleGroup pg2 in particle_groups) { if (pg1 != pg2) { foreach (Particle p in pg2.particles) { if (aabb.is_inside(p.q)) { collisions.Add(new CollisionPair(p, pg1)); } } } } } } //7: apply "projection" several times on all constraints for (int i = 0; i < ns; i++) { foreach (ParticleGroup x in particle_groups) { // DistanceConstraints of springs x.ProjectDistanceConstraints(in_k); x.ProjectFloorConstraints(limit_X, limit_Y, in_k); } if (compute_collisions) { foreach (CollisionPair c in collisions) { c.pg.ProjectCollisionConstraint(c.p); } } } //8: find correct velocities foreach (ParticleGroup x in particle_groups) { foreach (Particle p in x.particles) { p.velocity = (1.0 / dt) * (p.q - p.position); p.position = p.q; } } //9: apply friction and resistution impulses on velocities //no friction or resistution is needed } }