| 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..d84ecfa63230ef1e58b8ba03a6a04415cb4a1313 100644
|
| --- a/chrome/browser/android/vr_shell/vr_shell.cc
|
| +++ b/chrome/browser/android/vr_shell/vr_shell.cc
|
| @@ -67,7 +67,7 @@ static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f};
|
| static constexpr float kReticleOffset = 0.99f;
|
|
|
| // Limit the rendering distance of the reticle to the distance to a corner of
|
| -// the content quad, times this value. This lets the rendering distance
|
| +// the content quad, times this value. This lets the rendering distance
|
| // adjust according to content quad placement.
|
| static constexpr float kReticleDistanceMultiplier = 1.5f;
|
|
|
| @@ -87,7 +87,7 @@ float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) {
|
| }
|
|
|
| // Generate a quaternion representing the rotation from the negative Z axis
|
| -// (0, 0, -1) to a specified vector. This is an optimized version of a more
|
| +// (0, 0, -1) to a specified vector. This is an optimized version of a more
|
| // general vector-to-vector calculation.
|
| gvr::Quatf GetRotationFromZAxis(gvr::Vec3f vec) {
|
| vr_shell::NormalizeVector(vec);
|
| @@ -240,12 +240,22 @@ 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
|
| + // 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
|
| + // in other directions. Note that this approach uses distance from controller,
|
| + // rather than eye, for simplicity. This will make the sphere slightly
|
| // off-center.
|
| gvr::Vec3f corner = {0.5f, 0.5f, 0.0f};
|
| corner = MatrixVectorMul(desktop_plane_->transform.to_world, corner);
|
| @@ -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;
|
|
|