Bug 1245242 - Normalize to unit vector for DOMMatrix.rotateAxisAngleSelf. r=roc
This commit is contained in:
@@ -552,22 +552,10 @@ DOMMatrix::RotateAxisAngleSelf(double aX, double aY,
|
||||
}
|
||||
|
||||
aAngle *= radPerDegree;
|
||||
// sin(aAngle / 2) * cos(aAngle / 2)
|
||||
double sc = sin(aAngle) / 2;
|
||||
// pow(sin(aAngle / 2), 2)
|
||||
double sq = (1 - cos(aAngle)) / 2;
|
||||
|
||||
Ensure3DMatrix();
|
||||
gfx::Matrix4x4 m;
|
||||
m._11 = 1 - 2 * (aY * aY + aZ * aZ) * sq;
|
||||
m._12 = 2 * (aX * aY * sq + aZ * sc);
|
||||
m._13 = 2 * (aX * aZ * sq - aY * sc);
|
||||
m._21 = 2 * (aX * aY * sq - aZ * sc);
|
||||
m._22 = 1 - 2 * (aX * aX + aZ * aZ) * sq;
|
||||
m._23 = 2 * (aY * aZ * sq + aX * sc);
|
||||
m._31 = 2 * (aX * aZ * sq + aY * sc);
|
||||
m._32 = 2 * (aY * aZ * sq - aX * sc);
|
||||
m._33 = 1 - 2 * (aX * aX + aY * aY) * sq;
|
||||
m.SetRotateAxisAngle(aX, aY, aZ, aAngle);
|
||||
|
||||
*mMatrix3D = m * *mMatrix3D;
|
||||
|
||||
|
||||
@@ -323,4 +323,14 @@ test(function() {
|
||||
assert_throws("SyntaxError", function() { new WebKitCSSMatrix("initial"); }, "initial is not a valid constructor argument.")
|
||||
assert_throws("SyntaxError", function() { new WebKitCSSMatrix("inherit"); }, "inherit is not a valid constructor arugment.")
|
||||
}, "Test invalid constructor arguments.");
|
||||
|
||||
test(function() {
|
||||
var m1 = new WebKitCSSMatrix();
|
||||
m1 = m1.rotateAxisAngle(0, 0, 1, 45);
|
||||
|
||||
var m2 = new WebKitCSSMatrix();
|
||||
m2 = m2.rotateAxisAngle(0, 0, 3, 45);
|
||||
|
||||
assert_true(RoughCompareMatrix(m1, m2), "rotateAxisAngle should normalize vector to unit vector.");
|
||||
}, "Test normalization of vector for rotateAxisAngle");
|
||||
</script>
|
||||
|
||||
@@ -1433,6 +1433,48 @@ public:
|
||||
_24 = -sinTheta * temp + cosTheta * _24;
|
||||
}
|
||||
|
||||
// Sets this matrix to a rotation matrix about a
|
||||
// vector [x,y,z] by angle theta. The vector is normalized
|
||||
// to a unit vector.
|
||||
// https://www.w3.org/TR/css3-3d-transforms/#Rotate3dDefined
|
||||
void SetRotateAxisAngle(double aX, double aY, double aZ, double aTheta)
|
||||
{
|
||||
Point3D vector(aX, aY, aZ);
|
||||
if (!vector.Length()) {
|
||||
return;
|
||||
}
|
||||
vector.Normalize();
|
||||
|
||||
double x = vector.x;
|
||||
double y = vector.y;
|
||||
double z = vector.z;
|
||||
|
||||
double cosTheta = FlushToZero(cos(aTheta));
|
||||
double sinTheta = FlushToZero(sin(aTheta));
|
||||
|
||||
// sin(aTheta / 2) * cos(aTheta / 2)
|
||||
double sc = sinTheta / 2;
|
||||
// pow(sin(aTheta / 2), 2)
|
||||
double sq = (1 - cosTheta) / 2;
|
||||
|
||||
_11 = 1 - 2 * (y * y + z * z) * sq;
|
||||
_12 = 2 * (x * y * sq + z * sc);
|
||||
_13 = 2 * (x * z * sq - y * sc);
|
||||
_14 = 0.0f;
|
||||
_21 = 2 * (x * y * sq - z * sc);
|
||||
_22 = 1 - 2 * (x * x + z * z) * sq;
|
||||
_23 = 2 * (y * z * sq + x * sc);
|
||||
_24 = 0.0f;
|
||||
_31 = 2 * (x * z * sq + y * sc);
|
||||
_32 = 2 * (y * z * sq - x * sc);
|
||||
_33 = 1 - 2 * (x * x + y * y) * sq;
|
||||
_34 = 0.0f;
|
||||
_41 = 0.0f;
|
||||
_42 = 0.0f;
|
||||
_43 = 0.0f;
|
||||
_44 = 1.0f;
|
||||
}
|
||||
|
||||
void Perspective(float aDepth)
|
||||
{
|
||||
MOZ_ASSERT(aDepth > 0.0f, "Perspective must be positive!");
|
||||
|
||||
@@ -134,17 +134,6 @@ TransformReferenceBox::Init(const nsSize& aDimensions)
|
||||
mIsCached = true;
|
||||
}
|
||||
|
||||
/* Force small values to zero. We do this to avoid having sin(360deg)
|
||||
* evaluate to a tiny but nonzero value.
|
||||
*/
|
||||
static double FlushToZero(double aVal)
|
||||
{
|
||||
if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON)
|
||||
return 0.0f;
|
||||
else
|
||||
return aVal;
|
||||
}
|
||||
|
||||
float
|
||||
ProcessTranslatePart(const nsCSSValue& aValue,
|
||||
nsStyleContext* aContext,
|
||||
@@ -543,50 +532,13 @@ ProcessRotate3D(Matrix4x4& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 5, "Invalid array!");
|
||||
|
||||
/* We want our matrix to look like this:
|
||||
* | 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 |
|
||||
* (see http://www.w3.org/TR/css3-3d-transforms/#transform-functions)
|
||||
*/
|
||||
|
||||
/* The current spec specifies a matrix that rotates in the wrong direction. For now we just negate
|
||||
* the angle provided to get the correct rotation direction until the spec is updated.
|
||||
* See bug 704468.
|
||||
*/
|
||||
double theta = -aData->Item(4).GetAngleValueInRadians();
|
||||
float cosTheta = FlushToZero(cos(theta));
|
||||
float sinTheta = FlushToZero(sin(theta));
|
||||
|
||||
Point3D vector(aData->Item(1).GetFloatValue(),
|
||||
aData->Item(2).GetFloatValue(),
|
||||
aData->Item(3).GetFloatValue());
|
||||
|
||||
if (!vector.Length()) {
|
||||
return;
|
||||
}
|
||||
vector.Normalize();
|
||||
double theta = aData->Item(4).GetAngleValueInRadians();
|
||||
float x = aData->Item(1).GetFloatValue();
|
||||
float y = aData->Item(2).GetFloatValue();
|
||||
float z = aData->Item(3).GetFloatValue();
|
||||
|
||||
Matrix4x4 temp;
|
||||
|
||||
/* Create our matrix */
|
||||
temp._11 = 1 + (1 - cosTheta) * (vector.x * vector.x - 1);
|
||||
temp._12 = -vector.z * sinTheta + (1 - cosTheta) * vector.x * vector.y;
|
||||
temp._13 = vector.y * sinTheta + (1 - cosTheta) * vector.x * vector.z;
|
||||
temp._14 = 0.0f;
|
||||
temp._21 = vector.z * sinTheta + (1 - cosTheta) * vector.x * vector.y;
|
||||
temp._22 = 1 + (1 - cosTheta) * (vector.y * vector.y - 1);
|
||||
temp._23 = -vector.x * sinTheta + (1 - cosTheta) * vector.y * vector.z;
|
||||
temp._24 = 0.0f;
|
||||
temp._31 = -vector.y * sinTheta + (1 - cosTheta) * vector.x * vector.z;
|
||||
temp._32 = vector.x * sinTheta + (1 - cosTheta) * vector.y * vector.z;
|
||||
temp._33 = 1 + (1 - cosTheta) * (vector.z * vector.z - 1);
|
||||
temp._34 = 0.0f;
|
||||
temp._41 = 0.0f;
|
||||
temp._42 = 0.0f;
|
||||
temp._43 = 0.0f;
|
||||
temp._44 = 1.0f;
|
||||
temp.SetRotateAxisAngle(x, y, z, theta);
|
||||
|
||||
aMatrix = temp * aMatrix;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user