Update physics seperately, not with 3D graphics

Started by
12 comments, last by Telamon 16 years, 8 months ago
My problem is my physics system (which uses PhysX) seems to be synched with the 3D. The loewr the framerate the lower the choppier the physics become, in fact if the framerate drops below 200 the forces stop working (collision remains). I have to change the timestep when that happens. When I use a fixed timestep my problems remain, albeit with less issues, what happens is when the fps is lower the physics is choppy, when the fps is high the physics is smooth, though sometimes it can be like using the variable timestep in that it doesn't work at all when it's below 200fps. How can I update the physics, say, 30 times per second and keep the 3D fps rate at anything it wants to be? If this isn't possible how can I limit the actual 3D framerate to something like 60fps? I don't think this would be ideal since the framerate probably won't stay at 60 on slower computers so I'd rather not do it like this. Also heres how I get the variable time rate (in case theres something wrong in it):
int EnterMsgLoop( bool (*ptr_display)(float timeDelta) )
{
	MSG msg;
	::ZeroMemory(&msg, sizeof(MSG));

	static float lastTime = (float)timeGetTime(); 

	while(msg.message != WM_QUIT)
	{
		if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}
		else
		{	
			float currTime  = (float)timeGetTime();
			float timeDelta = (currTime - lastTime)*0.001f;

			ptr_display(timeDelta);

			lastTime = currTime;
		}
	}
	return msg.wParam;
}

Advertisement
timeGetTime isn't an accurate timer. At 200fps, you're expecting it to return at an accuracy of 5ms. In my experience, tgt only returns at intervals of 16ms. That is, if you call timeGetTime twice within 16ms, you'll get the same result.

[edit] timeGetTime is also affected by a system-wide frequency setting, that some application might change (I think Windows Media Player and MSN Messanger do)

I'm not sure if this is your only problem, but try looking into more accurate timers, such QueryPerformanceCounter. That might help the results you're getting.

As for PhysX, I don't see much point to updating it 200 times per second. PhysX manages it's own timing from what I recall, let it do so. Don't force it to run more often than it wants to.

Hope this helps.
Sirob Yes.» - status: Work-O-Rama.
This isn't a DirectX specific question. Moved to 'Game Programming' - maybe they can give you some architectural advice. Have a search around the internet on coupling (and 'seperation of concerns') as well - you might find some ideas.

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Quote:Original post by sirob
timeGetTime isn't an accurate timer. At 200fps, you're expecting it to return at an accuracy of 5ms. In my experience, tgt only returns at intervals of 16ms. That is, if you call timeGetTime twice within 16ms, you'll get the same result.

[edit] timeGetTime is also affected by a system-wide frequency setting, that some application might change (I think Windows Media Player and MSN Messanger do)

I'm not sure if this is your only problem, but try looking into more accurate timers, such QueryPerformanceCounter. That might help the results you're getting.

As for PhysX, I don't see much point to updating it 200 times per second. PhysX manages it's own timing from what I recall, let it do so. Don't force it to run more often than it wants to.

Hope this helps.


I'm not really a very experienced programmer, I actually just went through the tutorials on physx and it had this on it:
void PhysX::StartPhysics(NxReal time){	// Start collision and dynamics for delta time since the last frame	gScene->simulate(time);	gScene->flushStream();}


So I dunno what you mean by "PhysX manages it's own timing from what I recall, let it do so", if I could I would.


I did try changing from timeGetTiem to QueryPerformanceCounter but it didn't really change much.

The whole application seems to be depending on the framerate, if the framerate is high everything moves really fast (like the camera for instance), when it's low things move slow too.

I'm going to have to figure out a way to let the 3D update as often as it wants but make the input/output, physics and sound update at a more constant rate. The only way I can think of is with frame ratel imiting but I'm not sure if thats the best way to go.
Quote:Original post by chillypacman
Quote:Original post by sirob
timeGetTime isn't an accurate timer. At 200fps, you're expecting it to return at an accuracy of 5ms. In my experience, tgt only returns at intervals of 16ms. That is, if you call timeGetTime twice within 16ms, you'll get the same result.

[edit] timeGetTime is also affected by a system-wide frequency setting, that some application might change (I think Windows Media Player and MSN Messanger do)

I'm not sure if this is your only problem, but try looking into more accurate timers, such QueryPerformanceCounter. That might help the results you're getting.

As for PhysX, I don't see much point to updating it 200 times per second. PhysX manages it's own timing from what I recall, let it do so. Don't force it to run more often than it wants to.

Hope this helps.


I'm not really a very experienced programmer, I actually just went through the tutorials on physx and it had this on it:
*** Source Snippet Removed ***

So I dunno what you mean by "PhysX manages it's own timing from what I recall, let it do so", if I could I would.


I did try changing from timeGetTiem to QueryPerformanceCounter but it didn't really change much.

The whole application seems to be depending on the framerate, if the framerate is high everything moves really fast (like the camera for instance), when it's low things move slow too.

I'm going to have to figure out a way to let the 3D update as often as it wants but make the input/output, physics and sound update at a more constant rate. The only way I can think of is with frame ratel imiting but I'm not sure if thats the best way to go.


You might want to consider using a fixed timestep for physics (not sure how PhysX does things internally though),

the easiest way imo(using a low resolution timer) would be something like:

long oldtime = getTime();static int timeStepSize = 10;while(someCondition) {    long newtime = getTime();    long diff = newtime-oldtime;    while (diff>=timeStepSize) {        scene.update(timeStepSize);        diff-=timeStepSize;        oldtime+=timeStepSize;    }    scene.render();}


Thus each update is for 10ms, if less than 10ms has passed since the last update nothing will happen, if 20ms or more has passed it will update 2 times or more (but only render once).

This means that the simulation will run at the same speed no matter what your graphical framerate is. (as long as your cpu can handle it)
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
I made a simple physics engine back in 2004 for my pool game project. But that same year my laptop broke down and all is lost. though i can still remember how i managed to handle my physics update then.

Basically i make sure that the physics engine has a fix frame rate, or shall we call time-step throughout the run.

Say our timestep is 100ms. the application starts running and after 1 frame it took 50ms to complete it, then i don't have to update my physics because it's less than 100ms. however on next frame it took 70ms to complete, now the total time elapsed since application starts is 120ms. its time for me to update my physics. then on next frame, the application lagged due to some glitch and it took 300ms to complete it, physics will now update 3 times before it goes on to the next frame.

This way, you make sure that your physics timestep is fixed no matter what. I hope you get the idea. feel free to ask if something isn't clear.
Timer accuracy: I use QueryPerformanceTimer in all my timing code. IIRC it's accurate to around 9 ns.

You should design your physics code to degrade gracefully when hit by CPU resource constraints. If you lock-step your updates to either X-updates-per-frame or update-every-X-ms, you are going to run into problems if you ever have more bodies in-game that your machine can simulate. If you are designing for network play, this problem becomes worse (since the network connection becomes the bottleneck rather than the client CPU).

One trick we've found that works well in this case is actually slowing down time itself for the rest of the world while maintaining simulation of your player characters at responsive frame rates. This creates a "bullet time" effect when 1000s of parts start flying around, rather than stuttering physics and character updates.

Just my 2c.

Shedletsky's Bits: A Blog | ROBLOX | Twitter
Time held me green and dying
Though I sang in my chains like the sea...

Quote:Original post by SimonForsman
You might want to consider using a fixed timestep for physics (not sure how PhysX does things internally though),


Always use a fixed time step. In my experience, no physics engine handles variable framerates all that well. PhysX definately wants a constant 60fps - lower than that and you start getting problems.

Quote:the easiest way imo(using a low resolution timer) would be something like:

*** Source Snippet Removed ***

Thus each update is for 10ms, if less than 10ms has passed since the last update nothing will happen, if 20ms or more has passed it will update 2 times or more (but only render once).

This means that the simulation will run at the same speed no matter what your graphical framerate is. (as long as your cpu can handle it)


That's the best way to do it ;)
Quote:Original post by Telamon
One trick we've found that works well in this case is actually slowing down time itself for the rest of the world while maintaining simulation of your player characters at responsive frame rates. This creates a "bullet time" effect when 1000s of parts start flying around, rather than stuttering physics and character updates.


Ok for *some* single player games, but really not practical for anything networked unfortunately. The other problem i see with that solution is that if you are running the game on a 300Mhz P2 you have an advantage over someone running a 3Ghz P4 since you are likely to always be in bullet time mode, so the player can basically go and make a coffee and still have time to line up a head shot....

The solution presented by SimonForsman is the way we do it, and the way i'd recommend.
I did try SimonForsman idea but found that the physics was really choppy when the framerate went below 200.

Would having a timestep dependent on the difference between the delay between rendering be a good idea?

Like if the delay in rendering a frame is 10ms I can have a timestep of 5 (I'm pulling the numbers randomly so bare with me), and if the delay in rendering a frame were 20ms then the timestep would be 10. There wuld be some problems with fringe values but on the whole it wouldn't be very noticable. Not sure if it would be a good idea with networking, though.

This topic is closed to new replies.

Advertisement