Chromium Code Reviews| 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 |