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 10 matching lines...) Expand all Loading... | |
21 #include "chrome/browser/android/vr_shell/ui_scene_manager.h" | 21 #include "chrome/browser/android/vr_shell/ui_scene_manager.h" |
22 #include "chrome/browser/android/vr_shell/vr_controller.h" | 22 #include "chrome/browser/android/vr_shell/vr_controller.h" |
23 #include "chrome/browser/android/vr_shell/vr_gl_thread.h" | 23 #include "chrome/browser/android/vr_shell/vr_gl_thread.h" |
24 #include "chrome/browser/android/vr_shell/vr_gl_util.h" | 24 #include "chrome/browser/android/vr_shell/vr_gl_util.h" |
25 #include "chrome/browser/android/vr_shell/vr_shell.h" | 25 #include "chrome/browser/android/vr_shell/vr_shell.h" |
26 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" | 26 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" |
27 #include "device/vr/android/gvr/gvr_delegate.h" | 27 #include "device/vr/android/gvr/gvr_delegate.h" |
28 #include "device/vr/android/gvr/gvr_device.h" | 28 #include "device/vr/android/gvr/gvr_device.h" |
29 #include "device/vr/android/gvr/gvr_gamepad_data_provider.h" | 29 #include "device/vr/android/gvr/gvr_gamepad_data_provider.h" |
30 #include "device/vr/vr_math.h" | 30 #include "device/vr/vr_math.h" |
31 #include "third_party/WebKit/public/platform/WebGestureEvent.h" | |
31 #include "third_party/WebKit/public/platform/WebInputEvent.h" | 32 #include "third_party/WebKit/public/platform/WebInputEvent.h" |
32 #include "third_party/WebKit/public/platform/WebMouseEvent.h" | 33 #include "third_party/WebKit/public/platform/WebMouseEvent.h" |
33 #include "ui/gl/android/scoped_java_surface.h" | 34 #include "ui/gl/android/scoped_java_surface.h" |
34 #include "ui/gl/android/surface_texture.h" | 35 #include "ui/gl/android/surface_texture.h" |
35 #include "ui/gl/gl_bindings.h" | 36 #include "ui/gl/gl_bindings.h" |
36 #include "ui/gl/gl_context.h" | 37 #include "ui/gl/gl_context.h" |
37 #include "ui/gl/gl_surface.h" | 38 #include "ui/gl/gl_surface.h" |
38 #include "ui/gl/init/gl_factory.h" | 39 #include "ui/gl/init/gl_factory.h" |
39 | 40 |
40 namespace vr_shell { | 41 namespace vr_shell { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 result.m[0][2] = A; | 131 result.m[0][2] = A; |
131 result.m[1][1] = Y; | 132 result.m[1][1] = Y; |
132 result.m[1][2] = B; | 133 result.m[1][2] = B; |
133 result.m[2][2] = C; | 134 result.m[2][2] = C; |
134 result.m[2][3] = D; | 135 result.m[2][3] = D; |
135 result.m[3][2] = -1; | 136 result.m[3][2] = -1; |
136 | 137 |
137 return result; | 138 return result; |
138 } | 139 } |
139 | 140 |
140 std::unique_ptr<blink::WebMouseEvent> MakeMouseEvent(WebInputEvent::Type type, | 141 std::unique_ptr<blink::WebMouseEvent> MakeMouseEvent( |
141 double timestamp, | 142 blink::WebInputEvent::Type type, |
142 float x, | 143 double timestamp, |
143 float y) { | 144 const gfx::Point& loc) { |
144 std::unique_ptr<blink::WebMouseEvent> mouse_event(new blink::WebMouseEvent( | 145 std::unique_ptr<blink::WebMouseEvent> mouse_event(new blink::WebMouseEvent( |
145 type, blink::WebInputEvent::kNoModifiers, timestamp)); | 146 type, blink::WebInputEvent::kNoModifiers, timestamp)); |
146 mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kMouse; | 147 mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kMouse; |
147 mouse_event->SetPositionInWidget(x, y); | 148 mouse_event->SetPositionInWidget(loc.x(), loc.y()); |
148 mouse_event->click_count = 1; | 149 mouse_event->click_count = 1; |
149 | 150 |
150 return mouse_event; | 151 return mouse_event; |
151 } | 152 } |
152 | 153 |
153 enum class ViewerType { | 154 enum class ViewerType { |
154 UNKNOWN_TYPE = 0, | 155 UNKNOWN_TYPE = 0, |
155 CARDBOARD = 1, | 156 CARDBOARD = 1, |
156 DAYDREAM = 2, | 157 DAYDREAM = 2, |
157 VIEWER_TYPE_MAX, | 158 VIEWER_TYPE_MAX, |
(...skipping 18 matching lines...) Expand all Loading... | |
176 gvr::Rectf UVFromGfxRect(gfx::RectF rect) { | 177 gvr::Rectf UVFromGfxRect(gfx::RectF rect) { |
177 return {rect.x(), rect.x() + rect.width(), 1.0f - rect.bottom(), | 178 return {rect.x(), rect.x() + rect.width(), 1.0f - rect.bottom(), |
178 1.0f - rect.y()}; | 179 1.0f - rect.y()}; |
179 } | 180 } |
180 | 181 |
181 gfx::RectF GfxRectFromUV(gvr::Rectf rect) { | 182 gfx::RectF GfxRectFromUV(gvr::Rectf rect) { |
182 return gfx::RectF(rect.left, 1.0 - rect.top, rect.right - rect.left, | 183 return gfx::RectF(rect.left, 1.0 - rect.top, rect.right - rect.left, |
183 rect.top - rect.bottom); | 184 rect.top - rect.bottom); |
184 } | 185 } |
185 | 186 |
187 double NowSeconds() { | |
188 return (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); | |
189 } | |
190 | |
186 } // namespace | 191 } // namespace |
187 | 192 |
188 VrShellGl::VrShellGl(VrBrowserInterface* browser, | 193 VrShellGl::VrShellGl(VrBrowserInterface* browser, |
189 gvr_context* gvr_api, | 194 gvr_context* gvr_api, |
190 bool initially_web_vr, | 195 bool initially_web_vr, |
191 bool reprojected_rendering, | 196 bool reprojected_rendering, |
192 UiScene* scene) | 197 UiScene* scene) |
193 : web_vr_mode_(initially_web_vr), | 198 : web_vr_mode_(initially_web_vr), |
194 surfaceless_rendering_(reprojected_rendering), | 199 surfaceless_rendering_(reprojected_rendering), |
195 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 200 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
497 } | 502 } |
498 | 503 |
499 void VrShellGl::UpdateController(const gfx::Vector3dF& head_direction) { | 504 void VrShellGl::UpdateController(const gfx::Vector3dF& head_direction) { |
500 controller_->UpdateState(head_direction); | 505 controller_->UpdateState(head_direction); |
501 pointer_start_ = controller_->GetPointerStart(); | 506 pointer_start_ = controller_->GetPointerStart(); |
502 | 507 |
503 browser_->UpdateGamepadData(controller_->GetGamepadData()); | 508 browser_->UpdateGamepadData(controller_->GetGamepadData()); |
504 } | 509 } |
505 | 510 |
506 void VrShellGl::HandleControllerInput(const gfx::Vector3dF& head_direction) { | 511 void VrShellGl::HandleControllerInput(const gfx::Vector3dF& head_direction) { |
507 if (ShouldDrawWebVr()) { | 512 HandleWebVrCompatClick(); |
cjgrant
2017/05/10 20:16:25
s/Compat/Compatibility/
mthiesse
2017/05/10 21:09:08
Done.
| |
508 // Process screen touch events for Cardboard button compatibility. | |
509 // Also send tap events for controller "touchpad click" events. | |
510 if (touch_pending_ || | |
511 controller_->ButtonUpHappened( | |
512 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { | |
513 touch_pending_ = false; | |
514 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( | |
515 WebInputEvent::kGestureTapDown, WebInputEvent::kNoModifiers, | |
516 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); | |
517 gesture->source_device = blink::kWebGestureDeviceTouchpad; | |
518 gesture->x = 0; | |
519 gesture->y = 0; | |
520 SendGestureToContent(std::move(gesture)); | |
521 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; | |
522 } | |
523 } | |
524 | 513 |
525 gfx::Vector3dF ergo_neutral_pose; | 514 gfx::Vector3dF ergo_neutral_pose; |
526 if (!controller_->IsConnected()) { | 515 if (!controller_->IsConnected()) { |
527 // No controller detected, set up a gaze cursor that tracks the | 516 // No controller detected, set up a gaze cursor that tracks the |
528 // forward direction. | 517 // forward direction. |
529 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; | 518 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; |
530 controller_quat_ = GetRotationFromZAxis(head_direction); | 519 controller_quat_ = GetRotationFromZAxis(head_direction); |
531 } else { | 520 } else { |
532 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; | 521 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; |
533 controller_quat_ = controller_->Orientation(); | 522 controller_quat_ = controller_->Orientation(); |
534 } | 523 } |
535 | 524 |
536 vr::Mat4f mat; | 525 vr::Mat4f mat; |
537 QuatToMatrix(controller_quat_, &mat); | 526 QuatToMatrix(controller_quat_, &mat); |
538 gfx::Vector3dF controller_direction = | 527 gfx::Vector3dF controller_direction = |
539 vr::MatrixVectorMul(mat, ergo_neutral_pose); | 528 vr::MatrixVectorMul(mat, ergo_neutral_pose); |
540 | 529 |
541 HandleControllerAppButtonActivity(controller_direction); | 530 HandleControllerAppButtonActivity(controller_direction); |
542 | 531 |
543 if (ShouldDrawWebVr()) { | 532 if (ShouldDrawWebVr()) |
544 return; | 533 return; |
cjgrant
2017/05/10 20:16:26
Blank line after return?
mthiesse
2017/05/10 21:09:08
Done.
| |
545 } | 534 gfx::PointF target_local_point; |
546 | 535 gfx::Vector3dF eye_to_target; |
536 cursor_render_target_ = nullptr; | |
537 GetVisualTargetElement(controller_direction, eye_to_target, target_point_, | |
538 &cursor_render_target_, target_local_point); | |
539 | |
540 UiElement* target_element = nullptr; | |
541 if (input_locked_element_) { | |
542 gfx::Point3F plane_intersection_point; | |
543 float distance_to_plane; | |
544 GetTargetLocalPoint(eye_to_target, *input_locked_element_, | |
545 2 * scene_->GetBackgroundDistance(), target_local_point, | |
546 plane_intersection_point, distance_to_plane); | |
547 target_element = input_locked_element_; | |
548 } else if (!in_scroll_ && !in_click_) { | |
549 target_element = cursor_render_target_; | |
550 } | |
551 | |
552 // Handle input targeting on the content quad, ignoring any other elements. | |
553 // Content is treated specially to accomodate scrolling, flings, etc. | |
554 gfx::Point local_point_pixels; | |
555 if (target_element && (target_element->fill() == Fill::CONTENT)) { | |
556 gfx::RectF pixel_rect(0, 0, content_tex_css_width_, | |
557 content_tex_css_height_); | |
558 local_point_pixels.set_x(pixel_rect.x() + | |
559 pixel_rect.width() * target_local_point.x()); | |
560 local_point_pixels.set_y(pixel_rect.y() + | |
561 pixel_rect.height() * target_local_point.y()); | |
562 } | |
563 std::unique_ptr<GestureList> gesture_list_ptr = controller_->DetectGestures(); | |
564 GestureList& gesture_list = *gesture_list_ptr; | |
565 for (const std::unique_ptr<blink::WebGestureEvent>& gesture : gesture_list) { | |
566 gesture->x = local_point_pixels.x(); | |
567 gesture->y = local_point_pixels.y(); | |
568 } | |
569 SendFlingCancel(gesture_list); | |
570 // For simplicity, don't allow scrolling while clicking until we need to. | |
571 if (!in_click_) { | |
572 SendScrollEnd(gesture_list); | |
573 if (!SendScrollBegin(target_element, gesture_list)) { | |
574 SendScrollUpdate(gesture_list); | |
575 } | |
576 } | |
577 // If we're still scrolling, don't hover (and we can't be clicking, because | |
578 // click ends scroll). | |
579 if (in_scroll_) | |
580 return; | |
581 SendHoverLeave(target_element); | |
582 if (!SendHoverEnter(target_element, target_local_point, local_point_pixels)) { | |
583 SendHoverMove(target_local_point, local_point_pixels); | |
584 } | |
585 SendButtonDown(target_element, target_local_point); | |
586 if (!SendButtonUp(target_element, target_local_point)) | |
587 SendTap(target_element, target_local_point, local_point_pixels); | |
588 } | |
589 | |
590 void VrShellGl::HandleWebVrCompatClick() { | |
591 if (!ShouldDrawWebVr()) | |
592 return; | |
593 // Process screen touch events for Cardboard button compatibility. | |
594 // Also send tap events for controller "touchpad click" events. | |
595 if (touch_pending_ || | |
596 controller_->ButtonUpHappened(gvr::kControllerButtonClick)) { | |
597 touch_pending_ = false; | |
598 std::unique_ptr<blink::WebGestureEvent> gesture(new blink::WebGestureEvent( | |
599 blink::WebInputEvent::kGestureTapDown, | |
600 blink::WebInputEvent::kNoModifiers, NowSeconds())); | |
601 gesture->source_device = blink::kWebGestureDeviceTouchpad; | |
602 gesture->x = 0; | |
603 gesture->y = 0; | |
604 SendGestureToContent(std::move(gesture)); | |
605 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; | |
606 } | |
607 } | |
608 | |
609 void VrShellGl::SendFlingCancel(GestureList& gesture_list) { | |
610 if (!fling_target_) | |
611 return; | |
612 if (gesture_list.empty() || (gesture_list.front()->GetType() != | |
613 blink::WebInputEvent::kGestureFlingCancel)) | |
614 return; | |
615 // Scrolling currently only supported on content window. | |
616 DCHECK_EQ(fling_target_->fill(), Fill::CONTENT); | |
617 SendGestureToContent(std::move(gesture_list.front())); | |
618 gesture_list.erase(gesture_list.begin()); | |
619 } | |
620 | |
621 void VrShellGl::SendScrollEnd(GestureList& gesture_list) { | |
622 if (!in_scroll_) | |
623 return; | |
624 DCHECK_NE(input_locked_element_, nullptr); | |
625 if (controller_->ButtonDownHappened(gvr::kControllerButtonClick)) { | |
626 DCHECK_GT(gesture_list.size(), 0LU); | |
627 DCHECK_EQ(gesture_list.front()->GetType(), | |
628 blink::WebInputEvent::kGestureScrollEnd); | |
629 } | |
630 // Scrolling currently only supported on content window. | |
631 DCHECK_EQ(input_locked_element_->fill(), Fill::CONTENT); | |
632 if (gesture_list.empty() || (gesture_list.front()->GetType() != | |
633 blink::WebInputEvent::kGestureScrollEnd)) | |
634 return; | |
635 DCHECK_LE(gesture_list.size(), 2LU); | |
636 SendGestureToContent(std::move(gesture_list.front())); | |
637 gesture_list.erase(gesture_list.begin()); | |
638 if (!gesture_list.empty()) { | |
639 DCHECK_EQ(gesture_list.front()->GetType(), | |
640 blink::WebInputEvent::kGestureFlingStart); | |
641 SendGestureToContent(std::move(gesture_list.front())); | |
642 fling_target_ = input_locked_element_; | |
643 gesture_list.erase(gesture_list.begin()); | |
644 } | |
645 input_locked_element_ = nullptr; | |
646 in_scroll_ = false; | |
647 } | |
648 | |
649 bool VrShellGl::SendScrollBegin(UiElement* target, GestureList& gesture_list) { | |
650 if (in_scroll_ || !target) | |
651 return false; | |
652 // Scrolling currently only supported on content window. | |
653 if (target->fill() != Fill::CONTENT) | |
654 return false; | |
655 if (gesture_list.empty() || (gesture_list.front()->GetType() != | |
656 blink::WebInputEvent::kGestureScrollBegin)) | |
657 return false; | |
658 input_locked_element_ = target; | |
659 in_scroll_ = true; | |
660 | |
661 SendGestureToContent(std::move(gesture_list.front())); | |
662 gesture_list.erase(gesture_list.begin()); | |
663 return true; | |
664 } | |
665 | |
666 void VrShellGl::SendScrollUpdate(GestureList& gesture_list) { | |
667 if (!in_scroll_) | |
668 return; | |
669 DCHECK(input_locked_element_); | |
670 if (gesture_list.empty() || (gesture_list.front()->GetType() != | |
671 blink::WebInputEvent::kGestureScrollUpdate)) | |
672 return; | |
673 // Scrolling currently only supported on content window. | |
674 DCHECK_EQ(input_locked_element_->fill(), Fill::CONTENT); | |
675 SendGestureToContent(std::move(gesture_list.front())); | |
676 gesture_list.erase(gesture_list.begin()); | |
677 } | |
678 | |
679 void VrShellGl::SendHoverLeave(UiElement* target) { | |
680 if (!hover_target_ || (target == hover_target_)) | |
681 return; | |
682 if (hover_target_->fill() == Fill::CONTENT) { | |
683 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseLeave, | |
684 NowSeconds(), gfx::Point())); | |
685 } else { | |
686 hover_target_->OnHoverLeave(); | |
687 } | |
688 hover_target_ = nullptr; | |
689 } | |
690 | |
691 bool VrShellGl::SendHoverEnter(UiElement* target, | |
692 const gfx::PointF& target_point, | |
693 const gfx::Point& local_point_pixels) { | |
694 if (!target || target == hover_target_) | |
695 return false; | |
696 if (target->fill() == Fill::CONTENT) { | |
697 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseEnter, | |
698 NowSeconds(), local_point_pixels)); | |
699 } else { | |
700 target->OnHoverEnter(target_point); | |
701 } | |
702 hover_target_ = target; | |
703 return true; | |
704 } | |
705 | |
706 void VrShellGl::SendHoverMove(const gfx::PointF& target_point, | |
707 const gfx::Point& local_point_pixels) { | |
708 if (!hover_target_) | |
709 return; | |
710 if (hover_target_->fill() == Fill::CONTENT) { | |
711 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseMove, | |
712 NowSeconds(), local_point_pixels)); | |
713 } else { | |
714 hover_target_->OnMove(target_point); | |
715 } | |
716 } | |
717 | |
718 void VrShellGl::SendButtonDown(UiElement* target, | |
719 const gfx::PointF& target_point) { | |
720 if (in_click_) | |
721 return; | |
722 if (!controller_->ButtonDownHappened(gvr::kControllerButtonClick)) | |
cjgrant
2017/05/10 20:16:26
Isn't it more intuitive to not call SendButtonDown
mthiesse
2017/05/10 21:09:08
So this is a stylistic choice. I decided to avoid
| |
723 return; | |
724 input_locked_element_ = target; | |
725 in_click_ = true; | |
726 // We don't support down/up for content yet. | |
727 if (!target || target->fill() == Fill::CONTENT) | |
728 return; | |
729 target->OnButtonDown(target_point); | |
730 } | |
731 | |
732 bool VrShellGl::SendButtonUp(UiElement* target, | |
733 const gfx::PointF& target_point) { | |
734 if (!in_click_) | |
735 return false; | |
736 if (!controller_->ButtonUpHappened(gvr::kControllerButtonClick)) | |
737 return false; | |
738 DCHECK(input_locked_element_ == target); | |
739 input_locked_element_ = nullptr; | |
740 in_click_ = false; | |
741 // We don't support down/up for content yet. | |
742 if (target->fill() == Fill::CONTENT) | |
743 return false; | |
744 target->OnButtonUp(target_point); | |
745 return true; | |
746 } | |
747 | |
748 void VrShellGl::SendTap(UiElement* target, | |
749 const gfx::PointF& target_point, | |
750 const gfx::Point& local_point_pixels) { | |
751 if (!target) | |
752 return; | |
753 if (controller_->ButtonUpHappened(gvr::kControllerButtonClick) && | |
754 target->fill() == Fill::CONTENT) | |
755 touch_pending_ = true; | |
756 if (!touch_pending_) | |
757 return; | |
758 touch_pending_ = false; | |
759 if (target->fill() == Fill::CONTENT) { | |
760 auto gesture = base::MakeUnique<blink::WebGestureEvent>( | |
761 blink::WebInputEvent::kGestureTapDown, | |
762 blink::WebInputEvent::kNoModifiers, NowSeconds()); | |
763 gesture->source_device = blink::kWebGestureDeviceTouchpad; | |
764 gesture->x = local_point_pixels.x(); | |
765 gesture->y = local_point_pixels.y(); | |
766 SendGestureToContent(std::move(gesture)); | |
767 } else { | |
768 target->OnButtonDown(target_point); | |
769 target->OnButtonUp(target_point); | |
770 } | |
771 } | |
772 | |
773 void VrShellGl::GetVisualTargetElement( | |
774 const gfx::Vector3dF& controller_direction, | |
775 gfx::Vector3dF& eye_to_target, | |
776 gfx::Point3F& target_point, | |
777 UiElement** target_element, | |
778 gfx::PointF& target_local_point) const { | |
547 // If we place the reticle based on elements intersecting the controller beam, | 779 // If we place the reticle based on elements intersecting the controller beam, |
548 // we can end up with the reticle hiding behind elements, or jumping laterally | 780 // we can end up with the reticle hiding behind elements, or jumping laterally |
549 // in the field of view. This is physically correct, but hard to use. For | 781 // in the field of view. This is physically correct, but hard to use. For |
550 // usability, do the following instead: | 782 // usability, do the following instead: |
551 // | 783 // |
552 // - Project the controller laser onto a distance-limiting sphere. | 784 // - Project the controller laser onto a distance-limiting sphere. |
553 // - Create a vector between the eyes and the outer surface point. | 785 // - Create a vector between the eyes and the outer surface point. |
554 // - If any UI elements intersect this vector, and is within the bounding | 786 // - If any UI elements intersect this vector, and is within the bounding |
555 // sphere, choose the closest to the eyes, and place the reticle at the | 787 // sphere, choose the closest to the eyes, and place the reticle at the |
556 // intersection point. | 788 // intersection point. |
557 | 789 |
558 // Compute the distance from the eyes to the distance limiting sphere. Note | 790 // Compute the distance from the eyes to the distance limiting sphere. Note |
559 // that the sphere is centered at the controller, rather than the eye, for | 791 // that the sphere is centered at the controller, rather than the eye, for |
560 // simplicity. | 792 // simplicity. |
561 float distance = scene_->GetBackgroundDistance(); | 793 float distance = scene_->GetBackgroundDistance(); |
562 target_point_ = | 794 target_point = |
563 vr::GetRayPoint(pointer_start_, controller_direction, distance); | 795 vr::GetRayPoint(pointer_start_, controller_direction, distance); |
564 gfx::Vector3dF eye_to_target = target_point_ - kOrigin; | 796 eye_to_target = target_point - kOrigin; |
565 vr::NormalizeVector(&eye_to_target); | 797 vr::NormalizeVector(&eye_to_target); |
566 | 798 |
567 // Determine which UI element (if any) intersects the line between the eyes | 799 // Determine which UI element (if any) intersects the line between the eyes |
568 // and the controller target position. | 800 // and the controller target position. |
569 float closest_element_distance = (target_point_ - kOrigin).Length(); | 801 float closest_element_distance = (target_point - kOrigin).Length(); |
570 previous_target_element_ = target_element_; | |
571 target_element_ = nullptr; | |
572 float target_x; | |
573 float target_y; | |
574 | 802 |
575 for (auto& plane : scene_->GetUiElements()) { | 803 for (auto& element : scene_->GetUiElements()) { |
576 if (!plane->IsHitTestable()) | 804 if (!element->IsHitTestable()) |
805 continue; | |
806 gfx::PointF local_point; | |
807 gfx::Point3F plane_intersection_point; | |
808 float distance_to_plane; | |
809 if (!GetTargetLocalPoint(eye_to_target, *element.get(), | |
cjgrant
2017/05/10 20:16:26
So to be totally clear, the idea of having an elem
mthiesse
2017/05/10 21:09:08
yes.
| |
810 closest_element_distance, local_point, | |
811 plane_intersection_point, distance_to_plane)) | |
577 continue; | 812 continue; |
578 | 813 |
579 float distance_to_plane; | 814 if (local_point.x() < 0.0f || local_point.x() >= 1.0f || |
580 if (!plane->GetRayDistance(kOrigin, eye_to_target, &distance_to_plane)) | 815 local_point.y() < 0.0f || local_point.y() >= 1.0f) |
581 continue; | |
582 | |
583 if (distance_to_plane < 0 || distance_to_plane >= closest_element_distance) | |
584 continue; | |
585 | |
586 gfx::Point3F plane_intersection_point = | |
587 vr::GetRayPoint(kOrigin, eye_to_target, distance_to_plane); | |
588 gfx::PointF unit_xy_point = | |
589 plane->GetUnitRectangleCoordinates(plane_intersection_point); | |
590 | |
591 float x = 0.5f + unit_xy_point.x(); | |
592 float y = 0.5f - unit_xy_point.y(); | |
593 if (x < 0.0f || x >= 1.0f || y < 0.0f || y >= 1.0f) | |
594 continue; | 816 continue; |
595 | 817 |
596 closest_element_distance = distance_to_plane; | 818 closest_element_distance = distance_to_plane; |
597 target_point_ = plane_intersection_point; | 819 target_point = plane_intersection_point; |
598 target_element_ = plane.get(); | 820 *target_element = element.get(); |
599 target_x = x; | 821 target_local_point = local_point; |
600 target_y = y; | |
601 } | 822 } |
823 } | |
602 | 824 |
603 // Handle input targeting on the content quad, ignoring any other elements. | 825 bool VrShellGl::GetTargetLocalPoint(const gfx::Vector3dF& eye_to_target, |
604 // Content is treated specially to accomodate scrolling, flings, etc. | 826 const UiElement& element, |
605 InputTarget input_target = InputTarget::NONE; | 827 float max_distance_to_plane, |
606 int pixel_x = 0; | 828 gfx::PointF& target_local_point, |
607 int pixel_y = 0; | 829 gfx::Point3F& target_point, |
608 if (target_element_ != nullptr && target_element_->fill() == Fill::CONTENT) { | 830 float& distance_to_plane) const { |
609 input_target = InputTarget::CONTENT; | 831 if (!element.GetRayDistance(kOrigin, eye_to_target, &distance_to_plane)) |
610 gfx::RectF pixel_rect(0, 0, content_tex_css_width_, | 832 return false; |
611 content_tex_css_height_); | |
612 pixel_x = pixel_rect.x() + pixel_rect.width() * target_x; | |
613 pixel_y = pixel_rect.y() + pixel_rect.height() * target_y; | |
614 } | |
615 SendInputToContent(input_target, pixel_x, pixel_y); | |
616 | 833 |
617 // Handle input targeting on all non-content elements. | 834 if (distance_to_plane < 0 || distance_to_plane >= max_distance_to_plane) |
618 SendInputToUiElements(target_element_); | 835 return false; |
836 | |
837 target_point = vr::GetRayPoint(kOrigin, eye_to_target, distance_to_plane); | |
838 gfx::PointF unit_xy_point = element.GetUnitRectangleCoordinates(target_point); | |
839 | |
840 target_local_point.set_x(0.5f + unit_xy_point.x()); | |
841 target_local_point.set_y(0.5f - unit_xy_point.y()); | |
842 return true; | |
619 } | 843 } |
620 | 844 |
621 void VrShellGl::HandleControllerAppButtonActivity( | 845 void VrShellGl::HandleControllerAppButtonActivity( |
622 const gfx::Vector3dF& controller_direction) { | 846 const gfx::Vector3dF& controller_direction) { |
623 // Note that button up/down state is transient, so ButtonDownHappened only | 847 // Note that button up/down state is transient, so ButtonDownHappened only |
624 // returns true for a single frame (and we're guaranteed not to miss it). | 848 // returns true for a single frame (and we're guaranteed not to miss it). |
625 if (controller_->ButtonDownHappened( | 849 if (controller_->ButtonDownHappened( |
626 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { | 850 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { |
627 controller_start_direction_ = controller_direction; | 851 controller_start_direction_ = controller_direction; |
628 } | 852 } |
(...skipping 12 matching lines...) Expand all Loading... | |
641 direction = | 865 direction = |
642 gesture_xz_angle < 0 ? UiInterface::LEFT : UiInterface::RIGHT; | 866 gesture_xz_angle < 0 ? UiInterface::LEFT : UiInterface::RIGHT; |
643 browser_->AppButtonGesturePerformed(direction); | 867 browser_->AppButtonGesturePerformed(direction); |
644 } | 868 } |
645 } | 869 } |
646 if (direction == UiInterface::NONE) | 870 if (direction == UiInterface::NONE) |
647 browser_->AppButtonClicked(); | 871 browser_->AppButtonClicked(); |
648 } | 872 } |
649 } | 873 } |
650 | 874 |
651 void VrShellGl::SendInputToContent(InputTarget input_target, | |
652 int pixel_x, | |
653 int pixel_y) { | |
654 std::vector<std::unique_ptr<WebGestureEvent>> gesture_list = | |
655 controller_->DetectGestures(); | |
656 double timestamp = gesture_list.front()->TimeStampSeconds(); | |
657 | |
658 if (touch_pending_) { | |
659 touch_pending_ = false; | |
660 std::unique_ptr<WebGestureEvent> event( | |
661 new WebGestureEvent(WebInputEvent::kGestureTapDown, | |
662 WebInputEvent::kNoModifiers, timestamp)); | |
663 event->source_device = blink::kWebGestureDeviceTouchpad; | |
664 event->x = pixel_x; | |
665 event->y = pixel_y; | |
666 gesture_list.push_back(std::move(event)); | |
667 } | |
668 | |
669 for (auto& gesture : gesture_list) { | |
670 gesture->x = pixel_x; | |
671 gesture->y = pixel_y; | |
672 auto movableGesture = base::MakeUnique<WebGestureEvent>(*gesture); | |
673 | |
674 switch (gesture->GetType()) { | |
675 // Once the user starts scrolling send all the scroll events to this | |
676 // element until the scrolling stops. | |
677 case WebInputEvent::kGestureScrollBegin: | |
678 current_scroll_target_ = input_target; | |
679 if (current_scroll_target_ != InputTarget::NONE) { | |
680 SendGestureToContent(std::move(movableGesture)); | |
681 } | |
682 break; | |
683 case WebInputEvent::kGestureScrollEnd: | |
684 if (current_scroll_target_ != InputTarget::NONE) { | |
685 SendGestureToContent(std::move(movableGesture)); | |
686 } | |
687 current_fling_target_ = current_scroll_target_; | |
688 current_scroll_target_ = InputTarget::NONE; | |
689 break; | |
690 case WebInputEvent::kGestureScrollUpdate: | |
691 if (current_scroll_target_ != InputTarget::NONE) { | |
692 SendGestureToContent(std::move(movableGesture)); | |
693 } | |
694 break; | |
695 case WebInputEvent::kGestureFlingStart: | |
696 if (current_fling_target_ != InputTarget::NONE) { | |
697 SendGestureToContent(std::move(movableGesture)); | |
698 } | |
699 current_fling_target_ = InputTarget::NONE; | |
700 break; | |
701 case WebInputEvent::kGestureFlingCancel: | |
702 current_fling_target_ = InputTarget::NONE; | |
703 if (input_target != InputTarget::NONE) { | |
704 SendGestureToContent(std::move(movableGesture)); | |
705 } | |
706 break; | |
707 case WebInputEvent::kGestureTapDown: | |
708 current_fling_target_ = InputTarget::NONE; | |
709 if (input_target != InputTarget::NONE) { | |
710 SendGestureToContent(std::move(movableGesture)); | |
711 } | |
712 break; | |
713 case WebInputEvent::kUndefined: | |
714 break; | |
715 default: | |
716 NOTREACHED(); | |
717 } | |
718 } | |
719 | |
720 // Hover support | |
721 bool new_target = input_target != current_input_target_; | |
722 if (new_target && current_input_target_ != InputTarget::NONE) { | |
723 // Send a move event indicating that the pointer moved off of an element. | |
724 SendGestureToContent( | |
725 MakeMouseEvent(WebInputEvent::kMouseLeave, timestamp, 0, 0)); | |
726 } | |
727 current_input_target_ = input_target; | |
728 if (current_input_target_ != InputTarget::NONE) { | |
729 WebInputEvent::Type type = | |
730 new_target ? WebInputEvent::kMouseEnter : WebInputEvent::kMouseMove; | |
731 SendGestureToContent(MakeMouseEvent(type, timestamp, pixel_x, pixel_y)); | |
732 } | |
733 } | |
734 | |
735 void VrShellGl::SendInputToUiElements(UiElement* target_element) { | |
736 if (target_element != previous_target_element_) { | |
737 if (previous_target_element_ && | |
738 previous_target_element_->fill() != Fill::CONTENT) { | |
739 task_runner_->PostTask( | |
740 FROM_HERE, base::Bind(&UiElement::OnHoverLeave, | |
741 base::Unretained(previous_target_element_))); | |
742 } | |
743 if (target_element && target_element->fill() != Fill::CONTENT) { | |
744 task_runner_->PostTask(FROM_HERE, | |
745 base::Bind(&UiElement::OnHoverEnter, | |
746 base::Unretained(target_element))); | |
747 } | |
748 click_target_element_ = nullptr; | |
749 } | |
750 if (target_element && target_element->fill() != Fill::CONTENT) { | |
751 if (controller_->ButtonDownHappened( | |
752 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { | |
753 task_runner_->PostTask(FROM_HERE, | |
754 base::Bind(&UiElement::OnButtonDown, | |
755 base::Unretained(target_element))); | |
756 click_target_element_ = target_element; | |
757 } | |
758 if (controller_->ButtonUpHappened( | |
759 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { | |
760 if (click_target_element_ == target_element) { | |
761 task_runner_->PostTask(FROM_HERE, | |
762 base::Bind(&UiElement::OnButtonUp, | |
763 base::Unretained(target_element))); | |
764 } | |
765 click_target_element_ = nullptr; | |
766 } | |
767 } | |
768 } | |
769 | |
770 void VrShellGl::SendGestureToContent( | 875 void VrShellGl::SendGestureToContent( |
771 std::unique_ptr<blink::WebInputEvent> event) { | 876 std::unique_ptr<blink::WebInputEvent> event) { |
772 browser_->ProcessContentGesture(std::move(event)); | 877 browser_->ProcessContentGesture(std::move(event)); |
773 } | 878 } |
774 | 879 |
775 void VrShellGl::DrawFrame(int16_t frame_index) { | 880 void VrShellGl::DrawFrame(int16_t frame_index) { |
776 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); | 881 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); |
777 | 882 |
778 base::TimeTicks current_time = base::TimeTicks::Now(); | 883 base::TimeTicks current_time = base::TimeTicks::Now(); |
779 | 884 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1034 default: | 1139 default: |
1035 break; | 1140 break; |
1036 } | 1141 } |
1037 } | 1142 } |
1038 vr_shell_renderer_->Flush(); | 1143 vr_shell_renderer_->Flush(); |
1039 } | 1144 } |
1040 | 1145 |
1041 std::vector<const UiElement*> VrShellGl::GetElementsInDrawOrder( | 1146 std::vector<const UiElement*> VrShellGl::GetElementsInDrawOrder( |
1042 const vr::Mat4f& view_matrix, | 1147 const vr::Mat4f& view_matrix, |
1043 const std::vector<const UiElement*>& elements) { | 1148 const std::vector<const UiElement*>& elements) { |
1044 typedef std::pair<float, const UiElement*> DistanceElementPair; | 1149 std::vector<const UiElement*> sorted_elements = elements; |
1045 std::vector<DistanceElementPair> zOrderedElementPairs; | |
1046 zOrderedElementPairs.reserve(elements.size()); | |
1047 | |
1048 for (const auto* element : elements) { | |
1049 // Distance is the abs(z) value in view space. | |
1050 gfx::Vector3dF element_position = | |
1051 vr::GetTranslation(element->TransformMatrix()); | |
1052 | |
1053 float distance = | |
1054 std::fabs(vr::MatrixVectorMul(view_matrix, element_position).z()); | |
1055 zOrderedElementPairs.push_back(std::make_pair(distance, element)); | |
1056 } | |
1057 | 1150 |
1058 // Sort elements primarily based on their draw phase (lower draw phase first) | 1151 // Sort elements primarily based on their draw phase (lower draw phase first) |
1059 // and secondarily based on their distance (larger distance first). | 1152 // and secondarily based on their distance (larger z-axis first). |
cjgrant
2017/05/10 20:16:26
"...based on their Z-axis distance..." maybe?
mthiesse
2017/05/10 21:09:08
Done.
mthiesse
2017/05/10 21:09:08
Didn't mean to include these changes in this CL. W
| |
1060 std::sort( | 1153 // TODO(mthiesse): This will not work well for elements not directly in front |
1061 zOrderedElementPairs.begin(), zOrderedElementPairs.end(), | 1154 // of the user, but works well enough for our initial release, and provides a |
1062 [](const DistanceElementPair& first, const DistanceElementPair& second) { | 1155 // consistent ordering that we can easily design around. |
1063 if (first.second->draw_phase() != second.second->draw_phase()) { | 1156 std::sort(sorted_elements.begin(), sorted_elements.end(), |
1064 return first.second->draw_phase() < second.second->draw_phase(); | 1157 [](const UiElement* first, const UiElement* second) { |
1065 } else { | 1158 if (first->draw_phase() != second->draw_phase()) { |
1066 return first.first > second.first; | 1159 return first->draw_phase() < second->draw_phase(); |
1067 } | 1160 } else { |
1068 }); | 1161 return first->translation().z() < second->translation().z(); |
1162 } | |
1163 }); | |
1069 | 1164 |
1070 std::vector<const UiElement*> zOrderedElements; | 1165 return sorted_elements; |
1071 zOrderedElements.reserve(elements.size()); | |
1072 for (auto distanceElementPair : zOrderedElementPairs) { | |
1073 zOrderedElements.push_back(distanceElementPair.second); | |
1074 } | |
1075 return zOrderedElements; | |
1076 } | 1166 } |
1077 | 1167 |
1078 void VrShellGl::DrawCursor(const vr::Mat4f& render_matrix) { | 1168 void VrShellGl::DrawCursor(const vr::Mat4f& render_matrix) { |
1079 vr::Mat4f mat; | 1169 vr::Mat4f mat; |
1080 vr::SetIdentityM(&mat); | 1170 vr::SetIdentityM(&mat); |
1081 | 1171 |
1082 // Draw the reticle. | 1172 // Draw the reticle. |
1083 | 1173 |
1084 // Scale the pointer to have a fixed FOV size at any distance. | 1174 // Scale the pointer to have a fixed FOV size at any distance. |
1085 const float eye_to_target = | 1175 const float eye_to_target = |
1086 std::sqrt(target_point_.SquaredDistanceTo(kOrigin)); | 1176 std::sqrt(target_point_.SquaredDistanceTo(kOrigin)); |
1087 vr::ScaleM( | 1177 vr::ScaleM( |
1088 mat, | 1178 mat, |
1089 {kReticleWidth * eye_to_target, kReticleHeight * eye_to_target, 1.0f}, | 1179 {kReticleWidth * eye_to_target, kReticleHeight * eye_to_target, 1.0f}, |
1090 &mat); | 1180 &mat); |
1091 | 1181 |
1092 vr::Quatf rotation; | 1182 vr::Quatf rotation; |
1093 if (target_element_ != nullptr) { | 1183 if (cursor_render_target_ != nullptr) { |
1094 // Make the reticle planar to the element it's hitting. | 1184 // Make the reticle planar to the element it's hitting. |
1095 rotation = GetRotationFromZAxis(target_element_->GetNormal()); | 1185 rotation = GetRotationFromZAxis(cursor_render_target_->GetNormal()); |
1096 } else { | 1186 } else { |
1097 // Rotate the cursor to directly face the eyes. | 1187 // Rotate the cursor to directly face the eyes. |
1098 rotation = GetRotationFromZAxis(target_point_ - kOrigin); | 1188 rotation = GetRotationFromZAxis(target_point_ - kOrigin); |
1099 } | 1189 } |
1100 vr::Mat4f rotation_mat; | 1190 vr::Mat4f rotation_mat; |
1101 vr::QuatToMatrix(rotation, &rotation_mat); | 1191 vr::QuatToMatrix(rotation, &rotation_mat); |
1102 vr::MatrixMul(rotation_mat, mat, &mat); | 1192 vr::MatrixMul(rotation_mat, mat, &mat); |
1103 | 1193 |
1104 gfx::Point3F target_point = ScalePoint(target_point_, kReticleOffset); | 1194 gfx::Point3F target_point = ScalePoint(target_point_, kReticleOffset); |
1105 // Place the pointer slightly in front of the plane intersection point. | 1195 // Place the pointer slightly in front of the plane intersection point. |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1337 // This assumes that the initial webvr_surface_size_ was set to the | 1427 // This assumes that the initial webvr_surface_size_ was set to the |
1338 // appropriate recommended render resolution as the default size during | 1428 // appropriate recommended render resolution as the default size during |
1339 // InitializeGl. Revisit if the initialization order changes. | 1429 // InitializeGl. Revisit if the initialization order changes. |
1340 device::mojom::VRDisplayInfoPtr info = | 1430 device::mojom::VRDisplayInfoPtr info = |
1341 device::GvrDelegate::CreateVRDisplayInfo(gvr_api_.get(), | 1431 device::GvrDelegate::CreateVRDisplayInfo(gvr_api_.get(), |
1342 webvr_surface_size_, device_id); | 1432 webvr_surface_size_, device_id); |
1343 browser_->RunVRDisplayInfoCallback(callback, &info); | 1433 browser_->RunVRDisplayInfoCallback(callback, &info); |
1344 } | 1434 } |
1345 | 1435 |
1346 } // namespace vr_shell | 1436 } // namespace vr_shell |
OLD | NEW |