lovr/src/api/l_headset.c

739 lines
20 KiB
C
Raw Normal View History

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/graphics.h"
2019-04-03 04:28:41 +00:00
#include "graphics/model.h"
2019-01-25 20:08:45 +00:00
#include "graphics/texture.h"
2019-05-20 09:47:33 +00:00
#include "core/maf.h"
2021-03-16 00:54:27 +00:00
#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
2016-08-11 04:17:14 +00:00
2020-09-28 00:13:00 +00:00
StringEntry lovrHeadsetDriver[] = {
[DRIVER_DESKTOP] = ENTRY("desktop"),
[DRIVER_OPENXR] = ENTRY("openxr"),
2020-03-05 06:47:24 +00:00
[DRIVER_WEBXR] = ENTRY("webxr"),
{ 0 }
2018-07-05 03:11:52 +00:00
};
2020-09-28 00:13:00 +00:00
StringEntry lovrHeadsetOrigin[] = {
[ORIGIN_HEAD] = ENTRY("head"),
[ORIGIN_FLOOR] = ENTRY("floor"),
{ 0 }
2018-07-05 03:11:52 +00:00
};
2020-09-28 00:13:00 +00:00
StringEntry lovrDevice[] = {
[DEVICE_HEAD] = ENTRY("head"),
[DEVICE_HAND_LEFT] = ENTRY("hand/left"),
[DEVICE_HAND_RIGHT] = ENTRY("hand/right"),
[DEVICE_HAND_LEFT_POINT] = ENTRY("hand/left/point"),
[DEVICE_HAND_RIGHT_POINT] = ENTRY("hand/right/point"),
2020-11-19 07:39:38 +00:00
[DEVICE_ELBOW_LEFT] = ENTRY("elbow/left"),
[DEVICE_ELBOW_RIGHT] = ENTRY("elbow/right"),
[DEVICE_SHOULDER_LEFT] = ENTRY("shoulder/left"),
[DEVICE_SHOULDER_RIGHT] = ENTRY("shoulder/right"),
[DEVICE_CHEST] = ENTRY("chest"),
[DEVICE_WAIST] = ENTRY("waist"),
[DEVICE_KNEE_LEFT] = ENTRY("knee/left"),
[DEVICE_KNEE_RIGHT] = ENTRY("knee/right"),
[DEVICE_FOOT_LEFT] = ENTRY("foot/left"),
[DEVICE_FOOT_RIGHT] = ENTRY("foot/right"),
[DEVICE_CAMERA] = ENTRY("camera"),
[DEVICE_KEYBOARD] = ENTRY("keyboard"),
[DEVICE_EYE_LEFT] = ENTRY("eye/left"),
[DEVICE_EYE_RIGHT] = ENTRY("eye/right"),
[DEVICE_EYE_GAZE] = ENTRY("eye/gaze"),
[DEVICE_BEACON_1] = ENTRY("beacon/1"),
[DEVICE_BEACON_2] = ENTRY("beacon/2"),
[DEVICE_BEACON_3] = ENTRY("beacon/3"),
[DEVICE_BEACON_4] = ENTRY("beacon/4"),
{ 0 }
};
2020-09-28 00:13:00 +00:00
StringEntry lovrDeviceButton[] = {
[BUTTON_TRIGGER] = ENTRY("trigger"),
[BUTTON_THUMBSTICK] = ENTRY("thumbstick"),
2022-01-29 23:39:55 +00:00
[BUTTON_THUMBREST] = ENTRY("thumbrest"),
[BUTTON_TOUCHPAD] = ENTRY("touchpad"),
[BUTTON_GRIP] = ENTRY("grip"),
[BUTTON_MENU] = ENTRY("menu"),
[BUTTON_A] = ENTRY("a"),
[BUTTON_B] = ENTRY("b"),
[BUTTON_X] = ENTRY("x"),
[BUTTON_Y] = ENTRY("y"),
[BUTTON_PROXIMITY] = ENTRY("proximity"),
{ 0 }
};
2020-09-28 00:13:00 +00:00
StringEntry lovrDeviceAxis[] = {
[AXIS_TRIGGER] = ENTRY("trigger"),
[AXIS_THUMBSTICK] = ENTRY("thumbstick"),
[AXIS_TOUCHPAD] = ENTRY("touchpad"),
[AXIS_GRIP] = ENTRY("grip"),
{ 0 }
};
2018-03-11 07:42:33 +00:00
static void renderHelper(void* userdata) {
lua_State* L = userdata;
if (lua_isfunction(L, -1)) {
lua_call(L, 0, 0);
}
}
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;
}
2020-09-28 00:13:00 +00:00
return luax_checkenum(L, 1, Device, "head");
}
static int l_lovrHeadsetStart(lua_State* L) {
lovrHeadsetDisplayDriver->start();
return 0;
}
2018-09-27 01:27:38 +00:00
static int l_lovrHeadsetGetDriver(lua_State* L) {
if (lua_gettop(L) == 0) {
2020-09-28 00:13:00 +00:00
luax_pushenum(L, HeadsetDriver, lovrHeadsetDisplayDriver->driverType);
return 1;
} else {
Device device = luax_optdevice(L, 1);
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, position, orientation)) {
2020-09-28 00:13:00 +00:00
luax_pushenum(L, HeadsetDriver, driver->driverType);
return 1;
}
}
}
return 0;
}
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];
2020-09-28 00:13:00 +00:00
if (lovrHeadsetDisplayDriver->getName(name, sizeof(name))) {
2019-04-19 04:03:38 +00:00
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) {
2020-09-28 00:13:00 +00:00
luax_pushenum(L, HeadsetOrigin, lovrHeadsetDisplayDriver->getOriginType());
2017-08-04 05:21:49 +00:00
return 1;
}
2018-09-27 01:27:38 +00:00
static int l_lovrHeadsetGetDisplayWidth(lua_State* L) {
uint32_t width, height;
2020-09-28 00:13:00 +00:00
lovrHeadsetDisplayDriver->getDisplayDimensions(&width, &height);
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) {
uint32_t width, height;
2020-09-28 00:13:00 +00:00
lovrHeadsetDisplayDriver->getDisplayDimensions(&width, &height);
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) {
uint32_t width, height;
2020-09-28 00:13:00 +00:00
lovrHeadsetDisplayDriver->getDisplayDimensions(&width, &height);
lua_pushinteger(L, width);
lua_pushinteger(L, height);
2016-10-24 23:03:29 +00:00
return 2;
}
2020-01-25 07:06:30 +00:00
static int l_lovrHeadsetGetDisplayFrequency(lua_State* L) {
2020-09-28 00:13:00 +00:00
float frequency = lovrHeadsetDisplayDriver->getDisplayFrequency ? lovrHeadsetDisplayDriver->getDisplayFrequency() : 0.f;
2020-01-25 07:06:30 +00:00
if (frequency == 0.f) {
lua_pushnil(L);
} else {
lua_pushnumber(L, frequency);
}
return 1;
}
2019-06-28 07:13:30 +00:00
static int l_lovrHeadsetGetDisplayMask(lua_State* L) {
uint32_t count;
2020-09-28 00:13:00 +00:00
const float* points = lovrHeadsetDisplayDriver->getDisplayMask(&count);
2019-06-28 07:13:30 +00:00
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;
}
static int l_lovrHeadsetGetViewCount(lua_State* L) {
2020-09-28 00:13:00 +00:00
lua_pushinteger(L, lovrHeadsetDisplayDriver->getViewCount());
return 1;
}
static int l_lovrHeadsetGetViewPose(lua_State* L) {
float position[4], orientation[4];
uint32_t view = luax_checku32(L, 1) - 1;
2020-09-28 00:13:00 +00:00
if (!lovrHeadsetDisplayDriver->getViewPose(view, position, orientation)) {
lua_pushnil(L);
return 1;
}
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;
}
static int l_lovrHeadsetGetViewAngles(lua_State* L) {
float left, right, up, down;
uint32_t view = luax_checku32(L, 1) - 1;
2020-09-28 00:13:00 +00:00
if (!lovrHeadsetDisplayDriver->getViewAngles(view, &left, &right, &up, &down)) {
lua_pushnil(L);
return 1;
}
lua_pushnumber(L, left);
lua_pushnumber(L, right);
lua_pushnumber(L, up);
lua_pushnumber(L, down);
return 4;
}
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;
2020-09-28 00:13:00 +00:00
lovrHeadsetDisplayDriver->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) {
float clipNear = luax_checkfloat(L, 1);
float clipFar = luax_checkfloat(L, 2);
2020-09-28 00:13:00 +00:00
lovrHeadsetDisplayDriver->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;
2020-09-28 00:13:00 +00:00
lovrHeadsetDisplayDriver->getBoundsDimensions(&width, &depth);
2018-04-29 21:38:08 +00:00
lua_pushnumber(L, width);
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;
2020-09-28 00:13:00 +00:00
lovrHeadsetDisplayDriver->getBoundsDimensions(&width, &depth);
2018-04-29 21:38:08 +00:00
lua_pushnumber(L, depth);
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;
2020-09-28 00:13:00 +00:00
lovrHeadsetDisplayDriver->getBoundsDimensions(&width, &depth);
2018-04-29 21:38:08 +00:00
lua_pushnumber(L, width);
lua_pushnumber(L, depth);
2016-10-01 21:17:26 +00:00
return 2;
}
static int l_lovrHeadsetGetBoundsGeometry(lua_State* L) {
2019-05-21 03:35:07 +00:00
uint32_t count;
2020-09-28 00:13:00 +00:00
const float* points = lovrHeadsetDisplayDriver->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);
lua_createtable(L, count / 4, 0);
}
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++);
}
return 1;
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetIsTracked(lua_State* L) {
2019-07-18 00:09:45 +00:00
Device device = luax_optdevice(L, 1);
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, position, orientation)) {
lua_pushboolean(L, true);
return 1;
}
}
lua_pushboolean(L, false);
return 1;
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetGetPose(lua_State* L) {
Device device = luax_optdevice(L, 1);
2019-06-03 14:13:52 +00:00
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, 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;
2016-10-01 21:12:55 +00:00
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetGetPosition(lua_State* L) {
Device device = luax_optdevice(L, 1);
2019-06-03 14:13:52 +00:00
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, position, orientation)) {
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
return 3;
}
}
for (int i = 0; i < 3; i++) {
lua_pushnumber(L, 0.);
}
return 3;
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetGetOrientation(lua_State* L) {
Device device = luax_optdevice(L, 1);
2019-06-03 14:13:52 +00:00
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, position, orientation)) {
float angle, ax, ay, az;
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
lua_pushnumber(L, angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
return 4;
}
}
for (int i = 0; i < 4; i++) {
lua_pushnumber(L, 0.);
2019-04-19 02:23:59 +00:00
}
return 4;
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetGetVelocity(lua_State* L) {
Device device = luax_optdevice(L, 1);
2019-06-03 14:13:52 +00:00
float velocity[4], angularVelocity[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getVelocity(device, velocity, angularVelocity)) {
lua_pushnumber(L, velocity[0]);
lua_pushnumber(L, velocity[1]);
lua_pushnumber(L, velocity[2]);
return 3;
}
}
for (int i = 0; i < 3; i++) {
lua_pushnumber(L, 0.);
}
return 3;
2016-08-11 04:17:14 +00:00
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
Device device = luax_optdevice(L, 1);
2019-06-03 14:13:52 +00:00
float velocity[4], angularVelocity[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getVelocity(device, velocity, angularVelocity)) {
lua_pushnumber(L, angularVelocity[0]);
lua_pushnumber(L, angularVelocity[1]);
lua_pushnumber(L, angularVelocity[2]);
return 3;
}
}
for (int i = 0; i < 3; i++) {
lua_pushnumber(L, 0.);
}
return 3;
2016-09-16 06:57:01 +00:00
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetIsDown(lua_State* L) {
Device device = luax_optdevice(L, 1);
2020-09-28 00:13:00 +00:00
DeviceButton button = luax_checkenum(L, 2, DeviceButton, NULL);
bool down, changed;
FOREACH_TRACKING_DRIVER(driver) {
if (driver->isDown(device, button, &down, &changed)) {
lua_pushboolean(L, down);
return 1;
}
}
return 0;
}
static int l_lovrHeadsetWasPressed(lua_State* L) {
Device device = luax_optdevice(L, 1);
2020-09-28 00:13:00 +00:00
DeviceButton button = luax_checkenum(L, 2, DeviceButton, NULL);
bool down, changed;
FOREACH_TRACKING_DRIVER(driver) {
if (driver->isDown(device, button, &down, &changed)) {
lua_pushboolean(L, down && changed);
return 1;
}
}
lua_pushboolean(L, false);
return 1;
}
static int l_lovrHeadsetWasReleased(lua_State* L) {
Device device = luax_optdevice(L, 1);
2020-09-28 00:13:00 +00:00
DeviceButton button = luax_checkenum(L, 2, DeviceButton, NULL);
bool down, changed;
FOREACH_TRACKING_DRIVER(driver) {
if (driver->isDown(device, button, &down, &changed)) {
lua_pushboolean(L, !down && changed);
return 1;
}
}
lua_pushboolean(L, false);
return 1;
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetIsTouched(lua_State* L) {
Device device = luax_optdevice(L, 1);
2020-09-28 00:13:00 +00:00
DeviceButton button = luax_checkenum(L, 2, DeviceButton, NULL);
bool touched;
FOREACH_TRACKING_DRIVER(driver) {
2019-05-24 22:14:20 +00:00
if (driver->isTouched(device, button, &touched)) {
lua_pushboolean(L, touched);
return 1;
}
}
return 0;
}
2019-08-01 00:51:49 +00:00
static const int axisCounts[MAX_AXES] = {
[AXIS_TRIGGER] = 1,
[AXIS_THUMBSTICK] = 2,
2019-09-12 23:06:50 +00:00
[AXIS_TOUCHPAD] = 2,
[AXIS_GRIP] = 1
};
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetGetAxis(lua_State* L) {
Device device = luax_optdevice(L, 1);
2020-09-28 00:13:00 +00:00
DeviceAxis axis = luax_checkenum(L, 2, DeviceAxis, NULL);
2019-08-01 00:51:49 +00:00
int count = axisCounts[axis];
2019-06-03 14:13:52 +00:00
float value[4];
FOREACH_TRACKING_DRIVER(driver) {
2019-05-13 05:04:41 +00:00
if (driver->getAxis(device, axis, value)) {
2019-08-01 20:01:41 +00:00
for (int i = 0; i < count; i++) {
lua_pushnumber(L, value[i]);
2019-05-13 05:04:41 +00:00
}
return count;
}
}
2019-08-01 20:01:41 +00:00
for (int i = 0; i < count; i++) {
lua_pushnumber(L, 0.);
}
return count;
}
2020-02-13 05:37:52 +00:00
static int l_lovrHeadsetGetSkeleton(lua_State* L) {
Device device = luax_optdevice(L, 1);
2020-08-12 21:47:10 +00:00
float poses[HAND_JOINT_COUNT * 8];
2020-02-13 05:37:52 +00:00
FOREACH_TRACKING_DRIVER(driver) {
2020-08-12 21:47:10 +00:00
if (driver->getSkeleton(device, poses)) {
2020-02-13 05:37:52 +00:00
if (!lua_istable(L, 2)) {
2020-08-12 21:47:10 +00:00
lua_createtable(L, HAND_JOINT_COUNT, 0);
2020-02-13 05:37:52 +00:00
} else {
lua_settop(L, 2);
}
2020-08-12 21:47:10 +00:00
for (uint32_t i = 0; i < HAND_JOINT_COUNT; i++) {
lua_createtable(L, 8, 0);
2020-02-13 05:37:52 +00:00
float angle, ax, ay, az;
float* pose = poses + i * 8;
quat_getAngleAxis(pose + 4, &angle, &ax, &ay, &az);
lua_pushnumber(L, pose[0]);
lua_pushnumber(L, pose[1]);
lua_pushnumber(L, pose[2]);
lua_pushnumber(L, angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
lua_rawseti(L, -8, 7);
lua_rawseti(L, -7, 6);
lua_rawseti(L, -6, 5);
lua_rawseti(L, -5, 4);
lua_rawseti(L, -4, 3);
lua_rawseti(L, -3, 2);
lua_rawseti(L, -2, 1);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
}
lua_pushnil(L);
return 1;
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetVibrate(lua_State* L) {
Device device = luax_optdevice(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);
FOREACH_TRACKING_DRIVER(driver) {
if (driver->vibrate(device, strength, duration, frequency)) {
lua_pushboolean(L, true);
return 1;
}
}
lua_pushboolean(L, false);
return 1;
}
2020-01-23 18:55:46 +00:00
static int l_lovrHeadsetNewModel(lua_State* L) {
Device device = luax_optdevice(L, 1);
bool animated = false;
if (lua_istable(L, 2)) {
lua_getfield(L, 2, "animated");
animated = lua_toboolean(L, -1);
lua_pop(L, 1);
}
2019-04-03 04:28:41 +00:00
ModelData* modelData = NULL;
FOREACH_TRACKING_DRIVER(driver) {
if ((modelData = driver->newModelData(device, animated)) != NULL) {
2019-04-03 04:28:41 +00:00
break;
}
}
if (modelData) {
Model* model = lovrModelCreate(modelData);
luax_pushtype(L, Model, model);
2021-02-09 00:52:26 +00:00
lovrRelease(modelData, lovrModelDataDestroy);
lovrRelease(model, lovrModelDestroy);
2019-04-03 04:28:41 +00:00
return 1;
}
return 0;
}
static int l_lovrHeadsetAnimate(lua_State* L) {
Device device = luax_optdevice(L, 1);
Model* model = luax_checktype(L, 2, Model);
FOREACH_TRACKING_DRIVER(driver) {
if (driver->animate(device, model)) {
lua_pushboolean(L, true);
return 1;
}
}
lua_pushboolean(L, false);
return 1;
}
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);
lovrHeadsetDisplayDriver->renderTo(renderHelper, L);
lovrGraphicsSetViewMatrix(0, NULL);
lovrGraphicsSetViewMatrix(1, NULL);
lovrGraphicsSetProjection(0, NULL);
lovrGraphicsSetProjection(1, NULL);
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);
2020-09-28 00:13:00 +00:00
if (lovrHeadsetDisplayDriver->update) {
lovrHeadsetDisplayDriver->update(dt);
2019-04-09 19:38:55 +00:00
}
FOREACH_TRACKING_DRIVER(driver) {
2020-09-28 00:13:00 +00:00
if (driver->update && driver != lovrHeadsetDisplayDriver) {
2019-04-30 04:11:03 +00:00
driver->update(dt);
}
2018-05-01 22:10:51 +00:00
}
return 0;
}
2018-01-09 02:33:51 +00:00
static int l_lovrHeadsetGetTime(lua_State* L) {
2020-09-28 00:13:00 +00:00
lua_pushnumber(L, lovrHeadsetDisplayDriver->getDisplayTime());
return 1;
}
2019-01-25 20:08:45 +00:00
static int l_lovrHeadsetGetMirrorTexture(lua_State* L) {
2022-02-02 20:01:38 +00:00
Texture* texture = NULL;
2020-09-28 00:13:00 +00:00
if (lovrHeadsetDisplayDriver->getMirrorTexture)
texture = lovrHeadsetDisplayDriver->getMirrorTexture();
luax_pushtype(L, Texture, texture);
2019-01-25 20:08:45 +00:00
return 1;
}
static int l_lovrHeadsetGetHands(lua_State* L) {
if (lua_istable(L, 1)) {
lua_settop(L, 1);
} else {
lua_newtable(L);
}
int count = 0;
2019-06-14 20:04:10 +00:00
float position[4], orientation[4];
Device hands[] = { DEVICE_HAND_LEFT, DEVICE_HAND_RIGHT };
for (size_t i = 0; i < sizeof(hands) / sizeof(hands[0]); i++) {
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(hands[i], position, orientation)) {
2020-09-28 00:13:00 +00:00
luax_pushenum(L, Device, hands[i]);
lua_rawseti(L, -2, ++count);
}
}
}
lua_pushnil(L);
lua_rawseti(L, -2, ++count);
return 1;
}
2018-09-27 01:27:38 +00:00
static const luaL_Reg lovrHeadset[] = {
{ "start", l_lovrHeadsetStart },
{ "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 },
2017-03-11 11:08:07 +00:00
{ "getDisplayWidth", l_lovrHeadsetGetDisplayWidth },
{ "getDisplayHeight", l_lovrHeadsetGetDisplayHeight },
{ "getDisplayDimensions", l_lovrHeadsetGetDisplayDimensions },
2020-01-25 07:06:30 +00:00
{ "getDisplayFrequency", l_lovrHeadsetGetDisplayFrequency },
2019-06-28 07:13:30 +00:00
{ "getDisplayMask", l_lovrHeadsetGetDisplayMask },
{ "getViewCount", l_lovrHeadsetGetViewCount },
{ "getViewPose", l_lovrHeadsetGetViewPose },
{ "getViewAngles", l_lovrHeadsetGetViewAngles },
2017-03-11 11:08:07 +00:00
{ "getClipDistance", l_lovrHeadsetGetClipDistance },
{ "setClipDistance", l_lovrHeadsetSetClipDistance },
{ "getBoundsWidth", l_lovrHeadsetGetBoundsWidth },
{ "getBoundsDepth", l_lovrHeadsetGetBoundsDepth },
{ "getBoundsDimensions", l_lovrHeadsetGetBoundsDimensions },
{ "getBoundsGeometry", l_lovrHeadsetGetBoundsGeometry },
2019-07-18 00:09:45 +00:00
{ "isTracked", l_lovrHeadsetIsTracked },
{ "getPose", l_lovrHeadsetGetPose },
2017-03-11 11:08:07 +00:00
{ "getPosition", l_lovrHeadsetGetPosition },
{ "getOrientation", l_lovrHeadsetGetOrientation },
{ "getVelocity", l_lovrHeadsetGetVelocity },
{ "getAngularVelocity", l_lovrHeadsetGetAngularVelocity },
{ "isDown", l_lovrHeadsetIsDown },
{ "wasPressed", l_lovrHeadsetWasPressed },
{ "wasReleased", l_lovrHeadsetWasReleased },
{ "isTouched", l_lovrHeadsetIsTouched },
{ "getAxis", l_lovrHeadsetGetAxis },
{ "vibrate", l_lovrHeadsetVibrate },
2019-04-03 04:28:41 +00:00
{ "newModel", l_lovrHeadsetNewModel },
{ "animate", l_lovrHeadsetAnimate },
2020-02-13 05:37:52 +00:00
{ "getSkeleton", l_lovrHeadsetGetSkeleton },
2017-03-11 11:08:07 +00:00
{ "renderTo", l_lovrHeadsetRenderTo },
{ "update", l_lovrHeadsetUpdate },
{ "getTime", l_lovrHeadsetGetTime },
2019-01-25 20:08:45 +00:00
{ "getMirrorTexture", l_lovrHeadsetGetMirrorTexture },
{ "getHands", l_lovrHeadsetGetHands },
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) {
2018-09-27 01:27:38 +00:00
lua_newtable(L);
2020-08-19 19:12:06 +00:00
luax_register(L, lovrHeadset);
size_t driverCount = 0;
HeadsetDriver drivers[8];
float supersample = 1.f;
float offset = 1.7f;
int msaa = 4;
bool overlay = false;
2022-03-14 20:19:59 +00:00
luax_pushconf(L);
if (lua_istable(L, -1)) {
2022-03-14 20:19:59 +00:00
lua_getfield(L, -1, "headset");
if (lua_istable(L, -1)) {
// Drivers
lua_getfield(L, -1, "drivers");
int n = luax_len(L, -1);
for (int i = 0; i < n; i++) {
lua_rawgeti(L, -1, i + 1);
drivers[driverCount++] = luax_checkenum(L, -1, HeadsetDriver, NULL);
lovrAssert(driverCount < sizeof(drivers) / sizeof(drivers[0]), "Too many headset drivers specified in conf.lua");
lua_pop(L, 1);
}
lua_pop(L, 1);
2022-03-14 20:19:59 +00:00
// Supersample
lua_getfield(L, -1, "supersample");
if (lua_type(L, -1) == LUA_TBOOLEAN) {
supersample = lua_toboolean(L, -1) ? 2.f : 1.f;
} else {
supersample = luax_optfloat(L, -1, 1.f);
}
lua_pop(L, 1);
2022-03-14 20:19:59 +00:00
// Offset
lua_getfield(L, -1, "offset");
offset = luax_optfloat(L, -1, 1.7f);
lua_pop(L, 1);
2022-03-14 20:19:59 +00:00
// MSAA
lua_getfield(L, -1, "msaa");
msaa = luaL_optinteger(L, -1, 4);
lua_pop(L, 1);
2022-03-14 20:19:59 +00:00
// Overlay
lua_getfield(L, -1, "overlay");
overlay = lua_toboolean(L, -1);
lua_pop(L, 1);
}
lua_pop(L, 1);
}
2022-03-14 20:19:59 +00:00
lua_pop(L, 1);
2022-03-14 20:19:59 +00:00
luax_atexit(L, lovrHeadsetDestroy);
lovrHeadsetInit(drivers, driverCount, supersample, offset, msaa, overlay);
2018-09-27 01:27:38 +00:00
return 1;
}