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

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

Issue 2350253004: Controller support for VrShell (Closed)
Patch Set: removed unused files Created 4 years, 3 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;
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;
30 constexpr float kDelta = 1.0e-7f;
31
32 constexpr float kMinZoomAngle = 0.25f;
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) {
mthiesse 2016/09/22 16:20:10 replace gvr_ with gvr:: types throughout.
asimjour 2016/09/22 22:55:15 Done.
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 }
54
55 } // namespace
56
57 VrController::VrController(gvr_context_* vr_context) {
mthiesse 2016/09/22 16:20:11 gvr_context*
asimjour 2016/09/22 22:55:15 Done.
58 Reset();
59 }
60
61 VrController::~VrController() {}
62
63 void VrController::OnResume() {
64 if (controller_api_)
65 controller_api_->Resume();
66 }
67
68 void VrController::OnPause() {
69 if (controller_api_)
70 controller_api_->Pause();
71 }
72
73 bool VrController::IsTouching() {
74 return controller_state_.IsTouching();
75 }
76
77 float VrController::TouchPosX() {
78 return controller_state_.GetTouchPos().x;
79 }
80
81 float VrController::TouchPosY() {
82 return controller_state_.GetTouchPos().y;
83 }
84
85 const gvr_quatf VrController::Orientation() {
86 return controller_state_.GetOrientation();
87 }
88
89 bool VrController::IsTouchDown() {
90 return controller_state_.GetTouchDown();
91 }
92
93 bool VrController::IsTouchUp() {
94 return controller_state_.GetTouchUp();
95 }
96
97 bool VrController::ButtonDown(const int32_t button) {
98 return controller_state_.GetButtonDown(button);
99 }
100
101 bool VrController::ButtonUp(const int32_t button) {
102 return controller_state_.GetButtonUp(button);
103 }
104
105 bool VrController::IsConnected() {
106 return controller_state_.GetConnectionState() == gvr::kControllerConnected;
107 }
108
109 void VrController::UpdateState() {
110 const int32_t old_status = controller_state_.GetApiStatus();
111 const int32_t old_connection_state = controller_state_.GetConnectionState();
112 // Read current controller state.
113 controller_state_.Update(*controller_api_);
114 // Print new API status and connection state, if they changed.
115 if (controller_state_.GetApiStatus() != old_status ||
116 controller_state_.GetConnectionState() != old_connection_state) {
117 VLOG(1) << "Controller Connection status: "
118 << gvr_controller_connection_state_to_string(
119 controller_state_.GetConnectionState());
120 }
121 return;
122 }
123
124 void VrController::Update(bool touch_up,
125 bool touch_down,
126 bool is_touching,
127 const gvr_vec2f position,
128 int64_t timestamp) {
129 CHECK(touch_info_ != nullptr) << "touch_info_ not initialized properly.";
130 touch_info_->touch_up = touch_up;
131 touch_info_->touch_down = touch_down;
132 touch_info_->is_touching = is_touching;
133 touch_info_->touch_point.position = position;
134 ClampTouchpadPosition(&touch_info_->touch_point.position);
135 touch_info_->touch_point.timestamp = timestamp;
136
137 UpdateGestureFromTouchInfo();
138 }
139
140 void VrController::Initialize(gvr_context_* gvr_context) {
mthiesse 2016/09/22 16:20:11 gvr_context*
asimjour 2016/09/22 22:55:15 Done.
141 CHECK(gvr_context != nullptr) << "invalid gvr_context";
142 controller_api_.reset(new gvr::ControllerApi);
143 int32_t options = gvr::ControllerApi::DefaultOptions();
144
145 // Enable non-default options, if you need them:
146 // options |= GVR_CONTROLLER_ENABLE_GYRO;
147 CHECK(controller_api_->Init(options, gvr_context));
148 controller_api_->Resume();
149 }
150
151 VrGesture VrController::DetectGesture() {
152 if (controller_state_.GetConnectionState() == gvr::kControllerConnected) {
153 gvr_vec2f position;
154 position.x = TouchPosX();
155 position.y = TouchPosY();
156 Update(IsTouchUp(), IsTouchDown(), IsTouching(), position,
157 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos);
158 if (GetGestureListSize() > 0 &&
159 GetGesturePtr(0)->type == kGestureTypeScroll) {
160 switch (GetGesturePtr(0)->details.scroll.state) {
161 case WebInputEvent::GestureScrollBegin:
162 return VrGesture(
163 kGestureScroll,
164 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
165 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
166 GetGesturePtr(0)->displacement.x * kDisplacementScaleFactor,
167 GetGesturePtr(0)->displacement.y * kDisplacementScaleFactor,
168 WebInputEvent::GestureScrollBegin, Orientation());
169 case WebInputEvent::GestureScrollUpdate:
170 return VrGesture(
171 kGestureScroll,
172 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
173 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos, 0, 0,
174 WebInputEvent::GestureScrollUpdate, Orientation());
175 case WebInputEvent::GestureScrollEnd:
176 return VrGesture(
177 kGestureScroll,
178 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
179 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
180 GetGesturePtr(0)->displacement.x * kDisplacementScaleFactor,
181 GetGesturePtr(0)->displacement.y * kDisplacementScaleFactor,
182 WebInputEvent::GestureScrollEnd, Orientation());
183 }
184 }
185
186 if (ButtonDown(gvr::kControllerButtonClick)) {
187 return VrGesture(
188 kGestureButtonsChange,
189 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
190 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos, 1, 0,
191 Orientation());
192 }
193 float dqx = 0.0f;
194
195 dqx = last_qx_ - Orientation().qx;
196
197 // don't accept rapid moves
198 if (dqx < -1.0f || dqx > 1.0f)
199 dqx = 0.0f;
200 last_qx_ = Orientation().qx;
201
202 if (ButtonDown(gvr::kControllerButtonApp))
203 zoom_in_progress_ = true;
204 if (ButtonUp(gvr::kControllerButtonApp)) {
205 zoom_in_progress_ = false;
206 if (pinch_started_) {
207 pinch_started_ = false;
208 }
209 }
210 if (zoom_in_progress_) {
211 if (dqx != 0.0f) {
212 // dz == 1 means no zoom. dz < 1 means zoom-out and dz > 1 means
213 // zoom-in.
214 // dqx * 2 + 1 results to dz \in [0,2]
215 return VrGesture(
216 kGestureZoom,
217 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
218 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
219 dqx * 2 + 1, Orientation());
220 }
221 if (Orientation().qz < kMinZoomAngle &&
222 Orientation().qz > -1 * kMinZoomAngle && pinch_started_) {
223 pinch_started_ = false;
224 }
225 }
226 return VrGesture(kGestureAngularMove,
227 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
228 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos,
229 Orientation());
230 }
231 return VrGesture();
232 }
233
234 void VrController::UpdateGestureFromTouchInfo() {
235 // Clear the gesture list.
236 gesture_list_.clear();
237
238 switch (state_) {
239 // user has not put finger on touch pad.
240 case WAITING:
241 HandleWaitingState();
242 break;
243 // user has not started a gesture (by moving out of slop).
244 case TOUCHING:
245 HandleDetectingState();
246 break;
247 // user is scrolling on touchpad
248 case SCROLLING:
249 HandleScrollingState();
250 break;
251 default:
252 LOG(ERROR) << "Wrong gesture detector state: " << state_;
253 break;
254 }
255 }
256
257 const VrGesture* VrController::GetGesturePtr(const size_t index) {
258 CHECK(index < gesture_list_.size()) << "The gesture index exceeds the"
259 "size of gesture list.";
260 return const_cast<VrGesture*>(&gesture_list_[index]);
261 }
262
263 void VrController::Update(const gvr_controller_state* controller_state) {
264 // Update touch information.
265 CHECK(touch_info_ != nullptr) << "touch_info_ not initialized properly.";
266 touch_info_->touch_up = gvr_controller_state_get_touch_up(controller_state);
267 touch_info_->touch_down =
268 gvr_controller_state_get_touch_down(controller_state);
269 touch_info_->is_touching = gvr_controller_state_is_touching(controller_state);
270 touch_info_->touch_point.position.x =
271 gvr_controller_state_get_touch_pos(controller_state).x;
272 touch_info_->touch_point.position.y =
273 gvr_controller_state_get_touch_pos(controller_state).y;
274 ClampTouchpadPosition(&(touch_info_->touch_point.position));
275 touch_info_->touch_point.timestamp =
276 gvr_controller_state_get_last_touch_timestamp(controller_state);
277
278 UpdateGestureFromTouchInfo();
279 }
280
281 void VrController::HandleWaitingState() {
282 // User puts finger on touch pad (or when the touch down for current gesture
283 // is missed, initiate gesture from current touch point).
284 if (touch_info_->touch_down || touch_info_->is_touching) {
285 // update initial touchpoint
286 *init_touch_point_ = touch_info_->touch_point;
287 // update current touchpoint
288 *cur_touch_point_ = touch_info_->touch_point;
289 state_ = TOUCHING;
290 }
291 }
292
293 void VrController::HandleDetectingState() {
294 // User lifts up finger from touch pad.
295 if (touch_info_->touch_up || !(touch_info_->is_touching)) {
296 Reset();
297 return;
298 }
299
300 // Touch position is changed and the touch point moves outside of slop.
301 if (UpdateCurrentTouchpoint() && touch_info_->is_touching &&
302 !InSlop(touch_info_->touch_point.position)) {
303 state_ = SCROLLING;
304 VrGesture gesture;
305 gesture.type = kGestureTypeScroll;
306 gesture.details.scroll.state = WebInputEvent::GestureScrollBegin;
307 UpdateGesture(&gesture);
308 gesture_list_.push_back(gesture);
309 }
310 }
311
312 void VrController::HandleScrollingState() {
313 // Update current touch point.
314 bool touch_position_changed = UpdateCurrentTouchpoint();
315 if (touch_info_->touch_up || !(touch_info_->is_touching)) { // gesture ends
316 VrGesture scroll_end;
317 scroll_end.type = kGestureTypeScroll;
318 scroll_end.details.scroll.state = WebInputEvent::GestureScrollEnd;
319 UpdateGesture(&scroll_end);
320 gesture_list_.push_back(scroll_end);
321
322 Reset();
323 } else if (touch_position_changed) { // User continues scrolling and there is
324 // a change in touch position.
325 VrGesture scroll_update;
326 scroll_update.type = kGestureTypeScroll;
327 scroll_update.details.scroll.state = WebInputEvent::GestureScrollUpdate;
328 UpdateGesture(&scroll_update);
329 gesture_list_.push_back(scroll_update);
330 }
331 }
332
333 bool VrController::InSlop(const gvr_vec2f touch_position) {
334 return (std::abs(touch_position.x - init_touch_point_->position.x) <
335 kSlopHorizontal) &&
336 (std::abs(touch_position.y - init_touch_point_->position.y) <
337 kSlopVertical);
338 }
339
340 void VrController::Reset() {
341 // Reset state.
342 state_ = WAITING;
343
344 // Reset the pointers.
345 prev_touch_point_.reset(new TouchPoint);
346 cur_touch_point_.reset(new TouchPoint);
347 init_touch_point_.reset(new TouchPoint);
348 touch_info_.reset(new TouchInfo);
349 VectSetZero(&overall_velocity_);
350 }
351
352 void VrController::UpdateGesture(VrGesture* gesture) {
353 if (!gesture)
354 LOG(ERROR) << "The gesture pointer is not initiated properly.";
355 gesture->velocity = overall_velocity_;
356 gesture->displacement =
357 VectSubtract(cur_touch_point_->position, prev_touch_point_->position);
358 }
359
360 bool VrController::UpdateCurrentTouchpoint() {
361 if (touch_info_->is_touching || touch_info_->touch_up) {
362 // Update the touch point when the touch position has changed.
363 if (!VectEqual(cur_touch_point_->position,
364 touch_info_->touch_point.position)) {
365 prev_touch_point_.swap(cur_touch_point_);
366 *cur_touch_point_ = touch_info_->touch_point;
367
368 return true;
369 }
370 }
371 return false;
372 }
373
374 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698