| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |