This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 15610 - Definition for rotate3d() doesn't match implementations
Definition for rotate3d() doesn't match implementations
 Status: CLOSED FIXED None CSS Unclassified Transforms (show other bugs) unspecified All All P2 normal --- Dirk Schulze This bug has no owner yet - up for the taking

 Reported: 2012-01-18 17:33 UTC by Aryeh Gregor 2012-02-14 17:13 UTC (History) 5 users (show) cmarrin dino dschulze eoconnor smfr

Attachments
rotate3d (6.00 KB, image/png)
2012-02-12 02:49 UTC, Dirk Schulze
Details

 Aryeh Gregor 2012-01-18 17:33:48 UTC ```""" This function is equivalent to matrix3d(1 + (1-cos(angle))*(x*x-1), -z*sin(angle)+(1-cos(angle))*x*y, y*sin(angle)+(1-cos(angle))*x*z, 0, z*sin(angle)+(1-cos(angle))*x*y, 1 + (1-cos(angle))*(y*y-1), -x*sin(angle)+(1-cos(angle))*y*z, 0, -y*sin(angle)+(1-cos(angle))*x*z, x*sin(angle)+(1-cos(angle))*y*z, 1 + (1-cos(angle))*(z*z-1), 0, 0, 0, 0, 1). """ http://dev.w3.org/csswg/css3-3d-transforms/#transform-functions rotate3d(0, 0, 1, 90deg) should therefore be equivalent to matrix3d(0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) Test-case 1: data:text/html,
Test-case 2: data:text/html,
Per spec these should render the same. In Firefox 12.0a1 and Chrome 17 dev, however (with prefixes added), they render differently: the first has the border turned to the right, and the second has it turned to the left. Implementations have the angle negated with respect to the spec, which works out to the same as negating sin(angle). So the spec should say: """ This function is equivalent to matrix3d(1 + (1-cos(angle))*(x*x-1), z*sin(angle)+(1-cos(angle))*x*y, -y*sin(angle)+(1-cos(angle))*x*z, 0, -z*sin(angle)+(1-cos(angle))*x*y, 1 + (1-cos(angle))*(y*y-1), x*sin(angle)+(1-cos(angle))*y*z, 0, y*sin(angle)+(1-cos(angle))*x*z, -x*sin(angle)+(1-cos(angle))*y*z, 1 + (1-cos(angle))*(z*z-1), 0, 0, 0, 0, 1). """ where I've just replaced sin(angle) with -sin(angle) consistently.``` Simon Fraser 2012-01-31 21:40:21 UTC ```This seems pretty different from what WebKit actually implements: angle /= 2.0f; double sinA = sin(angle); double cosA = cos(angle); double sinA2 = sinA * sinA; double x2 = x*x; double y2 = y*y; double z2 = z*z; mat.m_matrix[0][0] = 1.0f - 2.0f * (y2 + z2) * sinA2; mat.m_matrix[0][1] = 2.0f * (x * y * sinA2 + z * sinA * cosA); mat.m_matrix[0][2] = 2.0f * (x * z * sinA2 - y * sinA * cosA); mat.m_matrix[1][0] = 2.0f * (y * x * sinA2 - z * sinA * cosA); mat.m_matrix[1][1] = 1.0f - 2.0f * (z2 + x2) * sinA2; mat.m_matrix[1][2] = 2.0f * (y * z * sinA2 + x * sinA * cosA); mat.m_matrix[2][0] = 2.0f * (z * x * sinA2 + y * sinA * cosA); mat.m_matrix[2][1] = 2.0f * (z * y * sinA2 - x * sinA * cosA); mat.m_matrix[2][2] = 1.0f - 2.0f * (x2 + y2) * sinA2; mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f; mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f; mat.m_matrix[3][3] = 1.0f;``` Aryeh Gregor 2012-02-01 17:07:26 UTC ```Remember your trig identities. :) E.g., for the first entry, the spec says 1 + (1-cos(angle))*(x*x-1) while WebKit says 1.0f - 2.0f * (y2 + z2) * sinA2 = 1 - 2*(y*y + z*z) * sin(angle/2)^2. sin(t)^2 = (1 - cos(2t))/2 , so this is the same as 1 - (y*y + z*z) * (1 - cos(angle)). (x, y, z) is normalized, so x*x + y*y + z*z = 1, which means y*y + z*z = 1 - x*x, and WebKit's formula is the same as 1 - (1 - x*x) * (1 - cos(angle)) which if we distribute the first minus sign across (1 - x*x), becomes 1 + (x*x - 1) * (1 - cos(angle)) which is the same as the spec. If you look at the terms involving sin(), you can see that WebKit does do the opposite of the spec, as my black-box testing discovered and as I explained in comment #0: 2.0f * (x * y * sinA2 + z * sinA * cosA) = 2*x*y*sin(angle/2)^2 + 2*z*sin(angle/2)*cos(angle/2) = x*y*(1 - cos(angle)) + 2*z*sin(angle/2)*cos(angle/2) (power reduction in first term) = x*y*(1 - cos(angle)) + z*sin(angle) (double-angle in second term). Note that it's z*sin(angle), as I say in the bottom of comment #0, not -z*sin(angle) as the spec says. The same goes for the other entries. sin(angle) needs to be negated in every case. FWIW, it looks like Mozilla independently realized the spec didn't match WebKit when developing their 3D transform implementation, and made their implementation match WebKit instead of the spec for compat with web content: https://bugzilla.mozilla.org/show_bug.cgi?id=704468``` Chris Marrin 2012-02-01 18:24:06 UTC ```... > FWIW, it looks like Mozilla independently realized the spec didn't match WebKit > when developing their 3D transform implementation, and made their > implementation match WebKit instead of the spec for compat with web content: > > https://bugzilla.mozilla.org/show_bug.cgi?id=704468 So, the spec is describing the left-hand rule for rotations, which is not very common. WebKit (and now FF) implement the right-hand rule, which is the more common way of expressing the direction. So I'd say we should change the spec to match the two implementations. OBTW, I'm betting Chrome matches the other two, unless they've made some changes in Chrome specific parts of the code. So changing the spec would match all the major transform implementations.``` Chris Marrin 2012-02-01 18:25:14 UTC `This is all probably a fallout of our changing the spec a while back from row-major to column-major notation. Changing the spec certainly seems like the right solution` Dirk Schulze 2012-02-12 02:49:50 UTC ```Created attachment 1077 [details] rotate3d Can some one verify that this is the correct matrix that we want? It is the code that Chris applied to this bug. But the matrix on SVG Transform[1] looks different to the attached matrix as well as to the matrix on CSS Transforms. [1] http://www.w3.org/TR/2009/WD-SVG-Transforms-20090320/#threed-rotate-definition``` Dirk Schulze 2012-02-13 03:57:07 UTC `I added a matrix to the mathematical description section, that matches the current behavior of WebKit. If all agree with the math, we can close this bug now.` Aryeh Gregor 2012-02-13 16:42:33 UTC ```There are two mistakes in the new version: 1) alpha needs to be replaced by alpha/2. This is the "angle /= 2.0f;" line in WebKit. 2) The first matrix entry has x^2 + z^2, but it should by y^2 + z^2 like WebKit. Otherwise it's correct.``` Dirk Schulze 2012-02-13 16:47:39 UTC `Thanks a lot, I'll change that asap. I will also add a comment that alpha must be in radian for the current rotate3d matrix. This might be the difference to SVG Transforms. I will check this as well.` Dirk Schulze 2012-02-14 17:00:03 UTC `I corrected the code with the commit 2012/02/13. Closing bug now. Feel free to reopen it if you find other issues with rotate3d.` Aryeh Gregor 2012-02-14 17:13:38 UTC `Looks good to me. Thanks!`