OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 // MSVC++ requires this to be set before any other includes to get M_PI. | 5 // MSVC++ requires this to be set before any other includes to get M_PI. |
6 #define _USE_MATH_DEFINES | 6 #define _USE_MATH_DEFINES |
7 | 7 |
8 #include "ui/gfx/transform.h" | 8 #include "ui/gfx/transform.h" |
9 | 9 |
10 #include <cmath> | 10 #include <cmath> |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 matrix_.getDouble(3, 1) || | 263 matrix_.getDouble(3, 1) || |
264 matrix_.getDouble(3, 2) || | 264 matrix_.getDouble(3, 2) || |
265 (matrix_.getDouble(3, 3) != 1); | 265 (matrix_.getDouble(3, 3) != 1); |
266 } | 266 } |
267 | 267 |
268 bool Transform::IsInvertible() const { | 268 bool Transform::IsInvertible() const { |
269 return std::abs(matrix_.determinant()) > kTooSmallForDeterminant; | 269 return std::abs(matrix_.determinant()) > kTooSmallForDeterminant; |
270 } | 270 } |
271 | 271 |
272 bool Transform::IsBackFaceVisible() const { | 272 bool Transform::IsBackFaceVisible() const { |
273 // Compute whether a layer with a forward-facing normal of (0, 0, 1) would | 273 // Compute whether a layer with a forward-facing normal of (0, 0, 1, 0) |
274 // have its back face visible after applying the transform. | 274 // would have its back face visible after applying the transform. |
275 // | 275 // |
276 // This is done by transforming the normal and seeing if the resulting z | 276 // This is done by transforming the normal and seeing if the resulting z |
277 // value is positive or negative. However, note that transforming a normal | 277 // value is positive or negative. However, note that transforming a normal |
278 // actually requires using the inverse-transpose of the original transform. | 278 // actually requires using the inverse-transpose of the original transform. |
| 279 // |
| 280 // We can avoid inverting and transposing the matrix since we know we want |
| 281 // to transform only the specific normal vector (0, 0, 1, 0). In this case, |
| 282 // we only need the 3rd row, 3rd column of the inverse-transpose. We can |
| 283 // calculate only the 3rd row 3rd column element of the inverse, skipping |
| 284 // everything else. |
| 285 // |
| 286 // For more information, refer to: |
| 287 // http://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution |
| 288 // |
279 | 289 |
280 // TODO (shawnsingh) make this perform more efficiently - we do not | 290 double determinant = matrix_.determinant(); |
281 // actually need to instantiate/invert/transpose any matrices, exploiting the | |
282 // fact that we only need to transform (0, 0, 1, 0). | |
283 SkMatrix44 inverse; | |
284 bool invertible = matrix_.invert(&inverse); | |
285 | 291 |
286 // Assume the transform does not apply if it's not invertible, so it's | 292 // If matrix was not invertible, then just assume back face is not visible. |
287 // front face remains visible. | 293 if (std::abs(determinant) <= kTooSmallForDeterminant) |
288 if (!invertible) | |
289 return false; | 294 return false; |
290 | 295 |
291 return inverse.getDouble(2, 2) < 0; | 296 // Compute the cofactor of the 3rd row, 3rd column. |
| 297 double cofactor_part_1 = |
| 298 matrix_.getDouble(0, 0) * |
| 299 matrix_.getDouble(1, 1) * |
| 300 matrix_.getDouble(3, 3); |
| 301 |
| 302 double cofactor_part_2 = |
| 303 matrix_.getDouble(0, 1) * |
| 304 matrix_.getDouble(1, 3) * |
| 305 matrix_.getDouble(3, 0); |
| 306 |
| 307 double cofactor_part_3 = |
| 308 matrix_.getDouble(0, 3) * |
| 309 matrix_.getDouble(1, 0) * |
| 310 matrix_.getDouble(3, 1); |
| 311 |
| 312 double cofactor_part_4 = |
| 313 matrix_.getDouble(0, 0) * |
| 314 matrix_.getDouble(1, 3) * |
| 315 matrix_.getDouble(3, 1); |
| 316 |
| 317 double cofactor_part_5 = |
| 318 matrix_.getDouble(0, 1) * |
| 319 matrix_.getDouble(1, 0) * |
| 320 matrix_.getDouble(3, 3); |
| 321 |
| 322 double cofactor_part_6 = |
| 323 matrix_.getDouble(0, 3) * |
| 324 matrix_.getDouble(1, 1) * |
| 325 matrix_.getDouble(3, 0); |
| 326 |
| 327 double cofactor33 = |
| 328 cofactor_part_1 + |
| 329 cofactor_part_2 + |
| 330 cofactor_part_3 - |
| 331 cofactor_part_4 - |
| 332 cofactor_part_5 - |
| 333 cofactor_part_6; |
| 334 |
| 335 // Technically the transformed z component is cofactor33 / determinant. But |
| 336 // we can avoid the costly division because we only care about the resulting |
| 337 // +/- sign; we can check this equivalently by multiplication. |
| 338 return cofactor33 * determinant < 0; |
292 } | 339 } |
293 | 340 |
294 bool Transform::GetInverse(Transform* transform) const { | 341 bool Transform::GetInverse(Transform* transform) const { |
295 return matrix_.invert(&transform->matrix_); | 342 return matrix_.invert(&transform->matrix_); |
296 } | 343 } |
297 | 344 |
298 void Transform::Transpose() { | 345 void Transform::Transpose() { |
299 matrix_.transpose(); | 346 matrix_.transpose(); |
300 } | 347 } |
301 | 348 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 SkDoubleToMScalar(0), | 451 SkDoubleToMScalar(0), |
405 SkDoubleToMScalar(1) | 452 SkDoubleToMScalar(1) |
406 }; | 453 }; |
407 | 454 |
408 xform.mapMScalars(p); | 455 xform.mapMScalars(p); |
409 | 456 |
410 point.SetPoint(ToRoundedInt(p[0]), ToRoundedInt(p[1])); | 457 point.SetPoint(ToRoundedInt(p[0]), ToRoundedInt(p[1])); |
411 } | 458 } |
412 | 459 |
413 } // namespace gfx | 460 } // namespace gfx |
OLD | NEW |