Merge pull request #24 from bcampbell/fake-headset

Fake headset
This commit is contained in:
Bjorn Swenson 2017-10-23 11:24:03 -07:00 committed by GitHub
commit 618be7b51d
12 changed files with 1091 additions and 214 deletions

View File

@ -201,7 +201,7 @@ endif()
if(NOT EMSCRIPTEN)
set(BUILD_SHARED ON CACHE BOOL "")
set(BUILD_UNIVERSAL OFF CACHE BOOL "")
include_directories(deps/openvr/headers)
include_directories(deps/openvr/headers)
include_directories(deps/openvr/src)
include_directories(deps/openvr/src/vrcommon)
add_subdirectory(deps/openvr openvr_api)
@ -251,6 +251,7 @@ set(LOVR_SRC
src/graphics/shader.c
src/graphics/shaders.c
src/graphics/texture.c
src/headset/fake.c
src/headset/headset.c
src/lib/glad/glad.c
src/lib/lua-cjson/fpconv.c
@ -281,9 +282,9 @@ set(LOVR_SRC
)
if(EMSCRIPTEN)
set(LOVR_HEADSET src/headset/webvr.c)
set(LOVR_SRC ${LOVR_SRC} src/headset/webvr.c)
else()
set(LOVR_HEADSET src/headset/openvr.c)
set(LOVR_SRC ${LOVR_SRC} src/headset/openvr.c)
endif()
if(WIN32)
@ -294,7 +295,7 @@ if(WIN32)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
add_executable(lovr ${LOVR_SRC} ${LOVR_HEADSET})
add_executable(lovr ${LOVR_SRC})
target_link_libraries(lovr
${LOVR_ASSIMP}
${LOVR_ENET}

View File

@ -64,6 +64,14 @@ int l_lovrHeadsetInit(lua_State* L) {
map_set(&HeadsetTypes, "vive", HEADSET_VIVE);
map_set(&HeadsetTypes, "rift", HEADSET_RIFT);
#if 0
// not needed yet, but if we expose driver selection to lua...
map_init(&HeadsetDrivers);
map_set(&HeadsetDrivers, "unknown", HEADSET_DRIVER_FAKE);
map_set(&HeadsetDrivers, "openvr", HEADSET_DRIVER_OPENVR);
map_set(&HeadsetDrivers, "webvr", HEADSET_DRIVER_WEBVR);
#endif
lovrHeadsetInit();
headsetRenderData.ref = LUA_NOREF;
@ -252,6 +260,11 @@ int l_lovrHeadsetRenderTo(lua_State* L) {
return 0;
}
int l_lovrHeadsetUpdate(lua_State* L) {
float dt = luaL_checknumber(L, 1);
lovrHeadsetUpdate(dt);
return 0;
}
const luaL_Reg lovrHeadset[] = {
{ "isPresent", l_lovrHeadsetIsPresent },
{ "getType", l_lovrHeadsetGetType },
@ -275,5 +288,6 @@ const luaL_Reg lovrHeadset[] = {
{ "getControllers", l_lovrHeadsetGetControllers },
{ "getControllerCount", l_lovrHeadsetGetControllerCount },
{ "renderTo", l_lovrHeadsetRenderTo },
{ "update", l_lovrHeadsetUpdate },
{ NULL, NULL }
};

View File

@ -186,6 +186,9 @@ function lovr.step()
lovr.handlers[name](a, b, c, d)
end
local dt = lovr.timer.step()
if lovr.headset then
lovr.headset.update(dt)
end
if lovr.audio then
lovr.audio.update()
if lovr.headset and lovr.headset.isPresent() then

View File

@ -437,80 +437,84 @@ unsigned char boot_lua[] = {
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,
0x64, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69,
0x6d, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64,
0x69, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x75,
0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69, 0x73, 0x50,
0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x4f, 0x72,
0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67,
0x65, 0x74, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65,
0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67,
0x65, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x56, 0x65,
0x6c, 0x6f, 0x63, 0x69, 0x74, 0x79, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x56,
0x65, 0x6c, 0x6f, 0x63, 0x69, 0x74, 0x79, 0x28, 0x29, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x75,
0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x64,
0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x64, 0x72, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x2e, 0x69, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x65, 0x74, 0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x54, 0x6f, 0x28,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x52, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x48,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70,
0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69,
0x6d, 0x65, 0x72, 0x2e, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x28, 0x2e, 0x30,
0x30, 0x31, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x72,
0x75, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x28, 0x29,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65,
0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x69, 0x74, 0x20,
0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x65, 0x78, 0x69,
0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x20, 0x65, 0x78, 0x69, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x69, 0x66,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79,
0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28,
0x27, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x27, 0x29, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69,
0x72, 0x65, 0x28, 0x27, 0x6d, 0x61, 0x69, 0x6e, 0x27, 0x29, 0x0a, 0x65,
0x6e, 0x64, 0x0a
0x65, 0x74, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x64, 0x74,
0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x69, 0x66,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69, 0x73, 0x50, 0x72, 0x65, 0x73,
0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75,
0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x4f, 0x72, 0x69, 0x65, 0x6e,
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x4f,
0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x50, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x50,
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75,
0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x56, 0x65, 0x6c, 0x6f, 0x63,
0x69, 0x74, 0x79, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x56, 0x65, 0x6c, 0x6f,
0x63, 0x69, 0x74, 0x79, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x64, 0x74, 0x29, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x63, 0x6c,
0x65, 0x61, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61,
0x77, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69, 0x73,
0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e,
0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x54, 0x6f, 0x28, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x48, 0x65, 0x61, 0x64,
0x73, 0x65, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x65, 0x73,
0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72,
0x2e, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x28, 0x2e, 0x30, 0x30, 0x31, 0x29,
0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x28,
0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x28, 0x29, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72,
0x75, 0x65, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x69, 0x74, 0x20, 0x3d, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x65, 0x78, 0x69, 0x74, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65,
0x78, 0x69, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x69, 0x66, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65,
0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x27, 0x6d, 0x61,
0x69, 0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x27, 0x29, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28,
0x27, 0x6d, 0x61, 0x69, 0x6e, 0x27, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a
};
unsigned int boot_lua_len = 6147;
unsigned int boot_lua_len = 6204;

View File

@ -1047,3 +1047,8 @@ void lovrGraphicsBindIndexBuffer(uint32_t indexBuffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
}
}
GLFWwindow* lovrGraphicsGetWindow() {
return state.window;
}

View File

@ -182,3 +182,5 @@ void lovrGraphicsUseProgram(uint32_t program);
void lovrGraphicsBindVertexArray(uint32_t vao);
void lovrGraphicsBindVertexBuffer(uint32_t vbo);
void lovrGraphicsBindIndexBuffer(uint32_t ibo);
GLFWwindow* lovrGraphicsGetWindow();

481
src/headset/fake.c Normal file
View File

@ -0,0 +1,481 @@
#include "event/event.h"
#include "graphics/graphics.h"
#include "math/mat4.h"
#include "math/vec3.h"
#include "math/quat.h"
#include "util.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// implements a fake headset, with mouselook and keyboard-driven movement.
// for use when a real headset isn't available.
typedef struct {
int isInitialized;
HeadsetType type;
vec_controller_t controllers;
float clipNear;
float clipFar;
float FOV;
float vel[3];
float pos[3];
double yaw;
double pitch;
float orientation[4]; // derived from pitch and yaw
float projection[16]; // projection matrix
float transform[16];
// keep track of currently hooked window, if any
GLFWwindow* hookedWindow;
int mouselook;
double prevCursorX;
double prevCursorY;
} FakeHeadsetState;
static FakeHeadsetState state;
// fwd declarations
static void fakePoll();
/*
* callback handlers
*/
static void enableMouselook(GLFWwindow* window) {
if (window) {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwGetCursorPos(window, &state.prevCursorX, &state.prevCursorY);
}
// track the intent for mouselook, even if no window yet. One might come along ;-)
state.mouselook = 1;
}
static void disableMouselook(GLFWwindow* window) {
if(window) {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
state.mouselook = 0;
}
static void cursor_enter_callback( GLFWwindow *window, int entered) {
if (entered) {
if( !state.mouselook) {
enableMouselook(window);
}
}
}
static void window_focus_callback(GLFWwindow* window, int focused) {
if (!focused) {
disableMouselook(window);
}
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
disableMouselook(window);
}
}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
if (!state.mouselook) {
return;
}
double dx = xpos - state.prevCursorX;
double dy = ypos - state.prevCursorY;
state.prevCursorX = xpos;
state.prevCursorY = ypos;
const double k = 0.01;
const double l = 0.01;
state.yaw -= dx*k;
state.pitch -= dy*l;
if (state.pitch < -M_PI/2.0) {
state.pitch = -M_PI/2.0;
}
if (state.pitch > M_PI/2.0) {
state.pitch = M_PI/2.0;
}
}
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (!state.mouselook) {
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
enableMouselook(window);
}
}
}
// headset can start up without a window, so we poll window existance here
static void check_window_existance()
{
GLFWwindow *window = lovrGraphicsGetWindow();
if (window == state.hookedWindow) {
// no change
return;
}
state.hookedWindow = window;
// window might be coming or going.
// If it's coming we'll install our event hooks.
// If it's going, it's already gone, so no way to uninstall our hooks.
if( window ) {
glfwSetCursorEnterCallback(window, cursor_enter_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetWindowFocusCallback(window, window_focus_callback);
glfwSetKeyCallback(window, key_callback);
// can now actually do mouselook!
if (state.mouselook ) {
enableMouselook(window);
} else {
disableMouselook(window);
}
}
}
/*
* headset implementation fns
*/
static int fakeIsAvailable()
{
return 1;
}
static void fakeInit() {
state.clipNear = 0.1f;
state.clipFar = 100.f;
state.FOV = 67.0f * M_PI / 100.0f;
// TODO: aspect here too?
mat4_identity(state.transform);
state.pitch = 0.0;
state.yaw = 0.0;
quat_set( state.orientation, 0,0,0,1);
vec3_set( state.vel, 0,0,0);
vec3_set( state.pos, 0,0,0);
// set up controller(s)
vec_init(&state.controllers);
Controller* controller = lovrAlloc(sizeof(Controller), lovrControllerDestroy);
controller->id = state.controllers.length;
vec_push(&state.controllers, controller);
lovrEventAddPump(fakePoll);
state.mouselook = 1;
state.hookedWindow = NULL;
state.isInitialized = 1;
}
static void fakeDestroy() {
int i;
Controller *controller;
state.isInitialized = 0;
// TODO: unhook lovrEventAddPump ?
// would be polite to unhook gracefully, but we're likely
// being called after glfw is already lone gone...
// not a big deal in practice.
#if 0
GLFWwindow *window = lovrGraphicsGetWindow();
if( window && window ==state.hookedWindow) {
glfwSetKeyCallback(window, NULL);
glfwSetWindowFocusCallback(window, NULL);
glfwSetCursorPosCallback(window, NULL);
glfwSetMouseButtonCallback(window, NULL);
glfwSetCursorEnterCallback(window, NULL);
state.hookedWindow = NULL;
}
#endif
vec_foreach(&state.controllers, controller, i) {
lovrRelease(&controller->ref);
}
vec_deinit(&state.controllers);
}
static void fakePoll() {
}
static int fakeIsPresent() {
return 1;
}
static HeadsetType fakeGetType() {
return HEADSET_FAKE;
}
static HeadsetOrigin fakeGetOriginType() {
return ORIGIN_HEAD; // seated
//return ORIGIN_FLOOR; // standing
}
static int fakeIsMirrored() {
return 0;
}
static void fakeSetMirrored(int mirror) {
}
static void fakeGetDisplayDimensions(int* width, int* height) {
GLFWwindow* window = lovrGraphicsGetWindow();
if(window) {
glfwGetWindowSize(window,width,height);
}
}
static void fakeGetClipDistance(float* clipNear, float* clipFar) {
*clipNear = state.clipNear;
*clipFar = state.clipFar;
}
static void fakeSetClipDistance(float clipNear, float clipFar) {
state.clipNear = clipNear;
state.clipFar = clipFar;
}
static float fakeGetBoundsWidth() {
return 0.0f;
}
static float fakeGetBoundsDepth() {
return 0.0f;
}
static void fakeGetBoundsGeometry(float* geometry) {
memset(geometry, 0, 12 * sizeof(float));
}
static void fakeGetPosition(float* x, float* y, float* z) {
// TODO: sit->stand transform?
*x = state.pos[0];
*y = state.pos[1];
*z = state.pos[2];
}
static void fakeGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
fakeGetPosition(x,y,z);
}
static void fakeGetOrientation(float* angle, float* x, float* y, float* z) {
float q[4];
quat_fromMat4(q, state.transform);
quat_getAngleAxis(q, angle, x, y, z);
}
static void fakeGetVelocity(float* x, float* y, float* z) {
// TODO: sit->stand transform?
*x = state.vel[0];
*y = state.vel[1];
*z = state.vel[2];
}
static void fakeGetAngularVelocity(float* x, float* y, float* z) {
#if 0
float v[3];
emscripten_vr_get_angular_velocity(&v[0], &v[1], &v[2]);
mat4_transformDirection(emscripten_vr_get_sitting_to_standing_matrix(), v);
*x = v[0];
*y = v[1];
*z = v[2];
#endif
// TODO
}
static vec_controller_t* fakeGetControllers() {
return &state.controllers;
}
static int fakeControllerIsPresent(Controller* controller) {
return 1;
}
static ControllerHand fakeControllerGetHand(Controller* controller) {
return HAND_UNKNOWN;
}
static void fakeControllerGetPosition(Controller* controller, float* x, float* y, float* z) {
// for now, locked to headset
fakeGetPosition(x,y,z);
}
static void fakeControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z) {
// for now, locked to headset
float q[4];
quat_fromMat4(q, state.transform);
quat_getAngleAxis(q, angle, x, y, z);
}
static float fakeControllerGetAxis(Controller* controller, ControllerAxis axis) {
return 0.0f;
}
static int fakeControllerIsDown(Controller* controller, ControllerButton button) {
GLFWwindow* window = lovrGraphicsGetWindow();
if(!window) {
return 0;
}
int b = glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_LEFT);
return (b == GLFW_PRESS) ? CONTROLLER_BUTTON_TRIGGER : 0;
}
static int fakeControllerIsTouched(Controller* controller, ControllerButton button) {
return 0;
}
static void fakeControllerVibrate(Controller* controller, float duration, float power) {
}
static ModelData* fakeControllerNewModelData(Controller* controller) {
return NULL;
}
static void fakeRenderTo(headsetRenderCallback callback, void* userdata) {
// float head[16], transform[16], projection[16];
// TODO: Head transform
// TODO: Eye transform
// Projection
int w,h;
GLFWwindow* window = lovrGraphicsGetWindow();
if(!window) {
return;
}
glfwGetWindowSize(window, &w, &h);
float transform[16];
mat4_perspective(state.projection, state.clipNear, state.clipFar, 67 * M_PI / 180.0, (float)w/h);
// render
lovrGraphicsPush();
float inv[16];
mat4_set(inv,state.transform);
mat4_invert(inv);
lovrGraphicsMatrixTransform(MATRIX_VIEW, inv);
lovrGraphicsSetProjection(state.projection);
lovrGraphicsClear(1, 1);
callback(EYE_LEFT, userdata);
lovrGraphicsPop();
}
static void fakeUpdate(float dt)
{
float k = 4.0f;
check_window_existance();
GLFWwindow* w = lovrGraphicsGetWindow();
if(!w) {
return;
}
float v[3] = {0.0f,0.0f,0.0f};
if (glfwGetKey(w, GLFW_KEY_W)==GLFW_PRESS || glfwGetKey(w, GLFW_KEY_UP)==GLFW_PRESS) {
v[2] = -k;
}
if (glfwGetKey(w, GLFW_KEY_S)==GLFW_PRESS || glfwGetKey(w, GLFW_KEY_DOWN)==GLFW_PRESS) {
v[2] = k;
}
if (glfwGetKey(w, GLFW_KEY_A)==GLFW_PRESS || glfwGetKey(w, GLFW_KEY_LEFT)==GLFW_PRESS) {
v[0] = -k;
}
if (glfwGetKey(w, GLFW_KEY_D)==GLFW_PRESS || glfwGetKey(w, GLFW_KEY_RIGHT)==GLFW_PRESS) {
v[0] = k;
}
if (glfwGetKey(w, GLFW_KEY_Q) == GLFW_PRESS) {
v[1] = k;
}
if (glfwGetKey(w, GLFW_KEY_E) == GLFW_PRESS) {
v[1] = -k;
}
// move
vec3_scale(v,dt);
mat4_transformDirection(state.transform, v);
vec3_add(state.pos, v);
// update transform
mat4_identity(state.transform);
mat4_translate(state.transform, state.pos[0], state.pos[1], state.pos[2]);
mat4_rotate(state.transform, state.yaw, 0,1,0);
mat4_rotate(state.transform, state.pitch, 1,0,0);
}
HeadsetInterface lovrHeadsetFakeDriver = {
fakeIsAvailable,
fakeInit,
fakeDestroy,
fakePoll,
fakeIsPresent,
fakeGetType,
fakeGetOriginType,
fakeIsMirrored,
fakeSetMirrored,
fakeGetDisplayDimensions,
fakeGetClipDistance,
fakeSetClipDistance,
fakeGetBoundsWidth,
fakeGetBoundsDepth,
fakeGetBoundsGeometry,
fakeGetPosition,
fakeGetEyePosition,
fakeGetOrientation,
fakeGetVelocity,
fakeGetAngularVelocity,
fakeGetControllers,
fakeControllerIsPresent,
fakeControllerGetHand,
fakeControllerGetPosition,
fakeControllerGetOrientation,
fakeControllerGetAxis,
fakeControllerIsDown,
fakeControllerIsTouched,
fakeControllerVibrate,
fakeControllerNewModelData,
fakeRenderTo,
fakeUpdate,
};

View File

@ -5,3 +5,238 @@ void lovrControllerDestroy(const Ref* ref) {
Controller* controller = containerof(ref, Controller);
free(controller);
}
static HeadsetInterface* headset = NULL;
void lovrHeadsetInit() {
// assert(headset==NULL)
// TODO: should expose driver selection to lua, so conf can express a preference?
#if EMSCRIPTEN
HeadsetInterface* drivers[] = { &lovrHeadsetWebVRDriver, &lovrHeadsetFakeDriver, NULL };
#else
HeadsetInterface* drivers[] = { &lovrHeadsetOpenVRDriver, &lovrHeadsetFakeDriver, NULL };
#endif
int i;
for (i=0; drivers[i]; ++i ) {
if (drivers[i]->isAvailable()) {
headset = drivers[i];
break;
}
}
if( headset) {
headset->init();
atexit(lovrHeadsetDestroy);
}
}
void lovrHeadsetDestroy() {
if (headset) {
headset->destroy();
headset = NULL;
}
}
void lovrHeadsetPoll() {
headset->poll();
}
int lovrHeadsetIsPresent() {
return headset ? headset->isPresent() : 0;
}
HeadsetType lovrHeadsetGetType() {
return headset ? headset->getType() : HEADSET_UNKNOWN;
}
HeadsetOrigin lovrHeadsetGetOriginType() {
return headset ? headset->getOriginType() : ORIGIN_HEAD;
}
int lovrHeadsetIsMirrored() {
return headset ? headset->isMirrored() : 0;
}
void lovrHeadsetSetMirrored(int mirror) {
if (headset) {
headset->setMirrored(mirror);
}
}
void lovrHeadsetGetDisplayDimensions(int* width, int* height) {
if (!headset) {
*width = *height = 0;
return;
}
headset->getDisplayDimensions(width, height);
}
void lovrHeadsetGetClipDistance(float* near, float* far) {
if (!headset) {
*near = *far = 0.f;
return;
}
headset->getClipDistance(near, far);
}
void lovrHeadsetSetClipDistance(float near, float far) {
if (headset) {
headset->setClipDistance(near, far);
}
}
float lovrHeadsetGetBoundsWidth() {
return headset ? headset->getBoundsWidth() : 0.0f;
}
float lovrHeadsetGetBoundsDepth() {
return headset ? headset->getBoundsDepth() : 0.0f;
}
void lovrHeadsetGetBoundsGeometry(float* geometry) {
if (!headset) {
*geometry = 0.f;
return;
}
headset->getBoundsGeometry(geometry);
}
void lovrHeadsetGetPosition(float* x, float* y, float* z) {
if (!headset) {
*x = *y = *z = 0.f;
return;
}
headset->getPosition(x, y, z);
}
void lovrHeadsetGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
if (!headset) {
*x = *y = *z = 0.f;
return;
}
headset->getEyePosition(eye,x, y, z);
}
void lovrHeadsetGetOrientation(float* angle, float* x, float* y, float* z) {
if (!headset) {
*angle = *x = *y = *z = 0.f;
return;
}
headset->getOrientation(angle,x,y,z);
}
void lovrHeadsetGetVelocity(float* x, float* y, float* z) {
if (!headset) {
*x = *y = *z = 0.f;
return;
}
headset->getVelocity(x,y,z);
}
void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z) {
if (!headset) {
*x = *y = *z = 0.f;
return;
}
headset->getAngularVelocity(x,y,z);
}
vec_controller_t* lovrHeadsetGetControllers() {
if (!headset) {
return NULL;
}
return headset->getControllers();
}
int lovrHeadsetControllerIsPresent(Controller* controller) {
if (!headset || !controller) {
return 0;
}
return headset->controllerIsPresent(controller);
}
ControllerHand lovrHeadsetControllerGetHand(Controller* controller) {
return headset ? headset->controllerGetHand(controller) : HAND_UNKNOWN;
}
void lovrHeadsetControllerGetPosition(Controller* controller, float* x, float* y, float* z) {
if (!headset || !controller) {
*x = *y = *z = 0.f;
return;
}
headset->controllerGetPosition(controller, x, y, z);
}
void lovrHeadsetControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z) {
if (!headset || !controller) {
*angle = *x = *y = *z = 0.f;
return;
}
headset->controllerGetOrientation(controller, angle, x, y, z);
}
float lovrHeadsetControllerGetAxis(Controller* controller, ControllerAxis axis) {
if (!headset || !controller) {
return 0.f;
}
return headset->controllerGetAxis(controller, axis);
}
int lovrHeadsetControllerIsDown(Controller* controller, ControllerButton button) {
if (!headset || !controller) {
return 0;
}
return headset->controllerIsDown(controller, button);
}
int lovrHeadsetControllerIsTouched(Controller* controller, ControllerButton button) {
return (headset && controller) ? headset->controllerIsTouched(controller,button) : 0;
}
void lovrHeadsetControllerVibrate(Controller* controller, float duration, float power) {
if (!headset || !controller) {
return;
}
headset->controllerVibrate(controller, duration, power);
}
ModelData* lovrHeadsetControllerNewModelData(Controller* controller)
{
if( headset && controller) {
return headset->controllerNewModelData(controller);
} else {
return NULL;
}
}
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata) {
if (headset) {
headset->renderTo(callback, userdata);
}
}
void lovrHeadsetUpdate(float dt) {
if(headset) {
headset->update(dt);
}
}

View File

@ -18,7 +18,8 @@ typedef enum {
typedef enum {
HEADSET_UNKNOWN,
HEADSET_VIVE,
HEADSET_RIFT
HEADSET_RIFT,
HEADSET_FAKE
} HeadsetType;
typedef enum {
@ -56,6 +57,48 @@ typedef struct {
typedef vec_t(Controller*) vec_controller_t;
typedef void (*headsetRenderCallback)(HeadsetEye eye, void* userdata);
typedef struct {
int (*isAvailable)();
void (*init)();
void (*destroy)();
void (*poll)();
int (*isPresent)();
HeadsetType (*getType)();
HeadsetOrigin (*getOriginType)();
int (*isMirrored)();
void (*setMirrored)(int mirror);
void (*getDisplayDimensions)(int* width, int* height);
void (*getClipDistance)(float* clipNear, float* clipFar);
void (*setClipDistance)(float clipNear, float clipFar);
float (*getBoundsWidth)();
float (*getBoundsDepth)();
void (*getBoundsGeometry)(float* geometry);
void (*getPosition)(float* x, float* y, float* z);
void (*getEyePosition)(HeadsetEye eye, float* x, float* y, float* z);
void (*getOrientation)(float* angle, float* x, float* y, float* z);
void (*getVelocity)(float* x, float* y, float* z);
void (*getAngularVelocity)(float* x, float* y, float* z);
vec_controller_t* (*getControllers)();
int (*controllerIsPresent)(Controller* controller);
ControllerHand (*controllerGetHand)(Controller* controller);
void (*controllerGetPosition)(Controller* controller, float* x, float* y, float* z);
void (*controllerGetOrientation)(Controller* controller, float* angle, float* x, float* y, float* z);
float (*controllerGetAxis)(Controller* controller, ControllerAxis axis);
int (*controllerIsDown)(Controller* controller, ControllerButton button);
int (*controllerIsTouched)(Controller* controller, ControllerButton button);
void (*controllerVibrate)(Controller* controller, float duration, float power);
ModelData* (*controllerNewModelData)(Controller* controller);
void (*renderTo)(headsetRenderCallback callback, void* userdata);
void (*update)(float dt);
} HeadsetInterface;
// headset implementations
extern HeadsetInterface lovrHeadsetOpenVRDriver;
extern HeadsetInterface lovrHeadsetFakeDriver;
void lovrHeadsetInit();
void lovrHeadsetDestroy();
void lovrHeadsetPoll();
@ -65,8 +108,8 @@ HeadsetOrigin lovrHeadsetGetOriginType();
int lovrHeadsetIsMirrored();
void lovrHeadsetSetMirrored(int mirror);
void lovrHeadsetGetDisplayDimensions(int* width, int* height);
void lovrHeadsetGetClipDistance(float* near, float* far);
void lovrHeadsetSetClipDistance(float near, float far);
void lovrHeadsetGetClipDistance(float* clipNear, float* clipFar);
void lovrHeadsetSetClipDistance(float clipNear, float clipFar);
float lovrHeadsetGetBoundsWidth();
float lovrHeadsetGetBoundsDepth();
void lovrHeadsetGetBoundsGeometry(float* geometry);
@ -86,5 +129,7 @@ int lovrHeadsetControllerIsTouched(Controller* controller, ControllerButton butt
void lovrHeadsetControllerVibrate(Controller* controller, float duration, float power);
ModelData* lovrHeadsetControllerNewModelData(Controller* controller);
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata);
void lovrHeadsetUpdate(float dt);
void lovrControllerDestroy(const Ref* ref);

View File

@ -1,15 +1,72 @@
#include "headset/openvr.h"
#include "event/event.h"
#include "graphics/graphics.h"
#include "math/mat4.h"
#include "math/quat.h"
#include "util.h"
#include "graphics/texture.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <openvr_capi.h>
// From openvr_capi.h
extern intptr_t VR_InitInternal(EVRInitError *peError, EVRApplicationType eType);
extern bool VR_IsHmdPresent();
extern intptr_t VR_GetGenericInterface(const char* pchInterfaceVersion, EVRInitError* peError);
extern bool VR_IsRuntimeInstalled();
static void openvrDestroy();
static void openvrPoll();
static void openvrRefreshControllers();
static ControllerHand openvrControllerGetHand(Controller* controller);
static Controller* openvrAddController(unsigned int deviceIndex);
static ControllerHand openvrControllerGetHand(Controller* controller);
typedef struct {
int isInitialized;
int isRendering;
int isMirrored;
struct VR_IVRSystem_FnTable* system;
struct VR_IVRCompositor_FnTable* compositor;
struct VR_IVRChaperone_FnTable* chaperone;
struct VR_IVRRenderModels_FnTable* renderModels;
unsigned int headsetIndex;
HeadsetType type;
TrackedDevicePose_t renderPoses[16];
RenderModel_t* deviceModels[16];
RenderModel_TextureMap_t* deviceTextures[16];
vec_controller_t controllers;
float clipNear;
float clipFar;
uint32_t renderWidth;
uint32_t renderHeight;
float refreshRate;
float vsyncToPhotons;
Texture* texture;
} HeadsetState;
static HeadsetState state;
static int openvrIsAvailable() {
if (VR_IsHmdPresent() && VR_IsRuntimeInstalled()) {
return 1;
} else {
return 0;
}
}
static ControllerButton getButton(uint32_t button, ControllerHand hand) {
switch (state.type) {
case HEADSET_RIFT:
@ -88,7 +145,7 @@ static TrackedDevicePose_t getPose(unsigned int deviceIndex) {
return poses[deviceIndex];
}
void lovrHeadsetInit() {
static void openvrInit() {
state.isInitialized = 0;
state.isRendering = 0;
state.isMirrored = 1;
@ -101,7 +158,7 @@ void lovrHeadsetInit() {
}
if (!VR_IsHmdPresent() || !VR_IsRuntimeInstalled()) {
lovrHeadsetDestroy();
openvrDestroy();
return;
}
@ -109,7 +166,7 @@ void lovrHeadsetInit() {
VR_InitInternal(&vrError, EVRApplicationType_VRApplication_Scene);
if (vrError != EVRInitError_VRInitError_None) {
lovrHeadsetDestroy();
openvrDestroy();
return;
}
@ -118,28 +175,28 @@ void lovrHeadsetInit() {
sprintf(buffer, "FnTable:%s", IVRSystem_Version);
state.system = (struct VR_IVRSystem_FnTable*) VR_GetGenericInterface(buffer, &vrError);
if (vrError != EVRInitError_VRInitError_None || !state.system) {
lovrHeadsetDestroy();
openvrDestroy();
return;
}
sprintf(buffer, "FnTable:%s", IVRCompositor_Version);
state.compositor = (struct VR_IVRCompositor_FnTable*) VR_GetGenericInterface(buffer, &vrError);
if (vrError != EVRInitError_VRInitError_None || !state.compositor) {
lovrHeadsetDestroy();
openvrDestroy();
return;
}
sprintf(buffer, "FnTable:%s", IVRChaperone_Version);
state.chaperone = (struct VR_IVRChaperone_FnTable*) VR_GetGenericInterface(buffer, &vrError);
if (vrError != EVRInitError_VRInitError_None || !state.chaperone) {
lovrHeadsetDestroy();
openvrDestroy();
return;
}
sprintf(buffer, "FnTable:%s", IVRRenderModels_Version);
state.renderModels = (struct VR_IVRRenderModels_FnTable*) VR_GetGenericInterface(buffer, &vrError);
if (vrError != EVRInitError_VRInitError_None || !state.renderModels) {
lovrHeadsetDestroy();
openvrDestroy();
return;
}
@ -160,12 +217,11 @@ void lovrHeadsetInit() {
state.clipNear = 0.1f;
state.clipFar = 30.f;
lovrHeadsetRefreshControllers();
lovrEventAddPump(lovrHeadsetPoll);
atexit(lovrHeadsetDestroy);
openvrRefreshControllers();
lovrEventAddPump(openvrPoll);
}
void lovrHeadsetDestroy() {
static void openvrDestroy() {
state.isInitialized = 0;
if (state.texture) {
lovrRelease(&state.texture->ref);
@ -184,7 +240,7 @@ void lovrHeadsetDestroy() {
vec_deinit(&state.controllers);
}
void lovrHeadsetPoll() {
static void openvrPoll() {
if (!state.isInitialized) return;
struct VREvent_t vrEvent;
while (state.system->PollNextEvent(&vrEvent, sizeof(vrEvent))) {
@ -192,7 +248,7 @@ void lovrHeadsetPoll() {
case EVREventType_VREvent_TrackedDeviceActivated:
case EVREventType_VREvent_TrackedDeviceDeactivated:
case EVREventType_VREvent_TrackedDeviceRoleChanged: {
lovrHeadsetRefreshControllers();
openvrRefreshControllers();
break;
}
@ -203,7 +259,7 @@ void lovrHeadsetPoll() {
int i;
vec_foreach(&state.controllers, controller, i) {
if (controller->id == vrEvent.trackedDeviceIndex) {
ControllerHand hand = lovrHeadsetControllerGetHand(controller);
ControllerHand hand = openvrControllerGetHand(controller);
Event event;
if (isPress) {
event.type = EVENT_CONTROLLER_PRESSED;
@ -233,15 +289,15 @@ void lovrHeadsetPoll() {
}
}
int lovrHeadsetIsPresent() {
static int openvrIsPresent() {
return state.isInitialized && state.system->IsTrackedDeviceConnected(state.headsetIndex);
}
HeadsetType lovrHeadsetGetType() {
static HeadsetType openvrGetType() {
return state.type;
}
HeadsetOrigin lovrHeadsetGetOriginType() {
static HeadsetOrigin openvrGetOriginType() {
if (!state.isInitialized) {
return ORIGIN_HEAD;
}
@ -253,15 +309,15 @@ HeadsetOrigin lovrHeadsetGetOriginType() {
}
}
int lovrHeadsetIsMirrored() {
static int openvrIsMirrored() {
return state.isMirrored;
}
void lovrHeadsetSetMirrored(int mirror) {
static void openvrSetMirrored(int mirror) {
state.isMirrored = mirror;
}
void lovrHeadsetGetDisplayDimensions(int* width, int* height) {
static void openvrGetDisplayDimensions(int* width, int* height) {
if (!state.isInitialized) {
*width = *height = 0;
} else {
@ -270,7 +326,7 @@ void lovrHeadsetGetDisplayDimensions(int* width, int* height) {
}
}
void lovrHeadsetGetClipDistance(float* near, float* far) {
static void openvrGetClipDistance(float* near, float* far) {
if (!state.isInitialized) {
*near = *far = 0.f;
} else {
@ -279,27 +335,27 @@ void lovrHeadsetGetClipDistance(float* near, float* far) {
}
}
void lovrHeadsetSetClipDistance(float near, float far) {
static void openvrSetClipDistance(float near, float far) {
if (!state.isInitialized) return;
state.clipNear = near;
state.clipFar = far;
}
float lovrHeadsetGetBoundsWidth() {
static float openvrGetBoundsWidth() {
if (!state.isInitialized) return 0.f;
float width;
state.chaperone->GetPlayAreaSize(&width, NULL);
return width;
}
float lovrHeadsetGetBoundsDepth() {
static float openvrGetBoundsDepth() {
if (!state.isInitialized) return 0.f;
float depth;
state.chaperone->GetPlayAreaSize(NULL, &depth);
return depth;
}
void lovrHeadsetGetBoundsGeometry(float* geometry) {
static void openvrGetBoundsGeometry(float* geometry) {
if (!state.isInitialized) {
memset(geometry, 0, 12 * sizeof(float));
} else {
@ -313,7 +369,7 @@ void lovrHeadsetGetBoundsGeometry(float* geometry) {
}
}
void lovrHeadsetGetPosition(float* x, float* y, float* z) {
static void openvrGetPosition(float* x, float* y, float* z) {
if (!state.isInitialized) {
*x = *y = *z = 0.f;
return;
@ -331,7 +387,7 @@ void lovrHeadsetGetPosition(float* x, float* y, float* z) {
*z = pose.mDeviceToAbsoluteTracking.m[2][3];
}
void lovrHeadsetGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
static void openvrGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
if (!state.isInitialized) {
*x = *y = *z = 0.f;
return;
@ -356,7 +412,7 @@ void lovrHeadsetGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
*z = transform[14];
}
void lovrHeadsetGetOrientation(float* angle, float* x, float* y, float *z) {
static void openvrGetOrientation(float* angle, float* x, float* y, float *z) {
if (!state.isInitialized) {
*angle = *x = *y = *z = 0.f;
return;
@ -375,7 +431,7 @@ void lovrHeadsetGetOrientation(float* angle, float* x, float* y, float *z) {
quat_getAngleAxis(rotation, angle, x, y, z);
}
void lovrHeadsetGetVelocity(float* x, float* y, float* z) {
static void openvrGetVelocity(float* x, float* y, float* z) {
if (!state.isInitialized) {
*x = *y = *z = 0.f;
return;
@ -393,7 +449,7 @@ void lovrHeadsetGetVelocity(float* x, float* y, float* z) {
*z = pose.vVelocity.v[2];
}
void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z) {
static void openvrGetAngularVelocity(float* x, float* y, float* z) {
if (!state.isInitialized) {
*x = *y = *z = 0.f;
return;
@ -411,7 +467,7 @@ void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z) {
*z = pose.vAngularVelocity.v[2];
}
void lovrHeadsetRefreshControllers() {
static void openvrRefreshControllers() {
if (!state.isInitialized) return;
unsigned int leftHand = ETrackedControllerRole_TrackedControllerRole_LeftHand;
@ -439,7 +495,7 @@ void lovrHeadsetRefreshControllers() {
// Add connected controllers that aren't in the list yet
for (i = 0; i < 2; i++) {
if ((int) controllerIds[i] != -1) {
controller = lovrHeadsetAddController(controllerIds[i]);
controller = openvrAddController(controllerIds[i]);
if (!controller) continue;
EventType type = EVENT_CONTROLLER_ADDED;
EventData data = { .controlleradded = { controller } };
@ -450,7 +506,7 @@ void lovrHeadsetRefreshControllers() {
}
}
Controller* lovrHeadsetAddController(unsigned int deviceIndex) {
static Controller* openvrAddController(unsigned int deviceIndex) {
if (!state.isInitialized) return NULL;
if ((int) deviceIndex == -1) {
@ -470,17 +526,17 @@ Controller* lovrHeadsetAddController(unsigned int deviceIndex) {
return controller;
}
vec_controller_t* lovrHeadsetGetControllers() {
static vec_controller_t* openvrGetControllers() {
if (!state.isInitialized) return NULL;
return &state.controllers;
}
int lovrHeadsetControllerIsPresent(Controller* controller) {
static int openvrControllerIsPresent(Controller* controller) {
if (!state.isInitialized || !controller) return 0;
return state.system->IsTrackedDeviceConnected(controller->id);
}
ControllerHand lovrHeadsetControllerGetHand(Controller* controller) {
static ControllerHand openvrControllerGetHand(Controller* controller) {
if (!state.isInitialized || !controller) return HAND_UNKNOWN;
switch (state.system->GetControllerRoleForTrackedDeviceIndex(controller->id)) {
case ETrackedControllerRole_TrackedControllerRole_LeftHand: return HAND_LEFT;
@ -489,7 +545,7 @@ ControllerHand lovrHeadsetControllerGetHand(Controller* controller) {
}
}
void lovrHeadsetControllerGetPosition(Controller* controller, float* x, float* y, float* z) {
static void openvrControllerGetPosition(Controller* controller, float* x, float* y, float* z) {
if (!state.isInitialized || !controller) {
*x = *y = *z = 0.f;
}
@ -506,7 +562,7 @@ void lovrHeadsetControllerGetPosition(Controller* controller, float* x, float* y
*z = pose.mDeviceToAbsoluteTracking.m[2][3];
}
void lovrHeadsetControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z) {
static void openvrControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z) {
if (!state.isInitialized || !controller) {
*angle = *x = *y = *z = 0.f;
}
@ -524,7 +580,7 @@ void lovrHeadsetControllerGetOrientation(Controller* controller, float* angle, f
quat_getAngleAxis(rotation, angle, x, y, z);
}
float lovrHeadsetControllerGetAxis(Controller* controller, ControllerAxis axis) {
static float openvrControllerGetAxis(Controller* controller, ControllerAxis axis) {
if (!state.isInitialized || !controller) return 0.f;
VRControllerState_t input;
@ -552,25 +608,25 @@ float lovrHeadsetControllerGetAxis(Controller* controller, ControllerAxis axis)
return 0;
}
int lovrHeadsetControllerIsDown(Controller* controller, ControllerButton button) {
static int openvrControllerIsDown(Controller* controller, ControllerButton button) {
if (!state.isInitialized || !controller) return 0;
VRControllerState_t input;
state.system->GetControllerState(controller->id, &input, sizeof(input));
ControllerHand hand = lovrHeadsetControllerGetHand(controller);
ControllerHand hand = openvrControllerGetHand(controller);
return getButtonState(input.ulButtonPressed, button, hand);
}
int lovrHeadsetControllerIsTouched(Controller* controller, ControllerButton button) {
static int openvrControllerIsTouched(Controller* controller, ControllerButton button) {
if (!state.isInitialized || !controller) return 0;
VRControllerState_t input;
state.system->GetControllerState(controller->id, &input, sizeof(input));
ControllerHand hand = lovrHeadsetControllerGetHand(controller);
ControllerHand hand = openvrControllerGetHand(controller);
return getButtonState(input.ulButtonTouched, button, hand);
}
void lovrHeadsetControllerVibrate(Controller* controller, float duration, float power) {
static void openvrControllerVibrate(Controller* controller, float duration, float power) {
if (!state.isInitialized || !controller || duration <= 0) return;
uint32_t axis = 0;
@ -578,7 +634,7 @@ void lovrHeadsetControllerVibrate(Controller* controller, float duration, float
state.system->TriggerHapticPulse(controller->id, axis, uSeconds);
}
ModelData* lovrHeadsetControllerNewModelData(Controller* controller) {
static ModelData* openvrControllerNewModelData(Controller* controller) {
if (!state.isInitialized || !controller) return NULL;
int id = controller->id;
@ -679,7 +735,7 @@ ModelData* lovrHeadsetControllerNewModelData(Controller* controller) {
return modelData;
}
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata) {
static void openvrRenderTo(headsetRenderCallback callback, void* userdata) {
if (!state.isInitialized) return;
if (!state.texture) {
@ -759,3 +815,43 @@ void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata) {
lovrGraphicsSetColor(oldColor);
}
}
static void openvrUpdate(float dt) {
}
HeadsetInterface lovrHeadsetOpenVRDriver = {
openvrIsAvailable,
openvrInit,
openvrDestroy,
openvrPoll,
openvrIsPresent,
openvrGetType,
openvrGetOriginType,
openvrIsMirrored,
openvrSetMirrored,
openvrGetDisplayDimensions,
openvrGetClipDistance,
openvrSetClipDistance,
openvrGetBoundsWidth,
openvrGetBoundsDepth,
openvrGetBoundsGeometry,
openvrGetPosition,
openvrGetEyePosition,
openvrGetOrientation,
openvrGetVelocity,
openvrGetAngularVelocity,
openvrGetControllers,
openvrControllerIsPresent,
openvrControllerGetHand,
openvrControllerGetPosition,
openvrControllerGetOrientation,
openvrControllerGetAxis,
openvrControllerIsDown,
openvrControllerIsTouched,
openvrControllerVibrate,
openvrControllerNewModelData,
openvrRenderTo,
openvrUpdate,
};

View File

@ -1,52 +0,0 @@
#include "headset/headset.h"
#include "graphics/texture.h"
#include "lib/glfw.h"
#include <stdbool.h>
#ifndef _WIN32
#define __stdcall
#endif
#include <openvr_capi.h>
#pragma once
// From openvr_capi.h
extern intptr_t VR_InitInternal(EVRInitError *peError, EVRApplicationType eType);
extern void VR_ShutdownInternal();
extern bool VR_IsHmdPresent();
extern intptr_t VR_GetGenericInterface(const char* pchInterfaceVersion, EVRInitError* peError);
extern bool VR_IsRuntimeInstalled();
extern const char* VR_GetVRInitErrorAsSymbol(EVRInitError error);
extern const char* VR_GetVRInitErrorAsEnglishDescription(EVRInitError error);
typedef struct {
int isInitialized;
int isRendering;
int isMirrored;
struct VR_IVRSystem_FnTable* system;
struct VR_IVRCompositor_FnTable* compositor;
struct VR_IVRChaperone_FnTable* chaperone;
struct VR_IVRRenderModels_FnTable* renderModels;
unsigned int headsetIndex;
HeadsetType type;
TrackedDevicePose_t renderPoses[16];
RenderModel_t* deviceModels[16];
RenderModel_TextureMap_t* deviceTextures[16];
vec_controller_t controllers;
float clipNear;
float clipFar;
uint32_t renderWidth;
uint32_t renderHeight;
float refreshRate;
float vsyncToPhotons;
Texture* texture;
} HeadsetState;
void lovrHeadsetRefreshControllers();
Controller* lovrHeadsetAddController(unsigned int id);

View File

@ -48,13 +48,16 @@ static void onRequestAnimationFrame(void* userdata) {
}
}
void lovrHeadsetInit() {
vec_init(&state.controllers);
emscripten_vr_init();
atexit(lovrHeadsetDestroy);
static int webvrIsAvailable() {
return emscripten_vr_is_present();
}
void lovrHeadsetDestroy() {
static void webvrInit() {
vec_init(&state.controllers);
emscripten_vr_init();
}
static void webvrDestroy() {
Controller* controller;
int i;
vec_foreach(&state.controllers, controller, i) {
@ -64,56 +67,56 @@ void lovrHeadsetDestroy() {
vec_deinit(&state.controllers);
}
void lovrHeadsetPoll() {
static void webvrPoll() {
//
}
int lovrHeadsetIsPresent() {
static int webvrIsPresent() {
return emscripten_vr_is_present();
}
HeadsetType lovrHeadsetGetType() {
static HeadsetType webvrGetType() {
return HEADSET_UNKNOWN;
}
HeadsetOrigin lovrHeadsetGetOriginType() {
static HeadsetOrigin webvrGetOriginType() {
return emscripten_vr_has_stage() ? ORIGIN_FLOOR : ORIGIN_HEAD;
}
int lovrHeadsetIsMirrored() {
static int webvrIsMirrored() {
return 1;
}
void lovrHeadsetSetMirrored(int mirror) {
static void webvrSetMirrored(int mirror) {
//
}
void lovrHeadsetGetDisplayDimensions(int* width, int* height) {
static void webvrGetDisplayDimensions(int* width, int* height) {
*width = emscripten_vr_get_display_width() / 2;
*height = emscripten_vr_get_display_height();
}
void lovrHeadsetGetClipDistance(float* near, float* far) {
static void webvrGetClipDistance(float* near, float* far) {
emscripten_vr_get_display_clip_distance(near, far);
}
void lovrHeadsetSetClipDistance(float near, float far) {
static void webvrSetClipDistance(float near, float far) {
emscripten_vr_set_display_clip_distance(near, far);
}
float lovrHeadsetGetBoundsWidth() {
static float webvrGetBoundsWidth() {
return emscripten_vr_get_bounds_width();
}
float lovrHeadsetGetBoundsDepth() {
static float webvrGetBoundsDepth() {
return emscripten_vr_get_bounds_depth();
}
void lovrHeadsetGetBoundsGeometry(float* geometry) {
static void webvrGetBoundsGeometry(float* geometry) {
memset(geometry, 0, 12 * sizeof(float));
}
void lovrHeadsetGetPosition(float* x, float* y, float* z) {
static void webvrGetPosition(float* x, float* y, float* z) {
float v[3];
emscripten_vr_get_position(&v[0], &v[1], &v[2]);
mat4_transform(emscripten_vr_get_sitting_to_standing_matrix(), v);
@ -122,7 +125,7 @@ void lovrHeadsetGetPosition(float* x, float* y, float* z) {
*z = v[2];
}
void lovrHeadsetGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
static void webvrGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
int i = eye == EYE_LEFT ? 0 : 1;
emscripten_vr_get_eye_offset(i, x, y, z);
float m[16];
@ -134,7 +137,7 @@ void lovrHeadsetGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
*z = m[14];
}
void lovrHeadsetGetOrientation(float* angle, float* x, float* y, float* z) {
static void webvrGetOrientation(float* angle, float* x, float* y, float* z) {
float quat[4];
float m[16];
emscripten_vr_get_orientation(&quat[0], &quat[1], &quat[2], &quat[3]);
@ -143,7 +146,7 @@ void lovrHeadsetGetOrientation(float* angle, float* x, float* y, float* z) {
quat_getAngleAxis(quat_fromMat4(quat, m), angle, x, y, z);
}
void lovrHeadsetGetVelocity(float* x, float* y, float* z) {
static void webvrGetVelocity(float* x, float* y, float* z) {
float v[3];
emscripten_vr_get_velocity(&v[0], &v[1], &v[2]);
mat4_transformDirection(emscripten_vr_get_sitting_to_standing_matrix(), v);
@ -152,7 +155,7 @@ void lovrHeadsetGetVelocity(float* x, float* y, float* z) {
*z = v[2];
}
void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z) {
static void webvrGetAngularVelocity(float* x, float* y, float* z) {
float v[3];
emscripten_vr_get_angular_velocity(&v[0], &v[1], &v[2]);
mat4_transformDirection(emscripten_vr_get_sitting_to_standing_matrix(), v);
@ -161,7 +164,7 @@ void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z) {
*z = v[2];
}
vec_controller_t* lovrHeadsetGetControllers() {
static vec_controller_t* webvrGetControllers() {
int controllerCount = emscripten_vr_get_controller_count();
while (state.controllers.length > controllerCount) {
@ -179,11 +182,11 @@ vec_controller_t* lovrHeadsetGetControllers() {
return &state.controllers;
}
int lovrHeadsetControllerIsPresent(Controller* controller) {
static int webvrControllerIsPresent(Controller* controller) {
return emscripten_vr_controller_is_present(controller->id);
}
ControllerHand lovrHeadsetControllerGetHand(Controller* controller) {
static ControllerHand webvrControllerGetHand(Controller* controller) {
switch (emscripten_vr_controller_get_hand(controller->id)) {
case 0: return HAND_UNKNOWN;
case 1: return HAND_LEFT;
@ -192,7 +195,7 @@ ControllerHand lovrHeadsetControllerGetHand(Controller* controller) {
}
}
void lovrHeadsetControllerGetPosition(Controller* controller, float* x, float* y, float* z) {
static void webvrControllerGetPosition(Controller* controller, float* x, float* y, float* z) {
float v[3];
emscripten_vr_get_controller_position(controller->id, &v[0], &v[1], &v[2]);
mat4_transform(emscripten_vr_get_sitting_to_standing_matrix(), v);
@ -201,7 +204,7 @@ void lovrHeadsetControllerGetPosition(Controller* controller, float* x, float* y
*z = v[2];
}
void lovrHeadsetControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z) {
static void webvrControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z) {
float quat[4];
float m[16];
emscripten_vr_get_controller_orientation(controller->id, &quat[0], &quat[1], &quat[2], &quat[3]);
@ -210,7 +213,7 @@ void lovrHeadsetControllerGetOrientation(Controller* controller, float* angle, f
quat_getAngleAxis(quat_fromMat4(quat, m), angle, x, y, z);
}
float lovrHeadsetControllerGetAxis(Controller* controller, ControllerAxis axis) {
static float webvrControllerGetAxis(Controller* controller, ControllerAxis axis) {
switch (axis) {
case CONTROLLER_AXIS_TRIGGER: return emscripten_vr_controller_get_axis(controller->id, -1);
case CONTROLLER_AXIS_TOUCHPAD_X: return emscripten_vr_controller_get_axis(controller->id, 0);
@ -219,7 +222,7 @@ float lovrHeadsetControllerGetAxis(Controller* controller, ControllerAxis axis)
}
}
int lovrHeadsetControllerIsDown(Controller* controller, ControllerButton button) {
static int webvrControllerIsDown(Controller* controller, ControllerButton button) {
switch (button) {
case CONTROLLER_BUTTON_TOUCHPAD:
return emscripten_vr_controller_is_down(controller->id, 0);
@ -234,19 +237,59 @@ int lovrHeadsetControllerIsDown(Controller* controller, ControllerButton button)
}
}
int lovrHeadsetControllerIsTouched(Controller* controller, ControllerButton button) {
static int webvrControllerIsTouched(Controller* controller, ControllerButton button) {
return 0;
}
void lovrHeadsetControllerVibrate(Controller* controller, float duration, float power) {
static void webvrControllerVibrate(Controller* controller, float duration, float power) {
emscripten_vr_controller_vibrate(controller->id, duration * 1000, power);
}
ModelData* lovrHeadsetControllerNewModelData(Controller* controller) {
static ModelData* webvrControllerNewModelData(Controller* controller) {
return NULL;
}
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata) {
static void webvrRenderTo(headsetRenderCallback callback, void* userdata) {
state.renderCallback = callback;
emscripten_vr_set_render_callback(onRequestAnimationFrame, userdata);
}
static void webvrUpdate(float dt) {
}
HeadsetInterface lovrHeadsetWebVRDriver = {
webvrIsAvailable,
webvrInit,
webvrDestroy,
webvrPoll,
webvrIsPresent,
webvrGetType,
webvrGetOriginType,
webvrIsMirrored,
webvrSetMirrored,
webvrGetDisplayDimensions,
webvrGetClipDistance,
webvrSetClipDistance,
webvrGetBoundsWidth,
webvrGetBoundsDepth,
webvrGetBoundsGeometry,
webvrGetPosition,
webvrGetEyePosition,
webvrGetOrientation,
webvrGetVelocity,
webvrGetAngularVelocity,
webvrGetControllers,
webvrControllerIsPresent,
webvrControllerGetHand,
webvrControllerGetPosition,
webvrControllerGetOrientation,
webvrControllerGetAxis,
webvrControllerIsDown,
webvrControllerIsTouched,
webvrControllerVibrate,
webvrControllerNewModelData,
webvrRenderTo,
webvrUpdate,
};