summaryrefslogtreecommitdiff
path: root/modules/openxr
diff options
context:
space:
mode:
Diffstat (limited to 'modules/openxr')
-rw-r--r--modules/openxr/SCsub1
-rw-r--r--modules/openxr/action_map/openxr_action_map.cpp20
-rw-r--r--modules/openxr/doc_classes/OpenXRInterface.xml13
-rw-r--r--modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp123
-rw-r--r--modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h70
-rw-r--r--modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp28
-rw-r--r--modules/openxr/openxr_api.cpp39
-rw-r--r--modules/openxr/openxr_api.h8
-rw-r--r--modules/openxr/openxr_interface.cpp88
-rw-r--r--modules/openxr/openxr_interface.h5
10 files changed, 357 insertions, 38 deletions
diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub
index 5ac167ad98..b5978ab134 100644
--- a/modules/openxr/SCsub
+++ b/modules/openxr/SCsub
@@ -96,6 +96,7 @@ env_openxr.add_source_files(module_obj, "extensions/openxr_composition_layer_dep
env_openxr.add_source_files(module_obj, "extensions/openxr_htc_vive_tracker_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_hand_tracking_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_fb_passthrough_extension_wrapper.cpp")
+env_openxr.add_source_files(module_obj, "extensions/openxr_fb_display_refresh_rate_extension.cpp")
env.modules_sources += module_obj
diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp
index 185e44c29d..123f860ce9 100644
--- a/modules/openxr/action_map/openxr_action_map.cpp
+++ b/modules/openxr/action_map/openxr_action_map.cpp
@@ -224,7 +224,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our interaction profiles
Ref<OpenXRInteractionProfile> profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/khr/simple_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -236,7 +236,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our Vive controller profile
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -257,7 +257,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our WMR controller profile
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/microsoft/motion_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -280,7 +280,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our Meta touch controller profile
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/oculus/touch_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -305,7 +305,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our Valve index controller profile
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/valve/index_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -333,7 +333,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our HP MR controller profile
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/hp/mixed_reality_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -356,7 +356,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our Samsung Odyssey controller profile,
// Note that this controller is only identified specifically on WMR, on SteamVR this is identified as a normal WMR controller.
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/samsung/odyssey_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -379,7 +379,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our Vive Cosmos controller
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_cosmos_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -403,7 +403,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Note, Vive Focus 3 currently is not yet supported as a stand alone device
// however HTC currently has a beta OpenXR runtime in testing we may support in the near future
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_focus3_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
@@ -427,7 +427,7 @@ void OpenXRActionMap::create_default_action_sets() {
// Create our Huawei controller
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/huawei/controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml
index 25bf496de9..f089fd066e 100644
--- a/modules/openxr/doc_classes/OpenXRInterface.xml
+++ b/modules/openxr/doc_classes/OpenXRInterface.xml
@@ -10,6 +10,19 @@
<tutorials>
<link title="Setting up XR">$DOCS_URL/tutorials/xr/setting_up_xr.html</link>
</tutorials>
+ <methods>
+ <method name="get_available_display_refresh_rates" qualifiers="const">
+ <return type="Array" />
+ <description>
+ Returns display refresh rates supported by the current HMD. Only returned if this feature is supported by the OpenXR runtime and after the interface has been initialized.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="display_refresh_rate" type="float" setter="set_display_refresh_rate" getter="get_display_refresh_rate" default="0.0">
+ The display refresh rate for the current HMD. Only functional if this feature is supported by the OpenXR runtime and after the interface has been initialized.
+ </member>
+ </members>
<signals>
<signal name="pose_recentered">
<description>
diff --git a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp
new file mode 100644
index 0000000000..c0bbaea5b4
--- /dev/null
+++ b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp
@@ -0,0 +1,123 @@
+/*************************************************************************/
+/* openxr_fb_display_refresh_rate_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.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 "openxr_fb_display_refresh_rate_extension.h"
+
+OpenXRDisplayRefreshRateExtension *OpenXRDisplayRefreshRateExtension::singleton = nullptr;
+
+OpenXRDisplayRefreshRateExtension *OpenXRDisplayRefreshRateExtension::get_singleton() {
+ return singleton;
+}
+
+OpenXRDisplayRefreshRateExtension::OpenXRDisplayRefreshRateExtension(OpenXRAPI *p_openxr_api) :
+ OpenXRExtensionWrapper(p_openxr_api) {
+ singleton = this;
+
+ // Extensions we use for our hand tracking.
+ request_extensions[XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME] = &display_refresh_rate_ext;
+}
+
+OpenXRDisplayRefreshRateExtension::~OpenXRDisplayRefreshRateExtension() {
+ display_refresh_rate_ext = false;
+}
+
+void OpenXRDisplayRefreshRateExtension::on_instance_created(const XrInstance p_instance) {
+ if (display_refresh_rate_ext) {
+ EXT_INIT_XR_FUNC(xrEnumerateDisplayRefreshRatesFB);
+ EXT_INIT_XR_FUNC(xrGetDisplayRefreshRateFB);
+ EXT_INIT_XR_FUNC(xrRequestDisplayRefreshRateFB);
+ }
+}
+
+void OpenXRDisplayRefreshRateExtension::on_instance_destroyed() {
+ display_refresh_rate_ext = false;
+}
+
+float OpenXRDisplayRefreshRateExtension::get_refresh_rate() const {
+ float refresh_rate = 0.0;
+
+ if (display_refresh_rate_ext) {
+ float rate;
+ XrResult result = xrGetDisplayRefreshRateFB(openxr_api->get_session(), &rate);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: Failed to obtain refresh rate [", openxr_api->get_error_string(result), "]");
+ } else {
+ refresh_rate = rate;
+ }
+ }
+
+ return refresh_rate;
+}
+
+void OpenXRDisplayRefreshRateExtension::set_refresh_rate(float p_refresh_rate) {
+ if (display_refresh_rate_ext) {
+ XrResult result = xrRequestDisplayRefreshRateFB(openxr_api->get_session(), p_refresh_rate);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: Failed to set refresh rate [", openxr_api->get_error_string(result), "]");
+ }
+ }
+}
+
+Array OpenXRDisplayRefreshRateExtension::get_available_refresh_rates() const {
+ Array arr;
+ XrResult result;
+
+ if (display_refresh_rate_ext) {
+ uint32_t display_refresh_rate_count = 0;
+ result = xrEnumerateDisplayRefreshRatesFB(openxr_api->get_session(), 0, &display_refresh_rate_count, nullptr);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: Failed to obtain refresh rates count [", openxr_api->get_error_string(result), "]");
+ }
+
+ if (display_refresh_rate_count > 0) {
+ float *display_refresh_rates = (float *)memalloc(sizeof(float) * display_refresh_rate_count);
+ if (display_refresh_rates == nullptr) {
+ print_line("OpenXR: Failed to obtain refresh rates memory buffer [", openxr_api->get_error_string(result), "]");
+ return arr;
+ }
+
+ result = xrEnumerateDisplayRefreshRatesFB(openxr_api->get_session(), display_refresh_rate_count, &display_refresh_rate_count, display_refresh_rates);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: Failed to obtain refresh rates count [", openxr_api->get_error_string(result), "]");
+ memfree(display_refresh_rates);
+ return arr;
+ }
+
+ for (uint32_t i = 0; i < display_refresh_rate_count; i++) {
+ float refresh_rate = display_refresh_rates[i];
+ arr.push_back(Variant(refresh_rate));
+ }
+
+ memfree(display_refresh_rates);
+ }
+ }
+
+ return arr;
+}
diff --git a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h
new file mode 100644
index 0000000000..dcd52fe4d1
--- /dev/null
+++ b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* openxr_fb_display_refresh_rate_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.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_DISPLAY_REFRESH_RATE_EXTENSION_H
+#define OPENXR_FB_DISPLAY_REFRESH_RATE_EXTENSION_H
+
+// This extension gives us access to the possible display refresh rates
+// supported by the HMD.
+// While this is an FB extension it has been adopted by most runtimes and
+// will likely become core in the near future.
+
+#include "../openxr_api.h"
+#include "../util.h"
+
+#include "openxr_extension_wrapper.h"
+
+class OpenXRDisplayRefreshRateExtension : public OpenXRExtensionWrapper {
+public:
+ static OpenXRDisplayRefreshRateExtension *get_singleton();
+
+ OpenXRDisplayRefreshRateExtension(OpenXRAPI *p_openxr_api);
+ virtual ~OpenXRDisplayRefreshRateExtension() override;
+
+ virtual void on_instance_created(const XrInstance p_instance) override;
+ virtual void on_instance_destroyed() override;
+
+ float get_refresh_rate() const;
+ void set_refresh_rate(float p_refresh_rate);
+
+ Array get_available_refresh_rates() const;
+
+private:
+ static OpenXRDisplayRefreshRateExtension *singleton;
+
+ bool display_refresh_rate_ext = false;
+
+ // OpenXR API call wrappers
+ EXT_PROTO_XRRESULT_FUNC4(xrEnumerateDisplayRefreshRatesFB, (XrSession), session, (uint32_t), displayRefreshRateCapacityInput, (uint32_t *), displayRefreshRateCountOutput, (float *), displayRefreshRates);
+ EXT_PROTO_XRRESULT_FUNC2(xrGetDisplayRefreshRateFB, (XrSession), session, (float *), display_refresh_rate);
+ EXT_PROTO_XRRESULT_FUNC2(xrRequestDisplayRefreshRateFB, (XrSession), session, (float), display_refresh_rate);
+};
+
+#endif // OPENXR_FB_DISPLAY_REFRESH_RATE_EXTENSION_H
diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
index 88cc7c061c..4d996e6283 100644
--- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
+++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
@@ -69,6 +69,34 @@ bool OpenXRHTCViveTrackerExtension::on_event_polled(const XrEventDataBuffer &eve
bool OpenXRHTCViveTrackerExtension::is_path_supported(const String &p_path) {
if (p_path == "/interaction_profiles/htc/vive_tracker_htcx") {
return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/handheld_object") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/left_foot") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/right_foot") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/left_shoulder") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/right_shoulder") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/left_elbow") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/right_elbow") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/left_knee") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/right_knee") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/waist") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/chest") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/chest") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/camera") {
+ return available;
+ } else if (p_path == "/user/vive_tracker_htcx/role/keyboard") {
+ return available;
}
// Not a path under this extensions control, so we return true;
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 8a67462613..1ff1dac512 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -50,6 +50,7 @@
#endif
#include "extensions/openxr_composition_layer_depth_extension.h"
+#include "extensions/openxr_fb_display_refresh_rate_extension.h"
#include "extensions/openxr_fb_passthrough_extension_wrapper.h"
#include "extensions/openxr_hand_tracking_extension.h"
#include "extensions/openxr_htc_vive_tracker_extension.h"
@@ -443,12 +444,12 @@ bool OpenXRAPI::load_supported_view_configuration_views(XrViewConfigurationType
for (uint32_t i = 0; i < view_count; i++) {
print_verbose("OpenXR: Found supported view configuration view");
- print_verbose(String(" - width: ") + view_configuration_views[i].maxImageRectWidth);
- print_verbose(String(" - height: ") + view_configuration_views[i].maxImageRectHeight);
- print_verbose(String(" - sample count: ") + view_configuration_views[i].maxSwapchainSampleCount);
- print_verbose(String(" - recommended render width: ") + view_configuration_views[i].recommendedImageRectWidth);
- print_verbose(String(" - recommended render height: ") + view_configuration_views[i].recommendedImageRectHeight);
- print_verbose(String(" - recommended render sample count: ") + view_configuration_views[i].recommendedSwapchainSampleCount);
+ print_verbose(String(" - width: ") + itos(view_configuration_views[i].maxImageRectWidth));
+ print_verbose(String(" - height: ") + itos(view_configuration_views[i].maxImageRectHeight));
+ print_verbose(String(" - sample count: ") + itos(view_configuration_views[i].maxSwapchainSampleCount));
+ print_verbose(String(" - recommended render width: ") + itos(view_configuration_views[i].recommendedImageRectWidth));
+ print_verbose(String(" - recommended render height: ") + itos(view_configuration_views[i].recommendedImageRectHeight));
+ print_verbose(String(" - recommended render sample count: ") + itos(view_configuration_views[i].recommendedSwapchainSampleCount));
}
return true;
@@ -1748,6 +1749,31 @@ void OpenXRAPI::end_frame() {
}
}
+float OpenXRAPI::get_display_refresh_rate() const {
+ OpenXRDisplayRefreshRateExtension *drrext = OpenXRDisplayRefreshRateExtension::get_singleton();
+ if (drrext) {
+ return drrext->get_refresh_rate();
+ }
+
+ return 0.0;
+}
+
+void OpenXRAPI::set_display_refresh_rate(float p_refresh_rate) {
+ OpenXRDisplayRefreshRateExtension *drrext = OpenXRDisplayRefreshRateExtension::get_singleton();
+ if (drrext != nullptr) {
+ drrext->set_refresh_rate(p_refresh_rate);
+ }
+}
+
+Array OpenXRAPI::get_available_display_refresh_rates() const {
+ OpenXRDisplayRefreshRateExtension *drrext = OpenXRDisplayRefreshRateExtension::get_singleton();
+ if (drrext != nullptr) {
+ return drrext->get_available_refresh_rates();
+ }
+
+ return Array();
+}
+
OpenXRAPI::OpenXRAPI() {
// OpenXRAPI is only constructed if OpenXR is enabled.
singleton = this;
@@ -1817,6 +1843,7 @@ OpenXRAPI::OpenXRAPI() {
register_extension_wrapper(memnew(OpenXRHTCViveTrackerExtension(this)));
register_extension_wrapper(memnew(OpenXRHandTrackingExtension(this)));
register_extension_wrapper(memnew(OpenXRFbPassthroughExtensionWrapper(this)));
+ register_extension_wrapper(memnew(OpenXRDisplayRefreshRateExtension(this)));
}
OpenXRAPI::~OpenXRAPI() {
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index bd69432dcb..5dce749351 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -84,8 +84,6 @@ private:
bool ext_vive_focus3_available = false;
bool ext_huawei_controller_available = false;
- bool is_path_supported(const String &p_path);
-
// composition layer providers
Vector<OpenXRCompositionLayerProvider *> composition_layer_providers;
@@ -302,6 +300,7 @@ public:
void parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
bool xr_result(XrResult result, const char *format, Array args = Array()) const;
+ bool is_path_supported(const String &p_path);
static bool openxr_is_enabled(bool p_check_run_in_editor = true);
static OpenXRAPI *get_singleton();
@@ -336,6 +335,11 @@ public:
void post_draw_viewport(RID p_render_target);
void end_frame();
+ // Display refresh rate
+ float get_display_refresh_rate() const;
+ void set_display_refresh_rate(float p_refresh_rate);
+ Array get_available_display_refresh_rates() const;
+
// action map
String get_default_action_map_resource_name();
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index 68414ae84e..bdf437b0b7 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -41,6 +41,13 @@ void OpenXRInterface::_bind_methods() {
ADD_SIGNAL(MethodInfo("session_focussed"));
ADD_SIGNAL(MethodInfo("session_visible"));
ADD_SIGNAL(MethodInfo("pose_recentered"));
+
+ // Display refresh rate
+ ClassDB::bind_method(D_METHOD("get_display_refresh_rate"), &OpenXRInterface::get_display_refresh_rate);
+ ClassDB::bind_method(D_METHOD("set_display_refresh_rate", "refresh_rate"), &OpenXRInterface::set_display_refresh_rate);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "display_refresh_rate"), "set_display_refresh_rate", "get_display_refresh_rate");
+
+ ClassDB::bind_method(D_METHOD("get_available_display_refresh_rates"), &OpenXRInterface::get_available_display_refresh_rates);
}
StringName OpenXRInterface::get_name() const {
@@ -147,24 +154,25 @@ void OpenXRInterface::_load_action_map() {
Ref<OpenXRAction> xr_action = actions[j];
PackedStringArray toplevel_paths = xr_action->get_toplevel_paths();
- Vector<Tracker *> trackers_new;
+ Vector<Tracker *> trackers_for_action;
for (int k = 0; k < toplevel_paths.size(); k++) {
- Tracker *tracker = find_tracker(toplevel_paths[k], true);
- if (tracker) {
- trackers_new.push_back(tracker);
+ // Only check for our tracker if our path is supported.
+ if (openxr_api->is_path_supported(toplevel_paths[k])) {
+ Tracker *tracker = find_tracker(toplevel_paths[k], true);
+ if (tracker) {
+ trackers_for_action.push_back(tracker);
+ }
}
}
- Action *action = create_action(action_set, xr_action->get_name(), xr_action->get_localized_name(), xr_action->get_action_type(), trackers);
- if (action) {
- // we link our actions back to our trackers so we know which actions to check when we're processing our trackers
- for (int t = 0; t < trackers_new.size(); t++) {
- link_action_to_tracker(trackers_new[t], action);
+ // Only add our action if we have atleast one valid toplevel path
+ if (trackers_for_action.size() > 0) {
+ Action *action = create_action(action_set, xr_action->get_name(), xr_action->get_localized_name(), xr_action->get_action_type(), trackers_for_action);
+ if (action) {
+ // add this to our map for creating our interaction profiles
+ xr_actions[xr_action] = action;
}
-
- // add this to our map for creating our interaction profiles
- xr_actions[xr_action] = action;
}
}
}
@@ -282,6 +290,13 @@ OpenXRInterface::Action *OpenXRInterface::create_action(ActionSet *p_action_set,
action->action_rid = openxr_api->action_create(p_action_set->action_set_rid, p_action_name, p_localized_name, p_action_type, tracker_rids);
p_action_set->actions.push_back(action);
+ // we link our actions back to our trackers so we know which actions to check when we're processing our trackers
+ for (int i = 0; i < p_trackers.size(); i++) {
+ if (p_trackers[i]->actions.find(action) == -1) {
+ p_trackers[i]->actions.push_back(action);
+ }
+ }
+
return action;
}
@@ -330,6 +345,8 @@ OpenXRInterface::Tracker *OpenXRInterface::find_tracker(const String &p_tracker_
return nullptr;
}
+ ERR_FAIL_COND_V(!openxr_api->is_path_supported(p_tracker_name), nullptr);
+
// Create our RID
RID tracker_rid = openxr_api->tracker_create(p_tracker_name);
ERR_FAIL_COND_V(tracker_rid.is_null(), nullptr);
@@ -389,12 +406,6 @@ void OpenXRInterface::tracker_profile_changed(RID p_tracker, RID p_interaction_p
}
}
-void OpenXRInterface::link_action_to_tracker(Tracker *p_tracker, Action *p_action) {
- if (p_tracker->actions.find(p_action) == -1) {
- p_tracker->actions.push_back(p_action);
- }
-}
-
void OpenXRInterface::handle_tracker(Tracker *p_tracker) {
ERR_FAIL_NULL(openxr_api);
ERR_FAIL_COND(p_tracker->positional_tracker.is_null());
@@ -447,9 +458,18 @@ void OpenXRInterface::handle_tracker(Tracker *p_tracker) {
void OpenXRInterface::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) {
ERR_FAIL_NULL(openxr_api);
+
Action *action = find_action(p_action_name);
ERR_FAIL_NULL(action);
- Tracker *tracker = find_tracker(p_tracker_name);
+
+ // We need to map our tracker name to our OpenXR name for our inbuild names.
+ String tracker_name = p_tracker_name;
+ if (tracker_name == "left_hand") {
+ tracker_name = "/user/hand/left";
+ } else if (tracker_name == "right_hand") {
+ tracker_name = "/user/hand/right";
+ }
+ Tracker *tracker = find_tracker(tracker_name);
ERR_FAIL_NULL(tracker);
// TODO OpenXR does not support delay, so we may need to add support for that somehow...
@@ -571,6 +591,36 @@ bool OpenXRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
return false;
}
+float OpenXRInterface::get_display_refresh_rate() const {
+ if (openxr_api == nullptr) {
+ return 0.0;
+ } else if (!openxr_api->is_initialized()) {
+ return 0.0;
+ } else {
+ return openxr_api->get_display_refresh_rate();
+ }
+}
+
+void OpenXRInterface::set_display_refresh_rate(float p_refresh_rate) {
+ if (openxr_api == nullptr) {
+ return;
+ } else if (!openxr_api->is_initialized()) {
+ return;
+ } else {
+ openxr_api->set_display_refresh_rate(p_refresh_rate);
+ }
+}
+
+Array OpenXRInterface::get_available_display_refresh_rates() const {
+ if (openxr_api == nullptr) {
+ return Array();
+ } else if (!openxr_api->is_initialized()) {
+ return Array();
+ } else {
+ return openxr_api->get_available_display_refresh_rates();
+ }
+}
+
Size2 OpenXRInterface::get_render_target_size() {
if (openxr_api == nullptr) {
return Size2();
diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h
index 72935b039c..454612346f 100644
--- a/modules/openxr/openxr_interface.h
+++ b/modules/openxr/openxr_interface.h
@@ -91,7 +91,6 @@ private:
void free_actions(ActionSet *p_action_set);
Tracker *find_tracker(const String &p_tracker_name, bool p_create = false);
- void link_action_to_tracker(Tracker *p_tracker, Action *p_action);
void handle_tracker(Tracker *p_tracker);
void free_trackers();
@@ -120,6 +119,10 @@ public:
virtual XRInterface::PlayAreaMode get_play_area_mode() const override;
virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode) override;
+ float get_display_refresh_rate() const;
+ void set_display_refresh_rate(float p_refresh_rate);
+ Array get_available_display_refresh_rates() const;
+
virtual Size2 get_render_target_size() override;
virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;