Particle System – Collisions

It only took two weeks, but I sorted out (almost) all the kinks with bullet physics. Check it out:

Building bullet is kinda roundabout, but once I built the libraries and separated out the necessary include files, I was good to go with integrating it into any of my projects. The basic tutorial app is pretty straightforward. Unfortunately, the documentation of what I would consider to be common functionality such as toggling collisions on objects, enabling friction, etc. was pretty lacking. Part of the issue was this is the first physics engine I’ve worked with and I wasn’t quite sure what to expect the engine to do for me, and what I had to do myself. I was disappointed that the physics engine didn’t seem to integrate both the spring and “orbital decay” forces I’ve modeled, or even better a “magnetic” force. But all is well I guess, because my work would have gone to waste if they were implemented by bullet. To be fair, there is a relative new “spring” constraint in bullet, but it seems a bit heavy handed to achieve the effect I’m going for.

I encountered a few issues with bullet. I was disappointed to find out that simply resetting the collision group of an object does not seem to disable collisions, but rather results in unintuitive static placement of that object. In my experimentation, I was only able to truly disable collisions for a “dead” particle by removing it from the dynamic world entirely, and then adding it again when the particle was re-spawned. The issue was presenting itself as what looked like a failing “new” which caused me to think I was running out of memory somehow. It turns out, all my dead particles were being added to the world in the exact same position, and although their collision flags were set so that they would not collide with other particles, they were not taking effect. Somehow, the calculations used to deal with multiple simultaneously colliding objects blows up when too many objects collide/overlap, so I was able to simulate on the order of 100 particles, but not on the order of 1000. That was the hardest bug to track down, and I don’t think my fix is too elegant for now, so I’ll have to scour the bullet forums for some suggestions.

I also stumbled across a few interesting topics. The most interesting was tradeoff between sending quaternions to the GPU and doing the rotation calculations in a shader, or computing the rotation matrices on the host to cut down on work the shader must do. Apparently, it is highly discouraged to send quaternions to the GPU and have the shader perform the quaternion rotation. Execution units on GPUs are naturally tuned to handle matrix calculations exceptionally fast, and the rule of thumb is that if you’re going to use quaternions (I had to, it’s what bullet produces), then you should convert them back to rotation matrices as soon as the quaternion representation is through being ‘convenient’. However, there may be an exception to this rule with instanced geometry. Because you will send unique rotation information for each instance, and a rotation matrix consumes 4x the space of a quaternion, then there may be a gain due to bandwidth by sending quaternions. There is likely an inflection point where the bandwidth gains of sending quaternions outweigh the computational gains of sending rotation matrices, based on the number of instanced particles, and the number of vertices used for each particle.

I’d also like to credit this google code site which has a few nice quaternion gems, one of which was used in my shader: http://code.google.com/p/kri/wiki/Quaternions

The simple quaternion rotation function I employed is reproduced below, but all credit goes to the link above:

//rotate vector
vec3 qrot(vec4 q, vec3 v)       {
        return v + 2.0*cross(q.xyz, cross(q.xyz,v) + q.w*v);
}

Leave a Comment