Chromium Code Reviews| Index: chrome/browser/android/vr_shell/vr_shell.cc |
| diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc |
| index 6bf4311be0d4b793a9d418e12f8b72f80c90fc24..01b655f7482a7d6a3f29f92dbf3ee8cd575ccd54 100644 |
| --- a/chrome/browser/android/vr_shell/vr_shell.cc |
| +++ b/chrome/browser/android/vr_shell/vr_shell.cc |
| @@ -240,13 +240,23 @@ void VrShell::UpdateController(const gvr::Vec3f& forward_vector) { |
| float distance = scene_.GetUiElementById(kBrowserUiElementId) |
| ->GetRayDistance(origin, forward); |
| + // If we place the reticle based on elements intersecting the controller beam, |
| + // we can end up with the reticle hiding behind elements, or jumping laterally |
| + // in the field of view. This is physically correct, but hard to use. For |
| + // usability, do the following instead: |
| + // |
| + // - Project the controller laser onto an outer surface, which is the |
| + // closer of the desktop plane, or a distance-limiting sphere. |
| + // - Create a vector between the eyes and the outer surface point. |
| + // - If any UI elements intersect this vector, choose the closest to the eyes, |
| + // and place the reticle at the intersection point. |
| + |
| // Find distance to a corner of the content quad, and limit the cursor |
| // distance to a multiple of that distance. This lets us keep the reticle on |
| // the content plane near the content window, and on the surface of a sphere |
| - // in other directions. |
| - // TODO(cjgrant): Note that this approach uses distance from controller, |
| - // rather than eye, for simplicity. This will make the sphere slightly |
| - // off-center. |
| + // in other directions. Note that this approach uses distance from |
|
bshe
2016/10/04 18:56:00
nit: remove extra space before "Note"
|
| + // controller, rather than eye, for simplicity. This will make the sphere |
|
bshe
2016/10/04 18:56:00
nit: remove extra space before "This"
|
| + // slightly off-center. |
| gvr::Vec3f corner = {0.5f, 0.5f, 0.0f}; |
| corner = MatrixVectorMul(desktop_plane_->transform.to_world, corner); |
| float max_distance = Distance(origin, corner) * kReticleDistanceMultiplier; |
| @@ -254,8 +264,11 @@ void VrShell::UpdateController(const gvr::Vec3f& forward_vector) { |
| distance = max_distance; |
| } |
| target_point_ = GetRayPoint(origin, forward, distance); |
| + gvr::Vec3f eye_to_target = target_point_; |
| + NormalizeVector(eye_to_target); |
| - // Determine which UI element (if any) the cursor is pointing to. |
| + // Determine which UI element (if any) intersects the line between the eyes |
| + // and the controller target position. |
| float closest_element_distance = std::numeric_limits<float>::infinity(); |
| int pixel_x = 0; |
| int pixel_y = 0; |
| @@ -266,15 +279,15 @@ void VrShell::UpdateController(const gvr::Vec3f& forward_vector) { |
| if (!plane.visible) { |
| continue; |
| } |
| - float distance_to_plane = plane.GetRayDistance(origin, forward); |
| + float distance_to_plane = plane.GetRayDistance(kOrigin, eye_to_target); |
| gvr::Vec3f plane_intersection_point = |
| - GetRayPoint(origin, forward, distance_to_plane); |
| + GetRayPoint(kOrigin, eye_to_target, distance_to_plane); |
| gvr::Vec3f rect_2d_point = |
| MatrixVectorMul(plane.transform.from_world, plane_intersection_point); |
| - float x = rect_2d_point.x + 0.5f; |
| - float y = 0.5f - rect_2d_point.y; |
| if (distance_to_plane > 0 && distance_to_plane < closest_element_distance) { |
| + float x = rect_2d_point.x + 0.5f; |
| + float y = 0.5f - rect_2d_point.y; |
| bool is_inside = x >= 0.0f && x < 1.0f && y >= 0.0f && y < 1.0f; |
| if (is_inside) { |
| closest_element_distance = distance_to_plane; |