asynchronous simulate with nxOgre

bach

18-07-2007 21:01:11

maybe I missed something, but I could not find a (simple) way to do the following:

lets say I have my custom ogre rendering loop like this:

currentTicks=root->getTimer()->getMilliseconds();
deltaMs=currentTicks-lastTicks;

// cca. 40 FPS fixed
if (deltaMs>=25)
{
root->_fireFrameStarted();
root->_updateAllRenderTargets();
root->_fireFrameEnded();
...
}

lets say it is refreshing the screen at cca 25ms/ or 40fps...

and NxOgre is set as:

mScene->getPhyScene().mScene->setTiming(1.0f/100.0,64,NX_TIMESTEP_FIXED);

the problem I have is although deltaMs is around 25ms, the evt.timeSinceLastFrame is not so constant, i.e. it deviates more, and furthermore that is the value used in the NXogre simulate() function ...

to make things more clear, look at the picture ... the red dotted line is the deltaMs which is 25-26ms, while the blue line represents the evt.timeSinceLastFrame which is changing between 18 and 35ms ??

(why is so much difference between these values??)



What would I like to do, is to have physX simulate(deltaMs) run at (almost) constant 40fps and the graphics refreshed asynchronously around this 40fps +/- 10fps even ....

how should I do this ?

betajaen

18-07-2007 22:04:18

Luis is more of an expert on this than I am. But according to him, there is an inaccuracy of the Windows timer of up to 5milliseconds. Which to a Physics Engine is a big difference. Which may account for it.

I'm going to assume your using 0.9 here so to achieve a 60 frame cap. You do:

mScene = mWorld->createScene(...., "time-step-method: fixed");

If you want to run at 40FPS then I can guide you through the process of creating your own SceneController and directly control how often the scene is simulated and renderered, and by pass the whole FrameListener system hook as well. ;)

bach

19-07-2007 10:16:14

i) about the timer, I'm using high performance timer, I mean Ogre getTimer is using QueryPerformanceCounter and it works very well (red line) so it calls frameStarted almost exactelly every 25ms, BUT evt.timeSinceLastFrame is changing from 18ms-36ms ..
Since it is averaged in the last 0.5 sec by Ogre, I did put Ogre::Root::getSingleton().setFrameSmoothingPeriod(0)
to get the exact value ...

ii) nope I'm still using 0.6/2.6.2, haven't had time to move everything to 0.9/2.7.x mainly because I did some small changes in NxOgre sources (I needed some specific body constructor) and in Nxu libraries (I wanted some proprietary collada fields) ... and also had some changes in ogre source regarding the WM_MOUSEWHELL (not captured from laptops' touchpads) and window termination ... :)

... so I knew I will have to spend few days when moving to new version(s)... anyway ...

I would like to have control over the simulation (60-100 Hz), lets say 60Hz is good for now, so the simulation can be as deterministic as possible, and have the rendering loop render if it can 60fps, but if it cannot then at 30fps, or 15fps ,etc ...

So the simulation is ALWAYS run at (60-100HZ) and rendering loop depending on the hardware.

betajaen

19-07-2007 10:36:19

i. I'm pretty sure he was talking about the QueryPerformanceCounter. Next time he is on MSN, I'll nudge him into here.

ii. You can create and use your own Body class (based of Actor) in 0.9 if you have specifics, you'll have to control the garbage collection but NxOgre will happily simulate and render it for you.

You can defiantly do that in 0.9 with a custom SceneController

bach

19-07-2007 11:04:48

ok, thanks.

I will try to move to 0.9 version and implement a custom SceneController then. I suppose I'll need your help :)

.. only I think I'll begin with that, when I get back from my vacation which start this weekend :D

luis

19-07-2007 11:56:44

Well this discussion is really interesting to me :)
http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=4565
http://www.ogre3d.org/phpBB2addons/view ... t=stepping

Since i'm simulating vehicles anything wrong with the stepping method makes the simulation jittering.

I'm using high performance timer, I mean Ogre getTimer is using QueryPerformanceCounter and it works very vell
i was going to said that you was wrong! but i took a look at the OgreTimer.cpp and my surprise you're right. It has to be new in Ogre version 1.4.x
So using Timer::getMicroseconds method you have microseconds resolution, but if you use Timer::getMicrosecondsCPU you will have milliseconds resolution under windows.

I agree with betajaen, use 0.9 and Physx 2.7.2....

if you want to have a very smooth simulation my advice is to use something like:

static const Ogre::Real UPDATE_PERIOD = 1.0/60.0;
mAccumTime += mTimer->getMicroseconds();
while( mAccumTime >= UPDATE_PERIOD )
{
mWorld->getNxWorld()->getPhysXDriver()->frameStarted( evt ); // simulate
mWorld->getNxWorld()->getPhysXDriver()->frameEnded( evt ); // render
mAccumTime -= UPDATE_PERIOD;
}
mTimer->reset();


But using you own custom SceneController and the most important:
call the simulate method exactly like this:

mNxScene->simulate( UPDATE_PERIOD );

UPDATE_PERIOD has to be either a literal constant like: 1.0/60.0 or a constant variable if you use NX_TIMESTEP_FIXED.

right now i'm using VariableSceneController (nxogre 0.9) and calling simulate with the real elapsed time but with VSync to ON and it is very smooth because in Ageia's SDK 2.7.2 they have fixed a problem with NX_TIMESTEP_VARIABLE method.

hope to be clear... my english isn't good i know ;)

bach

19-07-2007 15:58:51

@luis no te preocupes, lo entendí todo ;)

I used my own QueryPerformaceCounter and then to my surprise, after looking at ogre timer code, I found out that it used it also :o

millisecond precision is enough for me, for the rendering loop, but for the simulation loop I wanted exactly what you suggested...
simulate(1.0/100.0)

I have Vsync ON also, but haven't tried the variable time step, since I assumed fixed is more stable ...

I have to switch to 0.9 and I'm not familiar with its code, so I must say that I didn't get these two lines from your example:

mWorld->getNxWorld()->getPhysXDriver()->frameStarted( evt ); // simulate
mWorld->getNxWorld()->getPhysXDriver()->frameEnded( evt ); // render

how do u mean simulate? and render ?
where is the call to RenderOneFrame() ? and who calls simulate () :?

betajaen

19-07-2007 16:35:58

"Simulate" calculates the Physics scene and "Render" changes the Ogre scene to reflect them.

You'll need to tell World not to use a Ogre Framelistener to tell it when to do it; You will.

mWorld = new World("framelistener: no");

luis

19-07-2007 17:06:22

Ya somos unos cuantos que hablamos español!

Yes, i'm not using a framelistener in NxOgre.....

Basically PhysXDriver::frameStarted will end calling the SceneController::Simulate and mNxScene->simulate(deltaTime);

I have Vsync ON also, but haven't tried the variable time step, since I assumed fixed is more stable ...

Yes, fixed time step is more stable but i couldnt make it work with variable framerate without jittering.... maybe i'll try again now that Ogre has a better timer now....