Change everything;

Use enums because they make things easier.
This commit is contained in:
bjorn 2019-05-07 20:04:59 -07:00
parent b86340ac69
commit 05f4ba7342
8 changed files with 476 additions and 384 deletions

View File

@ -27,6 +27,74 @@ const char* HeadsetOrigins[] = {
NULL
};
const char* Devices[] = {
[DEVICE_HEAD] = "head",
[DEVICE_HAND] = "hand",
[DEVICE_HAND_LEFT] = "hand/left",
[DEVICE_HAND_RIGHT] = "hand/right",
[DEVICE_EYE_LEFT] = "eye/left",
[DEVICE_EYE_RIGHT] = "eye/left",
[DEVICE_TRACKER_1] = "tracker/1",
[DEVICE_TRACKER_2] = "tracker/2",
[DEVICE_TRACKER_3] = "tracker/3",
[DEVICE_TRACKER_4] = "tracker/4",
NULL
};
const char* DeviceButtons[] = {
[BUTTON_TRIGGER] = "trigger",
[BUTTON_THUMBSTICK] = "thumbstick",
[BUTTON_TRACKPAD] = "trackpad",
[BUTTON_GRIP] = "grip",
[BUTTON_MENU] = "menu",
[BUTTON_A] = "a",
[BUTTON_B] = "b",
[BUTTON_X] = "x",
[BUTTON_Y] = "y",
[BUTTON_PROXIMITY] = "proximity",
NULL
};
const char* DeviceAxes[] = {
[AXIS_TRIGGER] = "trigger",
[AXIS_THUMBSTICK_X] = "thumbstick/x",
[AXIS_THUMBSTICK_Y] = "thumbstick/y",
[AXIS_TRACKPAD_X] = "trackpad/x",
[AXIS_TRACKPAD_Y] = "trackpad/y",
[AXIS_PINCH] = "pinch",
[AXIS_GRIP] = "grip",
NULL
};
const char* DeviceBones[] = {
[BONE_THUMB] = "thumb",
[BONE_INDEX] = "index",
[BONE_MIDDLE] = "middle",
[BONE_RING] = "ring",
[BONE_PINKY] = "pinky",
[BONE_THUMB_NULL] = "thumb/null",
[BONE_THUMB_1] = "thumb/1",
[BONE_THUMB_2] = "thumb/2",
[BONE_THUMB_3] = "thumb/3",
[BONE_INDEX_1] = "index/1",
[BONE_INDEX_2] = "index/2",
[BONE_INDEX_3] = "index/3",
[BONE_INDEX_4] = "index/4",
[BONE_MIDDLE_1] = "middle/1",
[BONE_MIDDLE_2] = "middle/2",
[BONE_MIDDLE_3] = "middle/3",
[BONE_MIDDLE_4] = "middle/4",
[BONE_RING_1] = "ring/1",
[BONE_RING_2] = "ring/2",
[BONE_RING_3] = "ring/3",
[BONE_RING_4] = "ring/4",
[BONE_PINKY_1] = "pinky/1",
[BONE_PINKY_2] = "pinky/2",
[BONE_PINKY_3] = "pinky/3",
[BONE_PINKY_4] = "pinky/4",
NULL
};
typedef struct {
lua_State* L;
int ref;
@ -34,11 +102,6 @@ typedef struct {
static HeadsetRenderData headsetRenderData;
static const char* luax_optpath(lua_State* L, int index) {
const char* str = luaL_optstring(L, index, "head");
return str[0] == '/' ? ++str : str;
}
static void renderHelper(void* userdata) {
HeadsetRenderData* renderData = userdata;
lua_State* L = renderData->L;
@ -162,10 +225,10 @@ static int l_lovrHeadsetGetBoundsGeometry(lua_State* L) {
}
int l_lovrHeadsetGetPose(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
float position[3], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(path, position, orientation)) {
if (driver->getPose(device, position, orientation)) {
float angle, ax, ay, az;
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
lua_pushnumber(L, position[0]);
@ -182,10 +245,10 @@ int l_lovrHeadsetGetPose(lua_State* L) {
}
int l_lovrHeadsetGetPosition(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
float position[3];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(path, position, NULL)) {
if (driver->getPose(device, position, NULL)) {
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
@ -196,10 +259,10 @@ int l_lovrHeadsetGetPosition(lua_State* L) {
}
int l_lovrHeadsetGetOrientation(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
float orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(path, NULL, orientation)) {
if (driver->getPose(device, NULL, orientation)) {
float angle, ax, ay, az;
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
lua_pushnumber(L, angle);
@ -213,10 +276,10 @@ int l_lovrHeadsetGetOrientation(lua_State* L) {
}
int l_lovrHeadsetGetDirection(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
float orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(path, NULL, orientation)) {
if (driver->getPose(device, NULL, orientation)) {
float v[3] = { 0.f, 0.f, -1.f };
quat_rotate(orientation, v);
lua_pushnumber(L, v[0]);
@ -229,10 +292,10 @@ int l_lovrHeadsetGetDirection(lua_State* L) {
}
int l_lovrHeadsetGetVelocity(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
float velocity[3];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getVelocity(path, velocity, NULL)) {
if (driver->getVelocity(device, velocity, NULL)) {
lua_pushnumber(L, velocity[0]);
lua_pushnumber(L, velocity[1]);
lua_pushnumber(L, velocity[2]);
@ -243,10 +306,10 @@ int l_lovrHeadsetGetVelocity(lua_State* L) {
}
int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
float angularVelocity[3];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getVelocity(path, NULL, angularVelocity)) {
if (driver->getVelocity(device, NULL, angularVelocity)) {
lua_pushnumber(L, angularVelocity[0]);
lua_pushnumber(L, angularVelocity[1]);
lua_pushnumber(L, angularVelocity[2]);
@ -257,10 +320,11 @@ int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
}
int l_lovrHeadsetIsDown(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
DeviceButton button = luaL_checkoption(L, 2, NULL, DeviceButtons);
bool down;
FOREACH_TRACKING_DRIVER(driver) {
if (driver->isDown(path, &down)) {
if (driver->isDown(device, button, &down)) {
lua_pushboolean(L, down);
return 1;
}
@ -269,10 +333,11 @@ int l_lovrHeadsetIsDown(lua_State* L) {
}
int l_lovrHeadsetIsTouched(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
DeviceButton button = luaL_checkoption(L, 2, NULL, DeviceButtons);
bool touched;
FOREACH_TRACKING_DRIVER(driver) {
if (driver->isDown(path, &touched)) {
if (driver->isDown(device, button, &touched)) {
lua_pushboolean(L, touched);
return 1;
}
@ -281,28 +346,25 @@ int l_lovrHeadsetIsTouched(lua_State* L) {
}
int l_lovrHeadsetGetAxis(lua_State* L) {
const char* path = luax_optpath(L, 1);
float x, y, z;
int count;
Device device = luaL_checkoption(L, 1, "head", Devices);
DeviceAxis axis = luaL_checkoption(L, 2, NULL, DeviceAxes);
float value;
FOREACH_TRACKING_DRIVER(driver) {
if ((count = driver->getAxis(path, &x, &y, &z)) > 0) {
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
lua_pop(L, 3 - count);
return count;
if (driver->getAxis(device, axis, &value)) {
lua_pushnumber(L, value);
return 1;
}
}
return 0;
}
int l_lovrHeadsetVibrate(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
float strength = luax_optfloat(L, 2, 1.f);
float duration = luax_optfloat(L, 3, .5f);
float frequency = luax_optfloat(L, 4, 0.f);
FOREACH_TRACKING_DRIVER(driver) {
if (driver->vibrate(path, strength, duration, frequency)) {
if (driver->vibrate(device, strength, duration, frequency)) {
lua_pushboolean(L, true);
return 1;
}
@ -312,11 +374,11 @@ int l_lovrHeadsetVibrate(lua_State* L) {
}
int l_lovrHeadsetNewModel(lua_State* L) {
const char* path = luax_optpath(L, 1);
Device device = luaL_checkoption(L, 1, "head", Devices);
ModelData* modelData = NULL;
FOREACH_TRACKING_DRIVER(driver) {
if ((modelData = driver->newModelData(path)) != NULL) {
if ((modelData = driver->newModelData(device)) != NULL) {
break;
}
}

View File

@ -74,16 +74,13 @@ static const float* desktop_getBoundsGeometry(int* count) {
return NULL;
}
static bool desktop_getPose(const char* path, vec3 position, quat orientation) {
bool head = !strcmp(path, "head");
bool hand = !strcmp(path, "hand/left") || !strcmp(path, "hand/right");
if (!head && !hand) {
static bool desktop_getPose(Device device, vec3 position, quat orientation) {
if (device != DEVICE_HEAD && device != DEVICE_HAND) {
return false;
}
if (position) {
vec3_set(position, 0.f, 0.f, hand ? -.75f : 0.f);
vec3_set(position, 0.f, 0.f, device == DEVICE_HAND ? -.75f : 0.f);
mat4_transform(state.transform, &position[0], &position[1], &position[2]);
}
@ -94,8 +91,8 @@ static bool desktop_getPose(const char* path, vec3 position, quat orientation) {
return true;
}
static bool desktop_getVelocity(const char* path, vec3 velocity, vec3 angularVelocity) {
if (strcmp(path, "head")) {
static bool desktop_getVelocity(Device device, vec3 velocity, vec3 angularVelocity) {
if (device != DEVICE_HEAD) {
return false;
}
@ -110,28 +107,28 @@ static bool desktop_getVelocity(const char* path, vec3 velocity, vec3 angularVel
return true;
}
static bool desktop_isDown(const char* path, bool* down) {
if (!strcmp(path, "hand/left/trigger") || !strcmp(path, "hand/right/trigger")) {
*down = lovrPlatformIsMouseDown(MOUSE_RIGHT);
return true;
static bool desktop_isDown(Device device, DeviceButton button, bool* down) {
if (device != DEVICE_HAND || button != BUTTON_TRIGGER) {
return false;
}
*down = lovrPlatformIsMouseDown(MOUSE_RIGHT);
return true;
}
static bool desktop_isTouched(Device device, DeviceButton button, bool* touched) {
return false;
}
static bool desktop_isTouched(const char* path, bool* touched) {
static bool desktop_getAxis(Device device, DeviceAxis axis, float* value) {
return false;
}
static int desktop_getAxis(const char* path, float* x, float* y, float* z) {
return 0;
}
static bool desktop_vibrate(const char* path, float strength, float duration, float frequency) {
static bool desktop_vibrate(Device device, float strength, float duration, float frequency) {
return false;
}
static ModelData* desktop_newModelData(const char* path) {
static ModelData* desktop_newModelData(Device device) {
return NULL;
}

View File

@ -23,6 +23,70 @@ typedef enum {
DRIVER_WEBVR
} HeadsetDriver;
typedef enum {
DEVICE_HEAD,
DEVICE_HAND,
DEVICE_HAND_LEFT,
DEVICE_HAND_RIGHT,
DEVICE_EYE_LEFT,
DEVICE_EYE_RIGHT,
DEVICE_TRACKER_1,
DEVICE_TRACKER_2,
DEVICE_TRACKER_3,
DEVICE_TRACKER_4
} Device;
typedef enum {
BUTTON_TRIGGER,
BUTTON_THUMBSTICK,
BUTTON_TRACKPAD,
BUTTON_GRIP,
BUTTON_MENU,
BUTTON_A,
BUTTON_B,
BUTTON_X,
BUTTON_Y,
BUTTON_PROXIMITY
} DeviceButton;
typedef enum {
AXIS_TRIGGER,
AXIS_THUMBSTICK_X,
AXIS_THUMBSTICK_Y,
AXIS_TRACKPAD_X,
AXIS_TRACKPAD_Y,
AXIS_PINCH,
AXIS_GRIP
} DeviceAxis;
typedef enum {
BONE_THUMB,
BONE_INDEX,
BONE_MIDDLE,
BONE_RING,
BONE_PINKY,
BONE_THUMB_NULL,
BONE_THUMB_1,
BONE_THUMB_2,
BONE_THUMB_3,
BONE_INDEX_1,
BONE_INDEX_2,
BONE_INDEX_3,
BONE_INDEX_4,
BONE_MIDDLE_1,
BONE_MIDDLE_2,
BONE_MIDDLE_3,
BONE_MIDDLE_4,
BONE_RING_1,
BONE_RING_2,
BONE_RING_3,
BONE_RING_4,
BONE_PINKY_1,
BONE_PINKY_2,
BONE_PINKY_3,
BONE_PINKY_4
} DeviceBone;
typedef struct HeadsetInterface {
struct HeadsetInterface* next;
HeadsetDriver driverType;
@ -36,13 +100,14 @@ typedef struct HeadsetInterface {
void (*setClipDistance)(float clipNear, float clipFar);
void (*getBoundsDimensions)(float* width, float* depth);
const float* (*getBoundsGeometry)(int* count);
bool (*getPose)(const char* path, float* position, float* orientation);
bool (*getVelocity)(const char* path, float* velocity, float* angularVelocity);
bool (*isDown)(const char* path, bool* down);
bool (*isTouched)(const char* path, bool* touched);
int (*getAxis)(const char* path, float* x, float* y, float* z);
bool (*vibrate)(const char* path, float strength, float duration, float frequency);
struct ModelData* (*newModelData)(const char* path);
bool (*getPose)(Device device, float* position, float* orientation);
bool (*getBonePose)(Device device, DeviceBone bone, float* position, float* orientation);
bool (*getVelocity)(Device device, float* velocity, float* angularVelocity);
bool (*isDown)(Device device, DeviceButton button, bool* down);
bool (*isTouched)(Device device, DeviceButton button, bool* touched);
bool (*getAxis)(Device device, DeviceAxis axis, float* value);
bool (*vibrate)(Device device, float strength, float duration, float frequency);
struct ModelData* (*newModelData)(Device device);
void (*renderTo)(void (*callback)(void*), void* userdata);
struct Texture* (*getMirrorTexture)(void);
void (*update)(float dt);

View File

@ -62,76 +62,72 @@ static void leap_destroy(void) {
memset(&state, 0, sizeof(state));
}
static bool leap_getPose(const char* path, vec3 position, quat orientation) {
LEAP_HAND* hand;
if (state.leftHand && !strncmp("hand/left", path, strlen("hand/left"))) {
hand = state.leftHand;
path += strlen("hand/left");
} else if (state.rightHand && !strncmp("hand/right", path, strlen("hand/right"))) {
hand = state.rightHand;
path += strlen("hand/right");
} else {
return false;
}
static void adjustPose(vec3 position, vec3 direction) {
float temp;
float direction[3];
if (*path == '\0') {
vec3_set(position, hand->palm.position.x, hand->palm.position.z, hand->palm.position.y);
vec3_init(direction, hand->palm.normal.v);
} else if (!strncmp("/finger/", path, strlen("/finger/"))) {
path += strlen("/finger/");
int fingerIndex;
if (!strncmp("thumb", path, strlen("thumb"))) { fingerIndex = 0; path += strlen("thumb"); }
else if (!strncmp("index", path, strlen("index"))) { fingerIndex = 1; path += strlen("index"); }
else if (!strncmp("middle", path, strlen("middle"))) { fingerIndex = 2; path += strlen("middle"); }
else if (!strncmp("ring", path, strlen("ring"))) { fingerIndex = 3; path += strlen("ring"); }
else if (!strncmp("pinky", path, strlen("pinky"))) { fingerIndex = 4; path += strlen("pinky"); }
else { return false; }
LEAP_DIGIT* finger = &hand->digits[fingerIndex];
vec3 base;
vec3 tip;
if (*path == '\0') {
tip = finger->distal.next_joint.v;
base = finger->distal.prev_joint.v;
vec3_set(position, tip[0], tip[2], tip[1]);
} else if (!strncmp("/bone/", path, strlen("/bone/"))) {
path += strlen("/bone/");
int boneIndex;
if (!strcmp(path, "metacarpal")) { boneIndex = 0; }
else if (!strcmp(path, "proximal")) { boneIndex = 1; }
else if (!strcmp(path, "intermediate")) { boneIndex = 2; }
else if (!strcmp(path, "distal")) { boneIndex = 3; }
else { return false; }
LEAP_BONE* bone = &finger->bones[boneIndex];
tip = bone->next_joint.v;
base = bone->prev_joint.v;
vec3_set(position, base[0], base[2], base[1]);
} else {
return false;
}
vec3_sub(vec3_init(direction, tip), base);
}
// Convert hand positions to meters, and push them back a bit to account for the discrepancy
// between the leap motion device and the HMD
// Convert units from mm to meters, apply a z offset (leap is in front of HMD), and swap y/z
vec3_scale(position, -.001f);
temp = position[1];
position[1] = position[2];
position[2] = position[1];
position[2] -= .080f;
mat4_transform(state.headPose, &position[0], &position[1], &position[2]);
// Just swap y/z
vec3_normalize(direction);
vec3_scale(direction, -1.f);
float temp = direction[1];
temp = direction[1];
direction[1] = direction[2];
direction[2] = temp;
mat4_transformDirection(state.headPose, &direction[0], &direction[1], &direction[2]);
}
static bool leap_getPose(Device device, vec3 position, quat orientation) {
LEAP_HAND* hand;
switch (device) {
case DEVICE_HAND_LEFT: hand = state.leftHand; break;
case DEVICE_HAND_RIGHT: hand = state.rightHand; break;
default: return false;
}
float direction[3];
vec3_init(position, hand->palm.position);
vec3_init(direction, hand->palm.normal.v);
adjustPose(position, direction);
quat_between(orientation, (float[3]) { 0.f, 0.f, -1.f }, direction);
return true;
}
static bool leap_getBonePose(Device device, DeviceBone bone, vec3 position, quat orientation) {
LEAP_HAND* hand;
switch (device) {
case DEVICE_HAND_LEFT: hand = state.leftHand; break;
case DEVICE_HAND_RIGHT: hand = state.rightHand; break;
default: return false;
}
// Assumes that enum values for non-tip bones are grouped by finger, and start after BONE_PINKY,
// could be less clever and use a switch if needed
float direction[3];
if (bone <= BONE_PINKY) {
LEAP_DIGIT* finger = &hand->digits[bone];
vec3 base = finger->distal.prev_joint.v;
vec3 tip = finger->distal.next_joint.v;
vec3_sub(vec3_init(direction, tip), base);
vec3_init(position, tip);
} else {
bone -= BONE_PINKY + 1;
LEAP_DIGIT* finger = &hand->digits[bone / 4];
LEAP_BONE* leapBone = finger->bones[bone % 4];
vec3 base = leapBone->prev_joint.v;
vec3 tip = leapBone->next_joint.v;
vec3_sub(vec3_init(direction, tip), base);
vec3_init(position, base);
}
adjustPose(position, direction);
quat_between(orientation, (float[3]) { 0.f, 0.f, -1.f }, direction);
return true;
}
@ -235,6 +231,7 @@ HeadsetInterface lovrHeadsetLeapMotionDriver = {
.init = leap_init,
.destroy = leap_destroy,
.getPose = leap_getPose,
.getBonePose = leap_getBonePose,
.getVelocity = leap_getVelocity,
.isDown = leap_isDown,
.getAxis = leap_getAxis,

View File

@ -163,18 +163,15 @@ static const float* oculus_getBoundsGeometry(int* count) {
return NULL;
}
static bool oculus_getPose(const char* path, vec3 position, quat orientation) {
static bool oculus_getPose(Device device, vec3 position, quat orientation) {
ovrTrackingState *ts = refreshTracking();
ovrPosef* pose;
if (!strcmp(path, "head")) {
pose = &ts->HeadPose.ThePose;
} else if (!strcmp(path, "hand/left")) {
pose = &ts->HandPoses[0].ThePose;
} else if (!strcmp(path, "hand/right")) {
pose = &ts->HandPoses[1].ThePose;
} else {
return false;
switch (device) {
case DEVICE_HEAD: pose = &ts->HeadPose.ThePose; break;
case DEVICE_HAND_LEFT: pose = &ts->HandPoses[ovrHand_Left].ThePose; break;
case DEVICE_HAND_RIGHT: pose = &ts->HandPoses[ovrHand_Right].ThePose; break;
default: return false;
}
if (position) {
@ -192,14 +189,11 @@ static bool oculus_getVelocity(const char* path, vec3 velocity, vec3 angularVelo
ovrTrackingState *ts = refreshTracking();
ovrPoseStatef* pose;
if (!strcmp(path, "head")) {
pose = &ts->HeadPose;
} else if (!strcmp(path, "hand/left")) {
pose = &ts->HandPoses[ovrHand_Left];
} else if (!strcmp(path, "hand/right")) {
pose = &ts->HandPoses[ovrHand_Right];
} else {
return false;
switch (device) {
case DEVICE_HEAD: pose = &ts->HeadPose; break;
case DEVICE_HAND_LEFT: pose = &ts->HandPoses[ovrHand_Left]; break;
case DEVICE_HAND_RIGHT: pose = &ts->HandPoses[ovrHand_Right]; break;
default: return false;
}
if (velocity) {
@ -213,86 +207,75 @@ static bool oculus_getVelocity(const char* path, vec3 velocity, vec3 angularVelo
return true;
}
static bool getHandInfo(const char* path, ovrHandType* hand, uint32_t* mask, const char** next) {
if (!strncmp("hand/left", path, strlen("hand/left"))) {
*hand = ovrHand_Left;
*mask = ovrButton_LMask;
*next = path + strlen("hand/left/");
return true;
} else if (!strncmp("hand/right", path, strlen("hand/right"))) {
*hand = ovrHand_Right;
*mask = ovrButton_RMask;
*next = path + strlen("hand/right/");
return true;
} else {
return false;
}
}
static bool oculus_isDown(const char* path, bool* down) {
if (!strcmp(path, "head/proximity")) {
static bool oculus_isDown(Device device, DeviceButton button, bool* down) {
if (device == DEVICE_HEAD && button == BUTTON_PROXIMITY) {
ovrSessionStatus status;
ovr_GetSessionStatus(state.session, &status);
*down = status.HmdMounted;
return true;
} else if (device != DEVICE_HAND_LEFT && device != DEVICE_HAND_RIGHT) {
return false;
}
ovrHandType hand;
uint32_t mask;
const char* button;
ovrInputState* is = refreshButtons();
ovrHand hand = device == DEVICE_HAND_LEFT ? ovrHand_Left : ovrHand_Right;
uint32_t buttons = is->Buttons & (device == DEVICE_HAND_LEFT ? ovrButton_LMask : ovrButton_RMask);
if (getHandInfo(path, &hand, &mask, &button)) {
ovrInputState* is = refreshButtons();
if (!strcmp(path, "a")) { return *down = (mask & ovrButton_A), true; }
else if (!strcmp(path, "b")) { return *down = (mask & ovrButton_B), true; }
else if (!strcmp(path, "x")) { return *down = (mask & ovrButton_X), true; }
else if (!strcmp(path, "y")) { return *down = (mask & ovrButton_Y), true; }
else if (!strcmp(path, "menu")) { return *down = (mask & ovrButton_Enter), true; }
else if (!strcmp(path, "trigger")) { return *down = (is->IndexTriggerNoDeadzone[hand] > .5f), true; }
else if (!strcmp(path, "joystick")) { return *down = (mask & (ovrButton_LThumb | ovrButton_RThumb)), true; }
else if (!strcmp(path, "grip")) { return *down = (is->HandTrigger[hand] > .9f), true; }
switch (button) {
case BUTTON_A: return *down = (buttons & ovrButton_A), true;
case BUTTON_B: return *down = (buttons & ovrButton_B), true;
case BUTTON_X: return *down = (buttons & ovrButton_X), true;
case BUTTON_Y: return *down = (buttons & ovrButton_Y), true;
case BUTTON_MENU: return *down = (buttons & ovrButton_Enter), true;
case BUTTON_TRIGGER: return *down = (is->IndexTriggerNoDeadzone[hand] > .5f), true;
case BUTTON_THUMBSTICK: return *down = (buttons & (ovrButton_LThumb | ovrButton_RThumb), true;
case BUTTON_GRIP: return *down = (masks->HandTrigger[hand] > .9f), true;
default: return false;
}
return false;
}
static bool oculus_isTouched(const char* path, bool* touched) {
ovrHandType hand;
uint32_t mask;
const char* button;
if (getHandInfo(path, &hand, &mask, &button)) {
if (!strcmp(path, "a")) { return *touched = (mask & ovrTouch_A), true; }
else if (!strcmp(path, "b")) { return *touched = (mask & ovrTouch_B), true; }
else if (!strcmp(path, "x")) { return *touched = (mask & ovrTouch_X), true; }
else if (!strcmp(path, "y")) { return *touched = (mask & ovrTouch_Y), true; }
else if (!strcmp(path, "trigger")) { return *touched = (mask & (ovrTouch_LIndexTrigger | ovrTouch_RIndexTrigger)), true; }
else if (!strcmp(path, "joystick")) { return *touched = (mask & (ovrTouch_LThumb | ovrTouch_RThumb)), true; }
static bool oculus_isTouched(Device device, DeviceButton button, bool* touched) {
if (device != DEVICE_HAND_LEFT && device != DEVICE_HAND_RIGHT) {
return false;
}
return false;
ovrInputState* is = refreshButtons();
ovrHand hand = device == DEVICE_HAND_LEFT ? ovrHand_Left : ovrHand_Right;
uint32_t touches = is->Touches & (device == DEVICE_HAND_LEFT ? ovrTouch_LButtonMask : ovrTouch_RButtonMask);
switch (button) {
case BUTTON_A: return *touched = (touches & ovrTouch_A), true;
case BUTTON_B: return *touched = (touches & ovrTouch_B), true;
case BUTTON_X: return *touched = (touches & ovrTouch_X), true;
case BUTTON_Y: return *touched = (touches & ovrTouch_Y), true;
case BUTTON_TRIGGER: return *touched = (touches & (ovrTouch_LIndexTrigger | ovrTouch_RIndexTrigger)), true;
case BUTTON_THUMBSTICK: return *touched = (touches & (ovrTouch_LThumb | ovrTouch_RThumb)), true;
default: return false;
}
}
static int oculus_getAxis(const char* path, float* x, float* y, float* z) {
ovrHandType hand;
uint32_t mask;
const char* button;
if (getHandInfo(path, &hand, &mask, &button)) {
ovrInputState* is = refreshButtons();
if (!strcmp(path, "grip")) { return *x = is->HandTriggerNoDeadzone[hand], 1; }
if (!strcmp(path, "trigger")) { return *x = is->IndexTriggerNoDeadzone[hand], 1; }
if (!strcmp(path, "joystick")) { return *x = is->ThumbstickNoDeadzone[hand].x, *y = is->ThumbstickNoDeadzone[hand].y, 2; }
static bool oculus_getAxis(Device device, DeviceAxis axis, float* value) {
if (device != DEVICE_HAND_LEFT && device != DEVICE_HAND_RIGHT) {
return false;
}
return 0;
ovrInputState* is = refreshButtons();
ovrHand hand = device == DEVICE_HAND_LEFT ? ovrHand_Left : ovrHand_Right;
switch (axis) {
case AXIS_GRIP: return *value = is->HandTriggerNoDeadzone[hand], true;
case AXIS_TRIGGER: return *value = is->IndexTriggerNoDeadzone[hand], true;
case AXIS_THUMBSTICK_X: return *value = is->ThumbstickNoDeadzone[hand].x, true;
case AXIS_THUMBSTICK_Y: return *value = is->ThumbstickNoDeadzone[hand].y, true;
default: return false;
}
}
static bool oculus_vibrate(const char* path, float strength, float duration, float frequency) {
static bool oculus_vibrate(Device device, float strength, float duration, float frequency) {
return false; // TODO
}
static ModelData* oculus_newModelData(const char* path) {
static ModelData* oculus_newModelData(Device device) {
return NULL; // TODO
}

View File

@ -74,15 +74,13 @@ static const float* vrapi_getBoundsGeometry(int* count) {
return NULL;
}
static bool vrapi_getPose(const char* path, vec3 position, quat orientation) {
static bool vrapi_getPose(Device device, vec3 position, quat orientation) {
BridgeLovrPose* pose;
if (!strcmp(path, "head")) {
pose = &bridgeLovrMobileData.updateData.lastHeadPose;
} else if (!strcmp(path, "hand")) {
pose = &bridgeLovrMobileData.updateData.goPose;
} else {
return false;
switch (device) {
case DEVICE_HEAD: pose = &bridgeLovrMobileData.updateData.lastHeadPose; break;
case DEVICE_HAND: pose = &bridgeLovrMobileData.updateData.goPose; break;
default: return false;
}
if (position) {
@ -96,15 +94,13 @@ static bool vrapi_getPose(const char* path, vec3 position, quat orientation) {
return true;
}
static bool vrapi_getVelocity(const char* path, vec3 velocity, vec3 angularVelocity) {
static bool vrapi_getVelocity(Device device, vec3 velocity, vec3 angularVelocity) {
BridgeLovrVel* v;
if (!strcmp(path, "head")) {
v = &bridgeLovrMobileData.updateData.lastHeadVelocity;
} else if (!strcmp(path, "hand")) {
v = &bridgeLovrMobileData.updateData.goVelocity;
} else {
return false;
switch (device) {
case DEVICE_HEAD: v = &bridgeLovrMobileData.updateData.lastHeadVelocity; break;
case DEVICE_HAND: v = &bridgeLovrMobileData.updateData.goVelocity; break;
default: return false;
}
if (velocity) {
@ -118,46 +114,45 @@ static bool vrapi_getVelocity(const char* path, vec3 velocity, vec3 angularVeloc
return true;
}
static bool buttonCheck(BridgeLovrButton field, const char* path, bool* result) {
if (!strcmp("hand", path, strlen("hand"))) {
path += strlen("hand/");
if (!strcmp(path, "menu")) { return *result = (field & BRIDGE_LOVR_BUTTON_MENU), true; }
else if (!strcmp(path, "trigger")) { return *result = (field & BRIDGE_LOVR_BUTTON_SHOULDER), true; }
else if (!strcmp(path, "trackpad")) { return *result = (field & BRIDGE_LOVR_BUTTON_TOUCHPAD), true; }
static bool buttonCheck(BridgeLovrButton field, Device device, DeviceButton button, bool* result) {
if (device != DEVICE_HAND) {
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_TRACKPAD: return *result = (field & BRIDGE_LOVR_BUTTON_TOUCHPAD), true;
default: return false;
}
}
static bool vrapi_isDown(Device device, DeviceButton button, bool* down) {
return buttonCheck(bridgeLovrMobileData.updateData.goButtonDown, device, button, down);
}
static bool vrapi_isTouched(Device device, DeviceButton button, bool* touched) {
return buttonCheck(bridgeLovrMobileData.updateData.goButtonTouch, device, button, touched);
}
static int vrapi_getAxis(Device device, DeviceAxis axis, float* x, float* y, float* z) {
if (device != DEVICE_HAND) {
return false;
}
switch (axis) {
case AXIS_TRACKPAD_X: return *value = (bridgeLovrMobileData.updateData.goTrackpad.x - 160.f) / 160.f, true;
case AXIS_TRACKPAD_Y: return *value = (bridgeLovrMobileData.updateData.goTrackpad.y - 160.f) / 160.f, true;
case AXIS_TRIGGER: return *value = bridgeLovrMobileData.updateData.goButtonDown ? 1.f : 0.f, true;
default: return false;
}
}
static bool vrapi_vibrate(Device device, float strength, float duration, float frequency) {
return false;
}
static bool vrapi_isDown(const char* path, bool* down) {
return buttonCheck(bridgeLovrMobileData.updateData.goButtonDown, path, down);
}
static bool vrapi_isTouched(const char* path, bool* touched) {
return buttonCheck(bridgeLovrMobileData.updateData.goButtonTouch, path, touched);
}
static int vrapi_getAxis(const char* path, float* x, float* y, float* z) {
if (!strcmp("hand", path, strlen("hand"))) {
path += strlen("hand/");
if (!strcmp(path, "trackpad")) {
*x = (bridgeLovrMobileData.updateData.goTrackpad.x - 160.f) / 160.f;
*y = (bridgeLovrMobileData.updateData.goTrackpad.y - 160.f) / 160.f;
return 2;
} else if (!strcmp(path, "trigger")) {
*x = bridgeLovrMobileData.updateData.goButtonDown ? 1.f : 0.f;
return 1;
}
}
return 0;
}
static bool vrapi_vibrate(const char* path, float strength, float duration, float frequency) {
return false;
}
static ModelData* vrapi_newModelData(const char* path) {
static ModelData* vrapi_newModelData(Device device) {
return NULL;
}

View File

@ -44,24 +44,22 @@ static struct {
int msaa;
} state;
static TrackedDeviceIndex_t pathToDevice(const char* path, const char** next) {
if (!strcmp(path, "head")) {
if (next) *next = path + strlen("head/");
return HEADSET;
} else if (!strcmp(path, "hand/left")) {
if (next) *next = path + strlen("hand/left/");
return state.system->GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole_TrackedControllerRole_LeftHand);
} else if (!strcmp(path, "hand/right")) {
if (next) *next = path + strlen("hand/right/");
return state.system->GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole_TrackedControllerRole_RightHand);
} else if (!strncmp("tracker/", path, strlen("tracker/"))) {
path += strlen("tracker/");
uint32_t index = (path[0] - '0') - 1;
TrackedDeviceIndex_t indices[8];
uint32_t trackerCount = state.system->GetSortedTrackedDeviceIndicesOfClass(ETrackedDeviceClass_TrackedDeviceClass_GenericTracker, indices, 8, 0);
return (index >= 0 && index < trackerCount) ? indices[index] : INVALID_DEVICE;
} else {
return INVALID_DEVICE;
static TrackedDeviceIndex_t getDeviceIndex(Device device) {
switch (device) {
case DEVICE_HEAD: return HEADSET;
case DEVICE_HAND: return INVALID_DEVICE;
case DEVICE_HAND_LEFT: return state.system->GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole_TrackedControllerRole_LeftHand);
case DEVICE_HAND_RIGHT: return state.system->GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole_TrackedControllerRole_RightHand);
case DEVICE_TRACKER_1:
case DEVICE_TRACKER_2:
case DEVICE_TRACKER_3:
case DEVICE_TRACKER_4: {
TrackedDeviceIndex_t trackers[4];
uint32_t trackerCount = state.system->GetSortedTrackedDeviceIndicesOfClass(ETrackedDeviceClass_TrackedDeviceClass_GenericTracker, trackers, 4, 0);
uint32_t i = device - DEVICE_TRACKER_1;
return i < trackerCount ? trackers[i] : INVALID_DEVICE;
}
default: return INVALID_DEVICE;
}
}
@ -177,8 +175,8 @@ static const float* openvr_getBoundsGeometry(int* count) {
return NULL;
}
static bool getTransform(unsigned int device, mat4 transform) {
TrackedDevicePose_t pose = state.poses[device];
static bool getTransform(unsigned int index, mat4 transform) {
TrackedDevicePose_t pose = state.poses[index];
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
return false;
} else {
@ -188,10 +186,10 @@ static bool getTransform(unsigned int device, mat4 transform) {
}
}
static bool openvr_getPose(const char* path, vec3 position, quat orientation) {
static bool openvr_getPose(Device device, vec3 position, quat orientation) {
float transform[16];
TrackedDeviceIndex_t device = pathToDevice(path, NULL);
if (device == INVALID_DEVICE || !getTransform(device, transform)) {
TrackedDeviceIndex_t index = getDeviceIndex(device);
if (index == INVALID_DEVICE || !getTransform(index, transform)) {
return false;
}
@ -200,10 +198,10 @@ static bool openvr_getPose(const char* path, vec3 position, quat orientation) {
return true;
}
static bool openvr_getVelocity(const char* path, vec3 velocity, vec3 angularVelocity) {
TrackedDeviceIndex_t device = pathToDevice(path, NULL);
static bool openvr_getVelocity(Device device, vec3 velocity, vec3 angularVelocity) {
TrackedDeviceIndex_t index = getDeviceIndex(device);
TrackedDevicePose_t* pose = &state.poses[device];
if (device == INVALID_DEVICE || !pose->bPoseIsValid || !pose->bDeviceIsConnected) {
if (index == INVALID_DEVICE || !pose->bPoseIsValid || !pose->bDeviceIsConnected) {
return false;
}
@ -218,10 +216,10 @@ static bool openvr_getVelocity(const char* path, vec3 velocity, vec3 angularVelo
return true;
}
static bool getButtonState(const char* path, bool touch, bool* value) {
static bool getButtonState(Device device, DeviceButton button, bool touch, bool* value) {
VRControllerState_t input;
if (!strcmp(path, "head/proximity") && !touch) {
if (device == DEVICE_HEAD && button == BUTTON_PROXIMITY && !touch) {
if (!state.system->GetControllerState(HEADSET, &input, sizeof(input))) {
return false;
}
@ -229,82 +227,93 @@ static bool getButtonState(const char* path, bool touch, bool* value) {
return *value = (input.ulButtonPressed >> EVRButtonId_k_EButton_ProximitySensor) & 1, true;
}
const char* button;
TrackedDeviceIndex_t device = pathToDevice(path, &button);
if (device != INVALID_DEVICE || state.system->GetControllerState(device, &input, sizeof(input))) {
TrackedDeviceIndex_t index = getDeviceIndex(device);
if (index != INVALID_DEVICE || state.system->GetControllerState(index, &input, sizeof(input))) {
uint64_t mask = touch ? input.ulButtonTouched : input.ulButtonPressed;
if (state.rift) {
if (!strcmp(button, "trigger")) { return *value = (mask >> EVRButtonId_k_EButton_Axis1) & 1, true; }
else if (!strcmp(button, "grip")) { return *value = (mask >> EVRButtonId_k_EButton_Axis2) & 1, true; }
else if (!strcmp(button, "trackpad")) { return *value = (mask >> EVRButtonId_k_EButton_Axis0) & 1, true; }
else if (!strcmp(path, "hand/right/a") || !strcmp(path, "hand/left/x")) { return *value = (mask >> EVRButtonId_k_EButton_A) & 1, true; }
else if (!strcmp(path, "hand/right/b") || !strcmp(path, "hand/left/y")) { return *value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1, true; }
switch (button) {
case BUTTON_TRIGGER: return *value = (mask >> EVRButtonId_k_EButton_Axis1) & 1, true;
case BUTTON_GRIP: return *value = (mask >> EVRButtonId_k_EButton_Axis2) & 1, true;
case BUTTON_A: return *value = (mask >> EVRButtonId_k_EButton_A) & 1, device == DEVICE_HAND_RIGHT;
case BUTTON_B: return *value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1, device == DEVICE_HAND_RIGHT;
case BUTTON_X: return *value = (mask >> EVRButtonId_k_EButton_A) & 1, device == DEVICE_HAND_LEFT;
case BUTTON_Y: return *value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1, device == DEVICE_HAND_LEFT;
default: return false;
}
} else {
if (!strcmp(button, "trigger")) { return *value = (mask >> EVRButtonId_k_EButton_SteamVR_Trigger) & 1, true; }
else if (!strcmp(button, "trackpad")) { return *value = (mask >> EVRButtonId_k_EButton_SteamVR_Touchpad) & 1, true; }
else if (!strcmp(button, "menu")) { return *value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1, true; }
else if (!strcmp(button, "grip")) { return *value = (mask >> EVRButtonId_k_EButton_Grip) & 1, true; }
switch (button) {
case BUTTON_TRIGGER: return *value = (mask >> EVRButtonId_k_EButton_SteamVR_Trigger) & 1, true;
case BUTTON_TRACKPAD: return *value = (mask >> EVRButtonId_k_EButton_SteamVR_Touchpad) & 1, true;
case BUTTON_MENU: return *value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1, true;
case BUTTON_GRIP: return *value = (mask >> EVRButtonId_k_EButton_Grip) & 1, true;
default: return false;
}
}
}
return false;
}
static bool openvr_isDown(const char* path, bool* down) {
return getButtonState(path, false, down);
static bool openvr_isDown(Device device, DeviceButton button, bool* down) {
return getButtonState(device, button, false, down);
}
static bool openvr_isTouched(const char* path, bool* touched) {
return getButtonState(path, true, touched);
static bool openvr_isTouched(Device device, DeviceButton button, bool* touched) {
return getButtonState(device, button, true, touched);
}
static int openvr_getAxis(const char* path, float* x, float* y, float* z) {
const char* axis;
TrackedDeviceIndex_t device = pathToDevice(path, &axis);
static bool openvr_getAxis(Device device, DeviceAxis axis, float* value) {
TrackedDeviceIndex_t index = getDeviceIndex(device);
VRControllerState_t input;
if (device != INVALID_DEVICE || state.system->GetControllerState(device, &input, sizeof(input))) {
if (!strcmp(axis, "trigger")) { return *x = input.rAxis[1].x, 1; }
else if (state.rift && !strcmp(axis, "grip")) { return *x = input.rAxis[2].x, 1; }
else if (!strcmp(axis, "trackpad")) { return *x = input.rAxis[0].x, *y = input.rAxis[0].y, 2; }
if (index != INVALID_DEVICE || state.system->GetControllerState(index, &input, sizeof(input))) {
switch (axis) {
case AXIS_TRIGGER: return *value = input.rAxis[1].x, true;
case AXIS_GRIP: return *value = input.rAxis[2].x, state.rift;
case AXIS_TRACKPAD_X: return *value = input.rAxis[0].x, !state.rift;
case AXIS_TRACKPAD_Y: return *value = input.rAxis[0].y, !state.rift;
case AXIS_THUMBSTICK_X: return *value = input.rAxis[0].x, state.rift;
case AXIS_THUMBSTICK_Y: return *value = input.rAxis[0].y, state.rift;
default: return false;
}
}
return 0;
return false;
}
static bool openvr_vibrate(const char* path, float strength, float duration, float frequency) {
static bool openvr_vibrate(Device device, float strength, float duration, float frequency) {
if (duration <= 0) return false;
TrackedDeviceIndex_t device = pathToDevice(path, NULL);
if (device == INVALID_DEVICE) return false;
TrackedDeviceIndex_t index = getDeviceIndex(device);
if (index == INVALID_DEVICE) return false;
unsigned short uSeconds = (unsigned short) (duration * 1e6f + .5f);
state.system->TriggerHapticPulse(device, 0, uSeconds);
state.system->TriggerHapticPulse(index, 0, uSeconds);
return true;
}
static ModelData* openvr_newModelData(const char* path) {
TrackedDeviceIndex_t device = pathToDevice(path, NULL);
if (device == INVALID_DEVICE) return false;
static ModelData* openvr_newModelData(Device device) {
TrackedDeviceIndex_t index = getDeviceIndex(device);
if (index == INVALID_DEVICE) return false;
char renderModelName[1024];
ETrackedDeviceProperty renderModelNameProperty = ETrackedDeviceProperty_Prop_RenderModelName_String;
state.system->GetStringTrackedDeviceProperty(device, renderModelNameProperty, renderModelName, 1024, NULL);
state.system->GetStringTrackedDeviceProperty(index, renderModelNameProperty, renderModelName, 1024, NULL);
if (!state.deviceModels[device]) {
while (state.renderModels->LoadRenderModel_Async(renderModelName, &state.deviceModels[device]) == EVRRenderModelError_VRRenderModelError_Loading) {
if (!state.deviceModels[index]) {
while (state.renderModels->LoadRenderModel_Async(renderModelName, &state.deviceModels[index]) == EVRRenderModelError_VRRenderModelError_Loading) {
lovrSleep(.001);
}
}
if (!state.deviceTextures[device]) {
while (state.renderModels->LoadTexture_Async(state.deviceModels[device]->diffuseTextureId, &state.deviceTextures[device]) == EVRRenderModelError_VRRenderModelError_Loading) {
if (!state.deviceTextures[index]) {
while (state.renderModels->LoadTexture_Async(state.deviceModels[index]->diffuseTextureId, &state.deviceTextures[index]) == EVRRenderModelError_VRRenderModelError_Loading) {
lovrSleep(.001);
}
}
RenderModel_t* vrModel = state.deviceModels[device];
RenderModel_t* vrModel = state.deviceModels[index];
ModelData* model = lovrAlloc(ModelData);
size_t vertexSize = sizeof(RenderModel_Vertex_t);
@ -360,7 +369,7 @@ static ModelData* openvr_newModelData(const char* path) {
.components = 1
};
RenderModel_TextureMap_t* vrTexture = state.deviceTextures[device];
RenderModel_TextureMap_t* vrTexture = state.deviceTextures[index];
model->textures[0] = lovrTextureDataCreate(vrTexture->unWidth, vrTexture->unHeight, 0, FORMAT_RGBA);
memcpy(model->textures[0]->blob.data, vrTexture->rubTextureMapData, vrTexture->unWidth * vrTexture->unHeight * 4);

View File

@ -426,27 +426,24 @@ static const float* openxr_getBoundsGeometry(int* count) {
return NULL;
}
static bool getRelation(const char* path, XrSpaceRelation* relation) {
static bool getRelation(Device device, XrSpaceRelation* relation) {
XrSpace space;
if (!strcmp(path, "head")) {
space = state.headSpace;
} else if (!strcmp(path, "hand/left")) {
space = state.leftHandSpace;
} else if (!strcmp(path, "hand/right")) {
space = state.rightHandSpace;
} else {
return false;
switch (device) {
case DEVICE_HEAD: space = state.headSpace; break;
case DEVICE_HAND_LEFT: space = state.leftHandSpace; break;
case DEVICE_HAND_RIGHT: space = state.rightHandSpace; break;
default: return false;
}
XR(xrLocateSpace(space, state.space, state.displayTime, relation));
return true;
}
static bool openxr_getPose(const char* path, vec3 position, quat orientation) {
static bool openxr_getPose(Device device, vec3 position, quat orientation) {
XrSpaceRelation relation;
if (getRelation(path, &relation) && (relation.relationFlags & (XR_SPACE_RELATION_POSITION_VALID_BIT | XR_SPACE_RELATION_ORIENTATION_VALID_BIT))) {
if (getRelation(device, &relation) && (relation.relationFlags & (XR_SPACE_RELATION_POSITION_VALID_BIT | XR_SPACE_RELATION_ORIENTATION_VALID_BIT))) {
XrPosef* pose = &relation.pose;
if (position) {
@ -463,10 +460,10 @@ static bool openxr_getPose(const char* path, vec3 position, quat orientation) {
return false;
}
static bool openxr_getVelocity(const char* path, vec3 velocity, vec3 angularVelocity) {
static bool openxr_getVelocity(Device device, vec3 velocity, vec3 angularVelocity) {
XrSpaceRelation relation;
if (getRelation(path, &relation) && (relation.relationFlags & (XR_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT | XR_SPACE_RELATION_ANGULAR_VELOCITY_VALID_BIT))) {
if (getRelation(device, &relation) && (relation.relationFlags & (XR_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT | XR_SPACE_RELATION_ANGULAR_VELOCITY_VALID_BIT))) {
if (velocity) {
vec3_set(velocity, relation.linearVelocity.x, relation.linearVelocity.y, relation.linearVelocity.z);
}
@ -481,82 +478,70 @@ static bool openxr_getVelocity(const char* path, vec3 velocity, vec3 angularVelo
return false;
}
static bool getActionFilter(const char* path, XrPath* filter, const char** next) {
if (!strncmp("hand/left", path, strlen("hand/left"))) {
*filter = state.actionFilters[0];
*next = path + strlen("hand/left/");
return true;
} else if (!strncmp("hand/right", path, strlen("hand/right"))) {
*filter = state.actionFilters[1];
*next = path + strlen("hand/right/");
return true;
} else {
static XrPath getActionFilter(Device device) {
switch (device) {
case DEVICE_HAND_LEFT: return state.actionFilters[0];
case DEVICE_HAND_RIGHT: return state.actionFilters[1];
default: return XR_NULL_PATH;
}
}
static bool getButtonState(Device device, DeviceButton button, bool* value, bool touch) {
XrPath filter = getActionFilter(device);
if (filter == XR_NULL_PATH) {
return false;
}
}
static bool getButtonState(const char* path, bool* value, bool touch) {
XrPath filter;
const char* button;
if (getActionFilter(path, &filter, &button)) {
Action type;
if (!strcmp(button, "trigger")) { type = ACTION_TRIGGER_DOWN + touch; }
else if (!strcmp(button, "trackpad")) { type = ACTION_TRACKPAD_DOWN + touch; }
else if (!strcmp(button, "menu")) { type = ACTION_MENU_DOWN + touch; }
else if (!strcmp(button, "grip")) { type = ACTION_GRIP_DOWN + touch; }
else { return false; }
XrActionStateBoolean actionState;
XR(xrGetActionStateBoolean(state.actions[type], 1, &filter, &actionState));
if (actionState.isActive) {
*value = actionState.currentState;
return true;
}
Action type;
switch (button) {
case BUTTON_TRIGGER: type = ACTION_TRIGGER_DOWN + touch; break;
case BUTTON_TRACKPAD: type = ACTION_TRACKPAD_DOWN + touch; break;
case BUTTON_MENU: type = ACTION_MENU_DOWN + touch; break;
case BUTTON_GRIP: type = ACTION_GRIP_DOWN + touch; break;
default: return false;
}
return false;
XrActionStateBoolean actionState;
XR(xrGetActionStateBoolean(state.actions[type], 1, &filter, &actionState));
*value = actionState.currentState;
return actionState.isActive;
}
static bool openxr_isDown(const char* path, bool* down) {
return getButtonState(path, down, false);
static bool openxr_isDown(Device device, DeviceButton button, bool* down) {
return getButtonState(device, button, down, false);
}
static bool openxr_isTouched(const char* path, bool* touched) {
return getButtonState(path, touched, true);
static bool openxr_isTouched(Device device, DeviceButton button, bool* touched) {
return getButtonState(device, button, touched, true);
}
static int openxr_getAxis(const char* path, float* x, float* y, float* z) {
XrPath filter;
const char* axis;
static bool openxr_getAxis(Device device, DeviceAxis axis, float* value) {
XrPath filter = getActionFilter(device);
if (getActionFilter(path, &filter, &axis)) {
XrActionStateVector1f actionState;
if (!strcmp(axis, "trigger")) {
XR(xrGetActionStateVector1f(state.actions[ACTION_TRIGGER_AXIS], 1, &filter, &actionState));
*x = actionState.currentState;
return 1;
} else if (!strcmp(axis, "trackpad")) {
XR(xrGetActionStateVector1f(state.actions[ACTION_TRACKPAD_X], 1, &filter, &actionState));
*x = actionState.currentState;
XR(xrGetActionStateVector1f(state.actions[ACTION_TRACKPAD_Y], 1, &filter, &actionState));
*y = actionState.currentState;
return 2;
} else if (!strcmp(axis, "grip")) {
XR(xrGetActionStateVector1f(state.actions[ACTION_GRIP_AXIS], 1, &filter, &actionState));
*x = actionState.currentState;
return 1;
}
if (filter == XR_NULL_PATH) {
return false;
}
return 0;
Action type;
switch (axis) {
case AXIS_TRIGGER: type = ACTION_TRIGGER_AXIS; break;
case AXIS_TRACKPAD_X: type = ACTION_TRACKPAD_X; break;
case AXIS_TRACKPAD_Y: type = ACTION_TRACKPAD_Y; break;
case AXIS_GRIP: type = ACTION_GRIP_AXIS; break;
default: return false;
}
XrActionStateVector1f actionState;
XR(xrGetActionStateVector1f(state.actions[type], 1, &filter, &actionState));
*value = actionState.currentState;
return true;
}
static bool openxr_vibrate(const char* path, float power, float duration, float frequency) {
XrPath filter;
static bool openxr_vibrate(Device device, float power, float duration, float frequency) {
XrPath filter = getActionFilter(device);
if (!getActionFilter(path, &filter, &path)) {
if (filter == XR_NULL_PATH) {
return false;
}
@ -568,11 +553,10 @@ static bool openxr_vibrate(const char* path, float power, float duration, float
};
XR(xrApplyHapticFeedback(state.actions[ACTION_VIBRATE], 1, &filter, (XrHapticBaseHeader*) &vibration));
return true;
}
static struct ModelData* openxr_newModelData(const char* path) {
static struct ModelData* openxr_newModelData(Device device) {
return NULL;
}