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

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

Issue 2442873002: Control the VrShell content quad via the HTML UI. (Closed)
Patch Set: 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
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 "base/metrics/histogram_macros.h" 7 #include "base/metrics/histogram_macros.h"
8 #include "chrome/browser/android/vr_shell/ui_elements.h" 8 #include "chrome/browser/android/vr_shell/ui_elements.h"
9 #include "chrome/browser/android/vr_shell/ui_interface.h" 9 #include "chrome/browser/android/vr_shell/ui_interface.h"
10 #include "chrome/browser/android/vr_shell/ui_scene.h" 10 #include "chrome/browser/android/vr_shell/ui_scene.h"
(...skipping 20 matching lines...) Expand all
31 31
32 using base::android::JavaParamRef; 32 using base::android::JavaParamRef;
33 33
34 namespace { 34 namespace {
35 // Constant taken from treasure_hunt demo. 35 // Constant taken from treasure_hunt demo.
36 static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000; 36 static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000;
37 37
38 static constexpr float kZNear = 0.1f; 38 static constexpr float kZNear = 0.1f;
39 static constexpr float kZFar = 1000.0f; 39 static constexpr float kZFar = 1000.0f;
40 40
41 static constexpr gvr::Vec3f kDesktopPositionDefault = {0.0f, 0.0f, -2.0f};
42 static constexpr float kDesktopHeightDefault = 1.6f;
43
44 // Screen angle in degrees. 0 = vertical, positive = top closer. 41 // Screen angle in degrees. 0 = vertical, positive = top closer.
45 static constexpr float kDesktopScreenTiltDefault = 0; 42 static constexpr float kDesktopScreenTiltDefault = 0;
46 43
47 static constexpr float kScreenHeightRatio = 1.0f;
48 static constexpr float kScreenWidthRatio = 16.0f / 9.0f;
49
50 static constexpr float kReticleWidth = 0.025f; 44 static constexpr float kReticleWidth = 0.025f;
51 static constexpr float kReticleHeight = 0.025f; 45 static constexpr float kReticleHeight = 0.025f;
52 46
53 static constexpr float kLaserWidth = 0.01f; 47 static constexpr float kLaserWidth = 0.01f;
54 48
55 // Angle (radians) the beam down from the controller axis, for wrist comfort. 49 // Angle (radians) the beam down from the controller axis, for wrist comfort.
56 static constexpr float kErgoAngleOffset = 0.26f; 50 static constexpr float kErgoAngleOffset = 0.26f;
57 51
58 static constexpr gvr::Vec3f kOrigin = {0.0f, 0.0f, 0.0f}; 52 static constexpr gvr::Vec3f kOrigin = {0.0f, 0.0f, 0.0f};
59 53
60 // In lieu of an elbow model, we assume a position for the user's hand. 54 // In lieu of an elbow model, we assume a position for the user's hand.
61 // TODO(mthiesse): Handedness options. 55 // TODO(mthiesse): Handedness options.
62 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f}; 56 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f};
63 57
58 // If there is no content quad, and the reticle isn't hitting another element,
59 // draw the reticle at this distance.
60 static constexpr float kDefaultReticleDistance = 2.0f;
61
64 // Fraction of the distance to the object the cursor is drawn at to avoid 62 // Fraction of the distance to the object the cursor is drawn at to avoid
65 // rounding errors drawing the cursor behind the object. 63 // rounding errors drawing the cursor behind the object.
66 static constexpr float kReticleOffset = 0.99f; 64 static constexpr float kReticleOffset = 0.99f;
67 65
68 // Limit the rendering distance of the reticle to the distance to a corner of 66 // Limit the rendering distance of the reticle to the distance to a corner of
69 // the content quad, times this value. This lets the rendering distance 67 // the content quad, times this value. This lets the rendering distance
70 // adjust according to content quad placement. 68 // adjust according to content quad placement.
71 static constexpr float kReticleDistanceMultiplier = 1.5f; 69 static constexpr float kReticleDistanceMultiplier = 1.5f;
72 70
73 // UI element 0 is the browser content rectangle.
74 static constexpr int kBrowserUiElementId = 0;
75
76 // Positions and sizes of statically placed UI elements in the UI texture. 71 // Positions and sizes of statically placed UI elements in the UI texture.
77 // TODO(klausw): replace the hardcoded positions with JS position/offset 72 // TODO(klausw): replace the hardcoded positions with JS position/offset
78 // retrieval once the infrastructure for that is hooked up. 73 // retrieval once the infrastructure for that is hooked up.
79 // 74 //
80 // UI is designed with 1 pixel = 1mm at 1m distance. It's rescaled to 75 // UI is designed with 1 pixel = 1mm at 1m distance. It's rescaled to
81 // maintain the same angular resolution if placed closer or further. 76 // maintain the same angular resolution if placed closer or further.
82 // The warning overlays should be fairly close since they cut holes 77 // The warning overlays should be fairly close since they cut holes
83 // into geometry (they ignore the Z buffer), leading to odd effects 78 // into geometry (they ignore the Z buffer), leading to odd effects
84 // if they are far away. 79 // if they are far away.
85 static constexpr vr_shell::Recti kWebVrWarningTransientRect = { 80 static constexpr vr_shell::Recti kWebVrWarningTransientRect = {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 122
128 } // namespace 123 } // namespace
129 124
130 namespace vr_shell { 125 namespace vr_shell {
131 126
132 VrShell::VrShell(JNIEnv* env, jobject obj, 127 VrShell::VrShell(JNIEnv* env, jobject obj,
133 content::WebContents* main_contents, 128 content::WebContents* main_contents,
134 ui::WindowAndroid* content_window, 129 ui::WindowAndroid* content_window,
135 content::WebContents* ui_contents, 130 content::WebContents* ui_contents,
136 ui::WindowAndroid* ui_window) 131 ui::WindowAndroid* ui_window)
137 : desktop_screen_tilt_(kDesktopScreenTiltDefault), 132 : main_contents_(main_contents),
138 desktop_height_(kDesktopHeightDefault),
139 main_contents_(main_contents),
140 ui_contents_(ui_contents), 133 ui_contents_(ui_contents),
141 weak_ptr_factory_(this) { 134 weak_ptr_factory_(this) {
142 DCHECK(g_instance == nullptr); 135 DCHECK(g_instance == nullptr);
143 g_instance = this; 136 g_instance = this;
144 j_vr_shell_.Reset(env, obj); 137 j_vr_shell_.Reset(env, obj);
145 scene_.reset(new UiScene); 138 scene_.reset(new UiScene);
146 html_interface_.reset(new UiInterface); 139 html_interface_.reset(new UiInterface);
147 content_compositor_.reset(new VrCompositor(content_window, false)); 140 content_compositor_.reset(new VrCompositor(content_window, false));
148 ui_compositor_.reset(new VrCompositor(ui_window, true)); 141 ui_compositor_.reset(new VrCompositor(ui_window, true));
149 142
150 float screen_width = kScreenWidthRatio * desktop_height_;
151 float screen_height = kScreenHeightRatio * desktop_height_;
152 std::unique_ptr<ContentRectangle> rect(new ContentRectangle());
153 rect->id = kBrowserUiElementId;
154 rect->size = {screen_width, screen_height, 1.0f};
155 rect->translation = kDesktopPositionDefault;
156 scene_->AddUiElement(rect);
157
158 LoadUIContent(); 143 LoadUIContent();
159 144
160 gvr::Mat4f identity; 145 gvr::Mat4f identity;
161 SetIdentityM(identity); 146 SetIdentityM(identity);
162 webvr_head_pose_.resize(kPoseRingBufferSize, identity); 147 webvr_head_pose_.resize(kPoseRingBufferSize, identity);
163 } 148 }
164 149
165 void VrShell::UpdateCompositorLayers(JNIEnv* env, 150 void VrShell::UpdateCompositorLayers(JNIEnv* env,
166 const JavaParamRef<jobject>& obj) { 151 const JavaParamRef<jobject>& obj) {
167 content_compositor_->SetLayer(main_contents_); 152 content_compositor_->SetLayer(main_contents_);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 controller_quat_ = GetRotationFromZAxis(forward_vector); 261 controller_quat_ = GetRotationFromZAxis(forward_vector);
277 } else { 262 } else {
278 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; 263 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)};
279 controller_quat_ = controller_->Orientation(); 264 controller_quat_ = controller_->Orientation();
280 } 265 }
281 266
282 gvr::Mat4f mat = QuatToMatrix(controller_quat_); 267 gvr::Mat4f mat = QuatToMatrix(controller_quat_);
283 gvr::Vec3f forward = MatrixVectorMul(mat, ergo_neutral_pose); 268 gvr::Vec3f forward = MatrixVectorMul(mat, ergo_neutral_pose);
284 gvr::Vec3f origin = kHandPosition; 269 gvr::Vec3f origin = kHandPosition;
285 270
286 target_element_ = nullptr;
287
288 ContentRectangle* content_plane =
289 scene_->GetUiElementById(kBrowserUiElementId);
290
291 float distance = content_plane->GetRayDistance(origin, forward);
292
293 // If we place the reticle based on elements intersecting the controller beam, 271 // If we place the reticle based on elements intersecting the controller beam,
294 // we can end up with the reticle hiding behind elements, or jumping laterally 272 // we can end up with the reticle hiding behind elements, or jumping laterally
295 // in the field of view. This is physically correct, but hard to use. For 273 // in the field of view. This is physically correct, but hard to use. For
296 // usability, do the following instead: 274 // usability, do the following instead:
297 // 275 //
298 // - Project the controller laser onto an outer surface, which is the 276 // - Project the controller laser onto an outer surface, which is the
299 // closer of the desktop plane, or a distance-limiting sphere. 277 // closer of the desktop plane, or a distance-limiting sphere.
300 // - Create a vector between the eyes and the outer surface point. 278 // - Create a vector between the eyes and the outer surface point.
301 // - If any UI elements intersect this vector, choose the closest to the eyes, 279 // - If any UI elements intersect this vector, choose the closest to the eyes,
302 // and place the reticle at the intersection point. 280 // and place the reticle at the intersection point.
303 281
304 // Find distance to a corner of the content quad, and limit the cursor 282 // Find distance to a corner of the content quad, and limit the cursor
305 // distance to a multiple of that distance. This lets us keep the reticle on 283 // distance to a multiple of that distance. This lets us keep the reticle on
306 // the content plane near the content window, and on the surface of a sphere 284 // the content plane near the content window, and on the surface of a sphere
307 // in other directions. Note that this approach uses distance from controller, 285 // in other directions. Note that this approach uses distance from controller,
308 // rather than eye, for simplicity. This will make the sphere slightly 286 // rather than eye, for simplicity. This will make the sphere slightly
309 // off-center. 287 // off-center.
310 gvr::Vec3f corner = {0.5f, 0.5f, 0.0f}; 288 float distance = kDefaultReticleDistance;
311 corner = MatrixVectorMul(content_plane->transform.to_world, corner); 289 ContentRectangle* content_plane = scene_->GetContentQuad();
312 float max_distance = Distance(origin, corner) * kReticleDistanceMultiplier; 290 if (content_plane) {
313 if (distance > max_distance || distance <= 0.0f) { 291 distance = content_plane->GetRayDistance(origin, forward);
314 distance = max_distance; 292
293 gvr::Vec3f corner = {0.5f, 0.5f, 0.0f};
294 corner = MatrixVectorMul(content_plane->transform.to_world, corner);
295 float max_distance = Distance(origin, corner) * kReticleDistanceMultiplier;
296 if (distance > max_distance || distance <= 0.0f) {
297 distance = max_distance;
298 }
315 } 299 }
300
316 target_point_ = GetRayPoint(origin, forward, distance); 301 target_point_ = GetRayPoint(origin, forward, distance);
317 gvr::Vec3f eye_to_target = target_point_; 302 gvr::Vec3f eye_to_target = target_point_;
318 NormalizeVector(eye_to_target); 303 NormalizeVector(eye_to_target);
319 304
320 // Determine which UI element (if any) intersects the line between the eyes 305 // Determine which UI element (if any) intersects the line between the eyes
321 // and the controller target position. 306 // and the controller target position.
322 float closest_element_distance = std::numeric_limits<float>::infinity(); 307 float closest_element_distance = std::numeric_limits<float>::infinity();
323 int pixel_x = 0; 308 int pixel_x = 0;
324 int pixel_y = 0; 309 int pixel_y = 0;
310 target_element_ = nullptr;
325 VrInputManager* input_target = nullptr; 311 VrInputManager* input_target = nullptr;
326 312
327 for (std::size_t i = 0; i < scene_->GetUiElements().size(); ++i) { 313 for (std::size_t i = 0; i < scene_->GetUiElements().size(); ++i) {
328 const ContentRectangle* plane = scene_->GetUiElements()[i].get(); 314 const ContentRectangle* plane = scene_->GetUiElements()[i].get();
329 if (!plane->visible || !plane->hit_testable) { 315 if (!plane->visible || !plane->hit_testable) {
330 continue; 316 continue;
331 } 317 }
332 float distance_to_plane = plane->GetRayDistance(kOrigin, eye_to_target); 318 float distance_to_plane = plane->GetRayDistance(kOrigin, eye_to_target);
333 gvr::Vec3f plane_intersection_point = 319 gvr::Vec3f plane_intersection_point =
334 GetRayPoint(kOrigin, eye_to_target, distance_to_plane); 320 GetRayPoint(kOrigin, eye_to_target, distance_to_plane);
335 321
336 gvr::Vec3f rect_2d_point = 322 gvr::Vec3f rect_2d_point =
337 MatrixVectorMul(plane->transform.from_world, plane_intersection_point); 323 MatrixVectorMul(plane->transform.from_world, plane_intersection_point);
338 if (distance_to_plane > 0 && distance_to_plane < closest_element_distance) { 324 if (distance_to_plane > 0 && distance_to_plane < closest_element_distance) {
339 float x = rect_2d_point.x + 0.5f; 325 float x = rect_2d_point.x + 0.5f;
340 float y = 0.5f - rect_2d_point.y; 326 float y = 0.5f - rect_2d_point.y;
341 bool is_inside = x >= 0.0f && x < 1.0f && y >= 0.0f && y < 1.0f; 327 bool is_inside = x >= 0.0f && x < 1.0f && y >= 0.0f && y < 1.0f;
342 if (is_inside) { 328 if (is_inside) {
343 closest_element_distance = distance_to_plane; 329 closest_element_distance = distance_to_plane;
344 pixel_x = 330 pixel_x =
345 static_cast<int>(plane->copy_rect.width * x + plane->copy_rect.x); 331 static_cast<int>(plane->copy_rect.width * x + plane->copy_rect.x);
346 pixel_y = 332 pixel_y =
347 static_cast<int>(plane->copy_rect.height * y + plane->copy_rect.y); 333 static_cast<int>(plane->copy_rect.height * y + plane->copy_rect.y);
348 334
349 target_point_ = plane_intersection_point; 335 target_point_ = plane_intersection_point;
350 target_element_ = plane; 336 target_element_ = plane;
351 input_target = (plane->id == kBrowserUiElementId) 337 input_target = plane->content_quad ? content_input_manager_.get() :
352 ? content_input_manager_.get() : ui_input_manager_.get(); 338 ui_input_manager_.get();
353 } 339 }
354 } 340 }
355 } 341 }
356 bool new_target = input_target != current_input_target_; 342 bool new_target = input_target != current_input_target_;
357 if (new_target && current_input_target_ != nullptr) { 343 if (new_target && current_input_target_ != nullptr) {
358 // Send a move event indicating that the pointer moved off of an element. 344 // Send a move event indicating that the pointer moved off of an element.
359 gesture->type = WebInputEvent::MouseLeave; 345 gesture->type = WebInputEvent::MouseLeave;
360 gesture->details.move.delta.x = 0; 346 gesture->details.move.delta.x = 0;
361 gesture->details.move.delta.y = 0; 347 gesture->details.move.delta.y = 0;
362 current_input_target_->ProcessUpdatedGesture(*gesture.get()); 348 current_input_target_->ProcessUpdatedGesture(*gesture.get());
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 } 426 }
441 } else { 427 } else {
442 DrawVrShell(head_pose); 428 DrawVrShell(head_pose);
443 } 429 }
444 430
445 frame.Unbind(); 431 frame.Unbind();
446 frame.Submit(*buffer_viewport_list_, head_pose); 432 frame.Submit(*buffer_viewport_list_, head_pose);
447 } 433 }
448 434
449 void VrShell::DrawVrShell(const gvr::Mat4f& head_pose) { 435 void VrShell::DrawVrShell(const gvr::Mat4f& head_pose) {
450 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; 436 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f;
451 437
452 HandleQueuedTasks(); 438 HandleQueuedTasks();
453 439
454 // Update the render position of all UI elements (including desktop). 440 // Update the render position of all UI elements (including desktop).
455 scene_->UpdateTransforms(screen_tilt, UiScene::TimeInMicroseconds()); 441 scene_->UpdateTransforms(screen_tilt, UiScene::TimeInMicroseconds());
456 442
457 UpdateController(GetForwardVector(head_pose)); 443 UpdateController(GetForwardVector(head_pose));
458 444
459 // Use culling to remove back faces. 445 // Use culling to remove back faces.
460 glEnable(GL_CULL_FACE); 446 glEnable(GL_CULL_FACE);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 503
518 void VrShell::DrawUI(const gvr::Mat4f& world_matrix, 504 void VrShell::DrawUI(const gvr::Mat4f& world_matrix,
519 const gvr::Mat4f& fov_matrix) { 505 const gvr::Mat4f& fov_matrix) {
520 for (const auto& rect : scene_->GetUiElements()) { 506 for (const auto& rect : scene_->GetUiElements()) {
521 if (!rect->visible) { 507 if (!rect->visible) {
522 continue; 508 continue;
523 } 509 }
524 510
525 Rectf copy_rect; 511 Rectf copy_rect;
526 jint texture_handle; 512 jint texture_handle;
527 if (rect->id == kBrowserUiElementId) { 513 if (rect->content_quad) {
528 copy_rect = {0, 0, 1, 1}; 514 copy_rect = {0, 0, 1, 1};
529 texture_handle = content_texture_id_; 515 texture_handle = content_texture_id_;
530 } else { 516 } else {
531 copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_width_; 517 copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_width_;
532 copy_rect.y = static_cast<float>(rect->copy_rect.y) / ui_tex_height_; 518 copy_rect.y = static_cast<float>(rect->copy_rect.y) / ui_tex_height_;
533 copy_rect.width = static_cast<float>(rect->copy_rect.width) / 519 copy_rect.width = static_cast<float>(rect->copy_rect.width) /
534 ui_tex_width_; 520 ui_tex_width_;
535 copy_rect.height = static_cast<float>(rect->copy_rect.height) / 521 copy_rect.height = static_cast<float>(rect->copy_rect.height) /
536 ui_tex_height_; 522 ui_tex_height_;
537 texture_handle = ui_texture_id_; 523 texture_handle = ui_texture_id_;
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 gvr::GvrApi* VrShell::gvr_api() { 775 gvr::GvrApi* VrShell::gvr_api() {
790 return gvr_api_.get(); 776 return gvr_api_.get();
791 } 777 }
792 778
793 void VrShell::ContentSurfaceChanged(JNIEnv* env, 779 void VrShell::ContentSurfaceChanged(JNIEnv* env,
794 const JavaParamRef<jobject>& object, 780 const JavaParamRef<jobject>& object,
795 jint width, 781 jint width,
796 jint height, 782 jint height,
797 const JavaParamRef<jobject>& surface) { 783 const JavaParamRef<jobject>& surface) {
798 content_compositor_->SurfaceChanged((int)width, (int)height, surface); 784 content_compositor_->SurfaceChanged((int)width, (int)height, surface);
799 content::ScreenInfo result;
800 main_contents_->GetRenderWidgetHostView()->GetRenderWidgetHost()->
801 GetScreenInfo(&result);
802 float dpr = result.device_scale_factor;
803 scene_->GetUiElementById(kBrowserUiElementId)->copy_rect =
804 { 0, 0, width / dpr, height / dpr };
805 } 785 }
806 786
807 void VrShell::UiSurfaceChanged(JNIEnv* env, 787 void VrShell::UiSurfaceChanged(JNIEnv* env,
808 const JavaParamRef<jobject>& object, 788 const JavaParamRef<jobject>& object,
809 jint width, 789 jint width,
810 jint height, 790 jint height,
811 const JavaParamRef<jobject>& surface) { 791 const JavaParamRef<jobject>& surface) {
812 ui_compositor_->SurfaceChanged((int)width, (int)height, surface); 792 ui_compositor_->SurfaceChanged((int)width, (int)height, surface);
813 content::ScreenInfo result; 793 content::ScreenInfo result;
814 ui_contents_->GetRenderWidgetHostView()->GetRenderWidgetHost()->GetScreenInfo( 794 ui_contents_->GetRenderWidgetHostView()->GetRenderWidgetHost()->GetScreenInfo(
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 const JavaParamRef<jobject>& ui_web_contents, 860 const JavaParamRef<jobject>& ui_web_contents,
881 jlong ui_window_android) { 861 jlong ui_window_android) {
882 return reinterpret_cast<intptr_t>(new VrShell( 862 return reinterpret_cast<intptr_t>(new VrShell(
883 env, obj, content::WebContents::FromJavaWebContents(content_web_contents), 863 env, obj, content::WebContents::FromJavaWebContents(content_web_contents),
884 reinterpret_cast<ui::WindowAndroid*>(content_window_android), 864 reinterpret_cast<ui::WindowAndroid*>(content_window_android),
885 content::WebContents::FromJavaWebContents(ui_web_contents), 865 content::WebContents::FromJavaWebContents(ui_web_contents),
886 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); 866 reinterpret_cast<ui::WindowAndroid*>(ui_window_android)));
887 } 867 }
888 868
889 } // namespace vr_shell 869 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698