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

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

Issue 2350253004: Controller support for VrShell (Closed)
Patch Set: Clean up Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/android/vr_shell/vr_controller.h"
6
7 #include <android/log.h>
8
9 #include <cmath>
10
11 #include "third_party/WebKit/public/web/WebInputEvent.h"
12
13 using blink::WebInputEvent;
14
15 namespace vr_shell {
16
17 namespace {
18
19 const GestureScroll kDefaultGestureScroll = {{0, 0}, 0, {0, 0}};
20 const GestureButtonsChange kDefaultGestureButtonsChange = {{0, 0}, 0, 0};
21 const GestureAngularMove kDefaultGestureAngularMove = {{0, 0, 0}, 0};
22
23 constexpr float kDisplacementScaleFactor = 800.0f;
24
25 // A slop represents a small rectangular region around the first touch point of
26 // a gesture.
27 // If the user does not move outside of the slop, no gesture is detected.
28 // Gestures start to be detected when the user moves outside of the slop.
29 // Vertical distance from the border to the center of slop.
30 constexpr float kSlopVertical = 0.165f;
31
32 // Horizontal distance from the border to the center of slop.
33 constexpr float kSlopHorizontal = 0.125f;
34
35 // Minimum distance needed in at least one direction to call two vectors
36 // not equal.
37 constexpr float kDelta = 1.0e-7f;
38
39 class Vector {
40 public:
41 static inline void ClampTouchpadPosition(gvr::Vec2f* position) {
42 position->x = std::min(std::max(0.0f, position->x), 1.0f);
43 position->y = std::min(std::max(0.0f, position->y), 1.0f);
44 }
45
46 static inline void VectSetZero(gvr::Vec2f* v) {
47 v->x = 0;
48 v->y = 0;
49 }
50
51 static inline gvr::Vec2f VectSubtract(gvr::Vec2f v1, gvr::Vec2f v2) {
52 gvr::Vec2f result;
53 result.x = v1.x - v2.x;
54 result.y = v1.y - v2.y;
55 return result;
56 }
57
58 static inline bool VectEqual(const gvr::Vec2f v1, const gvr::Vec2f v2) {
59 return (std::abs(v1.x - v2.x) < kDelta) && (std::abs(v1.y - v2.y) < kDelta);
60 }
61 }; // Vector
62
63 } // namespace
64
65 VrController::VrController(gvr_context* vr_context) {
66 Initialize(vr_context);
67 Reset();
68 }
69
70 VrController::~VrController() {}
71
72 void VrController::OnResume() {
73 if (controller_api_)
74 controller_api_->Resume();
75 }
76
77 void VrController::OnPause() {
78 if (controller_api_)
79 controller_api_->Pause();
80 }
81
82 bool VrController::IsTouching() {
83 return controller_state_.IsTouching();
84 }
85
86 float VrController::TouchPosX() {
87 return controller_state_.GetTouchPos().x;
88 }
89
90 float VrController::TouchPosY() {
91 return controller_state_.GetTouchPos().y;
92 }
93
94 const gvr::Quatf VrController::Orientation() {
95 return controller_state_.GetOrientation();
96 }
97
98 bool VrController::IsTouchDown() {
99 return controller_state_.GetTouchDown();
100 }
101
102 bool VrController::IsTouchUp() {
103 return controller_state_.GetTouchUp();
104 }
105
106 bool VrController::IsButtonDown(const int32_t button) {
107 return controller_state_.GetButtonDown(button);
108 }
109
110 bool VrController::IsButtonUp(const int32_t button) {
111 return controller_state_.GetButtonUp(button);
112 }
113
114 bool VrController::IsConnected() {
115 return controller_state_.GetConnectionState() == gvr::kControllerConnected;
116 }
117
118 void VrController::UpdateState() {
119 const int32_t old_status = controller_state_.GetApiStatus();
120 const int32_t old_connection_state = controller_state_.GetConnectionState();
121 // Read current controller state.
122 controller_state_.Update(*controller_api_);
123 // Print new API status and connection state, if they changed.
124 if (controller_state_.GetApiStatus() != old_status ||
125 controller_state_.GetConnectionState() != old_connection_state) {
126 VLOG(1) << "Controller Connection status: "
127 << gvr_controller_connection_state_to_string(
128 controller_state_.GetConnectionState());
129 }
130 }
131
132 void VrController::Update(bool touch_up,
133 bool touch_down,
134 bool is_touching,
135 const gvr::Vec2f position,
136 int64_t timestamp) {
137 CHECK(touch_info_ != nullptr) << "touch_info_ not initialized properly.";
138 touch_info_->touch_up = touch_up;
139 touch_info_->touch_down = touch_down;
140 touch_info_->is_touching = is_touching;
141 touch_info_->touch_point.position = position;
142 Vector::ClampTouchpadPosition(&touch_info_->touch_point.position);
143 touch_info_->touch_point.timestamp = timestamp;
144
145 UpdateGestureFromTouchInfo();
146 }
147
148 void VrController::Initialize(gvr_context* gvr_context) {
149 CHECK(gvr_context != nullptr) << "invalid gvr_context";
150 controller_api_.reset(new gvr::ControllerApi);
151 int32_t options = gvr::ControllerApi::DefaultOptions();
152
153 // Enable non-default options, if you need them:
154 // options |= GVR_CONTROLLER_ENABLE_GYRO;
155 CHECK(controller_api_->Init(options, gvr_context));
156 controller_api_->Resume();
157 }
158
159 VrGesture VrController::DetectGesture() {
160 if (controller_state_.GetConnectionState() == gvr::kControllerConnected) {
161 gvr::Vec2f position;
162 position.x = TouchPosX();
163 position.y = TouchPosY();
164 Update(IsTouchUp(), IsTouchDown(), IsTouching(), position,
165 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos);
166 if (GetGestureListSize() > 0 &&
167 (GetGesturePtr(0)->type == WebInputEvent::GestureScrollBegin ||
168 GetGesturePtr(0)->type == WebInputEvent::GestureScrollUpdate ||
169 GetGesturePtr(0)->type == WebInputEvent::GestureScrollEnd)) {
170 switch (GetGesturePtr(0)->type) {
171 case WebInputEvent::GestureScrollBegin:
172 return VrGesture(
173 kDefaultGestureScroll,
174 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
175 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
176 GetGesturePtr(0)->displacement.x * kDisplacementScaleFactor,
177 GetGesturePtr(0)->displacement.y * kDisplacementScaleFactor,
178 WebInputEvent::GestureScrollBegin, Orientation());
179 case WebInputEvent::GestureScrollUpdate:
180 return VrGesture(
181 kDefaultGestureScroll,
182 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
183 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
184 GetGesturePtr(0)->displacement.x * kDisplacementScaleFactor,
185 GetGesturePtr(0)->displacement.y * kDisplacementScaleFactor,
186 WebInputEvent::GestureScrollUpdate, Orientation());
187 case WebInputEvent::GestureScrollEnd:
188 return VrGesture(
189 kDefaultGestureScroll,
190 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
191 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos, 0, 0,
192 WebInputEvent::GestureScrollEnd, Orientation());
193 default:
194 LOG(ERROR) << "Unknown Gesture";
195 return VrGesture();
196 }
197 }
198
199 if (IsButtonDown(gvr::kControllerButtonClick)) {
200 return VrGesture(
201 kDefaultGestureButtonsChange,
202 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
203 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos, 1, 0,
204 Orientation());
205 }
206 return VrGesture(kDefaultGestureAngularMove,
207 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
208 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
209 Orientation());
210 }
211 return VrGesture();
212 }
213
214 void VrController::UpdateGestureFromTouchInfo() {
215 // Clear the gesture list.
216 gesture_list_.clear();
217
218 switch (state_) {
219 // User has not put finger on touch pad.
220 case WAITING:
221 HandleWaitingState();
222 break;
223 // User has not started a gesture (by moving out of slop).
224 case TOUCHING:
225 HandleDetectingState();
226 break;
227 // User is scrolling on touchpad
228 case SCROLLING:
229 HandleScrollingState();
230 break;
231 default:
232 LOG(ERROR) << "Wrong gesture detector state: " << state_;
233 break;
234 }
235 }
236
237 const VrGesture* VrController::GetGesturePtr(const size_t index) {
238 CHECK(index < gesture_list_.size()) << "The gesture index exceeds the"
239 "size of gesture list.";
240 return const_cast<VrGesture*>(&gesture_list_[index]);
241 }
242
243 void VrController::Update(const gvr_controller_state* controller_state) {
244 // Update touch information.
245 CHECK(touch_info_ != nullptr) << "touch_info_ not initialized properly.";
246 touch_info_->touch_up = gvr_controller_state_get_touch_up(controller_state);
247 touch_info_->touch_down =
248 gvr_controller_state_get_touch_down(controller_state);
249 touch_info_->is_touching = gvr_controller_state_is_touching(controller_state);
250 touch_info_->touch_point.position.x =
251 gvr_controller_state_get_touch_pos(controller_state).x;
252 touch_info_->touch_point.position.y =
253 gvr_controller_state_get_touch_pos(controller_state).y;
254 Vector::ClampTouchpadPosition(&(touch_info_->touch_point.position));
255 touch_info_->touch_point.timestamp =
256 gvr_controller_state_get_last_touch_timestamp(controller_state);
257
258 UpdateGestureFromTouchInfo();
259 }
260
261 void VrController::HandleWaitingState() {
262 // User puts finger on touch pad (or when the touch down for current gesture
263 // is missed, initiate gesture from current touch point).
264 if (touch_info_->touch_down || touch_info_->is_touching) {
265 // update initial touchpoint
266 *init_touch_point_ = touch_info_->touch_point;
267 // update current touchpoint
268 *cur_touch_point_ = touch_info_->touch_point;
269 state_ = TOUCHING;
270 }
271 }
272
273 void VrController::HandleDetectingState() {
274 // User lifts up finger from touch pad.
275 if (touch_info_->touch_up || !(touch_info_->is_touching)) {
276 Reset();
277 return;
278 }
279
280 // Touch position is changed and the touch point moves outside of slop.
281 if (UpdateCurrentTouchpoint() && touch_info_->is_touching &&
282 !InSlop(touch_info_->touch_point.position)) {
283 state_ = SCROLLING;
284 VrGesture gesture;
285 gesture.type = WebInputEvent::GestureScrollBegin;
286 UpdateGesture(&gesture);
287 gesture_list_.push_back(gesture);
288 }
289 }
290
291 void VrController::HandleScrollingState() {
292 // Update current touch point.
293 bool touch_position_changed = UpdateCurrentTouchpoint();
294 if (touch_info_->touch_up || !(touch_info_->is_touching)) { // gesture ends
295 VrGesture scroll_end;
296 scroll_end.type = WebInputEvent::GestureScrollEnd;
297 UpdateGesture(&scroll_end);
298 gesture_list_.push_back(scroll_end);
299
300 Reset();
301 } else if (touch_position_changed) { // User continues scrolling and there is
302 // a change in touch position.
303 VrGesture scroll_update;
304 scroll_update.type = WebInputEvent::GestureScrollUpdate;
305 UpdateGesture(&scroll_update);
306 gesture_list_.push_back(scroll_update);
307 }
308 }
309
310 bool VrController::InSlop(const gvr::Vec2f touch_position) {
311 return (std::abs(touch_position.x - init_touch_point_->position.x) <
312 kSlopHorizontal) &&
313 (std::abs(touch_position.y - init_touch_point_->position.y) <
314 kSlopVertical);
315 }
316
317 void VrController::Reset() {
318 // Reset state.
319 state_ = WAITING;
320
321 // Reset the pointers.
322 prev_touch_point_.reset(new TouchPoint);
323 cur_touch_point_.reset(new TouchPoint);
324 init_touch_point_.reset(new TouchPoint);
325 touch_info_.reset(new TouchInfo);
326 Vector::VectSetZero(&overall_velocity_);
327 }
328
329 void VrController::UpdateGesture(VrGesture* gesture) {
330 if (!gesture)
331 LOG(ERROR) << "The gesture pointer is not initiated properly.";
332 gesture->velocity = overall_velocity_;
333 gesture->displacement = Vector::VectSubtract(cur_touch_point_->position,
334 prev_touch_point_->position);
335 }
336
337 bool VrController::UpdateCurrentTouchpoint() {
338 if (touch_info_->is_touching || touch_info_->touch_up) {
339 // Update the touch point when the touch position has changed.
340 if (!Vector::VectEqual(cur_touch_point_->position,
341 touch_info_->touch_point.position)) {
342 prev_touch_point_.swap(cur_touch_point_);
343 *cur_touch_point_ = touch_info_->touch_point;
344
345 return true;
346 }
347 }
348 return false;
349 }
350
351 } // namespace vr_shell
OLDNEW
« no previous file with comments | « chrome/browser/android/vr_shell/vr_controller.h ('k') | chrome/browser/android/vr_shell/vr_controller_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698