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

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

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

Powered by Google App Engine
This is Rietveld 408576698