OpenXR: Allow changing play area mode during active session

This commit is contained in:
David Snopek 2024-01-30 10:30:54 -06:00
parent 51991e2014
commit 5935bfa860
7 changed files with 105 additions and 62 deletions

View file

@ -680,71 +680,85 @@ bool OpenXRAPI::is_reference_space_supported(XrReferenceSpaceType p_reference_sp
return false;
}
bool OpenXRAPI::setup_spaces() {
XrResult result;
bool OpenXRAPI::setup_play_space() {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
XrPosef identityPose = {
{ 0.0, 0.0, 0.0, 1.0 },
{ 0.0, 0.0, 0.0 }
};
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
XrReferenceSpaceType new_reference_space;
XrSpace new_play_space = XR_NULL_HANDLE;
bool will_emulate_local_floor = false;
// create play space
{
emulating_local_floor = false;
if (is_reference_space_supported(requested_reference_space)) {
new_reference_space = requested_reference_space;
} else if (requested_reference_space == XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT && is_reference_space_supported(XR_REFERENCE_SPACE_TYPE_STAGE)) {
print_verbose("OpenXR: LOCAL_FLOOR space isn't supported, emulating using STAGE and LOCAL spaces.");
if (is_reference_space_supported(requested_reference_space)) {
reference_space = requested_reference_space;
} else if (requested_reference_space == XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT && is_reference_space_supported(XR_REFERENCE_SPACE_TYPE_STAGE)) {
print_verbose("OpenXR: LOCAL_FLOOR space isn't supported, emulating using STAGE and LOCAL spaces.");
reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL;
emulating_local_floor = true;
// We'll use the STAGE space to get the floor height, but we can't do that until
// after xrWaitFrame(), so just set this flag for now.
should_reset_emulated_floor_height = true;
} else {
// Fallback on LOCAL, which all OpenXR runtimes are required to support.
print_verbose(String("OpenXR: ") + OpenXRUtil::get_reference_space_name(requested_reference_space) + String(" isn't supported, defaulting to LOCAL space."));
reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL;
}
XrReferenceSpaceCreateInfo play_space_create_info = {
XR_TYPE_REFERENCE_SPACE_CREATE_INFO, // type
nullptr, // next
reference_space, // referenceSpaceType
identityPose, // poseInReferenceSpace
};
result = xrCreateReferenceSpace(session, &play_space_create_info, &play_space);
if (XR_FAILED(result)) {
print_line("OpenXR: Failed to create play space [", get_error_string(result), "]");
return false;
}
new_reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL;
will_emulate_local_floor = true;
} else {
// Fallback on LOCAL, which all OpenXR runtimes are required to support.
print_verbose(String("OpenXR: ") + OpenXRUtil::get_reference_space_name(requested_reference_space) + String(" isn't supported, defaulting to LOCAL space."));
new_reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL;
}
// create view space
{
if (!is_reference_space_supported(XR_REFERENCE_SPACE_TYPE_VIEW)) {
print_line("OpenXR: reference space XR_REFERENCE_SPACE_TYPE_VIEW is not supported.");
return false;
}
XrReferenceSpaceCreateInfo play_space_create_info = {
XR_TYPE_REFERENCE_SPACE_CREATE_INFO, // type
nullptr, // next
new_reference_space, // referenceSpaceType
identityPose, // poseInReferenceSpace
};
XrReferenceSpaceCreateInfo view_space_create_info = {
XR_TYPE_REFERENCE_SPACE_CREATE_INFO, // type
nullptr, // next
XR_REFERENCE_SPACE_TYPE_VIEW, // referenceSpaceType
identityPose // poseInReferenceSpace
};
XrResult result = xrCreateReferenceSpace(session, &play_space_create_info, &new_play_space);
if (XR_FAILED(result)) {
print_line("OpenXR: Failed to create play space [", get_error_string(result), "]");
return false;
}
result = xrCreateReferenceSpace(session, &view_space_create_info, &view_space);
if (XR_FAILED(result)) {
print_line("OpenXR: Failed to create view space [", get_error_string(result), "]");
return false;
}
// If we've previously created a play space, clean it up first.
if (play_space != XR_NULL_HANDLE) {
xrDestroySpace(play_space);
}
play_space = new_play_space;
reference_space = new_reference_space;
emulating_local_floor = will_emulate_local_floor;
if (emulating_local_floor) {
// We'll use the STAGE space to get the floor height, but we can't do that until
// after xrWaitFrame(), so just set this flag for now.
should_reset_emulated_floor_height = true;
}
return true;
}
bool OpenXRAPI::setup_view_space() {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
if (!is_reference_space_supported(XR_REFERENCE_SPACE_TYPE_VIEW)) {
print_line("OpenXR: reference space XR_REFERENCE_SPACE_TYPE_VIEW is not supported.");
return false;
}
XrPosef identityPose = {
{ 0.0, 0.0, 0.0, 1.0 },
{ 0.0, 0.0, 0.0 }
};
XrReferenceSpaceCreateInfo view_space_create_info = {
XR_TYPE_REFERENCE_SPACE_CREATE_INFO, // type
nullptr, // next
XR_REFERENCE_SPACE_TYPE_VIEW, // referenceSpaceType
identityPose // poseInReferenceSpace
};
XrResult result = xrCreateReferenceSpace(session, &view_space_create_info, &view_space);
if (XR_FAILED(result)) {
print_line("OpenXR: Failed to create view space [", get_error_string(result), "]");
return false;
}
return true;
@ -1262,10 +1276,14 @@ void OpenXRAPI::set_view_configuration(XrViewConfigurationType p_view_configurat
view_configuration = p_view_configuration;
}
void OpenXRAPI::set_requested_reference_space(XrReferenceSpaceType p_requested_reference_space) {
ERR_FAIL_COND(is_initialized());
bool OpenXRAPI::set_requested_reference_space(XrReferenceSpaceType p_requested_reference_space) {
requested_reference_space = p_requested_reference_space;
if (is_initialized()) {
return setup_play_space();
}
return true;
}
void OpenXRAPI::set_submit_depth_buffer(bool p_submit_depth_buffer) {
@ -1466,7 +1484,12 @@ bool OpenXRAPI::initialize_session() {
return false;
}
if (!setup_spaces()) {
if (!setup_play_space()) {
destroy_session();
return false;
}
if (!setup_view_space()) {
destroy_session();
return false;
}