void TransformationMatrix::blend(const TransformationMatrix& from, double progress) { if (from.isIdentity() && isIdentity()) return; // decompose DecomposedType fromDecomp; DecomposedType toDecomp; from.decompose(fromDecomp); decompose(toDecomp); // interpolate blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress); blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress); blendFloat(fromDecomp.scaleZ, toDecomp.scaleZ, progress); blendFloat(fromDecomp.skewXY, toDecomp.skewXY, progress); blendFloat(fromDecomp.skewXZ, toDecomp.skewXZ, progress); blendFloat(fromDecomp.skewYZ, toDecomp.skewYZ, progress); blendFloat(fromDecomp.translateX, toDecomp.translateX, progress); blendFloat(fromDecomp.translateY, toDecomp.translateY, progress); blendFloat(fromDecomp.translateZ, toDecomp.translateZ, progress); blendFloat(fromDecomp.perspectiveX, toDecomp.perspectiveX, progress); blendFloat(fromDecomp.perspectiveY, toDecomp.perspectiveY, progress); blendFloat(fromDecomp.perspectiveZ, toDecomp.perspectiveZ, progress); blendFloat(fromDecomp.perspectiveW, toDecomp.perspectiveW, progress); slerp(&fromDecomp.quaternionX, &toDecomp.quaternionX, progress); // recompose recompose(fromDecomp); }
PassRefPtr<TransformOperation> PerspectiveTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) { if (from && !from->isSameType(*this)) return this; if (blendToIdentity) { double p = WebCore::blend(m_p, 1., progress); // FIXME: this seems wrong. https://bugs.webkit.org/show_bug.cgi?id=52700 return PerspectiveTransformOperation::create(clampToPositiveInteger(p)); } const PerspectiveTransformOperation* fromOp = static_cast<const PerspectiveTransformOperation*>(from); TransformationMatrix fromT; TransformationMatrix toT; fromT.applyPerspective(fromOp ? fromOp->m_p : 0); toT.applyPerspective(m_p); toT.blend(fromT, progress); TransformationMatrix::DecomposedType decomp; toT.decompose(decomp); if (decomp.perspectiveZ) { double val = -1.0 / decomp.perspectiveZ; return PerspectiveTransformOperation::create(clampToPositiveInteger(val)); } return PerspectiveTransformOperation::create(0); }
PassRefPtr<TransformOperation> PerspectiveTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) { if (from && !from->isSameType(*this)) return this; if (blendToIdentity) return PerspectiveTransformOperation::create(m_p + (1. - m_p) * progress); const PerspectiveTransformOperation* fromOp = static_cast<const PerspectiveTransformOperation*>(from); double fromP = fromOp ? fromOp->m_p : 0; double toP = m_p; TransformationMatrix fromT; TransformationMatrix toT; fromT.applyPerspective(fromP); toT.applyPerspective(toP); toT.blend(fromT, progress); TransformationMatrix::DecomposedType decomp; toT.decompose(decomp); return PerspectiveTransformOperation::create(decomp.perspectiveZ ? -1.0 / decomp.perspectiveZ : 0.0); }
PassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) { if (from && !from->isSameType(*this)) return this; if (blendToIdentity) return RotateTransformOperation::create(m_x, m_y, m_z, m_angle - m_angle * progress, m_type); const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from); // Optimize for single axis rotation if (!fromOp || (fromOp->m_x == 0 && fromOp->m_y == 0 && fromOp->m_z == 1) || (fromOp->m_x == 0 && fromOp->m_y == 1 && fromOp->m_z == 0) || (fromOp->m_x == 1 && fromOp->m_y == 0 && fromOp->m_z == 0)) { double fromAngle = fromOp ? fromOp->m_angle : 0; return RotateTransformOperation::create(fromOp ? fromOp->m_x : m_x, fromOp ? fromOp->m_y : m_y, fromOp ? fromOp->m_z : m_z, UI::blend(fromAngle, m_angle, progress), m_type); } const RotateTransformOperation* toOp = this; // Create the 2 rotation matrices TransformationMatrix fromT; TransformationMatrix toT; fromT.rotate3d((float)(fromOp ? fromOp->m_x : 0), (float)(fromOp ? fromOp->m_y : 0), (float)(fromOp ? fromOp->m_z : 1), (float)(fromOp ? fromOp->m_angle : 0)); toT.rotate3d((float)(toOp ? toOp->m_x : 0), (float)(toOp ? toOp->m_y : 0), (float)(toOp ? toOp->m_z : 1), (float)(toOp ? toOp->m_angle : 0)); // Blend them toT.blend(fromT, progress); // Extract the result as a quaternion TransformationMatrix::DecomposedType decomp; toT.decompose(decomp); // Convert that to Axis/Angle form double x = -decomp.quaternionX; double y = -decomp.quaternionY; double z = -decomp.quaternionZ; double length = sqrt(x * x + y * y + z * z); double angle = 0; if (length > 0.00001) { x /= length; y /= length; z /= length; angle = rad2deg(acos(decomp.quaternionW) * 2); } else { x = 0; y = 0; z = 1; } return RotateTransformOperation::create(x, y, z, angle, ROTATE_3D); }