Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(438)

Side by Side Diff: cc/math_util.cc

Issue 11418197: Move temporary MathUtil wrappers to permanent home in gfx::Transform (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebased and addressed reviewer feedback Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/math_util.h" 5 #include "cc/math_util.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <limits> 8 #include <limits>
9 9
10 #include "ui/gfx/quad_f.h" 10 #include "ui/gfx/quad_f.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 numVerticesInClippedQuad++; 100 numVerticesInClippedQuad++;
101 } 101 }
102 102
103 gfx::Rect MathUtil::mapClippedRect(const gfx::Transform& transform, const gfx::R ect& srcRect) 103 gfx::Rect MathUtil::mapClippedRect(const gfx::Transform& transform, const gfx::R ect& srcRect)
104 { 104 {
105 return gfx::ToEnclosingRect(mapClippedRect(transform, gfx::RectF(srcRect))); 105 return gfx::ToEnclosingRect(mapClippedRect(transform, gfx::RectF(srcRect)));
106 } 106 }
107 107
108 gfx::RectF MathUtil::mapClippedRect(const gfx::Transform& transform, const gfx:: RectF& srcRect) 108 gfx::RectF MathUtil::mapClippedRect(const gfx::Transform& transform, const gfx:: RectF& srcRect)
109 { 109 {
110 if (MathUtil::isIdentityOrTranslation(transform)) 110 if (transform.IsIdentityOrTranslation())
111 return srcRect + gfx::Vector2dF(static_cast<float>(transform.matrix().ge tDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3))); 111 return srcRect + gfx::Vector2dF(static_cast<float>(transform.matrix().ge tDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3)));
112 112
113 // Apply the transform, but retain the result in homogeneous coordinates. 113 // Apply the transform, but retain the result in homogeneous coordinates.
114 gfx::QuadF q = gfx::QuadF(srcRect); 114 gfx::QuadF q = gfx::QuadF(srcRect);
115 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(q.p1( ))); 115 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(q.p1( )));
116 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(q.p2( ))); 116 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(q.p2( )));
117 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(q.p3( ))); 117 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(q.p3( )));
118 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(q.p4( ))); 118 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(q.p4( )));
119 119
120 return computeEnclosingClippedRect(h1, h2, h3, h4); 120 return computeEnclosingClippedRect(h1, h2, h3, h4);
121 } 121 }
122 122
123 gfx::RectF MathUtil::projectClippedRect(const gfx::Transform& transform, const g fx::RectF& srcRect) 123 gfx::RectF MathUtil::projectClippedRect(const gfx::Transform& transform, const g fx::RectF& srcRect)
124 { 124 {
125 if (MathUtil::isIdentityOrTranslation(transform)) 125 if (transform.IsIdentityOrTranslation())
126 return srcRect + gfx::Vector2dF(static_cast<float>(transform.matrix().ge tDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3))); 126 return srcRect + gfx::Vector2dF(static_cast<float>(transform.matrix().ge tDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3)));
127 127
128 // Perform the projection, but retain the result in homogeneous coordinates. 128 // Perform the projection, but retain the result in homogeneous coordinates.
129 gfx::QuadF q = gfx::QuadF(srcRect); 129 gfx::QuadF q = gfx::QuadF(srcRect);
130 HomogeneousCoordinate h1 = projectHomogeneousPoint(transform, q.p1()); 130 HomogeneousCoordinate h1 = projectHomogeneousPoint(transform, q.p1());
131 HomogeneousCoordinate h2 = projectHomogeneousPoint(transform, q.p2()); 131 HomogeneousCoordinate h2 = projectHomogeneousPoint(transform, q.p2());
132 HomogeneousCoordinate h3 = projectHomogeneousPoint(transform, q.p3()); 132 HomogeneousCoordinate h3 = projectHomogeneousPoint(transform, q.p3());
133 HomogeneousCoordinate h4 = projectHomogeneousPoint(transform, q.p4()); 133 HomogeneousCoordinate h4 = projectHomogeneousPoint(transform, q.p4());
134 134
135 return computeEnclosingClippedRect(h1, h2, h3, h4); 135 return computeEnclosingClippedRect(h1, h2, h3, h4);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d() ); 234 expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d() );
235 235
236 if (h4.shouldBeClipped() ^ h1.shouldBeClipped()) 236 if (h4.shouldBeClipped() ^ h1.shouldBeClipped())
237 expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointFo rEdge(h4, h1).cartesianPoint2d()); 237 expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointFo rEdge(h4, h1).cartesianPoint2d());
238 238
239 return gfx::RectF(gfx::PointF(xmin, ymin), gfx::SizeF(xmax - xmin, ymax - ym in)); 239 return gfx::RectF(gfx::PointF(xmin, ymin), gfx::SizeF(xmax - xmin, ymax - ym in));
240 } 240 }
241 241
242 gfx::QuadF MathUtil::mapQuad(const gfx::Transform& transform, const gfx::QuadF& q, bool& clipped) 242 gfx::QuadF MathUtil::mapQuad(const gfx::Transform& transform, const gfx::QuadF& q, bool& clipped)
243 { 243 {
244 if (MathUtil::isIdentityOrTranslation(transform)) { 244 if (transform.IsIdentityOrTranslation()) {
245 gfx::QuadF mappedQuad(q); 245 gfx::QuadF mappedQuad(q);
246 mappedQuad += gfx::Vector2dF(static_cast<float>(transform.matrix().getDo uble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3))); 246 mappedQuad += gfx::Vector2dF(static_cast<float>(transform.matrix().getDo uble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3)));
247 clipped = false; 247 clipped = false;
248 return mappedQuad; 248 return mappedQuad;
249 } 249 }
250 250
251 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(q.p1( ))); 251 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(q.p1( )));
252 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(q.p2( ))); 252 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(q.p2( )));
253 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(q.p3( ))); 253 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(q.p3( )));
254 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(q.p4( ))); 254 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(q.p4( )));
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 transform.matrix().setDouble(2, 3, 0); 366 transform.matrix().setDouble(2, 3, 0);
367 } 367 }
368 368
369 static inline float scaleOnAxis(double a, double b, double c) 369 static inline float scaleOnAxis(double a, double b, double c)
370 { 370 {
371 return std::sqrt(a * a + b * b + c * c); 371 return std::sqrt(a * a + b * b + c * c);
372 } 372 }
373 373
374 gfx::Vector2dF MathUtil::computeTransform2dScaleComponents(const gfx::Transform& transform) 374 gfx::Vector2dF MathUtil::computeTransform2dScaleComponents(const gfx::Transform& transform)
375 { 375 {
376 if (hasPerspective(transform)) 376 if (transform.HasPerspective())
377 return gfx::Vector2dF(1, 1); 377 return gfx::Vector2dF(1, 1);
378 float xScale = scaleOnAxis(transform.matrix().getDouble(0, 0), transform.mat rix().getDouble(1, 0), transform.matrix().getDouble(2, 0)); 378 float xScale = scaleOnAxis(transform.matrix().getDouble(0, 0), transform.mat rix().getDouble(1, 0), transform.matrix().getDouble(2, 0));
379 float yScale = scaleOnAxis(transform.matrix().getDouble(0, 1), transform.mat rix().getDouble(1, 1), transform.matrix().getDouble(2, 1)); 379 float yScale = scaleOnAxis(transform.matrix().getDouble(0, 1), transform.mat rix().getDouble(1, 1), transform.matrix().getDouble(2, 1));
380 return gfx::Vector2dF(xScale, yScale); 380 return gfx::Vector2dF(xScale, yScale);
381 } 381 }
382 382
383 float MathUtil::smallestAngleBetweenVectors(gfx::Vector2dF v1, gfx::Vector2dF v2 ) 383 float MathUtil::smallestAngleBetweenVectors(gfx::Vector2dF v1, gfx::Vector2dF v2 )
384 { 384 {
385 double dotProduct = gfx::DotProduct(v1, v2) / v1.Length() / v2.Length(); 385 double dotProduct = gfx::DotProduct(v1, v2) / v1.Length() / v2.Length();
386 // Clamp to compensate for rounding errors. 386 // Clamp to compensate for rounding errors.
387 dotProduct = std::max(-1.0, std::min(1.0, dotProduct)); 387 dotProduct = std::max(-1.0, std::min(1.0, dotProduct));
388 return static_cast<float>(Rad2Deg(std::acos(dotProduct))); 388 return static_cast<float>(Rad2Deg(std::acos(dotProduct)));
389 } 389 }
390 390
391 gfx::Vector2dF MathUtil::projectVector(gfx::Vector2dF source, gfx::Vector2dF des tination) 391 gfx::Vector2dF MathUtil::projectVector(gfx::Vector2dF source, gfx::Vector2dF des tination)
392 { 392 {
393 float projectedLength = gfx::DotProduct(source, destination) / destination.L engthSquared(); 393 float projectedLength = gfx::DotProduct(source, destination) / destination.L engthSquared();
394 return gfx::Vector2dF(projectedLength * destination.x(), projectedLength * d estination.y()); 394 return gfx::Vector2dF(projectedLength * destination.x(), projectedLength * d estination.y());
395 } 395 }
396 396
397 bool MathUtil::isBackFaceVisible(const gfx::Transform& transform)
398 {
399 // Compute whether a layer with a forward-facing normal of (0, 0, 1) would
400 // have its back face visible after applying the transform.
401 //
402 // This is done by transforming the normal and seeing if the resulting z
403 // value is positive or negative. However, note that transforming a normal
404 // actually requires using the inverse-transpose of the original transform.
405
406 // TODO (shawnsingh) make this perform more efficiently - we do not
407 // actually need to instantiate/invert/transpose any matrices, exploiting th e
408 // fact that we only need to transform (0, 0, 1, 0).
409 gfx::Transform inverseTransform = MathUtil::inverse(transform);
410 const SkMatrix44& mInv = inverseTransform.matrix();
411
412 return mInv.getDouble(2, 2) < 0;
413 }
414
415 bool MathUtil::isIdentityOrTranslation(const gfx::Transform& transform)
416 {
417 const SkMatrix44& matrix = transform.matrix();
418
419 bool hasNoPerspective = !matrix.getDouble(3, 0) && !matrix.getDouble(3, 1) & & !matrix.getDouble(3, 2) && (matrix.getDouble(3, 3) == 1);
420 bool hasNoRotationOrSkew = !matrix.getDouble(0, 1) && !matrix.getDouble(0, 2 ) && !matrix.getDouble(1, 0) &&
421 !matrix.getDouble(1, 2) && !matrix.getDouble(2, 0) && !matrix.getDouble( 2, 1);
422 bool hasNoScale = matrix.getDouble(0, 0) == 1 && matrix.getDouble(1, 1) == 1 && matrix.getDouble(2, 2) == 1;
423
424 return hasNoPerspective && hasNoRotationOrSkew && hasNoScale;
425 }
426
427 bool MathUtil::hasPerspective(const gfx::Transform& transform)
428 {
429 // Mathematically it is a bit too strict to expect the 4th element to be
430 // equal to 1. However, the only non-perspective case where this element
431 // becomes non-1 is when it was explicitly initialized. In that case it
432 // still causes us to have a nontrivial divide-by-w, so we count it as
433 // being perspective here.
434 const SkMatrix44& matrix = transform.matrix();
435 return matrix.getDouble(3, 0) || matrix.getDouble(3, 1) || matrix.getDouble( 3, 2) || (matrix.getDouble(3, 3) != 1);
436 }
437
438 void MathUtil::rotateEulerAngles(gfx::Transform* transform, double eulerX, doubl e eulerY, double eulerZ) 397 void MathUtil::rotateEulerAngles(gfx::Transform* transform, double eulerX, doubl e eulerY, double eulerZ)
439 { 398 {
440 // TODO (shawnsingh): make this implementation faster and more accurate by 399 // TODO (shawnsingh): make this implementation faster and more accurate by
441 // hard-coding each matrix instead of calling rotateAxisAngle(). 400 // hard-coding each matrix instead of calling RotateAbout().
442 gfx::Transform rotationAboutX; 401 gfx::Transform rotationAboutX;
443 gfx::Transform rotationAboutY; 402 gfx::Transform rotationAboutY;
444 gfx::Transform rotationAboutZ; 403 gfx::Transform rotationAboutZ;
445 404
446 MathUtil::rotateAxisAngle(&rotationAboutX, 1, 0, 0, eulerX); 405 rotationAboutX.RotateAboutXAxis(eulerX);
447 MathUtil::rotateAxisAngle(&rotationAboutY, 0, 1, 0, eulerY); 406 rotationAboutY.RotateAboutYAxis(eulerY);
448 MathUtil::rotateAxisAngle(&rotationAboutZ, 0, 0, 1, eulerZ); 407 rotationAboutZ.RotateAboutZAxis(eulerZ);
449 408
450 gfx::Transform composite = rotationAboutZ * rotationAboutY * rotationAboutX; 409 gfx::Transform composite = rotationAboutZ * rotationAboutY * rotationAboutX;
451 transform->PreconcatTransform(composite); 410 transform->PreconcatTransform(composite);
452 } 411 }
453 412
454 void MathUtil::rotateAxisAngle(gfx::Transform* transform, double i, double j, do uble k, double degrees)
455 {
456 gfx::Vector3dF axis(i, j, k);
457 transform->RotateAbout(axis, degrees);
458 }
459
460 gfx::Transform MathUtil::inverse(const gfx::Transform& transform) 413 gfx::Transform MathUtil::inverse(const gfx::Transform& transform)
461 { 414 {
462 gfx::Transform result; 415 gfx::Transform result;
463 bool invertedSuccessfully = transform.GetInverse(&result); 416 bool invertedSuccessfully = transform.GetInverse(&result);
464 417
465 if (invertedSuccessfully) 418 if (invertedSuccessfully)
466 return result; 419 return result;
467 420
468 // If transform was un-invertible, then just return identity. 421 // If transform was un-invertible, then just return identity.
469 return gfx::Transform(); 422 return gfx::Transform();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 matrix.setDouble(1, 0, b); 482 matrix.setDouble(1, 0, b);
530 matrix.setDouble(0, 1, c); 483 matrix.setDouble(0, 1, c);
531 matrix.setDouble(1, 1, d); 484 matrix.setDouble(1, 1, d);
532 matrix.setDouble(0, 3, e); 485 matrix.setDouble(0, 3, e);
533 matrix.setDouble(1, 3, f); 486 matrix.setDouble(1, 3, f);
534 487
535 return result; 488 return result;
536 } 489 }
537 490
538 } // namespace cc 491 } // namespace cc
OLDNEW
« no previous file with comments | « cc/math_util.h ('k') | cc/math_util_unittest.cc » ('j') | cc/math_util_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698