OpenVR: Added hysteresis to the touch pad dead spot

This should make using the Vive touch pad for movement more reliable.
This commit is contained in:
Anthony Thibault 2016-02-26 18:34:33 -08:00
parent 01ef5aabcb
commit 89885805d2
2 changed files with 54 additions and 21 deletions

View file

@ -234,8 +234,8 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle
auto rightHandDeviceIndex = _system->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
if (!jointsCaptured) {
handleHandController(leftHandDeviceIndex, inputCalibrationData, true);
handleHandController(rightHandDeviceIndex, inputCalibrationData, false);
handleHandController(deltaTime, leftHandDeviceIndex, inputCalibrationData, true);
handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false);
}
int numTrackedControllers = 0;
@ -248,7 +248,7 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle
_trackedControllers = numTrackedControllers;
}
void ViveControllerManager::InputDevice::handleHandController(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) {
void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) {
if (_system->IsTrackedDeviceConnected(deviceIndex) &&
_system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_Controller &&
@ -258,7 +258,7 @@ void ViveControllerManager::InputDevice::handleHandController(uint32_t deviceInd
const mat4& mat = _trackedDevicePoseMat4[deviceIndex];
const vec3 linearVelocity = _trackedDeviceLinearVelocities[deviceIndex];
const vec3 angularVelocity = _trackedDeviceAngularVelocities[deviceIndex];
handlePoseEvent(inputCalibrationData, mat, linearVelocity, angularVelocity, isLeftHand);
handlePoseEvent(deltaTime, inputCalibrationData, mat, linearVelocity, angularVelocity, isLeftHand);
vr::VRControllerState_t controllerState = vr::VRControllerState_t();
if (_system->GetControllerState(deviceIndex, &controllerState)) {
@ -267,12 +267,12 @@ void ViveControllerManager::InputDevice::handleHandController(uint32_t deviceInd
for (uint32_t i = 0; i < vr::k_EButton_Max; ++i) {
auto mask = vr::ButtonMaskFromId((vr::EVRButtonId)i);
bool pressed = 0 != (controllerState.ulButtonPressed & mask);
handleButtonEvent(i, pressed, isLeftHand);
handleButtonEvent(deltaTime, i, pressed, isLeftHand);
}
// process each axis
for (uint32_t i = 0; i < vr::k_unControllerStateAxisCount; i++) {
handleAxisEvent(i, controllerState.rAxis[i].x, controllerState.rAxis[i].y, isLeftHand);
handleAxisEvent(deltaTime, i, controllerState.rAxis[i].x, controllerState.rAxis[i].y, isLeftHand);
}
}
}
@ -284,36 +284,44 @@ void ViveControllerManager::InputDevice::focusOutEvent() {
};
// These functions do translation from the Steam IDs to the standard controller IDs
void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x, float y, bool isLeftHand) {
void ViveControllerManager::InputDevice::handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand) {
//FIX ME? It enters here every frame: probably we want to enter only if an event occurs
axis += vr::k_EButton_Axis0;
using namespace controller;
if (axis == vr::k_EButton_SteamVR_Touchpad) {
_axisStateMap[isLeftHand ? LX : RX] = x;
_axisStateMap[isLeftHand ? LY : RY] = y;
glm::vec2 stick(x, y);
if (isLeftHand) {
stick = _filteredLeftStick.process(deltaTime, stick);
} else {
stick = _filteredRightStick.process(deltaTime, stick);
}
_axisStateMap[isLeftHand ? LX : RX] = stick.x;
_axisStateMap[isLeftHand ? LY : RY] = stick.y;
} else if (axis == vr::k_EButton_SteamVR_Trigger) {
_axisStateMap[isLeftHand ? LT : RT] = x;
}
}
// These functions do translation from the Steam IDs to the standard controller IDs
void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool pressed, bool isLeftHand) {
void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool isLeftHand) {
if (!pressed) {
return;
}
using namespace controller;
if (button == vr::k_EButton_ApplicationMenu) {
_buttonPressedMap.insert(isLeftHand ? controller::LEFT_PRIMARY_THUMB : controller::RIGHT_PRIMARY_THUMB);
_buttonPressedMap.insert(isLeftHand ? LEFT_PRIMARY_THUMB : RIGHT_PRIMARY_THUMB);
} else if (button == vr::k_EButton_Grip) {
_buttonPressedMap.insert(isLeftHand ? controller::LB : controller::RB);
_buttonPressedMap.insert(isLeftHand ? LB : RB);
} else if (button == vr::k_EButton_SteamVR_Trigger) {
_buttonPressedMap.insert(isLeftHand ? controller::LT : controller::RT);
_buttonPressedMap.insert(isLeftHand ? LT : RT);
} else if (button == vr::k_EButton_SteamVR_Touchpad) {
_buttonPressedMap.insert(isLeftHand ? controller::LS : controller::RS);
_buttonPressedMap.insert(isLeftHand ? LS : RS);
}
}
void ViveControllerManager::InputDevice::handlePoseEvent(const controller::InputCalibrationData& inputCalibrationData,
void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData,
const mat4& mat, const vec3& linearVelocity,
const vec3& angularVelocity, bool isLeftHand) {
// When the sensor-to-world rotation is identity the coordinate axes look like this:

View file

@ -58,12 +58,39 @@ private:
virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
virtual void focusOutEvent() override;
void handleHandController(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand);
void handleButtonEvent(uint32_t button, bool pressed, bool isLeftHand);
void handleAxisEvent(uint32_t axis, float x, float y, bool isLeftHand);
void handlePoseEvent(const controller::InputCalibrationData& inputCalibrationData, const mat4& mat,
void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand);
void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool isLeftHand);
void handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand);
void handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const mat4& mat,
const vec3& linearVelocity, const vec3& angularVelocity, bool isLeftHand);
class FilteredStick {
public:
glm::vec2 process(float deltaTime, const glm::vec2& stick) {
// Use a timer to prevent the stick going to back to zero.
// This to work around the noisy touch pad that will flash back to zero breifly
const float ZERO_HYSTERESIS_PERIOD = 0.2f; // 200 ms
if (glm::length(stick) == 0.0f) {
if (_timer <= 0.0f) {
return glm::vec2(0.0f, 0.0f);
} else {
_timer -= deltaTime;
return _stick;
}
} else {
_timer = ZERO_HYSTERESIS_PERIOD;
_stick = stick;
return stick;
}
}
protected:
float _timer { 0.0f };
glm::vec2 _stick { 0.0f, 0.0f };
};
FilteredStick _filteredLeftStick;
FilteredStick _filteredRightStick;
int _trackedControllers { 0 };
vr::IVRSystem*& _system;
friend class ViveControllerManager;
@ -71,8 +98,6 @@ private:
void renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign);
bool _registeredWithInputMapper { false };
bool _modelLoaded { false };
model::Geometry _modelGeometry;