diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 3c606de6705..da6fd2e9b2b 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -87,7 +87,7 @@ String OpenXRAPI::get_default_action_map_resource_name() { return name; } -String OpenXRAPI::get_error_string(XrResult result) { +String OpenXRAPI::get_error_string(XrResult result) const { if (XR_SUCCEEDED(result)) { return String("Succeeded"); } @@ -1261,6 +1261,7 @@ bool OpenXRAPI::resolve_instance_openxr_symbols() { OPENXR_API_INIT_XR_FUNC_V(xrGetActionStateFloat); OPENXR_API_INIT_XR_FUNC_V(xrGetActionStateVector2f); OPENXR_API_INIT_XR_FUNC_V(xrGetCurrentInteractionProfile); + OPENXR_API_INIT_XR_FUNC_V(xrGetReferenceSpaceBoundsRect); OPENXR_API_INIT_XR_FUNC_V(xrGetSystem); OPENXR_API_INIT_XR_FUNC_V(xrGetSystemProperties); OPENXR_API_INIT_XR_FUNC_V(xrLocateViews); @@ -2072,6 +2073,25 @@ void OpenXRAPI::set_foveation_dynamic(bool p_foveation_dynamic) { } } +Size2 OpenXRAPI::get_play_space_bounds() const { + Size2 ret; + + ERR_FAIL_COND_V(session == XR_NULL_HANDLE, Size2()); + + XrExtent2Df extents; + + XrResult result = xrGetReferenceSpaceBoundsRect(session, reference_space, &extents); + if (XR_FAILED(result)) { + print_line("OpenXR: failed to get play space bounds! [", get_error_string(result), "]"); + return ret; + } + + ret.width = extents.width; + ret.height = extents.height; + + return ret; +} + OpenXRAPI::OpenXRAPI() { // OpenXRAPI is only constructed if OpenXR is enabled. singleton = this; diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index 64769b244c2..efa32b7544d 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -199,6 +199,7 @@ private: EXT_PROTO_XRRESULT_FUNC3(xrGetActionStateVector2f, (XrSession), session, (const XrActionStateGetInfo *), getInfo, (XrActionStateVector2f *), state) EXT_PROTO_XRRESULT_FUNC3(xrGetCurrentInteractionProfile, (XrSession), session, (XrPath), topLevelUserPath, (XrInteractionProfileState *), interactionProfile) EXT_PROTO_XRRESULT_FUNC2(xrGetInstanceProperties, (XrInstance), instance, (XrInstanceProperties *), instanceProperties) + EXT_PROTO_XRRESULT_FUNC3(xrGetReferenceSpaceBoundsRect, (XrSession), session, (XrReferenceSpaceType), referenceSpaceType, (XrExtent2Df *), bounds) EXT_PROTO_XRRESULT_FUNC3(xrGetSystem, (XrInstance), instance, (const XrSystemGetInfo *), getInfo, (XrSystemId *), systemId) EXT_PROTO_XRRESULT_FUNC3(xrGetSystemProperties, (XrInstance), instance, (XrSystemId), systemId, (XrSystemProperties *), properties) EXT_PROTO_XRRESULT_FUNC4(xrLocateSpace, (XrSpace), space, (XrSpace), baseSpace, (XrTime), time, (XrSpaceLocation *), location) @@ -317,7 +318,7 @@ public: XrResult try_get_instance_proc_addr(const char *p_name, PFN_xrVoidFunction *p_addr); XrResult get_instance_proc_addr(const char *p_name, PFN_xrVoidFunction *p_addr); - String get_error_string(XrResult result); + String get_error_string(XrResult result) const; String get_swapchain_format_name(int64_t p_swapchain_format) const; void set_xr_interface(OpenXRInterface *p_xr_interface); @@ -380,6 +381,9 @@ public: bool get_foveation_dynamic() const; void set_foveation_dynamic(bool p_foveation_dynamic); + // Play space. + Size2 get_play_space_bounds() 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 8ce76a5fad3..66f8192c9e0 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -690,6 +690,42 @@ bool OpenXRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) { return false; } +PackedVector3Array OpenXRInterface::get_play_area() const { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, PackedVector3Array()); + PackedVector3Array arr; + + Vector3 sides[4] = { + Vector3(-0.5f, 0.0f, -0.5f), + Vector3(0.5f, 0.0f, -0.5f), + Vector3(0.5f, 0.0f, 0.5f), + Vector3(-0.5f, 0.0f, 0.5f), + }; + + if (openxr_api != nullptr && openxr_api->is_initialized()) { + Size2 extents = openxr_api->get_play_space_bounds(); + if (extents.width != 0.0 && extents.height != 0.0) { + Transform3D reference_frame = xr_server->get_reference_frame(); + + for (int i = 0; i < 4; i++) { + Vector3 coord = sides[i]; + + // Scale it up. + coord.x *= extents.width; + coord.z *= extents.height; + + // Now apply our reference. + Vector3 out = reference_frame.xform(coord); + arr.push_back(out); + } + } else { + WARN_PRINT_ONCE("OpenXR: No extents available."); + } + } + + return arr; +} + float OpenXRInterface::get_display_refresh_rate() const { if (openxr_api == nullptr) { return 0.0; diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index 51ef4ea2284..489d0845ba5 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -125,6 +125,7 @@ public: virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode) override; virtual XRInterface::PlayAreaMode get_play_area_mode() const override; virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode) override; + virtual PackedVector3Array get_play_area() const override; float get_display_refresh_rate() const; void set_display_refresh_rate(float p_refresh_rate);