void Matrix4x4::RotateZ(double aTheta) { // XXX Is double precision really necessary here double cosTheta = FlushToZero(cos(aTheta)); double sinTheta = FlushToZero(sin(aTheta)); float temp; temp = _11; _11 = cosTheta * _11 + sinTheta * _21; _21 = -sinTheta * temp + cosTheta * _21; temp = _12; _12 = cosTheta * _12 + sinTheta * _22; _22 = -sinTheta * temp + cosTheta * _22; temp = _13; _13 = cosTheta * _13 + sinTheta * _23; _23 = -sinTheta * temp + cosTheta * _23; temp = _14; _14 = cosTheta * _14 + sinTheta * _24; _24 = -sinTheta * temp + cosTheta * _24; }
void Matrix4x4::RotateY(double aTheta) { // XXX Is double precision really necessary here double cosTheta = FlushToZero(cos(aTheta)); double sinTheta = FlushToZero(sin(aTheta)); float temp; temp = _11; _11 = cosTheta * _11 + -sinTheta * _31; _31 = sinTheta * temp + cosTheta * _31; temp = _12; _12 = cosTheta * _12 + -sinTheta * _32; _32 = sinTheta * temp + cosTheta * _32; temp = _13; _13 = cosTheta * _13 + -sinTheta * _33; _33 = sinTheta * temp + cosTheta * _33; temp = _14; _14 = cosTheta * _14 + -sinTheta * _34; _34 = sinTheta * temp + cosTheta * _34; }
void Matrix4x4::RotateX(double aTheta) { // XXX Is double precision really necessary here double cosTheta = FlushToZero(cos(aTheta)); double sinTheta = FlushToZero(sin(aTheta)); float temp; temp = _21; _21 = cosTheta * _21 + sinTheta * _31; _31 = -sinTheta * temp + cosTheta * _31; temp = _22; _22 = cosTheta * _22 + sinTheta * _32; _32 = -sinTheta * temp + cosTheta * _32; temp = _23; _23 = cosTheta * _23 + sinTheta * _33; _33 = -sinTheta * temp + cosTheta * _33; temp = _24; _24 = cosTheta * _24 + sinTheta * _34; _34 = -sinTheta * temp + cosTheta * _34; }
static void ProcessRotate3D(gfx3DMatrix& 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)); float x = aData->Item(1).GetFloatValue(); float y = aData->Item(2).GetFloatValue(); float z = aData->Item(3).GetFloatValue(); /* Normalize [x,y,z] */ float length = sqrt(x*x + y*y + z*z); if (length == 0.0) { return; } x /= length; y /= length; z /= length; gfx3DMatrix temp; /* Create our matrix */ temp._11 = 1 + (1 - cosTheta) * (x * x - 1); temp._12 = -z * sinTheta + (1 - cosTheta) * x * y; temp._13 = y * sinTheta + (1 - cosTheta) * x * z; temp._14 = 0.0f; temp._21 = z * sinTheta + (1 - cosTheta) * x * y; temp._22 = 1 + (1 - cosTheta) * (y * y - 1); temp._23 = -x * sinTheta + (1 - cosTheta) * y * z; temp._24 = 0.0f; temp._31 = -y * sinTheta + (1 - cosTheta) * x * z; temp._32 = x * sinTheta + (1 - cosTheta) * y * z; temp._33 = 1 + (1 - cosTheta) * (z * z - 1); temp._34 = 0.0f; temp._41 = 0.0f; temp._42 = 0.0f; temp._43 = 0.0f; temp._44 = 1.0f; aMatrix = temp * aMatrix; }
static void 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(); 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; aMatrix = temp * aMatrix; }
/* static */ gfx3DMatrix nsStyleTransformMatrix::ProcessRotate3D(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) */ double theta = aData->Item(4).GetAngleValueInRadians(); float cosTheta = FlushToZero(cos(theta)); float sinTheta = FlushToZero(sin(theta)); float x = aData->Item(1).GetFloatValue(); float y = aData->Item(2).GetFloatValue(); float z = aData->Item(3).GetFloatValue(); /* Normalize [x,y,z] */ float length = sqrt(x*x + y*y + z*z); if (length == 0.0) { return gfx3DMatrix(); } x /= length; y /= length; z /= length; gfx3DMatrix temp; /* Create our matrix */ temp._11 = 1 + (1 - cosTheta) * (x * x - 1); temp._12 = -z * sinTheta + (1 - cosTheta) * x * y; temp._13 = y * sinTheta + (1 - cosTheta) * x * z; temp._14 = 0.0f; temp._21 = z * sinTheta + (1 - cosTheta) * x * y; temp._22 = 1 + (1 - cosTheta) * (y * y - 1); temp._23 = -x * sinTheta + (1 - cosTheta) * y * z; temp._24 = 0.0f; temp._31 = -y * sinTheta + (1 - cosTheta) * x * z; temp._32 = x * sinTheta + (1 - cosTheta) * y * z; temp._33 = 1 + (1 - cosTheta) * (z * z - 1); temp._34 = 0.0f; temp._41 = 0.0f; temp._42 = 0.0f; temp._43 = 0.0f; temp._44 = 1.0f; return temp; }
/* Function that converts a rotate transform into a matrix. */ static void ProcessRotate(float aMain[4], const nsCSSValue::Array* aData) { NS_PRECONDITION(aData->Count() == 2, "Invalid array!"); /* We want our matrix to look like this: * | cos(theta) -sin(theta) 0| * | sin(theta) cos(theta) 0| * | 0 0 1| * (see http://www.w3.org/TR/SVG/coords.html#RotationDefined) */ double theta = aData->Item(1).GetAngleValueInRadians(); float cosTheta = FlushToZero(cos(theta)); float sinTheta = FlushToZero(sin(theta)); aMain[0] = cosTheta; aMain[1] = sinTheta; aMain[2] = -sinTheta; aMain[3] = cosTheta; }
/* static */ gfx3DMatrix nsStyleTransformMatrix::ProcessRotateY(const nsCSSValue::Array* aData) { NS_PRECONDITION(aData->Count() == 2, "Invalid array!"); /* We want our matrix to look like this: * | cos(theta) 0 -sin(theta) 0 | * | 0 1 0 0 | * | sin(theta) 0 cos(theta) 0 | * | 0 0 0 1 | * (see http://www.w3.org/TR/SVG/coords.html#RotationDefined) */ double theta = aData->Item(1).GetAngleValueInRadians(); float cosTheta = FlushToZero(cos(theta)); float sinTheta = FlushToZero(sin(theta)); gfx3DMatrix temp; temp._11 = cosTheta; temp._13 = -sinTheta; temp._31 = sinTheta; temp._33 = cosTheta; return temp; }
/* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is * undefined or very large, SafeTangent returns a manageably large value * of the correct sign. */ static double SafeTangent(double aTheta) { const double kEpsilon = 0.0001; /* tan(theta) = sin(theta)/cos(theta); problems arise when * cos(theta) is too close to zero. Limit cos(theta) to the * range [-1, -epsilon] U [epsilon, 1]. */ double sinTheta = sin(aTheta); double cosTheta = cos(aTheta); if (cosTheta >= 0 && cosTheta < kEpsilon) cosTheta = kEpsilon; else if (cosTheta < 0 && cosTheta >= -kEpsilon) cosTheta = -kEpsilon; return FlushToZero(sinTheta / cosTheta); }