mirror of https://github.com/bjornbytes/lovr.git
Use strings for paths;
It's probably slower, but it's way less complicated, so it seems like a win for now. Can implement compile-time hashing, tries etc. later if it's identified as a performance issue for a real person. Also a bunch of cleanup in openvr.c and oculus.c.
This commit is contained in:
parent
45931d005a
commit
df5de9a35e
|
@ -25,34 +25,6 @@ const char* HeadsetOrigins[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const char* Subpaths[] = {
|
||||
[P_NONE] = "",
|
||||
[P_HEAD] = "head",
|
||||
[P_HAND] = "hand",
|
||||
[P_EYE] = "eye",
|
||||
[P_TRACKER] = "tracker",
|
||||
[P_LEFT] = "left",
|
||||
[P_RIGHT] = "right",
|
||||
[P_PROXIMITY] = "proximity",
|
||||
[P_TRIGGER] = "trigger",
|
||||
[P_TRACKPAD] = "trackpad",
|
||||
[P_JOYSTICK] = "joystick",
|
||||
[P_MENU] = "menu",
|
||||
[P_GRIP] = "grip",
|
||||
[P_A] = "a",
|
||||
[P_B] = "b",
|
||||
[P_X] = "x",
|
||||
[P_Y] = "y",
|
||||
[P_1] = "1",
|
||||
[P_2] = "2",
|
||||
[P_3] = "3",
|
||||
[P_4] = "4",
|
||||
[P_5] = "5",
|
||||
[P_6] = "6",
|
||||
[P_7] = "7",
|
||||
[P_8] = "8"
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
lua_State* L;
|
||||
int ref;
|
||||
|
@ -60,42 +32,9 @@ typedef struct {
|
|||
|
||||
static HeadsetRenderData headsetRenderData;
|
||||
|
||||
Path luax_optpath(lua_State* L, int index, const char* fallback) {
|
||||
char* str = (char*) luaL_optstring(L, index, fallback);
|
||||
Path path = { { P_NONE } };
|
||||
int count = 0;
|
||||
|
||||
if (str[0] == '/') {
|
||||
str++;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
char* slash = strchr(str, '/');
|
||||
|
||||
if (slash) {
|
||||
*slash = '\0';
|
||||
}
|
||||
|
||||
Subpath subpath = P_NONE;
|
||||
for (size_t i = 0; i < sizeof(Subpaths) / sizeof(Subpaths[0]); i++) {
|
||||
if (!strcmp(str, Subpaths[i])) {
|
||||
subpath = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lovrAssert(subpath != P_NONE, "Unknown path component '%s'", str);
|
||||
path.p[count++] = subpath;
|
||||
|
||||
if (slash) {
|
||||
*slash = '/';
|
||||
str = slash + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
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) {
|
||||
|
@ -221,7 +160,7 @@ static int l_lovrHeadsetGetBoundsGeometry(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetGetPose(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
float x, y, z, angle, ax, ay, az;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->getPose(path, &x, &y, &z, &angle, &ax, &ay, &az)) {
|
||||
|
@ -239,7 +178,7 @@ int l_lovrHeadsetGetPose(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetGetPosition(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
float x, y, z;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->getPose(path, &x, &y, &z, NULL, NULL, NULL, NULL)) {
|
||||
|
@ -253,7 +192,7 @@ int l_lovrHeadsetGetPosition(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetGetOrientation(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
float angle, ax, ay, az;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->getPose(path, NULL, NULL, NULL, &angle, &ax, &ay, &az)) {
|
||||
|
@ -268,7 +207,7 @@ int l_lovrHeadsetGetOrientation(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetGetDirection(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
float angle, ax, ay, az;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->getPose(path, NULL, NULL, NULL, &angle, &ax, &ay, &az)) {
|
||||
|
@ -286,7 +225,7 @@ int l_lovrHeadsetGetDirection(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetGetVelocity(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
float vx, vy, vz;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->getVelocity(path, &vx, &vy, &vz, NULL, NULL, NULL)) {
|
||||
|
@ -300,7 +239,7 @@ int l_lovrHeadsetGetVelocity(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
float vax, vay, vaz;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->getVelocity(path, NULL, NULL, NULL, &vax, &vay, &vaz)) {
|
||||
|
@ -314,7 +253,7 @@ int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetIsTracked(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->getPose(path, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
|
||||
return true;
|
||||
|
@ -324,7 +263,7 @@ int l_lovrHeadsetIsTracked(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetIsDown(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
bool down;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->isDown(path, &down)) {
|
||||
|
@ -336,7 +275,7 @@ int l_lovrHeadsetIsDown(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetIsTouched(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
bool touched;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
if (driver->isDown(path, &touched)) {
|
||||
|
@ -348,7 +287,7 @@ int l_lovrHeadsetIsTouched(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetGetAxis(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
float x, y, z;
|
||||
int count;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
|
@ -364,7 +303,7 @@ int l_lovrHeadsetGetAxis(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetVibrate(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
float strength = luax_optfloat(L, 2, 1.f);
|
||||
float duration = luax_optfloat(L, 3, .5f);
|
||||
float frequency = luax_optfloat(L, 4, 0.f);
|
||||
|
@ -379,7 +318,7 @@ int l_lovrHeadsetVibrate(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrHeadsetNewModel(lua_State* L) {
|
||||
Path path = luax_optpath(L, 1, "head");
|
||||
const char* path = luax_optpath(L, 1);
|
||||
|
||||
ModelData* modelData = NULL;
|
||||
FOREACH_TRACKING_DRIVER(driver) {
|
||||
|
|
|
@ -74,9 +74,9 @@ static const float* getBoundsGeometry(int* count) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool getPose(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
bool head = PATH_EQ(path, P_HEAD);
|
||||
bool hand = PATH_EQ(path, P_HAND, P_LEFT) || PATH_EQ(path, P_HAND, P_RIGHT);
|
||||
static bool getPose(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
bool head = !strcmp(path, "head");
|
||||
bool hand = !strcmp(path, "hand/left") || !strcmp(path, "hand/right");
|
||||
|
||||
if (!head && !hand) {
|
||||
return false;
|
||||
|
@ -97,8 +97,8 @@ static bool getPose(Path path, float* x, float* y, float* z, float* angle, float
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) {
|
||||
if (!PATH_EQ(path, P_HEAD)) {
|
||||
static bool getVelocity(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) {
|
||||
if (strcmp(path, "head")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,8 @@ static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool isDown(Path path, bool* down) {
|
||||
if (PATH_EQ(path, P_HAND, P_LEFT) || PATH_EQ(path, P_HAND, P_RIGHT)) {
|
||||
static bool isDown(const char* path, bool* down) {
|
||||
if (!strcmp(path, "hand/left") || !strcmp(path, "hand/right")) {
|
||||
*down = lovrPlatformIsMouseDown(MOUSE_RIGHT);
|
||||
return true;
|
||||
}
|
||||
|
@ -126,19 +126,19 @@ static bool isDown(Path path, bool* down) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool isTouched(Path path, bool* touched) {
|
||||
static bool isTouched(const char* path, bool* touched) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static int getAxis(Path path, float* x, float* y, float* z) {
|
||||
static int getAxis(const char* path, float* x, float* y, float* z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool vibrate(Path path, float strength, float duration, float frequency) {
|
||||
static bool vibrate(const char* path, float strength, float duration, float frequency) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static ModelData* newModelData(Path path) {
|
||||
static ModelData* newModelData(const char* path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,43 +21,6 @@ typedef enum {
|
|||
DRIVER_WEBVR
|
||||
} HeadsetDriver;
|
||||
|
||||
typedef enum {
|
||||
P_NONE,
|
||||
P_HEAD,
|
||||
P_HAND,
|
||||
P_EYE,
|
||||
P_TRACKER,
|
||||
P_LEFT,
|
||||
P_RIGHT,
|
||||
P_PROXIMITY,
|
||||
P_TRIGGER,
|
||||
P_TRACKPAD,
|
||||
P_JOYSTICK,
|
||||
P_MENU,
|
||||
P_GRIP,
|
||||
P_A,
|
||||
P_B,
|
||||
P_X,
|
||||
P_Y,
|
||||
P_1,
|
||||
P_2,
|
||||
P_3,
|
||||
P_4,
|
||||
P_5,
|
||||
P_6,
|
||||
P_7,
|
||||
P_8
|
||||
} Subpath;
|
||||
|
||||
typedef union {
|
||||
uint8_t p[8];
|
||||
uint64_t u64;
|
||||
} Path;
|
||||
|
||||
#define MAKE_PATH(...) ((Path) { { __VA_ARGS__ } })
|
||||
#define PATH_EQ(p, ...) ((p).u64 == MAKE_PATH(__VA_ARGS__).u64)
|
||||
#define PATH_STARTS_WITH(p, ...) ((MAKE_PATH(__VA_ARGS__).u64 ^ p.u64 & MAKE_PATH(__VA_ARGS__).u64) == 0)
|
||||
|
||||
typedef struct HeadsetInterface {
|
||||
struct HeadsetInterface* next;
|
||||
HeadsetDriver driverType;
|
||||
|
@ -70,13 +33,13 @@ typedef struct HeadsetInterface {
|
|||
void (*setClipDistance)(float clipNear, float clipFar);
|
||||
void (*getBoundsDimensions)(float* width, float* depth);
|
||||
const float* (*getBoundsGeometry)(int* count);
|
||||
bool (*getPose)(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az);
|
||||
bool (*getVelocity)(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz);
|
||||
bool (*isDown)(Path path, bool* down);
|
||||
bool (*isTouched)(Path path, bool* touched);
|
||||
int (*getAxis)(Path path, float* x, float* y, float* z);
|
||||
bool (*vibrate)(Path path, float strength, float duration, float frequency);
|
||||
struct ModelData* (*newModelData)(Path path);
|
||||
bool (*getPose)(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az);
|
||||
bool (*getVelocity)(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz);
|
||||
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);
|
||||
void (*renderTo)(void (*callback)(void*), void* userdata);
|
||||
struct Texture* (*getMirrorTexture)(void);
|
||||
void (*update)(float dt);
|
||||
|
|
|
@ -159,14 +159,16 @@ static const float* getBoundsGeometry(int* count) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool getPose(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
static bool getPose(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
ovrTrackingState *ts = refreshTracking();
|
||||
ovrPosef* pose;
|
||||
|
||||
if (PATH_EQ(path, P_HEAD)) {
|
||||
if (!strcmp(path, "head")) {
|
||||
pose = &ts->HeadPose.ThePose;
|
||||
} else if (PATH_STARTS_WITH(path, P_HAND) && (path.p[1] == P_LEFT || path.p[1] == P_RIGHT)) {
|
||||
pose = &ts->HandPoses[path.p[1] - P_LEFT].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;
|
||||
}
|
||||
|
@ -185,14 +187,16 @@ static bool getPose(Path path, float* x, float* y, float* z, float* angle, float
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) {
|
||||
static bool getVelocity(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) {
|
||||
ovrTrackingState *ts = refreshTracking();
|
||||
ovrPosef* pose;
|
||||
ovrPoseStatef* pose;
|
||||
|
||||
if (PATH_EQ(path, P_HEAD)) {
|
||||
velocity = &ts->HeadPose;
|
||||
} else if (PATH_STARTS_WITH(path, P_HAND) && (path.p[1] == P_LEFT || path.p[1] == P_RIGHT)) {
|
||||
velocity = &ts->HandPoses[path.p[1] - P_LEFT];
|
||||
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;
|
||||
}
|
||||
|
@ -212,87 +216,86 @@ static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool isDown(Path path, bool* down) {
|
||||
if (PATH_EQ(path, P_HEAD, P_PROXIMITY)) {
|
||||
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 isDown(const char* path, bool* down) {
|
||||
if (!strcmp(path, "head/proximity")) {
|
||||
ovrSessionStatus status;
|
||||
ovr_GetSessionStatus(state.session, &status);
|
||||
*down = status.HmdMounted;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make sure the path starts with /hand/left or /hand/right and only has 3 pieces
|
||||
if (path.p[0] != P_HAND || (path.p[1] != P_LEFT && path.p[1] != P_RIGHT) || path.p[3] != P_NONE) {
|
||||
return false;
|
||||
}
|
||||
ovrHandType hand;
|
||||
uint32_t mask;
|
||||
const char* button;
|
||||
|
||||
ovrHandType hand = path.p[1] - P_LEFT;
|
||||
ovrInputState* is = refreshButtons();
|
||||
uint32_t mask = is->Buttons & (hand == ovrHand_Left ? ovrButton_LMask : ovrButton_RMask);
|
||||
|
||||
switch (path.p[2]) {
|
||||
case P_A: *down = (mask & ovrButton_A); return true;
|
||||
case P_B: *down = (mask & ovrButton_B); return true;
|
||||
case P_X: *down = (mask & ovrButton_X); return true;
|
||||
case P_Y: *down = (mask & ovrButton_Y); return true;
|
||||
case P_MENU: *down = (mask & ovrButton_Enter); return true;
|
||||
case P_TRIGGER: *down = (is->IndexTriggerNoDeadzone[hand] > 0.5f); return true;
|
||||
case P_JOYSTICK: *down = (mask & (ovrButton_LThumb | ovrButton_RThumb)); return true;
|
||||
case P_GRIP: *down = (is->HandTrigger[hand] > 0.9f); return true;
|
||||
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; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isTouched(Path path, bool* touched) {
|
||||
static bool isTouched(const char* path, bool* touched) {
|
||||
ovrHandType hand;
|
||||
uint32_t mask;
|
||||
const char* button;
|
||||
|
||||
// Make sure the path starts with /hand/left or /hand/right and only has 3 pieces
|
||||
if (path.p[0] != P_HAND || (path.p[1] != P_LEFT && path.p[1] != P_RIGHT) || path.p[3] != P_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ovrHandType hand = path.p[1] - P_LEFT;
|
||||
ovrInputState* is = refreshButtons();
|
||||
uint32_t mask = is->Buttons & (hand == ovrHand_Left ? ovrButton_LMask : ovrButton_RMask);
|
||||
|
||||
switch (path.p[2]) {
|
||||
case P_A: *touched = (mask & ovrTouch_A); return true;
|
||||
case P_B: *touched = (mask & ovrTouch_B); return true;
|
||||
case P_X: *touched = (mask & ovrTouch_X); return true;
|
||||
case P_Y: *touched = (mask & ovrTouch_Y); return true;
|
||||
case P_TRIGGER: *touched = (mask & (ovrTouch_LIndexTrigger | ovrTouch_RIndexTrigger)); return true;
|
||||
case P_JOYSTICK: *touched = (mask & (ovrTouch_LThumb | ovrTouch_RThumb)); return true;
|
||||
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; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int getAxis(Path path, float* x, float* y, float* z) {
|
||||
static int getAxis(const char* path, float* x, float* y, float* z) {
|
||||
ovrHandType hand;
|
||||
uint32_t mask;
|
||||
const char* button;
|
||||
|
||||
// Make sure the path starts with /hand/left or /hand/right and only has 3 pieces
|
||||
if (path.p[0] != P_HAND || (path.p[1] != P_LEFT && path.p[1] != P_RIGHT) || path.p[3] != P_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ovrInputState *is = refreshButtons();
|
||||
ovrHandType hand = path.p[1] - P_LEFT;
|
||||
|
||||
switch (path.p[2]) {
|
||||
case P_GRIP: *x = is->HandTriggerNoDeadzone[hand]; return 1;
|
||||
case P_TRIGGER: *x = is->IndexTriggerNoDeadzone[hand]; return 1;
|
||||
case P_JOYSTICK:
|
||||
*x = is->ThumbstickNoDeadzone[hand].x;
|
||||
*y = is->ThumbstickNoDeadzone[hand].y;
|
||||
return 2;
|
||||
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; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool vibrate(Path path, float strength, float duration, float frequency) {
|
||||
static bool vibrate(const char* path, float strength, float duration, float frequency) {
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
static ModelData* newModelData(Path path) {
|
||||
static ModelData* newModelData(const char* path) {
|
||||
return NULL; // TODO
|
||||
}
|
||||
|
||||
|
|
|
@ -74,12 +74,12 @@ static const float* getBoundsGeometry(int* count) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool getPose(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
static bool getPose(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
BridgeLovrPose* pose;
|
||||
|
||||
if (PATH_EQ(path, P_HEAD)) {
|
||||
if (!strcmp(path, "head")) {
|
||||
pose = &bridgeLovrMobileData.updateData.lastHeadPose;
|
||||
} else if (PATH_EQ(path, P_HAND)) {
|
||||
} else if (!strcmp(path, "hand")) {
|
||||
pose = &bridgeLovrMobileData.updateData.goPose;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -98,12 +98,12 @@ static bool getPose(Path path, float* x, float* y, float* z, float* angle, float
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) {
|
||||
static bool getVelocity(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) {
|
||||
BridgeLovrVel* velocity;
|
||||
|
||||
if (PATH_EQ(path, P_HEAD)) {
|
||||
if (!strcmp(path, "head")) {
|
||||
velocity = &bridgeLovrMobileData.updateData.lastHeadVelocity;
|
||||
} else if (PATH_EQ(path, P_HAND)) {
|
||||
} else if (!strcmp(path, "hand")) {
|
||||
velocity = &bridgeLovrMobileData.updateData.goVelocity;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -124,50 +124,46 @@ static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool buttonCheck(BridgeLovrButton field, Path path, bool* result) {
|
||||
if (!PATH_EQ(path, P_HAND) || path.p[2] != P_NONE) {
|
||||
return false; // Path needs to start with /hand and have exactly one more piece
|
||||
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; }
|
||||
}
|
||||
|
||||
switch (path.p[1]) {
|
||||
case P_MENU: *result = (field & BRIDGE_LOVR_BUTTON_MENU); return true;
|
||||
case P_TRIGGER: *result = (field & BRIDGE_LOVR_BUTTON_SHOULDER); return true;
|
||||
case P_TRACKPAD: *result = (field & BRIDGE_LOVR_BUTTON_TOUCHPAD); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isDown(Path path, bool* down) {
|
||||
return buttonCheck(bridgeLovrMobileData.updateData.goButtonDown, path, down);
|
||||
}
|
||||
|
||||
static bool isTouched(Path path, bool* touched) {
|
||||
return buttonCheck(bridgeLovrMobileData.updateData.goButtonTouch, path, touched);
|
||||
}
|
||||
|
||||
static int getAxis(Path path, float* x, float* y, float* z) {
|
||||
if (!PATH_EQ(path, P_HAND) || path.p[2] != P_NONE) {
|
||||
return 0; // Path needs to start with /hand and have exactly one more piece
|
||||
}
|
||||
|
||||
switch (path.p[1]) {
|
||||
case P_TRACKPAD:
|
||||
*x = (bridgeLovrMobileData.updateData.goTrackpad.x - 160.f) / 160.f;
|
||||
*y = (bridgeLovrMobileData.updateData.goTrackpad.y - 160.f) / 160.f;
|
||||
return 2;
|
||||
case P_TRIGGER:
|
||||
*x = bridgeLovrMobileData.updateData.goButtonDown ? 1.f : 0.f;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool vibrate(Path path, float strength, float duration, float frequency) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static ModelData* newModelData(Path path) {
|
||||
static bool isDown(const char* path, bool* down) {
|
||||
return buttonCheck(bridgeLovrMobileData.updateData.goButtonDown, path, down);
|
||||
}
|
||||
|
||||
static bool isTouched(const char* path, bool* touched) {
|
||||
return buttonCheck(bridgeLovrMobileData.updateData.goButtonTouch, path, touched);
|
||||
}
|
||||
|
||||
static int 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 vibrate(const char* path, float strength, float duration, float frequency) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static ModelData* newModelData(const char* path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ extern void VR_ShutdownInternal();
|
|||
extern bool VR_IsHmdPresent();
|
||||
extern intptr_t VR_GetGenericInterface(const char* pchInterfaceVersion, EVRInitError* peError);
|
||||
extern bool VR_IsRuntimeInstalled();
|
||||
#define HEADSET_INDEX k_unTrackedDeviceIndex_Hmd
|
||||
#define INVALID_INDEX k_unTrackedDeviceIndexInvalid
|
||||
#define HEADSET k_unTrackedDeviceIndex_Hmd
|
||||
#define INVALID_DEVICE k_unTrackedDeviceIndexInvalid
|
||||
|
||||
static struct {
|
||||
struct VR_IVRSystem_FnTable* system;
|
||||
|
@ -43,111 +43,24 @@ static struct {
|
|||
int msaa;
|
||||
} state;
|
||||
|
||||
static bool getTransform(unsigned int device, mat4 transform) {
|
||||
TrackedDevicePose_t pose = state.poses[device];
|
||||
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
|
||||
return false;
|
||||
} else {
|
||||
mat4_fromMat34(transform, pose.mDeviceToAbsoluteTracking.m);
|
||||
transform[13] += state.offset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static TrackedDeviceIndex_t getDeviceIndexForPath(Path path) {
|
||||
if (PATH_EQ(path, P_HEAD)) {
|
||||
return HEADSET_INDEX;
|
||||
} else if (PATH_EQ(path, P_HAND, P_LEFT)) {
|
||||
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 (PATH_EQ(path, P_HAND, P_RIGHT)) {
|
||||
} else if (!strcmp(path, "hand/right")) {
|
||||
if (next) *next = path + strlen("hand/right/");
|
||||
return state.system->GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole_TrackedControllerRole_RightHand);
|
||||
} else if (path.p[0] == P_TRACKER && path.p[1] >= P_1 && path.p[1] <= P_8 && path.p[2] == P_NONE) {
|
||||
} 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);
|
||||
uint32_t index = path.p[1] - P_1;
|
||||
return index < trackerCount ? indices[index] : k_unTrackedDeviceIndexInvalid;
|
||||
return (index >= 0 && index < trackerCount) ? indices[index] : INVALID_DEVICE;
|
||||
} else {
|
||||
return k_unTrackedDeviceIndexInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
static bool getButtonState(Path path, bool touch, bool* value) {
|
||||
VRControllerState_t input;
|
||||
|
||||
if (PATH_EQ(path, P_HEAD, P_PROXIMITY) && !touch) {
|
||||
if (!state.system->GetControllerState(HEADSET_INDEX, &input, sizeof(input))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = (input.ulButtonPressed >> EVRButtonId_k_EButton_ProximitySensor) & 1;
|
||||
return true;
|
||||
} else if (!PATH_STARTS_WITH(path, P_HAND, P_LEFT) && !PATH_STARTS_WITH(path, P_HAND, P_RIGHT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path);
|
||||
if (deviceIndex == INVALID_INDEX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!state.system->GetControllerState(deviceIndex, &input, sizeof(input))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t mask = touch ? input.ulButtonTouched : input.ulButtonPressed;
|
||||
|
||||
if (state.rift) {
|
||||
switch (path.p[2]) {
|
||||
case P_TRIGGER:
|
||||
*value = (mask >> EVRButtonId_k_EButton_Axis1) & 1;
|
||||
return true;
|
||||
|
||||
case P_GRIP:
|
||||
*value = (mask >> EVRButtonId_k_EButton_Axis2) & 1;
|
||||
return true;
|
||||
|
||||
case P_TRACKPAD:
|
||||
*value = (mask >> EVRButtonId_k_EButton_Axis0) & 1;
|
||||
return true;
|
||||
|
||||
case P_A:
|
||||
*value = path.p[1] == P_RIGHT && (mask >> EVRButtonId_k_EButton_A) & 1;
|
||||
return true;
|
||||
|
||||
case P_B:
|
||||
*value = path.p[1] == P_RIGHT && (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1;
|
||||
return true;
|
||||
|
||||
case P_X:
|
||||
*value = path.p[1] == P_LEFT && (mask >> EVRButtonId_k_EButton_A) & 1;
|
||||
return true;
|
||||
|
||||
case P_Y:
|
||||
*value = path.p[1] == P_LEFT && (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1;
|
||||
return true;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
} else {
|
||||
switch (path.p[2]) {
|
||||
case P_TRIGGER:
|
||||
*value = (mask >> EVRButtonId_k_EButton_SteamVR_Trigger) & 1;
|
||||
return true;
|
||||
|
||||
case P_TRACKPAD:
|
||||
*value = (mask >> EVRButtonId_k_EButton_SteamVR_Touchpad) & 1;
|
||||
return true;
|
||||
|
||||
case P_MENU:
|
||||
*value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1;
|
||||
return true;
|
||||
|
||||
case P_GRIP:
|
||||
*value = (mask >> EVRButtonId_k_EButton_Grip) & 1;
|
||||
return true;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
return INVALID_DEVICE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +117,7 @@ static void destroy(void) {
|
|||
|
||||
static bool getName(char* name, size_t length) {
|
||||
ETrackedPropertyError error;
|
||||
state.system->GetStringTrackedDeviceProperty(HEADSET_INDEX, ETrackedDeviceProperty_Prop_ManufacturerName_String, name, length, &error);
|
||||
state.system->GetStringTrackedDeviceProperty(HEADSET, ETrackedDeviceProperty_Prop_ManufacturerName_String, name, length, &error);
|
||||
return error == ETrackedPropertyError_TrackedProp_Success;
|
||||
}
|
||||
|
||||
|
@ -252,135 +165,137 @@ static const float* getBoundsGeometry(int* count) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool getPose(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path);
|
||||
float transform[16];
|
||||
if (deviceIndex != INVALID_INDEX && getTransform(deviceIndex, transform)) {
|
||||
mat4_getTransform(transform, x, y, z, NULL, NULL, NULL, angle, ax, ay, az);
|
||||
static bool getTransform(unsigned int device, mat4 transform) {
|
||||
TrackedDevicePose_t pose = state.poses[device];
|
||||
if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) {
|
||||
return false;
|
||||
} else {
|
||||
mat4_fromMat34(transform, pose.mDeviceToAbsoluteTracking.m);
|
||||
transform[13] += state.offset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool getPose(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) {
|
||||
float transform[16];
|
||||
TrackedDeviceIndex_t device = pathToDevice(path, NULL);
|
||||
if (device == INVALID_DEVICE && !getTransform(device, transform)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mat4_getTransform(transform, x, y, z, NULL, NULL, NULL, angle, ax, ay, az);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getVelocity(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) {
|
||||
TrackedDeviceIndex_t device = pathToDevice(path, NULL);
|
||||
TrackedDevicePose_t* pose = &state.poses[device];
|
||||
if (device == INVALID_DEVICE || !pose->bPoseIsValid || !pose->bDeviceIsConnected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vx) {
|
||||
*vx = pose->vVelocity.v[0];
|
||||
*vy = pose->vVelocity.v[1];
|
||||
*vz = pose->vVelocity.v[2];
|
||||
}
|
||||
|
||||
if (vax) {
|
||||
*vax = pose->vAngularVelocity.v[0];
|
||||
*vay = pose->vAngularVelocity.v[1];
|
||||
*vaz = pose->vAngularVelocity.v[2];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getButtonState(const char* path, bool touch, bool* value) {
|
||||
VRControllerState_t input;
|
||||
|
||||
if (!strcmp(path, "head/proximity") && !touch) {
|
||||
if (!state.system->GetControllerState(HEADSET, &input, sizeof(input))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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))) {
|
||||
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; }
|
||||
} 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; }
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) {
|
||||
TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path);
|
||||
if (deviceIndex == INVALID_INDEX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TrackedDevicePose_t* pose = &state.poses[deviceIndex];
|
||||
if (!pose->bPoseIsValid || !pose->bDeviceIsConnected) {
|
||||
return false;
|
||||
} else {
|
||||
if (vx) {
|
||||
*vx = pose->vVelocity.v[0];
|
||||
*vy = pose->vVelocity.v[1];
|
||||
*vz = pose->vVelocity.v[2];
|
||||
}
|
||||
|
||||
if (vax) {
|
||||
*vax = pose->vAngularVelocity.v[0];
|
||||
*vay = pose->vAngularVelocity.v[1];
|
||||
*vaz = pose->vAngularVelocity.v[2];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isDown(Path path, bool* down) {
|
||||
static bool isDown(const char* path, bool* down) {
|
||||
return getButtonState(path, false, down);
|
||||
}
|
||||
|
||||
static bool isTouched(Path path, bool* touched) {
|
||||
static bool isTouched(const char* path, bool* touched) {
|
||||
return getButtonState(path, true, touched);
|
||||
}
|
||||
|
||||
static int getAxis(Path path, float* x, float* y, float* z) {
|
||||
if (path.p[3] != P_NONE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path);
|
||||
if (deviceIndex == INVALID_INDEX) {
|
||||
return 0;
|
||||
}
|
||||
static int getAxis(const char* path, float* x, float* y, float* z) {
|
||||
const char* axis;
|
||||
TrackedDeviceIndex_t device = pathToDevice(path, &axis);
|
||||
|
||||
VRControllerState_t input;
|
||||
if (!state.system->GetControllerState(deviceIndex, &input, sizeof(input))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state.rift) {
|
||||
switch (path.p[2]) {
|
||||
case P_TRIGGER:
|
||||
*x = input.rAxis[1].x;
|
||||
return 1;
|
||||
|
||||
case P_GRIP:
|
||||
*x = input.rAxis[2].x;
|
||||
return 1;
|
||||
|
||||
case P_TRACKPAD:
|
||||
*x = input.rAxis[0].x;
|
||||
*y = input.rAxis[0].y;
|
||||
return 2;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
} else {
|
||||
switch (path.p[2]) {
|
||||
case P_TRIGGER:
|
||||
*x = input.rAxis[1].x;
|
||||
return 1;
|
||||
|
||||
case P_TRACKPAD:
|
||||
*x = input.rAxis[0].x;
|
||||
*y = input.rAxis[0].y;
|
||||
return 2;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
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; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool vibrate(Path path, float strength, float duration, float frequency) {
|
||||
static bool vibrate(const char* path, float strength, float duration, float frequency) {
|
||||
if (duration <= 0) return false;
|
||||
if (!PATH_STARTS_WITH(path, P_HAND)) return false;
|
||||
|
||||
TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path);
|
||||
if (deviceIndex == INVALID_INDEX) return false;
|
||||
TrackedDeviceIndex_t device = pathToDevice(path, NULL);
|
||||
if (device == INVALID_DEVICE) return false;
|
||||
|
||||
unsigned short uSeconds = (unsigned short) (duration * 1e6f);
|
||||
state.system->TriggerHapticPulse(deviceIndex, 0, uSeconds);
|
||||
unsigned short uSeconds = (unsigned short) (duration * 1e6f + .5f);
|
||||
state.system->TriggerHapticPulse(device, 0, uSeconds);
|
||||
return true;
|
||||
}
|
||||
|
||||
static ModelData* newModelData(Path path) {
|
||||
TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path);
|
||||
if (deviceIndex == INVALID_INDEX) return false;
|
||||
static ModelData* newModelData(const char* path) {
|
||||
TrackedDeviceIndex_t device = pathToDevice(path, NULL);
|
||||
if (device == INVALID_DEVICE) return false;
|
||||
|
||||
// Get model name
|
||||
char renderModelName[1024];
|
||||
ETrackedDeviceProperty renderModelNameProperty = ETrackedDeviceProperty_Prop_RenderModelName_String;
|
||||
state.system->GetStringTrackedDeviceProperty(deviceIndex, renderModelNameProperty, renderModelName, 1024, NULL);
|
||||
state.system->GetStringTrackedDeviceProperty(device, renderModelNameProperty, renderModelName, 1024, NULL);
|
||||
|
||||
// Load model
|
||||
if (!state.deviceModels[deviceIndex]) {
|
||||
while (state.renderModels->LoadRenderModel_Async(renderModelName, &state.deviceModels[deviceIndex]) == EVRRenderModelError_VRRenderModelError_Loading) {
|
||||
if (!state.deviceModels[device]) {
|
||||
while (state.renderModels->LoadRenderModel_Async(renderModelName, &state.deviceModels[device]) == EVRRenderModelError_VRRenderModelError_Loading) {
|
||||
lovrSleep(.001);
|
||||
}
|
||||
}
|
||||
|
||||
// Load texture
|
||||
if (!state.deviceTextures[deviceIndex]) {
|
||||
while (state.renderModels->LoadTexture_Async(state.deviceModels[deviceIndex]->diffuseTextureId, &state.deviceTextures[deviceIndex]) == EVRRenderModelError_VRRenderModelError_Loading) {
|
||||
if (!state.deviceTextures[device]) {
|
||||
while (state.renderModels->LoadTexture_Async(state.deviceModels[device]->diffuseTextureId, &state.deviceTextures[device]) == EVRRenderModelError_VRRenderModelError_Loading) {
|
||||
lovrSleep(.001);
|
||||
}
|
||||
}
|
||||
|
||||
RenderModel_t* vrModel = state.deviceModels[deviceIndex];
|
||||
RenderModel_t* vrModel = state.deviceModels[device];
|
||||
ModelData* model = lovrAlloc(ModelData);
|
||||
size_t vertexSize = sizeof(RenderModel_Vertex_t);
|
||||
|
||||
|
@ -436,7 +351,7 @@ static ModelData* newModelData(Path path) {
|
|||
.components = 1
|
||||
};
|
||||
|
||||
RenderModel_TextureMap_t* vrTexture = state.deviceTextures[deviceIndex];
|
||||
RenderModel_TextureMap_t* vrTexture = state.deviceTextures[device];
|
||||
model->textures[0] = lovrTextureDataCreate(vrTexture->unWidth, vrTexture->unHeight, 0, FORMAT_RGBA);
|
||||
memcpy(model->textures[0]->blob.data, vrTexture->rubTextureMapData, vrTexture->unWidth * vrTexture->unHeight * 4);
|
||||
|
||||
|
@ -482,7 +397,7 @@ static void renderTo(void (*callback)(void*), void* userdata) {
|
|||
Camera camera = { .canvas = state.canvas, .viewMatrix = { MAT4_IDENTITY, MAT4_IDENTITY } };
|
||||
|
||||
float head[16], eye[16];
|
||||
getTransform(HEADSET_INDEX, head);
|
||||
getTransform(HEADSET, head);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
EVREye vrEye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right;
|
||||
|
|
Loading…
Reference in New Issue