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

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

Issue 2350253004: Controller support for VrShell (Closed)
Patch Set: rebased + moved vr_input_manager 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 "base/logging.h"
12 #include "third_party/WebKit/public/web/WebInputEvent.h"
13
14 using blink::WebInputEvent;
15
16 namespace vr_shell {
17
18 namespace {
19 constexpr float kDisplacementScaleFactor = 800.0f;
tdresser 2016/09/23 13:48:18 Add comment explaining what this is.
asimjour 2016/09/23 16:58:20 This is a temporary scaling factor that should be
20
21 // A slop represents a small rectangular region around the first touch point of
22 // a gesture.
23 // If the user does not move outside of the slop, no gesture is detected.
24 // Gestures start to be detected when the user moves outside of the slop.
25 // Vertical distance from the border to the center of slop.
26 constexpr float kSlopVertical = 0.165f;
27
28 // Horizontal distance from the border to the center of slop.
29 constexpr float kSlopHorizontal = 0.125f;
tdresser 2016/09/23 13:48:18 Why are vertical and horizontal not equal? Why use
asimjour 2016/09/23 16:58:20 The constants are picked by UX team based on user
30 constexpr float kDelta = 1.0e-7f;
tdresser 2016/09/23 13:48:19 What is this?
asimjour 2016/09/23 16:58:20 Two vectors with this distance are considered to b
31
32 constexpr float kMinZoomAngle = 0.25f;
tdresser 2016/09/23 13:48:18 What is this?
asimjour 2016/09/23 16:58:20 Minimum angle that required for zoom gesture. It i
33
34 inline void ClampTouchpadPosition(gvr::Vec2f* position) {
35 position->x = std::min(std::max(0.0f, position->x), 1.0f);
36 position->y = std::min(std::max(0.0f, position->y), 1.0f);
37 }
38
39 inline void VectSetZero(gvr::Vec2f* v) {
40 v->x = 0;
41 v->y = 0;
42 }
43
44 inline gvr::Vec2f VectSubtract(gvr::Vec2f v1, gvr::Vec2f v2) {
45 gvr::Vec2f result;
46 result.x = v1.x - v2.x;
47 result.y = v1.y - v2.y;
48 return result;
49 }
50
51 inline bool VectEqual(const gvr::Vec2f v1, const gvr::Vec2f v2) {
52 return (std::abs(v1.x - v2.x) < kDelta) && (std::abs(v1.y - v2.y) < kDelta);
53 }
tdresser 2016/09/23 13:48:18 All this code would go away if we used Vector2dF,
54
55 } // namespace
56
57 VrController::VrController(gvr_context* vr_context) {
58 Initialize(vr_context);
59 Reset();
60 }
61
62 VrController::~VrController() {}
63
64 void VrController::OnResume() {
65 if (controller_api_)
66 controller_api_->Resume();
67 }
68
69 void VrController::OnPause() {
70 if (controller_api_)
71 controller_api_->Pause();
72 }
73
74 bool VrController::IsTouching() {
75 return controller_state_.IsTouching();
76 }
77
78 float VrController::TouchPosX() {
79 return controller_state_.GetTouchPos().x;
80 }
81
82 float VrController::TouchPosY() {
83 return controller_state_.GetTouchPos().y;
84 }
tdresser 2016/09/23 13:48:18 Why doesn't this return a Vector2dF?
85
86 const gvr::Quatf VrController::Orientation() {
87 return controller_state_.GetOrientation();
88 }
89
90 bool VrController::IsTouchDown() {
91 return controller_state_.GetTouchDown();
92 }
93
94 bool VrController::IsTouchUp() {
95 return controller_state_.GetTouchUp();
96 }
97
98 bool VrController::ButtonDown(const int32_t button) {
bshe 2016/09/22 23:16:48 nit: IsButtonDown?
asimjour 2016/09/23 16:58:20 Done.
99 return controller_state_.GetButtonDown(button);
100 }
101
102 bool VrController::ButtonUp(const int32_t button) {
bshe 2016/09/22 23:16:49 nit: IsButtonUp
asimjour 2016/09/23 16:58:20 Done.
103 return controller_state_.GetButtonUp(button);
104 }
105
106 bool VrController::IsConnected() {
107 return controller_state_.GetConnectionState() == gvr::kControllerConnected;
108 }
109
110 void VrController::UpdateState() {
111 const int32_t old_status = controller_state_.GetApiStatus();
112 const int32_t old_connection_state = controller_state_.GetConnectionState();
113 // Read current controller state.
114 controller_state_.Update(*controller_api_);
bshe 2016/09/22 23:16:48 If controller is not connected, what would Update
asimjour 2016/09/23 16:58:20 UpdateState only updates the state of the controll
115 // Print new API status and connection state, if they changed.
116 if (controller_state_.GetApiStatus() != old_status ||
117 controller_state_.GetConnectionState() != old_connection_state) {
118 VLOG(1) << "Controller Connection status: "
119 << gvr_controller_connection_state_to_string(
120 controller_state_.GetConnectionState());
121 }
122 return;
bshe 2016/09/22 23:16:49 nit: unnecessary return
asimjour 2016/09/23 16:58:20 Done.
123 }
124
125 void VrController::Update(bool touch_up,
126 bool touch_down,
127 bool is_touching,
128 const gvr::Vec2f position,
129 int64_t timestamp) {
130 CHECK(touch_info_ != nullptr) << "touch_info_ not initialized properly.";
131 touch_info_->touch_up = touch_up;
132 touch_info_->touch_down = touch_down;
133 touch_info_->is_touching = is_touching;
134 touch_info_->touch_point.position = position;
135 ClampTouchpadPosition(&touch_info_->touch_point.position);
136 touch_info_->touch_point.timestamp = timestamp;
137
138 UpdateGestureFromTouchInfo();
139 }
140
141 void VrController::Initialize(gvr_context* gvr_context) {
142 CHECK(gvr_context != nullptr) << "invalid gvr_context";
143 controller_api_.reset(new gvr::ControllerApi);
144 int32_t options = gvr::ControllerApi::DefaultOptions();
145
146 // Enable non-default options, if you need them:
147 // options |= GVR_CONTROLLER_ENABLE_GYRO;
148 CHECK(controller_api_->Init(options, gvr_context));
149 controller_api_->Resume();
150 }
151
152 VrGesture VrController::DetectGesture() {
153 if (controller_state_.GetConnectionState() == gvr::kControllerConnected) {
154 gvr::Vec2f position;
155 position.x = TouchPosX();
156 position.y = TouchPosY();
157 Update(IsTouchUp(), IsTouchDown(), IsTouching(), position,
158 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos);
159 if (GetGestureListSize() > 0 &&
160 GetGesturePtr(0)->type == kGestureTypeScroll) {
161 switch (GetGesturePtr(0)->details.scroll.state) {
162 case WebInputEvent::GestureScrollBegin:
163 return VrGesture(
tdresser 2016/09/23 13:48:18 If I understand correctly, we perform gesture dete
asimjour 2016/09/23 16:58:20 Our gestures are not limited to the gestures that
tdresser 2016/09/23 17:45:17 So why not construct VREvents immediately instead
asimjour 2016/09/23 19:56:31 Only constants regarding the state of the gesture
tdresser 2016/09/23 20:36:44 Which constants? Just the types? Don't we already
164 kGestureScroll,
165 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
166 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
167 GetGesturePtr(0)->displacement.x * kDisplacementScaleFactor,
168 GetGesturePtr(0)->displacement.y * kDisplacementScaleFactor,
169 WebInputEvent::GestureScrollBegin, Orientation());
170 case WebInputEvent::GestureScrollUpdate:
171 return VrGesture(
172 kGestureScroll,
173 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
174 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
175 GetGesturePtr(0)->displacement.x * kDisplacementScaleFactor,
176 GetGesturePtr(0)->displacement.y * kDisplacementScaleFactor,
177 WebInputEvent::GestureScrollUpdate, Orientation());
178 case WebInputEvent::GestureScrollEnd:
179 return VrGesture(
180 kGestureScroll,
181 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
182 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
183 GetGesturePtr(0)->displacement.x * kDisplacementScaleFactor,
184 GetGesturePtr(0)->displacement.y * kDisplacementScaleFactor,
185 WebInputEvent::GestureScrollEnd, Orientation());
186 }
187 }
188
189 if (ButtonDown(gvr::kControllerButtonClick)) {
190 return VrGesture(
191 kGestureButtonsChange,
192 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
193 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos, 1, 0,
194 Orientation());
195 }
196 float dqx = 0.0f;
197
198 dqx = last_qx_ - Orientation().qx;
199
200 // don't accept rapid moves
201 if (dqx < -1.0f || dqx > 1.0f)
202 dqx = 0.0f;
203 last_qx_ = Orientation().qx;
204
205 if (ButtonDown(gvr::kControllerButtonApp))
206 zoom_in_progress_ = true;
207 if (ButtonUp(gvr::kControllerButtonApp)) {
208 zoom_in_progress_ = false;
209 if (pinch_started_) {
210 pinch_started_ = false;
211 }
212 }
213 if (zoom_in_progress_) {
214 if (dqx != 0.0f) {
215 // dz == 1 means no zoom. dz < 1 means zoom-out and dz > 1 means
216 // zoom-in.
217 // dqx * 2 + 1 results to dz \in [0,2]
218 return VrGesture(
219 kGestureZoom,
220 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
221 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
222 dqx * 2 + 1, Orientation());
223 }
224 if (Orientation().qz < kMinZoomAngle &&
225 Orientation().qz > -1 * kMinZoomAngle && pinch_started_) {
226 pinch_started_ = false;
227 }
228 }
229 return VrGesture(kGestureAngularMove,
230 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
231 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
232 Orientation());
233 }
234 return VrGesture();
235 }
236
237 void VrController::UpdateGestureFromTouchInfo() {
238 // Clear the gesture list.
239 gesture_list_.clear();
240
241 switch (state_) {
242 // user has not put finger on touch pad.
tdresser 2016/09/23 20:36:44 Capitalize comments.
243 case WAITING:
244 HandleWaitingState();
245 break;
246 // user has not started a gesture (by moving out of slop).
247 case TOUCHING:
248 HandleDetectingState();
249 break;
250 // user is scrolling on touchpad
251 case SCROLLING:
252 HandleScrollingState();
253 break;
254 default:
255 LOG(ERROR) << "Wrong gesture detector state: " << state_;
256 break;
257 }
258 }
259
260 const VrGesture* VrController::GetGesturePtr(const size_t index) {
261 CHECK(index < gesture_list_.size()) << "The gesture index exceeds the"
262 "size of gesture list.";
263 return const_cast<VrGesture*>(&gesture_list_[index]);
264 }
265
266 void VrController::Update(const gvr_controller_state* controller_state) {
267 // Update touch information.
268 CHECK(touch_info_ != nullptr) << "touch_info_ not initialized properly.";
269 touch_info_->touch_up = gvr_controller_state_get_touch_up(controller_state);
270 touch_info_->touch_down =
271 gvr_controller_state_get_touch_down(controller_state);
272 touch_info_->is_touching = gvr_controller_state_is_touching(controller_state);
273 touch_info_->touch_point.position.x =
274 gvr_controller_state_get_touch_pos(controller_state).x;
275 touch_info_->touch_point.position.y =
276 gvr_controller_state_get_touch_pos(controller_state).y;
277 ClampTouchpadPosition(&(touch_info_->touch_point.position));
278 touch_info_->touch_point.timestamp =
279 gvr_controller_state_get_last_touch_timestamp(controller_state);
280
281 UpdateGestureFromTouchInfo();
282 }
283
284 void VrController::HandleWaitingState() {
285 // User puts finger on touch pad (or when the touch down for current gesture
286 // is missed, initiate gesture from current touch point).
287 if (touch_info_->touch_down || touch_info_->is_touching) {
288 // update initial touchpoint
289 *init_touch_point_ = touch_info_->touch_point;
290 // update current touchpoint
291 *cur_touch_point_ = touch_info_->touch_point;
292 state_ = TOUCHING;
293 }
294 }
295
296 void VrController::HandleDetectingState() {
297 // User lifts up finger from touch pad.
298 if (touch_info_->touch_up || !(touch_info_->is_touching)) {
299 Reset();
300 return;
301 }
302
303 // Touch position is changed and the touch point moves outside of slop.
304 if (UpdateCurrentTouchpoint() && touch_info_->is_touching &&
305 !InSlop(touch_info_->touch_point.position)) {
306 state_ = SCROLLING;
307 VrGesture gesture;
308 gesture.type = kGestureTypeScroll;
309 gesture.details.scroll.state = WebInputEvent::GestureScrollBegin;
310 UpdateGesture(&gesture);
311 gesture_list_.push_back(gesture);
312 }
313 }
314
315 void VrController::HandleScrollingState() {
316 // Update current touch point.
317 bool touch_position_changed = UpdateCurrentTouchpoint();
318 if (touch_info_->touch_up || !(touch_info_->is_touching)) { // gesture ends
319 VrGesture scroll_end;
320 scroll_end.type = kGestureTypeScroll;
321 scroll_end.details.scroll.state = WebInputEvent::GestureScrollEnd;
322 UpdateGesture(&scroll_end);
323 gesture_list_.push_back(scroll_end);
324
325 Reset();
326 } else if (touch_position_changed) { // User continues scrolling and there is
327 // a change in touch position.
328 VrGesture scroll_update;
329 scroll_update.type = kGestureTypeScroll;
330 scroll_update.details.scroll.state = WebInputEvent::GestureScrollUpdate;
331 UpdateGesture(&scroll_update);
332 gesture_list_.push_back(scroll_update);
333 }
334 }
335
336 bool VrController::InSlop(const gvr::Vec2f touch_position) {
337 return (std::abs(touch_position.x - init_touch_point_->position.x) <
338 kSlopHorizontal) &&
339 (std::abs(touch_position.y - init_touch_point_->position.y) <
340 kSlopVertical);
341 }
342
343 void VrController::Reset() {
344 // Reset state.
345 state_ = WAITING;
346
347 // Reset the pointers.
348 prev_touch_point_.reset(new TouchPoint);
349 cur_touch_point_.reset(new TouchPoint);
350 init_touch_point_.reset(new TouchPoint);
351 touch_info_.reset(new TouchInfo);
352 VectSetZero(&overall_velocity_);
353 }
354
355 void VrController::UpdateGesture(VrGesture* gesture) {
356 if (!gesture)
357 LOG(ERROR) << "The gesture pointer is not initiated properly.";
358 gesture->velocity = overall_velocity_;
359 gesture->displacement =
360 VectSubtract(cur_touch_point_->position, prev_touch_point_->position);
361 }
362
363 bool VrController::UpdateCurrentTouchpoint() {
364 if (touch_info_->is_touching || touch_info_->touch_up) {
365 // Update the touch point when the touch position has changed.
366 if (!VectEqual(cur_touch_point_->position,
367 touch_info_->touch_point.position)) {
368 prev_touch_point_.swap(cur_touch_point_);
369 *cur_touch_point_ = touch_info_->touch_point;
370
371 return true;
372 }
373 }
374 return false;
375 }
376
377 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698