Merge branch 'master' into dev

This commit is contained in:
bjorn 2022-06-16 23:50:11 -07:00
commit c1bb47d737
13 changed files with 151 additions and 31 deletions

View File

@ -303,14 +303,15 @@ endif()
set(LOVR 1)
link_libraries(${LOVR_LUA})
file(GLOB LOVR_PLUGINS ${CMAKE_SOURCE_DIR}/plugins/*)
foreach(plugin ${LOVR_PLUGINS})
if(IS_DIRECTORY ${plugin} AND EXISTS ${plugin}/CMakeLists.txt)
add_subdirectory(${plugin} "${CMAKE_CURRENT_BINARY_DIR}/plugins/lib")
get_directory_property(PLUGIN_TARGETS DIRECTORY ${plugin} DEFINITION LOVR_PLUGIN_TARGETS)
foreach(PLUGIN_PATH ${LOVR_PLUGINS})
if(IS_DIRECTORY ${PLUGIN_PATH} AND EXISTS ${PLUGIN_PATH}/CMakeLists.txt)
get_filename_component(PLUGIN "${PLUGIN_PATH}" NAME)
add_subdirectory(${PLUGIN_PATH} "${CMAKE_CURRENT_BINARY_DIR}/plugins/${PLUGIN}")
get_directory_property(PLUGIN_TARGETS DIRECTORY ${PLUGIN_PATH} DEFINITION LOVR_PLUGIN_TARGETS)
if(NOT PLUGIN_TARGETS)
get_directory_property(PLUGIN_TARGETS DIRECTORY ${plugin} BUILDSYSTEM_TARGETS)
get_directory_property(PLUGIN_TARGETS DIRECTORY ${PLUGIN_PATH} BUILDSYSTEM_TARGETS)
endif()
set_target_properties(${PLUGIN_TARGETS} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/plugins/lib")
set_target_properties(${PLUGIN_TARGETS} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/plugins/${PLUGIN}")
list(APPEND ALL_PLUGIN_TARGETS ${PLUGIN_TARGETS})
endif()
endforeach()
@ -342,6 +343,7 @@ endif()
set_target_properties(lovr PROPERTIES C_VISIBILITY_PRESET ${LOVR_SYMBOL_VISIBILITY})
set_target_properties(lovr PROPERTIES C_STANDARD 11)
set_target_properties(lovr PROPERTIES C_STANDARD_REQUIRED ON)
target_include_directories(lovr PRIVATE src src/modules src/lib/stdatomic etc)
target_link_libraries(lovr
${LOVR_GLFW}
@ -586,6 +588,9 @@ foreach(path ${LOVR_RESOURCES})
file(WRITE ${output} "const unsigned char ${identifier}[] = {${data}};\nconst unsigned int ${identifier}_len = sizeof(${identifier});\n")
endforeach()
# Add a custom target that is always out of date so libraries are always moved
add_custom_target(move_libraries ALL)
# Platforms
if(WIN32)
target_sources(lovr PRIVATE src/core/os_win32.c)
@ -608,7 +613,7 @@ if(WIN32)
function(move_dll)
if(TARGET ${ARGV0})
add_custom_command(TARGET lovr POST_BUILD
add_custom_command(TARGET move_libraries POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${ARGV0}>
$<TARGET_FILE_DIR:lovr>/$<TARGET_FILE_NAME:${ARGV0}>
@ -651,13 +656,13 @@ elseif(APPLE)
if(TARGET ${ARGV0})
get_target_property(TARGET_TYPE ${ARGV0} TYPE)
if(${TARGET_TYPE} STREQUAL "MODULE_LIBRARY")
add_custom_command(TARGET lovr POST_BUILD
add_custom_command(TARGET move_libraries POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${ARGV0}>
${EXE_DIR}/$<TARGET_FILE_NAME:${ARGV0}>
)
else()
add_custom_command(TARGET lovr POST_BUILD
add_custom_command(TARGET move_libraries POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_SONAME_FILE:${ARGV0}>
${EXE_DIR}/$<TARGET_SONAME_FILE_NAME:${ARGV0}>
@ -763,12 +768,13 @@ elseif(ANDROID)
# Copy plugin libraries to lib folder before packaging APK
foreach(target ${ALL_PLUGIN_TARGETS})
add_custom_command(TARGET lovr POST_BUILD
add_custom_command(TARGET move_libraries POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${target}>
raw/lib/${ANDROID_ABI}/$<TARGET_FILE_NAME:${target}>
)
endforeach()
add_dependencies(buildAPK move_libraries)
endif()
elseif(UNIX)
if(LOVR_USE_LINUX_EGL)
@ -786,13 +792,13 @@ elseif(UNIX)
if(TARGET ${ARGV0})
get_target_property(TARGET_TYPE ${ARGV0} TYPE)
if(${TARGET_TYPE} STREQUAL "MODULE_LIBRARY")
add_custom_command(TARGET lovr POST_BUILD
add_custom_command(TARGET move_libraries POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${ARGV0}>
${CMAKE_BINARY_DIR}/bin/$<TARGET_FILE_NAME:${ARGV0}>
)
else()
add_custom_command(TARGET lovr POST_BUILD
add_custom_command(TARGET move_libraries POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_SONAME_FILE:${ARGV0}>
${CMAKE_BINARY_DIR}/bin/$<TARGET_SONAME_FILE_NAME:${ARGV0}>

2
deps/openxr vendored

@ -1 +1 @@
Subproject commit 458984d7f59d1ae6dc1b597d94b02e4f7132eaba
Subproject commit 885a90f8934d84121344ba8e4aa5159d5b496e08

View File

@ -67,7 +67,8 @@ function lovr.boot()
}
lovr.filesystem = require('lovr.filesystem')
local hasConf, hasMain = lovr.filesystem.isFile('conf.lua'), lovr.filesystem.isFile('main.lua')
local main = arg[0] and arg[0]:match('[^\\/]-%.lua$') or 'main.lua'
local hasConf, hasMain = lovr.filesystem.isFile('conf.lua'), lovr.filesystem.isFile(main)
if not lovr.filesystem.getSource() or not (hasConf or hasMain) then nogame() end
-- Shift args up in fused mode, instead of consuming one for the source path
@ -110,7 +111,7 @@ function lovr.boot()
lovr.handlers = setmetatable({}, { __index = lovr })
if not confOk then error(confError) end
if hasMain then require 'main' end
if hasMain then require(main:gsub('%.lua$', '')) end
return lovr.run()
end

View File

@ -134,6 +134,41 @@ static int l_lovrHeadsetGetDisplayFrequency(lua_State* L) {
return 1;
}
static int l_lovrHeadsetGetDisplayFrequencies(lua_State* L) {
if (!lovrHeadsetInterface->getDisplayFrequencies) {
lua_pushnil(L);
return 1;
}
uint32_t count = 0;
float* frequencies = lovrHeadsetInterface->getDisplayFrequencies(&count);
if (!frequencies) {
lua_pushnil(L);
return 1;
}
lua_settop(L, 0);
lua_createtable(L, count, 0);
for (uint32_t i = 0; i < count; ++i) {
lua_pushnumber(L, frequencies[i]);
lua_rawseti(L, 1, i + 1);
}
free(frequencies);
return 1;
}
static int l_lovrHeadsetSetDisplayFrequency(lua_State* L) {
float frequency = luax_checkfloat(L, 1);
bool res = false;
if (lovrHeadsetInterface->setDisplayFrequency) {
res = lovrHeadsetInterface->setDisplayFrequency(frequency);
}
lua_pushboolean(L, res);
return 1;
}
static int l_lovrHeadsetGetViewCount(lua_State* L) {
lua_pushinteger(L, lovrHeadsetInterface->getViewCount());
return 1;
@ -529,6 +564,8 @@ static const luaL_Reg lovrHeadset[] = {
{ "getDisplayHeight", l_lovrHeadsetGetDisplayHeight },
{ "getDisplayDimensions", l_lovrHeadsetGetDisplayDimensions },
{ "getDisplayFrequency", l_lovrHeadsetGetDisplayFrequency },
{ "getDisplayFrequencies", l_lovrHeadsetGetDisplayFrequencies },
{ "setDisplayFrequency", l_lovrHeadsetSetDisplayFrequency },
{ "getViewCount", l_lovrHeadsetGetViewCount },
{ "getViewPose", l_lovrHeadsetGetViewPose },
{ "getViewAngles", l_lovrHeadsetGetViewAngles },

View File

@ -367,6 +367,20 @@ static int l_lovrWorldIsCollisionEnabledBetween(lua_State* L) {
return 1;
}
static int l_lovrWorldGetStepCount(lua_State* L) {
World* world = luax_checktype(L, 1, World);
int iterations = lovrWorldGetStepCount(world);
lua_pushnumber(L, iterations);
return 1;
}
static int l_lovrWorldSetStepCount(lua_State* L) {
World* world = luax_checktype(L, 1, World);
int iterations = luaL_checkinteger(L, 2);
lovrWorldSetStepCount(world, iterations);
return 0;
}
const luaL_Reg lovrWorld[] = {
{ "newCollider", l_lovrWorldNewCollider },
{ "newBoxCollider", l_lovrWorldNewBoxCollider },
@ -397,5 +411,7 @@ const luaL_Reg lovrWorld[] = {
{ "disableCollisionBetween", l_lovrWorldDisableCollisionBetween },
{ "enableCollisionBetween", l_lovrWorldEnableCollisionBetween },
{ "isCollisionEnabledBetween", l_lovrWorldIsCollisionEnabledBetween },
{ "getStepCount", l_lovrWorldGetStepCount },
{ "setStepCount", l_lovrWorldSetStepCount },
{ NULL, NULL }
};

View File

@ -35,10 +35,12 @@ int main(int argc, char** argv) {
if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) {
os_open_console();
printf(
"usage: lovr [options] [<folder>]\n"
"usage: lovr [options] [<source>]\n\n"
"options:\n"
" -h, --help\t\tShow help and exit\n"
" -v, --version\t\tShow version and exit\n"
" --console\t\tAttach Windows console\n"
" --console\t\tAttach Windows console\n\n"
"<source> can be a Lua file, a folder, or a zip archive\n"
);
exit(0);
}

View File

@ -214,7 +214,7 @@ bool lovrAudioInit(const char* spatializer, uint32_t sampleRate) {
// SteamAudio's default frequency-dependent absorption coefficients for air
state.absorption[0] = .0002f;
state.absorption[1] = .0017f;
state.absorption[1] = .0182f;
state.absorption[2] = .0182f;
quat_identity(state.orientation);

View File

@ -148,6 +148,22 @@ bool lovrFilesystemInit(const char* archive) {
if (archive) {
state.source[LOVR_PATH_MAX - 1] = '\0';
strncpy(state.source, archive, LOVR_PATH_MAX - 1);
// If the command line parameter is a file, use its containing folder as the source
size_t length = strlen(state.source);
if (length > 4 && !memcmp(state.source + length - 4, ".lua", 4)) {
char* slash = strrchr(state.source, '/');
if (slash) {
*slash = '\0';
} else if ((slash = strrchr(state.source, '\\')) != NULL) {
*slash = '\0';
} else {
state.source[0] = '.';
state.source[1] = '\0';
}
}
if (lovrFilesystemMount(state.source, NULL, true, NULL)) {
return true;
}

View File

@ -117,6 +117,8 @@ typedef struct HeadsetInterface {
HeadsetOrigin (*getOriginType)(void);
void (*getDisplayDimensions)(uint32_t* width, uint32_t* height);
float (*getDisplayFrequency)(void);
float* (*getDisplayFrequencies)(uint32_t* count);
bool (*setDisplayFrequency)(float);
double (*getDisplayTime)(void);
double (*getDeltaTime)(void);
uint32_t (*getViewCount)(void);

View File

@ -7,6 +7,7 @@
#include "core/maf.h"
#include "core/os.h"
#include "util.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
@ -87,7 +88,9 @@ uintptr_t gpu_vk_get_queue(uint32_t* queueFamilyIndex, uint32_t* queueIndex);
X(xrDestroyHandTrackerEXT)\
X(xrLocateHandJointsEXT)\
X(xrGetHandMeshFB)\
X(xrGetDisplayRefreshRateFB)
X(xrGetDisplayRefreshRateFB) \
X(xrEnumerateDisplayRefreshRatesFB) \
X(xrRequestDisplayRefreshRateFB)
#define XR_DECLARE(fn) static PFN_##fn fn;
#define XR_LOAD(fn) xrGetInstanceProcAddr(state.instance, #fn, (PFN_xrVoidFunction*) &fn);
@ -313,10 +316,14 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa, bool ove
for (uint32_t i = 0; i < extensionCount; i++) extensionProperties[i].type = XR_TYPE_EXTENSION_PROPERTIES;
xrEnumerateInstanceExtensionProperties(NULL, extensionCount, &extensionCount, extensionProperties);
#ifdef __ANDROID__
bool androidCreateInstanceExtension = false;
#endif
// Extensions without a feature are required
struct { const char* name; bool* feature; bool disable; } extensions[] = {
#ifdef __ANDROID__
{ "XR_KHR_android_create_instance", NULL, false },
{ "XR_KHR_android_create_instance", &androidCreateInstanceExtension, false },
#endif
#ifdef LOVR_VK
{ "XR_KHR_vulkan_enable2", NULL, false },
@ -345,6 +352,7 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa, bool ove
XrInstanceCreateInfo info = {
.type = XR_TYPE_INSTANCE_CREATE_INFO,
#ifdef __ANDROID__
// harmless to include even if not available from runtime
.next = &(XrInstanceCreateInfoAndroidKHR) {
.type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR,
.applicationVM = activity->vm,
@ -507,7 +515,7 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa, bool ove
{ 0, NULL, "vibrate", XR_ACTION_TYPE_VIBRATION_OUTPUT, 2, hands, "Vibrate" }
};
_Static_assert(COUNTOF(actionInfo) == MAX_ACTIONS, "Unbalanced action table!");
static_assert(COUNTOF(actionInfo) == MAX_ACTIONS, "Unbalanced action table!");
if (!state.features.viveTrackers) {
actionInfo[ACTION_TRACKER_POSE].countSubactionPaths = 0;
@ -994,6 +1002,23 @@ static float openxr_getDisplayFrequency(void) {
return frequency;
}
static float* openxr_getDisplayFrequencies(uint32_t* count) {
if (!state.features.refreshRate || !count) return NULL;
XR(xrEnumerateDisplayRefreshRatesFB(state.session, 0, count, NULL));
float *frequencies = malloc(*count * sizeof(float));
lovrAssert(frequencies, "Out of Memory");
XR(xrEnumerateDisplayRefreshRatesFB(state.session, *count, count, frequencies));
return frequencies;
}
static bool openxr_setDisplayFrequency(float frequency) {
if (!state.features.refreshRate) return false;
XrResult res = xrRequestDisplayRefreshRateFB(state.session, frequency);
if (res == XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB) return false;
XR(res);
return true;
}
static double openxr_getDisplayTime(void) {
return state.frameState.predictedDisplayTime / 1e9;
}
@ -1763,6 +1788,8 @@ HeadsetInterface lovrHeadsetOpenXRDriver = {
.getOriginType = openxr_getOriginType,
.getDisplayDimensions = openxr_getDisplayDimensions,
.getDisplayFrequency = openxr_getDisplayFrequency,
.getDisplayFrequencies = openxr_getDisplayFrequencies,
.setDisplayFrequency = openxr_setDisplayFrequency,
.getDisplayTime = openxr_getDisplayTime,
.getDeltaTime = openxr_getDeltaTime,
.getViewCount = openxr_getViewCount,

View File

@ -191,6 +191,14 @@ void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* u
dJointGroupEmpty(world->contactGroup);
}
int lovrWorldGetStepCount(World* world) {
return dWorldGetQuickStepNumIterations(world->id);
}
void lovrWorldSetStepCount(World* world, int iterations) {
dWorldSetQuickStepNumIterations(world->id, iterations);
}
void lovrWorldComputeOverlaps(World* world) {
arr_clear(&world->overlaps);
dSpaceCollide(world->space, world, customNearCallback);
@ -918,6 +926,7 @@ void lovrShapeGetAABB(Shape* shape, float aabb[6]) {
}
SphereShape* lovrSphereShapeCreate(float radius) {
lovrCheck(radius > 0.f, "SphereShape radius must be positive");
SphereShape* sphere = calloc(1, sizeof(SphereShape));
lovrAssert(sphere, "Out of memory");
sphere->ref = 1;
@ -932,6 +941,7 @@ float lovrSphereShapeGetRadius(SphereShape* sphere) {
}
void lovrSphereShapeSetRadius(SphereShape* sphere, float radius) {
lovrCheck(radius > 0.f, "SphereShape radius must be positive");
dGeomSphereSetRadius(sphere->id, radius);
}
@ -954,10 +964,12 @@ void lovrBoxShapeGetDimensions(BoxShape* box, float* x, float* y, float* z) {
}
void lovrBoxShapeSetDimensions(BoxShape* box, float x, float y, float z) {
lovrCheck(x > 0.f && y > 0.f && z > 0.f, "BoxShape dimensions must be positive");
dGeomBoxSetLengths(box->id, x, y, z);
}
CapsuleShape* lovrCapsuleShapeCreate(float radius, float length) {
lovrCheck(radius > 0.f && length > 0.f, "CapsuleShape dimensions must be positive");
CapsuleShape* capsule = calloc(1, sizeof(CapsuleShape));
lovrAssert(capsule, "Out of memory");
capsule->ref = 1;
@ -974,6 +986,7 @@ float lovrCapsuleShapeGetRadius(CapsuleShape* capsule) {
}
void lovrCapsuleShapeSetRadius(CapsuleShape* capsule, float radius) {
lovrCheck(radius > 0.f, "CapsuleShape dimensions must be positive");
dGeomCapsuleSetParams(capsule->id, radius, lovrCapsuleShapeGetLength(capsule));
}
@ -984,10 +997,12 @@ float lovrCapsuleShapeGetLength(CapsuleShape* capsule) {
}
void lovrCapsuleShapeSetLength(CapsuleShape* capsule, float length) {
lovrCheck(length > 0.f, "CapsuleShape dimensions must be positive");
dGeomCapsuleSetParams(capsule->id, lovrCapsuleShapeGetRadius(capsule), length);
}
CylinderShape* lovrCylinderShapeCreate(float radius, float length) {
lovrCheck(radius > 0.f && length > 0.f, "CylinderShape dimensions must be positive");
CylinderShape* cylinder = calloc(1, sizeof(CylinderShape));
lovrAssert(cylinder, "Out of memory");
cylinder->ref = 1;
@ -1004,6 +1019,7 @@ float lovrCylinderShapeGetRadius(CylinderShape* cylinder) {
}
void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius) {
lovrCheck(radius > 0.f, "CylinderShape dimensions must be positive");
dGeomCylinderSetParams(cylinder->id, radius, lovrCylinderShapeGetLength(cylinder));
}
@ -1014,6 +1030,7 @@ float lovrCylinderShapeGetLength(CylinderShape* cylinder) {
}
void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length) {
lovrCheck(length > 0.f, "CylinderShape dimensions must be positive");
dGeomCylinderSetParams(cylinder->id, lovrCylinderShapeGetRadius(cylinder), length);
}

View File

@ -42,6 +42,8 @@ World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char
void lovrWorldDestroy(void* ref);
void lovrWorldDestroyData(World* world);
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata);
int lovrWorldGetStepCount(World* world);
void lovrWorldSetStepCount(World* world, int iterations);
void lovrWorldComputeOverlaps(World* world);
int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b);
int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float restitution);

View File

@ -65,15 +65,6 @@ void* arr_alloc(void* data, size_t size) {
}
// Hashmap
static uint32_t prevpo2(uint32_t x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x - (x >> 1);
}
static void map_rehash(map_t* map) {
map_t old = *map;
map->size <<= 1;
@ -110,7 +101,10 @@ static inline uint64_t map_find(map_t* map, uint64_t hash) {
}
void map_init(map_t* map, uint32_t n) {
map->size = prevpo2(n) + !n;
map->size = 1;
while (map->size + (map->size >> 1) < n) {
map->size <<= 1;
}
map->used = 0;
map->hashes = NULL;
map_rehash(map);