Game Development Community

Interation Bug fix for fast machines

by Ray Gebhardt · in Torque Game Builder · 03/04/2005 (3:59 pm) · 5 replies

I ran into a problem with my machine handling the physics correctly at different resolutions. I evetually figure out that it had to do with floating point errors due to running too many iterations (the game was running at about 300 fps on my machine). Here is the code that fixes the issue for me.

fxSceneGraph2D.cc - Line 1924
if ( elapsedTime < limitFPSTime )
	{
		if(elapsedTime > targetFPSTime)
		{
			// Get the underflow by subtracting the current iteration from elapsed time
			elapsedUnderflow = elapsedTime - targetFPSTime;

			// Yes, so do a full integration of the elapsed time.
			subUpdateScene(targetFPSTime, &mDebugStats);

			// Set Physics Metrics.
			mDebugStats.objectPhysicsIterations = 1;
			mDebugStats.objectPhysicsIterationTime = targetFPSTime;
			mDebugStats.objectPhysicsUnderflowTime = elapsedUnderflow;
		}
		else
		{
			elapsedUnderflow = elapsedTime;
		}
	}


Tell me if this fix has any issues.

#1
03/06/2005 (1:47 am)
We've still got work to do on this part of the code but are you replacing all of the sub-update code e.g. you don't iterate the physics? That may work on some stuff but things like stacking boxes gets extremely unstable as the FPS drops. Iterating, although expensive, partially resolves some of these problems.

Weeks prior to release, the iteration code wasn't in there but when we stressed systems down to sub 30fps, rigid-body dynamics breaks down. Iteration is the only way to keep things stable at this point, irrelevant of frame-rate. For games that have things in equillibrium, removing the code will destroy such setups. Tasking away from T2D or having an anti-virus kicking can cause severe upsets in the frame-rate.

This is all kinda' academic really as we've got lots of work to do on the physics with relation to prediction across the network etc so this stuff will change in the future.

- Melv.
#2
03/06/2005 (2:00 am)
No it just updates the same amount of iterations per second on all machines (unless they are running under 10 fps i believe). The operation of this code on slower machines has not changed, and has identical functionality. On faster machines it will only run a physics iteration if enough time has passed to do a full iteration. If not, it will just add the value to the elapsedUnderflow, and skip the iteration. In addition after it runs the iteration step, if there is any time "left over" it will just add it to the elapseUnderflow. If you trace through the code, it basically limits iteration to exactly 100 times a second on all machines (targetFPSTime = 1.0f / mScenePhysicsTargetFPS and mScenePhysicsTargetFPS = 100) .
#3
03/06/2005 (2:15 am)
Arg...actually you are right with the way i posted the code...i still have the "else" at the end in my code. I should have pasted a little more code, but i wanted to paste as little code as possible. Here is what you should actually do.

fxSceneGraph2D.cc - Line 1923
// Are we inside the limit?
	if ( elapsedTime < limitFPSTime )
	{
		if(elapsedTime > targetFPSTime)
		{
			// Get the underflow by subtracting the current iteration from elapsed time
			elapsedUnderflow = elapsedTime - targetFPSTime;

			// Yes, so do a full integration of the elapsed time.
			subUpdateScene(targetFPSTime, &mDebugStats);

			// Set Physics Metrics.
			mDebugStats.objectPhysicsIterations = 1;
			mDebugStats.objectPhysicsIterationTime = targetFPSTime;
			mDebugStats.objectPhysicsUnderflowTime = elapsedUnderflow;
		}
		else
		{
			elapsedUnderflow = elapsedTime;
		}
	}
	else
	{
		// No, oh well, here we go then...

		// Use a dummy debug stats structure for all iterations apart from the final
		// one.  This'll stop the accumulation of stats from the multiple iterations.
		// We could average here but we're already in a tight situation and we don't
		// want to make things worse!
		static CDebugStats pDummyDebugStats;

		// Calculate Iterations for now.
		// NOTE:- We'll cap iterations here to stop things getting out of hand.
		U32 iterations = (U32)getMin( (S32)(elapsedTime / targetFPSTime), (S32)mScenePhysicsMaxIterations );

		// Calculate Underflow.
		elapsedUnderflow = getMax(0.0f, elapsedTime - (targetFPSTime * iterations));

		// Do the iterations.
		for ( U32 n = 1; n < iterations; n++ )
				subUpdateScene(targetFPSTime, &pDummyDebugStats);

		// Do the Final Iteration with a valid debug-stats.
		subUpdateScene(targetFPSTime, &mDebugStats);

		// Set Physics Metrics.
		mDebugStats.objectPhysicsIterations = iterations;
		mDebugStats.objectPhysicsIterationTime = targetFPSTime * iterations;
		mDebugStats.objectPhysicsUnderflowTime = elapsedUnderflow;
	}
#4
03/06/2005 (4:37 am)
@Ray: Thanks, I see how you're working this now. I thought you were discussing a non-iterative approach for all machines.

I'll go through this in more detail soon but it'll definatley be replaced with something much more superior in the future.

Thanks for the info.

- Melv.
#5
03/08/2005 (2:29 am)
@Ray: Okay, I just got around to looking at this code properly (working through the bugs list) and yes, jeeeez, what a cock-up the original code was. I must admit to it being a last minute addition as not very well tested.

The original intent was that the simulation run at a target FPS rate but the code wasn't actually achieving that.

Expect this in the next update.

Many thanks for pointing this out!


- Melv.