Jump to content
  • Advertisement
Sign in to follow this  
chillypacman

Update physics seperately, not with 3D graphics

This topic is 4155 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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;
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 ;)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!