diff --git a/doc_classes/OpenXRFbSpaceWarpExtensionWrapper.xml b/doc_classes/OpenXRFbSpaceWarpExtensionWrapper.xml new file mode 100644 index 00000000..f2f20db4 --- /dev/null +++ b/doc_classes/OpenXRFbSpaceWarpExtensionWrapper.xml @@ -0,0 +1,34 @@ + + + + Wraps the [code]XR_FB_space_warp[/code] extension. + + + Wraps the [code]XR_FB_space_warp[/code] extension. + + + + + + + + Checks if the extension is enabled or not. + + + + + + + Sets the extension as enabled or disabled. + Note: The Application Space Warp project setting must be enabled in order to enable Application Space Warp. + + + + + + Skips space warp frame extrapolation for the next rendered frame. + This is useful in situations where the player camera is snapping/teleporting to a different position. + + + + diff --git a/docs/manual/meta/application_space_warp.rst b/docs/manual/meta/application_space_warp.rst new file mode 100644 index 00000000..c13335be --- /dev/null +++ b/docs/manual/meta/application_space_warp.rst @@ -0,0 +1,20 @@ +Meta Application Space Warp +=========================== + +.. note:: + + Check out the `Meta Space Warp Sample Project `_ + for a working demo of Application Space Warp. + +Application Space Warp is an extension for Meta XR devices that allows applications to render at half FPS while the runtime +generates the in-between frames, perserving a smooth experience for users while lowering the workload of the device's CPU/GPU. + +For more info on how Application Space Warp works, check out Meta's `Introducing Application Space Warp `_ blog post. + +Project Settings +---------------- + +To use Application Space Warp, the feature must be enabled in your project settings. The setting can be found in **Project Settings** under the **OpenXR** section. +The **Application Space Warp** setting should be listed under **Extensions**. The setting will not display unless **Advanced Settings** are enabled. + +.. image:: img/application_space_warp/space_warp_project_setting.png diff --git a/docs/manual/meta/img/application_space_warp/space_warp_project_setting.png b/docs/manual/meta/img/application_space_warp/space_warp_project_setting.png new file mode 100644 index 00000000..61687d0d Binary files /dev/null and b/docs/manual/meta/img/application_space_warp/space_warp_project_setting.png differ diff --git a/docs/manual/meta/index.rst b/docs/manual/meta/index.rst index cc4fdf64..10b46d05 100644 --- a/docs/manual/meta/index.rst +++ b/docs/manual/meta/index.rst @@ -7,6 +7,7 @@ Meta :maxdepth: 1 :name: toc-meta + application_space_warp composition_layers hand_tracking passthrough diff --git a/plugin/src/main/cpp/extensions/openxr_fb_space_warp_extension_wrapper.cpp b/plugin/src/main/cpp/extensions/openxr_fb_space_warp_extension_wrapper.cpp new file mode 100644 index 00000000..d9af4eb9 --- /dev/null +++ b/plugin/src/main/cpp/extensions/openxr_fb_space_warp_extension_wrapper.cpp @@ -0,0 +1,293 @@ +/**************************************************************************/ +/* openxr_fb_space_warp_extension_wrapper.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT XR */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "extensions/openxr_fb_space_warp_extension_wrapper.h" + +#include +#include +#include +#include +#include +#include + +#define GL_RGBA16F 0x881A +#define GL_DEPTH24_STENCIL8 0x88F0 + +#define VK_FORMAT_R16G16B16A16_SFLOAT 97 +#define VK_FORMAT_D24_UNORM_S8_UINT 129 + +OpenXRFbSpaceWarpExtensionWrapper *OpenXRFbSpaceWarpExtensionWrapper::singleton = nullptr; + +OpenXRFbSpaceWarpExtensionWrapper *OpenXRFbSpaceWarpExtensionWrapper::get_singleton() { + if (singleton == nullptr) { + singleton = memnew(OpenXRFbSpaceWarpExtensionWrapper()); + } + return singleton; +} + +OpenXRFbSpaceWarpExtensionWrapper::OpenXRFbSpaceWarpExtensionWrapper() : + OpenXRExtensionWrapperExtension() { + ERR_FAIL_COND_MSG(singleton != nullptr, "An OpenXRFbSpaceWarpExtensionWrapper singleton already exists."); + + request_extensions[XR_FB_SPACE_WARP_EXTENSION_NAME] = &fb_space_warp_ext; + singleton = this; +} + +OpenXRFbSpaceWarpExtensionWrapper::~OpenXRFbSpaceWarpExtensionWrapper() { + cleanup(); + singleton = nullptr; +} + +godot::Dictionary OpenXRFbSpaceWarpExtensionWrapper::_get_requested_extensions() { + godot::Dictionary result; + for (auto ext : request_extensions) { + godot::String key = ext.first; + uint64_t value = reinterpret_cast(ext.second); + result[key] = (godot::Variant)value; + } + return result; +} + +uint64_t OpenXRFbSpaceWarpExtensionWrapper::_set_system_properties_and_get_next_pointer(void *p_next_pointer) { + if (fb_space_warp_ext) { + system_space_warp_properties.next = p_next_pointer; + return reinterpret_cast(&system_space_warp_properties); + } else { + return reinterpret_cast(p_next_pointer); + } +} + +uint64_t OpenXRFbSpaceWarpExtensionWrapper::_set_projection_views_and_get_next_pointer(int p_view_index, void *p_next_pointer) { + if (fb_space_warp_ext) { + space_warp_info[p_view_index].next = p_next_pointer; + return reinterpret_cast(&space_warp_info[p_view_index]); + } else { + return reinterpret_cast(p_next_pointer); + } +} + +void OpenXRFbSpaceWarpExtensionWrapper::_on_instance_destroyed() { + cleanup(); +} + +void OpenXRFbSpaceWarpExtensionWrapper::_on_session_created(uint64_t p_instance) { + if (!fb_space_warp_ext) { + return; + } + + ProjectSettings *project_settings = ProjectSettings::get_singleton(); + bool is_project_setting_enabled = (bool)project_settings->get_setting_with_override("xr/openxr/extensions/application_space_warp"); + if (!is_project_setting_enabled) { + fb_space_warp_ext = false; + return; + } else { + enabled = true; + } + + String rendering_method = (String)project_settings->get_setting_with_override("rendering/renderer/rendering_method"); + if (rendering_method == "forward_plus") { + UtilityFunctions::print_verbose("Disabling XR_FB_space_warp extension; this extension is not supported in the forward plus renderer"); + cleanup(); + return; + } + + get_openxr_api()->register_projection_views_extension(this); +} + +void OpenXRFbSpaceWarpExtensionWrapper::_on_session_destroyed() { + if (!fb_space_warp_ext) { + return; + } + + get_openxr_api()->unregister_projection_views_extension(this); + memdelete_arr(space_warp_info); +} + +void OpenXRFbSpaceWarpExtensionWrapper::_on_state_ready() { + if (!is_enabled()) { + return; + } + + Ref openxr_interface = XRServer::get_singleton()->find_interface("OpenXR"); + int view_count = openxr_interface->get_view_count(); + int width = system_space_warp_properties.recommendedMotionVectorImageRectWidth; + int height = system_space_warp_properties.recommendedMotionVectorImageRectHeight; + + String rendering_driver_name = RenderingServer::get_singleton()->get_current_rendering_driver_name(); + int swapchain_format, depth_swapchain_format = 0; + + if (rendering_driver_name.contains("opengl")) { + swapchain_format = GL_RGBA16F; + depth_swapchain_format = GL_DEPTH24_STENCIL8; + } else if (rendering_driver_name == "vulkan") { + swapchain_format = VK_FORMAT_R16G16B16A16_SFLOAT; + depth_swapchain_format = VK_FORMAT_D24_UNORM_S8_UINT; + } else { + UtilityFunctions::print_verbose("Disabling XR_FB_space_warp extension; rendering driver is not supported: ", rendering_driver_name); + cleanup(); + return; + } + + motion_vector_swapchain_info = get_openxr_api()->openxr_swapchain_create(0, XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, swapchain_format, width, height, 1, view_count); + motion_vector_depth_swapchain_info = get_openxr_api()->openxr_swapchain_create(0, XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, depth_swapchain_format, width, height, 1, view_count); +} + +void OpenXRFbSpaceWarpExtensionWrapper::_on_main_swapchains_created() { + if (!fb_space_warp_ext) { + return; + } + + Ref openxr_interface = XRServer::get_singleton()->find_interface("OpenXR"); + int view_count = openxr_interface->get_view_count(); + + space_warp_info = memnew_arr(XrCompositionLayerSpaceWarpInfoFB, view_count); + for (int i = 0; i < view_count; i++) { + space_warp_info[i].type = XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB; + + space_warp_info[i].next = nullptr; + + space_warp_info[i].layerFlags = 0; + + space_warp_info[i].motionVectorSubImage.swapchain = (XrSwapchain)get_openxr_api()->openxr_swapchain_get_swapchain(motion_vector_swapchain_info); + space_warp_info[i].motionVectorSubImage.imageRect.offset.x = 0; + space_warp_info[i].motionVectorSubImage.imageRect.offset.y = 0; + space_warp_info[i].motionVectorSubImage.imageRect.extent.width = system_space_warp_properties.recommendedMotionVectorImageRectWidth; + space_warp_info[i].motionVectorSubImage.imageRect.extent.height = system_space_warp_properties.recommendedMotionVectorImageRectHeight; + space_warp_info[i].motionVectorSubImage.imageArrayIndex = i; + + space_warp_info[i].appSpaceDeltaPose = { { 0.0, 0.0, 0.0, 1.0 }, { 0.0, 0.0, 0.0 } }; + + space_warp_info[i].depthSubImage.swapchain = (XrSwapchain)get_openxr_api()->openxr_swapchain_get_swapchain(motion_vector_depth_swapchain_info); + space_warp_info[i].depthSubImage.imageRect.offset.x = 0; + space_warp_info[i].depthSubImage.imageRect.offset.y = 0; + space_warp_info[i].depthSubImage.imageRect.extent.width = system_space_warp_properties.recommendedMotionVectorImageRectWidth; + space_warp_info[i].depthSubImage.imageRect.extent.height = system_space_warp_properties.recommendedMotionVectorImageRectHeight; + space_warp_info[i].depthSubImage.imageArrayIndex = i; + + space_warp_info[i].minDepth = 0.0; + space_warp_info[i].maxDepth = 1.0; + + space_warp_info[i].farZ = get_openxr_api()->get_render_state_z_near(); + space_warp_info[i].nearZ = get_openxr_api()->get_render_state_z_far(); + } +} + +void OpenXRFbSpaceWarpExtensionWrapper::_on_pre_render() { + if (!is_enabled()) { + return; + } + + get_openxr_api()->openxr_swapchain_acquire(motion_vector_swapchain_info); + get_openxr_api()->openxr_swapchain_acquire(motion_vector_depth_swapchain_info); + + RID motion_vector_swapchain_image = get_openxr_api()->openxr_swapchain_get_image(motion_vector_swapchain_info); + get_openxr_api()->set_velocity_texture(motion_vector_swapchain_image); + RID motion_vector_depth_swapchain_image = get_openxr_api()->openxr_swapchain_get_image(motion_vector_depth_swapchain_info); + get_openxr_api()->set_velocity_depth_texture(motion_vector_depth_swapchain_image); + + int target_width = system_space_warp_properties.recommendedMotionVectorImageRectWidth; + int target_height = system_space_warp_properties.recommendedMotionVectorImageRectHeight; + Size2i render_target_size = { target_width, target_height }; + get_openxr_api()->set_velocity_target_size(render_target_size); + + Transform3D world_transform = XRServer::get_singleton()->get_world_origin(); + Transform3D delta_transform = render_state.previous_transform.affine_inverse() * world_transform; + Quaternion delta_quat = delta_transform.basis.get_quaternion(); + Vector3 delta_origin = delta_transform.origin; + + Ref openxr_interface = XRServer::get_singleton()->find_interface("OpenXR"); + int view_count = openxr_interface->get_view_count(); + for (int i = 0; i < view_count; i++) { + space_warp_info[i].layerFlags = render_state.skip_space_warp_frame ? XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB : 0; + space_warp_info[i].appSpaceDeltaPose = { { delta_quat.x, delta_quat.y, delta_quat.z, delta_quat.w }, { delta_origin.x, delta_origin.y, delta_origin.z } }; + space_warp_info[i].farZ = get_openxr_api()->get_render_state_z_near(); + space_warp_info[i].nearZ = get_openxr_api()->get_render_state_z_far(); + } + + render_state.skip_space_warp_frame = false; + render_state.previous_transform = world_transform; +} + +void OpenXRFbSpaceWarpExtensionWrapper::_on_post_draw_viewport(const RID &p_render_target) { + if (!is_enabled()) { + return; + } + + get_openxr_api()->openxr_swapchain_release(motion_vector_swapchain_info); + get_openxr_api()->openxr_swapchain_release(motion_vector_depth_swapchain_info); +} + +bool OpenXRFbSpaceWarpExtensionWrapper::is_enabled() { + return fb_space_warp_ext && enabled; +} + +void OpenXRFbSpaceWarpExtensionWrapper::set_space_warp_enabled(bool p_enable) { + enabled = p_enable; +} + +void OpenXRFbSpaceWarpExtensionWrapper::_skip_space_warp_frame() { + render_state.skip_space_warp_frame = true; +} + +void OpenXRFbSpaceWarpExtensionWrapper::skip_space_warp_frame() { + if (!is_enabled()) { + return; + } + + RenderingServer::get_singleton()->call_on_render_thread(callable_mp(this, &OpenXRFbSpaceWarpExtensionWrapper::_skip_space_warp_frame)); +} + +void OpenXRFbSpaceWarpExtensionWrapper::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_space_warp_enabled", "enable"), &OpenXRFbSpaceWarpExtensionWrapper::set_space_warp_enabled); + ClassDB::bind_method(D_METHOD("is_enabled"), &OpenXRFbSpaceWarpExtensionWrapper::is_enabled); + ClassDB::bind_method(D_METHOD("skip_space_warp_frame"), &OpenXRFbSpaceWarpExtensionWrapper::skip_space_warp_frame); +} + +void OpenXRFbSpaceWarpExtensionWrapper::cleanup() { + if (fb_space_warp_ext) { + get_openxr_api()->unregister_projection_views_extension(this); + } + + fb_space_warp_ext = false; + enabled = false; +} + +void OpenXRFbSpaceWarpExtensionWrapper::add_project_setting() { + String p_name = "xr/openxr/extensions/application_space_warp"; + if (!ProjectSettings::get_singleton()->has_setting(p_name)) { + ProjectSettings::get_singleton()->set_setting(p_name, false); + } + + ProjectSettings::get_singleton()->set_initial_value(p_name, false); + Dictionary property_info; + property_info["name"] = p_name; + property_info["type"] = Variant::Type::BOOL; + property_info["hint"] = PROPERTY_HINT_NONE; + ProjectSettings::get_singleton()->add_property_info(property_info); +} diff --git a/plugin/src/main/cpp/include/extensions/openxr_fb_space_warp_extension_wrapper.h b/plugin/src/main/cpp/include/extensions/openxr_fb_space_warp_extension_wrapper.h new file mode 100644 index 00000000..c3a9e623 --- /dev/null +++ b/plugin/src/main/cpp/include/extensions/openxr_fb_space_warp_extension_wrapper.h @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* openxr_fb_space_warp_extension_wrapper.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT XR */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef OPENXR_FB_SPACE_WARP_EXTENSION_WRAPPER_H +#define OPENXR_FB_SPACE_WARP_EXTENSION_WRAPPER_H + +#include +#include +#include +#include + +using namespace godot; + +class OpenXRFbSpaceWarpExtensionWrapper : public OpenXRExtensionWrapperExtension { + GDCLASS(OpenXRFbSpaceWarpExtensionWrapper, OpenXRExtensionWrapperExtension); + +public: + static OpenXRFbSpaceWarpExtensionWrapper *get_singleton(); + + OpenXRFbSpaceWarpExtensionWrapper(); + virtual ~OpenXRFbSpaceWarpExtensionWrapper() override; + + godot::Dictionary _get_requested_extensions() override; + + uint64_t _set_system_properties_and_get_next_pointer(void *p_next_pointer) override; + uint64_t _set_projection_views_and_get_next_pointer(int p_view_index, void *p_next_pointer) override; + + void _on_instance_destroyed() override; + void _on_session_created(uint64_t p_instance) override; + void _on_session_destroyed() override; + void _on_state_ready() override; + void _on_main_swapchains_created() override; + void _on_pre_render() override; + void _on_post_draw_viewport(const RID &p_render_target) override; + + bool is_enabled(); + + void set_space_warp_enabled(bool p_enable); + + void skip_space_warp_frame(); + + void add_project_setting(); + +protected: + static void _bind_methods(); + +private: + void _skip_space_warp_frame(); + + void cleanup(); + + static OpenXRFbSpaceWarpExtensionWrapper *singleton; + + bool enabled = false; + + XrSystemSpaceWarpPropertiesFB system_space_warp_properties = { + XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB, // type + nullptr, // next + 0, // recommendedMotionVectorImageRectWidth + 0, // recommendedMotionVectorImageRectHeight + }; + + uint64_t motion_vector_swapchain_info = 0; + uint64_t motion_vector_depth_swapchain_info = 0; + + XrCompositionLayerSpaceWarpInfoFB *space_warp_info; + + std::map request_extensions; + bool fb_space_warp_ext = false; + + struct RenderState { + bool skip_space_warp_frame = false; + Transform3D previous_transform = { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 0.0, 0.0 } }; + } render_state; +}; + +#endif // OPENXR_FB_SPACE_WARP_EXTENSION_WRAPPER_H diff --git a/plugin/src/main/cpp/register_types.cpp b/plugin/src/main/cpp/register_types.cpp index 95978586..71e26bc1 100644 --- a/plugin/src/main/cpp/register_types.cpp +++ b/plugin/src/main/cpp/register_types.cpp @@ -58,6 +58,7 @@ #include "extensions/openxr_fb_render_model_extension_wrapper.h" #include "extensions/openxr_fb_scene_capture_extension_wrapper.h" #include "extensions/openxr_fb_scene_extension_wrapper.h" +#include "extensions/openxr_fb_space_warp_extension_wrapper.h" #include "extensions/openxr_fb_spatial_entity_container_extension_wrapper.h" #include "extensions/openxr_fb_spatial_entity_extension_wrapper.h" #include "extensions/openxr_fb_spatial_entity_query_extension_wrapper.h" @@ -126,6 +127,9 @@ void initialize_plugin_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); OpenXRFbSceneExtensionWrapper::get_singleton()->register_extension_wrapper(); + ClassDB::register_class(); + OpenXRFbSpaceWarpExtensionWrapper::get_singleton()->register_extension_wrapper(); + ClassDB::register_class(); OpenXRFbFaceTrackingExtensionWrapper::get_singleton()->register_extension_wrapper(); @@ -175,6 +179,7 @@ void initialize_plugin_module(ModuleInitializationLevel p_level) { Engine::get_singleton()->register_singleton("OpenXRFbSpatialEntityQueryExtensionWrapper", OpenXRFbSpatialEntityQueryExtensionWrapper::get_singleton()); Engine::get_singleton()->register_singleton("OpenXRFbSpatialEntityContainerExtensionWrapper", OpenXRFbSpatialEntityContainerExtensionWrapper::get_singleton()); Engine::get_singleton()->register_singleton("OpenXRFbSceneExtensionWrapper", OpenXRFbSceneExtensionWrapper::get_singleton()); + Engine::get_singleton()->register_singleton("OpenXRFbSpaceWarpExtensionWrapper", OpenXRFbSpaceWarpExtensionWrapper::get_singleton()); Engine::get_singleton()->register_singleton("OpenXRFbHandTrackingAimExtensionWrapper", OpenXRFbHandTrackingAimExtensionWrapper::get_singleton()); Engine::get_singleton()->register_singleton("OpenXRFbHandTrackingCapsulesExtensionWrapper", OpenXRFbHandTrackingCapsulesExtensionWrapper::get_singleton()); Engine::get_singleton()->register_singleton("OpenXRFbCompositionLayerSettingsExtensionWrapper", OpenXRFbCompositionLayerSettingsExtensionWrapper::get_singleton()); @@ -197,6 +202,7 @@ void initialize_plugin_module(ModuleInitializationLevel p_level) { OpenXRFbHandTrackingAimExtensionWrapper::get_singleton()->add_project_setting(); OpenXRMetaRecommendedLayerResolutionExtensionWrapper::get_singleton()->add_project_setting(); + OpenXRFbSpaceWarpExtensionWrapper::get_singleton()->add_project_setting(); } break; case MODULE_INITIALIZATION_LEVEL_EDITOR: { diff --git a/samples/.gitignore b/samples/.gitignore index fbf95ea5..6d1d0e44 100644 --- a/samples/.gitignore +++ b/samples/.gitignore @@ -2,3 +2,4 @@ */.godot/ */addons/godotopenxrvendors */android/ +*/screenshots/*.import diff --git a/samples/hybrid-app-sample/.gitattributes b/samples/hybrid-app-sample/.gitattributes deleted file mode 100644 index 8ad74f78..00000000 --- a/samples/hybrid-app-sample/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Normalize EOL for all files that Git considers text files. -* text=auto eol=lf diff --git a/samples/hybrid-app-sample/.gitignore b/samples/hybrid-app-sample/.gitignore deleted file mode 100644 index 7de8ea58..00000000 --- a/samples/hybrid-app-sample/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Godot 4+ specific ignores -.godot/ -android/ diff --git a/samples/meta-space-warp-sample/.editorconfig b/samples/meta-space-warp-sample/.editorconfig new file mode 100644 index 00000000..f28239ba --- /dev/null +++ b/samples/meta-space-warp-sample/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/samples/meta-space-warp-sample/README.md b/samples/meta-space-warp-sample/README.md new file mode 100644 index 00000000..a3edef18 --- /dev/null +++ b/samples/meta-space-warp-sample/README.md @@ -0,0 +1,9 @@ +# Meta Hand Tracking Sample + +> Note: this project requires Godot 4.4 or later + +This is a sample project demonstrating the Meta Application SpaceWarp feature supported by the Godot OpenXR Vendors plugin. + +# Screenshots + +![Screenshot](screenshots/meta_space_warp_screenshot_01.png) diff --git a/samples/meta-space-warp-sample/bone-cube.glb b/samples/meta-space-warp-sample/bone-cube.glb new file mode 100644 index 00000000..d3c9adf2 Binary files /dev/null and b/samples/meta-space-warp-sample/bone-cube.glb differ diff --git a/samples/meta-space-warp-sample/bone-cube.glb.import b/samples/meta-space-warp-sample/bone-cube.glb.import new file mode 100644 index 00000000..87b8687b --- /dev/null +++ b/samples/meta-space-warp-sample/bone-cube.glb.import @@ -0,0 +1,37 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://detbvmjyhigan" +path="res://.godot/imported/bone-cube.glb-853e452a3ff35207a1fee3eefca16cf0.scn" + +[deps] + +source_file="res://bone-cube.glb" +dest_files=["res://.godot/imported/bone-cube.glb-853e452a3ff35207a1fee3eefca16cf0.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +_subresources={} +gltf/naming_version=1 +gltf/embedded_image_handling=1 diff --git a/samples/meta-space-warp-sample/bone_cube.gd b/samples/meta-space-warp-sample/bone_cube.gd new file mode 100644 index 00000000..1c58bf93 --- /dev/null +++ b/samples/meta-space-warp-sample/bone_cube.gd @@ -0,0 +1,11 @@ +extends Node3D + +@onready var skeleton := $Armature/Skeleton3D + +func _physics_process(delta: float) -> void: + if not "--xrsim-automated-tests" in OS.get_cmdline_user_args(): + # When we're running tests via the XR Simulator, we don't want this + # to be animated, which can lead to differences in the screenshots. + var new_basis := basis.rotated(Vector3.FORWARD, TAU * (Time.get_ticks_msec() / 2000.0)) + var quat := Quaternion(new_basis) + skeleton.set_bone_pose_rotation(0, quat) diff --git a/samples/meta-space-warp-sample/bone_cube.gd.uid b/samples/meta-space-warp-sample/bone_cube.gd.uid new file mode 100644 index 00000000..aae3389d --- /dev/null +++ b/samples/meta-space-warp-sample/bone_cube.gd.uid @@ -0,0 +1 @@ +uid://c46atn5swoq1e diff --git a/samples/meta-space-warp-sample/bone_cube.tscn b/samples/meta-space-warp-sample/bone_cube.tscn new file mode 100644 index 00000000..c2c0b532 --- /dev/null +++ b/samples/meta-space-warp-sample/bone_cube.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=3 format=3 uid="uid://cfbmcnbws28t1"] + +[ext_resource type="PackedScene" uid="uid://detbvmjyhigan" path="res://bone-cube.glb" id="1_fud8w"] +[ext_resource type="Script" path="res://bone_cube.gd" id="2_n023m"] + +[node name="BoneCube" instance=ExtResource("1_fud8w")] +script = ExtResource("2_n023m") diff --git a/samples/meta-space-warp-sample/export_presets.cfg b/samples/meta-space-warp-sample/export_presets.cfg new file mode 100644 index 00000000..57676713 --- /dev/null +++ b/samples/meta-space-warp-sample/export_presets.cfg @@ -0,0 +1,239 @@ +[preset.0] + +name="Quest" +platform="Android" +runnable=true +advanced_options=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="../builds/MetaSpaceWarpSample.apk" +patches=PackedStringArray() +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +gradle_build/use_gradle_build=true +gradle_build/gradle_build_directory="" +gradle_build/android_source_template="" +gradle_build/compress_native_libraries=false +gradle_build/export_format=0 +gradle_build/min_sdk="" +gradle_build/target_sdk="" +architectures/armeabi-v7a=false +architectures/arm64-v8a=true +architectures/x86=false +architectures/x86_64=false +version/code=1 +version/name="" +package/unique_name="com.godotopenxrvendors.metaspacewarpsample" +package/name="" +package/signed=true +package/app_category=2 +package/retain_data_on_uninstall=false +package/exclude_from_recents=false +package/show_in_android_tv=false +package/show_in_app_library=true +package/show_as_launcher_app=false +launcher_icons/main_192x192="" +launcher_icons/adaptive_foreground_432x432="" +launcher_icons/adaptive_background_432x432="" +launcher_icons/adaptive_monochrome_432x432="" +graphics/opengl_debug=false +xr_features/xr_mode=1 +screen/immersive_mode=true +screen/support_small=true +screen/support_normal=true +screen/support_large=true +screen/support_xlarge=true +user_data_backup/allow=false +command_line/extra_args="" +apk_expansion/enable=false +apk_expansion/SALT="" +apk_expansion/public_key="" +permissions/custom_permissions=PackedStringArray() +permissions/access_checkin_properties=false +permissions/access_coarse_location=false +permissions/access_fine_location=false +permissions/access_location_extra_commands=false +permissions/access_mock_location=false +permissions/access_network_state=false +permissions/access_surface_flinger=false +permissions/access_wifi_state=false +permissions/account_manager=false +permissions/add_voicemail=false +permissions/authenticate_accounts=false +permissions/battery_stats=false +permissions/bind_accessibility_service=false +permissions/bind_appwidget=false +permissions/bind_device_admin=false +permissions/bind_input_method=false +permissions/bind_nfc_service=false +permissions/bind_notification_listener_service=false +permissions/bind_print_service=false +permissions/bind_remoteviews=false +permissions/bind_text_service=false +permissions/bind_vpn_service=false +permissions/bind_wallpaper=false +permissions/bluetooth=false +permissions/bluetooth_admin=false +permissions/bluetooth_privileged=false +permissions/brick=false +permissions/broadcast_package_removed=false +permissions/broadcast_sms=false +permissions/broadcast_sticky=false +permissions/broadcast_wap_push=false +permissions/call_phone=false +permissions/call_privileged=false +permissions/camera=false +permissions/capture_audio_output=false +permissions/capture_secure_video_output=false +permissions/capture_video_output=false +permissions/change_component_enabled_state=false +permissions/change_configuration=false +permissions/change_network_state=false +permissions/change_wifi_multicast_state=false +permissions/change_wifi_state=false +permissions/clear_app_cache=false +permissions/clear_app_user_data=false +permissions/control_location_updates=false +permissions/delete_cache_files=false +permissions/delete_packages=false +permissions/device_power=false +permissions/diagnostic=false +permissions/disable_keyguard=false +permissions/dump=false +permissions/expand_status_bar=false +permissions/factory_test=false +permissions/flashlight=false +permissions/force_back=false +permissions/get_accounts=false +permissions/get_package_size=false +permissions/get_tasks=false +permissions/get_top_activity_info=false +permissions/global_search=false +permissions/hardware_test=false +permissions/inject_events=false +permissions/install_location_provider=false +permissions/install_packages=false +permissions/install_shortcut=false +permissions/internal_system_window=false +permissions/internet=false +permissions/kill_background_processes=false +permissions/location_hardware=false +permissions/manage_accounts=false +permissions/manage_app_tokens=false +permissions/manage_documents=false +permissions/manage_external_storage=false +permissions/master_clear=false +permissions/media_content_control=false +permissions/modify_audio_settings=false +permissions/modify_phone_state=false +permissions/mount_format_filesystems=false +permissions/mount_unmount_filesystems=false +permissions/nfc=false +permissions/persistent_activity=false +permissions/post_notifications=false +permissions/process_outgoing_calls=false +permissions/read_calendar=false +permissions/read_call_log=false +permissions/read_contacts=false +permissions/read_external_storage=false +permissions/read_frame_buffer=false +permissions/read_history_bookmarks=false +permissions/read_input_state=false +permissions/read_logs=false +permissions/read_phone_state=false +permissions/read_profile=false +permissions/read_sms=false +permissions/read_social_stream=false +permissions/read_sync_settings=false +permissions/read_sync_stats=false +permissions/read_user_dictionary=false +permissions/reboot=false +permissions/receive_boot_completed=false +permissions/receive_mms=false +permissions/receive_sms=false +permissions/receive_wap_push=false +permissions/record_audio=false +permissions/reorder_tasks=false +permissions/restart_packages=false +permissions/send_respond_via_message=false +permissions/send_sms=false +permissions/set_activity_watcher=false +permissions/set_alarm=false +permissions/set_always_finish=false +permissions/set_animation_scale=false +permissions/set_debug_app=false +permissions/set_orientation=false +permissions/set_pointer_speed=false +permissions/set_preferred_applications=false +permissions/set_process_limit=false +permissions/set_time=false +permissions/set_time_zone=false +permissions/set_wallpaper=false +permissions/set_wallpaper_hints=false +permissions/signal_persistent_processes=false +permissions/status_bar=false +permissions/subscribed_feeds_read=false +permissions/subscribed_feeds_write=false +permissions/system_alert_window=false +permissions/transmit_ir=false +permissions/uninstall_shortcut=false +permissions/update_device_stats=false +permissions/use_credentials=false +permissions/use_sip=false +permissions/vibrate=false +permissions/wake_lock=false +permissions/write_apn_settings=false +permissions/write_calendar=false +permissions/write_call_log=false +permissions/write_contacts=false +permissions/write_external_storage=false +permissions/write_gservices=false +permissions/write_history_bookmarks=false +permissions/write_profile=false +permissions/write_secure_settings=false +permissions/write_settings=false +permissions/write_sms=false +permissions/write_social_stream=false +permissions/write_sync_settings=false +permissions/write_user_dictionary=false +xr_features/enable_khronos_plugin=false +khronos_xr_features/vendors=0 +khronos_xr_features/htc/hand_tracking=0 +khronos_xr_features/htc/tracker=0 +khronos_xr_features/htc/eye_tracking=0 +khronos_xr_features/htc/lip_expression=0 +xr_features/enable_lynx_plugin=false +xr_features/enable_meta_plugin=true +meta_xr_features/eye_tracking=0 +meta_xr_features/face_tracking=0 +meta_xr_features/body_tracking=0 +meta_xr_features/hand_tracking=0 +meta_xr_features/hand_tracking_frequency=0 +meta_xr_features/passthrough=0 +meta_xr_features/render_model=2 +meta_xr_features/use_anchor_api=false +meta_xr_features/use_scene_api=false +meta_xr_features/use_overlay_keyboard=false +meta_xr_features/use_experimental_features=false +meta_xr_features/boundary_mode=0 +meta_xr_features/quest_1_support=false +meta_xr_features/quest_2_support=true +meta_xr_features/quest_3_support=true +meta_xr_features/quest_pro_support=true +xr_features/enable_pico_plugin=false +pico_xr_features/eye_tracking=0 +pico_xr_features/face_tracking=0 +pico_xr_features/hand_tracking=0 +xr_features/enable_magicleap_plugin=false +magicleap_xr_features/hand_tracking=0 diff --git a/samples/meta-space-warp-sample/grass-texture.jpg b/samples/meta-space-warp-sample/grass-texture.jpg new file mode 100644 index 00000000..5c67d6e5 Binary files /dev/null and b/samples/meta-space-warp-sample/grass-texture.jpg differ diff --git a/samples/meta-space-warp-sample/grass-texture.jpg.import b/samples/meta-space-warp-sample/grass-texture.jpg.import new file mode 100644 index 00000000..a75d2e69 --- /dev/null +++ b/samples/meta-space-warp-sample/grass-texture.jpg.import @@ -0,0 +1,36 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bmei66qp1ec7m" +path.s3tc="res://.godot/imported/grass-texture.jpg-ce694d3fd90cc76a7e9aa814a3c28b67.s3tc.ctex" +path.etc2="res://.godot/imported/grass-texture.jpg-ce694d3fd90cc76a7e9aa814a3c28b67.etc2.ctex" +metadata={ +"imported_formats": ["s3tc_bptc", "etc2_astc"], +"vram_texture": true +} + +[deps] + +source_file="res://grass-texture.jpg" +dest_files=["res://.godot/imported/grass-texture.jpg-ce694d3fd90cc76a7e9aa814a3c28b67.s3tc.ctex", "res://.godot/imported/grass-texture.jpg-ce694d3fd90cc76a7e9aa814a3c28b67.etc2.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/samples/meta-space-warp-sample/icon.svg b/samples/meta-space-warp-sample/icon.svg new file mode 100644 index 00000000..b370ceb7 --- /dev/null +++ b/samples/meta-space-warp-sample/icon.svg @@ -0,0 +1 @@ + diff --git a/samples/meta-space-warp-sample/icon.svg.import b/samples/meta-space-warp-sample/icon.svg.import new file mode 100644 index 00000000..c7092d22 --- /dev/null +++ b/samples/meta-space-warp-sample/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cvlahew2pulnf" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/samples/meta-space-warp-sample/main.gd b/samples/meta-space-warp-sample/main.gd new file mode 100644 index 00000000..70a21378 --- /dev/null +++ b/samples/meta-space-warp-sample/main.gd @@ -0,0 +1,107 @@ +extends StartXR + +const SNAP_TURN_THRESHOLD := 0.8 +const SNAP_TURN_ANGLE := TAU / 16 +const SMOOTH_TURN_SPEED := 0.05 +const MOVE_SPEED := 2.0 + +var movement_input := Vector2.ZERO +var smooth_turn_input := 0.0 +var snap_turn_enabled := false +var countdown_to_check_space_warp_enabled: int = 3 + +@onready var xr_origin: XROrigin3D = $XROrigin3D +@onready var xr_camera: XRCamera3D = $XROrigin3D/XRCamera3D +@onready var left_hand: XRController3D = $XROrigin3D/LeftHand +@onready var right_hand: XRController3D = $XROrigin3D/RightHand +@onready var right_controller_label: Label3D = $XROrigin3D/RightHand/Label3D +@onready var turn_timer: Timer = $XROrigin3D/TurnTimer +@onready var gpu_particles_3d: GPUParticles3D = $GPUParticles3D +@onready var cpu_particles_3d: CPUParticles3D = $CPUParticles3D +@onready var gpu_particles_3d_2: GPUParticles3D = $GPUParticles3D2 +@onready var cpu_particles_3d_2: CPUParticles3D = $CPUParticles3D2 + +func _ready() -> void: + super._ready() + right_hand.connect("button_pressed", _on_right_hand_button_pressed) + right_hand.connect("input_vector2_changed", check_turn) + left_hand.connect("input_vector2_changed", _on_left_hand_input_vector_2_changed) + if "--xrsim-automated-tests" in OS.get_cmdline_user_args(): + # When we're running tests via the XR Simulator, we don't want these + # to be animated, which can lead to differences in the screenshots. + gpu_particles_3d.emitting = false + cpu_particles_3d.emitting = false + gpu_particles_3d_2.emitting = false + cpu_particles_3d_2.emitting = false + gpu_particles_3d.emitting = false + + +func _process(delta: float) -> void: + if countdown_to_check_space_warp_enabled > 0: + countdown_to_check_space_warp_enabled -= 1 + if countdown_to_check_space_warp_enabled == 0: + var fb_space_warp = Engine.get_singleton("OpenXRFbSpaceWarpExtensionWrapper") + if not fb_space_warp.is_enabled(): + right_controller_label.text = right_controller_label.text.replace("ENABLED", "DISABLED") + + +func _physics_process(delta: float) -> void: + if movement_input != Vector2.ZERO: + xr_origin.position.z += -movement_input.y * delta * MOVE_SPEED + xr_origin.position.x += movement_input.x * delta * MOVE_SPEED + if smooth_turn_input != 0.0: + rotate_player(smooth_turn_input * SMOOTH_TURN_SPEED) + + +func _on_right_hand_button_pressed(name: String) -> void: + if name == "ax_button": + var fb_space_warp = Engine.get_singleton("OpenXRFbSpaceWarpExtensionWrapper") + fb_space_warp.set_space_warp_enabled(!fb_space_warp.is_enabled()) + + if fb_space_warp.is_enabled(): + right_controller_label.text = right_controller_label.text.replace("DISABLED", "ENABLED") + else: + right_controller_label.text = right_controller_label.text.replace("ENABLED", "DISABLED") + elif name == "by_button": + if not snap_turn_enabled: + smooth_turn_input = 0.0 + snap_turn_enabled = !snap_turn_enabled + + if snap_turn_enabled: + right_controller_label.text = right_controller_label.text.replace("SMOOTH", "SNAP") + else: + right_controller_label.text = right_controller_label.text.replace("SNAP", "SMOOTH") + + +func check_turn(name: String, value: Vector2) -> void: + if snap_turn_enabled: + if not turn_timer.is_stopped(): + return + + if name == "primary": + if abs(value.x) > SNAP_TURN_THRESHOLD: + rotate_player(sign(value.x) * SNAP_TURN_ANGLE) + turn_timer.start() + var fb_space_warp = Engine.get_singleton("OpenXRFbSpaceWarpExtensionWrapper") + fb_space_warp.skip_space_warp_frame() + else: + smooth_turn_input = value.x + + +func rotate_player(angle: float): + var t1 := Transform3D() + var t2 := Transform3D() + var rot := Transform3D() + + t1.origin = -xr_camera.transform.origin + t2.origin = xr_camera.transform.origin + rot = rot.rotated(Vector3.DOWN, angle) + xr_origin.transform = (xr_origin.transform * t2 * rot * t1).orthonormalized() + + for composition_layer in get_tree().get_nodes_in_group("composition_layer"): + composition_layer.global_transform = get_node(NodePath(composition_layer.name)).global_transform + + +func _on_left_hand_input_vector_2_changed(name: String, value: Vector2) -> void: + if name == "primary": + movement_input = value diff --git a/samples/meta-space-warp-sample/main.gd.uid b/samples/meta-space-warp-sample/main.gd.uid new file mode 100644 index 00000000..0b1ee641 --- /dev/null +++ b/samples/meta-space-warp-sample/main.gd.uid @@ -0,0 +1 @@ +uid://cxxy74r3njgxw diff --git a/samples/meta-space-warp-sample/main.tscn b/samples/meta-space-warp-sample/main.tscn new file mode 100644 index 00000000..84929e72 --- /dev/null +++ b/samples/meta-space-warp-sample/main.tscn @@ -0,0 +1,237 @@ +[gd_scene load_steps=22 format=3 uid="uid://cqsodpswgup8w"] + +[ext_resource type="Script" uid="uid://cxxy74r3njgxw" path="res://main.gd" id="1_fsva1"] +[ext_resource type="Script" uid="uid://w3jfhbcsh0bl" path="res://multi_mesh_move.gd" id="3_h2yge"] +[ext_resource type="PackedScene" uid="uid://cfbmcnbws28t1" path="res://bone_cube.tscn" id="4_1bvp3"] +[ext_resource type="Script" uid="uid://bqdcpwjw3mtb3" path="res://moving_cube.gd" id="5_lquwl"] +[ext_resource type="Texture2D" uid="uid://bmei66qp1ec7m" path="res://grass-texture.jpg" id="6_7mycd"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0x6cv"] +sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) +ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) + +[sub_resource type="Sky" id="Sky_dqyx0"] +sky_material = SubResource("ProceduralSkyMaterial_0x6cv") + +[sub_resource type="Environment" id="Environment_m0xew"] +background_mode = 2 +background_color = Color(0, 0, 0, 0) +sky = SubResource("Sky_dqyx0") +ambient_light_source = 2 +ambient_light_color = Color(0.270588, 0.270588, 0.270588, 1) +tonemap_mode = 2 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_k604q"] + +[sub_resource type="PlaneMesh" id="PlaneMesh_mjcgt"] +material = SubResource("StandardMaterial3D_k604q") +size = Vector2(10, 10) + +[sub_resource type="BoxShape3D" id="BoxShape3D_lquwl"] +size = Vector3(9.99512, 0.0859375, 10.0342) + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_yvvw4"] +direction = Vector3(-1, 0, 0) +spread = 0.0 +initial_velocity_min = 3.0 +initial_velocity_max = 3.0 +gravity = Vector3(0, 0, 0) + +[sub_resource type="BoxMesh" id="BoxMesh_t5jnj"] + +[sub_resource type="BoxMesh" id="BoxMesh_0xm2m"] + +[sub_resource type="BoxMesh" id="BoxMesh_h2yge"] + +[sub_resource type="MultiMesh" id="MultiMesh_1bvp3"] +transform_format = 1 +instance_count = 1 +mesh = SubResource("BoxMesh_h2yge") +buffer = PackedFloat32Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_lquwl"] +direction = Vector3(0, 1, 0) +spread = 0.0 +initial_velocity_min = 3.0 +initial_velocity_max = 3.0 +gravity = Vector3(0, 0, 0) + +[sub_resource type="MultiMesh" id="MultiMesh_lquwl"] +transform_format = 1 +instance_count = 1 +mesh = SubResource("BoxMesh_h2yge") +buffer = PackedFloat32Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +[sub_resource type="BoxMesh" id="BoxMesh_7mycd"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_272bh"] +shading_mode = 0 +albedo_texture = ExtResource("6_7mycd") +uv1_scale = Vector3(0.35, 0.35, 0.35) +uv1_triplanar = true + +[sub_resource type="PlaneMesh" id="PlaneMesh_5vw27"] +material = SubResource("StandardMaterial3D_272bh") +size = Vector2(8, 6) + +[node name="Main" type="Node3D"] +script = ExtResource("1_fsva1") + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_m0xew") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.677077, -0.692092, 0.25015, 0.264251, 0.545897, 0.79509, -0.686831, -0.472235, 0.552501, 0, 0, 0) + +[node name="XROrigin3D" type="XROrigin3D" parent="."] + +[node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.352791, 0) + +[node name="LeftHand" type="XRController3D" parent="XROrigin3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.460909, 0.388594, -0.241118) +tracker = &"left_hand" +pose = &"grip" + +[node name="LeftControllerFbRenderModel" type="OpenXRFbRenderModel" parent="XROrigin3D/LeftHand"] + +[node name="Label3D" type="Label3D" parent="XROrigin3D/LeftHand"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, -0.124, -0.186) +pixel_size = 0.001 +text = "[Analog Stick] Move" + +[node name="RightHand" type="XRController3D" parent="XROrigin3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.478861, 0.468292, -0.241097) +tracker = &"right_hand" +pose = &"grip" + +[node name="RightControllerFbRenderModel" type="OpenXRFbRenderModel" parent="XROrigin3D/RightHand"] +render_model_type = 1 + +[node name="Label3D" type="Label3D" parent="XROrigin3D/RightHand"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, -0.124, -0.186) +pixel_size = 0.001 +text = "Turn Mode: SMOOTH +Space Warp: ENABLED + +[B] Toggle Turn Mode +[A] Enable/Disable Space Warp +[Analog Stick] Turn" + +[node name="TurnTimer" type="Timer" parent="XROrigin3D"] +wait_time = 0.2 +one_shot = true + +[node name="Floor" type="MeshInstance3D" parent="."] +mesh = SubResource("PlaneMesh_mjcgt") + +[node name="FloorCollider" type="Area3D" parent="Floor"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor/FloorCollider"] +shape = SubResource("BoxShape3D_lquwl") + +[node name="GPUParticles3D" type="GPUParticles3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.08746, 1, -4) +amount = 2 +process_material = SubResource("ParticleProcessMaterial_yvvw4") +draw_pass_1 = SubResource("BoxMesh_t5jnj") + +[node name="Label3D" type="Label3D" parent="GPUParticles3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.08746, 0, 0) +text = "GPU +Particles" + +[node name="CPUParticles3D" type="CPUParticles3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 2.21267, -4) +amount = 2 +mesh = SubResource("BoxMesh_0xm2m") +spread = 0.0 +gravity = Vector3(0, 0, 0) +initial_velocity_min = 3.0 +initial_velocity_max = 3.0 + +[node name="Label3D" type="Label3D" parent="CPUParticles3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 0, 0) +text = "CPU +Particles" + +[node name="MultiMeshInstance3D" type="MultiMeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.40488, -4) +multimesh = SubResource("MultiMesh_1bvp3") +script = ExtResource("3_h2yge") + +[node name="Label3D" type="Label3D" parent="MultiMeshInstance3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0, 0) +text = "MultiMesh" + +[node name="GPUParticles3D2" type="GPUParticles3D" parent="."] +transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 4, 2, -2.99679) +amount = 2 +process_material = SubResource("ParticleProcessMaterial_lquwl") +draw_pass_1 = SubResource("BoxMesh_t5jnj") + +[node name="Label3D" type="Label3D" parent="GPUParticles3D2"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.96046e-08, -1, 0) +text = "GPU +Particles" + +[node name="CPUParticles3D2" type="CPUParticles3D" parent="."] +transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 4, 5.15442, -1.19841) +amount = 2 +mesh = SubResource("BoxMesh_0xm2m") +direction = Vector3(0, -1, 0) +spread = 0.0 +gravity = Vector3(0, 0, 0) +initial_velocity_min = 3.0 +initial_velocity_max = 3.0 + +[node name="Label3D" type="Label3D" parent="CPUParticles3D2"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -4.1477, 0) +text = "CPU +Particles" + +[node name="MultiMeshInstance3D2" type="MultiMeshInstance3D" parent="."] +transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 4, 2.9845, 0.891652) +multimesh = SubResource("MultiMesh_lquwl") +script = ExtResource("3_h2yge") +direction = Vector3(0, 1, 0) + +[node name="Label3D" type="Label3D" parent="MultiMeshInstance3D2"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, 0) +text = "MultiMesh" + +[node name="BoneCube" parent="." instance=ExtResource("4_1bvp3")] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -4, 1, -1) + +[node name="Label3D" type="Label3D" parent="BoneCube"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.52612, 0, 0) +text = "Skeleton" + +[node name="MovingCube" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 3.399, -1) + +[node name="MovingCube" type="MeshInstance3D" parent="MovingCube"] +mesh = SubResource("BoxMesh_7mycd") +skeleton = NodePath("../..") +script = ExtResource("5_lquwl") + +[node name="Label3D" type="Label3D" parent="MovingCube"] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0.000349998, 2) +text = "Mesh" + +[node name="GrassTextures" type="Node3D" parent="."] + +[node name="GrassTexture" type="MeshInstance3D" parent="GrassTextures"] +transform = Transform3D(-4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0, 1, -5, 2, -1) +mesh = SubResource("PlaneMesh_5vw27") +skeleton = NodePath("../..") + +[node name="GrassTexture2" type="MeshInstance3D" parent="GrassTextures"] +transform = Transform3D(1.91069e-15, -4.37114e-08, -1, -1, -4.37114e-08, 0, -4.37114e-08, 1, -4.37114e-08, 0, 2, -5) +mesh = SubResource("PlaneMesh_5vw27") +skeleton = NodePath("../..") + +[node name="GrassTexture3" type="MeshInstance3D" parent="GrassTextures"] +transform = Transform3D(4.37114e-08, -1, 8.74228e-08, -1, -4.37114e-08, 0, 3.82138e-15, -8.74228e-08, -1, 5, 2, -0.996788) +mesh = SubResource("PlaneMesh_5vw27") +skeleton = NodePath("../..") diff --git a/samples/meta-space-warp-sample/moving_cube.gd b/samples/meta-space-warp-sample/moving_cube.gd new file mode 100644 index 00000000..c2257d0b --- /dev/null +++ b/samples/meta-space-warp-sample/moving_cube.gd @@ -0,0 +1,8 @@ +extends MeshInstance3D + +func _process(delta: float) -> void: + if not "--xrsim-automated-tests" in OS.get_cmdline_user_args(): + # When we're running tests via the XR Simulator, we don't want this + # to be animated, which can lead to differences in the screenshots. + position.z = sin(Time.get_ticks_msec() / 300.0) + position.y = cos(Time.get_ticks_msec() / 300.0) diff --git a/samples/meta-space-warp-sample/moving_cube.gd.uid b/samples/meta-space-warp-sample/moving_cube.gd.uid new file mode 100644 index 00000000..77dbfee9 --- /dev/null +++ b/samples/meta-space-warp-sample/moving_cube.gd.uid @@ -0,0 +1 @@ +uid://bqdcpwjw3mtb3 diff --git a/samples/meta-space-warp-sample/multi_mesh_move.gd b/samples/meta-space-warp-sample/multi_mesh_move.gd new file mode 100644 index 00000000..cab19cbd --- /dev/null +++ b/samples/meta-space-warp-sample/multi_mesh_move.gd @@ -0,0 +1,13 @@ +extends MultiMeshInstance3D + +@export var direction: Vector3 = Vector3(1, 0, 0) + +func _process(delta: float) -> void: + if not "--xrsim-automated-tests" in OS.get_cmdline_user_args(): + # When we're running tests via the XR Simulator, we don't want this + # to be animated, which can lead to differences in the screenshots. + var displacement = sin(Time.get_ticks_msec() / 300.0) + var origin := Vector3(displacement, displacement, displacement) + origin = origin * direction + var new_transform := Transform3D(basis, origin) + multimesh.set_instance_transform(0, new_transform) diff --git a/samples/meta-space-warp-sample/multi_mesh_move.gd.uid b/samples/meta-space-warp-sample/multi_mesh_move.gd.uid new file mode 100644 index 00000000..e256bff0 --- /dev/null +++ b/samples/meta-space-warp-sample/multi_mesh_move.gd.uid @@ -0,0 +1 @@ +uid://w3jfhbcsh0bl diff --git a/samples/meta-space-warp-sample/openxr_action_map.tres b/samples/meta-space-warp-sample/openxr_action_map.tres new file mode 100644 index 00000000..46810f68 --- /dev/null +++ b/samples/meta-space-warp-sample/openxr_action_map.tres @@ -0,0 +1,1547 @@ +[gd_resource type="OpenXRActionMap" load_steps=375 format=3 uid="uid://b1wdu77pwks8y"] + +[sub_resource type="OpenXRAction" id="OpenXRAction_6v1ja"] +resource_name = "trigger" +localized_name = "Trigger" +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_iw5kk"] +resource_name = "trigger_click" +localized_name = "Trigger click" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_8vn7r"] +resource_name = "trigger_touch" +localized_name = "Trigger touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_57lfg"] +resource_name = "grip" +localized_name = "Grip" +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_my2cy"] +resource_name = "grip_click" +localized_name = "Grip click" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_s0au3"] +resource_name = "grip_touch" +localized_name = "Grip touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_h857g"] +resource_name = "grip_force" +localized_name = "Grip force" +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_jhwoi"] +resource_name = "primary" +localized_name = "Primary joystick/thumbstick/trackpad" +action_type = 2 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_ujxhj"] +resource_name = "primary_click" +localized_name = "Primary joystick/thumbstick/trackpad click" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_2sp3t"] +resource_name = "primary_touch" +localized_name = "Primary joystick/thumbstick/trackpad touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_sfrr4"] +resource_name = "secondary" +localized_name = "Secondary joystick/thumbstick/trackpad" +action_type = 2 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_nagay"] +resource_name = "secondary_click" +localized_name = "Secondary joystick/thumbstick/trackpad click" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_6xco2"] +resource_name = "secondary_touch" +localized_name = "Secondary joystick/thumbstick/trackpad touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_stco1"] +resource_name = "menu_button" +localized_name = "Menu button" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_oxyin"] +resource_name = "select_button" +localized_name = "Select button" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_vcq1d"] +resource_name = "ax_button" +localized_name = "A/X button" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_3fgr7"] +resource_name = "ax_touch" +localized_name = "A/X touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_vo38g"] +resource_name = "by_button" +localized_name = "B/Y button" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_qcwp8"] +resource_name = "by_touch" +localized_name = "B/Y touching" +action_type = 0 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_vk7pf"] +resource_name = "default_pose" +localized_name = "Default pose" +action_type = 3 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/keyboard", "/user/eyes_ext") + +[sub_resource type="OpenXRAction" id="OpenXRAction_1vol5"] +resource_name = "aim_pose" +localized_name = "Aim pose" +action_type = 3 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_18qyl"] +resource_name = "grip_pose" +localized_name = "Grip pose" +action_type = 3 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_1pnpo"] +resource_name = "palm_pose" +localized_name = "Palm pose" +action_type = 3 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right") + +[sub_resource type="OpenXRAction" id="OpenXRAction_0kk6l"] +resource_name = "haptic" +localized_name = "Haptic" +action_type = 4 +toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/keyboard") + +[sub_resource type="OpenXRActionSet" id="OpenXRActionSet_kd2ms"] +resource_name = "godot" +localized_name = "Godot action set" +actions = [SubResource("OpenXRAction_6v1ja"), SubResource("OpenXRAction_iw5kk"), SubResource("OpenXRAction_8vn7r"), SubResource("OpenXRAction_57lfg"), SubResource("OpenXRAction_my2cy"), SubResource("OpenXRAction_s0au3"), SubResource("OpenXRAction_h857g"), SubResource("OpenXRAction_jhwoi"), SubResource("OpenXRAction_ujxhj"), SubResource("OpenXRAction_2sp3t"), SubResource("OpenXRAction_sfrr4"), SubResource("OpenXRAction_nagay"), SubResource("OpenXRAction_6xco2"), SubResource("OpenXRAction_stco1"), SubResource("OpenXRAction_oxyin"), SubResource("OpenXRAction_vcq1d"), SubResource("OpenXRAction_3fgr7"), SubResource("OpenXRAction_vo38g"), SubResource("OpenXRAction_qcwp8"), SubResource("OpenXRAction_vk7pf"), SubResource("OpenXRAction_1vol5"), SubResource("OpenXRAction_18qyl"), SubResource("OpenXRAction_1pnpo"), SubResource("OpenXRAction_0kk6l")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6ivru"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vfhwq"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5w03k"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_typ1r"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_clvbf"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5bppb"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3k6la"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_i8esw"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_um1hv"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_oqnsu"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/right/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_r5bl7"] +action = SubResource("OpenXRAction_oxyin") +binding_path = "/user/hand/left/input/select/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ytptc"] +action = SubResource("OpenXRAction_oxyin") +binding_path = "/user/hand/right/input/select/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_iphn4"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3p2as"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_kitsa"] +interaction_profile_path = "/interaction_profiles/khr/simple_controller" +bindings = [SubResource("OpenXRIPBinding_6ivru"), SubResource("OpenXRIPBinding_vfhwq"), SubResource("OpenXRIPBinding_5w03k"), SubResource("OpenXRIPBinding_typ1r"), SubResource("OpenXRIPBinding_clvbf"), SubResource("OpenXRIPBinding_5bppb"), SubResource("OpenXRIPBinding_3k6la"), SubResource("OpenXRIPBinding_i8esw"), SubResource("OpenXRIPBinding_um1hv"), SubResource("OpenXRIPBinding_oqnsu"), SubResource("OpenXRIPBinding_r5bl7"), SubResource("OpenXRIPBinding_ytptc"), SubResource("OpenXRIPBinding_iphn4"), SubResource("OpenXRIPBinding_3p2as")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wdehm"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_clfly"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_e1frq"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l7aq8"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_oi0ij"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_m08eo"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c4j1d"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sopde"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sow2k"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ngwcy"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/right/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_r3qn1"] +action = SubResource("OpenXRAction_oxyin") +binding_path = "/user/hand/left/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n01b8"] +action = SubResource("OpenXRAction_oxyin") +binding_path = "/user/hand/right/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pjtev"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nqyri"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_86uui"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nrtxc"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qovyo"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d6uso"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hvi7v"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7dxun"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rp8ih"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/trackpad" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0uca0"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/trackpad" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rjtq8"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/trackpad/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lce2q"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/trackpad/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ckeh6"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/left/input/trackpad/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_538mi"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/right/input/trackpad/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_548p5"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6o0wr"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_uoohe"] +interaction_profile_path = "/interaction_profiles/htc/vive_controller" +bindings = [SubResource("OpenXRIPBinding_wdehm"), SubResource("OpenXRIPBinding_clfly"), SubResource("OpenXRIPBinding_e1frq"), SubResource("OpenXRIPBinding_l7aq8"), SubResource("OpenXRIPBinding_oi0ij"), SubResource("OpenXRIPBinding_m08eo"), SubResource("OpenXRIPBinding_c4j1d"), SubResource("OpenXRIPBinding_sopde"), SubResource("OpenXRIPBinding_sow2k"), SubResource("OpenXRIPBinding_ngwcy"), SubResource("OpenXRIPBinding_r3qn1"), SubResource("OpenXRIPBinding_n01b8"), SubResource("OpenXRIPBinding_pjtev"), SubResource("OpenXRIPBinding_nqyri"), SubResource("OpenXRIPBinding_86uui"), SubResource("OpenXRIPBinding_nrtxc"), SubResource("OpenXRIPBinding_qovyo"), SubResource("OpenXRIPBinding_d6uso"), SubResource("OpenXRIPBinding_hvi7v"), SubResource("OpenXRIPBinding_7dxun"), SubResource("OpenXRIPBinding_rp8ih"), SubResource("OpenXRIPBinding_0uca0"), SubResource("OpenXRIPBinding_rjtq8"), SubResource("OpenXRIPBinding_lce2q"), SubResource("OpenXRIPBinding_ckeh6"), SubResource("OpenXRIPBinding_538mi"), SubResource("OpenXRIPBinding_548p5"), SubResource("OpenXRIPBinding_6o0wr")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fsghu"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_88umk"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4uneg"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_67o31"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lf1a1"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_x1adc"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_j1vtv"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tud50"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_akdt0"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xri1r"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/right/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_etqcv"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_og5pg"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nwe40"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ts2ff"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yhsv0"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sf2dt"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_67dwi"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hswdx"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7gr0f"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_uvspk"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ica2g"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5fecu"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0nfxl"] +action = SubResource("OpenXRAction_sfrr4") +binding_path = "/user/hand/left/input/trackpad" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sbe0d"] +action = SubResource("OpenXRAction_sfrr4") +binding_path = "/user/hand/right/input/trackpad" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rf1ko"] +action = SubResource("OpenXRAction_nagay") +binding_path = "/user/hand/left/input/trackpad/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jx7ge"] +action = SubResource("OpenXRAction_nagay") +binding_path = "/user/hand/right/input/trackpad/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d2w1t"] +action = SubResource("OpenXRAction_6xco2") +binding_path = "/user/hand/left/input/trackpad/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v2kct"] +action = SubResource("OpenXRAction_6xco2") +binding_path = "/user/hand/right/input/trackpad/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_37uq4"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kooyb"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_k2llo"] +interaction_profile_path = "/interaction_profiles/microsoft/motion_controller" +bindings = [SubResource("OpenXRIPBinding_fsghu"), SubResource("OpenXRIPBinding_88umk"), SubResource("OpenXRIPBinding_4uneg"), SubResource("OpenXRIPBinding_67o31"), SubResource("OpenXRIPBinding_lf1a1"), SubResource("OpenXRIPBinding_x1adc"), SubResource("OpenXRIPBinding_j1vtv"), SubResource("OpenXRIPBinding_tud50"), SubResource("OpenXRIPBinding_akdt0"), SubResource("OpenXRIPBinding_xri1r"), SubResource("OpenXRIPBinding_etqcv"), SubResource("OpenXRIPBinding_og5pg"), SubResource("OpenXRIPBinding_nwe40"), SubResource("OpenXRIPBinding_ts2ff"), SubResource("OpenXRIPBinding_yhsv0"), SubResource("OpenXRIPBinding_sf2dt"), SubResource("OpenXRIPBinding_67dwi"), SubResource("OpenXRIPBinding_hswdx"), SubResource("OpenXRIPBinding_7gr0f"), SubResource("OpenXRIPBinding_uvspk"), SubResource("OpenXRIPBinding_ica2g"), SubResource("OpenXRIPBinding_5fecu"), SubResource("OpenXRIPBinding_0nfxl"), SubResource("OpenXRIPBinding_sbe0d"), SubResource("OpenXRIPBinding_rf1ko"), SubResource("OpenXRIPBinding_jx7ge"), SubResource("OpenXRIPBinding_d2w1t"), SubResource("OpenXRIPBinding_v2kct"), SubResource("OpenXRIPBinding_37uq4"), SubResource("OpenXRIPBinding_kooyb")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_51qre"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fncxp"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qi50k"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_h5icu"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_b1sv6"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yu2t6"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_labib"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_altuc"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7p0fp"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yjnix"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/right/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pgh0x"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/left/input/x/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lplyu"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/right/input/a/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ifnya"] +action = SubResource("OpenXRAction_3fgr7") +binding_path = "/user/hand/left/input/x/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jl4vo"] +action = SubResource("OpenXRAction_3fgr7") +binding_path = "/user/hand/right/input/a/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1n6j6"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/left/input/y/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_o1nfs"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/right/input/b/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_unnrh"] +action = SubResource("OpenXRAction_qcwp8") +binding_path = "/user/hand/left/input/y/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3wafl"] +action = SubResource("OpenXRAction_qcwp8") +binding_path = "/user/hand/right/input/b/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tjb53"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lcg2b"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sp6l2"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xj6ir"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_igmf3"] +action = SubResource("OpenXRAction_8vn7r") +binding_path = "/user/hand/left/input/trigger/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_inw5v"] +action = SubResource("OpenXRAction_8vn7r") +binding_path = "/user/hand/right/input/trigger/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_iy2wq"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_plu03"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dad45"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_m5e8q"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5t7jh"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_chplt"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_obxrh"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_on7oi"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ege4h"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/left/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_h7ix0"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/right/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8qanm"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3senm"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_2masb"] +interaction_profile_path = "/interaction_profiles/oculus/touch_controller" +bindings = [SubResource("OpenXRIPBinding_51qre"), SubResource("OpenXRIPBinding_fncxp"), SubResource("OpenXRIPBinding_qi50k"), SubResource("OpenXRIPBinding_h5icu"), SubResource("OpenXRIPBinding_b1sv6"), SubResource("OpenXRIPBinding_yu2t6"), SubResource("OpenXRIPBinding_labib"), SubResource("OpenXRIPBinding_altuc"), SubResource("OpenXRIPBinding_7p0fp"), SubResource("OpenXRIPBinding_yjnix"), SubResource("OpenXRIPBinding_pgh0x"), SubResource("OpenXRIPBinding_lplyu"), SubResource("OpenXRIPBinding_ifnya"), SubResource("OpenXRIPBinding_jl4vo"), SubResource("OpenXRIPBinding_1n6j6"), SubResource("OpenXRIPBinding_o1nfs"), SubResource("OpenXRIPBinding_unnrh"), SubResource("OpenXRIPBinding_3wafl"), SubResource("OpenXRIPBinding_tjb53"), SubResource("OpenXRIPBinding_lcg2b"), SubResource("OpenXRIPBinding_sp6l2"), SubResource("OpenXRIPBinding_xj6ir"), SubResource("OpenXRIPBinding_igmf3"), SubResource("OpenXRIPBinding_inw5v"), SubResource("OpenXRIPBinding_iy2wq"), SubResource("OpenXRIPBinding_plu03"), SubResource("OpenXRIPBinding_dad45"), SubResource("OpenXRIPBinding_m5e8q"), SubResource("OpenXRIPBinding_5t7jh"), SubResource("OpenXRIPBinding_chplt"), SubResource("OpenXRIPBinding_obxrh"), SubResource("OpenXRIPBinding_on7oi"), SubResource("OpenXRIPBinding_ege4h"), SubResource("OpenXRIPBinding_h7ix0"), SubResource("OpenXRIPBinding_8qanm"), SubResource("OpenXRIPBinding_3senm")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7ca55"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ih1l2"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ipewn"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5ngl7"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_klygg"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4p63k"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6vi2m"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_888d1"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_246v5"] +action = SubResource("OpenXRAction_oxyin") +binding_path = "/user/hand/left/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xj73r"] +action = SubResource("OpenXRAction_oxyin") +binding_path = "/user/hand/right/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sugej"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/back/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fp7u7"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/right/input/back/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gvgeq"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/left/input/x/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_i0s8c"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/right/input/a/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ynetq"] +action = SubResource("OpenXRAction_3fgr7") +binding_path = "/user/hand/left/input/x/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_p8bcx"] +action = SubResource("OpenXRAction_3fgr7") +binding_path = "/user/hand/right/input/a/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jkemj"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/left/input/y/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d3nfp"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/right/input/b/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jyu76"] +action = SubResource("OpenXRAction_qcwp8") +binding_path = "/user/hand/left/input/y/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_aecy5"] +action = SubResource("OpenXRAction_qcwp8") +binding_path = "/user/hand/right/input/b/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8vb80"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_myee0"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1vv3a"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_tjysa"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_r4yxn"] +action = SubResource("OpenXRAction_8vn7r") +binding_path = "/user/hand/left/input/trigger/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_me87v"] +action = SubResource("OpenXRAction_8vn7r") +binding_path = "/user/hand/right/input/trigger/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d8myu"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hsh5n"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lng5j"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_aeeoj"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gosqu"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n52fm"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vushy"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lbhgg"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_m1cgb"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/left/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yfktj"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/right/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kjhen"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_32kw4"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_ert82"] +interaction_profile_path = "/interaction_profiles/bytedance/pico_neo3_controller" +bindings = [SubResource("OpenXRIPBinding_7ca55"), SubResource("OpenXRIPBinding_ih1l2"), SubResource("OpenXRIPBinding_ipewn"), SubResource("OpenXRIPBinding_5ngl7"), SubResource("OpenXRIPBinding_klygg"), SubResource("OpenXRIPBinding_4p63k"), SubResource("OpenXRIPBinding_6vi2m"), SubResource("OpenXRIPBinding_888d1"), SubResource("OpenXRIPBinding_246v5"), SubResource("OpenXRIPBinding_xj73r"), SubResource("OpenXRIPBinding_sugej"), SubResource("OpenXRIPBinding_fp7u7"), SubResource("OpenXRIPBinding_gvgeq"), SubResource("OpenXRIPBinding_i0s8c"), SubResource("OpenXRIPBinding_ynetq"), SubResource("OpenXRIPBinding_p8bcx"), SubResource("OpenXRIPBinding_jkemj"), SubResource("OpenXRIPBinding_d3nfp"), SubResource("OpenXRIPBinding_jyu76"), SubResource("OpenXRIPBinding_aecy5"), SubResource("OpenXRIPBinding_8vb80"), SubResource("OpenXRIPBinding_myee0"), SubResource("OpenXRIPBinding_1vv3a"), SubResource("OpenXRIPBinding_tjysa"), SubResource("OpenXRIPBinding_r4yxn"), SubResource("OpenXRIPBinding_me87v"), SubResource("OpenXRIPBinding_d8myu"), SubResource("OpenXRIPBinding_hsh5n"), SubResource("OpenXRIPBinding_lng5j"), SubResource("OpenXRIPBinding_aeeoj"), SubResource("OpenXRIPBinding_gosqu"), SubResource("OpenXRIPBinding_n52fm"), SubResource("OpenXRIPBinding_vushy"), SubResource("OpenXRIPBinding_lbhgg"), SubResource("OpenXRIPBinding_m1cgb"), SubResource("OpenXRIPBinding_yfktj"), SubResource("OpenXRIPBinding_kjhen"), SubResource("OpenXRIPBinding_32kw4")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ktbxl"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8ldfe"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nueak"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vopyr"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rgbyv"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bflds"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pueci"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jn5l0"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_44ra8"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bh82f"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/right/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7b312"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/left/input/a/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ajt26"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/right/input/a/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_grl1h"] +action = SubResource("OpenXRAction_3fgr7") +binding_path = "/user/hand/left/input/a/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dlpx3"] +action = SubResource("OpenXRAction_3fgr7") +binding_path = "/user/hand/right/input/a/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_s4h6a"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/left/input/b/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0njdn"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/right/input/b/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xtpgr"] +action = SubResource("OpenXRAction_qcwp8") +binding_path = "/user/hand/left/input/b/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sm8ja"] +action = SubResource("OpenXRAction_qcwp8") +binding_path = "/user/hand/right/input/b/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fyyqw"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6yfaw"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_x7rhh"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8cuio"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v0kom"] +action = SubResource("OpenXRAction_8vn7r") +binding_path = "/user/hand/left/input/trigger/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v1men"] +action = SubResource("OpenXRAction_8vn7r") +binding_path = "/user/hand/right/input/trigger/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qujgh"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8xxre"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jceb4"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lvl5r"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2juyq"] +action = SubResource("OpenXRAction_h857g") +binding_path = "/user/hand/left/input/squeeze/force" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c1fap"] +action = SubResource("OpenXRAction_h857g") +binding_path = "/user/hand/right/input/squeeze/force" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_34k6i"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_biq8g"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7rnxc"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_go0kb"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_psf6i"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/left/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_q7kgi"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/right/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ggehc"] +action = SubResource("OpenXRAction_sfrr4") +binding_path = "/user/hand/left/input/trackpad" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8isuk"] +action = SubResource("OpenXRAction_sfrr4") +binding_path = "/user/hand/right/input/trackpad" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l36rf"] +action = SubResource("OpenXRAction_nagay") +binding_path = "/user/hand/left/input/trackpad/force" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7xtpc"] +action = SubResource("OpenXRAction_nagay") +binding_path = "/user/hand/right/input/trackpad/force" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lxj72"] +action = SubResource("OpenXRAction_6xco2") +binding_path = "/user/hand/left/input/trackpad/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ipsea"] +action = SubResource("OpenXRAction_6xco2") +binding_path = "/user/hand/right/input/trackpad/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n5ic7"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yb78u"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_aq5p3"] +interaction_profile_path = "/interaction_profiles/valve/index_controller" +bindings = [SubResource("OpenXRIPBinding_ktbxl"), SubResource("OpenXRIPBinding_8ldfe"), SubResource("OpenXRIPBinding_nueak"), SubResource("OpenXRIPBinding_vopyr"), SubResource("OpenXRIPBinding_rgbyv"), SubResource("OpenXRIPBinding_bflds"), SubResource("OpenXRIPBinding_pueci"), SubResource("OpenXRIPBinding_jn5l0"), SubResource("OpenXRIPBinding_44ra8"), SubResource("OpenXRIPBinding_bh82f"), SubResource("OpenXRIPBinding_7b312"), SubResource("OpenXRIPBinding_ajt26"), SubResource("OpenXRIPBinding_grl1h"), SubResource("OpenXRIPBinding_dlpx3"), SubResource("OpenXRIPBinding_s4h6a"), SubResource("OpenXRIPBinding_0njdn"), SubResource("OpenXRIPBinding_xtpgr"), SubResource("OpenXRIPBinding_sm8ja"), SubResource("OpenXRIPBinding_fyyqw"), SubResource("OpenXRIPBinding_6yfaw"), SubResource("OpenXRIPBinding_x7rhh"), SubResource("OpenXRIPBinding_8cuio"), SubResource("OpenXRIPBinding_v0kom"), SubResource("OpenXRIPBinding_v1men"), SubResource("OpenXRIPBinding_qujgh"), SubResource("OpenXRIPBinding_8xxre"), SubResource("OpenXRIPBinding_jceb4"), SubResource("OpenXRIPBinding_lvl5r"), SubResource("OpenXRIPBinding_2juyq"), SubResource("OpenXRIPBinding_c1fap"), SubResource("OpenXRIPBinding_34k6i"), SubResource("OpenXRIPBinding_biq8g"), SubResource("OpenXRIPBinding_7rnxc"), SubResource("OpenXRIPBinding_go0kb"), SubResource("OpenXRIPBinding_psf6i"), SubResource("OpenXRIPBinding_q7kgi"), SubResource("OpenXRIPBinding_ggehc"), SubResource("OpenXRIPBinding_8isuk"), SubResource("OpenXRIPBinding_l36rf"), SubResource("OpenXRIPBinding_7xtpc"), SubResource("OpenXRIPBinding_lxj72"), SubResource("OpenXRIPBinding_ipsea"), SubResource("OpenXRIPBinding_n5ic7"), SubResource("OpenXRIPBinding_yb78u")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_u1xt5"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_e0b0t"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_e56i2"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_o3gnr"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_x0dby"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_oysla"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jfg4b"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dkohk"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4j1at"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0c4l6"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/right/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dj07b"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/left/input/x/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_p2sos"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/right/input/a/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sjamf"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/left/input/y/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_if5c0"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/right/input/b/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_57aju"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2nhts"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7wbbb"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xagmn"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_x3bni"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ix831"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_shvqi"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mqshq"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bugar"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1tmte"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ve8wc"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_txme2"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nudtj"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2a6v2"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_4petf"] +interaction_profile_path = "/interaction_profiles/hp/mixed_reality_controller" +bindings = [SubResource("OpenXRIPBinding_u1xt5"), SubResource("OpenXRIPBinding_e0b0t"), SubResource("OpenXRIPBinding_e56i2"), SubResource("OpenXRIPBinding_o3gnr"), SubResource("OpenXRIPBinding_x0dby"), SubResource("OpenXRIPBinding_oysla"), SubResource("OpenXRIPBinding_jfg4b"), SubResource("OpenXRIPBinding_dkohk"), SubResource("OpenXRIPBinding_4j1at"), SubResource("OpenXRIPBinding_0c4l6"), SubResource("OpenXRIPBinding_dj07b"), SubResource("OpenXRIPBinding_p2sos"), SubResource("OpenXRIPBinding_sjamf"), SubResource("OpenXRIPBinding_if5c0"), SubResource("OpenXRIPBinding_57aju"), SubResource("OpenXRIPBinding_2nhts"), SubResource("OpenXRIPBinding_7wbbb"), SubResource("OpenXRIPBinding_xagmn"), SubResource("OpenXRIPBinding_x3bni"), SubResource("OpenXRIPBinding_ix831"), SubResource("OpenXRIPBinding_shvqi"), SubResource("OpenXRIPBinding_mqshq"), SubResource("OpenXRIPBinding_bugar"), SubResource("OpenXRIPBinding_1tmte"), SubResource("OpenXRIPBinding_ve8wc"), SubResource("OpenXRIPBinding_txme2"), SubResource("OpenXRIPBinding_nudtj"), SubResource("OpenXRIPBinding_2a6v2")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jhul1"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hpd1k"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7djuc"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rlsjo"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ad82e"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_053t8"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3y48y"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_eqmbe"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lml5w"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bw6yn"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/right/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rmtug"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_got3w"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cfhcx"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wuspj"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_j7v05"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_a0qeh"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hop5q"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wi6q4"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0x121"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pxanv"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ylsgs"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lyc6f"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t1gg6"] +action = SubResource("OpenXRAction_sfrr4") +binding_path = "/user/hand/left/input/trackpad" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_u2vet"] +action = SubResource("OpenXRAction_sfrr4") +binding_path = "/user/hand/right/input/trackpad" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gh4ss"] +action = SubResource("OpenXRAction_nagay") +binding_path = "/user/hand/left/input/trackpad/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1olwi"] +action = SubResource("OpenXRAction_nagay") +binding_path = "/user/hand/right/input/trackpad/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_t23ty"] +action = SubResource("OpenXRAction_6xco2") +binding_path = "/user/hand/left/input/trackpad/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_eusi4"] +action = SubResource("OpenXRAction_6xco2") +binding_path = "/user/hand/right/input/trackpad/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_etsgv"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_dnwvb"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_sd46l"] +interaction_profile_path = "/interaction_profiles/samsung/odyssey_controller" +bindings = [SubResource("OpenXRIPBinding_jhul1"), SubResource("OpenXRIPBinding_hpd1k"), SubResource("OpenXRIPBinding_7djuc"), SubResource("OpenXRIPBinding_rlsjo"), SubResource("OpenXRIPBinding_ad82e"), SubResource("OpenXRIPBinding_053t8"), SubResource("OpenXRIPBinding_3y48y"), SubResource("OpenXRIPBinding_eqmbe"), SubResource("OpenXRIPBinding_lml5w"), SubResource("OpenXRIPBinding_bw6yn"), SubResource("OpenXRIPBinding_rmtug"), SubResource("OpenXRIPBinding_got3w"), SubResource("OpenXRIPBinding_cfhcx"), SubResource("OpenXRIPBinding_wuspj"), SubResource("OpenXRIPBinding_j7v05"), SubResource("OpenXRIPBinding_a0qeh"), SubResource("OpenXRIPBinding_hop5q"), SubResource("OpenXRIPBinding_wi6q4"), SubResource("OpenXRIPBinding_0x121"), SubResource("OpenXRIPBinding_pxanv"), SubResource("OpenXRIPBinding_ylsgs"), SubResource("OpenXRIPBinding_lyc6f"), SubResource("OpenXRIPBinding_t1gg6"), SubResource("OpenXRIPBinding_u2vet"), SubResource("OpenXRIPBinding_gh4ss"), SubResource("OpenXRIPBinding_1olwi"), SubResource("OpenXRIPBinding_t23ty"), SubResource("OpenXRIPBinding_eusi4"), SubResource("OpenXRIPBinding_etsgv"), SubResource("OpenXRIPBinding_dnwvb")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_g2w4v"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_icb4r"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xeo6w"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_76fhr"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ddmi7"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hasjr"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fcs2k"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_eh655"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_s3ybd"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nkt0h"] +action = SubResource("OpenXRAction_oxyin") +binding_path = "/user/hand/right/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_a7x12"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/left/input/x/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cimi4"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/right/input/a/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d63gl"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/left/input/y/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_uthup"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/right/input/b/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_204g3"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4n1wc"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7hjyr"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_60nb8"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_klm8s"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_r7qos"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ox4ja"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bnyx8"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0mq2u"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_mi28r"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_h1y2o"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cag8c"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_17tdw"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/left/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pm24r"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/right/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3wkk3"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lkcwa"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_prh4s"] +interaction_profile_path = "/interaction_profiles/htc/vive_cosmos_controller" +bindings = [SubResource("OpenXRIPBinding_g2w4v"), SubResource("OpenXRIPBinding_icb4r"), SubResource("OpenXRIPBinding_xeo6w"), SubResource("OpenXRIPBinding_76fhr"), SubResource("OpenXRIPBinding_ddmi7"), SubResource("OpenXRIPBinding_hasjr"), SubResource("OpenXRIPBinding_fcs2k"), SubResource("OpenXRIPBinding_eh655"), SubResource("OpenXRIPBinding_s3ybd"), SubResource("OpenXRIPBinding_nkt0h"), SubResource("OpenXRIPBinding_a7x12"), SubResource("OpenXRIPBinding_cimi4"), SubResource("OpenXRIPBinding_d63gl"), SubResource("OpenXRIPBinding_uthup"), SubResource("OpenXRIPBinding_204g3"), SubResource("OpenXRIPBinding_4n1wc"), SubResource("OpenXRIPBinding_7hjyr"), SubResource("OpenXRIPBinding_60nb8"), SubResource("OpenXRIPBinding_klm8s"), SubResource("OpenXRIPBinding_r7qos"), SubResource("OpenXRIPBinding_ox4ja"), SubResource("OpenXRIPBinding_bnyx8"), SubResource("OpenXRIPBinding_0mq2u"), SubResource("OpenXRIPBinding_mi28r"), SubResource("OpenXRIPBinding_h1y2o"), SubResource("OpenXRIPBinding_cag8c"), SubResource("OpenXRIPBinding_17tdw"), SubResource("OpenXRIPBinding_pm24r"), SubResource("OpenXRIPBinding_3wkk3"), SubResource("OpenXRIPBinding_lkcwa")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_h43g7"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_j3htv"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_umnyo"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/left/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_61gsj"] +action = SubResource("OpenXRAction_1vol5") +binding_path = "/user/hand/right/input/aim/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_f63eo"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/left/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3megw"] +action = SubResource("OpenXRAction_18qyl") +binding_path = "/user/hand/right/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1875n"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/left/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jrx7l"] +action = SubResource("OpenXRAction_1pnpo") +binding_path = "/user/hand/right/input/palm_ext/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_y14qq"] +action = SubResource("OpenXRAction_stco1") +binding_path = "/user/hand/left/input/menu/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nj67o"] +action = SubResource("OpenXRAction_oxyin") +binding_path = "/user/hand/right/input/system/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sddo8"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/left/input/x/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5idg5"] +action = SubResource("OpenXRAction_vcq1d") +binding_path = "/user/hand/right/input/a/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5vlhu"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/left/input/y/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yto2p"] +action = SubResource("OpenXRAction_vo38g") +binding_path = "/user/hand/right/input/b/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_35s7d"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/left/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cukgo"] +action = SubResource("OpenXRAction_6v1ja") +binding_path = "/user/hand/right/input/trigger/value" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_58wje"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/left/input/trigger/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_x1ifb"] +action = SubResource("OpenXRAction_iw5kk") +binding_path = "/user/hand/right/input/trigger/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hw16p"] +action = SubResource("OpenXRAction_8vn7r") +binding_path = "/user/hand/left/input/trigger/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gdlwa"] +action = SubResource("OpenXRAction_8vn7r") +binding_path = "/user/hand/right/input/trigger/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_drau7"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0vq03"] +action = SubResource("OpenXRAction_57lfg") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_y7ek0"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/left/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_cy6rb"] +action = SubResource("OpenXRAction_my2cy") +binding_path = "/user/hand/right/input/squeeze/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6r8a6"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/left/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vmwlg"] +action = SubResource("OpenXRAction_jhwoi") +binding_path = "/user/hand/right/input/thumbstick" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qcgh6"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/left/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bwwah"] +action = SubResource("OpenXRAction_ujxhj") +binding_path = "/user/hand/right/input/thumbstick/click" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rtyas"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/left/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hk5ci"] +action = SubResource("OpenXRAction_2sp3t") +binding_path = "/user/hand/right/input/thumbstick/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_4j055"] +action = SubResource("OpenXRAction_6xco2") +binding_path = "/user/hand/left/input/thumbrest/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_awtpp"] +action = SubResource("OpenXRAction_6xco2") +binding_path = "/user/hand/right/input/thumbrest/touch" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xh6fl"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/left/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ixewl"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/hand/right/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_kk5vf"] +interaction_profile_path = "/interaction_profiles/htc/vive_focus3_controller" +bindings = [SubResource("OpenXRIPBinding_h43g7"), SubResource("OpenXRIPBinding_j3htv"), SubResource("OpenXRIPBinding_umnyo"), SubResource("OpenXRIPBinding_61gsj"), SubResource("OpenXRIPBinding_f63eo"), SubResource("OpenXRIPBinding_3megw"), SubResource("OpenXRIPBinding_1875n"), SubResource("OpenXRIPBinding_jrx7l"), SubResource("OpenXRIPBinding_y14qq"), SubResource("OpenXRIPBinding_nj67o"), SubResource("OpenXRIPBinding_sddo8"), SubResource("OpenXRIPBinding_5idg5"), SubResource("OpenXRIPBinding_5vlhu"), SubResource("OpenXRIPBinding_yto2p"), SubResource("OpenXRIPBinding_35s7d"), SubResource("OpenXRIPBinding_cukgo"), SubResource("OpenXRIPBinding_58wje"), SubResource("OpenXRIPBinding_x1ifb"), SubResource("OpenXRIPBinding_hw16p"), SubResource("OpenXRIPBinding_gdlwa"), SubResource("OpenXRIPBinding_drau7"), SubResource("OpenXRIPBinding_0vq03"), SubResource("OpenXRIPBinding_y7ek0"), SubResource("OpenXRIPBinding_cy6rb"), SubResource("OpenXRIPBinding_6r8a6"), SubResource("OpenXRIPBinding_vmwlg"), SubResource("OpenXRIPBinding_qcgh6"), SubResource("OpenXRIPBinding_bwwah"), SubResource("OpenXRIPBinding_rtyas"), SubResource("OpenXRIPBinding_hk5ci"), SubResource("OpenXRIPBinding_4j055"), SubResource("OpenXRIPBinding_awtpp"), SubResource("OpenXRIPBinding_xh6fl"), SubResource("OpenXRIPBinding_ixewl")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qwqvw"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/left_foot/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_oqlrv"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/right_foot/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jw3vw"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_3bjy3"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8upnq"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/left_elbow/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0w2ls"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/right_elbow/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_u8hab"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/left_knee/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_eikk2"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/right_knee/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5lybe"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/waist/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_l4y5i"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/chest/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_f7m66"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/camera/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d13a6"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/vive_tracker_htcx/role/keyboard/input/grip/pose" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_wxcrn"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/left_foot/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_6k8ea"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/right_foot/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1qemc"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/left_shoulder/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8u6xu"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/right_shoulder/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7camc"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/left_elbow/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0fset"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/right_elbow/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ei7tg"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/left_knee/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_c2jdk"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/right_knee/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_g5ap7"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/waist/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_bw6j3"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/chest/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gsob2"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/camera/output/haptic" + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_145o5"] +action = SubResource("OpenXRAction_0kk6l") +binding_path = "/user/vive_tracker_htcx/role/keyboard/output/haptic" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_wxdsn"] +interaction_profile_path = "/interaction_profiles/htc/vive_tracker_htcx" +bindings = [SubResource("OpenXRIPBinding_qwqvw"), SubResource("OpenXRIPBinding_oqlrv"), SubResource("OpenXRIPBinding_jw3vw"), SubResource("OpenXRIPBinding_3bjy3"), SubResource("OpenXRIPBinding_8upnq"), SubResource("OpenXRIPBinding_0w2ls"), SubResource("OpenXRIPBinding_u8hab"), SubResource("OpenXRIPBinding_eikk2"), SubResource("OpenXRIPBinding_5lybe"), SubResource("OpenXRIPBinding_l4y5i"), SubResource("OpenXRIPBinding_f7m66"), SubResource("OpenXRIPBinding_d13a6"), SubResource("OpenXRIPBinding_wxcrn"), SubResource("OpenXRIPBinding_6k8ea"), SubResource("OpenXRIPBinding_1qemc"), SubResource("OpenXRIPBinding_8u6xu"), SubResource("OpenXRIPBinding_7camc"), SubResource("OpenXRIPBinding_0fset"), SubResource("OpenXRIPBinding_ei7tg"), SubResource("OpenXRIPBinding_c2jdk"), SubResource("OpenXRIPBinding_g5ap7"), SubResource("OpenXRIPBinding_bw6j3"), SubResource("OpenXRIPBinding_gsob2"), SubResource("OpenXRIPBinding_145o5")] + +[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_73bb6"] +action = SubResource("OpenXRAction_vk7pf") +binding_path = "/user/eyes_ext/input/gaze_ext/pose" + +[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_07fna"] +interaction_profile_path = "/interaction_profiles/ext/eye_gaze_interaction" +bindings = [SubResource("OpenXRIPBinding_73bb6")] + +[resource] +action_sets = [SubResource("OpenXRActionSet_kd2ms")] +interaction_profiles = [SubResource("OpenXRInteractionProfile_kitsa"), SubResource("OpenXRInteractionProfile_uoohe"), SubResource("OpenXRInteractionProfile_k2llo"), SubResource("OpenXRInteractionProfile_2masb"), SubResource("OpenXRInteractionProfile_ert82"), SubResource("OpenXRInteractionProfile_aq5p3"), SubResource("OpenXRInteractionProfile_4petf"), SubResource("OpenXRInteractionProfile_sd46l"), SubResource("OpenXRInteractionProfile_prh4s"), SubResource("OpenXRInteractionProfile_kk5vf"), SubResource("OpenXRInteractionProfile_wxdsn"), SubResource("OpenXRInteractionProfile_07fna")] diff --git a/samples/meta-space-warp-sample/project.godot b/samples/meta-space-warp-sample/project.godot new file mode 100644 index 00000000..0b7715f9 --- /dev/null +++ b/samples/meta-space-warp-sample/project.godot @@ -0,0 +1,39 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Meta Space Warp Sample" +run/main_scene="res://main.tscn" +config/features=PackedStringArray("4.4", "GL Compatibility") +config/icon="res://icon.svg" + +[debug] + +settings/stdout/verbose_stdout=true + +[layer_names] + +3d_physics/layer_1="Virtual Environment" +3d_physics/layer_2="Scene Understanding" +3d_physics/layer_3="Spatial Anchors" + +[rendering] + +renderer/rendering_method="mobile" +textures/vram_compression/import_etc2_astc=true + +[xr] + +openxr/enabled=true +openxr/reference_space=2 +openxr/extensions/eye_gaze_interaction=true +shaders/enabled=true +openxr/extensions/application_space_warp=true diff --git a/samples/meta-space-warp-sample/screenshots/meta_space_warp_screenshot_01.png b/samples/meta-space-warp-sample/screenshots/meta_space_warp_screenshot_01.png new file mode 100644 index 00000000..1a3723c9 Binary files /dev/null and b/samples/meta-space-warp-sample/screenshots/meta_space_warp_screenshot_01.png differ diff --git a/samples/meta-space-warp-sample/start_xr.gd b/samples/meta-space-warp-sample/start_xr.gd new file mode 100644 index 00000000..cd32c56a --- /dev/null +++ b/samples/meta-space-warp-sample/start_xr.gd @@ -0,0 +1,120 @@ +class_name StartXR +extends Node3D + +# This script uses "A Better XR Start Script" in the Godot Docs as a starting template +# https://docs.godotengine.org/en/latest/tutorials/xr/a_better_xr_start_script.html + +signal focus_lost +signal focus_gained +signal pose_recentered + +@export var maximum_refresh_rate : int = 90 + +var xr_interface : OpenXRInterface +var xr_is_focussed = false + +# Called when the node enters the scene tree for the first time. +func _ready(): + xr_interface = XRServer.find_interface("OpenXR") + if xr_interface and xr_interface.is_initialized(): + print("OpenXR instantiated successfully.") + var vp : Viewport = get_viewport() + + # Enable XR on our viewport + vp.use_xr = true + + # Make sure v-sync is off, v-sync is handled by OpenXR + DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) + + # Enable VRS + if RenderingServer.get_rendering_device(): + vp.vrs_mode = Viewport.VRS_XR + elif int(ProjectSettings.get_setting("xr/openxr/foveation_level")) == 0: + push_warning("OpenXR: Recommend setting Foveation level to High in Project Settings") + + # Connect the OpenXR events + xr_interface.session_begun.connect(_on_openxr_session_begun) + xr_interface.session_visible.connect(_on_openxr_visible_state) + xr_interface.session_focussed.connect(_on_openxr_focused_state) + xr_interface.session_stopping.connect(_on_openxr_stopping) + xr_interface.pose_recentered.connect(_on_openxr_pose_recentered) + else: + # We couldn't start OpenXR. + print("OpenXR not instantiated!") + get_tree().quit() + + +# Handle OpenXR session ready +func _on_openxr_session_begun() -> void: + # Get the reported refresh rate + var current_refresh_rate = xr_interface.get_display_refresh_rate() + if current_refresh_rate > 0: + print("OpenXR: Refresh rate reported as ", str(current_refresh_rate)) + else: + print("OpenXR: No refresh rate given by XR runtime") + + # See if we have a better refresh rate available + var new_rate = current_refresh_rate + var available_rates : Array = xr_interface.get_available_display_refresh_rates() + if available_rates.size() == 0: + print("OpenXR: Target does not support refresh rate extension") + elif available_rates.size() == 1: + # Only one available, so use it + new_rate = available_rates[0] + else: + for rate in available_rates: + if rate > new_rate and rate <= maximum_refresh_rate: + new_rate = rate + + # Did we find a better rate? + if current_refresh_rate != new_rate: + print("OpenXR: Setting refresh rate to ", str(new_rate)) + xr_interface.set_display_refresh_rate(new_rate) + current_refresh_rate = new_rate + + # Now match our physics rate + Engine.physics_ticks_per_second = current_refresh_rate + + +# Handle OpenXR visible state +func _on_openxr_visible_state() -> void: + # We always pass this state at startup, + # but the second time we get this it means our player took off their headset + if xr_is_focussed: + print("OpenXR lost focus") + + xr_is_focussed = false + + # pause our game + process_mode = Node.PROCESS_MODE_DISABLED + + emit_signal("focus_lost") + + +# Handle OpenXR focused state +func _on_openxr_focused_state() -> void: + print("OpenXR gained focus") + xr_is_focussed = true + + # unpause our game + process_mode = Node.PROCESS_MODE_INHERIT + + emit_signal("focus_gained") + + +# Handle OpenXR stopping state +func _on_openxr_stopping() -> void: + # Our session is being stopped. + print("OpenXR is stopping") + + if "--xrsim-automated-tests" in OS.get_cmdline_user_args(): + # When we're running tests via the XR Simulator, it will end the OpenXR + # session automatically, and in that case, we want to quit. + get_tree().quit() + + +# Handle OpenXR pose recentered signal +func _on_openxr_pose_recentered() -> void: + # User recentered view, we have to react to this by recentering the view. + # This is game implementation dependent. + emit_signal("pose_recentered") diff --git a/samples/meta-space-warp-sample/start_xr.gd.uid b/samples/meta-space-warp-sample/start_xr.gd.uid new file mode 100644 index 00000000..ab017566 --- /dev/null +++ b/samples/meta-space-warp-sample/start_xr.gd.uid @@ -0,0 +1 @@ +uid://dbtf8ce1fg6a5 diff --git a/samples/meta-space-warp-sample/tests/test1.vrs b/samples/meta-space-warp-sample/tests/test1.vrs new file mode 100644 index 00000000..fdf2e8f7 --- /dev/null +++ b/samples/meta-space-warp-sample/tests/test1.vrs @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4d59dc1655360472d826fa8b552d9745ceb93d2eb08c90878a261a9685e835f +size 185723 diff --git a/thirdparty/godot_cpp_build_profile/build_profile.json b/thirdparty/godot_cpp_build_profile/build_profile.json index fff93370..259dd318 100644 --- a/thirdparty/godot_cpp_build_profile/build_profile.json +++ b/thirdparty/godot_cpp_build_profile/build_profile.json @@ -36,6 +36,7 @@ "PrimitiveMesh", "ProjectSettings", "RefCounted", + "RenderingServer", "Resource", "SceneTree", "Shader",