Deriving the best interpolation function

I wanted to play around with a simple VR app with fun affects around the hand detections from the Quest 3 headset.

I had plans for all kinds of effects I wanted to do, and I started with this simple sphere following my finger. But it didn’t look nice enough at first!

So I became interested in deriving a smoothstep function by myself.

Nice interpolation of sphere position

Detour - deriving smoothstep ourselves

Idea - smoothness at the edges, constant speed inbetween. Because what if we want to travel large distances

Idea for the interpolation function with a straight section

Constraints:

  • f(0)=0f(0)=0
  • f(0)=0f'(0) = 0
  • D=f(p)+f(p)(T2p)+f(p)D = f(p) + f'(p) * (T - 2p) + f(p)
  • Where 0D,0T,0pT/20 \leq D, 0\leq T, 0\leq p \leq T/2
  • Given DD, TT, and PP as input constraints, we then have 1 less degree of freedom for whatever parameters define f(x)f(x)
  • Controlling for a, we get a set of curves, which all satisfy our needs
  • Another thing: f(p)0f''(p) \geq 0, so that we don’t get this

Using a cubic function:

{f(x)=ax3+bx2+cx+df(0)=0f(0)=0f(p)0D=2f(p)+f(p)(T2p){f(x)=ax3+bx2b=D+4ap33ap2T2pT2p2aD3p2T2p3\begin{cases} f(x) = ax^3 + bx^2 + cx + d \\ f(0) = 0 \\ f'(0) = 0 \\ f''(p) \geq 0 \\ D = 2f(p) + f'(p) * (T - 2p) \end{cases} \Longrightarrow \begin{cases} f(x) = ax^3 + bx^2 \\ b = \frac{ D + 4ap^3 -3ap^2T}{2pT-2p^2 } \\ a \geq -\frac{D}{3p^2T - 2p^3} \end{cases}

The function is nice!

seam carving comparison
Nice interpolation of sphere position

But then I’ve got a problem - this function is complicated to compute the inverse of, which I’ll need later. There are formulas for computing the inverse for the cubic from above, and Inigo Quilez even did a post about it. But I don’t want to integrate it because it’s not something I want to derive right now

So I tried a couple more families of functions:

  • b(1cos(ax))b(1 - \cos(ax))
  • axbax^b

This is all fun & stuff, but the section is called a detour because this function specification isn’t very useful. The speed of the middle section is derived, not an input parameter. and the “warmup distance” isn’t an input parameter.

Deriving a “warmup/warmdown” function

The purpose is to get a function with specific warmup / warmdown properties. I.e.:

  • The warmup/warmdown must take time TT
  • During the warmup/warmdown, distance DD should be traveled
  • By the end of warmup we should have speed VV

Or:

{f(0)=0f(0)=0f(T)=Df(T)=Vf(x)0,0xT\begin{cases} f(0) = 0 \\ f'(0) = 0 \\ f(T) = D \\ f'(T) = V \\ f''(x) \geq 0,& 0\leq x\leq T \end{cases}

Didn’t manage to derive this for a cubic ax3+bx2ax^3 + bx^2 or a trigonometrical b(1cos(ax))b(1 - \cos(ax))

But it was very doable for axbax^b !

b=TVD,  a=DTbb=\frac{TV}{D}, \; a=\frac{D}{T^b}
New warmup function

Assume current position is xx , target position is tt, and current speed is ss

d=xtd = ||x-t|| – the distance to target

  • If dDd \geq D:

    • if v=Vv = V , then we’re up to speed and don’t need to do anything, just update position

    • i.e. we’re not close enough to do “warmdown” yet, we should do “warmup”:

      xnewx+vΔtvnewf(f1(v)+Δt)\begin{equation} \begin{aligned} x_{\text{new}} \coloneqq & x + v \Delta t \\ v_{\text{new}} \coloneqq & f'(f'^{-1}(v) + \Delta t) \end{aligned} \end{equation}
  • Otherwise we need to do “warmdown”, strictly according to the function:

    xnewf(f1(d)Δt)vnewf(f1(d)Δt)\begin{equation} \begin{aligned} x_{\text{new}} \coloneqq & f(f^{-1}(d) - \Delta t) \\ v_{\text{new}} \coloneqq & f'(f^{-1}(d) - \Delta t) \end{aligned} \end{equation}

Voila! It works