Advertisement

Bizarre Bullet Physics Behaviour

Started by March 19, 2019 12:58 AM
4 comments, last by OandO 5 years, 4 months ago

I've encountered a very strange bug in a project that I can't explain. I'm using Bullet Physics under my own C wrapper, a simple entity component system of my own design, where entities are allocated objects, each with a single fixed component (For things like transformation and whether or not it should be replicated over a network), and a number of other, variable components. Components are allocated in entirely separate arrays, rather than inside the entity itself. I've created a simple test scene with a handful of static bodies, and a dynamic, rigid body for a character, implemented some simple walking and jumping. My simulation runs at a fixed 60Hz, with physics substeps at 240Hz, and everything works fine.

Then I came to add an extra field to the fixed entity component structure. A single integer to make networking the exact "type" of entity simpler (Rocket, character, vehicle, etc.). I should add that I'm testing this on a single machine, not over a network at the moment. I put this field just above the transformation data, recompiled everything and ran it. The physics simulation was running at about half-speed; walking, jumping, falling, all running slowly. I had the game print out the game timer every frame, along with the frame number and the delta time being fed into world->stepSimulation (and double checked that with a breakpoint on that function), and everything was correct. Additionally, there's a cooldown period on jumping that requires you to have been on the ground for 0.25 seconds before jumping again, and that behaved properly. The only thing that was affected was the physics simulation.

Next step, I moved the "type" field to the very bottom of the fixed component structure. Suddenly everything goes back to normal. I've scoured every usage of the fixed component, making sure I've not done anything weird like accessing a value directly from its memory address, which I haven't. Also perhaps worth mentioning that Bullet doesn't ever read / write directly from / to this component, instead I pull values after the simulation step is complete.

I realise this is a difficult problem to diagnose without source code, but it's a somewhat large project, and at the moment I'm really just looking for something that could point me in the right direction. It's not currently critical, everything seems to be working fine with the "type" field at the bottom, but if anyone has encountered something like this, it'd be good to hear from you.

Sounds like your field moved other fields in the same structure, and those other fields were no longer available in time for usage due to caching strategies or limits.

I recently found the "What every programmer should know about memory" article by Ulrich Drepper (2007), which is a detailed explanation how all the internals of a CPU work (or rather, worked, at that time), and how that affects execution of the program that you are running. He also explains how to measure and analyze these things.

This may give you a few pointers how to check the behavior, perhaps.

Advertisement

The fields following it aren't accessed until considerably after Bullet's world->stepSimulation function returns, though. Could that still be the reason? This is considerably outside of my expertise, and it's going to take me a while to get through a 114 page article!

On 3/19/2019 at 2:58 AM, OandO said:

A single integer <...> I put this field just above the transformation data

This is a far stretched guess, but perhaps SSE/AVX instructions are being used on transformation data? Putting integer before transformation data could have broken the alignment.

This same bug reared its head in a slightly different place, and I'm in the process of tracking down the root cause. So far the good news is that it's not a bug in Bullet, or anything to do with memory alignment or caching. The bad news is it's a fault somewhere in my own code that was causing rigid bodies to be added to the world twice, and therefore being updated twice in the physics step. Ironically I was complaining that the simulation was running too slowly, when in reality it was running too fast, and I had scaled my movement speed around the broken version.

Many thanks to those who tried to help, but it turns out I'm just inept in some way.

This topic is closed to new replies.

Advertisement