Framerate-independent stair-step smoothing

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Framerate-independent stair-step smoothing

Postby mh » Fri Feb 22, 2013 10:02 pm

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];
      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
User avatar
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: Framerate-independent stair-step smoothing

Postby taniwha » Wed Feb 27, 2013 5:38 am

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.
Posts: 399
Joined: Thu Jan 14, 2010 7:11 am

Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest