Create a swarm around an object

Nickert
Posts: 25
Joined: Sat Dec 29, 2012 7:20 pm

Create a swarm around an object

Post by Nickert »

Hey guys, I'd like to create a swarm of rigidbodies around another body. What would be a nice way to achieve this?

Now I have got something like

for(b : bodies in the swarm){
b->applyCentralImpulse(force/(distance*distance));
}

Which creates an okay pulling motion, but it just crashes through the swarm.. they don't stick, they just swing back and forth and it's very unstable. I'm not sure how to solve this. Any suggestions?
psionprime
Posts: 4
Joined: Sat Mar 16, 2013 10:43 pm

Re: Create a swarm around an object

Post by psionprime »

Does it have to be an interactive swarm or just a visual ? If it is just a visual then I can think of a number of ways for the effect. Perhaps it you give a description of what the end result should be close to we can work it out.
Nickert
Posts: 25
Joined: Sat Dec 29, 2012 7:20 pm

Re: Create a swarm around an object

Post by Nickert »

The effect I'd like is pretty much this: http://youtu.be/pt_n_V_Yl9Y?t=1m28s . I failed to do this so far because I can't figure out how to get to slow down.

Problem:
Begin:

Code: Select all

-------------------[attractor]-------------------[object]
After a bit of attraction:

Code: Select all

-------------------[attractor]-----[object]--------------
And some later:

Code: Select all

[object]------------[attractor]---------------------------
Rinse, repeat :(. I want them to cluster at the attractor, not blow past it. And this is when the object is on a collision course with it. If it's not, it'll just fly right over.
psionprime
Posts: 4
Joined: Sat Mar 16, 2013 10:43 pm

Re: Create a swarm around an object

Post by psionprime »

That video has comments that state how they did it....
We use a kinematic object, with no contact response to detect which objects reside inside the blast radius.

In the internal physics tick callback we check whether one of the affected bodies is the kinematic object. If it is, we apply an impulse to it based on the distance to the center. In case of the explosions the impulse is applied to the object relative to the contactpoints (using ApplyImpulse). That didn't work very well for the attractors (instable), so we applied the impulse to the center of the object (using ApplyCentralImpulse).
So, there you go.
Nickert
Posts: 25
Joined: Sat Dec 29, 2012 7:20 pm

Re: Create a swarm around an object

Post by Nickert »

I'm doing that now, but I can't get the swinging motion to dissapear.

Here's some sample code of what I'm doing now.

Code: Select all

void Planet::update(float const dt, Player& player, motor::Scene& scene, btDynamicsWorld& physics){
	for(auto& city : cities){
		for(auto& h : city->get_houses()){
			if(h->is_being_beamed){

				auto const player_position = player.get_model()->get_position();
				// auto const player_physical_body = player->get_model()->get_physical_body();
				auto const house_position = h->get_position();
				auto const house_physical_body = h->get_physical_body();

				float const distance = length(player_position - house_position);
				auto const unit_vector = normalized(player_position - house_position);

				// ! Quadratic falloff attraction
				auto const gravitational_attract = [&](float const power) -> moggle::vector3<float> {
					auto const force = unit_vector * (power/(distance*distance)) * dt;
					return force.slice<0, 3>();
				};

				// ! inverse-quadratic falloff (i.e. pulls harder when things are further away)
				auto const inverse_gravitational_attract = [&](float const power){
					auto const force = unit_vector * (power*distance) * dt;
					return force.slice<0, 3>();
				};

				auto const attract = inverse_gravitational_attract;
				// gravitational_attract can use a power of 10000000000
				// float const power = 10000000000;
				// inverse one can use a far lower power
				float const power = 100;

				float const ideal_distance = 15.0f;
				if(distance > ideal_distance){
					house_physical_body->applyCentralImpulse(convert<btVector3>(attract(power)));
				}
			}
		}
	}
}
I understand why the swining motion is there, I'm creating it, but I'm not sure what a nice way is to stop the swinging from happening. (The swinging I described in my first post, if it's not clear I'll gladly clarify)
anthrax11
Posts: 72
Joined: Wed Feb 24, 2010 9:49 pm

Re: Create a swarm around an object

Post by anthrax11 »

Perhaps you can apply linear damping to the bodies as they get near to where they need to stick.

Code: Select all

if(distance > ideal_distance){
               house_physical_body->applyCentralImpulse(convert<btVector3>(attract(power)));
               house_physical_body->setDamping(0, 0);
} else {
               house_physical_body->setDamping(0.5f, 0);
}
Of course you can tweak the damping coefficient and how exactly you apply it, but you get the idea. :)
Nickert
Posts: 25
Joined: Sat Dec 29, 2012 7:20 pm

Re: Create a swarm around an object

Post by Nickert »

Ah yes thanks! That was what I was looking for. How stupid. Thanks man! :)