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

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

Issue 2591253002: VR: Improve scrolling (Closed)
Patch Set: VR: Improve scrolling Created 3 years, 11 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
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_controller.h" 5 #include "chrome/browser/android/vr_shell/vr_controller.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
11 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/ gvr.h" 11 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/ gvr.h"
12 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/ gvr_controller.h" 12 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/ gvr_controller.h"
13 13
14 namespace vr_shell { 14 namespace vr_shell {
15 15
16 namespace { 16 namespace {
17 17
18 constexpr float kDisplacementScaleFactor = 300.0f; 18 constexpr float kDisplacementScaleFactor = 300.0f;
19 19
20 // A slop represents a small rectangular region around the first touch point of 20 // A slop represents a small rectangular region around the first touch point of
21 // a gesture. 21 // a gesture.
22 // If the user does not move outside of the slop, no gesture is detected. 22 // If the user does not move outside of the slop, no gesture is detected.
23 // Gestures start to be detected when the user moves outside of the slop. 23 // Gestures start to be detected when the user moves outside of the slop.
24 // Vertical distance from the border to the center of slop. 24 // Vertical distance from the border to the center of slop.
25 constexpr float kSlopVertical = 0.165f; 25 constexpr float kSlopVertical = 0.165f;
26 26
27 // Horizontal distance from the border to the center of slop. 27 // Horizontal distance from the border to the center of slop.
28 constexpr float kSlopHorizontal = 0.125f; 28 constexpr float kSlopHorizontal = 0.15f;
29 29
30 // Minimum distance needed in at least one direction to call two vectors 30 // Minimum distance needed in at least one direction to call two vectors
31 // not equal. Also, minimum time distance needed to call two timestamps 31 // not equal. Also, minimum time distance needed to call two timestamps
32 // not equal. 32 // not equal.
33 constexpr float kDelta = 1.0e-7f; 33 constexpr float kDelta = 1.0e-7f;
34 34
35 constexpr float kCutoffHz = 10.0f; 35 constexpr float kCutoffHz = 10.0f;
36 constexpr float kRC = static_cast<float>(1.0 / (2.0 * M_PI * kCutoffHz)); 36 constexpr float kRC = static_cast<float>(1.0 / (2.0 * M_PI * kCutoffHz));
37 constexpr float kNanoSecondsPerSecond = 1.0e9f; 37 constexpr float kNanoSecondsPerSecond = 1.0e9f;
38 38
39 constexpr int kMaxNumOfExtrapolations = 2;
40
39 class Vector { 41 class Vector {
40 public: 42 public:
41 static inline void ClampTouchpadPosition(gvr::Vec2f* position) { 43 static inline void ClampTouchpadPosition(gvr::Vec2f* position) {
42 position->x = std::min(std::max(0.0f, position->x), 1.0f); 44 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); 45 position->y = std::min(std::max(0.0f, position->y), 1.0f);
44 } 46 }
45 47
46 static inline void SetZero(gvr::Vec2f* v) { 48 static inline void SetZero(gvr::Vec2f* v) {
47 v->x = 0; 49 v->x = 0;
48 v->y = 0; 50 v->y = 0;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 if (controller_state_->GetApiStatus() != old_status || 141 if (controller_state_->GetApiStatus() != old_status ||
140 controller_state_->GetConnectionState() != old_connection_state) { 142 controller_state_->GetConnectionState() != old_connection_state) {
141 VLOG(1) << "Controller Connection status: " 143 VLOG(1) << "Controller Connection status: "
142 << gvr_controller_connection_state_to_string( 144 << gvr_controller_connection_state_to_string(
143 controller_state_->GetConnectionState()); 145 controller_state_->GetConnectionState());
144 } 146 }
145 } 147 }
146 148
147 void VrController::UpdateTouchInfo() { 149 void VrController::UpdateTouchInfo() {
148 CHECK(touch_info_ != nullptr) << "touch_info_ not initialized properly."; 150 CHECK(touch_info_ != nullptr) << "touch_info_ not initialized properly.";
149 gvr::Vec2f position; 151 touch_point_->position.x = TouchPosX();
150 position.x = TouchPosX(); 152 touch_point_->position.y = TouchPosY();
151 position.y = TouchPosY();
152 touch_info_->touch_up = TouchUpHappened(); 153 touch_info_->touch_up = TouchUpHappened();
153 touch_info_->touch_down = TouchDownHappened(); 154 touch_info_->touch_down = TouchDownHappened();
154 touch_info_->is_touching = IsTouching(); 155 touch_info_->is_touching = IsTouching();
155 touch_info_->touch_point.position = position; 156 touch_info_->touch_point.position = touch_point_->position;
156 Vector::ClampTouchpadPosition(&touch_info_->touch_point.position); 157 Vector::ClampTouchpadPosition(&touch_info_->touch_point.position);
157 touch_info_->touch_point.timestamp = 158 touch_info_->touch_point.timestamp =
158 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; 159 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos;
159 if (controller_state_->GetLastTouchTimestamp() == last_touch_timestamp_) { 160 touch_point_->timestamp = touch_info_->touch_point.timestamp;
161
162 if (IsTouching() && state_ == SCROLLING &&
163 (controller_state_->GetLastTouchTimestamp() == last_touch_timestamp_ ||
164 (touch_point_->position.x == cur_touch_point_->position.x &&
165 touch_point_->position.y == cur_touch_point_->position.y &&
bshe 2017/01/09 19:38:54 Vector::Equal(touch_point_->position, cur_touch_po
asimjour1 2017/01/11 21:59:45 Used Vector::Equal touch_point_ is the point that
166 extrapolated_touch_ < kMaxNumOfExtrapolations))) {
167 extrapolated_touch_++;
160 // Fill the touch_info 168 // Fill the touch_info
161 float duration = 169 float duration =
162 (gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos - 170 (gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos -
163 last_timestamp_nanos_) / 171 last_timestamp_nanos_) /
164 kNanoSecondsPerSecond; 172 kNanoSecondsPerSecond;
165 173
166 position.x += overall_velocity_.x * duration; 174 touch_info_->touch_point.position.x =
167 position.y += overall_velocity_.y * duration; 175 touch_point_->position.x + overall_velocity_.x * duration;
168 touch_info_->touch_point.position.x = position.x; 176 touch_info_->touch_point.position.y =
169 touch_info_->touch_point.position.y = position.y; 177 touch_point_->position.y + overall_velocity_.y * duration;
178 } else {
179 if (extrapolated_touch_ == kMaxNumOfExtrapolations) {
180 Vector::SetZero(&overall_velocity_);
181 }
182 extrapolated_touch_ = 0;
170 } 183 }
171 last_touch_timestamp_ = controller_state_->GetLastTouchTimestamp(); 184 last_touch_timestamp_ = controller_state_->GetLastTouchTimestamp();
172 last_timestamp_nanos_ = 185 last_timestamp_nanos_ =
173 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; 186 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos;
187 touch_position_changed_ = UpdateCurrentTouchpoint();
174 } 188 }
175 189
176 void VrController::Initialize(gvr_context* gvr_context) { 190 void VrController::Initialize(gvr_context* gvr_context) {
177 CHECK(gvr_context != nullptr) << "invalid gvr_context"; 191 CHECK(gvr_context != nullptr) << "invalid gvr_context";
178 controller_api_.reset(new gvr::ControllerApi); 192 controller_api_.reset(new gvr::ControllerApi);
179 controller_state_.reset(new gvr::ControllerState); 193 controller_state_.reset(new gvr::ControllerState);
180 int32_t options = gvr::ControllerApi::DefaultOptions(); 194 int32_t options = gvr::ControllerApi::DefaultOptions();
181 195
182 // Enable non-default options, if you need them: 196 // Enable non-default options, if you need them:
183 // options |= GVR_CONTROLLER_ENABLE_GYRO; 197 // options |= GVR_CONTROLLER_ENABLE_GYRO;
184 CHECK(controller_api_->Init(options, gvr_context)); 198 CHECK(controller_api_->Init(options, gvr_context));
185 controller_api_->Resume(); 199 controller_api_->Resume();
186 } 200 }
187 201
188 std::vector<std::unique_ptr<WebGestureEvent>> VrController::DetectGestures() { 202 std::vector<std::unique_ptr<WebGestureEvent>> VrController::DetectGestures() {
189 std::vector<std::unique_ptr<WebGestureEvent>> gesture_list; 203 std::vector<std::unique_ptr<WebGestureEvent>> gesture_list;
190 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent()); 204 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent());
205 touch_point_.reset(new TouchPoint);
191 206
192 if (controller_state_->GetConnectionState() != gvr::kControllerConnected) { 207 if (controller_state_->GetConnectionState() != gvr::kControllerConnected) {
193 gesture_list.push_back(std::move(gesture)); 208 gesture_list.push_back(std::move(gesture));
194 return gesture_list; 209 return gesture_list;
195 } 210 }
196 UpdateTouchInfo(); 211 UpdateTouchInfo();
197 UpdateGestureFromTouchInfo(gesture.get()); 212 UpdateGestureFromTouchInfo(gesture.get());
198 213
199 if (gesture->type == WebInputEvent::Undefined && 214 if (gesture->type == WebInputEvent::Undefined &&
200 ButtonUpHappened(gvr::kControllerButtonClick)) { 215 ButtonUpHappened(gvr::kControllerButtonClick)) {
201 gesture->type = WebInputEvent::GestureTapDown; 216 gesture->type = WebInputEvent::GestureTapDown;
202 gesture->x = 0; 217 gesture->x = 0;
203 gesture->y = 0; 218 gesture->y = 0;
204 } 219 }
205 gesture->sourceDevice = blink::WebGestureDeviceTouchpad; 220 gesture->sourceDevice = blink::WebGestureDeviceTouchpad;
206 gesture_list.push_back(std::move(gesture)); 221 gesture_list.push_back(std::move(gesture));
207 222
208 if (gesture_list.back()->type == WebInputEvent::GestureScrollEnd) { 223 if (gesture_list.back()->type == WebInputEvent::GestureScrollEnd) {
209 if (!ButtonDownHappened(gvr::kControllerButtonClick)) { 224 if (!ButtonDownHappened(gvr::kControllerButtonClick) &&
225 (last_velocity_.x != 0.0 || last_velocity_.y != 0.0)) {
210 std::unique_ptr<WebGestureEvent> fling(new WebGestureEvent()); 226 std::unique_ptr<WebGestureEvent> fling(new WebGestureEvent());
211 fling->timeStampSeconds = gesture_list.back()->timeStampSeconds; 227 fling->timeStampSeconds = gesture_list.back()->timeStampSeconds;
212 fling->sourceDevice = blink::WebGestureDeviceTouchpad; 228 fling->sourceDevice = blink::WebGestureDeviceTouchpad;
213 fling->type = WebInputEvent::GestureFlingStart; 229 fling->type = WebInputEvent::GestureFlingStart;
214 if (IsHorizontalGesture()) { 230 if (IsHorizontalGesture()) {
215 fling->data.flingStart.velocityX = 231 fling->data.flingStart.velocityX =
216 overall_velocity_.x * kDisplacementScaleFactor; 232 last_velocity_.x * kDisplacementScaleFactor;
217 } else { 233 } else {
218 fling->data.flingStart.velocityY = 234 fling->data.flingStart.velocityY =
219 overall_velocity_.y * kDisplacementScaleFactor; 235 last_velocity_.y * kDisplacementScaleFactor;
220 } 236 }
221 gesture_list.push_back(std::move(fling)); 237 gesture_list.push_back(std::move(fling));
222 } 238 }
223 Reset(); 239 Reset();
224 } 240 }
225 241
226 return gesture_list; 242 return gesture_list;
227 } 243 }
228 244
229 void VrController::UpdateGestureFromTouchInfo(WebGestureEvent* gesture) { 245 void VrController::UpdateGestureFromTouchInfo(WebGestureEvent* gesture) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 281
266 void VrController::HandleDetectingState(WebGestureEvent* gesture) { 282 void VrController::HandleDetectingState(WebGestureEvent* gesture) {
267 // User lifts up finger from touch pad. 283 // User lifts up finger from touch pad.
268 if (touch_info_->touch_up || !(touch_info_->is_touching)) { 284 if (touch_info_->touch_up || !(touch_info_->is_touching)) {
269 Reset(); 285 Reset();
270 return; 286 return;
271 } 287 }
272 288
273 // Touch position is changed, the touch point moves outside of slop, 289 // Touch position is changed, the touch point moves outside of slop,
274 // and the Controller's button is not down. 290 // and the Controller's button is not down.
275 if (UpdateCurrentTouchpoint() && touch_info_->is_touching && 291 if (touch_position_changed_ && touch_info_->is_touching &&
276 !InSlop(touch_info_->touch_point.position) && 292 !InSlop(touch_info_->touch_point.position) &&
277 !ButtonDownHappened(gvr::kControllerButtonClick)) { 293 !ButtonDownHappened(gvr::kControllerButtonClick)) {
278 state_ = SCROLLING; 294 state_ = SCROLLING;
279 gesture->type = WebInputEvent::GestureScrollBegin; 295 gesture->type = WebInputEvent::GestureScrollBegin;
280 UpdateGesture(gesture); 296 UpdateGesture(gesture);
281 gesture->data.scrollBegin.deltaXHint = 297 gesture->data.scrollBegin.deltaXHint =
282 displacement_.x * kDisplacementScaleFactor; 298 displacement_.x * kDisplacementScaleFactor;
283 gesture->data.scrollBegin.deltaYHint = 299 gesture->data.scrollBegin.deltaYHint =
284 displacement_.y * kDisplacementScaleFactor; 300 displacement_.y * kDisplacementScaleFactor;
285 } 301 }
286 } 302 }
287 303
288 void VrController::HandleScrollingState(WebGestureEvent* gesture) { 304 void VrController::HandleScrollingState(WebGestureEvent* gesture) {
289 // Update current touch point. 305 // Update current touch point.
bshe 2017/01/09 19:38:54 nit: remove the above comment
asimjour1 2017/01/11 21:59:45 Done.
290 bool touch_position_changed = UpdateCurrentTouchpoint();
291 if (touch_info_->touch_up || !(touch_info_->is_touching) || 306 if (touch_info_->touch_up || !(touch_info_->is_touching) ||
292 ButtonDownHappened(gvr::kControllerButtonClick)) { 307 ButtonDownHappened(gvr::kControllerButtonClick)) {
293 // Gesture ends. 308 // Gesture ends.
294 gesture->type = WebInputEvent::GestureScrollEnd; 309 gesture->type = WebInputEvent::GestureScrollEnd;
295 UpdateGesture(gesture); 310 UpdateGesture(gesture);
296 } else if (touch_position_changed) { 311 } else if (touch_position_changed_) {
297 // User continues scrolling and there is a change in touch position. 312 // User continues scrolling and there is a change in touch position.
298 gesture->type = WebInputEvent::GestureScrollUpdate; 313 gesture->type = WebInputEvent::GestureScrollUpdate;
299 UpdateGesture(gesture); 314 UpdateGesture(gesture);
300 if (IsHorizontalGesture()) { 315 if (IsHorizontalGesture()) {
301 gesture->data.scrollUpdate.deltaX = 316 gesture->data.scrollUpdate.deltaX =
302 displacement_.x * kDisplacementScaleFactor; 317 displacement_.x * kDisplacementScaleFactor;
303 } else { 318 } else {
304 gesture->data.scrollUpdate.deltaY = 319 gesture->data.scrollUpdate.deltaY =
305 displacement_.y * kDisplacementScaleFactor; 320 displacement_.y * kDisplacementScaleFactor;
306 } 321 }
322 last_velocity_ = overall_velocity_;
307 } 323 }
308 } 324 }
309 325
310 bool VrController::IsHorizontalGesture() { 326 bool VrController::IsHorizontalGesture() {
311 return std::abs(overall_velocity_.x) > std::abs(overall_velocity_.y); 327 return std::abs(last_velocity_.x) > std::abs(last_velocity_.y);
312 } 328 }
313 329
314 bool VrController::InSlop(const gvr::Vec2f touch_position) { 330 bool VrController::InSlop(const gvr::Vec2f touch_position) {
315 return (std::abs(touch_position.x - init_touch_point_->position.x) < 331 return (std::abs(touch_position.x - init_touch_point_->position.x) <
316 kSlopHorizontal) && 332 kSlopHorizontal) &&
317 (std::abs(touch_position.y - init_touch_point_->position.y) < 333 (std::abs(touch_position.y - init_touch_point_->position.y) <
318 kSlopVertical); 334 kSlopVertical);
319 } 335 }
320 336
321 void VrController::Reset() { 337 void VrController::Reset() {
322 // Reset state. 338 // Reset state.
323 state_ = WAITING; 339 state_ = WAITING;
324 340
325 // Reset the pointers. 341 // Reset the pointers.
326 prev_touch_point_.reset(new TouchPoint); 342 prev_touch_point_.reset(new TouchPoint);
327 cur_touch_point_.reset(new TouchPoint); 343 cur_touch_point_.reset(new TouchPoint);
328 init_touch_point_.reset(new TouchPoint); 344 init_touch_point_.reset(new TouchPoint);
329 touch_info_.reset(new TouchInfo); 345 touch_info_.reset(new TouchInfo);
330 Vector::SetZero(&overall_velocity_); 346 Vector::SetZero(&overall_velocity_);
347 Vector::SetZero(&last_velocity_);
331 } 348 }
332 349
333 void VrController::UpdateGesture(WebGestureEvent* gesture) { 350 void VrController::UpdateGesture(WebGestureEvent* gesture) {
334 if (!gesture) 351 if (!gesture)
335 LOG(ERROR) << "The gesture pointer is not initiated properly."; 352 LOG(ERROR) << "The gesture pointer is not initiated properly.";
336 displacement_ = 353 displacement_ = Vector::Subtract(touch_info_->touch_point.position,
337 Vector::Subtract(cur_touch_point_->position, prev_touch_point_->position); 354 prev_touch_point_->position);
bshe 2017/01/09 19:38:54 IIUC, should prev_touch_point save previous extrop
asimjour1 2017/01/11 21:59:45 It shouldn't be the previous extrapolated point. i
338 } 355 }
339 356
340 bool VrController::UpdateCurrentTouchpoint() { 357 bool VrController::UpdateCurrentTouchpoint() {
341 if (touch_info_->is_touching || touch_info_->touch_up) { 358 if (touch_info_->is_touching || touch_info_->touch_up) {
342 // Update the touch point when the touch position has changed. 359 // Update the touch point when the touch position has changed.
343 if (!Vector::Equal(cur_touch_point_->position, 360 if (!Vector::Equal(cur_touch_point_->position,
344 touch_info_->touch_point.position)) { 361 touch_info_->touch_point.position)) {
345 prev_touch_point_.swap(cur_touch_point_); 362 prev_touch_point_.swap(cur_touch_point_);
346 *cur_touch_point_ = touch_info_->touch_point; 363 cur_touch_point_ = std::move(touch_point_);
347 UpdateOverallVelocity(); 364 UpdateOverallVelocity();
348 return true; 365 return true;
349 } 366 }
350 } 367 }
351 return false; 368 return false;
352 } 369 }
353 370
354 void VrController::UpdateOverallVelocity() { 371 void VrController::UpdateOverallVelocity() {
355 float duration = 372 float duration =
356 (cur_touch_point_->timestamp - prev_touch_point_->timestamp) / 373 (touch_info_->touch_point.timestamp - prev_touch_point_->timestamp) /
357 kNanoSecondsPerSecond; 374 kNanoSecondsPerSecond;
358 375
359 // If the timestamp does not change, do not update velocity. 376 // If the timestamp does not change, do not update velocity.
360 if (duration < kDelta) 377 if (duration < kDelta)
361 return; 378 return;
362 379
363 gvr::Vec2f displacement = 380 gvr::Vec2f displacement = Vector::Subtract(touch_info_->touch_point.position,
364 Vector::Subtract(cur_touch_point_->position, prev_touch_point_->position); 381 prev_touch_point_->position);
365 382
366 gvr::Vec2f velocity = Vector::ScalarMult(displacement, 1 / duration); 383 gvr::Vec2f velocity = Vector::ScalarMult(displacement, 1 / duration);
367 384
368 float weight = duration / (kRC + duration); 385 float weight = duration / (kRC + duration);
369 386
370 overall_velocity_ = 387 overall_velocity_ =
371 Vector::Add(Vector::ScalarMult(overall_velocity_, 1 - weight), 388 Vector::Add(Vector::ScalarMult(overall_velocity_, 1 - weight),
372 Vector::ScalarMult(velocity, weight)); 389 Vector::ScalarMult(velocity, weight));
373 } 390 }
374 391
375 } // namespace vr_shell 392 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698