W3C home > Mailing lists > Public > public-css-archive@w3.org > April 2019

Re: [csswg-drafts] [css-easing-2] Complex easing/timing functions (#229)

From: VisibleCode via GitHub <sysbot+gh@w3.org>
Date: Tue, 30 Apr 2019 03:54:38 +0000
To: public-css-archive@w3.org
Message-ID: <issue_comment.created-487814397-1556596477-sysbot+gh@w3.org>
brief overview on the math, I can go into more detail on specific things if you want

Every segment of a cubic spline translates to a cubic polynomial. There are a number of ways to represent a cubic polynomial, which are all exactly convertible (within the limits of floating point precision etc.), including:

* the obvious way:  ax<sup>3</sup> + bx<sup>2</sup> + cx + d
* [Hermite form](https://en.wikipedia.org/wiki/Hermite_polynomials): starting value, starting tangent, ending tangent, ending value
* [Bernstein form](https://en.wikipedia.org/wiki/Bernstein_polynomial): starting value, two control values, ending value

The thing is, Bézier curves are based on Bernstein polynomials (the bezier handles map to the control values). The catch is that a 2D Bézier curve segment consists of *two* polynomials, one for x and one for y. For drawing curves on screen that's perfect, the two polynomials can be evaluated directly with all the usual advantages of cubics. Mathematically precise, versatile, and efficient to evaluate.

But, for uses like CSS's cubic-bezier(), you have to solve for the unique root of the x polynomial (with things constrained so there is one), and plug the result into the y polynomial. The root finding part isn't possible to do super efficiently, so in practice what most implementations of cubic-bezier() do is precompute a rough approximation and linearly interpolate over that. It works _okay_, but there's a big speed/accuracy tradeoff. Probably there's more variation between implementations than people realize, especially in extreme cases.

TBH, in general implementors would probably get better results (both in terms of accuracy and also performance) converting each cubic-bezier() segment to a cubic spline (of ~1-3 segments) rather than trying to approximate cubic-bezier() directly in realtime.

There are a bunch of other animation curve representations which get used as well, NURBS and so on. Some of these superficially resemble Béziers (they have similar handles, etc.), but don't allow exact conversion to/from them.

Blender's smoothing is a bit different to the `auto` thing I described above (which is based on [spline interpolation](https://en.wikipedia.org/wiki/Spline_interpolation)). Blender's curves can still be approximated by cubic splines but you wouldn't use `auto` to do it.

GitHub Notification of comment by visiblecode
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/229#issuecomment-487814397 using your GitHub account
Received on Tuesday, 30 April 2019 03:54:39 UTC

This archive was generated by hypermail 2.4.0 : Tuesday, 5 July 2022 06:41:46 UTC