Creating a Particle System in Processing

Embed Size (px)

Citation preview

  • 8/8/2019 Creating a Particle System in Processing

    1/24

    Creating a Particle System in Processing: Beginning with Particle Animation

    March 12th, 2010 Code, Java, Processing, Software

    I have recently decided to take on the task of creating a particle system from scratch designed towork specifically with Processing. I have always been interested in the subject and I wanted to

    challenge myself and share something with the Processing community. I am going to write thisseries of articles to document my learning process as well as the evolution of this library.

    For this first article, I am going to start with the most basic concepts of dealing with particles in

    Processing. No differential equations, no numerical methods, just simple linear algebra and Java.This one may be pretty boring to most Processing users, but I want to start off simple to establish

    a good base of knowledge because it will get pretty hairy later. If you are a complete beginner, Isuggest you start here and come back when you have a decent understanding of Processing.

    The Hello World! of particle physics

    The first thing we want to examine is how to draw and move a single particle. First check outthis code in action here then come back and closely examine the source:

    //particle's screen coordinatesfloat x, y;//particle's velocity//velocity is change in postionfloat vx, vy;

    void setup() {size(400, 400);

    stroke(0);strokeWeight(3);fill(150);smooth();//set position and velocityresetParticle();}

    void draw() {background(255);

    //draw the particle with diameter of 10ellipse(x, y, 10, 10);

    /** update the position by adding on the velocity* remember that velocity means incremental change* in position.*/x += vx;y += vy;

    }

  • 8/8/2019 Creating a Particle System in Processing

    2/24

  • 8/8/2019 Creating a Particle System in Processing

    3/24

    stroke(0);strokeWeight(3);fill(150);smooth();//set position and velocityresetParticle();}

    void draw() {background(255);

    //draw the particle with diameter of 10ellipse(x, y, 10, 10);

    /** update the velocity by adding on the acceleration* remember that acceleration means incremental change* in velocity.*/vx += ax;

    vy += ay;

    /** update the position by adding on the velocity* remember that velocity means incremental change* in position.*/x += vx;y += vy;

    }

    // on a mouse clickvoid mousePressed() {resetParticle();

    }

    void resetParticle() {//reset the particle to the middle of the screenx = y = width/2f;

    //set velocity to 0vx = vy = 0f;

    ax = random(-0.01, 0.01);ay = random(0.003, 0.01);//downward

    }

    Now that we are adding on the acceleration to the velocity each frame, the velocity increases as

    time goes on and the particle moves faster and faster. Kind of like gravity (an acceleration of 9.8

    m/s2) or a car accelerating faster and faster. Congratulations! We now have the ability to crudelydescribe Newtonian motion!

    Abstraction and Multiple Particles

  • 8/8/2019 Creating a Particle System in Processing

    4/24

    Now that we can create one particle with ease, lets create many. Basically what we need to do iscreate an abstraction of what a particle is then turn that into a Java class. This isnt a Java lesson

    and I hope you know what that means so lets jump straight into it. Check out this program thencome back and learn about the code.

    Particle[] particles;int NUM_PARTICLES = 100;

    void setup() {size(400, 400);stroke(0);strokeWeight(3);fill(150);smooth();}

    void draw() {background(255);if (particles != null) {

    for (int i = 0; i < NUM_PARTICLES; i++) {particles[i].exist();

    }}

    }

    void mousePressed() {particles = new Particle[NUM_PARTICLES];for (int i = 0; i < NUM_PARTICLES; i++) {particles[i] = new Particle();

    }}

    public class Particle {float x, y;float vx, vy;float ax, ay;

    public Particle() {x = mouseX;y = mouseY;vx = vy = 0f;ax = random(-0.2, 0.2);ay = random(-0.08, 0.05);

    }

    public void exist() {

    vx += ax;vy += ay;x += vx;y += vy;ellipse(x, y, 10, 10);

    }}

  • 8/8/2019 Creating a Particle System in Processing

    5/24

    Of course this is too crazy to resemble anything real in the our physical world, but it shows thepoint. Basically what we have done is created a Particle class which contains references to its

    own state information. Then we can have an array of Particles and update those in a nice loop.There is still some more improvement that can be done to this though. Lets talk about vectors.

    Vectors

    A Vector is essentially a 1 row N column matrix. In computer graphics, we use the Vector data

    structure to represent multi-dimensional state information such as position, velocity, andacceleration. Because they are matrices and we set them to have the same dimensions, we can

    use standard matrix operations and concepts from linear algebra to help us solve some of thesystems of linear equations we face. Processing contains its own implementation of a vector

    called a PVector. It is a 3-dimensional vector so we can represent things in 2d or 3d space.Check out this re-write of the last program in action and I will explain how it works after the

    code:

    ArrayList particles;int LIFESPAN = 120;//global gravityPVector acceleration = new PVector(0f, 0.025);

    void setup() {size(400, 400);stroke(0);strokeWeight(3);fill(150);smooth();particles = new ArrayList();}

    void draw() {background(255);//only create when mouse movesif (abs(mouseX-pmouseX) > 0.0001) {particles.add(new Particle());

    }for (int i = particles.size()-1; i >= 0; i--) {Particle p = (Particle)particles.get(i);if(!p.exist()) {particles.remove(i);

    }}

    }

    public class Particle {PVector location;PVector velocity;int age;

    public Particle() {location = new PVector(mouseX, mouseY);//get velocity from direction and speed of mouse movementvelocity = new PVector(mouseX-pmouseX, mouseY-pmouseY);

  • 8/8/2019 Creating a Particle System in Processing

    6/24

    age = 0;}

    public boolean exist() {velocity.add(acceleration);location.add(velocity);ellipse(location.x, location.y, 10, 10);if (age > LIFESPAN) {return false;

    }age++;return true;

    }

    }

    Notice that I changed over the x and y variables to the PVectors and this gives us operations like

    add, subtract, multiply, magnitude, normalize, and etc. Check out this article on matrix math ifyou dont remember it from grade school. In this example, all you need to know is that when you

    add two PVectors, it does a matrix add. I do, however, highly suggest that you get real familiarwith matrix math and systems of equations if you want to move on:

    velocity.add(acceleration);

    //is equivalent to

    velocity.set( acceleration.x+velocity.x,acceleration.y+velocity.y,acceleration.z+velocity.z );

    I also moved the acceleration vector out to have global static scope. And I am getting the

    velocity from the changing mouse positions. Remember that velocity is change in position, so wecan get the velocity vector by subtracting the new cursor position from the old.

    I dont really want to go into Java stuff but notice that I also changed the array to an ArrayList.And if you are wondering why I didnt use a parameterized ArrayList, it is b/c Processing uses a

    light-weight open source java compiler that doesnt support it.

    Until next time

    That is it for now. I hope that wasnt too boring. In the next article, I am going to talk more aboutvectors, different kinds of forces. I will also briefly point out the inaccuracies in our integration

    technique and open up a huge can of maths worms.

  • 8/8/2019 Creating a Particle System in Processing

    7/24

    Creating a Particle System in Processing: Applying Forces

    March 17th, 2010 Code, Java, Processing, Software

    This article is one in a series of articles about particle systems in Processing. To view the first of

    the series, click here.

    To recap, in my last article, I went over the basics of particles and Newtonian motion inProcessing. In this article, I am going to explain using forces andNewtons Second Law of

    Motion to describe the effects of forces on our particles. I am also going to point out that ourcurrent integration technique is flawed as segway into the next article.

    Forces

    When we last left our particle physics sandbox, it looked liked this:

    ArrayList particles;int LIFESPAN = 120;//global gravityPVector acceleration = new PVector(0f, 0.025);

    void setup() {size(400, 400);stroke(0);strokeWeight(3);fill(150);smooth();particles = new ArrayList();}

    void draw() {background(255);//only create when mouse movesif (abs(mouseX-pmouseX) > 0.0001) {particles.add(new Particle());

    }for (int i = particles.size()-1; i >= 0; i--) {Particle p = (Particle)particles.get(i);if(!p.exist()) {particles.remove(i);

    }}

    }

    public class Particle {PVector location;PVector velocity;int age;

    public Particle() {location = new PVector(mouseX, mouseY);//get velocity from direction and speed of mouse movementvelocity = new PVector(mouseX-pmouseX, mouseY-pmouseY);

  • 8/8/2019 Creating a Particle System in Processing

    8/24

    age = 0;}

    public boolean exist() {velocity.add(acceleration);location.add(velocity);ellipse(location.x, location.y, 10, 10);if (age > LIFESPAN) {return false;

    }age++;return true;

    }

    }

    The PVectoracceleration represents the acceleration resulting from a gravitational force.

    Gravity is a force and results in an acceleration of an object. There is an equation to determinegravity but we usually take it to result in a constant acceleration of 9.8 m/s^2 when viewing

    things on earth. This is because our measurements on earth usually involve relatively small andclose things [relative to earth's mass and space] and the difference b/w earths effects on these

    objects is negligible.

    Anyways, like all other units of motion, a force can be represented as a Vector. And differentforces have different equations to describe their effects. The result a force has on an object is

    described by Newtons Second Law of Motion:

    where fis the force, m is the objects mass, and a is acceleration. It is usually more helpful to

    represent the equation in this alternate form:

    Knowing this, we can now calculate the acceleration resulting from a force on an object. First wewill get rid of the global PVector acceleration then we will alter the Particle class to look like

    this:

    public class Particle {PVector location;PVector velocity;PVector acceleration;float mass;

    public Particle() {location = new PVector(mouseX, mouseY);//get velocity from direction and speed of mouse movementvelocity = new PVector(mouseX-pmouseX, mouseY-pmouseY);acceleration = new PVector(0, 0, 0);mass = 1;

  • 8/8/2019 Creating a Particle System in Processing

    9/24

    }

    public boolean exist() {velocity.add(acceleration);location.add(velocity);ellipse(location.x, location.y, 10, 10);//when it comes to a rest, get rid of itif (abs(velocity.x) < 0.001 && abs(velocity.y) < 0.001) {return false;

    }acceleration.mult(0); //need to clear accelerationreturn true;

    }

    void applyForce(PVector force) {acceleration.add(PVector.div(force, mass));

    }

    }

    First, note the changes to the Particle class structure:

    1. The particle now keeps track of its own acceleration2. Each particle has a mass, which we are just setting to 1 for convenience3. We added the applyForce(PVector) method4. We are now removing a particle from the system when its velocity falls below a certain level

    Take a look at the applyForce method. There are a few things to note about this method in

    particular:

    1. Notice that this is basically Newtons equation in the second form we presented:a = f/m2. We are calling add() on acceleration b/c we may be applying other forces to this particle. It may

    already have an acceleration value set. But we are also clearing the acceleration after each

    iteration [line 23]. This is important b/c we dont want the force to have an accumulative effect.

    See what happens when you comment out that operation.

    3. Not that this is a Java lesson, but notice that I used the static PVector.div(PVector, float)method rather than using an instance method. The static methods return the results of the

    operations as new instances whereas the instance methods modify the PVector that the

    reference points to. Pay attention to this detail, when to use either should become obvious if

    not already.

    Applying a Force: Friction

    Now we want to actually apply a force to a particle. There are many types of forces and many

    equations to describe their behavior. By far, one of the easiest to understand is a dissipativeforce. It most commonly manifests itself in day to day life in the form offriction but can also be

    used to simulate other phenomena. The equation is:

  • 8/8/2019 Creating a Particle System in Processing

    10/24

    where fis the resulting force, C is a mathematical constant known as the coefficient offriction, and v is the objects velocity. Obviously, the largerC is, the more friction is applied

    and the quicker your object will come to a state of rest. It is usually between 0.0 and 1.0 . Toimplement this, I added this global function:

    void applyDissipativeForce(Particle p, float friction) {PVector f = PVector.mult(p.velocity, -friction);p.applyForce(f);

    }

    Pretty self-explanatory. We take the velocity of the particle that we are applying this force to and

    we multiply it by the coefficient * -1. Lets put all this together. Check out the code in action,then come back and examine the whole source:

    ArrayList particles;

    void setup() {size(400, 400);

    stroke(0);strokeWeight(3);fill(150);smooth();particles = new ArrayList();}

    void draw() {background(255);//only create when mouse movesif (abs(mouseX-pmouseX) > 0.0001) {particles.add(new Particle());

    }

    for (int i = particles.size()-1; i >= 0; i--) {Particle p = (Particle)particles.get(i);// experiment w/ different friction coefficientsapplyDissipativeForce(p, 0.08);if(!p.exist()) {particles.remove(i);

    }}

    }

    void applyDissipativeForce(Particle p, float friction) {PVector f = PVector.mult(p.velocity, -friction);p.applyForce(f);

    }

    public class Particle {PVector location;PVector velocity;PVector acceleration;float mass;

    public Particle() {location = new PVector(mouseX, mouseY);

  • 8/8/2019 Creating a Particle System in Processing

    11/24

    //get velocity from direction and speed of mouse movementvelocity = new PVector(mouseX-pmouseX, mouseY-pmouseY);acceleration = new PVector(0, 0, 0);mass = 1;

    }

    public boolean exist() {//when it comes to a rest, get rid of itif (abs(velocity.x) < 0.001 && abs(velocity.y) < 0.001) {return false;

    }velocity.add(acceleration);location.add(velocity);ellipse(location.x, location.y, 10, 10);acceleration.mult(0);return true;

    }

    void applyForce(PVector force) {acceleration.add(PVector.div(force, mass));

    }

    }

    Applying Another Force: Attraction

    Now we are going to implement a more complicated force, attraction. This force could be used tosimulate gravitational force, without all that Einstein, space-time continuum craziness of course.

    The equation we are going to use is:

    where fis the force, G is the gravitational constant [defines the apparent 'strength'], m1 and

    m2 are the masses of the two bodies in effect, and d is the distance between the two bodies. The

    problem is that this equation computes the magnitude, or the power, of the force; but not thedirection. With the dissipative force, the direction was the opposite of the velocity. This was

    obvious in the equation. The force in this situation however is between the 2 bodies, so naturally,the equation will involve subtracting the positions. Here it is:

    where d is direction and L1 and L2 are the position vectors of the bodies.

    Now we will implement the global function to apply an attractive force on two particles. We will

    also have to modify the Particle class:

    void applyAttractiveForce(Particle a, Particle b, float strength, floatminDistance) {

    PVector dir = PVector.sub(a.location, b.location);

  • 8/8/2019 Creating a Particle System in Processing

    12/24

    float d = dir.mag();if (d < minDistance) d = minDistance;dir.normalize();float force = (strength * a.mass * b.mass) / (d * d);dir.mult(force);if (!b.fixed) b.applyForce(dir);if (!a.fixed) {

    dir.mult(-1f);a.applyForce(dir);

    }}

    public class Particle {PVector location;PVector velocity;PVector acceleration;float mass;boolean fixed;

    public Particle() {

    location = new PVector(mouseX, mouseY);//get velocity from direction and speed of mouse movementvelocity = new PVector(mouseX-pmouseX, mouseY-pmouseY);acceleration = new PVector(0, 0, 0);mass = 1;fixed = false;

    }

    public boolean exist() {if (fixed) {fill(255,0,0);

    } else {velocity.add(acceleration);location.add(velocity);acceleration.mult(0);fill(150);

    }ellipse(location.x, location.y, 10, 10);return true;

    }

    void applyForce(PVector force) {acceleration.add(PVector.div(force, mass));

    }

    }

    I added a fixed property. If the Particle is fixed, it is not affected by outside forces. They alsorender red.

    As for the applyAttractiveForce(), for the most part, it follows our two equations above. Thefirst thing to note is that we are constraining the distance:

    if (d < minDistance) d = minDistance;

  • 8/8/2019 Creating a Particle System in Processing

    13/24

    This is because too small a distance value will create too large a force and the particles will goflying off. Also notice that we are applying equal but opposite forces on each particle:

    if (!b.fixed) b.applyForce(dir);if (!a.fixed) {

    dir.mult(-1f);

    a.applyForce(dir);}

    Now lets look at the whole thing. Check out this code in action then come back and view the

    source:

    ArrayList particles;

    Particle a;

    void setup() {size(800, 600);stroke(0);strokeWeight(3);fill(150);smooth();

    particles = new ArrayList();

    a = new Particle();a.location = new PVector(width/2f, height/2f);a.fixed = true;a.mass = 5.0;

    particles.add(a);}

    void draw() {background(255);for (int i = particles.size()-1; i >= 0; i--) {Particle p = (Particle)particles.get(i);// experiment w/ different friction coefficientsapplyDissipativeForce(p, 0.01);//experiment with strength and minDistance, try a minDistance below 30applyAttractiveForce(a, p, 500f, 50f);if(!p.exist()) {particles.remove(i);

    }}

    }

    void mouseDragged() {particles.add(new Particle());

    }

    void applyDissipativeForce(Particle p, float friction) {PVector f = PVector.mult(p.velocity, -friction);p.applyForce(f);

    }

  • 8/8/2019 Creating a Particle System in Processing

    14/24

    void applyAttractiveForce(Particle a, Particle b, float strength, floatminDistance) {PVector dir = PVector.sub(a.location, b.location);float d = dir.mag();if (d < minDistance) d = minDistance;dir.normalize();float force = (strength * a.mass * b.mass) / (d * d);dir.mult(force);if (!b.fixed) b.applyForce(dir);if (!a.fixed) {dir.mult(-1f);a.applyForce(dir);

    }}

    public class Particle {PVector location;PVector velocity;PVector acceleration;

    float mass;boolean fixed;

    public Particle() {location = new PVector(mouseX, mouseY);//get velocity from direction and speed of mouse movementvelocity = new PVector(mouseX-pmouseX, mouseY-pmouseY);acceleration = new PVector(0, 0, 0);mass = 1;fixed = false;

    }

    public boolean exist() {if (fixed) {fill(255,0,0);

    } else {velocity.add(acceleration);location.add(velocity);acceleration.mult(0);fill(150);

    }ellipse(location.x, location.y, 10, 10);return true;

    }

    void applyForce(PVector force) {acceleration.add(PVector.div(force, mass));

    }

    }

    Hopefully this code is pretty easy to understand. Particle a is the center red particle. We set its

    location to the center of the screen, set it as fixed, then give it a bigger mass. For every particle,we are applying both the dissipative force and the attraction to particle a:

    applyDissipativeForce(p, 0.01);

  • 8/8/2019 Creating a Particle System in Processing

    15/24

    applyAttractiveForce(a, p, 500f, 50f);

    Re-examining our Integration Technique

    If you took the time to closely examine our technique for determining a particles position at

    each frame, you may have noticed some inaccuracies.L

    ets use an analogy. Switch over yourthought process from 2d down to 1d. Lets say we are in a car travelling down a road [iscommonly described as if it is one dimension]. If we know the cars acceleration, and we assume

    that it is constant, we can theoretically calculate the position after a given time with theequation:

    where s is the distance, u is the initial velocity, a is the acceleration, and t is time. So if wehave an initial velocity of0, an acceleration of10 meters per second every second and we travel

    for10 seconds, we end up with a distance of500 meters. Now lets try this with our

    methodology. Here is a python script to simulate our technique:

    t = 0

    vel = 0pos = 0acc = 10

    while (t

  • 8/8/2019 Creating a Particle System in Processing

    16/24

    vel = 30-

    t = 4pos = 100

    vel = 40

    -t = 5pos = 150

    vel = 50-

    t = 6pos = 210

    vel = 60-

    t = 7pos = 280

    vel = 70-

    t = 8pos = 360

    vel = 80-

    t = 9pos = 450

    vel = 90-

    t = 10pos = 550

    vel = 100-

    Position = 550!?!? Why is it so far off? After 10 seconds in the simulation we have already

    drifted off 50 meters from where we should be. Another problem we see is that this error isaccumulating [or compounding]. So as time goes on, our calculations of the particles positions

    will become farther and farther away from the truth. The solution to this problem requires acloser examination of the mathematics behind our process and Newtons Second Law in general.

    In the next article, I am going to attempt to explain how this error occurs and how we can reduceit to a manageable level.

  • 8/8/2019 Creating a Particle System in Processing

    17/24

    Creating a Particle System in Processing: Re-examining our Integration

    Technique

    March 18th, 2010 Code, Java, Processing, Software

    This article is one in a series of articles about particle systems in Processing. To view the first ofthe series, click here.

    In the last article, we discussed forces and left off with questions about our technique fordetermining the particles position at each frame. It turns out that it was wildly inaccurate. In this

    article, I am first going to try to explain the mathematics behind what we are doing and use thatknowledge to expose the source of our problem. Then I am going to try to present a solution.

    Where Does the Problem Come From?

    Recall the equation I presented in the last article which gives us distance given the state of a

    body and a time period:

    This equation gives us an exact distance for the given acceleration, initial velocity, and timeperiod and we used it to measure the error of our technique. So the question remains, why not

    use this equation to determine the particle position at each frame? Well, the problem isunfortunately too complicated for me to explain easily but I am going to try. From my

    understanding, that equation only works when acceleration is constant over time. If you take ahard look at it, this property will become apparent. The equation gives you a distance for a given

    step of time but is not actually a continuous function with respect to time. In other words, youcannot use it to solve acceleration for any given point in time. In a particle system, there may be

    one to many forces acting on a given particle at any time. On top of that, those forces arechanging the acceleration of the particle in seemingly erratic ways. In fact, it is said that the

    function which determines the acceleration with respect to time is well-defined but is actually

    unknown. Therefore, we cannot get an exact value at any given point, we can only approximate

    it. Given that our calculations are approximations, we have to assume there will always be anerror. All we can do is find techniques to make the error manageable.

    Solving Systems Governed by Unknown Functions

    So, how exactly were we solving this unknown function before? Lets step away from our

    particle system for a very brief moment. You may remember from high school maths that youcan solve the integral of a function by integrating that function over an interval when given

    boundary conditions. You may also remember that in certain situations, such as when f(t, y) isunknown or cannot be solved analytically, you can solve these problems by taking an initial

    value and solving in steps. This is called an initial value problem and follows this form:

  • 8/8/2019 Creating a Particle System in Processing

    18/24

    Some tricky manipulating of this formula results in a series which usually looks something likethis:

    So, I am pretty bad at all this maths o_0 but hopefully you are starting to see something here. Inthis series, we are determining the next value [y_n+1] using the current value [y_n] and addingthe differential function. Just like we did with our particles, we found velocity by adding the last

    velocity plus the difference in velocity[acceleration]. Then we did the same for position.Acceleration is a second order derivative so when using this method which solves first order

    diffEQs, we must break it down into two first order derivatives:

    where v is velocity and p is position.

    Now lets try and make sense out of this mess.

    Eulers Method for Solving First Order Differential Equatons

    You may not have known it, but the method we were using before in our code is known as

    Eulers Method and is the defacto, inherent approach to this problem. The only thing I left out isthe time step. The actual process should look something like this:

    velocity.add(PVector.mult(acceleration, h));location.add(PVector.mult(velocity, h));

    where h is the time step in the simulation. As an astute reader, you may realize that the h wasactually accounted for before. It was just assumed to be 1 ;) The common way to make the

    Euler method more accurate is to reduce the time-step [h]. I will explain why in a second, letsjust quickly alter the code to see what happens. Go check it out in action then come back and

    examine the source:

    ArrayList particles;

    Particle a;

    float h = 0.2; //new time step < 1

    void setup() {size(600, 600);stroke(0);strokeWeight(3);fill(150);smooth();

    particles = new ArrayList();

  • 8/8/2019 Creating a Particle System in Processing

    19/24

    a = new Particle();a.location = new PVector(width/2f, height/2f);a.fixed = true;

    particles.add(a);}

    void draw() {background(255);for (int i = particles.size()-1; i >= 0; i--) {Particle p = (Particle)particles.get(i);// experiment w/ different friction coefficientsapplyDissipativeForce(p, 0.01);applyAttractiveForce(a, p, 5000f, 50f);if(!p.exist()) {particles.remove(i);

    }}

    }

    void mouseDragged() {particles.add(new Particle());

    }

    void applyDissipativeForce(Particle p, float friction) {PVector f = PVector.mult(p.velocity, -friction);p.applyForce(f);

    }

    void applyAttractiveForce(Particle a, Particle b, float strength, floatminDistance) {PVector dir = PVector.sub(a.location, b.location);float d = dir.mag();if (d < minDistance) d = minDistance;dir.normalize();float force = (strength * a.mass * b.mass) / (d * d);dir.mult(force);if (!b.fixed) b.applyForce(dir);if (!a.fixed) {dir.mult(-1f);a.applyForce(dir);

    }}

    public class Particle {PVector location;PVector velocity;

    PVector acceleration;float mass;boolean fixed;

    public Particle() {location = new PVector(mouseX, mouseY);//get velocity from direction and speed of mouse movementvelocity = new PVector(mouseX-pmouseX, mouseY-pmouseY);acceleration = new PVector(0, 0, 0);mass = 1;

  • 8/8/2019 Creating a Particle System in Processing

    20/24

    fixed = false;}

    public boolean exist() {if (fixed) {fill(255,0,0);

    } else {velocity.add(PVector.mult(acceleration, h));location.add(PVector.mult(velocity, h));acceleration.mult(0);fill(150);

    }ellipse(location.x, location.y, 10, 10);return true;

    }

    void applyForce(PVector force) {acceleration.add(PVector.div(force, mass));

    }

    }

    All I did was alter the integration part, added the h float at 0.2, and increased the strength to 5000

    to speed things up a little. What you should have noticed is that it has gotten a lot slower and it

    should be obvious why: Our framerate is the same but we are stepping ahead in the simulation insmaller steps of time.

    What you probably did not notice is the huge increase in accuracy. To prove this, lets re-implement our python script experiment from the last article and compare it with the exact

    results again. This time we will have a time step-size of 0.1:

    t = 0h = 0.1

    vel = 0pos = 0acc = 10

    while (t

  • 8/8/2019 Creating a Particle System in Processing

    21/24

    t = 0.1pos = 0.1

    vel = 1.0-

    t = 0.2

    pos = 0.3vel = 2.0-

    t = 0.3pos = 0.6

    vel = 3.0-

    t = 0.4pos = 1.0

    vel = 4.0-

    t = 0.5pos = 1.5

    vel = 5.0-

    .

    .

    .-

    t = 9.6pos = 465.6

    vel = 96.0-

    t = 9.7pos = 475.3

    vel = 97.0-

    t = 9.8pos = 485.1

    vel = 98.0-

    t = 9.9pos = 495.0

    vel = 99.0-

    t = 10.0pos = 505.0

    vel = 100.0

    Position = 505. You may remember that using these initial values with our equation:

  • 8/8/2019 Creating a Particle System in Processing

    22/24

    yielded an exact end position of500. Now we are only offby 5 whereas with a time-step of 1we were offby 50! This should show you that the error for this method is close to [i think?]:

    There is a mathematical way to determine the real error but we arent going to go into it becausewe will be abandoning this method soon and it is too complicated for the little value it providesus. If you really want to know, check out the Wikipedia article on Eulers method.

    Why does a Smaller h Yield More Accurate results?

    The question arises, why is it more accurate? The answer may help you better understand what is

    happening. Lets look at a graphic representation of the Euler method in action:

    Graphical representation of Euler's method (Source: Wikipedia)

    Pretend that the blue line is our unknown but well-defined function in which the acceleration is

    the dependent variable and that A0, A1, A2, A3, and A4 are the acceleration values we calculate.Essentially, at each step, we know the derivative [the tangent to the curve] and multiply it by the

    time step, then add it to the current A value to guess the next value. At that point, we assume weare at the correct spot and do this again and again and again. You can now see why the error

    accumulates. We are basically walking a dark path using a slow strobe light. Now imagine thatthe A values were taken in smaller intervals [the strobe light is blinking faster] and you can see

    that we would be closer to the blue line [exact solutions]. But if you took a bigger step size, youwould be farther away from the exact values. The following pictures illustrate the point perfectly.

    The red line is the exact solution and the blue is the approximation:

  • 8/8/2019 Creating a Particle System in Processing

    23/24

    big step of h

    medium sized step of h

    small step of h

  • 8/8/2019 Creating a Particle System in Processing

    24/24

    tiny step of h

    Here is the source of these photos.

    So as h gets smaller, our approximated curve inches closer to the exact curve.

    Picking a NewMethod

    Where do we go from here? Well, we have determined that the Euler method is just not reallyfeasible. Sure, it may have worked out for our little examples but we can achieve more stability

    and accuracy with some other methods. Plus we cant pump up the framerate enough to get arealistic speed. It just doesnt look believable. In the next article, I am going to show you how to

    implement the Runge-Kutta methods, particularly the Fourth Order Runge-Kutta method. I amalso going to try to explain the differences between implicit and explicit integration.