OLD | NEW |
---|---|
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 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 |
bshe
2016/10/04 18:56:00
nit: remove extra space before "Note"
| |
247 // TODO(cjgrant): Note that this approach uses distance from controller, | 258 // controller, rather than eye, for simplicity. This will make the sphere |
bshe
2016/10/04 18:56:00
nit: remove extra space before "This"
| |
248 // rather than eye, for simplicity. This will make the sphere slightly | 259 // slightly off-center. |
249 // 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 Loading... | |
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 |
OLD | NEW |