Skip to content

Commit

Permalink
Making Oculus Quest support haptic feedback.
Browse files Browse the repository at this point in the history
  • Loading branch information
daoshengmu committed Nov 14, 2019
1 parent f695b88 commit e758ae9
Showing 1 changed file with 53 additions and 2 deletions.
55 changes: 53 additions & 2 deletions app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,9 @@ struct DeviceDelegateOculusVR::State {
ovrInputTrackedRemoteCapabilities capabilities = {};
vrb::Matrix transform = vrb::Matrix::Identity();
ovrInputStateTrackedRemote inputState = {};
uint64_t inputFrameID = 0;
float remainingVibrateTime = 0.0f;
double lastHapticUpdateTimeStamp = 0.0f;

bool Is6DOF() const {
return (capabilities.ControllerCapabilities & ovrControllerCaps_HasPositionTracking) &&
Expand Down Expand Up @@ -689,7 +692,6 @@ struct DeviceDelegateOculusVR::State {
device::CPULevel minCPULevel = device::CPULevel::Normal;
device::DeviceType deviceType = device::UnknownType;


void UpdatePerspective() {
float fovX = vrapi_GetSystemPropertyFloat(&java, VRAPI_SYS_PROP_SUGGESTED_EYE_FOV_DEGREES_X);
float fovY = vrapi_GetSystemPropertyFloat(&java, VRAPI_SYS_PROP_SUGGESTED_EYE_FOV_DEGREES_Y);
Expand Down Expand Up @@ -965,6 +967,16 @@ struct DeviceDelegateOculusVR::State {
}
}

double GetTimeStamp() {
timespec spec = {};
const double kNanosecondsToSeconds = 1.0e9;
double timeStamp = 0.0f;
if (clock_gettime(CLOCK_MONOTONIC, &spec) == 0) {
timeStamp = (double) spec.tv_sec + (spec.tv_nsec / kNanosecondsToSeconds);
}
return timeStamp;
}

void UpdateControllers(const vrb::Matrix & head) {
UpdateDeviceId();
if (!controller) {
Expand Down Expand Up @@ -1034,7 +1046,6 @@ struct DeviceDelegateOculusVR::State {
const bool yTouched = (controllerState.inputState.Touches & ovrTouch_Y) != 0;
const bool menuPressed = (controllerState.inputState.Buttons & ovrButton_Enter) != 0;


controller->SetButtonState(controllerState.index, ControllerDelegate::BUTTON_X, 3, xPressed, xTouched);
controller->SetButtonState(controllerState.index, ControllerDelegate::BUTTON_Y, 4, yPressed, yTouched);

Expand All @@ -1061,6 +1072,46 @@ struct DeviceDelegateOculusVR::State {

const bool thumbRest = (controllerState.inputState.Touches & ovrTouch_ThumbUp) != 0;
controller->SetButtonState(controllerState.index, ControllerDelegate::BUTTON_OTHERS, 5, thumbRest, thumbRest);

// Only Oculus 6 DOF (Quest) has haptic feedback.
controller->SetHapticCount(controllerState.index, 1);
uint64_t inputFrameID = 0;
float pulseDuration = 0.0f, pulseIntensity = 0.0f;
controller->GetHapticFeedback(controllerState.index, inputFrameID, pulseDuration, pulseIntensity);
if (inputFrameID > 0 && pulseIntensity > 0.0f && pulseDuration > 0) {
if (controllerState.inputFrameID != inputFrameID) {
// When there is a new input frame id from haptic vibration,
// that means we start a new session for a vibration.
controllerState.inputFrameID = inputFrameID;
controllerState.remainingVibrateTime = pulseDuration;
controllerState.lastHapticUpdateTimeStamp = GetTimeStamp();
} else {
// We are still running the previous vibration.
// So, it needs to reduce the delta time from the last vibration.
const double timeStamp = GetTimeStamp();
controllerState.remainingVibrateTime -= (timeStamp - controllerState.lastHapticUpdateTimeStamp);
controllerState.lastHapticUpdateTimeStamp = timeStamp;
}
if (controllerState.remainingVibrateTime > 0.0f) {
if (vrapi_SetHapticVibrationSimple(ovr, controllerState.index, pulseIntensity > 1.0f ? 1.0f : pulseIntensity)
== ovrError_InvalidOperation) {
VRB_ERROR("vrapi_SetHapticVibrationBuffer failed.");
}
} else {
// The remaining time is zero, stop the vibration.
if (vrapi_SetHapticVibrationSimple(ovr, controllerState.index, 0.0f) == ovrError_InvalidOperation) {
VRB_ERROR("vrapi_SetHapticVibrationBuffer failed.");
}
controllerState.remainingVibrateTime = 0.0f;
}
} else if (controllerState.remainingVibrateTime > 0.0f) {
// While the haptic feedback is terminated from the client side,
// but it still have remaining time, we need to ask for stopping vibration.
if (vrapi_SetHapticVibrationSimple(ovr, controllerState.index, 0.0f) == ovrError_InvalidOperation) {
VRB_ERROR("vrapi_SetHapticVibrationBuffer failed.");
}
controllerState.remainingVibrateTime = 0.0f;
}
} else {
triggerPressed = (controllerState.inputState.Buttons & ovrButton_A) != 0;
triggerTouched = triggerPressed;
Expand Down

0 comments on commit e758ae9

Please sign in to comment.