OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 // Needed on Windows to get |M_PI| from <cmath> | 5 // Needed on Windows to get |M_PI| from <cmath> |
6 #ifdef _WIN32 | 6 #ifdef _WIN32 |
7 #define _USE_MATH_DEFINES | 7 #define _USE_MATH_DEFINES |
8 #endif | 8 #endif |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
307 origin + gfx::ScaleVector3d(normal, gfx::DotProduct(to_point, normal)); | 307 origin + gfx::ScaleVector3d(normal, gfx::DotProduct(to_point, normal)); |
308 | 308 |
309 // Now we need to find two vectors in the plane of rotation. One pointing | 309 // Now we need to find two vectors in the plane of rotation. One pointing |
310 // towards point and another, perpendicular vector in the plane. | 310 // towards point and another, perpendicular vector in the plane. |
311 gfx::Vector3dF v1 = point - center; | 311 gfx::Vector3dF v1 = point - center; |
312 float v1_length = v1.Length(); | 312 float v1_length = v1.Length(); |
313 if (v1_length == 0.f) | 313 if (v1_length == 0.f) |
314 return; | 314 return; |
315 | 315 |
316 v1.Scale(1.f / v1_length); | 316 v1.Scale(1.f / v1_length); |
317 gfx::Vector3dF v2 = gfx::CrossProduct(normal, v1); | |
318 // v1 is the basis vector in the direction of the point. | |
319 // i.e. with a rotation of 0, v1 is our +x vector. | |
320 // v2 is a perpenticular basis vector of our plane (+y). | |
317 | 321 |
318 gfx::Vector3dF v2 = gfx::CrossProduct(normal, v1); | 322 // Take the parametric equation of a circle. |
319 | 323 // x = r*cos(t); y = r*sin(t); |
320 // Now figure out where (1, 0, 0) and (0, 0, 1) project on the rotation | 324 // We can treat that as a circle on the plane v1xv2. |
321 // plane. | 325 // From that we get the parametric equations for a circle on the |
322 gfx::Point3F px(1.f, 0.f, 0.f); | 326 // plane in 3d space of: |
323 gfx::Vector3dF to_px = px - center; | 327 // x(t) = r*cos(t)*v1.x + r*sin(t)*v2.x + cx |
324 gfx::Point3F px_projected = | 328 // y(t) = r*cos(t)*v1.y + r*sin(t)*v2.y + cy |
325 px - gfx::ScaleVector3d(normal, gfx::DotProduct(to_px, normal)); | 329 // z(t) = r*cos(t)*v1.z + r*sin(t)*v2.z + cz |
326 gfx::Vector3dF vx = px_projected - origin; | 330 // Taking the derivative of (x, y, z) and solving for 0 gives us our |
327 | 331 // maximum/minimum x, y, z values. |
328 gfx::Point3F pz(0.f, 0.f, 1.f); | 332 // x'(t) = r*cos(t)*v2.x - r*sin(t)*v1.x = 0 |
329 gfx::Vector3dF to_pz = pz - center; | 333 // tan(t) = v2.x/v1.x |
330 gfx::Point3F pz_projected = | 334 // t = atan2(v2.x, v1.x) + n*M_PI; |
ajuma
2014/05/27 16:00:54
Very nice!
| |
331 pz - ScaleVector3d(normal, gfx::DotProduct(to_pz, normal)); | 335 candidates[0] = atan2(v2.x(), v1.x()); |
332 gfx::Vector3dF vz = pz_projected - origin; | |
333 | |
334 double phi_x = atan2(gfx::DotProduct(v2, vx), gfx::DotProduct(v1, vx)); | |
335 double phi_z = atan2(gfx::DotProduct(v2, vz), gfx::DotProduct(v1, vz)); | |
336 | |
337 candidates[0] = atan2(normal.y(), normal.x() * normal.z()) + phi_x; | |
338 candidates[1] = candidates[0] + M_PI; | 336 candidates[1] = candidates[0] + M_PI; |
339 candidates[2] = atan2(-normal.z(), normal.x() * normal.y()) + phi_x; | 337 candidates[2] = atan2(v2.y(), v1.y()); |
340 candidates[3] = candidates[2] + M_PI; | 338 candidates[3] = candidates[2] + M_PI; |
341 candidates[4] = atan2(normal.y(), -normal.x() * normal.z()) + phi_z; | 339 candidates[4] = atan2(v2.z(), v1.z()); |
342 candidates[5] = candidates[4] + M_PI; | 340 candidates[5] = candidates[4] + M_PI; |
343 } | 341 } |
344 | 342 |
345 double min_radians = DegreesToRadians(min_degrees); | 343 double min_radians = DegreesToRadians(min_degrees); |
346 double max_radians = DegreesToRadians(max_degrees); | 344 double max_radians = DegreesToRadians(max_degrees); |
347 | 345 |
348 for (int i = 0; i < num_candidates; ++i) { | 346 for (int i = 0; i < num_candidates; ++i) { |
349 double radians = candidates[i]; | 347 double radians = candidates[i]; |
350 while (radians < min_radians) | 348 while (radians < min_radians) |
351 radians += 2.0 * M_PI; | 349 radians += 2.0 * M_PI; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
432 return true; | 430 return true; |
433 } | 431 } |
434 case TransformOperation::TransformOperationMatrix: | 432 case TransformOperation::TransformOperationMatrix: |
435 return false; | 433 return false; |
436 } | 434 } |
437 NOTREACHED(); | 435 NOTREACHED(); |
438 return false; | 436 return false; |
439 } | 437 } |
440 | 438 |
441 } // namespace cc | 439 } // namespace cc |
OLD | NEW |