Cinder++::Cinder Creative Coding Cookbook 5, Particles

Bookmark and Share

Chapter 5 and 6 in Cinder Creative Coding Cookbook provide a series of recipes to simulate and display particles. In chapter 5 yo have recipes from simple 2D systems to springs, repulsion, attraction forces, particles flying in the wind, flocking behavior, particles sound reactive, particles to processed images. And the chapter 6 is focused in rendering and texturing particle systems. Since particle systems and physics simulation are hot issue in the architectural field and computational design. I will not base this post in the book’s code, instead I’m going to make an introduction to this theme.

PARTICLE SYSTEMS
Particle systems is a computer graphic technique that uses a number of graphic objects to simulate some physical phenomena from the real world. This technique has been extensively developed for video game and computer animations. Is possible to find examples in simulate chaotic systems, chemical reactions, collisions of solid objects, fire and water simulation, clouds, flocking, and a long etc.

MOTION
The first thing to do it is a mathematical model, based on Newton physics,: Velocity, acceleration, friction and mass. If we start from a circle, is necessary define its location. obviously the radius too. Lets imagine our particle is represented by a static circle of radius 50px.

In that case we should have something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void physics_OneApp::setup()
{
	x = getWindowWidth()/2;
	y = getWindowHeight()/2;
}
 
void physics_OneApp::draw()
{
	// clear out the window with black
	gl::clear( Color( 0, 0, 0 ) ); 
 
	//x and y location coordinates.
	gl::drawSolidCircle(Vec2f(x, y), 50, 50);
}

Nevertheless we can change the position of our particle modifying its coordinates. The movement of the particle will be defined by the velocity and direction. If we modify the position of our particle in the X coordinate, the particle is going to move in that axis (we have the direction). So the velocity is going to be defined of the step size per each frame in the window. Lets see our mathematical model: x = x + speed. Or by coding will be: x += speed;

This code display our particle floating and bouncing into the window. I use speed2 *= -1; to invert the speed and direction to simulate the particle bounce in the windows edge.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void physics_OneApp::setup()
{
	rad = 20;
	x = getWindowWidth()/2;
	y = getWindowHeight()/2;
 
	speed1 = 2.0f;
	speed2 = 3.0f;
 
}
 
void physics_OneApp::update()
{
	x += speed1;
	if(x > getWindowWidth() - rad || x - (rad/2) < 0)
	speed1 *= -1;
 
	y += speed2;
	if(y > getWindowHeight() - rad || y - (rad/2) < 0)
	speed2 *= -1;
}
 
void physics_OneApp::draw()
{
	// clear out the window with black
	gl::clear( Color( 0, 0, 0 ) ); 
 
	//x and y location coordinates.
	gl::drawSolidCircle(Vec2f(x, y), rad, 50);
}

Now we have a basic particle motion, and it’s time to continue with the particle system. If we want to create two or more particles, and each with their own position, speed and size, it would be necessary to package up all of them into its own class to make it easier to access each particle individually. Nevertheless if we need to deal with thousands of particles is necessary to think how to face up the problem. Based on this tutorial we are going to create 2 classes the first class is to define the particle itself. and it`s look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "Particle.h"
#include "cinder/Rand.h"
#include "cinder/gl/gl.h"
#include "cinder/app/AppBasic.h"
 
using namespace ci;
 
Particle::Particle()
{
}
 
Particle::Particle(Vec2f pos)
{
	mPos    = pos;
	mDir    = Rand::randVec2f(); //random direction.
	mSpeed = Rand::randFloat(5.0f); //random speed.
	mRad = 3.0f;
}
 
void Particle::update()
{
        //move the particle in the mDir direction by mSpeed velocity
	mPos += mDir * mSpeed; 
}
 
void Particle::draw()
{
        //draw the particle
	gl::drawSolidCircle(mPos, mRad); 
}

The second class is to control all the particle system. Here is where creates the particles array, and where we change the direction of the particle when collided to the windows edge. The class look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "cinder/app/AppBasic.h"
#include "cinder/Rand.h"
#include "cinder/Vector.h"
#include "ParticleController.h"
 
using namespace ci;
using std::list;
 
ParticleController::ParticleController()
{
}
 
void ParticleController::update()
{
	for(list<Particle>::iterator p = mParticles.begin(); p != mParticles.end(); ++p)
	{
		p->update();
	}
}
 
void ParticleController::draw()
{
	for(list<Particle>::iterator p = mParticles.begin(); p != mParticles.end(); ++p)
	{
		p->draw();
	}
}
 
void ParticleController::addParticles(int amt)
{
	for(int i = 0; i < amt; ++i)
	{
		float x = Rand::randFloat(app::getWindowWidth());
		float y = Rand::randFloat(app::getWindowHeight());
 
                //add a particle at the end of the array
		mParticles.push_back(Particle(Vec2f(x, y))); 
	}
}
 
void ParticleController::detectCollisions()
{
	//detect the border collisions...
	float xpos, ypos;
	for(list<Particle>::iterator p = mParticles.begin(); p!= mParticles.end(); ++p)
	{
		xpos = p->mPos.x;
		ypos = p->mPos.y;
 
                //if the particle coordinates collides with the window edge, 
                //thus change the particle direction.
		if((xpos > app::getWindowWidth() - p->mRad  || xpos - p->mRad < 0) ||
                  (ypos > app::getWindowHeight() - p->mRad || ypos - p->mRad < 0))
		p->mDir = Rand::randVec2f();
	}
}

In the main class include the ControllerParticle header and initialize the class. set the number of particles you want floating. The final Result.

SOURCE:
Simple particle
Particle System

Leave a Reply