Merge pull request #120 from mcclure/oculus-quest

Oculus quest support
This commit is contained in:
Bjorn Swenson 2019-05-28 16:30:17 -07:00 committed by GitHub
commit 5ec6f1d1d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 187 additions and 51 deletions

View File

@ -33,7 +33,8 @@ bool lovrPlatformCreateWindow(WindowFlags* flags) {
}
void lovrPlatformGetWindowSize(int* width, int* height) {
*width = *height = 0;
if (width) *width = 0;
if (height) *height = 0;
}
/* Temporarily implemented elsewhere

View File

@ -39,6 +39,7 @@ static bool vrapi_getName(char* buffer, size_t length) {
switch (bridgeLovrMobileData.deviceType) {
case BRIDGE_LOVR_DEVICE_GEAR: name = "Gear VR"; break;
case BRIDGE_LOVR_DEVICE_GO: name = "Oculus Go"; break;
case BRIDGE_LOVR_DEVICE_QUEST: name = "Oculus Quest"; break;
default: return false;
}
@ -74,13 +75,36 @@ static const float* vrapi_getBoundsGeometry(uint32_t* count) {
return NULL;
}
static int getHandIdx(Device device) {
switch (device) {
case DEVICE_HAND:
if (bridgeLovrMobileData.deviceType != BRIDGE_LOVR_DEVICE_GO || bridgeLovrMobileData.updateData.controllerCount <= 0)
return -1;
return 0;
case DEVICE_HAND_LEFT:
case DEVICE_HAND_RIGHT:
if (bridgeLovrMobileData.deviceType == BRIDGE_LOVR_DEVICE_QUEST) {
for(int c = 0; c < BRIDGE_LOVR_CONTROLLERMAX && c < bridgeLovrMobileData.updateData.controllerCount; c++) {
BridgeLovrHand hand = (device == DEVICE_HAND_LEFT ? BRIDGE_LOVR_HAND_LEFT : BRIDGE_LOVR_HAND_RIGHT);
if (bridgeLovrMobileData.updateData.controllers[c].hand & hand)
return c;
}
}
default: // FALLTHROUGH
return -1;
}
}
static bool vrapi_getPose(Device device, vec3 position, quat orientation) {
BridgeLovrPose* pose;
switch (device) {
case DEVICE_HEAD: pose = &bridgeLovrMobileData.updateData.lastHeadPose; break;
case DEVICE_HAND: pose = &bridgeLovrMobileData.updateData.goPose; break;
default: return false;
if (device == DEVICE_HEAD) {
pose = &bridgeLovrMobileData.updateData.lastHeadPose;
} else {
int idx = getHandIdx(device);
if (idx < 0)
return false;
pose = &bridgeLovrMobileData.updateData.controllers[idx].pose;
}
vec3_set(position, pose->x, pose->y + state.offset, pose->z);
@ -92,61 +116,125 @@ static bool vrapi_getBonePose(Device device, DeviceBone bone, vec3 position, qua
return false;
}
static bool vrapi_getVelocity(Device device, vec3 velocity, vec3 angularVelocity) {
BridgeLovrVel* v;
// Shared code for velocity/acceleration
static bool vrapi_getAngularVector(Device device, vec3 linear, vec3 angular, bool isAcceleration) {
BridgeLovrMovement* m;
switch (device) {
case DEVICE_HEAD: v = &bridgeLovrMobileData.updateData.lastHeadVelocity; break;
case DEVICE_HAND: v = &bridgeLovrMobileData.updateData.goVelocity; break;
default: return false;
if (device == DEVICE_HEAD) {
m = &bridgeLovrMobileData.updateData.lastHeadMovement;
} else {
int idx = getHandIdx(device);
if (idx < 0)
return false;
m = &bridgeLovrMobileData.updateData.controllers[idx].movement;
}
vec3_set(velocity, v->x, v->y, v->z);
vec3_set(angularVelocity, v->ax, v->ay, v->az);
BridgeLovrAngularVector* v = isAcceleration ? &m->acceleration : &m->velocity;
vec3_set(linear, v->x, v->y, v->z);
vec3_set(angular, v->ax, v->ay, v->az);
return true;
}
static bool vrapi_getAcceleration(Device device, vec3 acceleration, vec3 angularAcceleration) {
return false;
static bool vrapi_getVelocity(Device device, vec3 velocity, vec3 angularVelocity) {
return vrapi_getAngularVector(device, velocity, angularVelocity, false);
}
static bool buttonCheck(BridgeLovrButton field, Device device, DeviceButton button, bool* result) {
if (device != DEVICE_HAND) {
return false;
static bool vrapi_getAcceleration(Device device, vec3 acceleration, vec3 angularAcceleration) {
return vrapi_getAngularVector(device, acceleration, angularAcceleration, true);
}
static bool buttonDown(BridgeLovrButton field, DeviceButton button, bool *result) {
if (bridgeLovrMobileData.deviceType == BRIDGE_LOVR_DEVICE_QUEST) {
switch (button) {
case BUTTON_MENU: *result = field & BRIDGE_LOVR_BUTTON_MENU; break; // Technically "LMENU" but only fires on left controller
case BUTTON_TRIGGER: *result = field & BRIDGE_LOVR_BUTTON_SHOULDER; break;
case BUTTON_GRIP: *result = field & BRIDGE_LOVR_BUTTON_GRIP; break;
case BUTTON_TOUCHPAD: *result = field & BRIDGE_LOVR_BUTTON_JOYSTICK; break;
case BUTTON_A: *result = field & BRIDGE_LOVR_BUTTON_A; break;
case BUTTON_B: *result = field & BRIDGE_LOVR_BUTTON_B; break;
case BUTTON_X: *result = field & BRIDGE_LOVR_BUTTON_X; break;
case BUTTON_Y: *result = field & BRIDGE_LOVR_BUTTON_Y; break;
default: return false;
}
} else {
switch (button) {
case BUTTON_MENU: *result = field & BRIDGE_LOVR_BUTTON_GOMENU; break; // Technically "RMENU" but quest only has one
case BUTTON_TRIGGER: *result = field & BRIDGE_LOVR_BUTTON_GOSHOULDER; break;
case BUTTON_TOUCHPAD: *result = field & BRIDGE_LOVR_BUTTON_TOUCHPAD; break;
default: return false;
}
}
return true;
}
static bool buttonTouch(BridgeLovrTouch field, DeviceButton button, bool *result) {
// Only Go touch sensor is the touchpad
if (bridgeLovrMobileData.deviceType == BRIDGE_LOVR_DEVICE_GO && button != BUTTON_TOUCHPAD)
return false;
switch (button) {
case BUTTON_MENU: return *result = (field & BRIDGE_LOVR_BUTTON_MENU), true;
case BUTTON_TRIGGER: return *result = (field & BRIDGE_LOVR_BUTTON_SHOULDER), true;
case BUTTON_TOUCHPAD: return *result = (field & BRIDGE_LOVR_BUTTON_TOUCHPAD), true;
case BUTTON_TRIGGER: *result = field & (BRIDGE_LOVR_TOUCH_TRIGGER); break;
case BUTTON_TOUCHPAD: *result = field & (BRIDGE_LOVR_TOUCH_TOUCHPAD | BRIDGE_LOVR_TOUCH_JOYSTICK); break;
case BUTTON_A: *result = field & BRIDGE_LOVR_TOUCH_A; break;
case BUTTON_B: *result = field & BRIDGE_LOVR_TOUCH_B; break;
case BUTTON_X: *result = field & BRIDGE_LOVR_TOUCH_X; break;
case BUTTON_Y: *result = field & BRIDGE_LOVR_TOUCH_Y; break;
default: return false;
}
return true;
}
static bool vrapi_isDown(Device device, DeviceButton button, bool* down) {
return buttonCheck(bridgeLovrMobileData.updateData.goButtonDown, device, button, down);
int idx = getHandIdx(device);
if (idx < 0)
return false;
return buttonDown(bridgeLovrMobileData.updateData.controllers[idx].buttonDown, button, down);
}
static bool vrapi_isTouched(Device device, DeviceButton button, bool* touched) {
return buttonCheck(bridgeLovrMobileData.updateData.goButtonTouch, device, button, touched);
int idx = getHandIdx(device);
if (idx < 0)
return false;
return buttonTouch(bridgeLovrMobileData.updateData.controllers[idx].buttonTouch, button, touched);
}
static bool vrapi_getAxis(Device device, DeviceAxis axis, float* value) {
if (device != DEVICE_HAND) {
int idx = getHandIdx(device);
if (idx < 0)
return false;
}
switch (axis) {
case AXIS_TOUCHPAD:
value[0] = (bridgeLovrMobileData.updateData.goTrackpad.x - 160.f) / 160.f;
value[1] = (bridgeLovrMobileData.updateData.goTrackpad.y - 160.f) / 160.f;
return true;
case AXIS_TRIGGER:
value[0] = bridgeLovrMobileData.updateData.goButtonDown ? 1.f : 0.f;
return true;
default:
return false;
BridgeLovrController *data = &bridgeLovrMobileData.updateData.controllers[idx];
if (bridgeLovrMobileData.deviceType == BRIDGE_LOVR_DEVICE_QUEST) {
switch (axis) {
case AXIS_THUMBSTICK:
value[0] = data->trackpad.x;
value[1] = data->trackpad.y;
break;
case AXIS_TRIGGER: value[0] = data->trigger; break;
case AXIS_GRIP: value[0] = data->grip; break;
default: return false;
}
} else {
switch (axis) {
case AXIS_TOUCHPAD:
value[0] = (data->trackpad.x - 160) / 160.f;
value[1] = (data->trackpad.y - 160) / 160.f;
break;
case AXIS_TRIGGER: {
bool down;
if (!buttonDown(data->buttonDown, BUTTON_TRIGGER, &down))
return false;
value[0] = down ? 1.f : 0.f;
break;
}
default: return false;
}
}
return true;
}
static bool vrapi_vibrate(Device device, float strength, float duration, float frequency) {
@ -199,8 +287,10 @@ double lovrPlatformGetTime(void) {
}
void lovrPlatformGetFramebufferSize(int* width, int* height) {
*width = bridgeLovrMobileData.displayDimensions.width;
*height = bridgeLovrMobileData.displayDimensions.height;
if (width)
*width = bridgeLovrMobileData.displayDimensions.width;
if (height)
*height = bridgeLovrMobileData.displayDimensions.height;
}
bool lovrPlatformHasWindow() {
@ -357,6 +447,8 @@ void bridgeLovrUpdate(BridgeLovrUpdateData *updateData) {
// Unpack update data
bridgeLovrMobileData.updateData = *updateData;
// for(int c = 0; c < updateData->controllerCount; c++) lovrLog("%d: d %x t %x\n", c, (uint32_t)updateData->controllers[c].buttonDown, (uint32_t)updateData->controllers[c].buttonTouch);
if (pauseState == PAUSESTATE_BUG) { // Bad frame-- replace bad time with last known good oculus time
bridgeLovrMobileData.updateData.displayTime = lastPauseAtRaw;
pauseState = PAUSESTATE_RESUME;

View File

@ -29,7 +29,12 @@ typedef struct {
float ax;
float ay;
float az;
} BridgeLovrVel;
} BridgeLovrAngularVector;
typedef struct {
BridgeLovrAngularVector velocity;
BridgeLovrAngularVector acceleration;
} BridgeLovrMovement;
typedef struct {
float x;
@ -41,36 +46,74 @@ typedef enum
{
BRIDGE_LOVR_BUTTON_NONE = 0,
BRIDGE_LOVR_BUTTON_SHOULDER = 0x00000001, // "Set for trigger pulled on the Gear VR and Go Controllers"
BRIDGE_LOVR_BUTTON_TOUCHPAD = 0x00100000, // "Set for touchpad click on the Gear VR and Go Controllers"
BRIDGE_LOVR_BUTTON_MENU = 0x00200000, // "Back button on the headset or Gear VR Controller (only set when a short press comes up)"
BRIDGE_LOVR_BUTTON_GOSHOULDER = 0x00000001, // "Set for trigger pulled on the Gear VR and Go Controllers"
BRIDGE_LOVR_BUTTON_A = 0x00000001, // A
BRIDGE_LOVR_BUTTON_B = 0x00000002, // B
BRIDGE_LOVR_BUTTON_X = 0x00000100, // X
BRIDGE_LOVR_BUTTON_Y = 0x00000200, // Y
BRIDGE_LOVR_BUTTON_TOUCHPAD = 0x00100000, // "Set for touchpad click on the Gear VR and Go Controllers"
BRIDGE_LOVR_BUTTON_MENU = 0x00100000, // On Go this is touchpad, on the Quest it is the menu button
BRIDGE_LOVR_BUTTON_GOMENU = 0x00200000, // "Back button on the headset or Gear VR Controller (only set when a short press comes up)"
BRIDGE_LOVR_BUTTON_GRIP = 0x04000000, // Quest grip
BRIDGE_LOVR_BUTTON_SHOULDER = 0x20000000, // Quest shoulders
BRIDGE_LOVR_BUTTON_JOYSTICK = 0x80000000, // Quest joystick click-down
} BridgeLovrButton;
// Bit identical with VrApi_Input.h ovrButton
typedef enum
{
BRIDGE_LOVR_TOUCH_NONE = 0,
BRIDGE_LOVR_TOUCH_A = 0x00000001, // "The A button has a finger resting on it."
BRIDGE_LOVR_TOUCH_B = 0x00000002, // "The B button has a finger resting on it."
BRIDGE_LOVR_TOUCH_X = 0x00000004, // "The X button has a finger resting on it."
BRIDGE_LOVR_TOUCH_Y = 0x00000008, // "The Y button has a finger resting on it."
BRIDGE_LOVR_TOUCH_TOUCHPAD = 0x00000010, // "The TrackPad has a finger resting on it."
BRIDGE_LOVR_TOUCH_JOYSTICK = 0x00000020, // "The Joystick has a finger resting on it."
BRIDGE_LOVR_TOUCH_TRIGGER = 0x00000040, // "The Index Trigger has a finger resting on it."
BRIDGE_LOVR_TOUCH_FACE_ANTI = 0x00000100, // "None of A, B, X, Y, or Joystick has a finger/thumb in proximity to it"
BRIDGE_LOVR_TOUCH_TRIGGER_ANTI = 0x00000200, // "The finger is sufficiently far away from the trigger to not be considered in proximity to it."
} BridgeLovrTouch;
// Bit identical with VrApi_Input.h ovrControllerCapabilties
typedef enum {
BRIDGE_LOVR_HAND_LEFT = 0x00000004,
BRIDGE_LOVR_HAND_RIGHT = 0x00000008,
} BridgeLovrHand;
// Values identical with headset.h HeadsetType
typedef enum
{
BRIDGE_LOVR_DEVICE_UNKNOWN,
BRIDGE_LOVR_DEVICE_GEAR = 3,
BRIDGE_LOVR_DEVICE_GO = 4
BRIDGE_LOVR_DEVICE_GO = 4,
BRIDGE_LOVR_DEVICE_QUEST = 5,
} BridgeLovrDevice;
typedef struct {
bool handset;
BridgeLovrHand hand;
BridgeLovrPose pose;
BridgeLovrMovement movement;
BridgeLovrTrackpad trackpad;
float trigger, grip;
BridgeLovrButton buttonDown;
BridgeLovrTouch buttonTouch;
} BridgeLovrController;
#define BRIDGE_LOVR_CONTROLLERMAX 3
// Data passed from Lovr_NativeActivity to BridgeLovr at update time
typedef struct {
double displayTime; // Projected
BridgeLovrPose lastHeadPose;
BridgeLovrVel lastHeadVelocity;
BridgeLovrMovement lastHeadMovement;
float eyeViewMatrix[2][16];
float projectionMatrix[2][16];
// TODO: Controller object
bool goPresent;
BridgeLovrPose goPose;
BridgeLovrVel goVelocity;
BridgeLovrTrackpad goTrackpad;
bool goTrackpadTouch;
BridgeLovrButton goButtonDown;
BridgeLovrButton goButtonTouch;
int controllerCount;
BridgeLovrController controllers[BRIDGE_LOVR_CONTROLLERMAX];
} BridgeLovrUpdateData;
// Data passed from Lovr_NativeActivity to BridgeLovr at init time