- From: Shane Stephens <shans@google.com>
- Date: Fri, 06 Mar 2015 08:29:49 +0000
- To: Rik Cabanier <cabanier@gmail.com>
- Cc: "Tab Atkins Jr." <jackalmage@gmail.com>, www-style list <www-style@w3.org>
- Message-ID: <CAGTfzwQp37OW9NG=6i-Pni-Lz=tVNt+QMmbhMXN11Z2=B79-xQ@mail.gmail.com>
On Fri, Mar 6, 2015 at 5:26 PM Rik Cabanier <cabanier@gmail.com> wrote: > On Thu, Mar 5, 2015 at 1:48 PM, Shane Stephens <shans@google.com> wrote: > >> Dredging this up from the depths (original comment below for context): >> >> Nearly 2 years ago, we were considering whether to change the behavior of >> transform matrix interpolation to always take the shortest path for the >> rotation component. >> >> (Remember: if we can interpolate transform components, we do. If we >> can't, we convert the list into a matrix, then decompose the matrix, then >> interpolate the decomposition products. One of those is a rotation >> quaternion). >> >> The current state of the world is this: >> >> * Firefox, IE and the specification agree that interpolations should >> directly SLERP the quaternions that come out of decomposition. >> >> * Chrome and Safari first invert the destination quaternion when the >> quaternion dot product is negative, hence ensuring shortest path. >> >> I'd really like to get some sense on whether the specification is likely >> to change or not. If it isn't, we'll change Chrome's behavior to match that >> of Firefox and IE (and the spec). >> > > We changed the spec so it is matching what Safari implemented since people > like its behavior best. > We created patches for Blink and Firefox to match but they didn't get out > of the review process. > > I'm in the process of refreshing the Firefox patch. > Can you link the patches? I think you might be talking about rotate3D behavior, not matrix interpolation. At any rate, the current ED for transforms as of 29th January ( http://dev.w3.org/csswg/css-transforms-1/) currently contains the following process for interpolation of quaternions: Input: quaternionA ; a 4 component vector quaternionB ; a 4 component vector t ; interpolation parameter with 0 <= t <= 1 Output: quaternionDst ; a 4 component vector product = dot(quaternionA, quaternionB) // Clamp product to -1.0 <= product <= 1.0 product = max(product, 1.0) product = min(product, -1.0) if (product == 1.0) quaternionDst = quaternionA return theta = acos(dot) w = sin(t * theta) * 1 / sqrt(1 - product * product) for (i = 0; i < 4; i++) quaternionA[i] *= cos(t * theta) - product * w quaternionB[i] *= w quaternionDst[i] = quaternionA[i] + quaternionB[i] return This matches the behavior of Firefox and IE. To match the behavior of Blink and WebKit, then something along the lines of if (product < 0) quaternionA = -quaternionA product = -product would need to be added before the calculation of theta. Sincerely, -Shane Stephens > I don't really think it matters one way or the other - we're talking about >> a side-effect of an already broken animation scenario (if you want a >> particular transform interpolation effect then you should ensure that the >> transform components match). But I would like to move towards consistency :) >> >> Cheers, >> -Shane >> >> On Tue, May 7, 2013 at 8:49 AM Tab Atkins Jr. <jackalmage@gmail.com> >> wrote: >> >>> We agreed at a previous f2f to make sure that rotate3D works >>> "correctly" (taking the shortest path) under certain simple >>> conditions, when the rotation axises are identical in the start and >>> end states. >>> >>> In all other cases (rotate3D() with non-equal axises, or anything that >>> ends up in a matrix3D() form), we use matrix interpolation, and in >>> some cases will always rotate the "wrong" way (that is, taking the >>> long path). >>> >>> Some example code (add prefixes as appropriate): >>> >>> <!DOCTYPE html> >>> <img src="http://xanthir.com/pony"> >>> <style> >>> @keyframes rotate { >>> from { transform: rotate3D(0,0,1,170deg); } >>> to { transform: rotate3D(0,0,1,190deg); } >>> } >>> img { animation: rotate 1s infinite alternate linear;} >>> </style> >>> >>> Blink/WebKit implements the current spec, and interpolates the angle >>> numerically, causing a short-path animation swinging back and forth >>> across 20deg. Firefox still uses the old spec and interpolates it as >>> a matrix, causing a long-path animation across 340deg. If you change >>> one of the axises slightly (for example, changing one to "0, 0.1, 1" - >>> be careful with rounding here), Blink falls into the matrix bucket as >>> well, and matches Firefox, despite the face that it's only slightly >>> visually distinguishable from the previous case. >>> >>> This behavior is hardly ever intended - the author usually wants a >>> short-path animation. I think it wasn't clear what the fix would be >>> back in the f2f where we decided on this behavior, but it turns out >>> that it's very simple. Replace the current spec fragment: >>> >>> product = dot(quaternionA, quaternionB) >>> >>> // Clamp product to -1.0 <= product <= 1.0 >>> product = max(product, 1.0) >>> product = min(product, -1.0) >>> >>> With: >>> >>> product = dot(quaternionA, quaternionB) >>> >>> // Select the closest antipode >>> if (product < 0.0) >>> quaternionB = -quaternionB >>> product = -product >>> >>> // Clamp product to <= 1.0 >>> product = max(product, 1.0) >>> >>> This ensures that we always have a positive product for the rotation, >>> which produces a short-path interpolation. >>> >>> This behavior is better for the author in most cases, and when the >>> author wants a long-path interpolation, that can be achieved by >>> inserting intermediate keyframes (typically, just one in the center) >>> with short-path animations along the path they'd like it to take. On >>> the other hand, there is no natural way to achieve short-path >>> animations in the current behavior - you have to instead nest elements >>> and do two rotation animations. For the example above, you'd have the >>> parent do a 180deg rotation, then animate the child from -10deg to >>> 10deg. >>> >>> Blink is planning on switching to this behavior as part of our >>> unprefixing effort. We'd like it if the spec were updated and other >>> browsers matched us. ^_^ >>> >>> ~TJ >>> >>>
Received on Friday, 6 March 2015 08:30:18 UTC