FPS independent physics

kenny.bsp

05-06-2007 20:57:06

I've just started using NxOgre and seem to have a problem ..
If I run the simulation with no fps limit it's all fine .. but when I firt tried to record it all with fraps everything moved a lot slower. Already tried to search the forum but all I found didn't help me .. maybe I'm doing something wrong.
Thanks in advance.

Chaster

05-06-2007 21:39:07

I've just started using NxOgre and seem to have a problem ..
If I run the simulation with no fps limit it's all fine .. but when I firt tried to record it all with fraps everything moved a lot slower. Already tried to search the forum but all I found didn't help me .. maybe I'm doing something wrong.
Thanks in advance.


Make sure you're stepping the simulation at a fixed frame rate (say, 60hz) which is independent of the rendering frame rate.

kenny.bsp

05-06-2007 23:21:27

and how would I do that ?
I've tried
mScene->setTiming();
with different settings
but there is still difference in simulation and it's huge

Chaster

05-06-2007 23:30:27

and how would I do that ?
I've tried
mScene->setTiming();
with different settings
but there is still difference in simulation and it's huge


I'd love to tell you how, but I myself don't know how since I'm not yet an Ageia developer (still waiting for my developer license/access) so I don't know how the PhysX handles stepping.

I only made the suggestion because (having worked with many physics engines in the past) your problem sounds like a classic case of not having a constant (and reasonable) time step.

A lot of people, when they first start out with a physics engine, make the mistake of just passing in whatever time step the rendering took per frame, and that varies a lot obviously. For a physics engine to produce good results, it needs a constant time step (most games try to go at least 60 hz). This is usually done by substepping a rendering frame if the rendering is going at less than the desired physics stepping rate... But as for how this is exactly done in PhysX, I can't tell you because I don't (yet) have access to the SDK/API.. Sorry..

Chaster

kenny.bsp

06-06-2007 00:00:18

Thanks for your reply.
Probably i'm doing something wrong ..
But for now I will try to come up with some kind of calculation based on frame rendering time, so the force applied is about the same.
Hope someone can post some examples of hoe they worked around it.
For more info :
Every frame i call
player->addForce(pCamRoot->getOrientation() * Ogre::Vector3(0,0,-200));
and here's a vid of how it looks in"game":
http://youtube.com/watch?v=6Ni_ORFZVDs

betajaen

06-06-2007 00:40:36

Try:

player->addForce((pCamRoot->getOrientation() * Ogre::Vector3(0,0,-200)) * timeSinceLastFrame);

kenny.bsp

06-06-2007 11:17:29

Try:
player->addForce((pCamRoot->getOrientation() * Ogre::Vector3(0,0,-200)) * timeSinceLastFrame);

Tried, doesnt work.
If I multiply it by time since last frame the pig doesnt move at all.

luis

06-06-2007 11:23:02

If I multiply it by time since last frame the pig doesnt move at all.
it should work...
did you check the value of timeSinceLastFrame var ? are you calling the 'addForce' every frame ?

In my opinion you should do two things, multiply it by timeSinceLastFrame and call the 'addForce' in a fixed timing.

Read this post:
http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=4518

kenny.bsp

06-06-2007 22:25:27

timeSinceLastFrame is mostly 0.001 with FPS=800 ... so this means that if i multiply the force by the time since last frame there's nothing left from
player->addForce((pCamRoot->getOrientation() * Ogre::Vector3(0,0,-200)) * timeSinceLastFrame);
-200 on high framerates ...
I can change the force amount to a bigger value like 200000 for example, but this seems kinda wrong ..
And it is wrong .. now I get pig that moves faster at lower framerates :D damn :D
Now I'm confused
btw I dont get how to call the 'addForce' in a fixed timing.

luis

07-06-2007 08:30:51

btw I dont get how to call the 'addForce' in a fixed timing.

you have to do something like this (on each frame):


if( mAccumTime >= 0.0666667 ) // ~15Hz
{
player->addForce((pCamRoot->getOrientation() * Ogre::Vector3(0,0,-200)) * mAccumTime );
mAccumTime = 0.0;
} else mAccumTime += event.timeSinceLastFrame;


This will fix your FPS problem ;)

ELO

07-06-2007 10:55:18

You should keep the time that passed over the timestep. Then you have a more precise timestep.
if( mAccumTime >= 0.0666667 ) // ~15Hz
{
player->addForce((pCamRoot->getOrientation() * Ogre::Vector3(0,0,-200)) * mAccumTime );
mAccumTime -= 0.0666667;


I am running PhysX/NxOgre at a fixed timestep independent from Ogre. If somebody ist interested, i could post some code hiere.

betajaen

07-06-2007 11:24:18

I would like to see it ;).

I'm experimenting with it as well, which also keeps the extra time per time step:

void Scene::simulate(NxReal time) {
mThisHz += time;

if (mThisHz < mTimeStep)
return;

mRenderFrame = true;

mScene->simulate(mTimeStep);
mScene->flushStream();

if (mThisHz > mTimeStep)
mThisHz = mThisHz - mTimeStep;
else
mThisHz = 0;

...
}


This method also makes sure the nodes, and meshes controlled by NxOgre are rendered every 1/60th of a second. Quite a performance boost, I would imagine with cloth, fluids or soft bodies.



Implementing the new code in the NxOgre core without upsetting the majority of people will be tricky, but I have a cunning plan that involves function pointers. :D

luis

07-06-2007 12:07:20

I am running PhysX/NxOgre at a fixed timestep independent from Ogre. If somebody ist interested, i could post some code hiere.

yes ! I really want it. I created this thread:
http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=4565

to avoid hijacking this one ;)

ELO

07-06-2007 12:22:25

This is how we managed our mainloop.
Our game ist running in steps, every 20msec one step.

Init() {
mWorld = new NxOgre::World("FrameListener: No, log: text");
mPhyScene = mWorld->createScene("SceneLevel01", mSceneMgr, "gravity: yes, floor: yes");
mGameStepEveryMSec = 20; every 20 msec one game-step (update physics, input etc)
}

UpdatePhysics() {
float dt = (float) mGameStepEveryMSec / 1000;
mWorld ->simulate(dt); //NxOgre wants seconds
mWorld ->render(dt);
}

MainLoop() {
mCurrentTime=mMainloopTimer->getMilliseconds();
mGameCurrentTimeStepMS = mCurrentTime - mMainLoopLastTime; //time since last loop msec
mMainLoopLastTime=mCurrentTime; //for next loop

mGameStepTimer += mGameCurrentTimeStepMS;
while (mGameStepTimer > mGameStepEveryMSec )
{
UpdatePhysics(); //fixed timestep!
gamePlayStep();
mGameStepTimer -= mGameStepEveryMSec ;
}

mGraphicsEngine->mRoot->renderOneFrame();
}


@luis
sorry, i read your post too late.
We do not use ogre-framelisteners.

kenny.bsp

12-06-2007 23:46:34

I'm back :D
I expirimened with physics some more and found a few strange things..
the first one is that if I set timestep to the value of time since last frame the results are the same as what i get with timestep of 1/60 ..
Other things are related to spheres. If i create a lot of spheres on top of each other with the same Z they fall on top of each other and stay there without falling down. I understand there's no wind or something but this is kinda strange.. Another thing is if when they are placed like that and fps drops down a lot they are pushed closer to the ground..
I'll upload video on youtube later to show what I meant
---
Video : http://youtube.com/watch?v=Loro1h-l53g

betajaen

13-06-2007 00:14:56

It just shows that the Spheres have a perfect balance. You can do it with capsules as well, and they fall it looks like they move on two axis.

No randomness there ;)

kenny.bsp

13-06-2007 12:15:03

It just shows that the Spheres have a perfect balance. You can do it with capsules as well, and they fall it looks like they move on two axis.
No randomness there ;)

Well yes .. it just looks kinda funny :D
but what about the FPS drop at the end of the movie when i turn the debug on? It seems that with lower fps they should get higher not lower...

betajaen

13-06-2007 12:26:38

Probably due to the sudden change in frame rate. PhysX would have to "guess" the movement for those Actors until the next timestep. Since the timestep is larger than normal, the guess is less accurate than it would be for a small timestep.

Of course it isn't a guess, it's a rather complicated piece of code. ;)

Pottej

14-06-2007 09:12:32

I'm back :D
I expirimened with physics some more and found a few strange things..
the first one is that if I set timestep to the value of time since last frame the results are the same as what i get with timestep of 1/60 ..


If you have vsync on then timestep should be 1/60 if your monitor is at 60hz.

Also doesnt ageia deal with forces and time steps for you, so we should never be multiplying a force by time. If you do multiply force by time you should probably choose force type impulse, at least my physics education tells me you should ;)