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

Side by Side Diff: chrome/browser/android/vr_shell/vr_shell.cc

Issue 2392023002: VrShell: Restore smooth reticle positioning in the user FOV. (Closed)
Patch Set: Fix comment nits. Created 4 years, 2 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 | « no previous file | 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 #include "chrome/browser/android/vr_shell/vr_shell.h" 5 #include "chrome/browser/android/vr_shell/vr_shell.h"
6 6
7 #include <thread> 7 #include <thread>
8 8
9 #include "chrome/browser/android/vr_shell/ui_scene.h" 9 #include "chrome/browser/android/vr_shell/ui_scene.h"
10 #include "chrome/browser/android/vr_shell/vr_compositor.h" 10 #include "chrome/browser/android/vr_shell/vr_compositor.h"
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 60
61 // In lieu of an elbow model, we assume a position for the user's hand. 61 // In lieu of an elbow model, we assume a position for the user's hand.
62 // TODO(mthiesse): Handedness options. 62 // TODO(mthiesse): Handedness options.
63 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f}; 63 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f};
64 64
65 // Fraction of the distance to the object the cursor is drawn at to avoid 65 // Fraction of the distance to the object the cursor is drawn at to avoid
66 // rounding errors drawing the cursor behind the object. 66 // rounding errors drawing the cursor behind the object.
67 static constexpr float kReticleOffset = 0.99f; 67 static constexpr float kReticleOffset = 0.99f;
68 68
69 // Limit the rendering distance of the reticle to the distance to a corner of 69 // Limit the rendering distance of the reticle to the distance to a corner of
70 // the content quad, times this value. This lets the rendering distance 70 // the content quad, times this value. This lets the rendering distance
71 // adjust according to content quad placement. 71 // adjust according to content quad placement.
72 static constexpr float kReticleDistanceMultiplier = 1.5f; 72 static constexpr float kReticleDistanceMultiplier = 1.5f;
73 73
74 // UI element 0 is the browser content rectangle. 74 // UI element 0 is the browser content rectangle.
75 static constexpr int kBrowserUiElementId = 0; 75 static constexpr int kBrowserUiElementId = 0;
76 76
77 vr_shell::VrShell* g_instance; 77 vr_shell::VrShell* g_instance;
78 78
79 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; 79 static const char kVrShellUIURL[] = "chrome://vr-shell-ui";
80 80
81 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { 81 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) {
82 float xdiff = (vec1.x - vec2.x); 82 float xdiff = (vec1.x - vec2.x);
83 float ydiff = (vec1.y - vec2.y); 83 float ydiff = (vec1.y - vec2.y);
84 float zdiff = (vec1.z - vec2.z); 84 float zdiff = (vec1.z - vec2.z);
85 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; 85 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
86 return std::sqrt(scale); 86 return std::sqrt(scale);
87 } 87 }
88 88
89 // Generate a quaternion representing the rotation from the negative Z axis 89 // Generate a quaternion representing the rotation from the negative Z axis
90 // (0, 0, -1) to a specified vector. This is an optimized version of a more 90 // (0, 0, -1) to a specified vector. This is an optimized version of a more
91 // general vector-to-vector calculation. 91 // general vector-to-vector calculation.
92 gvr::Quatf GetRotationFromZAxis(gvr::Vec3f vec) { 92 gvr::Quatf GetRotationFromZAxis(gvr::Vec3f vec) {
93 vr_shell::NormalizeVector(vec); 93 vr_shell::NormalizeVector(vec);
94 gvr::Quatf quat; 94 gvr::Quatf quat;
95 quat.qw = 1.0f - vec.z; 95 quat.qw = 1.0f - vec.z;
96 if (quat.qw < 1e-6f) { 96 if (quat.qw < 1e-6f) {
97 // Degenerate case: vectors are exactly opposite. Replace by an 97 // Degenerate case: vectors are exactly opposite. Replace by an
98 // arbitrary 180 degree rotation to avoid invalid normalization. 98 // arbitrary 180 degree rotation to avoid invalid normalization.
99 quat.qx = 1.0f; 99 quat.qx = 1.0f;
100 quat.qy = 0.0f; 100 quat.qy = 0.0f;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 } 233 }
234 234
235 gvr::Mat4f mat = QuatToMatrix(controller_quat_); 235 gvr::Mat4f mat = QuatToMatrix(controller_quat_);
236 gvr::Vec3f forward = MatrixVectorMul(mat, kNeutralPose); 236 gvr::Vec3f forward = MatrixVectorMul(mat, kNeutralPose);
237 gvr::Vec3f origin = kHandPosition; 237 gvr::Vec3f origin = kHandPosition;
238 238
239 target_element_ = nullptr; 239 target_element_ = nullptr;
240 float distance = scene_.GetUiElementById(kBrowserUiElementId) 240 float distance = scene_.GetUiElementById(kBrowserUiElementId)
241 ->GetRayDistance(origin, forward); 241 ->GetRayDistance(origin, forward);
242 242
243 // If we place the reticle based on elements intersecting the controller beam,
244 // we can end up with the reticle hiding behind elements, or jumping laterally
245 // in the field of view. This is physically correct, but hard to use. For
246 // usability, do the following instead:
247 //
248 // - Project the controller laser onto an outer surface, which is the
249 // closer of the desktop plane, or a distance-limiting sphere.
250 // - Create a vector between the eyes and the outer surface point.
251 // - If any UI elements intersect this vector, choose the closest to the eyes,
252 // and place the reticle at the intersection point.
253
243 // Find distance to a corner of the content quad, and limit the cursor 254 // Find distance to a corner of the content quad, and limit the cursor
244 // distance to a multiple of that distance. This lets us keep the reticle on 255 // distance to a multiple of that distance. This lets us keep the reticle on
245 // the content plane near the content window, and on the surface of a sphere 256 // the content plane near the content window, and on the surface of a sphere
246 // in other directions. 257 // in other directions. Note that this approach uses distance from controller,
247 // TODO(cjgrant): Note that this approach uses distance from controller, 258 // rather than eye, for simplicity. This will make the sphere slightly
248 // rather than eye, for simplicity. This will make the sphere slightly
249 // off-center. 259 // off-center.
250 gvr::Vec3f corner = {0.5f, 0.5f, 0.0f}; 260 gvr::Vec3f corner = {0.5f, 0.5f, 0.0f};
251 corner = MatrixVectorMul(desktop_plane_->transform.to_world, corner); 261 corner = MatrixVectorMul(desktop_plane_->transform.to_world, corner);
252 float max_distance = Distance(origin, corner) * kReticleDistanceMultiplier; 262 float max_distance = Distance(origin, corner) * kReticleDistanceMultiplier;
253 if (distance > max_distance || distance <= 0.0f) { 263 if (distance > max_distance || distance <= 0.0f) {
254 distance = max_distance; 264 distance = max_distance;
255 } 265 }
256 target_point_ = GetRayPoint(origin, forward, distance); 266 target_point_ = GetRayPoint(origin, forward, distance);
267 gvr::Vec3f eye_to_target = target_point_;
268 NormalizeVector(eye_to_target);
257 269
258 // Determine which UI element (if any) the cursor is pointing to. 270 // Determine which UI element (if any) intersects the line between the eyes
271 // and the controller target position.
259 float closest_element_distance = std::numeric_limits<float>::infinity(); 272 float closest_element_distance = std::numeric_limits<float>::infinity();
260 int pixel_x = 0; 273 int pixel_x = 0;
261 int pixel_y = 0; 274 int pixel_y = 0;
262 VrInputManager* input_target = nullptr; 275 VrInputManager* input_target = nullptr;
263 276
264 for (std::size_t i = 0; i < scene_.GetUiElements().size(); ++i) { 277 for (std::size_t i = 0; i < scene_.GetUiElements().size(); ++i) {
265 const ContentRectangle& plane = *scene_.GetUiElements()[i].get(); 278 const ContentRectangle& plane = *scene_.GetUiElements()[i].get();
266 if (!plane.visible) { 279 if (!plane.visible) {
267 continue; 280 continue;
268 } 281 }
269 float distance_to_plane = plane.GetRayDistance(origin, forward); 282 float distance_to_plane = plane.GetRayDistance(kOrigin, eye_to_target);
270 gvr::Vec3f plane_intersection_point = 283 gvr::Vec3f plane_intersection_point =
271 GetRayPoint(origin, forward, distance_to_plane); 284 GetRayPoint(kOrigin, eye_to_target, distance_to_plane);
272 285
273 gvr::Vec3f rect_2d_point = 286 gvr::Vec3f rect_2d_point =
274 MatrixVectorMul(plane.transform.from_world, plane_intersection_point); 287 MatrixVectorMul(plane.transform.from_world, plane_intersection_point);
275 float x = rect_2d_point.x + 0.5f;
276 float y = 0.5f - rect_2d_point.y;
277 if (distance_to_plane > 0 && distance_to_plane < closest_element_distance) { 288 if (distance_to_plane > 0 && distance_to_plane < closest_element_distance) {
289 float x = rect_2d_point.x + 0.5f;
290 float y = 0.5f - rect_2d_point.y;
278 bool is_inside = x >= 0.0f && x < 1.0f && y >= 0.0f && y < 1.0f; 291 bool is_inside = x >= 0.0f && x < 1.0f && y >= 0.0f && y < 1.0f;
279 if (is_inside) { 292 if (is_inside) {
280 closest_element_distance = distance_to_plane; 293 closest_element_distance = distance_to_plane;
281 pixel_x = 294 pixel_x =
282 static_cast<int>(plane.copy_rect.width * x + plane.copy_rect.x); 295 static_cast<int>(plane.copy_rect.width * x + plane.copy_rect.x);
283 pixel_y = 296 pixel_y =
284 static_cast<int>(plane.copy_rect.height * y + plane.copy_rect.y); 297 static_cast<int>(plane.copy_rect.height * y + plane.copy_rect.y);
285 298
286 target_point_ = plane_intersection_point; 299 target_point_ = plane_intersection_point;
287 target_element_ = &plane; 300 target_element_ = &plane;
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 content::WebContents::FromJavaWebContents(content_web_contents)); 666 content::WebContents::FromJavaWebContents(content_web_contents));
654 content::ContentViewCore* ui_core = content::ContentViewCore::FromWebContents( 667 content::ContentViewCore* ui_core = content::ContentViewCore::FromWebContents(
655 content::WebContents::FromJavaWebContents(ui_web_contents)); 668 content::WebContents::FromJavaWebContents(ui_web_contents));
656 return reinterpret_cast<intptr_t>(new VrShell( 669 return reinterpret_cast<intptr_t>(new VrShell(
657 env, obj, c_core, 670 env, obj, c_core,
658 reinterpret_cast<ui::WindowAndroid*>(content_window_android), ui_core, 671 reinterpret_cast<ui::WindowAndroid*>(content_window_android), ui_core,
659 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); 672 reinterpret_cast<ui::WindowAndroid*>(ui_window_android)));
660 } 673 }
661 674
662 } // namespace vr_shell 675 } // namespace vr_shell
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698