2017-12-10 20:40:37 +00:00
|
|
|
#include "api.h"
|
2016-11-19 09:28:01 +00:00
|
|
|
#include "headset/headset.h"
|
2019-04-03 04:28:41 +00:00
|
|
|
#include "data/modelData.h"
|
|
|
|
#include "graphics/model.h"
|
2019-01-25 20:08:45 +00:00
|
|
|
#include "graphics/texture.h"
|
2019-06-08 10:45:03 +00:00
|
|
|
#include "core/arr.h"
|
2019-05-20 09:47:33 +00:00
|
|
|
#include "core/maf.h"
|
2019-06-02 07:20:10 +00:00
|
|
|
#include "core/ref.h"
|
|
|
|
#include <stdlib.h>
|
2016-08-11 04:17:14 +00:00
|
|
|
|
2018-10-25 03:40:11 +00:00
|
|
|
#if defined(EMSCRIPTEN) || defined(LOVR_USE_OCULUS_MOBILE)
|
|
|
|
#define LOVR_HEADSET_HELPER_USES_REGISTRY
|
|
|
|
#endif
|
|
|
|
|
2018-07-05 03:11:52 +00:00
|
|
|
const char* HeadsetDrivers[] = {
|
2019-03-07 07:02:03 +00:00
|
|
|
[DRIVER_DESKTOP] = "desktop",
|
2019-04-09 19:38:55 +00:00
|
|
|
[DRIVER_LEAP_MOTION] = "leap",
|
2018-09-09 17:58:20 +00:00
|
|
|
[DRIVER_OCULUS] = "oculus",
|
2018-10-25 03:40:11 +00:00
|
|
|
[DRIVER_OCULUS_MOBILE] = "oculusmobile",
|
2018-07-05 03:11:52 +00:00
|
|
|
[DRIVER_OPENVR] = "openvr",
|
2019-04-30 23:21:30 +00:00
|
|
|
[DRIVER_OPENXR] = "openxr",
|
2018-07-05 03:11:52 +00:00
|
|
|
[DRIVER_WEBVR] = "webvr",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
const char* HeadsetOrigins[] = {
|
|
|
|
[ORIGIN_HEAD] = "head",
|
|
|
|
[ORIGIN_FLOOR] = "floor",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2019-05-08 03:04:59 +00:00
|
|
|
const char* Devices[] = {
|
|
|
|
[DEVICE_HEAD] = "head",
|
|
|
|
[DEVICE_HAND_LEFT] = "hand/left",
|
|
|
|
[DEVICE_HAND_RIGHT] = "hand/right",
|
|
|
|
[DEVICE_EYE_LEFT] = "eye/left",
|
2019-05-22 21:37:46 +00:00
|
|
|
[DEVICE_EYE_RIGHT] = "eye/right",
|
2019-05-08 03:04:59 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
const char* DeviceButtons[] = {
|
2019-05-31 19:00:15 +00:00
|
|
|
[BUTTON_PRIMARY] = "primary",
|
2019-05-08 03:04:59 +00:00
|
|
|
[BUTTON_TRIGGER] = "trigger",
|
|
|
|
[BUTTON_THUMBSTICK] = "thumbstick",
|
2019-05-08 23:57:51 +00:00
|
|
|
[BUTTON_TOUCHPAD] = "touchpad",
|
2019-05-08 03:04:59 +00:00
|
|
|
[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[] = {
|
2019-05-31 19:00:15 +00:00
|
|
|
[AXIS_PRIMARY] = "primary",
|
2019-05-08 03:04:59 +00:00
|
|
|
[AXIS_TRIGGER] = "trigger",
|
2019-05-13 05:04:41 +00:00
|
|
|
[AXIS_THUMBSTICK] = "thumbstick",
|
|
|
|
[AXIS_TOUCHPAD] = "touchpad",
|
2019-05-08 03:04:59 +00:00
|
|
|
[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
|
|
|
|
};
|
|
|
|
|
2017-04-16 23:56:49 +00:00
|
|
|
typedef struct {
|
|
|
|
lua_State* L;
|
|
|
|
int ref;
|
|
|
|
} HeadsetRenderData;
|
|
|
|
|
|
|
|
static HeadsetRenderData headsetRenderData;
|
|
|
|
|
2018-03-11 07:42:33 +00:00
|
|
|
static void renderHelper(void* userdata) {
|
2017-04-16 23:56:49 +00:00
|
|
|
HeadsetRenderData* renderData = userdata;
|
2019-03-06 16:42:32 +00:00
|
|
|
lua_State* L = renderData->L;
|
2018-10-25 03:40:11 +00:00
|
|
|
#ifdef LOVR_HEADSET_HELPER_USES_REGISTRY
|
2019-03-06 18:05:20 +00:00
|
|
|
luax_geterror(L);
|
|
|
|
if (lua_isnil(L, -1)) {
|
2018-11-13 07:43:36 +00:00
|
|
|
lua_pushcfunction(L, luax_getstack);
|
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, renderData->ref);
|
|
|
|
if (lua_pcall(L, 0, 0, -2)) {
|
2019-03-06 18:05:20 +00:00
|
|
|
luax_seterror(L);
|
2018-11-13 07:43:36 +00:00
|
|
|
}
|
|
|
|
lua_pop(L, 1); // pop luax_getstack
|
|
|
|
}
|
2019-03-06 18:05:20 +00:00
|
|
|
lua_pop(L, 1);
|
2018-06-04 00:18:42 +00:00
|
|
|
#else
|
2018-03-11 07:42:33 +00:00
|
|
|
lua_call(L, 0, 0);
|
2018-11-13 07:43:36 +00:00
|
|
|
#endif
|
2018-11-13 06:34:02 +00:00
|
|
|
}
|
|
|
|
|
2019-05-08 09:56:20 +00:00
|
|
|
static Device luax_optdevice(lua_State* L, int index) {
|
|
|
|
const char* str = luaL_optstring(L, 1, "head");
|
|
|
|
if (!strcmp(str, "left")) {
|
|
|
|
return DEVICE_HAND_LEFT;
|
|
|
|
} else if (!strcmp(str, "right")) {
|
|
|
|
return DEVICE_HAND_RIGHT;
|
|
|
|
}
|
|
|
|
return luaL_checkoption(L, 1, "head", Devices);
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetDriver(lua_State* L) {
|
2019-05-08 11:10:22 +00:00
|
|
|
if (lua_gettop(L) == 0) {
|
|
|
|
lua_pushstring(L, HeadsetDrivers[lovrHeadsetDriver->driverType]);
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
Device device = luax_optdevice(L, 1);
|
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
|
|
|
if (driver->getPose(device, NULL, NULL)) {
|
|
|
|
lua_pushstring(L, HeadsetDrivers[driver->driverType]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
2017-11-25 21:01:56 +00:00
|
|
|
}
|
|
|
|
|
2019-04-06 22:09:20 +00:00
|
|
|
static int l_lovrHeadsetGetName(lua_State* L) {
|
2019-04-19 04:03:38 +00:00
|
|
|
char name[256];
|
|
|
|
if (lovrHeadsetDriver->getName(name, sizeof(name))) {
|
|
|
|
lua_pushstring(L, name);
|
|
|
|
} else {
|
|
|
|
lua_pushnil(L);
|
|
|
|
}
|
2016-10-01 21:12:55 +00:00
|
|
|
return 1;
|
2016-08-11 04:17:14 +00:00
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetOriginType(lua_State* L) {
|
2018-07-05 03:11:52 +00:00
|
|
|
lua_pushstring(L, HeadsetOrigins[lovrHeadsetDriver->getOriginType()]);
|
2017-08-04 05:21:49 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-06-30 00:33:49 +00:00
|
|
|
static int l_lovrHeadsetGetDisplayTime(lua_State* L) {
|
|
|
|
lua_pushnumber(L, lovrHeadsetDriver->getDisplayTime());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetDisplayWidth(lua_State* L) {
|
2018-10-21 15:40:57 +00:00
|
|
|
uint32_t width, height;
|
2018-08-25 23:16:58 +00:00
|
|
|
lovrHeadsetDriver->getDisplayDimensions(&width, &height);
|
2018-10-21 15:40:57 +00:00
|
|
|
lua_pushinteger(L, width);
|
2016-10-24 23:03:29 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetDisplayHeight(lua_State* L) {
|
2018-10-21 15:40:57 +00:00
|
|
|
uint32_t width, height;
|
2018-08-25 23:16:58 +00:00
|
|
|
lovrHeadsetDriver->getDisplayDimensions(&width, &height);
|
2018-10-21 15:40:57 +00:00
|
|
|
lua_pushinteger(L, height);
|
2016-10-24 23:03:29 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetDisplayDimensions(lua_State* L) {
|
2018-10-21 15:40:57 +00:00
|
|
|
uint32_t width, height;
|
2018-04-28 23:59:53 +00:00
|
|
|
lovrHeadsetDriver->getDisplayDimensions(&width, &height);
|
2018-10-21 15:40:57 +00:00
|
|
|
lua_pushinteger(L, width);
|
|
|
|
lua_pushinteger(L, height);
|
2016-10-24 23:03:29 +00:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2019-06-28 07:13:30 +00:00
|
|
|
static int l_lovrHeadsetGetDisplayMask(lua_State* L) {
|
|
|
|
uint32_t count;
|
|
|
|
const float* points = lovrHeadsetDriver->getDisplayMask(&count);
|
|
|
|
|
|
|
|
if (!points) {
|
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_createtable(L, count, 0);
|
|
|
|
for (uint32_t i = 0; i < count; i += 2) {
|
|
|
|
lua_createtable(L, 2, 0);
|
|
|
|
|
|
|
|
lua_pushnumber(L, points[i + 0]);
|
|
|
|
lua_rawseti(L, -2, 1);
|
|
|
|
lua_pushnumber(L, points[i + 1]);
|
|
|
|
lua_rawseti(L, -2, 2);
|
|
|
|
|
|
|
|
lua_rawseti(L, -2, i / 2 + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetClipDistance(lua_State* L) {
|
2018-02-23 05:01:34 +00:00
|
|
|
float clipNear, clipFar;
|
2018-04-28 23:59:53 +00:00
|
|
|
lovrHeadsetDriver->getClipDistance(&clipNear, &clipFar);
|
2018-02-23 05:01:34 +00:00
|
|
|
lua_pushnumber(L, clipNear);
|
|
|
|
lua_pushnumber(L, clipFar);
|
2016-09-27 06:48:09 +00:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetSetClipDistance(lua_State* L) {
|
2019-01-29 10:28:55 +00:00
|
|
|
float clipNear = luax_checkfloat(L, 1);
|
|
|
|
float clipFar = luax_checkfloat(L, 2);
|
2018-04-28 23:59:53 +00:00
|
|
|
lovrHeadsetDriver->setClipDistance(clipNear, clipFar);
|
2016-10-01 21:12:55 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetBoundsWidth(lua_State* L) {
|
2018-04-29 21:38:08 +00:00
|
|
|
float width, depth;
|
|
|
|
lovrHeadsetDriver->getBoundsDimensions(&width, &depth);
|
|
|
|
lua_pushnumber(L, width);
|
2016-11-24 04:54:04 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetBoundsDepth(lua_State* L) {
|
2018-04-29 21:38:08 +00:00
|
|
|
float width, depth;
|
|
|
|
lovrHeadsetDriver->getBoundsDimensions(&width, &depth);
|
|
|
|
lua_pushnumber(L, depth);
|
2016-11-24 04:54:04 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetGetBoundsDimensions(lua_State* L) {
|
2018-04-29 21:38:08 +00:00
|
|
|
float width, depth;
|
|
|
|
lovrHeadsetDriver->getBoundsDimensions(&width, &depth);
|
|
|
|
lua_pushnumber(L, width);
|
|
|
|
lua_pushnumber(L, depth);
|
2016-10-01 21:17:26 +00:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2018-10-10 00:51:05 +00:00
|
|
|
static int l_lovrHeadsetGetBoundsGeometry(lua_State* L) {
|
2019-05-21 03:35:07 +00:00
|
|
|
uint32_t count;
|
2018-10-10 00:51:05 +00:00
|
|
|
const float* points = lovrHeadsetDriver->getBoundsGeometry(&count);
|
|
|
|
|
|
|
|
if (!points) {
|
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lua_type(L, 1) == LUA_TTABLE) {
|
|
|
|
lua_settop(L, 1);
|
|
|
|
} else {
|
|
|
|
lua_settop(L, 0);
|
2019-06-08 10:45:03 +00:00
|
|
|
lua_createtable(L, count / 4, 0);
|
2018-10-10 00:51:05 +00:00
|
|
|
}
|
|
|
|
|
2019-06-08 10:45:03 +00:00
|
|
|
int j = 1;
|
|
|
|
for (uint32_t i = 0; i < count; i += 4) {
|
|
|
|
lua_pushnumber(L, points[i + 0]);
|
|
|
|
lua_rawseti(L, 1, j++);
|
|
|
|
lua_pushnumber(L, points[i + 1]);
|
|
|
|
lua_rawseti(L, 1, j++);
|
|
|
|
lua_pushnumber(L, points[i + 2]);
|
|
|
|
lua_rawseti(L, 1, j++);
|
2018-10-10 00:51:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-03-31 08:53:20 +00:00
|
|
|
int l_lovrHeadsetGetPose(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-06-03 14:13:52 +00:00
|
|
|
float position[4], orientation[4];
|
2019-03-20 00:21:16 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-08 03:04:59 +00:00
|
|
|
if (driver->getPose(device, position, orientation)) {
|
2019-04-30 23:21:49 +00:00
|
|
|
float angle, ax, ay, az;
|
|
|
|
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
|
|
|
|
lua_pushnumber(L, position[0]);
|
|
|
|
lua_pushnumber(L, position[1]);
|
|
|
|
lua_pushnumber(L, position[2]);
|
2019-03-20 00:21:16 +00:00
|
|
|
lua_pushnumber(L, angle);
|
|
|
|
lua_pushnumber(L, ax);
|
|
|
|
lua_pushnumber(L, ay);
|
|
|
|
lua_pushnumber(L, az);
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
for (int i = 0; i < 7; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
}
|
|
|
|
return 7;
|
2016-10-01 21:12:55 +00:00
|
|
|
}
|
|
|
|
|
2019-03-31 08:53:20 +00:00
|
|
|
int l_lovrHeadsetGetPosition(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-06-03 14:13:52 +00:00
|
|
|
float position[4], orientation[4];
|
2019-03-20 00:21:16 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-09 09:17:33 +00:00
|
|
|
if (driver->getPose(device, position, orientation)) {
|
2019-04-30 23:21:49 +00:00
|
|
|
lua_pushnumber(L, position[0]);
|
|
|
|
lua_pushnumber(L, position[1]);
|
|
|
|
lua_pushnumber(L, position[2]);
|
2019-03-20 00:21:16 +00:00
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
}
|
|
|
|
return 3;
|
2017-01-23 05:20:34 +00:00
|
|
|
}
|
|
|
|
|
2019-03-31 08:53:20 +00:00
|
|
|
int l_lovrHeadsetGetOrientation(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-06-03 14:13:52 +00:00
|
|
|
float position[4], orientation[4];
|
2019-03-20 00:21:16 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-09 09:17:33 +00:00
|
|
|
if (driver->getPose(device, position, orientation)) {
|
2019-04-30 23:21:49 +00:00
|
|
|
float angle, ax, ay, az;
|
|
|
|
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
|
2019-03-20 00:21:16 +00:00
|
|
|
lua_pushnumber(L, angle);
|
|
|
|
lua_pushnumber(L, ax);
|
|
|
|
lua_pushnumber(L, ay);
|
|
|
|
lua_pushnumber(L, az);
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
2019-04-19 02:23:59 +00:00
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
return 4;
|
2019-05-08 09:56:20 +00:00
|
|
|
}
|
|
|
|
|
2019-03-31 08:53:20 +00:00
|
|
|
int l_lovrHeadsetGetVelocity(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-06-03 14:13:52 +00:00
|
|
|
float velocity[4], angularVelocity[4];
|
2019-03-20 00:21:16 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-09 09:17:33 +00:00
|
|
|
if (driver->getVelocity(device, velocity, angularVelocity)) {
|
2019-04-30 23:21:49 +00:00
|
|
|
lua_pushnumber(L, velocity[0]);
|
|
|
|
lua_pushnumber(L, velocity[1]);
|
|
|
|
lua_pushnumber(L, velocity[2]);
|
2019-03-20 00:21:16 +00:00
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
}
|
|
|
|
return 3;
|
2016-08-11 04:17:14 +00:00
|
|
|
}
|
|
|
|
|
2019-03-31 08:53:20 +00:00
|
|
|
int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-06-03 14:13:52 +00:00
|
|
|
float velocity[4], angularVelocity[4];
|
2019-03-20 00:21:16 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-09 09:17:33 +00:00
|
|
|
if (driver->getVelocity(device, velocity, angularVelocity)) {
|
2019-04-30 23:21:49 +00:00
|
|
|
lua_pushnumber(L, angularVelocity[0]);
|
|
|
|
lua_pushnumber(L, angularVelocity[1]);
|
|
|
|
lua_pushnumber(L, angularVelocity[2]);
|
2019-03-20 00:21:16 +00:00
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
}
|
|
|
|
return 3;
|
2016-09-16 06:57:01 +00:00
|
|
|
}
|
|
|
|
|
2019-05-08 10:15:17 +00:00
|
|
|
int l_lovrHeadsetGetAcceleration(lua_State* L) {
|
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-06-03 14:13:52 +00:00
|
|
|
float acceleration[4], angularAcceleration[4];
|
2019-05-08 10:15:17 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-09 09:17:33 +00:00
|
|
|
if (driver->getAcceleration(device, acceleration, angularAcceleration)) {
|
2019-05-08 10:15:17 +00:00
|
|
|
lua_pushnumber(L, acceleration[0]);
|
|
|
|
lua_pushnumber(L, acceleration[1]);
|
|
|
|
lua_pushnumber(L, acceleration[2]);
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
}
|
|
|
|
return 3;
|
2019-05-08 10:15:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrHeadsetGetAngularAcceleration(lua_State* L) {
|
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-06-03 14:13:52 +00:00
|
|
|
float acceleration[4], angularAcceleration[4];
|
2019-05-08 10:15:17 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-09 09:17:33 +00:00
|
|
|
if (driver->getAcceleration(device, acceleration, angularAcceleration)) {
|
2019-05-08 10:15:17 +00:00
|
|
|
lua_pushnumber(L, angularAcceleration[0]);
|
|
|
|
lua_pushnumber(L, angularAcceleration[1]);
|
|
|
|
lua_pushnumber(L, angularAcceleration[2]);
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
}
|
|
|
|
return 3;
|
2019-05-08 10:15:17 +00:00
|
|
|
}
|
|
|
|
|
2019-04-03 05:13:08 +00:00
|
|
|
int l_lovrHeadsetIsDown(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-05-08 03:04:59 +00:00
|
|
|
DeviceButton button = luaL_checkoption(L, 2, NULL, DeviceButtons);
|
2019-04-03 05:13:08 +00:00
|
|
|
bool down;
|
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-08 03:04:59 +00:00
|
|
|
if (driver->isDown(device, button, &down)) {
|
2019-04-03 05:13:08 +00:00
|
|
|
lua_pushboolean(L, down);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
lua_pushboolean(L, false);
|
|
|
|
return 1;
|
2019-04-03 05:13:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrHeadsetIsTouched(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-05-08 03:04:59 +00:00
|
|
|
DeviceButton button = luaL_checkoption(L, 2, NULL, DeviceButtons);
|
2019-04-03 05:13:08 +00:00
|
|
|
bool touched;
|
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-24 22:14:20 +00:00
|
|
|
if (driver->isTouched(device, button, &touched)) {
|
2019-04-03 05:13:08 +00:00
|
|
|
lua_pushboolean(L, touched);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
lua_pushboolean(L, 1);
|
|
|
|
return false;
|
2019-04-03 05:13:08 +00:00
|
|
|
}
|
|
|
|
|
2019-07-18 00:07:33 +00:00
|
|
|
static const size_t axisCounts[MAX_AXES] = {
|
|
|
|
[AXIS_TRIGGER] = 1,
|
|
|
|
[AXIS_PINCH] = 1,
|
|
|
|
[AXIS_GRIP] = 1,
|
|
|
|
[AXIS_PRIMARY] = 2,
|
|
|
|
[AXIS_THUMBSTICK] = 2,
|
|
|
|
[AXIS_TOUCHPAD] = 2
|
|
|
|
};
|
|
|
|
|
2019-04-01 14:25:29 +00:00
|
|
|
int l_lovrHeadsetGetAxis(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-05-08 03:04:59 +00:00
|
|
|
DeviceAxis axis = luaL_checkoption(L, 2, NULL, DeviceAxes);
|
2019-07-18 00:07:33 +00:00
|
|
|
size_t count = axisCounts[axis];
|
2019-06-03 14:13:52 +00:00
|
|
|
float value[4];
|
2019-04-01 14:25:29 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-13 05:04:41 +00:00
|
|
|
if (driver->getAxis(device, axis, value)) {
|
2019-07-18 00:07:33 +00:00
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
|
|
lua_pushnumber(L, value[i]);
|
2019-05-13 05:04:41 +00:00
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
return count;
|
2019-04-01 14:25:29 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:07:33 +00:00
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
}
|
|
|
|
return count;
|
2019-04-01 14:25:29 +00:00
|
|
|
}
|
|
|
|
|
2019-04-01 15:41:27 +00:00
|
|
|
int l_lovrHeadsetVibrate(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-04-01 15:41:27 +00:00
|
|
|
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) {
|
2019-05-08 03:04:59 +00:00
|
|
|
if (driver->vibrate(device, strength, duration, frequency)) {
|
2019-04-01 15:41:27 +00:00
|
|
|
lua_pushboolean(L, true);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lua_pushboolean(L, false);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-04-03 04:28:41 +00:00
|
|
|
int l_lovrHeadsetNewModel(lua_State* L) {
|
2019-05-08 09:56:20 +00:00
|
|
|
Device device = luax_optdevice(L, 1);
|
2019-04-03 04:28:41 +00:00
|
|
|
|
|
|
|
ModelData* modelData = NULL;
|
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-08 03:04:59 +00:00
|
|
|
if ((modelData = driver->newModelData(device)) != NULL) {
|
2019-04-03 04:28:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modelData) {
|
|
|
|
Model* model = lovrModelCreate(modelData);
|
2019-06-02 07:20:10 +00:00
|
|
|
luax_pushtype(L, Model, model);
|
2019-04-03 04:28:41 +00:00
|
|
|
lovrRelease(ModelData, modelData);
|
|
|
|
lovrRelease(Model, model);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-07-18 00:07:33 +00:00
|
|
|
int l_lovrHeadsetGetBonePose(lua_State* L) {
|
|
|
|
Device device = luax_optdevice(L, 1);
|
|
|
|
DeviceBone bone = luaL_checkoption(L, 2, NULL, DeviceBones);
|
|
|
|
float position[4], orientation[4];
|
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
|
|
|
if (driver->getBonePose(device, bone, position, orientation)) {
|
|
|
|
float angle, ax, ay, az;
|
|
|
|
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
|
|
|
|
lua_pushnumber(L, position[0]);
|
|
|
|
lua_pushnumber(L, position[1]);
|
|
|
|
lua_pushnumber(L, position[2]);
|
|
|
|
lua_pushnumber(L, angle);
|
|
|
|
lua_pushnumber(L, ax);
|
|
|
|
lua_pushnumber(L, ay);
|
|
|
|
lua_pushnumber(L, az);
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < 7; i++) {
|
|
|
|
lua_pushnumber(L, 0.);
|
|
|
|
}
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetRenderTo(lua_State* L) {
|
2017-04-16 23:56:49 +00:00
|
|
|
lua_settop(L, 1);
|
2016-08-11 04:17:14 +00:00
|
|
|
luaL_checktype(L, 1, LUA_TFUNCTION);
|
2017-04-21 04:17:25 +00:00
|
|
|
|
2018-10-25 03:40:11 +00:00
|
|
|
#ifdef LOVR_HEADSET_HELPER_USES_REGISTRY
|
2017-04-23 06:21:29 +00:00
|
|
|
if (headsetRenderData.ref != LUA_NOREF) {
|
2017-04-21 04:17:25 +00:00
|
|
|
luaL_unref(L, LUA_REGISTRYINDEX, headsetRenderData.ref);
|
|
|
|
}
|
|
|
|
|
2017-04-16 23:56:49 +00:00
|
|
|
headsetRenderData.ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
2019-03-06 16:42:32 +00:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD);
|
|
|
|
headsetRenderData.L = lua_tothread(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
#else
|
2017-04-16 23:56:49 +00:00
|
|
|
headsetRenderData.L = L;
|
2019-03-06 16:42:32 +00:00
|
|
|
#endif
|
2018-04-28 23:59:53 +00:00
|
|
|
lovrHeadsetDriver->renderTo(renderHelper, &headsetRenderData);
|
2016-08-11 04:17:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-03-11 11:08:07 +00:00
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static int l_lovrHeadsetUpdate(lua_State* L) {
|
2019-04-09 19:38:55 +00:00
|
|
|
float dt = luax_checkfloat(L, 1);
|
|
|
|
|
2018-05-01 22:10:51 +00:00
|
|
|
if (lovrHeadsetDriver->update) {
|
2019-04-09 19:38:55 +00:00
|
|
|
lovrHeadsetDriver->update(dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-04-30 04:11:03 +00:00
|
|
|
if (driver->update && driver != lovrHeadsetDriver) {
|
|
|
|
driver->update(dt);
|
|
|
|
}
|
2018-05-01 22:10:51 +00:00
|
|
|
}
|
|
|
|
|
2017-10-13 20:46:33 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-01-09 02:33:51 +00:00
|
|
|
|
2019-01-25 20:08:45 +00:00
|
|
|
static int l_lovrHeadsetGetMirrorTexture(lua_State* L) {
|
|
|
|
Texture *texture = NULL;
|
|
|
|
if (lovrHeadsetDriver->getMirrorTexture)
|
|
|
|
texture = lovrHeadsetDriver->getMirrorTexture();
|
2019-06-02 07:20:10 +00:00
|
|
|
luax_pushtype(L, Texture, texture);
|
2019-01-25 20:08:45 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-05-31 17:52:31 +00:00
|
|
|
static int l_lovrHeadsetGetHands(lua_State* L) {
|
|
|
|
if (lua_istable(L, 1)) {
|
|
|
|
lua_settop(L, 1);
|
|
|
|
} else {
|
|
|
|
lua_newtable(L);
|
|
|
|
}
|
2019-05-31 17:57:29 +00:00
|
|
|
|
2019-05-31 17:52:31 +00:00
|
|
|
int count = 0;
|
2019-06-14 20:04:10 +00:00
|
|
|
float position[4], orientation[4];
|
2019-05-31 17:57:29 +00:00
|
|
|
Device hands[] = { DEVICE_HAND_LEFT, DEVICE_HAND_RIGHT };
|
2019-05-31 17:52:31 +00:00
|
|
|
for (size_t i = 0; i < sizeof(hands) / sizeof(hands[0]); i++) {
|
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
|
|
|
if (driver->getPose(hands[i], position, orientation)) {
|
|
|
|
lua_pushstring(L, Devices[hands[i]]);
|
|
|
|
lua_rawseti(L, -2, ++count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lua_pushnil(L);
|
|
|
|
lua_rawseti(L, -2, ++count);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-05-31 17:57:29 +00:00
|
|
|
static int handIterator(lua_State* L) {
|
|
|
|
Device hands[] = { DEVICE_HAND_LEFT, DEVICE_HAND_RIGHT };
|
2019-05-08 11:06:50 +00:00
|
|
|
size_t index = lua_tointeger(L, lua_upvalueindex(1));
|
2019-06-03 14:13:52 +00:00
|
|
|
float position[4], orientation[4];
|
2019-05-08 11:06:50 +00:00
|
|
|
|
2019-05-31 17:57:29 +00:00
|
|
|
while (index < 2) {
|
2019-05-08 11:06:50 +00:00
|
|
|
FOREACH_TRACKING_DRIVER(driver) {
|
2019-05-31 17:57:29 +00:00
|
|
|
if (driver->getPose(hands[index], position, orientation)) {
|
|
|
|
lua_pushstring(L, Devices[hands[index]]);
|
2019-05-08 11:06:50 +00:00
|
|
|
lua_pushinteger(L, ++index);
|
|
|
|
lua_replace(L, lua_upvalueindex(1));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int l_lovrHeadsetHands(lua_State* L) {
|
|
|
|
lua_pushinteger(L, 0);
|
2019-05-31 17:57:29 +00:00
|
|
|
lua_pushcclosure(L, handIterator, 1);
|
2019-05-08 11:06:50 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-27 01:27:38 +00:00
|
|
|
static const luaL_Reg lovrHeadset[] = {
|
2017-11-25 21:01:56 +00:00
|
|
|
{ "getDriver", l_lovrHeadsetGetDriver },
|
2019-04-06 22:09:20 +00:00
|
|
|
{ "getName", l_lovrHeadsetGetName },
|
2017-08-07 06:56:22 +00:00
|
|
|
{ "getOriginType", l_lovrHeadsetGetOriginType },
|
2019-06-30 00:33:49 +00:00
|
|
|
{ "getDisplayTime", l_lovrHeadsetGetDisplayTime },
|
2017-03-11 11:08:07 +00:00
|
|
|
{ "getDisplayWidth", l_lovrHeadsetGetDisplayWidth },
|
|
|
|
{ "getDisplayHeight", l_lovrHeadsetGetDisplayHeight },
|
|
|
|
{ "getDisplayDimensions", l_lovrHeadsetGetDisplayDimensions },
|
2019-06-28 07:13:30 +00:00
|
|
|
{ "getDisplayMask", l_lovrHeadsetGetDisplayMask },
|
2017-03-11 11:08:07 +00:00
|
|
|
{ "getClipDistance", l_lovrHeadsetGetClipDistance },
|
|
|
|
{ "setClipDistance", l_lovrHeadsetSetClipDistance },
|
|
|
|
{ "getBoundsWidth", l_lovrHeadsetGetBoundsWidth },
|
|
|
|
{ "getBoundsDepth", l_lovrHeadsetGetBoundsDepth },
|
|
|
|
{ "getBoundsDimensions", l_lovrHeadsetGetBoundsDimensions },
|
2018-10-10 00:51:05 +00:00
|
|
|
{ "getBoundsGeometry", l_lovrHeadsetGetBoundsGeometry },
|
2017-12-18 06:13:58 +00:00
|
|
|
{ "getPose", l_lovrHeadsetGetPose },
|
2017-03-11 11:08:07 +00:00
|
|
|
{ "getPosition", l_lovrHeadsetGetPosition },
|
|
|
|
{ "getOrientation", l_lovrHeadsetGetOrientation },
|
|
|
|
{ "getVelocity", l_lovrHeadsetGetVelocity },
|
|
|
|
{ "getAngularVelocity", l_lovrHeadsetGetAngularVelocity },
|
2019-05-08 10:15:17 +00:00
|
|
|
{ "getAcceleration", l_lovrHeadsetGetAcceleration },
|
|
|
|
{ "getAngularAcceleration", l_lovrHeadsetGetAngularAcceleration },
|
2019-04-03 05:13:08 +00:00
|
|
|
{ "isDown", l_lovrHeadsetIsDown },
|
|
|
|
{ "isTouched", l_lovrHeadsetIsTouched },
|
2019-04-01 14:25:29 +00:00
|
|
|
{ "getAxis", l_lovrHeadsetGetAxis },
|
2019-04-01 15:41:27 +00:00
|
|
|
{ "vibrate", l_lovrHeadsetVibrate },
|
2019-04-03 04:28:41 +00:00
|
|
|
{ "newModel", l_lovrHeadsetNewModel },
|
2019-07-18 00:07:33 +00:00
|
|
|
{ "getBonePose", l_lovrHeadsetGetBonePose },
|
2017-03-11 11:08:07 +00:00
|
|
|
{ "renderTo", l_lovrHeadsetRenderTo },
|
2017-10-13 20:46:33 +00:00
|
|
|
{ "update", l_lovrHeadsetUpdate },
|
2019-01-25 20:08:45 +00:00
|
|
|
{ "getMirrorTexture", l_lovrHeadsetGetMirrorTexture },
|
2019-05-31 17:52:31 +00:00
|
|
|
{ "getHands", l_lovrHeadsetGetHands },
|
2019-05-08 11:06:50 +00:00
|
|
|
{ "hands", l_lovrHeadsetHands },
|
2017-03-11 11:08:07 +00:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
2018-09-27 01:27:38 +00:00
|
|
|
|
|
|
|
int luaopen_lovr_headset(lua_State* L) {
|
|
|
|
lua_newtable(L);
|
|
|
|
luaL_register(L, NULL, lovrHeadset);
|
|
|
|
|
|
|
|
luax_pushconf(L);
|
|
|
|
lua_getfield(L, -1, "headset");
|
|
|
|
|
2019-06-08 10:45:03 +00:00
|
|
|
arr_t(HeadsetDriver, 8) drivers;
|
|
|
|
arr_init(&drivers);
|
2019-02-17 07:43:20 +00:00
|
|
|
float offset = 1.7f;
|
2018-09-27 01:27:38 +00:00
|
|
|
int msaa = 4;
|
|
|
|
|
|
|
|
if (lua_istable(L, -1)) {
|
|
|
|
|
|
|
|
// Drivers
|
|
|
|
lua_getfield(L, -1, "drivers");
|
2019-03-17 07:58:01 +00:00
|
|
|
int n = luax_len(L, -1);
|
2018-09-27 01:27:38 +00:00
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
lua_rawgeti(L, -1, i + 1);
|
2019-06-08 10:45:03 +00:00
|
|
|
arr_push(&drivers, luaL_checkoption(L, -1, NULL, HeadsetDrivers));
|
2018-09-27 01:27:38 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
// Offset
|
|
|
|
lua_getfield(L, -1, "offset");
|
2019-01-29 10:28:55 +00:00
|
|
|
offset = luax_optfloat(L, -1, 1.7f);
|
2018-09-27 01:27:38 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
// MSAA
|
|
|
|
lua_getfield(L, -1, "msaa");
|
2019-01-12 06:37:54 +00:00
|
|
|
msaa = luaL_optinteger(L, -1, 4);
|
2018-09-27 01:27:38 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
2018-11-19 16:08:56 +00:00
|
|
|
if (lovrHeadsetInit(drivers.data, drivers.length, offset, msaa)) {
|
|
|
|
luax_atexit(L, lovrHeadsetDestroy);
|
|
|
|
}
|
|
|
|
|
2019-06-08 10:45:03 +00:00
|
|
|
arr_free(&drivers);
|
2018-09-27 01:27:38 +00:00
|
|
|
lua_pop(L, 2);
|
|
|
|
|
|
|
|
headsetRenderData.ref = LUA_NOREF;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|