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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 static_cast<int>(matrix_.get(0, 3)) == matrix_.get(0, 3) && | 251 static_cast<int>(matrix_.get(0, 3)) == matrix_.get(0, 3) && |
252 static_cast<int>(matrix_.get(1, 3)) == matrix_.get(1, 3) && | 252 static_cast<int>(matrix_.get(1, 3)) == matrix_.get(1, 3) && |
253 static_cast<int>(matrix_.get(2, 3)) == matrix_.get(2, 3); | 253 static_cast<int>(matrix_.get(2, 3)) == matrix_.get(2, 3); |
254 | 254 |
255 return no_fractional_translation; | 255 return no_fractional_translation; |
256 } | 256 } |
257 | 257 |
258 bool Transform::IsBackFaceVisible() const { | 258 bool Transform::IsBackFaceVisible() const { |
259 // Compute whether a layer with a forward-facing normal of (0, 0, 1, 0) | 259 // Compute whether a layer with a forward-facing normal of (0, 0, 1, 0) |
260 // would have its back face visible after applying the transform. | 260 // would have its back face visible after applying the transform. |
261 if (matrix_.isIdentity()) | 261 |
| 262 // Case 1: Shortcut if simple translate and scale. |
| 263 if (!(matrix_.getType() & SkMatrix44::kAffine_Mask)) |
| 264 return matrix_.get(2, 2) < 0; |
| 265 |
| 266 // Case 2: Determine back face in the projected space. |
| 267 // |
| 268 // This is done by projecting an arbitrary vector that points to the |
| 269 // front side of the plane. For simplicity we can use (0, 0, 1, 0). |
| 270 // Note that this projected vector will no longer be the normal vector |
| 271 // of the projected plane. To avoid confusion, it will be referred as |
| 272 // the front-face indicator. |
| 273 // |
| 274 // Then we find the normal vector of the projected plane. This vector |
| 275 // is not normalized and does not indicate the face direction. Compute |
| 276 // the dot product of the front-face indicator by the normal vector to |
| 277 // determine which face is the front face. |
| 278 // |
| 279 // The face that faces the half-space where the origin resides is visible. |
| 280 |
| 281 // Compute the normal vector of the projected plane. |
| 282 double normal_x = matrix_.get(1, 0) * matrix_.get(3, 1) - |
| 283 matrix_.get(3, 0) * matrix_.get(1, 1); |
| 284 double normal_y = matrix_.get(3, 0) * matrix_.get(0, 1) - |
| 285 matrix_.get(0, 0) * matrix_.get(3, 1); |
| 286 double normal_w = matrix_.get(0, 0) * matrix_.get(1, 1) - |
| 287 matrix_.get(1, 0) * matrix_.get(0, 1); |
| 288 |
| 289 // Compute the determinant to determine which half-space the origin resides. |
| 290 // Note that the origin resides in the half-space of the opposite sign. |
| 291 double determinant = normal_x * matrix_.get(0, 3) + |
| 292 normal_y * matrix_.get(1, 3) + |
| 293 normal_w * matrix_.get(3, 3); |
| 294 |
| 295 // The origin coplanes the projected plane or the plane is degenerate. |
| 296 if (!determinant) |
262 return false; | 297 return false; |
263 | 298 |
264 // This is done by transforming the normal and seeing if the resulting z | 299 // Compute the dot product of the normal vector by the front-face indicator. |
265 // value is positive or negative. However, note that transforming a normal | 300 double face_direction = normal_x * matrix_.get(0, 2) + |
266 // actually requires using the inverse-transpose of the original transform. | 301 normal_y * matrix_.get(1, 2) + |
| 302 normal_w * matrix_.get(3, 2); |
| 303 |
| 304 // We are seeing the back face if the front face faces the opposite |
| 305 // half-space the origin resides. |
| 306 if (face_direction) |
| 307 return determinant * face_direction > 0; |
| 308 |
| 309 // Case 3: Front-face indicator is 0. |
267 // | 310 // |
268 // We can avoid inverting and transposing the matrix since we know we want | 311 // This can happen if the z component does not participate the projection, |
269 // to transform only the specific normal vector (0, 0, 1, 0). In this case, | 312 // which means the original space gets flattened there is no front or back. |
270 // we only need the 3rd row, 3rd column of the inverse-transpose. We can | 313 // A notable example is no perspective (= infinite perspective). |
271 // calculate only the 3rd row 3rd column element of the inverse, skipping | |
272 // everything else. | |
273 // | 314 // |
274 // For more information, refer to: | 315 // Try again as if a perspective that approaches infinite is applied. |
275 // http://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution | 316 // | 1 0 0 0 | |
276 // | 317 // lim | 0 1 0 0 | |
| 318 // e->+0 | 0 0 1 0 | |
| 319 // | 0 0 -e 1 | |
277 | 320 |
278 double determinant = matrix_.determinant(); | 321 double normal_x_epsilon = matrix_.get(1, 0) * -matrix_.get(2, 1) - |
| 322 -matrix_.get(2, 0) * matrix_.get(1, 1); |
| 323 double normal_y_epsilon = -matrix_.get(2, 0) * matrix_.get(0, 1) - |
| 324 matrix_.get(0, 0) * -matrix_.get(2, 1); |
279 | 325 |
280 // If matrix was not invertible, then just assume back face is not visible. | 326 face_direction = normal_x_epsilon * matrix_.get(0, 2) + |
281 if (std::abs(determinant) <= kEpsilon) | 327 normal_y_epsilon * matrix_.get(1, 2) + |
282 return false; | 328 normal_w * -matrix_.get(2, 2); |
283 | 329 |
284 // Compute the cofactor of the 3rd row, 3rd column. | 330 return determinant * face_direction > 0; |
285 double cofactor_part_1 = | |
286 matrix_.get(0, 0) * matrix_.get(1, 1) * matrix_.get(3, 3); | |
287 | |
288 double cofactor_part_2 = | |
289 matrix_.get(0, 1) * matrix_.get(1, 3) * matrix_.get(3, 0); | |
290 | |
291 double cofactor_part_3 = | |
292 matrix_.get(0, 3) * matrix_.get(1, 0) * matrix_.get(3, 1); | |
293 | |
294 double cofactor_part_4 = | |
295 matrix_.get(0, 0) * matrix_.get(1, 3) * matrix_.get(3, 1); | |
296 | |
297 double cofactor_part_5 = | |
298 matrix_.get(0, 1) * matrix_.get(1, 0) * matrix_.get(3, 3); | |
299 | |
300 double cofactor_part_6 = | |
301 matrix_.get(0, 3) * matrix_.get(1, 1) * matrix_.get(3, 0); | |
302 | |
303 double cofactor33 = | |
304 cofactor_part_1 + | |
305 cofactor_part_2 + | |
306 cofactor_part_3 - | |
307 cofactor_part_4 - | |
308 cofactor_part_5 - | |
309 cofactor_part_6; | |
310 | |
311 // Technically the transformed z component is cofactor33 / determinant. But | |
312 // we can avoid the costly division because we only care about the resulting | |
313 // +/- sign; we can check this equivalently by multiplication. | |
314 return cofactor33 * determinant < 0; | |
315 } | 331 } |
316 | 332 |
317 bool Transform::GetInverse(Transform* transform) const { | 333 bool Transform::GetInverse(Transform* transform) const { |
318 if (!matrix_.invert(&transform->matrix_)) { | 334 if (!matrix_.invert(&transform->matrix_)) { |
319 // Initialize the return value to identity if this matrix turned | 335 // Initialize the return value to identity if this matrix turned |
320 // out to be un-invertible. | 336 // out to be un-invertible. |
321 transform->MakeIdentity(); | 337 transform->MakeIdentity(); |
322 return false; | 338 return false; |
323 } | 339 } |
324 | 340 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 matrix_.get(2, 1), | 576 matrix_.get(2, 1), |
561 matrix_.get(2, 2), | 577 matrix_.get(2, 2), |
562 matrix_.get(2, 3), | 578 matrix_.get(2, 3), |
563 matrix_.get(3, 0), | 579 matrix_.get(3, 0), |
564 matrix_.get(3, 1), | 580 matrix_.get(3, 1), |
565 matrix_.get(3, 2), | 581 matrix_.get(3, 2), |
566 matrix_.get(3, 3)); | 582 matrix_.get(3, 3)); |
567 } | 583 } |
568 | 584 |
569 } // namespace gfx | 585 } // namespace gfx |
OLD | NEW |