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_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 29 matching lines...) Expand all Loading... |
40 | 40 |
41 namespace { | 41 namespace { |
42 static constexpr float kZNear = 0.1f; | 42 static constexpr float kZNear = 0.1f; |
43 static constexpr float kZFar = 1000.0f; | 43 static constexpr float kZFar = 1000.0f; |
44 | 44 |
45 static constexpr float kReticleWidth = 0.025f; | 45 static constexpr float kReticleWidth = 0.025f; |
46 static constexpr float kReticleHeight = 0.025f; | 46 static constexpr float kReticleHeight = 0.025f; |
47 | 47 |
48 static constexpr float kLaserWidth = 0.01f; | 48 static constexpr float kLaserWidth = 0.01f; |
49 | 49 |
50 // Angle (radians) the beam down from the controller axis, for wrist comfort. | |
51 static constexpr float kErgoAngleOffset = 0.26f; | |
52 | |
53 static constexpr gfx::Point3F kOrigin = {0.0f, 0.0f, 0.0f}; | 50 static constexpr gfx::Point3F kOrigin = {0.0f, 0.0f, 0.0f}; |
54 | 51 |
55 // In lieu of an elbow model, we assume a position for the user's hand. | |
56 // TODO(mthiesse): Handedness options. | |
57 static constexpr gfx::Point3F kHandPosition = {0.2f, -0.5f, -0.2f}; | |
58 | |
59 // Fraction of the distance to the object the cursor is drawn at to avoid | 52 // Fraction of the distance to the object the cursor is drawn at to avoid |
60 // rounding errors drawing the cursor behind the object. | 53 // rounding errors drawing the cursor behind the object. |
61 static constexpr float kReticleOffset = 0.99f; | 54 static constexpr float kReticleOffset = 0.99f; |
62 | 55 |
63 // GVR buffer indices for use with viewport->SetSourceBufferIndex | 56 // GVR buffer indices for use with viewport->SetSourceBufferIndex |
64 // or frame.BindBuffer. We use one for world content (with reprojection) | 57 // or frame.BindBuffer. We use one for world content (with reprojection) |
65 // including main VrShell and WebVR content plus world-space UI. | 58 // including main VrShell and WebVR content plus world-space UI. |
66 // The headlocked buffer is for UI that should not use reprojection. | 59 // The headlocked buffer is for UI that should not use reprojection. |
67 static constexpr int kFramePrimaryBuffer = 0; | 60 static constexpr int kFramePrimaryBuffer = 0; |
68 static constexpr int kFrameHeadlockedBuffer = 1; | 61 static constexpr int kFrameHeadlockedBuffer = 1; |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 webvr_right_viewport_.reset( | 500 webvr_right_viewport_.reset( |
508 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); | 501 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); |
509 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, | 502 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, |
510 webvr_right_viewport_.get()); | 503 webvr_right_viewport_.get()); |
511 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); | 504 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); |
512 | 505 |
513 main_thread_task_runner_->PostTask( | 506 main_thread_task_runner_->PostTask( |
514 FROM_HERE, base::Bind(&VrShell::GvrDelegateReady, weak_vr_shell_)); | 507 FROM_HERE, base::Bind(&VrShell::GvrDelegateReady, weak_vr_shell_)); |
515 } | 508 } |
516 | 509 |
517 void VrShellGl::UpdateController() { | 510 void VrShellGl::UpdateController(const gfx::Vector3dF& head_direction) { |
518 controller_->UpdateState(); | 511 controller_->UpdateState(head_direction); |
| 512 pointer_start_ = controller_->GetPointerStart(); |
519 | 513 |
520 device::GvrGamepadData pad = controller_->GetGamepadData(); | 514 device::GvrGamepadData pad = controller_->GetGamepadData(); |
521 main_thread_task_runner_->PostTask( | 515 main_thread_task_runner_->PostTask( |
522 FROM_HERE, base::Bind(&VrShell::UpdateGamepadData, weak_vr_shell_, pad)); | 516 FROM_HERE, base::Bind(&VrShell::UpdateGamepadData, weak_vr_shell_, pad)); |
523 } | 517 } |
524 | 518 |
525 void VrShellGl::HandleControllerInput(const gfx::Vector3dF& forward_vector) { | 519 void VrShellGl::HandleControllerInput(const gfx::Vector3dF& head_direction) { |
526 if (ShouldDrawWebVr()) { | 520 if (ShouldDrawWebVr()) { |
527 // Process screen touch events for Cardboard button compatibility. | 521 // Process screen touch events for Cardboard button compatibility. |
528 // Also send tap events for controller "touchpad click" events. | 522 // Also send tap events for controller "touchpad click" events. |
529 if (touch_pending_ || | 523 if (touch_pending_ || |
530 controller_->ButtonUpHappened( | 524 controller_->ButtonUpHappened( |
531 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { | 525 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { |
532 touch_pending_ = false; | 526 touch_pending_ = false; |
533 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( | 527 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( |
534 WebInputEvent::kGestureTapDown, WebInputEvent::kNoModifiers, | 528 WebInputEvent::kGestureTapDown, WebInputEvent::kNoModifiers, |
535 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); | 529 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); |
536 gesture->source_device = blink::kWebGestureDeviceTouchpad; | 530 gesture->source_device = blink::kWebGestureDeviceTouchpad; |
537 gesture->x = 0; | 531 gesture->x = 0; |
538 gesture->y = 0; | 532 gesture->y = 0; |
539 SendGesture(InputTarget::CONTENT, std::move(gesture)); | 533 SendGesture(InputTarget::CONTENT, std::move(gesture)); |
540 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; | 534 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; |
541 } | 535 } |
542 } | 536 } |
543 | 537 |
544 gfx::Vector3dF ergo_neutral_pose; | 538 gfx::Vector3dF ergo_neutral_pose; |
545 if (!controller_->IsConnected()) { | 539 if (!controller_->IsConnected()) { |
546 // No controller detected, set up a gaze cursor that tracks the | 540 // No controller detected, set up a gaze cursor that tracks the |
547 // forward direction. | 541 // forward direction. |
548 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; | 542 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; |
549 controller_quat_ = GetRotationFromZAxis(forward_vector); | 543 controller_quat_ = GetRotationFromZAxis(head_direction); |
550 } else { | 544 } else { |
551 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; | 545 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; |
552 controller_quat_ = controller_->Orientation(); | 546 controller_quat_ = controller_->Orientation(); |
553 } | 547 } |
554 | 548 |
555 vr::Mat4f mat; | 549 vr::Mat4f mat; |
556 QuatToMatrix(controller_quat_, &mat); | 550 QuatToMatrix(controller_quat_, &mat); |
557 gfx::Vector3dF controller_direction = | 551 gfx::Vector3dF controller_direction = |
558 vr::MatrixVectorMul(mat, ergo_neutral_pose); | 552 vr::MatrixVectorMul(mat, ergo_neutral_pose); |
559 | 553 |
(...skipping 12 matching lines...) Expand all Loading... |
572 // - Create a vector between the eyes and the outer surface point. | 566 // - Create a vector between the eyes and the outer surface point. |
573 // - If any UI elements intersect this vector, and is within the bounding | 567 // - If any UI elements intersect this vector, and is within the bounding |
574 // sphere, choose the closest to the eyes, and place the reticle at the | 568 // sphere, choose the closest to the eyes, and place the reticle at the |
575 // intersection point. | 569 // intersection point. |
576 | 570 |
577 // Compute the distance from the eyes to the distance limiting sphere. Note | 571 // Compute the distance from the eyes to the distance limiting sphere. Note |
578 // that the sphere is centered at the controller, rather than the eye, for | 572 // that the sphere is centered at the controller, rather than the eye, for |
579 // simplicity. | 573 // simplicity. |
580 float distance = scene_->GetBackgroundDistance(); | 574 float distance = scene_->GetBackgroundDistance(); |
581 target_point_ = | 575 target_point_ = |
582 vr::GetRayPoint(kHandPosition, controller_direction, distance); | 576 vr::GetRayPoint(pointer_start_, controller_direction, distance); |
583 gfx::Vector3dF eye_to_target = target_point_ - kOrigin; | 577 gfx::Vector3dF eye_to_target = target_point_ - kOrigin; |
584 vr::NormalizeVector(&eye_to_target); | 578 vr::NormalizeVector(&eye_to_target); |
585 | 579 |
586 // Determine which UI element (if any) intersects the line between the eyes | 580 // Determine which UI element (if any) intersects the line between the eyes |
587 // and the controller target position. | 581 // and the controller target position. |
588 float closest_element_distance = (target_point_ - kOrigin).Length(); | 582 float closest_element_distance = (target_point_ - kOrigin).Length(); |
589 target_element_ = nullptr; | 583 target_element_ = nullptr; |
590 float target_x; | 584 float target_x; |
591 float target_y; | 585 float target_y; |
592 | 586 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 device::GvrDelegate::GetGvrPoseWithNeckModel(gvr_api_.get(), &head_pose); | 853 device::GvrDelegate::GetGvrPoseWithNeckModel(gvr_api_.get(), &head_pose); |
860 } | 854 } |
861 | 855 |
862 // Update the render position of all UI elements (including desktop). | 856 // Update the render position of all UI elements (including desktop). |
863 scene_->UpdateTransforms(current_time); | 857 scene_->UpdateTransforms(current_time); |
864 | 858 |
865 { | 859 { |
866 // TODO(crbug.com/704690): Acquire controller state in a way that's timely | 860 // TODO(crbug.com/704690): Acquire controller state in a way that's timely |
867 // for both the gamepad API and UI input handling. | 861 // for both the gamepad API and UI input handling. |
868 TRACE_EVENT0("gpu", "VrShellGl::UpdateController"); | 862 TRACE_EVENT0("gpu", "VrShellGl::UpdateController"); |
869 UpdateController(); | 863 auto head_direction = vr::GetForwardVector(head_pose); |
870 HandleControllerInput(vr::GetForwardVector(head_pose)); | 864 UpdateController(head_direction); |
| 865 HandleControllerInput(head_direction); |
871 } | 866 } |
872 | 867 |
873 DrawWorldElements(head_pose); | 868 DrawWorldElements(head_pose); |
874 | 869 |
875 frame.Unbind(); | 870 frame.Unbind(); |
876 | 871 |
877 // Draw head-locked elements to a separate, non-reprojected buffer. | 872 // Draw head-locked elements to a separate, non-reprojected buffer. |
878 if (scene_->HasVisibleHeadLockedElements()) { | 873 if (scene_->HasVisibleHeadLockedElements()) { |
879 frame.BindBuffer(kFrameHeadlockedBuffer); | 874 frame.BindBuffer(kFrameHeadlockedBuffer); |
880 DrawHeadLockedElements(); | 875 DrawHeadLockedElements(); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
976 vr::Mat4f render_matrix; | 971 vr::Mat4f render_matrix; |
977 vr::Mat4f perspective_matrix; | 972 vr::Mat4f perspective_matrix; |
978 GvrMatToMatf(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), | 973 GvrMatToMatf(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), |
979 kZNear, kZFar), | 974 kZNear, kZFar), |
980 &perspective_matrix); | 975 &perspective_matrix); |
981 | 976 |
982 vr::MatrixMul(perspective_matrix, eye_view_matrix, &render_matrix); | 977 vr::MatrixMul(perspective_matrix, eye_view_matrix, &render_matrix); |
983 | 978 |
984 DrawElements(render_matrix, elementsInDrawOrder); | 979 DrawElements(render_matrix, elementsInDrawOrder); |
985 if (draw_cursor) { | 980 if (draw_cursor) { |
| 981 DrawController(render_matrix); |
986 DrawCursor(render_matrix); | 982 DrawCursor(render_matrix); |
987 DrawController(render_matrix); | |
988 } | 983 } |
989 } | 984 } |
990 } | 985 } |
991 | 986 |
992 void VrShellGl::DrawElements(const vr::Mat4f& view_proj_matrix, | 987 void VrShellGl::DrawElements(const vr::Mat4f& view_proj_matrix, |
993 const std::vector<const UiElement*>& elements) { | 988 const std::vector<const UiElement*>& elements) { |
994 for (const auto* rect : elements) { | 989 for (const auto* rect : elements) { |
995 vr::Mat4f transform; | 990 vr::Mat4f transform; |
996 vr::MatrixMul(view_proj_matrix, rect->TransformMatrix(), &transform); | 991 vr::MatrixMul(view_proj_matrix, rect->TransformMatrix(), &transform); |
997 | 992 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 vr::TranslateM(mat, target_point - kOrigin, &mat); | 1088 vr::TranslateM(mat, target_point - kOrigin, &mat); |
1094 | 1089 |
1095 vr::Mat4f transform; | 1090 vr::Mat4f transform; |
1096 vr::MatrixMul(render_matrix, mat, &transform); | 1091 vr::MatrixMul(render_matrix, mat, &transform); |
1097 vr_shell_renderer_->GetReticleRenderer()->Draw(transform); | 1092 vr_shell_renderer_->GetReticleRenderer()->Draw(transform); |
1098 | 1093 |
1099 // Draw the laser. | 1094 // Draw the laser. |
1100 | 1095 |
1101 // Find the length of the beam (from hand to target). | 1096 // Find the length of the beam (from hand to target). |
1102 const float laser_length = | 1097 const float laser_length = |
1103 std::sqrt(kHandPosition.SquaredDistanceTo(target_point)); | 1098 std::sqrt(pointer_start_.SquaredDistanceTo(target_point)); |
1104 | 1099 |
1105 // Build a beam, originating from the origin. | 1100 // Build a beam, originating from the origin. |
1106 vr::SetIdentityM(&mat); | 1101 vr::SetIdentityM(&mat); |
1107 | 1102 |
1108 // Move the beam half its height so that its end sits on the origin. | 1103 // Move the beam half its height so that its end sits on the origin. |
1109 vr::TranslateM(mat, {0.0f, 0.5f, 0.0f}, &mat); | 1104 vr::TranslateM(mat, {0.0f, 0.5f, 0.0f}, &mat); |
1110 vr::ScaleM(mat, {kLaserWidth, laser_length, 1}, &mat); | 1105 vr::ScaleM(mat, {kLaserWidth, laser_length, 1}, &mat); |
1111 | 1106 |
1112 // Tip back 90 degrees to flat, pointing at the scene. | 1107 // Tip back 90 degrees to flat, pointing at the scene. |
1113 const vr::Quatf quat = vr::QuatFromAxisAngle({1.0f, 0.0f, 0.0f, -M_PI / 2}); | 1108 const vr::Quatf quat = vr::QuatFromAxisAngle({1.0f, 0.0f, 0.0f, -M_PI / 2}); |
1114 vr::QuatToMatrix(quat, &rotation_mat); | 1109 vr::QuatToMatrix(quat, &rotation_mat); |
1115 vr::MatrixMul(rotation_mat, mat, &mat); | 1110 vr::MatrixMul(rotation_mat, mat, &mat); |
1116 | 1111 |
1117 const gfx::Vector3dF beam_direction = target_point_ - kHandPosition; | 1112 const gfx::Vector3dF beam_direction = target_point_ - pointer_start_; |
1118 | 1113 |
1119 vr::Mat4f beam_direction_mat; | 1114 vr::Mat4f beam_direction_mat; |
1120 vr::QuatToMatrix(GetRotationFromZAxis(beam_direction), &beam_direction_mat); | 1115 vr::QuatToMatrix(GetRotationFromZAxis(beam_direction), &beam_direction_mat); |
1121 | 1116 |
| 1117 float opacity = controller_->GetOpacity(); |
1122 // Render multiple faces to make the laser appear cylindrical. | 1118 // Render multiple faces to make the laser appear cylindrical. |
1123 const int faces = 4; | 1119 const int faces = 4; |
1124 for (int i = 0; i < faces; i++) { | 1120 for (int i = 0; i < faces; i++) { |
1125 // Rotate around Z. | 1121 // Rotate around Z. |
1126 const float angle = M_PI * 2 * i / faces; | 1122 const float angle = M_PI * 2 * i / faces; |
1127 const vr::Quatf rot = vr::QuatFromAxisAngle({0.0f, 0.0f, 1.0f, angle}); | 1123 const vr::Quatf rot = vr::QuatFromAxisAngle({0.0f, 0.0f, 1.0f, angle}); |
1128 vr::Mat4f face_transform; | 1124 vr::Mat4f face_transform; |
1129 vr::QuatToMatrix(rot, &face_transform); | 1125 vr::QuatToMatrix(rot, &face_transform); |
1130 vr::MatrixMul(face_transform, mat, &face_transform); | 1126 vr::MatrixMul(face_transform, mat, &face_transform); |
1131 // Orient according to target direction. | 1127 // Orient according to target direction. |
1132 vr::MatrixMul(beam_direction_mat, face_transform, &face_transform); | 1128 vr::MatrixMul(beam_direction_mat, face_transform, &face_transform); |
1133 | 1129 |
1134 // Move the beam origin to the hand. | 1130 // Move the beam origin to the hand. |
1135 vr::TranslateM(face_transform, kHandPosition - kOrigin, &face_transform); | 1131 vr::TranslateM(face_transform, pointer_start_ - kOrigin, &face_transform); |
1136 | 1132 |
1137 vr::MatrixMul(render_matrix, face_transform, &transform); | 1133 vr::MatrixMul(render_matrix, face_transform, &transform); |
1138 vr_shell_renderer_->GetLaserRenderer()->Draw(transform); | 1134 vr_shell_renderer_->GetLaserRenderer()->Draw(opacity, transform); |
1139 } | 1135 } |
1140 } | 1136 } |
1141 | 1137 |
1142 void VrShellGl::DrawController(const vr::Mat4f& view_proj_matrix) { | 1138 void VrShellGl::DrawController(const vr::Mat4f& view_proj_matrix) { |
1143 if (!vr_shell_renderer_->GetControllerRenderer()->IsSetUp()) | 1139 if (!vr_shell_renderer_->GetControllerRenderer()->IsSetUp()) |
1144 return; | 1140 return; |
| 1141 auto state = controller_->GetModelState(); |
| 1142 auto opacity = controller_->GetOpacity(); |
1145 vr::Mat4f controller_transform; | 1143 vr::Mat4f controller_transform; |
1146 controller_->GetTransform(&controller_transform); | 1144 controller_->GetTransform(&controller_transform); |
1147 vr::Mat4f transform; | 1145 vr::Mat4f transform; |
1148 vr::MatrixMul(view_proj_matrix, controller_transform, &transform); | 1146 vr::MatrixMul(view_proj_matrix, controller_transform, &transform); |
1149 auto state = controller_->GetModelState(); | 1147 vr_shell_renderer_->GetControllerRenderer()->Draw(state, opacity, transform); |
1150 vr_shell_renderer_->GetControllerRenderer()->Draw(state, transform); | |
1151 } | 1148 } |
1152 | 1149 |
1153 bool VrShellGl::ShouldDrawWebVr() { | 1150 bool VrShellGl::ShouldDrawWebVr() { |
1154 return web_vr_mode_ && scene_->GetWebVrRenderingEnabled(); | 1151 return web_vr_mode_ && scene_->GetWebVrRenderingEnabled(); |
1155 } | 1152 } |
1156 | 1153 |
1157 void VrShellGl::DrawWebVr() { | 1154 void VrShellGl::DrawWebVr() { |
1158 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); | 1155 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); |
1159 // Don't need face culling, depth testing, blending, etc. Turn it all off. | 1156 // Don't need face culling, depth testing, blending, etc. Turn it all off. |
1160 glDisable(GL_CULL_FACE); | 1157 glDisable(GL_CULL_FACE); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1325 // InitializeGl. Revisit if the initialization order changes. | 1322 // InitializeGl. Revisit if the initialization order changes. |
1326 device::mojom::VRDisplayInfoPtr info = | 1323 device::mojom::VRDisplayInfoPtr info = |
1327 device::GvrDelegate::CreateVRDisplayInfo(gvr_api_.get(), | 1324 device::GvrDelegate::CreateVRDisplayInfo(gvr_api_.get(), |
1328 webvr_surface_size_, device_id); | 1325 webvr_surface_size_, device_id); |
1329 main_thread_task_runner_->PostTask( | 1326 main_thread_task_runner_->PostTask( |
1330 FROM_HERE, | 1327 FROM_HERE, |
1331 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); | 1328 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); |
1332 } | 1329 } |
1333 | 1330 |
1334 } // namespace vr_shell | 1331 } // namespace vr_shell |
OLD | NEW |