particles, wind and following a leader

Hi,

I’m trying to create this kind of motion of the leaves rotating in a tube and also following a path:
http://www.youtube.com/watch?v=nJam5Auwj1E

I’m rotating the particles/leaves simple by using cos(x)/sin(y) around a certain radius. This looks nice and works okay. Though I don’t understand how I can add the forces which make all particles follow the leader like in that movie.

Here is my code. I’ve got a “Dust” class which is a particle and a DustCloud which is the group of particles:
Dust

  
#include "Dust.h"  
  
Dust::Dust(float fX, float fY, float fZ) {  
	pos.set(fX, fY, fZ);  
	angle = 0;  
	angle_inc = ofRandom(0,0.08);  
	radius = ofRandom(60,90.0f);  
	start_x = move_pos.x = fX;  
	start_y = move_pos.y = fY;  
	start_z = fZ;  
	move_pos.z = fZ;  
	vel = ofRandom(0.05,0.08);  
}  
  
float Dust::getStartZ() {  
	return start_z;  
}  
void Dust::update() {  
	vel += accel;  
	vel.limit(30);  
	move_pos += vel;  
	//pos.z += vel.z;  
  
	pos.z = move_pos.z;  
	angle += angle_inc;  
	pos.x = move_pos.x + cos(angle) * radius;  
	pos.y = move_pos.y + sin(angle) * radius;  
}  
  
void Dust::draw() {  
	glPushMatrix();  
	ofSetColor(0xFF00CC);  
	glTranslatef(pos.x, pos.y, pos.z);  
	ofCircle(0,0,4);  
	glPopMatrix();  
}  
  
  
void Dust::setPosition(ofxVec3f oPos) {  
	move_pos = oPos;  
}  
  
void Dust::arrive(Dust* pParent) {  
	/*  
	ofxVec3f target = pParent->getPosition();  
	ofxVec3f desired_vel = target - pos;  
	float dist = desired_vel.length();  
	desired_vel.normalize();  
	float max_vel = 80;  
	float arrive_dist = 40;  
	if (dist <= arrive_dist) {  
		desired_vel *= ((max_vel * dist / arrive_dist));  
	}  
	else {  
		desired_vel *= max_vel;  
	}  
	if (dist > 10) {  
		desired_vel -= vel;  
		addForce(desired_vel);  
	}  
	*/  
}  
  
ofxVec3f Dust::getPosition() {  
	return move_pos;  
}  
  
void Dust::addForce(ofxVec3f oForce) {  
	accel += oForce;  
}  
  

DustCloud

  
  
#include "DustCloud.h"  
  
DustCloud::DustCloud() {  
	float z = 0;  
	angle_z = 0;  
  
	for(int i = 0; i < 60; ++i) {  
		dusts.push_back(new Dust(  
			ofRandom(300,320)  
			,ofRandom(300,330)  
			,z  
		));  
		if (i > 0) {  
			springs.push_back(new DustSpring(  
				dusts[i]  
				,dusts[i-1]  
				,20  
			));  
		}  
		z-= ofRandom(10,30);  
	}  
  
}  
  
void DustCloud::update() {  
	for (int i = 0; i < dusts.size(); ++i) {  
		dusts[i]->update();  
	}  
}  
  
vector<Dust*> DustCloud::getDusts() {  
	return dusts;  
}  
void DustCloud::draw() {  
	for(int i = 0; i < dusts.size(); ++i) {  
		dusts[i]->draw();  
	}  
}  
  
  

Roxlu

1 Like

hi roxlu,

the way id approach it would be to first work out the motion of the leader. so this would be a directional vector in the direction it is travelling.
on every frame you want to move the leader forward as you’ve done,
pos += vel

id then keep a stack of the last 100 positions in a list as they are the easiest to work with, especially when you reach your max capacity of ~100 you can remove the last pos and add a new pos. so you always have the last 100 points.

for all leaves that are trailing the leader, id first pick a random position in the list for each leaf to follow.
so say your vector list of leader positions is called = ‘posBuffer’
one leaf can follow posBuffer[20] and another one can follow posBuffer[50]
this will make sure that they are always spaced out and following the same path as the leader has taken.

i’d also throw in a little easing in there too…
so for example, for each leaf you’d do,
leafPos.x += ( posBuffer[20].x - leafPos.x ) * 0.3 // between 0-1
leafPos.y += ( posBuffer[20].y - leafPos.y ) * 0.3 // between 0-1
leafPos.z += ( posBuffer[20].z - leafPos.z ) * 0.3 // between 0-1

easing will give you a slight lag behind the position each leaf is chasing and it will also smooth out the motion.

then as the final step, you can rotate each leaf around its center.
and you can also rotate its position in a radius around the direction vector of the leader’s trail.

L.

Hi Julapy,

Thanks a lot! I’ll try it. If I understand it correctly, I should first reposition the leaf using the leaders position and than add the rotation to it?

Roxlu

yeah that’s the way id do it…
once you have the leaf trailing behind the leader where you want it, you can then apply rotations to it.