Merge branch 'master' into dev

This commit is contained in:
bjorn 2021-04-27 22:20:38 -06:00
commit 87bf9c7b27
23 changed files with 119 additions and 37 deletions

View File

@ -264,12 +264,13 @@ if(LOVR_USE_STEAM_AUDIO)
include_directories("${LOVR_STEAM_AUDIO_PATH}/include")
add_library(Phonon SHARED IMPORTED)
if(ANDROID)
set_target_properties(OculusAudio PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/lib/Android/arm64/libphonon.so")
set_target_properties(Phonon PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/lib/Android/arm64/libphonon.so")
elseif(WIN32)
set_target_properties(Phonon PROPERTIES IMPORTED_IMPLIB "${LOVR_STEAM_AUDIO_PATH}/lib/Windows/x64/phonon.lib")
set_target_properties(Phonon PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/bin/Windows/x64/phonon.dll")
elseif(APPLE) # This should be possible, there is a dylib in OSX/
message(FATAL_ERROR "LOVR_USE_STEAM_AUDIO is not currently supported on Apple platforms")
elseif(APPLE)
set_target_properties(Phonon PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/lib/OSX/libphonon.dylib"
IMPORTED_SONAME "@rpath/libphonon.dylib") # It doesn't make sense this line is required, but it is
else() # Assume Linux. Note: This has *not* been tested. FIXME: When is the .so copied?
set_target_properties(Phonon PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/lib/Linux/x64/libphonon.so")
endif()
@ -296,8 +297,21 @@ if(LOVR_USE_OCULUS_AUDIO)
set_target_properties(OculusAudio PROPERTIES IMPORTED_IMPLIB "${LOVR_OCULUS_AUDIO_PATH}/Lib/Win32/ovraudio32.lib")
set_target_properties(OculusAudio PROPERTIES IMPORTED_LOCATION "${LOVR_OCULUS_AUDIO_PATH}/Lib/Win32/ovraudio32.dll")
endif()
elseif(APPLE) # This *might* be possible-- there is a .framework in "macub/" ("universal binary"?)
message(FATAL_ERROR "LOVR_USE_OCULUS_AUDIO is not currently supported on Apple platforms")
elseif(APPLE)
# Oculus Audio ships with an intel .framework, but (as of 25.0.0) it is broken. We can convert it to a working dylib with install_name_tool in a custom target:
SET(OCULUS_AUDIO_MAC_LIB_DIR "${CMAKE_CURRENT_BINARY_DIR}/ovraudio")
SET(OCULUS_AUDIO_MAC_LIB_FILE "${OCULUS_AUDIO_MAC_LIB_DIR}/ovraudio64.dylib")
SET(OCULUS_AUDIO_MAC_RPATH "@rpath/ovraudio64.dylib")
file(MAKE_DIRECTORY "${OCULUS_AUDIO_MAC_LIB_DIR}")
add_custom_command(OUTPUT "${OCULUS_AUDIO_MAC_LIB_FILE}"
COMMAND ${CMAKE_COMMAND} -E copy "${LOVR_OCULUS_AUDIO_PATH}/Lib/mac64/OVRAudio64.framework/Versions/A/ovraudio64" "${OCULUS_AUDIO_MAC_LIB_FILE}"
COMMAND install_name_tool -id ${OCULUS_AUDIO_MAC_RPATH} "${OCULUS_AUDIO_MAC_LIB_FILE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
add_custom_target(OculusAudioFixed DEPENDS "${OCULUS_AUDIO_MAC_LIB_FILE}")
add_dependencies(OculusAudio OculusAudioFixed)
# IMPORTED_SONAME required because the automatic rpath requires the dylib file to exist before builds start
set_target_properties(OculusAudio PROPERTIES IMPORTED_LOCATION "${OCULUS_AUDIO_MAC_LIB_FILE}"
IMPORTED_SONAME "${OCULUS_AUDIO_MAC_RPATH}")
else() # Assume Linux. Note: This has *not* been tested. FIXME: When is the .so copied?
set_target_properties(OculusAudio PROPERTIES IMPORTED_LOCATION "${LOVR_OCULUS_AUDIO_PATH}/Lib/Linux64/libovraudio64.so")
endif()
@ -387,6 +401,8 @@ if(LOVR_ENABLE_AUDIO)
if(LOVR_USE_STEAM_AUDIO)
target_compile_definitions(lovr PRIVATE LOVR_ENABLE_PHONON)
target_sources(lovr PRIVATE src/modules/audio/spatializer_phonon.c)
# Dynamically linked at runtime, so this is not otherwise a dependency
add_dependencies(lovr ${LOVR_PHONON})
endif()
if(LOVR_USE_OCULUS_AUDIO)
@ -814,6 +830,14 @@ elseif(UNIX)
endif()
endif()
endfunction()
function(move_app_image_file)
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/resources/${ARGV0}")
set(DST "${CMAKE_BINARY_DIR}/bin/${ARGV0}")
add_custom_command(TARGET lovr POST_BUILD
DEPENDS ${SRC}
COMMAND ${CMAKE_COMMAND} -E copy ${SRC} ${DST}
)
endfunction()
move_lib(${LOVR_GLFW})
move_lib(${LOVR_LUA})
move_lib(${LOVR_ODE})
@ -823,4 +847,9 @@ elseif(UNIX)
foreach(target ${ALL_PLUGIN_TARGETS})
move_lib(${target})
endforeach()
if(LOVR_BUILD_BUNDLE)
move_app_image_file("lovr.desktop")
move_app_image_file("AppRun")
move_app_image_file("logo.svg")
endif()
endif()

View File

@ -113,6 +113,7 @@ Contributors
- [@nevyn](https://github.com/nevyn)
- [@porglezomp](https://github.com/porglezomp)
- [@jmiskovic](https://github.com/jmiskovic)
- [@wallbraker](https://github.com/wallbraker)
License
---

View File

@ -399,14 +399,12 @@ void luax_readcolor(lua_State* L, int index, Color* color) {
color->g = luax_checkfloat(L, index + 1);
color->b = luax_checkfloat(L, index + 2);
color->a = luax_optfloat(L, index + 3, 1.);
} else if (lua_gettop(L) == index) {
} else if (lua_gettop(L) <= index + 1) {
uint32_t x = luaL_checkinteger(L, index);
color->r = ((x >> 16) & 0xff) / 255.f;
color->g = ((x >> 8) & 0xff) / 255.f;
color->b = ((x >> 0) & 0xff) / 255.f;
color->a = 1.f;
} else {
luaL_error(L, "Invalid color, expected a hexcode, 3 numbers, 4 numbers, or a table");
color->a = luax_optfloat(L, index + 1, 1.);
}
}
@ -419,6 +417,8 @@ int luax_readmesh(lua_State* L, int index, float** vertices, uint32_t* vertexCou
*vertexCount = luax_len(L, index) / (nested ? 1 : 3);
*indexCount = luax_len(L, index + 1);
lovrAssert(*vertexCount > 0, "Invalid mesh data: vertex count is zero");
lovrAssert(*indexCount > 0, "Invalid mesh data: index count is zero");
lovrAssert(*indexCount % 3 == 0, "Index count must be a multiple of 3");
*vertices = malloc(sizeof(float) * *vertexCount * 3);
*indices = malloc(sizeof(uint32_t) * *indexCount);

View File

@ -122,6 +122,7 @@ static int l_lovrHeadsetInit(lua_State* L) {
float supersample = 1.f;
float offset = 1.7f;
int msaa = 4;
bool overlay = false;
if (lua_istable(L, -1)) {
@ -154,10 +155,15 @@ static int l_lovrHeadsetInit(lua_State* L) {
lua_getfield(L, -1, "msaa");
msaa = luaL_optinteger(L, -1, 4);
lua_pop(L, 1);
// Overlay
lua_getfield(L, -1, "overlay");
overlay = lua_toboolean(L, -1);
lua_pop(L, 1);
}
luax_atexit(L, lovrHeadsetDestroy); // Always make sure the headset module gets cleaned up
lovrHeadsetInit(drivers, driverCount, supersample, offset, msaa);
lovrHeadsetInit(drivers, driverCount, supersample, offset, msaa, overlay);
lua_pop(L, 2);
return 0;

View File

@ -5,9 +5,9 @@
#pragma once
#define LOVR_VERSION_MAJOR 0
#define LOVR_VERSION_MINOR 14
#define LOVR_VERSION_MINOR 15
#define LOVR_VERSION_PATCH 0
#define LOVR_VERSION_ALIAS "Maximum Moss"
#define LOVR_VERSION_ALIAS "Government Goop"
#ifdef _WIN32
#define LOVR_NORETURN __declspec(noreturn)

View File

@ -1,7 +1,7 @@
#define MINIAUDIO_IMPLEMENTATION
#define MA_ENABLE_ONLY_SPECIFIC_BACKENDS
#define MA_ENABLE_WASAPI
#define MA_ENABLE_ALSA
#define MA_ENABLE_PULSEAUDIO
#define MA_ENABLE_COREAUDIO
#define MA_ENABLE_AAUDIO
#define MA_ENABLE_WEBAUDIO

View File

@ -393,7 +393,10 @@ void lovrAudioSetPose(float position[4], float orientation[4]) {
}
bool lovrAudioSetGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount, AudioMaterial material) {
return state.spatializer->setGeometry(vertices, indices, vertexCount, indexCount, material);
ma_mutex_lock(&state.lock);
bool success = state.spatializer->setGeometry(vertices, indices, vertexCount, indexCount, material);
ma_mutex_unlock(&state.lock);
return success;
}
const char* lovrAudioGetSpatializer() {

View File

@ -360,7 +360,7 @@ bool phonon_setGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount
return true;
fail:
free(materials);
free(triangleMaterials);
if (state.mesh) phonon_iplDestroyStaticMesh(&state.mesh);
if (state.scene) phonon_iplDestroyScene(&state.scene);
if (state.environment) phonon_iplDestroyEnvironment(&state.environment);

View File

@ -5,7 +5,7 @@ HeadsetInterface* lovrHeadsetDisplayDriver = NULL;
HeadsetInterface* lovrHeadsetTrackingDrivers = NULL;
static bool initialized = false;
bool lovrHeadsetInit(HeadsetDriver* drivers, size_t count, float supersample, float offset, uint32_t msaa) {
bool lovrHeadsetInit(HeadsetDriver* drivers, size_t count, float supersample, float offset, uint32_t msaa, bool overlay) {
if (initialized) return false;
initialized = true;
@ -42,7 +42,7 @@ bool lovrHeadsetInit(HeadsetDriver* drivers, size_t count, float supersample, fl
bool hasDisplay = interface->renderTo != NULL;
bool shouldInitialize = !hasDisplay || !lovrHeadsetDisplayDriver;
if (shouldInitialize && interface->init(supersample, offset, msaa)) {
if (shouldInitialize && interface->init(supersample, offset, msaa, overlay)) {
if (hasDisplay) {
lovrHeadsetDisplayDriver = interface;
}

View File

@ -112,7 +112,7 @@ typedef enum {
typedef struct HeadsetInterface {
struct HeadsetInterface* next;
HeadsetDriver driverType;
bool (*init)(float supersample, float offset, uint32_t msaa);
bool (*init)(float supersample, float offset, uint32_t msaa, bool overlay);
void (*destroy)(void);
bool (*getName)(char* name, size_t length);
HeadsetOrigin (*getOriginType)(void);
@ -157,5 +157,5 @@ extern HeadsetInterface* lovrHeadsetTrackingDrivers;
#define FOREACH_TRACKING_DRIVER(i)\
for (HeadsetInterface* i = lovrHeadsetTrackingDrivers; i != NULL; i = i->next)
bool lovrHeadsetInit(HeadsetDriver* drivers, size_t count, float supersample, float offset, uint32_t msaa);
bool lovrHeadsetInit(HeadsetDriver* drivers, size_t count, float supersample, float offset, uint32_t msaa, bool overlay);
void lovrHeadsetDestroy(void);

View File

@ -31,7 +31,7 @@ static struct {
float yaw;
} state;
static bool desktop_init(float supersample, float offset, uint32_t msaa) {
static bool desktop_init(float supersample, float offset, uint32_t msaa, bool overlay) {
state.offset = offset;
state.clipNear = .1f;
state.clipFar = 100.f;

View File

@ -83,7 +83,8 @@ static ovrInputState *refreshButtons(void) {
return &is;
}
static bool oculus_init(float supersample, float offset, uint32_t msaa) {
static bool oculus_init(float supersample, float offset, uint32_t msaa, bool overlay) {
arr_init(&state.textures, realloc);
ovrResult result = ovr_Initialize(NULL);

View File

@ -112,7 +112,7 @@ static TrackedDeviceIndex_t getDeviceIndex(Device device) {
}
static bool openvr_getName(char* name, size_t length);
static bool openvr_init(float supersample, float offset, uint32_t msaa) {
static bool openvr_init(float supersample, float offset, uint32_t msaa, bool overlay) {
if (!VR_IsHmdPresent() || !VR_IsRuntimeInstalled()) {
return false;
}

View File

@ -145,6 +145,7 @@ static struct {
XrHandTrackerEXT handTrackers[2];
struct {
bool handTracking;
bool overlay;
} features;
} state;
@ -168,7 +169,7 @@ static bool hasExtension(XrExtensionProperties* extensions, uint32_t count, cons
static void openxr_destroy();
static bool openxr_init(float supersample, float offset, uint32_t msaa) {
static bool openxr_init(float supersample, float offset, uint32_t msaa, bool overlay) {
state.msaa = msaa;
#ifdef __ANDROID__
@ -198,17 +199,13 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa) {
for (uint32_t i = 0; i < extensionCount; i++) extensions[i].type = XR_TYPE_EXTENSION_PROPERTIES;
xrEnumerateInstanceExtensionProperties(NULL, 32, &extensionCount, extensions);
const char* enabledExtensionNames[4];
const char* enabledExtensionNames[5];
uint32_t enabledExtensionCount = 0;
#ifdef __ANDROID__
enabledExtensionNames[enabledExtensionCount++] = XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME;
#endif
#ifdef LOVR_LINUX_EGL
enabledExtensionNames[enabledExtensionCount++] = "XR_MNDX_egl_enable";
#endif
enabledExtensionNames[enabledExtensionCount++] = GRAPHICS_EXTENSION;
if (hasExtension(extensions, extensionCount, XR_EXT_HAND_TRACKING_EXTENSION_NAME)) {
@ -216,6 +213,18 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa) {
state.features.handTracking = true;
}
#ifdef XR_EXTX_overlay
// Provisional extension.
if (overlay && hasExtension(extensions, extensionCount, XR_EXTX_OVERLAY_EXTENSION_NAME)) {
enabledExtensionNames[enabledExtensionCount++] = XR_EXTX_OVERLAY_EXTENSION_NAME;
state.features.overlay = true;
}
#endif
#ifdef LOVR_LINUX_EGL
enabledExtensionNames[enabledExtensionCount++] = XR_MNDX_EGL_ENABLE_EXTENSION_NAME;
#endif
free(extensions);
XrInstanceCreateInfo info = {
@ -381,6 +390,19 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa) {
.systemId = state.system
};
#ifdef XR_EXTX_overlay
// Provisional extension.
XrSessionCreateInfoOverlayEXTX overlayInfo = {
.type = XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX,
.next = info.next,
// Fields may fluctuate, leave as auto initialised for now.
};
if (state.features.overlay) {
info.next = &overlayInfo;
}
#endif
XrSessionActionSetsAttachInfo attachInfo = {
.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO,
.countActionSets = 1,
@ -482,10 +504,18 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa) {
lovrRelease(texture, lovrTextureDestroy);
}
XrCompositionLayerFlags layerFlags = 0;
if (state.features.overlay) {
layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT |
XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
}
// Pre-init composition layer
state.layers[0] = (XrCompositionLayerProjection) {
.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION,
.space = state.referenceSpace,
.layerFlags = layerFlags,
.viewCount = 2,
.views = state.layerViews
};

View File

@ -234,7 +234,7 @@ static struct {
void* renderUserdata;
} state;
static bool pico_init(float supersample, float offset, uint32_t msaa) {
static bool pico_init(float supersample, float offset, uint32_t msaa, bool overlay) {
state.offset = offset;
state.clipNear = .1f;
state.clipFar = 100.f;

View File

@ -52,7 +52,7 @@ static struct {
float hapticDuration[2];
} state;
static bool vrapi_init(float supersample, float offset, uint32_t msaa) {
static bool vrapi_init(float supersample, float offset, uint32_t msaa, bool overlay) {
ANativeActivity* activity = os_get_activity();
JNIEnv* jni = os_get_jni();
state.java.Vm = activity->vm;
@ -602,8 +602,8 @@ static bool vrapi_animate(Device device, struct Model* model) {
float compensate[4];
if (device == DEVICE_HAND_LEFT) {
float q[4];
quat_fromAngleAxis(compensate, (float) -M_PI, 0.f, 0.f, 1.f);
quat_mul(compensate, compensate, quat_fromAngleAxis(q, (float) -M_PI / 2.f, 0.f, 1.f, 0.f));
quat_fromAngleAxis(compensate, (float) M_PI, 0.f, 0.f, 1.f);
quat_mul(compensate, compensate, quat_fromAngleAxis(q, (float) M_PI / 2.f, 0.f, 1.f, 0.f));
} else {
quat_fromAngleAxis(compensate, (float) -M_PI / 2.f, 0.f, 1.f, 0.f);
}

View File

@ -1,6 +1,6 @@
#include "headset/headset.h"
extern bool webxr_init(float supersample, float offset, uint32_t msaa);
extern bool webxr_init(float supersample, float offset, uint32_t msaa, bool overlay);
extern void webxr_destroy(void);
extern bool webxr_getName(char* name, size_t length);
extern HeadsetOrigin webxr_getOriginType(void);

5
src/resources/AppRun Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
IMAGE_DIR="$(dirname "$(readlink -f "$0")")"
exec "$IMAGE_DIR/lovr" "$@"

View File

@ -13,7 +13,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>v0.14.0</string>
<string>v0.15.0</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>

View File

@ -98,7 +98,7 @@ end
-- Note: Cannot be overloaded
function lovr.boot()
local conf = {
version = '0.14.0',
version = '0.15.0',
identity = 'default',
saveprecedence = true,
modules = {
@ -124,7 +124,8 @@ function lovr.boot()
drivers = { 'openxr', 'oculus', 'vrapi', 'pico', 'openvr', 'webxr', 'desktop' },
supersample = false,
offset = 1.7,
msaa = 4
msaa = 4,
overlay = false
},
math = {
globals = true

1
src/resources/logo.svg Normal file
View File

@ -0,0 +1 @@
<svg viewBox="0 0 85 78" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><defs><linearGradient x1="50%" y1="10.433596%" x2="50%" y2="89.3888378%" id="g1"><stop stop-color="#18A9E3" offset="0%"></stop><stop stop-color="#E94699" offset="100%"></stop></linearGradient><path d="M36.0947816,24.4670322 C44.9603247,9.17704943 59.3351373,9.17826246 68.2002532,24.4670322 L90.4871564,62.9030025 C99.3529756,78.1929853 92.2066627,90.5879653 74.5447305,90.5879653 L29.7514983,90.5879653 C12.0809204,90.5879653 4.94373271,78.1917723 13.8085725,62.9030025 L36.0947816,24.4670322 Z" id="p2"></path><mask id="m3" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="84.2947002" height="77.5879653" fill="white"><use href="#p2"></use></mask></defs><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g transform="translate(-10.000000, -13.000000)" stroke="url(#g1)" stroke-width="16" fill="rgba(255, 255, 255, .1)"><use mask="url(#m3)" href="#p2"></use></g></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,5 @@
[Desktop Entry]
Type=Application
Name=LÖVR
Icon=logo
Categories=

View File

@ -48,7 +48,7 @@ var webxr = {
},
webxr_init__deps: ['$buttons', '$axes'],
webxr_init: function(supersample, offset, msaa) {
webxr_init: function(supersample, offset, msaa, overlay) {
if (!navigator.xr) {
return false;
}