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

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

Issue 2591253002: VR: Improve scrolling (Closed)
Patch Set: Remove touch_point_ + rebase Created 3 years, 10 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
« no previous file with comments | « chrome/browser/android/vr_shell/vr_controller.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 if (IsTouching() && state_ == SCROLLING &&
150 position.x = TouchPosX(); 152 (controller_state_->GetLastTouchTimestamp() == last_touch_timestamp_ ||
151 position.y = TouchPosY(); 153 (Vector::Equal(cur_touch_point_->position,
152 touch_info_->touch_up = TouchUpHappened(); 154 prev_touch_point_->position) &&
153 touch_info_->touch_down = TouchDownHappened(); 155 extrapolated_touch_ < kMaxNumOfExtrapolations))) {
154 touch_info_->is_touching = IsTouching(); 156 extrapolated_touch_++;
155 touch_info_->touch_point.position = position; 157 touch_position_changed_ = true;
156 Vector::ClampTouchpadPosition(&touch_info_->touch_point.position);
157 touch_info_->touch_point.timestamp =
158 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos;
159 if (controller_state_->GetLastTouchTimestamp() == last_touch_timestamp_) {
160 // Fill the touch_info 158 // Fill the touch_info
161 float duration = 159 float duration =
162 (gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos - 160 (gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos -
163 last_timestamp_nanos_) / 161 last_timestamp_nanos_) /
164 kNanoSecondsPerSecond; 162 kNanoSecondsPerSecond;
165 163 touch_info_->touch_point.position.x =
166 position.x += overall_velocity_.x * duration; 164 cur_touch_point_->position.x + overall_velocity_.x * duration;
167 position.y += overall_velocity_.y * duration; 165 touch_info_->touch_point.position.y =
168 touch_info_->touch_point.position.x = position.x; 166 cur_touch_point_->position.y + overall_velocity_.y * duration;
169 touch_info_->touch_point.position.y = position.y; 167 } else {
168 if (extrapolated_touch_ == kMaxNumOfExtrapolations) {
169 Vector::SetZero(&overall_velocity_);
170 }
171 extrapolated_touch_ = 0;
170 } 172 }
171 last_touch_timestamp_ = controller_state_->GetLastTouchTimestamp(); 173 last_touch_timestamp_ = controller_state_->GetLastTouchTimestamp();
172 last_timestamp_nanos_ = 174 last_timestamp_nanos_ =
173 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; 175 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos;
174 } 176 }
175 177
176 void VrController::Initialize(gvr_context* gvr_context) { 178 void VrController::Initialize(gvr_context* gvr_context) {
177 CHECK(gvr_context != nullptr) << "invalid gvr_context"; 179 CHECK(gvr_context != nullptr) << "invalid gvr_context";
178 controller_api_.reset(new gvr::ControllerApi); 180 controller_api_.reset(new gvr::ControllerApi);
179 controller_state_.reset(new gvr::ControllerState); 181 controller_state_.reset(new gvr::ControllerState);
180 int32_t options = gvr::ControllerApi::DefaultOptions(); 182 int32_t options = gvr::ControllerApi::DefaultOptions();
181 183
182 // Enable non-default options, if you need them: 184 // Enable non-default options, if you need them:
183 // options |= GVR_CONTROLLER_ENABLE_GYRO; 185 // options |= GVR_CONTROLLER_ENABLE_GYRO;
184 CHECK(controller_api_->Init(options, gvr_context)); 186 CHECK(controller_api_->Init(options, gvr_context));
185 controller_api_->Resume(); 187 controller_api_->Resume();
186 } 188 }
187 189
188 std::vector<std::unique_ptr<WebGestureEvent>> VrController::DetectGestures() { 190 std::vector<std::unique_ptr<WebGestureEvent>> VrController::DetectGestures() {
189 std::vector<std::unique_ptr<WebGestureEvent>> gesture_list; 191 std::vector<std::unique_ptr<WebGestureEvent>> gesture_list;
190 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent()); 192 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent());
191 193
192 if (controller_state_->GetConnectionState() != gvr::kControllerConnected) { 194 if (controller_state_->GetConnectionState() != gvr::kControllerConnected) {
193 gesture_list.push_back(std::move(gesture)); 195 gesture_list.push_back(std::move(gesture));
194 return gesture_list; 196 return gesture_list;
195 } 197 }
198
199 touch_position_changed_ = UpdateCurrentTouchpoint();
196 UpdateTouchInfo(); 200 UpdateTouchInfo();
201 if (touch_position_changed_)
202 UpdateOverallVelocity();
203
197 UpdateGestureFromTouchInfo(gesture.get()); 204 UpdateGestureFromTouchInfo(gesture.get());
198 205
199 if (gesture->type() == WebInputEvent::Undefined && 206 if (gesture->type() == WebInputEvent::Undefined &&
200 ButtonUpHappened(gvr::kControllerButtonClick)) { 207 ButtonUpHappened(gvr::kControllerButtonClick)) {
201 gesture->setType(WebInputEvent::GestureTapDown); 208 gesture->setType(WebInputEvent::GestureTapDown);
202 gesture->x = 0; 209 gesture->x = 0;
203 gesture->y = 0; 210 gesture->y = 0;
204 } 211 }
205 gesture->sourceDevice = blink::WebGestureDeviceTouchpad; 212 gesture->sourceDevice = blink::WebGestureDeviceTouchpad;
206 gesture_list.push_back(std::move(gesture)); 213 gesture_list.push_back(std::move(gesture));
207 214
208 if (gesture_list.back()->type() == WebInputEvent::GestureScrollEnd) { 215 if (gesture_list.back()->type() == WebInputEvent::GestureScrollEnd) {
209 if (!ButtonDownHappened(gvr::kControllerButtonClick)) { 216 if (!ButtonDownHappened(gvr::kControllerButtonClick) &&
217 (last_velocity_.x != 0.0 || last_velocity_.y != 0.0)) {
210 std::unique_ptr<WebGestureEvent> fling(new WebGestureEvent( 218 std::unique_ptr<WebGestureEvent> fling(new WebGestureEvent(
211 WebInputEvent::GestureFlingStart, WebInputEvent::NoModifiers, 219 WebInputEvent::GestureFlingStart, WebInputEvent::NoModifiers,
212 gesture_list.back()->timeStampSeconds())); 220 gesture_list.back()->timeStampSeconds()));
213 fling->sourceDevice = blink::WebGestureDeviceTouchpad; 221 fling->sourceDevice = blink::WebGestureDeviceTouchpad;
214 if (IsHorizontalGesture()) { 222 if (IsHorizontalGesture()) {
215 fling->data.flingStart.velocityX = 223 fling->data.flingStart.velocityX =
216 overall_velocity_.x * kDisplacementScaleFactor; 224 last_velocity_.x * kDisplacementScaleFactor;
217 } else { 225 } else {
218 fling->data.flingStart.velocityY = 226 fling->data.flingStart.velocityY =
219 overall_velocity_.y * kDisplacementScaleFactor; 227 last_velocity_.y * kDisplacementScaleFactor;
220 } 228 }
221 gesture_list.push_back(std::move(fling)); 229 gesture_list.push_back(std::move(fling));
222 } 230 }
223 Reset(); 231 Reset();
224 } 232 }
225 233
226 return gesture_list; 234 return gesture_list;
227 } 235 }
228 236
229 void VrController::UpdateGestureFromTouchInfo(WebGestureEvent* gesture) { 237 void VrController::UpdateGestureFromTouchInfo(WebGestureEvent* gesture) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 273
266 void VrController::HandleDetectingState(WebGestureEvent* gesture) { 274 void VrController::HandleDetectingState(WebGestureEvent* gesture) {
267 // User lifts up finger from touch pad. 275 // User lifts up finger from touch pad.
268 if (touch_info_->touch_up || !(touch_info_->is_touching)) { 276 if (touch_info_->touch_up || !(touch_info_->is_touching)) {
269 Reset(); 277 Reset();
270 return; 278 return;
271 } 279 }
272 280
273 // Touch position is changed, the touch point moves outside of slop, 281 // Touch position is changed, the touch point moves outside of slop,
274 // and the Controller's button is not down. 282 // and the Controller's button is not down.
275 if (UpdateCurrentTouchpoint() && touch_info_->is_touching && 283 if (touch_position_changed_ && touch_info_->is_touching &&
276 !InSlop(touch_info_->touch_point.position) && 284 !InSlop(touch_info_->touch_point.position) &&
277 !ButtonDownHappened(gvr::kControllerButtonClick)) { 285 !ButtonDownHappened(gvr::kControllerButtonClick)) {
278 state_ = SCROLLING; 286 state_ = SCROLLING;
279 gesture->setType(WebInputEvent::GestureScrollBegin); 287 gesture->setType(WebInputEvent::GestureScrollBegin);
280 UpdateGesture(gesture); 288 UpdateGesture(gesture);
281 gesture->data.scrollBegin.deltaXHint = 289 gesture->data.scrollBegin.deltaXHint =
282 displacement_.x * kDisplacementScaleFactor; 290 displacement_.x * kDisplacementScaleFactor;
283 gesture->data.scrollBegin.deltaYHint = 291 gesture->data.scrollBegin.deltaYHint =
284 displacement_.y * kDisplacementScaleFactor; 292 displacement_.y * kDisplacementScaleFactor;
285 } 293 }
286 } 294 }
287 295
288 void VrController::HandleScrollingState(WebGestureEvent* gesture) { 296 void VrController::HandleScrollingState(WebGestureEvent* gesture) {
289 // Update current touch point.
290 bool touch_position_changed = UpdateCurrentTouchpoint();
291 if (touch_info_->touch_up || !(touch_info_->is_touching) || 297 if (touch_info_->touch_up || !(touch_info_->is_touching) ||
292 ButtonDownHappened(gvr::kControllerButtonClick)) { 298 ButtonDownHappened(gvr::kControllerButtonClick)) {
293 // Gesture ends. 299 // Gesture ends.
294 gesture->setType(WebInputEvent::GestureScrollEnd); 300 gesture->setType(WebInputEvent::GestureScrollEnd);
295 UpdateGesture(gesture); 301 UpdateGesture(gesture);
296 } else if (touch_position_changed) { 302 } else if (touch_position_changed_) {
297 // User continues scrolling and there is a change in touch position. 303 // User continues scrolling and there is a change in touch position.
298 gesture->setType(WebInputEvent::GestureScrollUpdate); 304 gesture->setType(WebInputEvent::GestureScrollUpdate);
299 UpdateGesture(gesture); 305 UpdateGesture(gesture);
300 if (IsHorizontalGesture()) { 306 if (IsHorizontalGesture()) {
301 gesture->data.scrollUpdate.deltaX = 307 gesture->data.scrollUpdate.deltaX =
302 displacement_.x * kDisplacementScaleFactor; 308 displacement_.x * kDisplacementScaleFactor;
303 } else { 309 } else {
304 gesture->data.scrollUpdate.deltaY = 310 gesture->data.scrollUpdate.deltaY =
305 displacement_.y * kDisplacementScaleFactor; 311 displacement_.y * kDisplacementScaleFactor;
306 } 312 }
313 last_velocity_ = overall_velocity_;
307 } 314 }
308 } 315 }
309 316
310 bool VrController::IsHorizontalGesture() { 317 bool VrController::IsHorizontalGesture() {
311 return std::abs(overall_velocity_.x) > std::abs(overall_velocity_.y); 318 return std::abs(last_velocity_.x) > std::abs(last_velocity_.y);
312 } 319 }
313 320
314 bool VrController::InSlop(const gvr::Vec2f touch_position) { 321 bool VrController::InSlop(const gvr::Vec2f touch_position) {
315 return (std::abs(touch_position.x - init_touch_point_->position.x) < 322 return (std::abs(touch_position.x - init_touch_point_->position.x) <
316 kSlopHorizontal) && 323 kSlopHorizontal) &&
317 (std::abs(touch_position.y - init_touch_point_->position.y) < 324 (std::abs(touch_position.y - init_touch_point_->position.y) <
318 kSlopVertical); 325 kSlopVertical);
319 } 326 }
320 327
321 void VrController::Reset() { 328 void VrController::Reset() {
322 // Reset state. 329 // Reset state.
323 state_ = WAITING; 330 state_ = WAITING;
324 331
325 // Reset the pointers. 332 // Reset the pointers.
326 prev_touch_point_.reset(new TouchPoint); 333 prev_touch_point_.reset(new TouchPoint);
327 cur_touch_point_.reset(new TouchPoint); 334 cur_touch_point_.reset(new TouchPoint);
328 init_touch_point_.reset(new TouchPoint); 335 init_touch_point_.reset(new TouchPoint);
329 touch_info_.reset(new TouchInfo); 336 touch_info_.reset(new TouchInfo);
330 Vector::SetZero(&overall_velocity_); 337 Vector::SetZero(&overall_velocity_);
338 Vector::SetZero(&last_velocity_);
331 } 339 }
332 340
333 void VrController::UpdateGesture(WebGestureEvent* gesture) { 341 void VrController::UpdateGesture(WebGestureEvent* gesture) {
334 if (!gesture) 342 if (!gesture)
335 LOG(ERROR) << "The gesture pointer is not initiated properly."; 343 LOG(ERROR) << "The gesture pointer is not initiated properly.";
336 displacement_ = 344 displacement_ = Vector::Subtract(touch_info_->touch_point.position,
337 Vector::Subtract(cur_touch_point_->position, prev_touch_point_->position); 345 prev_touch_point_->position);
338 } 346 }
339 347
340 bool VrController::UpdateCurrentTouchpoint() { 348 bool VrController::UpdateCurrentTouchpoint() {
341 if (touch_info_->is_touching || touch_info_->touch_up) { 349 touch_info_->touch_up = TouchUpHappened();
350 touch_info_->touch_down = TouchDownHappened();
351 touch_info_->is_touching = IsTouching();
352 touch_info_->touch_point.position.x = TouchPosX();
353 touch_info_->touch_point.position.y = TouchPosY();
354 Vector::ClampTouchpadPosition(&touch_info_->touch_point.position);
355 touch_info_->touch_point.timestamp =
356 gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos;
357
358 if (IsTouching() || TouchUpHappened()) {
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_.reset(new TouchPoint);
347 UpdateOverallVelocity(); 364 cur_touch_point_->position = touch_info_->touch_point.position;
365 cur_touch_point_->timestamp = touch_info_->touch_point.timestamp;
348 return true; 366 return true;
349 } 367 }
350 } 368 }
351 return false; 369 return false;
352 } 370 }
353 371
354 void VrController::UpdateOverallVelocity() { 372 void VrController::UpdateOverallVelocity() {
355 float duration = 373 float duration =
356 (cur_touch_point_->timestamp - prev_touch_point_->timestamp) / 374 (touch_info_->touch_point.timestamp - prev_touch_point_->timestamp) /
357 kNanoSecondsPerSecond; 375 kNanoSecondsPerSecond;
358 376
359 // If the timestamp does not change, do not update velocity. 377 // If the timestamp does not change, do not update velocity.
360 if (duration < kDelta) 378 if (duration < kDelta)
361 return; 379 return;
362 380
363 gvr::Vec2f displacement = 381 gvr::Vec2f displacement = Vector::Subtract(touch_info_->touch_point.position,
364 Vector::Subtract(cur_touch_point_->position, prev_touch_point_->position); 382 prev_touch_point_->position);
365 383
366 gvr::Vec2f velocity = Vector::ScalarMult(displacement, 1 / duration); 384 gvr::Vec2f velocity = Vector::ScalarMult(displacement, 1 / duration);
367 385
368 float weight = duration / (kRC + duration); 386 float weight = duration / (kRC + duration);
369 387
370 overall_velocity_ = 388 overall_velocity_ =
371 Vector::Add(Vector::ScalarMult(overall_velocity_, 1 - weight), 389 Vector::Add(Vector::ScalarMult(overall_velocity_, 1 - weight),
372 Vector::ScalarMult(velocity, weight)); 390 Vector::ScalarMult(velocity, weight));
373 } 391 }
374 392
375 } // namespace vr_shell 393 } // namespace vr_shell
OLDNEW
« no previous file with comments | « chrome/browser/android/vr_shell/vr_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698