iphone bullet stepSimulation issue

webjeff
Posts: 15
Joined: Tue Dec 16, 2008 1:46 am

iphone bullet stepSimulation issue

Post by webjeff »

I constructed a test app where I am launching a box outward (think of a cannon shooting). I am applying the same force in the same direction, however I can do this 10 times in a row and the box lands in different spots. Reading some stuff, it seems its not deterministic if I call step with something like mDynamicsWorld->stepSimulation(ms/1000.0f,5); Not a problem, but the problem is sometimes, the framerate drops (I think this is the issue), but the framerate hiccups slightly and then my box gets launched WAAAAY past the point it should have been.

I tried making the substeps large like 20 or so, but that didn't help.

I tried to fix the delta with stepSimulation(1/24,7) and I think its working, but I don't want to do this, because running on the pc, it acts completely different obviously because the pc is running at 60hz no problem.

So, I am now confused on what I should do. My iphone game can't afford the occasional hiccups and have it look like the object had too much force applied, it won't make sense.

Any ideas?!?!?!?

Thanks!
Jeff.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: iphone bullet stepSimulation issue

Post by Erwin Coumans »

It seems its not deterministic if I call step with something like mDynamicsWorld->stepSimulation(ms/1000.0f,5);
Actually this should be deterministic, because the internal substep is fixed to 60 hertz, no matter you pass in a variable deltaTime (ms/1000).

It might be best to apply the force within the tick callback, to make sure not to accumulate the force:

Code: Select all

The prototype function for the callback is this:

typedef void (*btInternalTickCallback)(const btDynamicsWorld *world, btScalar timeStep);
and the appropriate call to add it to the world is

void btDynamicsWorld::setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0);
Your code to use it in its simplest form might look something like this:

void myTickCallback(const btDynamicsWorld *world, btScalar timeStep) {
    printf(“The world just ticked by %f seconds\n”, (float)timeStep);
}

// And then somewhere after you construct the world:

mWorld->setInternalTickCallback(myTickCallback);
Also, there are some ways to optimize the iPhone build:
1) don't 'compile for thumb', use -O3 or -O3, and add the "-fno-regmove" flag (one word) in Xcode Build configuration, here are my User Defined settings:

Code: Select all

GCC_OPTIMIZATION_LEVEL = 2
GCC_THUMB_SUPPORT = NO
OTHER_CFLAGS = -fno-regmove
2) add some VFP optimizations for matrix class
3) disable the following lines in src/LinearMath/btScalar.h:

Code: Select all

Oolong Engine/Bullet/src/LinearMath/btScalar.h

/// older compilers (gcc 3.x) and Sun needs double version of sqrt etc.
/// exclude Apple Intel (i's assumed to be a Macbook or new Intel Dual Core Processor)
#if defined (__sun) || defined (__sun__) || defined (__sparc) || (defined (__APPLE__) && ! defined (__i386__))
//use slow double float precision operation on those platforms
#ifndef BT_USE_DOUBLE_PRECISION
#define BT_FORCE_DOUBLE_FUNCTIONS
#endif
#endif
Can you share some profile dump, to see where performance is going? Use CProfileManager::dumpAll(), after a slow stepSimulation call.
Hope this helps,
Erwin
webjeff
Posts: 15
Joined: Tue Dec 16, 2008 1:46 am

Re: iphone bullet stepSimulation issue

Post by webjeff »

Erwin,

Thanks for your response, I tried the callback with similar results. After a bit more testing I think I have figured out why its happening. Right before the applyforces call, I want the projectile to launch from a specified height (not off the ground). So I am setting the world matrix to a translated matrix up 3 units. Then I apply the force, its done like...

mRigidBody->activate();
mRigidBody->getMotionState()->setWorldTransform(up3units_transform);
mRigidBody->setWorldTransform(up3units_transform);
mRigidBody->clearForces();
mRigidBody->applyCentralForce(btVector(force.x,force.y,force.z));

When I see the object fly in the same rotation, it lands in the same spot. However, I notice sometimes it is rotating differently in the air, almost like the force wasn't applied to the object in my initial state.

Is it possible the update is moving the object down a hair (because of gravity) and then appling force to it?? Any thoughts if I can get this acting the same way every time?

Thanks!
Jeff
webjeff
Posts: 15
Joined: Tue Dec 16, 2008 1:46 am

Re: iphone bullet stepSimulation issue

Post by webjeff »

One more thing...

I can't get the simulator to act like the iphone. I still believe it has to do with the framerate, since the simulator is doing 60 fps and the iphone is around 24-30 fps. But the iphone ball goes much further distance, than the simulator, I tried putting 500 substeps with no difference (in distance difference). This doesn't make any sense! Any clues?!? I don't think it has to do with the performance in bullet, Bullet itself seems to be running good, I already had most of those optimizations in there already. Just this bug is killing me!! :)

Thanks

Jeff.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: iphone bullet stepSimulation issue

Post by Erwin Coumans »

mRigidBody->activate();
mRigidBody->getMotionState()->setWorldTransform(up3units_transform);
mRigidBody->setWorldTransform(up3units_transform);
mRigidBody->clearForces();
mRigidBody->applyCentralForce(btVector(force.x,force.y,force.z));
You need to apply forces within a tick callback to make sure the applied force is synchronized with the internal simulation substep. And don't accumulate the 'force' outside of this callback. Is above code called from within a tick callback?

I assume the problem already happens at the very start, right?
It requires a bit of work to 'reset' the simulation to get the same result. There is more involved to 'reset', apart from simply putting the objects back at the same position, and reset the velocity.
See the implementation in Bullet/Demos/OpenGL/DemoApplication.cpp, method "void DemoApplication::clientResetScene()".

Thanks,
Erwin