diff options
Diffstat (limited to 'cc/math_util.cc')
-rw-r--r-- | cc/math_util.cc | 114 |
1 files changed, 53 insertions, 61 deletions
diff --git a/cc/math_util.cc b/cc/math_util.cc index a9c0c82..9312d10 100644 --- a/cc/math_util.cc +++ b/cc/math_util.cc @@ -11,10 +11,8 @@ #include "ui/gfx/rect.h" #include "ui/gfx/rect_conversions.h" #include "ui/gfx/rect_f.h" +#include "ui/gfx/transform.h" #include "ui/gfx/vector2d_f.h" -#include <public/WebTransformationMatrix.h> - -using WebKit::WebTransformationMatrix; namespace cc { @@ -22,39 +20,39 @@ const double MathUtil::PI_DOUBLE = 3.14159265358979323846; const float MathUtil::PI_FLOAT = 3.14159265358979323846f; const double MathUtil::EPSILON = 1e-9; -static HomogeneousCoordinate projectHomogeneousPoint(const WebTransformationMatrix& transform, const gfx::PointF& p) +static HomogeneousCoordinate projectHomogeneousPoint(const gfx::Transform& transform, const gfx::PointF& p) { // In this case, the layer we are trying to project onto is perpendicular to ray // (point p and z-axis direction) that we are trying to project. This happens when the // layer is rotated so that it is infinitesimally thin, or when it is co-planar with // the camera origin -- i.e. when the layer is invisible anyway. - if (!transform.m33()) + if (!transform.matrix().getDouble(2, 2)) return HomogeneousCoordinate(0, 0, 0, 1); double x = p.x(); double y = p.y(); - double z = -(transform.m13() * x + transform.m23() * y + transform.m43()) / transform.m33(); + double z = -(transform.matrix().getDouble(2, 0) * x + transform.matrix().getDouble(2, 1) * y + transform.matrix().getDouble(2, 3)) / transform.matrix().getDouble(2, 2); // implicit definition of w = 1; - double outX = x * transform.m11() + y * transform.m21() + z * transform.m31() + transform.m41(); - double outY = x * transform.m12() + y * transform.m22() + z * transform.m32() + transform.m42(); - double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33() + transform.m43(); - double outW = x * transform.m14() + y * transform.m24() + z * transform.m34() + transform.m44(); + double outX = x * transform.matrix().getDouble(0, 0) + y * transform.matrix().getDouble(0, 1) + z * transform.matrix().getDouble(0, 2) + transform.matrix().getDouble(0, 3); + double outY = x * transform.matrix().getDouble(1, 0) + y * transform.matrix().getDouble(1, 1) + z * transform.matrix().getDouble(1, 2) + transform.matrix().getDouble(1, 3); + double outZ = x * transform.matrix().getDouble(2, 0) + y * transform.matrix().getDouble(2, 1) + z * transform.matrix().getDouble(2, 2) + transform.matrix().getDouble(2, 3); + double outW = x * transform.matrix().getDouble(3, 0) + y * transform.matrix().getDouble(3, 1) + z * transform.matrix().getDouble(3, 2) + transform.matrix().getDouble(3, 3); return HomogeneousCoordinate(outX, outY, outZ, outW); } -static HomogeneousCoordinate mapHomogeneousPoint(const WebTransformationMatrix& transform, const gfx::Point3F& p) +static HomogeneousCoordinate mapHomogeneousPoint(const gfx::Transform& transform, const gfx::Point3F& p) { double x = p.x(); double y = p.y(); double z = p.z(); // implicit definition of w = 1; - double outX = x * transform.m11() + y * transform.m21() + z * transform.m31() + transform.m41(); - double outY = x * transform.m12() + y * transform.m22() + z * transform.m32() + transform.m42(); - double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33() + transform.m43(); - double outW = x * transform.m14() + y * transform.m24() + z * transform.m34() + transform.m44(); + double outX = x * transform.matrix().getDouble(0, 0) + y * transform.matrix().getDouble(0, 1) + z * transform.matrix().getDouble(0, 2) + transform.matrix().getDouble(0, 3); + double outY = x * transform.matrix().getDouble(1, 0) + y * transform.matrix().getDouble(1, 1) + z * transform.matrix().getDouble(1, 2) + transform.matrix().getDouble(1, 3); + double outZ = x * transform.matrix().getDouble(2, 0) + y * transform.matrix().getDouble(2, 1) + z * transform.matrix().getDouble(2, 2) + transform.matrix().getDouble(2, 3); + double outW = x * transform.matrix().getDouble(3, 0) + y * transform.matrix().getDouble(3, 1) + z * transform.matrix().getDouble(3, 2) + transform.matrix().getDouble(3, 3); return HomogeneousCoordinate(outX, outY, outZ, outW); } @@ -102,15 +100,15 @@ static inline void addVertexToClippedQuad(const gfx::PointF& newVertex, gfx::Poi numVerticesInClippedQuad++; } -gfx::Rect MathUtil::mapClippedRect(const WebTransformationMatrix& transform, const gfx::Rect& srcRect) +gfx::Rect MathUtil::mapClippedRect(const gfx::Transform& transform, const gfx::Rect& srcRect) { return gfx::ToEnclosingRect(mapClippedRect(transform, gfx::RectF(srcRect))); } -gfx::RectF MathUtil::mapClippedRect(const WebTransformationMatrix& transform, const gfx::RectF& srcRect) +gfx::RectF MathUtil::mapClippedRect(const gfx::Transform& transform, const gfx::RectF& srcRect) { - if (transform.isIdentityOrTranslation()) - return srcRect + gfx::Vector2dF(static_cast<float>(transform.m41()), static_cast<float>(transform.m42())); + if (MathUtil::isIdentityOrTranslation(transform)) + return srcRect + gfx::Vector2dF(static_cast<float>(transform.matrix().getDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3))); // Apply the transform, but retain the result in homogeneous coordinates. gfx::QuadF q = gfx::QuadF(srcRect); @@ -122,10 +120,10 @@ gfx::RectF MathUtil::mapClippedRect(const WebTransformationMatrix& transform, co return computeEnclosingClippedRect(h1, h2, h3, h4); } -gfx::RectF MathUtil::projectClippedRect(const WebTransformationMatrix& transform, const gfx::RectF& srcRect) +gfx::RectF MathUtil::projectClippedRect(const gfx::Transform& transform, const gfx::RectF& srcRect) { - if (transform.isIdentityOrTranslation()) - return srcRect + gfx::Vector2dF(static_cast<float>(transform.m41()), static_cast<float>(transform.m42())); + if (MathUtil::isIdentityOrTranslation(transform)) + return srcRect + gfx::Vector2dF(static_cast<float>(transform.matrix().getDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3))); // Perform the projection, but retain the result in homogeneous coordinates. gfx::QuadF q = gfx::QuadF(srcRect); @@ -137,7 +135,7 @@ gfx::RectF MathUtil::projectClippedRect(const WebTransformationMatrix& transform return computeEnclosingClippedRect(h1, h2, h3, h4); } -void MathUtil::mapClippedQuad(const WebTransformationMatrix& transform, const gfx::QuadF& srcQuad, gfx::PointF clippedQuad[8], int& numVerticesInClippedQuad) +void MathUtil::mapClippedQuad(const gfx::Transform& transform, const gfx::QuadF& srcQuad, gfx::PointF clippedQuad[8], int& numVerticesInClippedQuad) { HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(srcQuad.p1())); HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(srcQuad.p2())); @@ -241,11 +239,11 @@ gfx::RectF MathUtil::computeEnclosingClippedRect(const HomogeneousCoordinate& h1 return gfx::RectF(gfx::PointF(xmin, ymin), gfx::SizeF(xmax - xmin, ymax - ymin)); } -gfx::QuadF MathUtil::mapQuad(const WebTransformationMatrix& transform, const gfx::QuadF& q, bool& clipped) +gfx::QuadF MathUtil::mapQuad(const gfx::Transform& transform, const gfx::QuadF& q, bool& clipped) { - if (transform.isIdentityOrTranslation()) { + if (MathUtil::isIdentityOrTranslation(transform)) { gfx::QuadF mappedQuad(q); - mappedQuad += gfx::Vector2dF(static_cast<float>(transform.m41()), static_cast<float>(transform.m42())); + mappedQuad += gfx::Vector2dF(static_cast<float>(transform.matrix().getDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3))); clipped = false; return mappedQuad; } @@ -261,7 +259,7 @@ gfx::QuadF MathUtil::mapQuad(const WebTransformationMatrix& transform, const gfx return gfx::QuadF(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d()); } -gfx::PointF MathUtil::mapPoint(const WebTransformationMatrix& transform, const gfx::PointF& p, bool& clipped) +gfx::PointF MathUtil::mapPoint(const gfx::Transform& transform, const gfx::PointF& p, bool& clipped) { HomogeneousCoordinate h = mapHomogeneousPoint(transform, gfx::Point3F(p)); @@ -284,7 +282,7 @@ gfx::PointF MathUtil::mapPoint(const WebTransformationMatrix& transform, const g return h.cartesianPoint2d(); } -gfx::Point3F MathUtil::mapPoint(const WebTransformationMatrix& transform, const gfx::Point3F& p, bool& clipped) +gfx::Point3F MathUtil::mapPoint(const gfx::Transform& transform, const gfx::Point3F& p, bool& clipped) { HomogeneousCoordinate h = mapHomogeneousPoint(transform, p); @@ -307,7 +305,7 @@ gfx::Point3F MathUtil::mapPoint(const WebTransformationMatrix& transform, const return h.cartesianPoint3d(); } -gfx::QuadF MathUtil::projectQuad(const WebTransformationMatrix& transform, const gfx::QuadF& q, bool& clipped) +gfx::QuadF MathUtil::projectQuad(const gfx::Transform& transform, const gfx::QuadF& q, bool& clipped) { gfx::QuadF projectedQuad; bool clippedPoint; @@ -323,7 +321,7 @@ gfx::QuadF MathUtil::projectQuad(const WebTransformationMatrix& transform, const return projectedQuad; } -gfx::PointF MathUtil::projectPoint(const WebTransformationMatrix& transform, const gfx::PointF& p, bool& clipped) +gfx::PointF MathUtil::projectPoint(const gfx::Transform& transform, const gfx::PointF& p, bool& clipped) { HomogeneousCoordinate h = projectHomogeneousPoint(transform, p); @@ -347,7 +345,7 @@ gfx::PointF MathUtil::projectPoint(const WebTransformationMatrix& transform, con return h.cartesianPoint2d(); } -void MathUtil::flattenTransformTo2d(WebTransformationMatrix& transform) +void MathUtil::flattenTransformTo2d(gfx::Transform& transform) { // Set both the 3rd row and 3rd column to (0, 0, 1, 0). // @@ -359,13 +357,13 @@ void MathUtil::flattenTransformTo2d(WebTransformationMatrix& transform) // - Because of linearity of transforms, this flattened transform also preserves the // effect that any subsequent (post-multiplied) transforms would have on z values. // - transform.setM13(0); - transform.setM23(0); - transform.setM31(0); - transform.setM32(0); - transform.setM33(1); - transform.setM34(0); - transform.setM43(0); + transform.matrix().setDouble(2, 0, 0); + transform.matrix().setDouble(2, 1, 0); + transform.matrix().setDouble(0, 2, 0); + transform.matrix().setDouble(1, 2, 0); + transform.matrix().setDouble(2, 2, 1); + transform.matrix().setDouble(3, 2, 0); + transform.matrix().setDouble(2, 3, 0); } static inline float scaleOnAxis(double a, double b, double c) @@ -373,12 +371,12 @@ static inline float scaleOnAxis(double a, double b, double c) return std::sqrt(a * a + b * b + c * c); } -gfx::Vector2dF MathUtil::computeTransform2dScaleComponents(const WebTransformationMatrix& transform) +gfx::Vector2dF MathUtil::computeTransform2dScaleComponents(const gfx::Transform& transform) { - if (transform.hasPerspective()) + if (hasPerspective(transform)) return gfx::Vector2dF(1, 1); - float xScale = scaleOnAxis(transform.m11(), transform.m12(), transform.m13()); - float yScale = scaleOnAxis(transform.m21(), transform.m22(), transform.m23()); + float xScale = scaleOnAxis(transform.matrix().getDouble(0, 0), transform.matrix().getDouble(1, 0), transform.matrix().getDouble(2, 0)); + float yScale = scaleOnAxis(transform.matrix().getDouble(0, 1), transform.matrix().getDouble(1, 1), transform.matrix().getDouble(2, 1)); return gfx::Vector2dF(xScale, yScale); } @@ -396,23 +394,22 @@ gfx::Vector2dF MathUtil::projectVector(gfx::Vector2dF source, gfx::Vector2dF des return gfx::Vector2dF(projectedLength * destination.x(), projectedLength * destination.y()); } -bool MathUtil::isInvertible(const gfx::Transform& transform) +bool MathUtil::isBackFaceVisible(const gfx::Transform& transform) { - const SkMatrix44& matrix = transform.matrix(); - double determinant = matrix.determinant(); - return abs(determinant) > EPSILON; -} + // Compute whether a layer with a forward-facing normal of (0, 0, 1) would + // have its back face visible after applying the transform. + // + // This is done by transforming the normal and seeing if the resulting z + // value is positive or negative. However, note that transforming a normal + // actually requires using the inverse-transpose of the original transform. -bool MathUtil::isBackFaceVisible(const gfx::Transform&) -{ - // TODO (shawnsingh): to be implemented in a follow up patch very soon. - NOTREACHED(); - return false; -} + // TODO (shawnsingh) make this perform more efficiently - we do not + // actually need to instantiate/invert/transpose any matrices, exploiting the + // fact that we only need to transform (0, 0, 1, 0). + gfx::Transform inverseTransform = MathUtil::inverse(transform); + const SkMatrix44& mInv = inverseTransform.matrix(); -bool MathUtil::isIdentity(const gfx::Transform& transform) -{ - return transform.matrix().isIdentity(); + return mInv.getDouble(2, 2) < 0; } bool MathUtil::isIdentityOrTranslation(const gfx::Transform& transform) @@ -438,11 +435,6 @@ bool MathUtil::hasPerspective(const gfx::Transform& transform) return matrix.getDouble(3, 0) || matrix.getDouble(3, 1) || matrix.getDouble(3, 2) || (matrix.getDouble(3, 3) != 1); } -void MathUtil::makeIdentity(gfx::Transform* transform) -{ - transform->matrix().setIdentity(); -} - void MathUtil::rotateEulerAngles(gfx::Transform* transform, double eulerX, double eulerY, double eulerZ) { // TODO (shawnsingh): make this implementation faster and more accurate by |