OLD | NEW |
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" |
11 #include "ui/gfx/rect.h" | 11 #include "ui/gfx/rect.h" |
12 #include "ui/gfx/rect_conversions.h" | 12 #include "ui/gfx/rect_conversions.h" |
13 #include "ui/gfx/rect_f.h" | 13 #include "ui/gfx/rect_f.h" |
14 #include "ui/gfx/vector2d_f.h" | 14 #include "ui/gfx/vector2d_f.h" |
15 #include <public/WebTransformationMatrix.h> | 15 #include <public/WebTransformationMatrix.h> |
16 | 16 |
17 using WebKit::WebTransformationMatrix; | 17 using WebKit::WebTransformationMatrix; |
18 | 18 |
19 namespace cc { | 19 namespace cc { |
20 | 20 |
21 const double MathUtil::PI_DOUBLE = 3.14159265358979323846; | 21 const double MathUtil::PI_DOUBLE = 3.14159265358979323846; |
22 const float MathUtil::PI_FLOAT = 3.14159265358979323846f; | 22 const float MathUtil::PI_FLOAT = 3.14159265358979323846f; |
| 23 const double MathUtil::EPSILON = 1e-9; |
23 | 24 |
24 static HomogeneousCoordinate projectHomogeneousPoint(const WebTransformationMatr
ix& transform, const gfx::PointF& p) | 25 static HomogeneousCoordinate projectHomogeneousPoint(const WebTransformationMatr
ix& transform, const gfx::PointF& p) |
25 { | 26 { |
26 // In this case, the layer we are trying to project onto is perpendicular to
ray | 27 // In this case, the layer we are trying to project onto is perpendicular to
ray |
27 // (point p and z-axis direction) that we are trying to project. This happen
s when the | 28 // (point p and z-axis direction) that we are trying to project. This happen
s when the |
28 // layer is rotated so that it is infinitesimally thin, or when it is co-pla
nar with | 29 // layer is rotated so that it is infinitesimally thin, or when it is co-pla
nar with |
29 // the camera origin -- i.e. when the layer is invisible anyway. | 30 // the camera origin -- i.e. when the layer is invisible anyway. |
30 if (!transform.m33()) | 31 if (!transform.m33()) |
31 return HomogeneousCoordinate(0, 0, 0, 1); | 32 return HomogeneousCoordinate(0, 0, 0, 1); |
32 | 33 |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 dotProduct = std::max(-1.0, std::min(1.0, dotProduct)); | 389 dotProduct = std::max(-1.0, std::min(1.0, dotProduct)); |
389 return static_cast<float>(Rad2Deg(std::acos(dotProduct))); | 390 return static_cast<float>(Rad2Deg(std::acos(dotProduct))); |
390 } | 391 } |
391 | 392 |
392 gfx::Vector2dF MathUtil::projectVector(gfx::Vector2dF source, gfx::Vector2dF des
tination) | 393 gfx::Vector2dF MathUtil::projectVector(gfx::Vector2dF source, gfx::Vector2dF des
tination) |
393 { | 394 { |
394 float projectedLength = gfx::DotProduct(source, destination) / destination.L
engthSquared(); | 395 float projectedLength = gfx::DotProduct(source, destination) / destination.L
engthSquared(); |
395 return gfx::Vector2dF(projectedLength * destination.x(), projectedLength * d
estination.y()); | 396 return gfx::Vector2dF(projectedLength * destination.x(), projectedLength * d
estination.y()); |
396 } | 397 } |
397 | 398 |
| 399 bool MathUtil::isInvertible(const gfx::Transform& transform) |
| 400 { |
| 401 const SkMatrix44& matrix = transform.matrix(); |
| 402 double determinant = matrix.determinant(); |
| 403 return abs(determinant) > EPSILON; |
| 404 } |
| 405 |
| 406 bool MathUtil::isBackFaceVisible(const gfx::Transform&) |
| 407 { |
| 408 // TODO (shawnsingh): to be implemented in a follow up patch very soon. |
| 409 NOTREACHED(); |
| 410 return false; |
| 411 } |
| 412 |
| 413 bool MathUtil::isIdentity(const gfx::Transform& transform) |
| 414 { |
| 415 return transform.matrix().isIdentity(); |
| 416 } |
| 417 |
| 418 bool MathUtil::isIdentityOrTranslation(const gfx::Transform& transform) |
| 419 { |
| 420 const SkMatrix44& matrix = transform.matrix(); |
| 421 |
| 422 bool hasNoPerspective = !matrix.getDouble(3, 0) && !matrix.getDouble(3, 1) &
& !matrix.getDouble(3, 2) && (matrix.getDouble(3, 3) == 1); |
| 423 bool hasNoRotationOrSkew = !matrix.getDouble(0, 1) && !matrix.getDouble(0, 2
) && !matrix.getDouble(1, 0) && |
| 424 !matrix.getDouble(1, 2) && !matrix.getDouble(2, 0) && !matrix.getDouble(
2, 1); |
| 425 bool hasNoScale = matrix.getDouble(0, 0) == 1 && matrix.getDouble(1, 1) == 1
&& matrix.getDouble(2, 2) == 1; |
| 426 |
| 427 return hasNoPerspective && hasNoRotationOrSkew && hasNoScale; |
| 428 } |
| 429 |
| 430 bool MathUtil::hasPerspective(const gfx::Transform& transform) |
| 431 { |
| 432 // Mathematically it is a bit too strict to expect the 4th element to be |
| 433 // equal to 1. However, the only non-perspective case where this element |
| 434 // becomes non-1 is when it was explicitly initialized. In that case it |
| 435 // still causes us to have a nontrivial divide-by-w, so we count it as |
| 436 // being perspective here. |
| 437 const SkMatrix44& matrix = transform.matrix(); |
| 438 return matrix.getDouble(3, 0) || matrix.getDouble(3, 1) || matrix.getDouble(
3, 2) || (matrix.getDouble(3, 3) != 1); |
| 439 } |
| 440 |
| 441 void MathUtil::makeIdentity(gfx::Transform* transform) |
| 442 { |
| 443 transform->matrix().setIdentity(); |
| 444 } |
| 445 |
| 446 void MathUtil::rotateEulerAngles(gfx::Transform* transform, double eulerX, doubl
e eulerY, double eulerZ) |
| 447 { |
| 448 // TODO (shawnsingh): make this implementation faster and more accurate by |
| 449 // hard-coding each matrix instead of calling rotateAxisAngle(). |
| 450 gfx::Transform rotationAboutX; |
| 451 gfx::Transform rotationAboutY; |
| 452 gfx::Transform rotationAboutZ; |
| 453 |
| 454 MathUtil::rotateAxisAngle(&rotationAboutX, 1, 0, 0, eulerX); |
| 455 MathUtil::rotateAxisAngle(&rotationAboutY, 0, 1, 0, eulerY); |
| 456 MathUtil::rotateAxisAngle(&rotationAboutZ, 0, 0, 1, eulerZ); |
| 457 |
| 458 gfx::Transform composite = rotationAboutZ * rotationAboutY * rotationAboutX; |
| 459 transform->PreconcatTransform(composite); |
| 460 } |
| 461 |
| 462 void MathUtil::rotateAxisAngle(gfx::Transform* transform, double i, double j, do
uble k, double degrees) |
| 463 { |
| 464 // TODO (shawnsingh): fix gfx::Transform API to receive vector instead of |
| 465 // point for the axis. |
| 466 gfx::Point3F axis(i, j, k); |
| 467 transform->PreconcatRotateAbout(axis, degrees); |
| 468 } |
| 469 |
| 470 gfx::Transform MathUtil::inverse(const gfx::Transform& transform) |
| 471 { |
| 472 gfx::Transform result; |
| 473 bool invertedSuccessfully = transform.GetInverse(&result); |
| 474 |
| 475 if (invertedSuccessfully) |
| 476 return result; |
| 477 |
| 478 // If transform was un-invertible, then just return identity. |
| 479 return gfx::Transform(); |
| 480 } |
| 481 |
| 482 gfx::Transform MathUtil::to2dTransform(const gfx::Transform& transform) |
| 483 { |
| 484 gfx::Transform result = transform; |
| 485 SkMatrix44& matrix = result.matrix(); |
| 486 matrix.setDouble(0, 2, 0); |
| 487 matrix.setDouble(1, 2, 0); |
| 488 matrix.setDouble(2, 2, 1); |
| 489 matrix.setDouble(3, 2, 0); |
| 490 |
| 491 matrix.setDouble(2, 0, 0); |
| 492 matrix.setDouble(2, 1, 0); |
| 493 matrix.setDouble(2, 3, 0); |
| 494 |
| 495 return result; |
| 496 } |
| 497 |
| 498 gfx::Transform MathUtil::createGfxTransform(double m11, double m12, double m13,
double m14, |
| 499 double m21, double m22, double m23,
double m24, |
| 500 double m31, double m32, double m33,
double m34, |
| 501 double m41, double m42, double m43,
double m44) |
| 502 { |
| 503 gfx::Transform result; |
| 504 SkMatrix44& matrix = result.matrix(); |
| 505 |
| 506 // Initialize column 1 |
| 507 matrix.setDouble(0, 0, m11); |
| 508 matrix.setDouble(1, 0, m12); |
| 509 matrix.setDouble(2, 0, m13); |
| 510 matrix.setDouble(3, 0, m14); |
| 511 |
| 512 // Initialize column 2 |
| 513 matrix.setDouble(0, 1, m21); |
| 514 matrix.setDouble(1, 1, m22); |
| 515 matrix.setDouble(2, 1, m23); |
| 516 matrix.setDouble(3, 1, m24); |
| 517 |
| 518 // Initialize column 3 |
| 519 matrix.setDouble(0, 2, m31); |
| 520 matrix.setDouble(1, 2, m32); |
| 521 matrix.setDouble(2, 2, m33); |
| 522 matrix.setDouble(3, 2, m34); |
| 523 |
| 524 // Initialize column 4 |
| 525 matrix.setDouble(0, 3, m41); |
| 526 matrix.setDouble(1, 3, m42); |
| 527 matrix.setDouble(2, 3, m43); |
| 528 matrix.setDouble(3, 3, m44); |
| 529 |
| 530 return result; |
| 531 } |
| 532 |
| 533 gfx::Transform MathUtil::createGfxTransform(double a, double b, double c, |
| 534 double d, double e, double f) |
| 535 { |
| 536 gfx::Transform result; |
| 537 SkMatrix44& matrix = result.matrix(); |
| 538 matrix.setDouble(0, 0, a); |
| 539 matrix.setDouble(1, 0, b); |
| 540 matrix.setDouble(0, 1, c); |
| 541 matrix.setDouble(1, 1, d); |
| 542 matrix.setDouble(0, 3, e); |
| 543 matrix.setDouble(1, 3, f); |
| 544 |
| 545 return result; |
| 546 } |
| 547 |
| 548 gfx::Transform operator*(const gfx::Transform& A, const gfx::Transform& B) |
| 549 { |
| 550 // Compute A * B. |
| 551 gfx::Transform result = A; |
| 552 result.PreconcatTransform(B); |
| 553 return result; |
| 554 } |
| 555 |
398 } // namespace cc | 556 } // namespace cc |
OLD | NEW |