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

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

Issue 2795793002: Implementation of elbow model for the controller position and rotation. (Closed)
Patch Set: Created 3 years, 8 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_gl.h" 5 #include "chrome/browser/android/vr_shell/vr_shell_gl.h"
6 6
7 #include <chrono> 7 #include <chrono>
8 #include <limits> 8 #include <limits>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 30 matching lines...) Expand all
41 static constexpr int64_t kPredictionTimeWithoutVsyncNanos = 50000000; 41 static constexpr int64_t kPredictionTimeWithoutVsyncNanos = 50000000;
42 42
43 static constexpr float kZNear = 0.1f; 43 static constexpr float kZNear = 0.1f;
44 static constexpr float kZFar = 1000.0f; 44 static constexpr float kZFar = 1000.0f;
45 45
46 static constexpr float kReticleWidth = 0.025f; 46 static constexpr float kReticleWidth = 0.025f;
47 static constexpr float kReticleHeight = 0.025f; 47 static constexpr float kReticleHeight = 0.025f;
48 48
49 static constexpr float kLaserWidth = 0.01f; 49 static constexpr float kLaserWidth = 0.01f;
50 50
51 // Angle (radians) the beam down from the controller axis, for wrist comfort.
52 static constexpr float kErgoAngleOffset = 0.26f;
53
54 static constexpr gvr::Vec3f kOrigin = {0.0f, 0.0f, 0.0f}; 51 static constexpr gvr::Vec3f kOrigin = {0.0f, 0.0f, 0.0f};
55 52
56 // In lieu of an elbow model, we assume a position for the user's hand.
57 // TODO(mthiesse): Handedness options.
58 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f};
59
60 // Fraction of the distance to the object the cursor is drawn at to avoid 53 // Fraction of the distance to the object the cursor is drawn at to avoid
61 // rounding errors drawing the cursor behind the object. 54 // rounding errors drawing the cursor behind the object.
62 static constexpr float kReticleOffset = 0.99f; 55 static constexpr float kReticleOffset = 0.99f;
63 56
64 // GVR buffer indices for use with viewport->SetSourceBufferIndex 57 // GVR buffer indices for use with viewport->SetSourceBufferIndex
65 // or frame.BindBuffer. We use one for world content (with reprojection) 58 // or frame.BindBuffer. We use one for world content (with reprojection)
66 // including main VrShell and WebVR content plus world-space UI. 59 // including main VrShell and WebVR content plus world-space UI.
67 // The headlocked buffer is for UI that should not use reprojection. 60 // The headlocked buffer is for UI that should not use reprojection.
68 static constexpr int kFramePrimaryBuffer = 0; 61 static constexpr int kFramePrimaryBuffer = 0;
69 static constexpr int kFrameHeadlockedBuffer = 1; 62 static constexpr int kFrameHeadlockedBuffer = 1;
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 webvr_right_viewport_.reset( 455 webvr_right_viewport_.reset(
463 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); 456 new gvr::BufferViewport(gvr_api_->CreateBufferViewport()));
464 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, 457 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE,
465 webvr_right_viewport_.get()); 458 webvr_right_viewport_.get());
466 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); 459 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer);
467 460
468 main_thread_task_runner_->PostTask( 461 main_thread_task_runner_->PostTask(
469 FROM_HERE, base::Bind(&VrShell::GvrDelegateReady, weak_vr_shell_)); 462 FROM_HERE, base::Bind(&VrShell::GvrDelegateReady, weak_vr_shell_));
470 } 463 }
471 464
472 void VrShellGl::UpdateController() { 465 void VrShellGl::UpdateController(const gvr::Vec3f& head_direction) {
473 controller_->UpdateState(); 466 controller_->UpdateState(head_direction);
467 pointer_start_ = controller_->GetPointerStart();
474 468
475 device::GvrGamepadData pad = controller_->GetGamepadData(); 469 device::GvrGamepadData pad = controller_->GetGamepadData();
476 main_thread_task_runner_->PostTask( 470 main_thread_task_runner_->PostTask(
477 FROM_HERE, base::Bind(&VrShell::UpdateGamepadData, weak_vr_shell_, pad)); 471 FROM_HERE, base::Bind(&VrShell::UpdateGamepadData, weak_vr_shell_, pad));
478 } 472 }
479 473
480 void VrShellGl::HandleControllerInput(const gvr::Vec3f& forward_vector) { 474 void VrShellGl::HandleControllerInput(const gvr::Vec3f& head_direction) {
481 if (ShouldDrawWebVr()) { 475 if (ShouldDrawWebVr()) {
482 // Process screen touch events for Cardboard button compatibility. 476 // Process screen touch events for Cardboard button compatibility.
483 // Also send tap events for controller "touchpad click" events. 477 // Also send tap events for controller "touchpad click" events.
484 if (touch_pending_ || 478 if (touch_pending_ ||
485 controller_->ButtonUpHappened( 479 controller_->ButtonUpHappened(
486 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { 480 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) {
487 touch_pending_ = false; 481 touch_pending_ = false;
488 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( 482 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent(
489 WebInputEvent::GestureTapDown, WebInputEvent::NoModifiers, 483 WebInputEvent::GestureTapDown, WebInputEvent::NoModifiers,
490 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); 484 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF()));
491 gesture->sourceDevice = blink::WebGestureDeviceTouchpad; 485 gesture->sourceDevice = blink::WebGestureDeviceTouchpad;
492 gesture->x = 0; 486 gesture->x = 0;
493 gesture->y = 0; 487 gesture->y = 0;
494 SendGesture(InputTarget::CONTENT, std::move(gesture)); 488 SendGesture(InputTarget::CONTENT, std::move(gesture));
495 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; 489 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture";
496 } 490 }
497 } 491 }
498 492
499 gvr::Vec3f ergo_neutral_pose; 493 gvr::Vec3f ergo_neutral_pose;
500 if (!controller_->IsConnected()) { 494 if (!controller_->IsConnected()) {
501 // No controller detected, set up a gaze cursor that tracks the 495 // No controller detected, set up a gaze cursor that tracks the
502 // forward direction. 496 // forward direction.
503 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; 497 ergo_neutral_pose = {0.0f, 0.0f, -1.0f};
504 controller_quat_ = GetRotationFromZAxis(forward_vector); 498 controller_quat_ = GetRotationFromZAxis(head_direction);
505 } else { 499 } else {
506 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; 500 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)};
507 controller_quat_ = controller_->Orientation(); 501 controller_quat_ = controller_->Orientation();
508 } 502 }
509 503
510 gvr::Mat4f mat = QuatToMatrix(controller_quat_); 504 gvr::Mat4f mat = QuatToMatrix(controller_quat_);
511 gvr::Vec3f controller_direction = MatrixVectorMul(mat, ergo_neutral_pose); 505 gvr::Vec3f controller_direction = MatrixVectorMul(mat, ergo_neutral_pose);
512 506
513 HandleControllerAppButtonActivity(controller_direction); 507 HandleControllerAppButtonActivity(controller_direction);
514 508
515 if (ShouldDrawWebVr()) { 509 if (ShouldDrawWebVr()) {
516 return; 510 return;
517 } 511 }
518 512
519 // If we place the reticle based on elements intersecting the controller beam, 513 // If we place the reticle based on elements intersecting the controller beam,
520 // we can end up with the reticle hiding behind elements, or jumping laterally 514 // we can end up with the reticle hiding behind elements, or jumping laterally
521 // in the field of view. This is physically correct, but hard to use. For 515 // in the field of view. This is physically correct, but hard to use. For
522 // usability, do the following instead: 516 // usability, do the following instead:
523 // 517 //
524 // - Project the controller laser onto a distance-limiting sphere. 518 // - Project the controller laser onto a distance-limiting sphere.
525 // - Create a vector between the eyes and the outer surface point. 519 // - Create a vector between the eyes and the outer surface point.
526 // - If any UI elements intersect this vector, and is within the bounding 520 // - If any UI elements intersect this vector, and is within the bounding
527 // sphere, choose the closest to the eyes, and place the reticle at the 521 // sphere, choose the closest to the eyes, and place the reticle at the
528 // intersection point. 522 // intersection point.
529 523
530 // Compute the distance from the eyes to the distance limiting sphere. Note 524 // Compute the distance from the eyes to the distance limiting sphere. Note
531 // that the sphere is centered at the controller, rather than the eye, for 525 // that the sphere is centered at the controller, rather than the eye, for
532 // simplicity. 526 // simplicity.
533 float distance = scene_->GetBackgroundDistance(); 527 float distance = scene_->GetBackgroundDistance();
534 target_point_ = GetRayPoint(kHandPosition, controller_direction, distance); 528 target_point_ = GetRayPoint(pointer_start_, controller_direction, distance);
535 gvr::Vec3f eye_to_target = target_point_; 529 gvr::Vec3f eye_to_target = target_point_;
536 NormalizeVector(eye_to_target); 530 NormalizeVector(eye_to_target);
537 531
538 // Determine which UI element (if any) intersects the line between the eyes 532 // Determine which UI element (if any) intersects the line between the eyes
539 // and the controller target position. 533 // and the controller target position.
540 float closest_element_distance = VectorLength(target_point_); 534 float closest_element_distance = VectorLength(target_point_);
541 target_element_ = nullptr; 535 target_element_ = nullptr;
542 float target_x; 536 float target_x;
543 float target_y; 537 float target_y;
544 538
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); 806 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
813 } 807 }
814 808
815 gvr::Vec3f position = GetTranslation(head_pose); 809 gvr::Vec3f position = GetTranslation(head_pose);
816 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { 810 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) {
817 // This appears to be a 3DOF pose without a neck model. Add one. 811 // This appears to be a 3DOF pose without a neck model. Add one.
818 // The head pose has redundant data. Assume we're only using the 812 // The head pose has redundant data. Assume we're only using the
819 // object_from_reference_matrix, we're not updating position_external. 813 // object_from_reference_matrix, we're not updating position_external.
820 // TODO: Not sure what object_from_reference_matrix is. The new api removed 814 // TODO: Not sure what object_from_reference_matrix is. The new api removed
821 // it. For now, removing it seems working fine. 815 // it. For now, removing it seems working fine.
822 gvr_api_->ApplyNeckModel(head_pose, 1.0f); 816 head_pose = gvr_api_->ApplyNeckModel(head_pose, 1.0f);
823 } 817 }
824 818
825 // Update the render position of all UI elements (including desktop). 819 // Update the render position of all UI elements (including desktop).
826 scene_->UpdateTransforms(TimeInMicroseconds()); 820 scene_->UpdateTransforms(TimeInMicroseconds());
827 821
828 { 822 {
829 // TODO(crbug.com/704690): Acquire controller state in a way that's timely 823 // TODO(crbug.com/704690): Acquire controller state in a way that's timely
830 // for both the gamepad API and UI input handling. 824 // for both the gamepad API and UI input handling.
831 TRACE_EVENT0("gpu", "VrShellGl::UpdateController"); 825 TRACE_EVENT0("gpu", "VrShellGl::UpdateController");
832 UpdateController(); 826 auto head_direction = GetForwardVector(head_pose);
833 HandleControllerInput(GetForwardVector(head_pose)); 827 UpdateController(head_direction);
828 HandleControllerInput(head_direction);
834 } 829 }
835 830
836 DrawWorldElements(head_pose); 831 DrawWorldElements(head_pose);
837 832
838 frame.Unbind(); 833 frame.Unbind();
839 834
840 // Draw head-locked elements to a separate, non-reprojected buffer. 835 // Draw head-locked elements to a separate, non-reprojected buffer.
841 if (scene_->HasVisibleHeadLockedElements()) { 836 if (scene_->HasVisibleHeadLockedElements()) {
842 frame.BindBuffer(kFrameHeadlockedBuffer); 837 frame.BindBuffer(kFrameHeadlockedBuffer);
843 DrawHeadLockedElements(); 838 DrawHeadLockedElements();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 pixel_rect.right - pixel_rect.left, 922 pixel_rect.right - pixel_rect.left,
928 pixel_rect.top - pixel_rect.bottom); 923 pixel_rect.top - pixel_rect.bottom);
929 924
930 const gvr::Mat4f render_matrix = 925 const gvr::Mat4f render_matrix =
931 MatrixMul(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), 926 MatrixMul(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(),
932 kZNear, kZFar), 927 kZNear, kZFar),
933 eye_view_matrix); 928 eye_view_matrix);
934 929
935 DrawElements(render_matrix, elementsInDrawOrder); 930 DrawElements(render_matrix, elementsInDrawOrder);
936 if (draw_cursor) { 931 if (draw_cursor) {
932 DrawController(render_matrix);
937 DrawCursor(render_matrix); 933 DrawCursor(render_matrix);
938 DrawController(render_matrix);
939 } 934 }
940 } 935 }
941 } 936 }
942 937
943 void VrShellGl::DrawElements( 938 void VrShellGl::DrawElements(
944 const gvr::Mat4f& view_proj_matrix, 939 const gvr::Mat4f& view_proj_matrix,
945 const std::vector<const ContentRectangle*>& elements) { 940 const std::vector<const ContentRectangle*>& elements) {
946 for (const auto* rect : elements) { 941 for (const auto* rect : elements) {
947 gvr::Mat4f transform = MatrixMul(view_proj_matrix, rect->TransformMatrix()); 942 gvr::Mat4f transform = MatrixMul(view_proj_matrix, rect->TransformMatrix());
948 943
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 TranslateM(mat, mat, target_point_.x * kReticleOffset, 1045 TranslateM(mat, mat, target_point_.x * kReticleOffset,
1051 target_point_.y * kReticleOffset, 1046 target_point_.y * kReticleOffset,
1052 target_point_.z * kReticleOffset); 1047 target_point_.z * kReticleOffset);
1053 1048
1054 gvr::Mat4f transform = MatrixMul(render_matrix, mat); 1049 gvr::Mat4f transform = MatrixMul(render_matrix, mat);
1055 vr_shell_renderer_->GetReticleRenderer()->Draw(transform); 1050 vr_shell_renderer_->GetReticleRenderer()->Draw(transform);
1056 1051
1057 // Draw the laser. 1052 // Draw the laser.
1058 1053
1059 // Find the length of the beam (from hand to target). 1054 // Find the length of the beam (from hand to target).
1060 const float laser_length = Distance(kHandPosition, target_point_); 1055 const float laser_length = Distance(pointer_start_, target_point_);
1061 1056
1062 // Build a beam, originating from the origin. 1057 // Build a beam, originating from the origin.
1063 SetIdentityM(mat); 1058 SetIdentityM(mat);
1064 1059
1065 // Move the beam half its height so that its end sits on the origin. 1060 // Move the beam half its height so that its end sits on the origin.
1066 TranslateM(mat, mat, 0.0f, 0.5f, 0.0f); 1061 TranslateM(mat, mat, 0.0f, 0.5f, 0.0f);
1067 ScaleM(mat, mat, kLaserWidth, laser_length, 1); 1062 ScaleM(mat, mat, kLaserWidth, laser_length, 1);
1068 1063
1069 // Tip back 90 degrees to flat, pointing at the scene. 1064 // Tip back 90 degrees to flat, pointing at the scene.
1070 const gvr::Quatf q = QuatFromAxisAngle({1.0f, 0.0f, 0.0f}, -M_PI / 2); 1065 const gvr::Quatf q = QuatFromAxisAngle({1.0f, 0.0f, 0.0f}, -M_PI / 2);
1071 mat = MatrixMul(QuatToMatrix(q), mat); 1066 mat = MatrixMul(QuatToMatrix(q), mat);
1072 1067
1073 const gvr::Vec3f beam_direction = {target_point_.x - kHandPosition.x, 1068 const gvr::Vec3f beam_direction = {target_point_.x - pointer_start_.x,
1074 target_point_.y - kHandPosition.y, 1069 target_point_.y - pointer_start_.y,
1075 target_point_.z - kHandPosition.z}; 1070 target_point_.z - pointer_start_.z};
1076 const gvr::Mat4f beam_direction_mat = 1071 const gvr::Mat4f beam_direction_mat =
1077 QuatToMatrix(GetRotationFromZAxis(beam_direction)); 1072 QuatToMatrix(GetRotationFromZAxis(beam_direction));
1078 1073
1074 float opacity = controller_->GetOpacity();
1079 // Render multiple faces to make the laser appear cylindrical. 1075 // Render multiple faces to make the laser appear cylindrical.
1080 const int faces = 4; 1076 const int faces = 4;
1081 for (int i = 0; i < faces; i++) { 1077 for (int i = 0; i < faces; i++) {
1082 // Rotate around Z. 1078 // Rotate around Z.
1083 const float angle = M_PI * 2 * i / faces; 1079 const float angle = M_PI * 2 * i / faces;
1084 const gvr::Quatf rot = QuatFromAxisAngle({0.0f, 0.0f, 1.0f}, angle); 1080 const gvr::Quatf rot = QuatFromAxisAngle({0.0f, 0.0f, 1.0f}, angle);
1085 gvr::Mat4f face_transform = MatrixMul(QuatToMatrix(rot), mat); 1081 gvr::Mat4f face_transform = MatrixMul(QuatToMatrix(rot), mat);
1086 1082
1087 // Orient according to target direction. 1083 // Orient according to target direction.
1088 face_transform = MatrixMul(beam_direction_mat, face_transform); 1084 face_transform = MatrixMul(beam_direction_mat, face_transform);
1089 1085
1090 // Move the beam origin to the hand. 1086 // Move the beam origin to the hand.
1091 TranslateM(face_transform, face_transform, kHandPosition.x, kHandPosition.y, 1087 TranslateM(face_transform, face_transform, pointer_start_.x,
1092 kHandPosition.z); 1088 pointer_start_.y, pointer_start_.z);
1093 1089
1094 transform = MatrixMul(render_matrix, face_transform); 1090 transform = MatrixMul(render_matrix, face_transform);
1095 vr_shell_renderer_->GetLaserRenderer()->Draw(transform); 1091 vr_shell_renderer_->GetLaserRenderer()->Draw(opacity, transform);
1096 } 1092 }
1097 } 1093 }
1098 1094
1099 void VrShellGl::DrawController(const gvr::Mat4f& view_proj_matrix) { 1095 void VrShellGl::DrawController(const gvr::Mat4f& view_proj_matrix) {
1100 if (!vr_shell_renderer_->GetControllerRenderer()->IsSetUp()) 1096 if (!vr_shell_renderer_->GetControllerRenderer()->IsSetUp())
1101 return; 1097 return;
1098 auto state = controller_->GetModelState();
1099 auto opacity = controller_->GetOpacity();
1102 auto transform = MatrixMul(view_proj_matrix, controller_->GetTransform()); 1100 auto transform = MatrixMul(view_proj_matrix, controller_->GetTransform());
1103 auto state = controller_->GetModelState(); 1101 vr_shell_renderer_->GetControllerRenderer()->Draw(state, opacity, transform);
1104 vr_shell_renderer_->GetControllerRenderer()->Draw(state, transform);
1105 } 1102 }
1106 1103
1107 bool VrShellGl::ShouldDrawWebVr() { 1104 bool VrShellGl::ShouldDrawWebVr() {
1108 return web_vr_mode_ && scene_->GetWebVrRenderingEnabled(); 1105 return web_vr_mode_ && scene_->GetWebVrRenderingEnabled();
1109 } 1106 }
1110 1107
1111 void VrShellGl::DrawWebVr() { 1108 void VrShellGl::DrawWebVr() {
1112 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); 1109 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr");
1113 // Don't need face culling, depth testing, blending, etc. Turn it all off. 1110 // Don't need face culling, depth testing, blending, etc. Turn it all off.
1114 glDisable(GL_CULL_FACE); 1111 glDisable(GL_CULL_FACE);
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 // appropriate recommended render resolution as the default size during 1301 // appropriate recommended render resolution as the default size during
1305 // InitializeGl. Revisit if the initialization order changes. 1302 // InitializeGl. Revisit if the initialization order changes.
1306 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( 1303 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo(
1307 gvr_api_.get(), webvr_surface_size_, device_id); 1304 gvr_api_.get(), webvr_surface_size_, device_id);
1308 main_thread_task_runner_->PostTask( 1305 main_thread_task_runner_->PostTask(
1309 FROM_HERE, 1306 FROM_HERE,
1310 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); 1307 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info)));
1311 } 1308 }
1312 1309
1313 } // namespace vr_shell 1310 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698