From 3f20364c3f5e9708bb04ddaf215638a510125fdf Mon Sep 17 00:00:00 2001 From: Ilya Chelyadin Date: Tue, 22 Nov 2022 20:22:27 +0300 Subject: [PATCH] Pico is back! Tested on Pico Neo 3 with PUI v4.9.3 Also included generic (Monado-Android) Android flavor. --- CMakeLists.txt | 17 +++++- etc/AndroidManifest_generic.xml | 36 +++++++++++ ...anifest.xml => AndroidManifest_oculus.xml} | 0 etc/AndroidManifest_pico.xml | 19 ++++++ src/modules/headset/headset_openxr.c | 61 ++++++++++++++++++- 5 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 etc/AndroidManifest_generic.xml rename etc/{AndroidManifest.xml => AndroidManifest_oculus.xml} (100%) create mode 100644 etc/AndroidManifest_pico.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 315378dd..a1591895 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,7 @@ if(EMSCRIPTEN) set(LOVR_USE_WEBGPU ON) set(LOVR_USE_VULKAN OFF) elseif(ANDROID) + set(ANDROID_FLAVOR "oculus" CACHE STRING "Which Android flavor to build (oculus, pico or generis)") find_package(Java REQUIRED) set(LOVR_USE_DESKTOP OFF) if(LOVR_BUILD_EXE) @@ -201,8 +202,18 @@ if(LOVR_ENABLE_HEADSET AND LOVR_USE_OPENXR) if(ANDROID) add_library(openxr_loader SHARED IMPORTED) set(LOVR_OPENXR openxr_loader) - set(LOVR_OPENXR_OCULUS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/deps/oculus-openxr" CACHE STRING "The path to the Oculus OpenXR loader") - set_target_properties(openxr_loader PROPERTIES IMPORTED_LOCATION "${LOVR_OPENXR_OCULUS_PATH}/Libs/Android/${ANDROID_ABI}/Release/libopenxr_loader.so") + if(ANDROID_FLAVOR STREQUAL "oculus") + set(LOVR_OPENXR_OCULUS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/deps/oculus-openxr" CACHE STRING "The path to the Oculus OpenXR loader") + set_target_properties(openxr_loader PROPERTIES IMPORTED_LOCATION "${LOVR_OPENXR_OCULUS_PATH}/Libs/Android/${ANDROID_ABI}/Release/libopenxr_loader.so") + elseif(ANDROID_FLAVOR STREQUAL "pico") + set(LOVR_OPENXR_PICO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/deps/pico-openxr" CACHE STRING "The path to the Pico OpenXR loader") + set_target_properties(openxr_loader PROPERTIES IMPORTED_LOCATION "${LOVR_OPENXR_PICO_PATH}/Libs/Android/${ANDROID_ABI}/libopenxr_loader.so") + elseif(ANDROID_FLAVOR STREQUAL "generic") + set(LOVR_OPENXR_GENERIC_PATH "${CMAKE_CURRENT_SOURCE_DIR}/deps/generic-openxr" CACHE STRING "The path to the Generic OpenXR loader") + set_target_properties(openxr_loader PROPERTIES IMPORTED_LOCATION "${LOVR_OPENXR_GENERIC_PATH}/Libs/Android/${ANDROID_ABI}/libopenxr_loader.so") + else() + message(FATAL_ERROR "Unsupported Android flavor (expected: oculus, pico or generis)") + endif() else() if(LOVR_SYSTEM_OPENXR) pkg_search_module(OPENXR openxr) @@ -727,7 +738,7 @@ elseif(ANDROID) if(LOVR_BUILD_EXE) set(ANDROID_JAR "${ANDROID_SDK}/platforms/${ANDROID_PLATFORM}/android.jar") set(ANDROID_TOOLS "${ANDROID_SDK}/build-tools/${ANDROID_BUILD_TOOLS_VERSION}") - set(ANDROID_MANIFEST "${CMAKE_CURRENT_SOURCE_DIR}/etc/AndroidManifest.xml" CACHE STRING "The AndroidManifest.xml file to use") + set(ANDROID_MANIFEST "${CMAKE_CURRENT_SOURCE_DIR}/etc/AndroidManifest_${ANDROID_FLAVOR}.xml" CACHE STRING "The AndroidManifest.xml file to use") # If assets are included in the apk then add '-A assets' to aapt, otherwise don't add any flags if(ANDROID_ASSETS) diff --git a/etc/AndroidManifest_generic.xml b/etc/AndroidManifest_generic.xml new file mode 100644 index 00000000..0f583ca4 --- /dev/null +++ b/etc/AndroidManifest_generic.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etc/AndroidManifest.xml b/etc/AndroidManifest_oculus.xml similarity index 100% rename from etc/AndroidManifest.xml rename to etc/AndroidManifest_oculus.xml diff --git a/etc/AndroidManifest_pico.xml b/etc/AndroidManifest_pico.xml new file mode 100644 index 00000000..e7b82156 --- /dev/null +++ b/etc/AndroidManifest_pico.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/headset/headset_openxr.c b/src/modules/headset/headset_openxr.c index a29a5db5..f4f4c738 100644 --- a/src/modules/headset/headset_openxr.c +++ b/src/modules/headset/headset_openxr.c @@ -329,6 +329,11 @@ static bool openxr_init(HeadsetConfig* config) { #ifdef LOVR_VK { "XR_KHR_vulkan_enable2", NULL, true }, #endif + +#ifdef __ANDROID__ + { "XR_KHR_android_create_instance", NULL, true }, + { "XR_PICO_android_controller_function_ext_enable", NULL, true}, +#endif { "XR_KHR_composition_layer_depth", &state.features.depth, config->submitDepth }, { "XR_EXT_eye_gaze_interaction", &state.features.gaze, true }, { "XR_EXT_hand_tracking", &state.features.handTracking, true }, @@ -352,6 +357,15 @@ static bool openxr_init(HeadsetConfig* config) { free(extensionProperties); +#ifdef __ANDROID__ + XrInstanceCreateInfoAndroidKHR infoAndroid = { + .type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, + .applicationVM = os_get_java_vm(), + .applicationActivity = os_get_jni_context(), + .next = NULL + }; +#endif + XrInstanceCreateInfo info = { .type = XR_TYPE_INSTANCE_CREATE_INFO, .applicationInfo.engineName = "LÖVR", @@ -360,7 +374,10 @@ static bool openxr_init(HeadsetConfig* config) { .applicationInfo.applicationVersion = 0, .applicationInfo.apiVersion = XR_CURRENT_API_VERSION, .enabledExtensionCount = enabledExtensionCount, - .enabledExtensionNames = enabledExtensionNames + .enabledExtensionNames = enabledExtensionNames, +#ifdef __ANDROID__ + .next = &infoAndroid +#endif }; XR_INIT(xrCreateInstance(&info, &state.instance)); @@ -545,6 +562,7 @@ static bool openxr_init(HeadsetConfig* config) { PROFILE_WMR, PROFILE_TRACKER, PROFILE_GAZE, + PROFILE_PICO, MAX_PROFILES }; @@ -556,7 +574,8 @@ static bool openxr_init(HeadsetConfig* config) { [PROFILE_INDEX] = "/interaction_profiles/valve/index_controller", [PROFILE_WMR] = "/interaction_profiles/microsoft/motion_controller", [PROFILE_TRACKER] = "/interaction_profiles/htc/vive_tracker_htcx", - [PROFILE_GAZE] = "/interaction_profiles/ext/eye_gaze_interaction" + [PROFILE_GAZE] = "/interaction_profiles/ext/eye_gaze_interaction", + [PROFILE_PICO] = "/interaction_profiles/pico/neo3_controller", }; typedef struct { @@ -755,6 +774,44 @@ static bool openxr_init(HeadsetConfig* config) { [PROFILE_GAZE] = (Binding[]) { { ACTION_GAZE_POSE, "/user/eyes_ext/input/gaze_ext/pose" }, { 0, NULL } + }, + [PROFILE_PICO] = (Binding[]) { + { ACTION_HAND_POSE, "/user/hand/left/input/grip/pose" }, + { ACTION_HAND_POSE, "/user/hand/right/input/grip/pose" }, + { ACTION_POINTER_POSE, "/user/hand/left/input/aim/pose" }, + { ACTION_POINTER_POSE, "/user/hand/right/input/aim/pose" }, + { ACTION_TRIGGER_DOWN, "/user/hand/left/input/trigger/value" }, + { ACTION_TRIGGER_DOWN, "/user/hand/right/input/trigger/value" }, + { ACTION_TRIGGER_TOUCH, "/user/hand/left/input/trigger/touch" }, + { ACTION_TRIGGER_TOUCH, "/user/hand/right/input/trigger/touch" }, + { ACTION_TRIGGER_AXIS, "/user/hand/left/input/trigger/value" }, + { ACTION_TRIGGER_AXIS, "/user/hand/right/input/trigger/value" }, + { ACTION_THUMBSTICK_DOWN, "/user/hand/left/input/thumbstick/click" }, + { ACTION_THUMBSTICK_DOWN, "/user/hand/right/input/thumbstick/click" }, + { ACTION_THUMBSTICK_TOUCH, "/user/hand/left/input/thumbstick/touch" }, + { ACTION_THUMBSTICK_TOUCH, "/user/hand/right/input/thumbstick/touch" }, + { ACTION_THUMBSTICK_X, "/user/hand/left/input/thumbstick/x" }, + { ACTION_THUMBSTICK_X, "/user/hand/right/input/thumbstick/x" }, + { ACTION_THUMBSTICK_Y, "/user/hand/left/input/thumbstick/y" }, + { ACTION_THUMBSTICK_Y, "/user/hand/right/input/thumbstick/y" }, + //{ ACTION_MENU_DOWN, "/user/hand/left/input/menu/click" }, //Imposter + { ACTION_MENU_DOWN, "/user/hand/right/input/system/click" }, + { ACTION_GRIP_DOWN, "/user/hand/left/input/squeeze/click" }, + { ACTION_GRIP_DOWN, "/user/hand/right/input/squeeze/click" }, + { ACTION_GRIP_AXIS, "/user/hand/left/input/squeeze/value" }, + { ACTION_GRIP_AXIS, "/user/hand/right/input/squeeze/value" }, + { ACTION_A_DOWN, "/user/hand/right/input/a/click" }, + { ACTION_A_TOUCH, "/user/hand/right/input/a/touch" }, + { ACTION_B_DOWN, "/user/hand/right/input/b/click" }, + { ACTION_B_TOUCH, "/user/hand/right/input/b/touch" }, + { ACTION_X_DOWN, "/user/hand/left/input/x/click" }, + { ACTION_X_TOUCH, "/user/hand/left/input/x/touch" }, + { ACTION_Y_DOWN, "/user/hand/left/input/y/click" }, + { ACTION_Y_TOUCH, "/user/hand/left/input/y/touch" }, + { ACTION_THUMBREST_TOUCH, "/user/hand/left/input/thumbrest/touch" }, + { ACTION_THUMBREST_TOUCH, "/user/hand/right/input/thumbrest/touch" }, + { ACTION_VIBRATE, "/user/hand/left/output/haptic" }, + { ACTION_VIBRATE, "/user/hand/right/output/haptic" }, } };