Framerate-independent stair-step smoothing

Post tutorials on how to do certain tasks within game or engine code here.
Post Reply
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Framerate-independent stair-step smoothing

Post by mh »

Here's another one. The problem with stair-step smoothing is that it accumulates lots of tiny floats; run fast enough and precision errors build up. Here's a stab at fixing it. all changes to view.c, so declare these at the top:

Code: Select all

float	v_oldz, v_stepz;
float	v_steptime;
Now find the "smooth out stair step ups" block and replace with:

Code: Select all

	// smooth out stair step ups
	if (cl.onground && ent->origin[2] - v_stepz > 0)
	{
		v_stepz = v_oldz + (cl.time - v_steptime) * 80; // BJP Quake used 160 here

		if (v_stepz > ent->origin[2])
		{
			v_steptime = cl.time;
			v_stepz = v_oldz = ent->origin[2];
		}

		if (ent->origin[2] - v_stepz > 12)
		{
			v_steptime = cl.time;
			v_stepz = v_oldz = ent->origin[2] - 12;
		}

		r_refdef.vieworigin[2] += v_stepz - ent->origin[2];
		view->origin[2] += v_stepz - ent->origin[2];
	}
	else
	{
		v_oldz = v_stepz = ent->origin[2];
		v_steptime = cl.time;
	}
Finally add the following function and call it from somewhere in R_NewMap:

Code: Select all

void V_NewMap (void)
{
	v_oldz = v_stepz = 0;
	v_steptime = 0;
}
So, instead of accumulating lots of tiny deltas we're working off absolute differences with far lower precision loss.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
taniwha
Posts: 401
Joined: Thu Jan 14, 2010 7:11 am
Contact:

Re: Framerate-independent stair-step smoothing

Post by taniwha »

v_stepz = v_oldz + (cl.time - v_steptime) * 80;
You might like to take a look at this article ("Stable algorithms also matter" section). It presents an alternate calculation for blend functions that guarantees the blend factor will never escape the 0..1 range, no matter how crappy time's precision has become. As far as I can tell, it just gracefully degrades to such that blend is always 1.

I've already implemented his int-time (64 bits, microseconds) and 4Gs offset suggestions (found an issue in the timedemo code: start time was stored as a float: ouch). I've only just pushed the changes because I had found a nasty bug with 128 dlight support while testing the time changes, then forgot about them.
Leave others their otherness.
http://quakeforge.net/
Post Reply