Bug 1500820 - Compare absolute dot-product to 1.0 when interpolating quaternions; r=hiro
authorBrian Birtles <birtles@gmail.com>
Wed, 24 Oct 2018 07:06:43 +0000
changeset 491078 0ce248abad81e801972662b8c56a726f039a9cf0
parent 491077 daf8a3b98eee4a27c5691ecea4d4699dfc33cd31
child 491079 c4123efb05361326c6ad4da81e8d826367efea36
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewershiro
bugs1500820
milestone65.0a1
Bug 1500820 - Compare absolute dot-product to 1.0 when interpolating quaternions; r=hiro See the extended commit message for the following spec change: https://github.com/w3c/csswg-drafts/commit/6b36d41ebc2e790c86cc768a6ea1dcfa81fffe75 Basically, by failing to take the absolute value, for certain content we can end up doing division by zero which will mean that the test included in this patch will cause an assertion to fail in debug builds and return "matrix(NaN, NaN....)" in release builds. Differential Revision: https://phabricator.services.mozilla.com/D9618
servo/components/style/properties/helpers/animated_properties.mako.rs
testing/web-platform/tests/css/css-transforms/animation/matrix-interpolation.html
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -1824,17 +1824,17 @@ impl Animate for Quaternion {
         // Dot product, clamped between -1 and 1.
         let dot =
             (self.0 * other.0 +
              self.1 * other.1 +
              self.2 * other.2 +
              self.3 * other.3)
             .min(1.0).max(-1.0);
 
-        if dot == 1.0 {
+        if dot.abs() == 1.0 {
             return Ok(*self);
         }
 
         let theta = dot.acos();
         let rsintheta = 1.0 / (1.0 - dot * dot).sqrt();
 
         let right_weight = (other_weight * theta).sin() * rsintheta;
         let left_weight = (other_weight * theta).cos() - dot * right_weight;
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transforms/animation/matrix-interpolation.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Matrix interpolation</title>
+<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#interpolation-of-3d-matrices">
+<meta name="assert" content="When interpolating between two matrices, each matrix is decomposed into the corresponding translation, rotation, scale, skew and (for a 3D matrix) perspective values">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/interpolation-testcommon.js"></script>
+<body>
+<script>
+// Test interpolation of quaternions when the dot product is -1.
+//
+// We need to be particularly careful not to use a rotate function with a zero
+// angle since the handling of zero angle rotations may change in future as per:
+//
+//   https://github.com/w3c/csswg-drafts/issues/3236
+//
+// For rotateY(360deg) we should get a quaternion of:
+//    [ 0, sin(2 * PI / 2), 0, cos(2 * PI / 2) ]
+//  = [ 0, 0, 0, -1 ]
+//
+// For rotateX(720deg) we should get a quaternion of:
+//    [ 0, 0, sin(4 * PI / 2), cos(4 * PI / 2) ]
+//  = [ 0, 0, 0, 1 ]
+//
+// Dot product = 0 * 0 + 0 * 0 + 0 * 0 + 1 * -1 = -1
+test_interpolation(
+  {
+    property: 'transform',
+    from: 'rotateY(360deg)',
+    to: 'rotateX(720deg)',
+  },
+  [{ at: 0.5, expect: 'matrix(1, 0, 0, 1, 0, 0)' }]
+);
+</script>
+</body>