XaiJu
animatrix
animatrix

patreon


Substeps and Subframe Interpolation

In Houdini, dealing with substeps is a complex phenomenon. Writing them is easy, but reading and interpolating between the subframes is tricky.

To write subframes on disk, all you have to do is to use $FF, instead of $F. That's it.

Now to read them, if you use the same file sequence used for writing subframes to disk, and you have the Integer Frame Values option turned off in Global Animation Options, you will have a lot of read errors as you scrub the timeline.

What you have to do is to read the nearest (sub)frame using the TimeShift SOP with this expression: int($FF * ch("../substeps")) / ch("../substeps")

This will get rid of the read errors and also make sure you always have some data to read. After this to blend between the available (sub)frames, all you have to do should have been to use the TimeBlend SOP. Unfortunately neither the old TimeBlend nor the new old which is a preconfig of the Retime SOP won't work.

The old TimeBlend SOP will ignore all of your subframes. If you dive inside, you can see that it's applying floor/ceil to the current frame ($FF) to turn them into integers. So you can't use this.

The new Retime SOP also doesn't read the subframes as is, but will match the result of the old TimeBlend SOP. It has an option called Interpolate Between Input Frames. If you turn this off, it will read your subframes, but you won't get any interpolation at all. It will only give you your subframes. If you leave this option on (default), you will only get interpolation between your integer frames, which defeats the purpose of writing out subframe data.

All this is because Retime SOP also applies floor/ceil to the current frame ($FF) to turn them into integers. So that means you have to implement your own subframe blending.

We have already started it with the first expression in this post which implements the option of Interpolation = None. Now we have to implement Linear, Cubic and Subdivision.

Fortunately we will use the core operator that powers the Retime SOP; the Sequence Blend SOP. All we have to do is to provide 2 inputs for Linear and 4 inputs for Cubic and Subdivision interpolation. It will do the rest.

We will create a generic implementation for all. So we gather 4 (sub)frames:

Past (-1)

Current (0)

Future (1)

Next Future (2)

The only thing we have to do is to compute the step size based on the substeps used and then offset the current time by this amount, multiplied by the appropriate integer as shown above. Then provide 2 or 4 of these inputs to the Sequence Blend and it will blend perfectly between our (sub)frames.

past = int(($FF + (-1 * ch("stepsize"))) * ch("../substeps")) / ch("../substeps")

current = int(($FF + (0 * ch("stepsize"))) * ch("../substeps")) / ch("../substeps")

future = int(($FF + (1 * ch("stepsize"))) * ch("../substeps")) / ch("../substeps")

next future = int(($FF + (2 * ch("stepsize"))) * ch("../substeps")) / ch("../substeps")

stepsize = if(ch("../substeps") == 1, 1, 1 / ch("../substeps"))


2 more gotchas though:

1. Because of time offsetting into the past and the future, you have to hold your first and last frame.

2. The Blend amount for 4 samples will have 1 added to the blend amount as we are starting from the 2nd sample. The first sample is just there to compute a higher order interpolation.

Not so straight forward as it should be huh? Check out the provided scene to see it in action. I didn't make a tool for this because creating and maintaining new tools that fix problems in the standard ones is painful, and should better be addressed by SESI.

https://www.dropbox.com/s/19ezrcilqjbyiw2/subframes.hip?dl=1

Substeps and Subframe Interpolation

More Creators