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 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 webvr_right_viewport_.reset( | 498 webvr_right_viewport_.reset( |
506 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); | 499 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); |
507 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, | 500 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, |
508 webvr_right_viewport_.get()); | 501 webvr_right_viewport_.get()); |
509 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); | 502 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); |
510 | 503 |
511 main_thread_task_runner_->PostTask( | 504 main_thread_task_runner_->PostTask( |
512 FROM_HERE, base::Bind(&VrShell::GvrDelegateReady, weak_vr_shell_)); | 505 FROM_HERE, base::Bind(&VrShell::GvrDelegateReady, weak_vr_shell_)); |
513 } | 506 } |
514 | 507 |
515 void VrShellGl::UpdateController() { | 508 void VrShellGl::UpdateController(const gfx::Vector3dF& head_direction) { |
516 controller_->UpdateState(); | 509 controller_->UpdateState(head_direction); |
| 510 pointer_start_ = controller_->GetPointerStart(); |
517 | 511 |
518 device::GvrGamepadData pad = controller_->GetGamepadData(); | 512 device::GvrGamepadData pad = controller_->GetGamepadData(); |
519 main_thread_task_runner_->PostTask( | 513 main_thread_task_runner_->PostTask( |
520 FROM_HERE, base::Bind(&VrShell::UpdateGamepadData, weak_vr_shell_, pad)); | 514 FROM_HERE, base::Bind(&VrShell::UpdateGamepadData, weak_vr_shell_, pad)); |
521 } | 515 } |
522 | 516 |
523 void VrShellGl::HandleControllerInput(const gfx::Vector3dF& forward_vector) { | 517 void VrShellGl::HandleControllerInput(const gfx::Vector3dF& head_direction) { |
524 if (ShouldDrawWebVr()) { | 518 if (ShouldDrawWebVr()) { |
525 // Process screen touch events for Cardboard button compatibility. | 519 // Process screen touch events for Cardboard button compatibility. |
526 // Also send tap events for controller "touchpad click" events. | 520 // Also send tap events for controller "touchpad click" events. |
527 if (touch_pending_ || | 521 if (touch_pending_ || |
528 controller_->ButtonUpHappened( | 522 controller_->ButtonUpHappened( |
529 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { | 523 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { |
530 touch_pending_ = false; | 524 touch_pending_ = false; |
531 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( | 525 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( |
532 WebInputEvent::kGestureTapDown, WebInputEvent::kNoModifiers, | 526 WebInputEvent::kGestureTapDown, WebInputEvent::kNoModifiers, |
533 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); | 527 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); |
534 gesture->source_device = blink::kWebGestureDeviceTouchpad; | 528 gesture->source_device = blink::kWebGestureDeviceTouchpad; |
535 gesture->x = 0; | 529 gesture->x = 0; |
536 gesture->y = 0; | 530 gesture->y = 0; |
537 SendGesture(InputTarget::CONTENT, std::move(gesture)); | 531 SendGesture(InputTarget::CONTENT, std::move(gesture)); |
538 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; | 532 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; |
539 } | 533 } |
540 } | 534 } |
541 | 535 |
542 gfx::Vector3dF ergo_neutral_pose; | 536 gfx::Vector3dF ergo_neutral_pose; |
543 if (!controller_->IsConnected()) { | 537 if (!controller_->IsConnected()) { |
544 // No controller detected, set up a gaze cursor that tracks the | 538 // No controller detected, set up a gaze cursor that tracks the |
545 // forward direction. | 539 // forward direction. |
546 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; | 540 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; |
547 controller_quat_ = GetRotationFromZAxis(forward_vector); | 541 controller_quat_ = GetRotationFromZAxis(head_direction); |
548 } else { | 542 } else { |
549 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; | 543 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; |
550 controller_quat_ = controller_->Orientation(); | 544 controller_quat_ = controller_->Orientation(); |
551 } | 545 } |
552 | 546 |
553 vr::Mat4f mat; | 547 vr::Mat4f mat; |
554 QuatToMatrix(controller_quat_, &mat); | 548 QuatToMatrix(controller_quat_, &mat); |
555 gfx::Vector3dF controller_direction = | 549 gfx::Vector3dF controller_direction = |
556 vr::MatrixVectorMul(mat, ergo_neutral_pose); | 550 vr::MatrixVectorMul(mat, ergo_neutral_pose); |
557 | 551 |
(...skipping 12 matching lines...) Expand all Loading... |
570 // - Create a vector between the eyes and the outer surface point. | 564 // - Create a vector between the eyes and the outer surface point. |
571 // - If any UI elements intersect this vector, and is within the bounding | 565 // - If any UI elements intersect this vector, and is within the bounding |
572 // sphere, choose the closest to the eyes, and place the reticle at the | 566 // sphere, choose the closest to the eyes, and place the reticle at the |
573 // intersection point. | 567 // intersection point. |
574 | 568 |
575 // Compute the distance from the eyes to the distance limiting sphere. Note | 569 // Compute the distance from the eyes to the distance limiting sphere. Note |
576 // that the sphere is centered at the controller, rather than the eye, for | 570 // that the sphere is centered at the controller, rather than the eye, for |
577 // simplicity. | 571 // simplicity. |
578 float distance = scene_->GetBackgroundDistance(); | 572 float distance = scene_->GetBackgroundDistance(); |
579 target_point_ = | 573 target_point_ = |
580 vr::GetRayPoint(kHandPosition, controller_direction, distance); | 574 vr::GetRayPoint(pointer_start_, controller_direction, distance); |
581 gfx::Vector3dF eye_to_target = target_point_ - kOrigin; | 575 gfx::Vector3dF eye_to_target = target_point_ - kOrigin; |
582 vr::NormalizeVector(&eye_to_target); | 576 vr::NormalizeVector(&eye_to_target); |
583 | 577 |
584 // Determine which UI element (if any) intersects the line between the eyes | 578 // Determine which UI element (if any) intersects the line between the eyes |
585 // and the controller target position. | 579 // and the controller target position. |
586 float closest_element_distance = (target_point_ - kOrigin).Length(); | 580 float closest_element_distance = (target_point_ - kOrigin).Length(); |
587 target_element_ = nullptr; | 581 target_element_ = nullptr; |
588 float target_x; | 582 float target_x; |
589 float target_y; | 583 float target_y; |
590 | 584 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 device::GvrDelegate::GetGvrPoseWithNeckModel(gvr_api_.get(), &head_pose); | 851 device::GvrDelegate::GetGvrPoseWithNeckModel(gvr_api_.get(), &head_pose); |
858 } | 852 } |
859 | 853 |
860 // Update the render position of all UI elements (including desktop). | 854 // Update the render position of all UI elements (including desktop). |
861 scene_->UpdateTransforms(current_time); | 855 scene_->UpdateTransforms(current_time); |
862 | 856 |
863 { | 857 { |
864 // TODO(crbug.com/704690): Acquire controller state in a way that's timely | 858 // TODO(crbug.com/704690): Acquire controller state in a way that's timely |
865 // for both the gamepad API and UI input handling. | 859 // for both the gamepad API and UI input handling. |
866 TRACE_EVENT0("gpu", "VrShellGl::UpdateController"); | 860 TRACE_EVENT0("gpu", "VrShellGl::UpdateController"); |
867 UpdateController(); | 861 auto head_direction = vr::GetForwardVector(head_pose); |
868 HandleControllerInput(vr::GetForwardVector(head_pose)); | 862 UpdateController(head_direction); |
| 863 HandleControllerInput(head_direction); |
869 } | 864 } |
870 | 865 |
871 DrawWorldElements(head_pose); | 866 DrawWorldElements(head_pose); |
872 | 867 |
873 frame.Unbind(); | 868 frame.Unbind(); |
874 | 869 |
875 // Draw head-locked elements to a separate, non-reprojected buffer. | 870 // Draw head-locked elements to a separate, non-reprojected buffer. |
876 if (scene_->HasVisibleHeadLockedElements()) { | 871 if (scene_->HasVisibleHeadLockedElements()) { |
877 frame.BindBuffer(kFrameHeadlockedBuffer); | 872 frame.BindBuffer(kFrameHeadlockedBuffer); |
878 DrawHeadLockedElements(); | 873 DrawHeadLockedElements(); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
974 vr::Mat4f render_matrix; | 969 vr::Mat4f render_matrix; |
975 vr::Mat4f perspective_matrix; | 970 vr::Mat4f perspective_matrix; |
976 GvrMatToMatf(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), | 971 GvrMatToMatf(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), |
977 kZNear, kZFar), | 972 kZNear, kZFar), |
978 &perspective_matrix); | 973 &perspective_matrix); |
979 | 974 |
980 vr::MatrixMul(perspective_matrix, eye_view_matrix, &render_matrix); | 975 vr::MatrixMul(perspective_matrix, eye_view_matrix, &render_matrix); |
981 | 976 |
982 DrawElements(render_matrix, elementsInDrawOrder); | 977 DrawElements(render_matrix, elementsInDrawOrder); |
983 if (draw_cursor) { | 978 if (draw_cursor) { |
| 979 DrawController(render_matrix); |
984 DrawCursor(render_matrix); | 980 DrawCursor(render_matrix); |
985 DrawController(render_matrix); | |
986 } | 981 } |
987 } | 982 } |
988 } | 983 } |
989 | 984 |
990 void VrShellGl::DrawElements(const vr::Mat4f& view_proj_matrix, | 985 void VrShellGl::DrawElements(const vr::Mat4f& view_proj_matrix, |
991 const std::vector<const UiElement*>& elements) { | 986 const std::vector<const UiElement*>& elements) { |
992 for (const auto* rect : elements) { | 987 for (const auto* rect : elements) { |
993 vr::Mat4f transform; | 988 vr::Mat4f transform; |
994 vr::MatrixMul(view_proj_matrix, rect->TransformMatrix(), &transform); | 989 vr::MatrixMul(view_proj_matrix, rect->TransformMatrix(), &transform); |
995 | 990 |
(...skipping 97 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 |