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

Side by Side Diff: ui/gfx/transform.cc

Issue 1047463002: Determine face orientation in (x, y: w) projected space (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months 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
« no previous file with comments | « cc/trees/layer_tree_host_common.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « cc/trees/layer_tree_host_common.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698