OpenXR: Allow changing play area mode during active session
This commit is contained in:
parent
51991e2014
commit
5935bfa860
7 changed files with 105 additions and 62 deletions
|
@ -141,6 +141,7 @@
|
||||||
<param index="0" name="mode" type="int" enum="XRInterface.PlayAreaMode" />
|
<param index="0" name="mode" type="int" enum="XRInterface.PlayAreaMode" />
|
||||||
<description>
|
<description>
|
||||||
Sets the active play area mode, will return [code]false[/code] if the mode can't be used with this interface.
|
Sets the active play area mode, will return [code]false[/code] if the mode can't be used with this interface.
|
||||||
|
[b]Note:[/b] Changing this after the interface has already been initialized can be jarring for the player, so it's recommended to recenter on the HMD with [method XRServer.center_on_hmd] (if switching to [constant XRInterface.XR_PLAY_AREA_STAGE]) or make the switch during a scene change.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="start_passthrough">
|
<method name="start_passthrough">
|
||||||
|
|
|
@ -37,6 +37,12 @@
|
||||||
You should call this method after a few seconds have passed. For example, when the user requests a realignment of the display holding a designated button on a controller for a short period of time, or when implementing a teleport mechanism.
|
You should call this method after a few seconds have passed. For example, when the user requests a realignment of the display holding a designated button on a controller for a short period of time, or when implementing a teleport mechanism.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="clear_reference_frame" qualifiers="const">
|
||||||
|
<return type="Transform3D" />
|
||||||
|
<description>
|
||||||
|
Clears the reference frame that was set by previous calls to [method center_on_hmd].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="find_interface" qualifiers="const">
|
<method name="find_interface" qualifiers="const">
|
||||||
<return type="XRInterface" />
|
<return type="XRInterface" />
|
||||||
<param index="0" name="name" type="String" />
|
<param index="0" name="name" type="String" />
|
||||||
|
|
|
@ -680,59 +680,74 @@ bool OpenXRAPI::is_reference_space_supported(XrReferenceSpaceType p_reference_sp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXRAPI::setup_spaces() {
|
bool OpenXRAPI::setup_play_space() {
|
||||||
XrResult result;
|
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
|
||||||
|
|
||||||
XrPosef identityPose = {
|
XrPosef identityPose = {
|
||||||
{ 0.0, 0.0, 0.0, 1.0 },
|
{ 0.0, 0.0, 0.0, 1.0 },
|
||||||
{ 0.0, 0.0, 0.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;
|
||||||
// create play space
|
bool will_emulate_local_floor = false;
|
||||||
{
|
|
||||||
emulating_local_floor = false;
|
|
||||||
|
|
||||||
if (is_reference_space_supported(requested_reference_space)) {
|
if (is_reference_space_supported(requested_reference_space)) {
|
||||||
reference_space = 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)) {
|
} 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.");
|
print_verbose("OpenXR: LOCAL_FLOOR space isn't supported, emulating using STAGE and LOCAL spaces.");
|
||||||
|
|
||||||
reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
new_reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||||
emulating_local_floor = true;
|
will_emulate_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 {
|
} else {
|
||||||
// Fallback on LOCAL, which all OpenXR runtimes are required to support.
|
// 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."));
|
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;
|
new_reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
XrReferenceSpaceCreateInfo play_space_create_info = {
|
XrReferenceSpaceCreateInfo play_space_create_info = {
|
||||||
XR_TYPE_REFERENCE_SPACE_CREATE_INFO, // type
|
XR_TYPE_REFERENCE_SPACE_CREATE_INFO, // type
|
||||||
nullptr, // next
|
nullptr, // next
|
||||||
reference_space, // referenceSpaceType
|
new_reference_space, // referenceSpaceType
|
||||||
identityPose, // poseInReferenceSpace
|
identityPose, // poseInReferenceSpace
|
||||||
};
|
};
|
||||||
|
|
||||||
result = xrCreateReferenceSpace(session, &play_space_create_info, &play_space);
|
XrResult result = xrCreateReferenceSpace(session, &play_space_create_info, &new_play_space);
|
||||||
if (XR_FAILED(result)) {
|
if (XR_FAILED(result)) {
|
||||||
print_line("OpenXR: Failed to create play space [", get_error_string(result), "]");
|
print_line("OpenXR: Failed to create play space [", get_error_string(result), "]");
|
||||||
return false;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create view space
|
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)) {
|
if (!is_reference_space_supported(XR_REFERENCE_SPACE_TYPE_VIEW)) {
|
||||||
print_line("OpenXR: reference space XR_REFERENCE_SPACE_TYPE_VIEW is not supported.");
|
print_line("OpenXR: reference space XR_REFERENCE_SPACE_TYPE_VIEW is not supported.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XrPosef identityPose = {
|
||||||
|
{ 0.0, 0.0, 0.0, 1.0 },
|
||||||
|
{ 0.0, 0.0, 0.0 }
|
||||||
|
};
|
||||||
|
|
||||||
XrReferenceSpaceCreateInfo view_space_create_info = {
|
XrReferenceSpaceCreateInfo view_space_create_info = {
|
||||||
XR_TYPE_REFERENCE_SPACE_CREATE_INFO, // type
|
XR_TYPE_REFERENCE_SPACE_CREATE_INFO, // type
|
||||||
nullptr, // next
|
nullptr, // next
|
||||||
|
@ -740,12 +755,11 @@ bool OpenXRAPI::setup_spaces() {
|
||||||
identityPose // poseInReferenceSpace
|
identityPose // poseInReferenceSpace
|
||||||
};
|
};
|
||||||
|
|
||||||
result = xrCreateReferenceSpace(session, &view_space_create_info, &view_space);
|
XrResult result = xrCreateReferenceSpace(session, &view_space_create_info, &view_space);
|
||||||
if (XR_FAILED(result)) {
|
if (XR_FAILED(result)) {
|
||||||
print_line("OpenXR: Failed to create view space [", get_error_string(result), "]");
|
print_line("OpenXR: Failed to create view space [", get_error_string(result), "]");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1262,10 +1276,14 @@ void OpenXRAPI::set_view_configuration(XrViewConfigurationType p_view_configurat
|
||||||
view_configuration = p_view_configuration;
|
view_configuration = p_view_configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXRAPI::set_requested_reference_space(XrReferenceSpaceType p_requested_reference_space) {
|
bool OpenXRAPI::set_requested_reference_space(XrReferenceSpaceType p_requested_reference_space) {
|
||||||
ERR_FAIL_COND(is_initialized());
|
|
||||||
|
|
||||||
requested_reference_space = 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) {
|
void OpenXRAPI::set_submit_depth_buffer(bool p_submit_depth_buffer) {
|
||||||
|
@ -1466,7 +1484,12 @@ bool OpenXRAPI::initialize_session() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setup_spaces()) {
|
if (!setup_play_space()) {
|
||||||
|
destroy_session();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!setup_view_space()) {
|
||||||
destroy_session();
|
destroy_session();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,8 @@ private:
|
||||||
bool create_session();
|
bool create_session();
|
||||||
bool load_supported_reference_spaces();
|
bool load_supported_reference_spaces();
|
||||||
bool is_reference_space_supported(XrReferenceSpaceType p_reference_space);
|
bool is_reference_space_supported(XrReferenceSpaceType p_reference_space);
|
||||||
bool setup_spaces();
|
bool setup_play_space();
|
||||||
|
bool setup_view_space();
|
||||||
bool load_supported_swapchain_formats();
|
bool load_supported_swapchain_formats();
|
||||||
bool is_swapchain_format_supported(int64_t p_swapchain_format);
|
bool is_swapchain_format_supported(int64_t p_swapchain_format);
|
||||||
bool create_swapchains();
|
bool create_swapchains();
|
||||||
|
@ -338,7 +339,7 @@ public:
|
||||||
void set_view_configuration(XrViewConfigurationType p_view_configuration);
|
void set_view_configuration(XrViewConfigurationType p_view_configuration);
|
||||||
XrViewConfigurationType get_view_configuration() const { return view_configuration; }
|
XrViewConfigurationType get_view_configuration() const { return view_configuration; }
|
||||||
|
|
||||||
void set_requested_reference_space(XrReferenceSpaceType p_requested_reference_space);
|
bool set_requested_reference_space(XrReferenceSpaceType p_requested_reference_space);
|
||||||
XrReferenceSpaceType get_requested_reference_space() const { return requested_reference_space; }
|
XrReferenceSpaceType get_requested_reference_space() const { return requested_reference_space; }
|
||||||
XrReferenceSpaceType get_reference_space() const { return reference_space; }
|
XrReferenceSpaceType get_reference_space() const { return reference_space; }
|
||||||
|
|
||||||
|
|
|
@ -711,7 +711,6 @@ XRInterface::PlayAreaMode OpenXRInterface::get_play_area_mode() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
|
bool OpenXRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
|
||||||
ERR_FAIL_COND_V_MSG(initialized, false, "Cannot change play area mode after OpenXR interface has been initialized");
|
|
||||||
ERR_FAIL_NULL_V(openxr_api, false);
|
ERR_FAIL_NULL_V(openxr_api, false);
|
||||||
|
|
||||||
XrReferenceSpaceType reference_space;
|
XrReferenceSpaceType reference_space;
|
||||||
|
@ -726,8 +725,15 @@ bool OpenXRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
openxr_api->set_requested_reference_space(reference_space);
|
if (openxr_api->set_requested_reference_space(reference_space)) {
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
if (xr_server) {
|
||||||
|
xr_server->clear_reference_frame();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackedVector3Array OpenXRInterface::get_play_area() const {
|
PackedVector3Array OpenXRInterface::get_play_area() const {
|
||||||
|
|
|
@ -55,6 +55,7 @@ void XRServer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_world_origin"), &XRServer::get_world_origin);
|
ClassDB::bind_method(D_METHOD("get_world_origin"), &XRServer::get_world_origin);
|
||||||
ClassDB::bind_method(D_METHOD("set_world_origin", "world_origin"), &XRServer::set_world_origin);
|
ClassDB::bind_method(D_METHOD("set_world_origin", "world_origin"), &XRServer::set_world_origin);
|
||||||
ClassDB::bind_method(D_METHOD("get_reference_frame"), &XRServer::get_reference_frame);
|
ClassDB::bind_method(D_METHOD("get_reference_frame"), &XRServer::get_reference_frame);
|
||||||
|
ClassDB::bind_method(D_METHOD("clear_reference_frame"), &XRServer::get_reference_frame);
|
||||||
ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &XRServer::center_on_hmd);
|
ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &XRServer::center_on_hmd);
|
||||||
ClassDB::bind_method(D_METHOD("get_hmd_transform"), &XRServer::get_hmd_transform);
|
ClassDB::bind_method(D_METHOD("get_hmd_transform"), &XRServer::get_hmd_transform);
|
||||||
|
|
||||||
|
@ -158,6 +159,10 @@ void XRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) {
|
||||||
reference_frame = new_reference_frame.inverse();
|
reference_frame = new_reference_frame.inverse();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void XRServer::clear_reference_frame() {
|
||||||
|
reference_frame = Transform3D();
|
||||||
|
}
|
||||||
|
|
||||||
Transform3D XRServer::get_hmd_transform() {
|
Transform3D XRServer::get_hmd_transform() {
|
||||||
Transform3D hmd_transform;
|
Transform3D hmd_transform;
|
||||||
if (primary_interface != nullptr) {
|
if (primary_interface != nullptr) {
|
||||||
|
|
|
@ -142,6 +142,7 @@ public:
|
||||||
and in the virtual world out of sync
|
and in the virtual world out of sync
|
||||||
*/
|
*/
|
||||||
Transform3D get_reference_frame() const;
|
Transform3D get_reference_frame() const;
|
||||||
|
void clear_reference_frame();
|
||||||
void center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height);
|
void center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue