A simple particle system physics engine for processing. I've designed this to be application / domain agnostic. All this is supposed to do is let you make particles, apply forces and calculate the positions of particles over time in real-time. Anything else you need to handle yourself.
There are four parts
Changes since the previous version
DOWNLOAD LIBRARY + SOURCE
LICENSE - Use this code for whatever you want, just send me a link firstname.lastname@example.org
The particle system is in charge of everything. It makes particles and forces for you and you tell it to advance the simulation using tick().
new ParticleSystem( float gravityY, float drag )
new ParticleSystem( float gx, float gy, float gz, float drag )
Construct a new particle system with some downward (positive y) or 3D gravity and some drag. You can make as many of these as you'd like per sketch as long as forces from one system don't refer to particles from another. I don't know what would happen if you connected particles from one system to another.
void setIntegrator( int integrator )
pass this either: ParticleSystem.RUNGE_KUTTA or ParticleSystem.MODIFIED_EULER Runge-Kutta is the default. It takes about 4 times as many cycles as Modified Euler. In return the system gets very stable. If you plan to have have over 1000 particles interacting with each other try Modified Euler. If you will have fewer particles and want tight springs and quicker responses use Runge-Kutta. Stick with the default and if things get slow try switching to Euler. You may have to add more drag or reduce the strength of springs and attractions to keep it stable. The example Random Arboretum above has sections of code you can uncomment to experiment with this.
void setGravity( float y )
void setGravity( float x, float, y, float z )
set the strength of gravity, down (in the positive y direction) or in whatever 3D direction you feel like. You probably want the magnitude of this to be in the range of 0-5.
void setDrag( float drag )
set the drag force that acts on all objects equally, and proportional to velocity.
void tick( float t )
advance the simulation by some time t, or by the default 1.0. You'll want to call this in draw(). You probably want to keep this the same at all times unless you want speed up or slow things down.
this deletes all the particles and all the forces in the system (except the omnipresent gravity and drag even if ther are 0).
Particle makeParticle( float mass, float x, float y, float z )
Create a new particle in the system with some mass and at some x, y, z position. The default is a new particle with mass 1.0 at (0, 0, 0).
Particle getParticle( int index )
void removeParticle( int index )
void removeParticle( Particle p )
Note removing things shifts the indices and the library does not take responsibility for you deleting particles that forces refer to. e.g. if you have a spring between two particles and remove one things will definitely break.
Spring makeSpring( Particle a, Particle b, float strength, float damping, float restLength )
make a spring in the system between 2 particles you have previously created. Look at spring down there for what the parameters mean.
Spring getSpring( int index )
void removeSpring( int index )
void removeSpring( Spring s )
Note removing things shifts the indices.
Attraction makeAttraction( Particle a, Particle b, float strength, float minimumDistance )
Make an attraction (or repulsion) force between two particles. If the strength is negative they repel each other, if the strength is positive they attract. There is also a minimum distance that limits how strong this force can get close up.
Attraction getAttraction( int index )
void removeAttraction( int index )
void removeAttraction( Attraction a )
Note removing things shifts the indices.
Particles can represent objects, corners of 2D or 3D shapes or abstract things that won't even be drawn. Particles have 4 properties:
void positon().set( float x, float y, float z )
Move the particle to some 3D location.
void position().add( float x, float y, float z );
Move the particle by some 3D amount
This is how you get to the dimensions of particle position.
void velocity().set( float x, float y, float z )
Set the velocity to some 3D quantity, maybe use this to send a particle flying off in a particular direction.
void velocity().add float x, float y, float z )
This adds some 3D quantity to the velocity of the particle. You could maybe use this to speed up or slow down a particle.
This is how you get at the dimensions of the particles velocity.
void setMass( float m )
These set and get the mass of the particle. Heavier particles will have more inertia and will accelerate slower. Attraction/repulsion forces will also be stronger for heavier particles. If you aren't doing anything special this will probably be the same for all particles.
Particles can either be fixed or free. If they are free they move around and are affected by forces, if they are fixed they stay where they are.
How long the particle has been around. Every time you advance the simulation by t every particle gets a little older by t.
Springs connect 2 particles and try to keep them a certain distance apart. They have 3 properties:
Return the particles that are on either end of this spring.
The current length of the spring.
void setRestLength( float l )
void setStrength( float s )
void setDamping( float s )
Attractions or repulsions (negative attraction) act on 2 particles and either constantly pull them together or constantly pull them apart by applying a force to each particle:
in other words the force is is much stronger close up than far away.
Attractions/repulsions have 2 properties:
void setStrength( float s )
Positive strength is attraction negative strength is repulsion.
Return the particles being attracting or repeling each other.
void setMinimumDistance( float d )
Get and set the minimum distance, which limits how strong the force can get close up.
Each particle has a Vector3D called force. If you make your own subclass of Force you can stick it in the particle system and have it applied along with all the other forces. The relevant methods from ParticleSystem are:
void addCustomForce( Force f )
Force getCustomForce( int index )
void removeCustomForce( int index )
void removeCustomForce( Force f )
public class MyCustomForce implements Force
// Particle p; or one or more particles
// you're applying this force to
public void apply()
// calculate force to apply to particle(s)
// based on their position and velocity
// e.g. float f = p.position().x();
// add that force to the particle's force vector
// e.g. p.force().add( f, f, f );
Then in setup() do something like
physics.addCustomForce( new MyCustomForce( p ) );
p.force() is an instance of Vector3D (just like position and velocity). It has all sorts of facilities like multiplication and dot products that you may want to use. Have a look at the source and how it's used in Spring and Attraction for inspiration.
If you have a good example of a custom force of some kind drop me a line and I'll put it up for others.