diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml
index 4179ba821cf..49b13986ca1 100644
--- a/doc/classes/XRServer.xml
+++ b/doc/classes/XRServer.xml
@@ -135,6 +135,11 @@
Emitted when an interface is removed.
+
+
+ Emitted when the reference frame transform changes.
+
+
diff --git a/modules/openxr/scene/openxr_composition_layer.cpp b/modules/openxr/scene/openxr_composition_layer.cpp
index b02f3082ab5..f69a907be9a 100644
--- a/modules/openxr/scene/openxr_composition_layer.cpp
+++ b/modules/openxr/scene/openxr_composition_layer.cpp
@@ -151,6 +151,16 @@ void OpenXRCompositionLayer::update_fallback_mesh() {
should_update_fallback_mesh = true;
}
+XrPosef OpenXRCompositionLayer::get_openxr_pose() {
+ Transform3D reference_frame = XRServer::get_singleton()->get_reference_frame();
+ Transform3D transform = reference_frame.inverse() * get_transform();
+ Quaternion quat(transform.basis.orthonormalized());
+ return {
+ { (float)quat.x, (float)quat.y, (float)quat.z, (float)quat.w },
+ { (float)transform.origin.x, (float)transform.origin.y, (float)transform.origin.z }
+ };
+}
+
bool OpenXRCompositionLayer::is_viewport_in_use(SubViewport *p_viewport) {
for (const OpenXRCompositionLayer *other_composition_layer : composition_layer_nodes) {
if (other_composition_layer != this && other_composition_layer->is_inside_tree() && other_composition_layer->get_layer_viewport() == p_viewport) {
diff --git a/modules/openxr/scene/openxr_composition_layer.h b/modules/openxr/scene/openxr_composition_layer.h
index 6792364295b..55cae27d237 100644
--- a/modules/openxr/scene/openxr_composition_layer.h
+++ b/modules/openxr/scene/openxr_composition_layer.h
@@ -77,6 +77,8 @@ protected:
void update_fallback_mesh();
+ XrPosef get_openxr_pose();
+
static Vector composition_layer_nodes;
bool is_viewport_in_use(SubViewport *p_viewport);
diff --git a/modules/openxr/scene/openxr_composition_layer_cylinder.cpp b/modules/openxr/scene/openxr_composition_layer_cylinder.cpp
index 728ba71006a..6c8d2fc885c 100644
--- a/modules/openxr/scene/openxr_composition_layer_cylinder.cpp
+++ b/modules/openxr/scene/openxr_composition_layer_cylinder.cpp
@@ -52,6 +52,7 @@ OpenXRCompositionLayerCylinder::OpenXRCompositionLayerCylinder() {
aspect_ratio, // aspectRatio
};
openxr_layer_provider = memnew(OpenXRViewportCompositionLayerProvider((XrCompositionLayerBaseHeader *)&composition_layer));
+ XRServer::get_singleton()->connect("reference_frame_changed", callable_mp(this, &OpenXRCompositionLayerCylinder::update_transform));
}
OpenXRCompositionLayerCylinder::~OpenXRCompositionLayerCylinder() {
@@ -131,14 +132,15 @@ Ref OpenXRCompositionLayerCylinder::_create_fallback_mesh() {
void OpenXRCompositionLayerCylinder::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- Transform3D transform = get_transform();
- Quaternion quat(transform.basis.orthonormalized());
- composition_layer.pose.orientation = { (float)quat.x, (float)quat.y, (float)quat.z, (float)quat.w };
- composition_layer.pose.position = { (float)transform.origin.x, (float)transform.origin.y, (float)transform.origin.z };
+ update_transform();
} break;
}
}
+void OpenXRCompositionLayerCylinder::update_transform() {
+ composition_layer.pose = get_openxr_pose();
+}
+
void OpenXRCompositionLayerCylinder::set_radius(float p_radius) {
ERR_FAIL_COND(p_radius <= 0);
radius = p_radius;
diff --git a/modules/openxr/scene/openxr_composition_layer_cylinder.h b/modules/openxr/scene/openxr_composition_layer_cylinder.h
index bb1d2422670..9bd5a42d369 100644
--- a/modules/openxr/scene/openxr_composition_layer_cylinder.h
+++ b/modules/openxr/scene/openxr_composition_layer_cylinder.h
@@ -50,6 +50,8 @@ protected:
void _notification(int p_what);
+ void update_transform();
+
virtual Ref _create_fallback_mesh() override;
public:
diff --git a/modules/openxr/scene/openxr_composition_layer_equirect.cpp b/modules/openxr/scene/openxr_composition_layer_equirect.cpp
index 14cfea8da63..b6f5d27ffe8 100644
--- a/modules/openxr/scene/openxr_composition_layer_equirect.cpp
+++ b/modules/openxr/scene/openxr_composition_layer_equirect.cpp
@@ -53,6 +53,7 @@ OpenXRCompositionLayerEquirect::OpenXRCompositionLayerEquirect() {
-lower_vertical_angle, // lowerVerticalAngle
};
openxr_layer_provider = memnew(OpenXRViewportCompositionLayerProvider((XrCompositionLayerBaseHeader *)&composition_layer));
+ XRServer::get_singleton()->connect("reference_frame_changed", callable_mp(this, &OpenXRCompositionLayerEquirect::update_transform));
}
OpenXRCompositionLayerEquirect::~OpenXRCompositionLayerEquirect() {
@@ -139,14 +140,15 @@ Ref OpenXRCompositionLayerEquirect::_create_fallback_mesh() {
void OpenXRCompositionLayerEquirect::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- Transform3D transform = get_transform();
- Quaternion quat(transform.basis.orthonormalized());
- composition_layer.pose.orientation = { (float)quat.x, (float)quat.y, (float)quat.z, (float)quat.w };
- composition_layer.pose.position = { (float)transform.origin.x, (float)transform.origin.y, (float)transform.origin.z };
+ update_transform();
} break;
}
}
+void OpenXRCompositionLayerEquirect::update_transform() {
+ composition_layer.pose = get_openxr_pose();
+}
+
void OpenXRCompositionLayerEquirect::set_radius(float p_radius) {
ERR_FAIL_COND(p_radius <= 0);
radius = p_radius;
diff --git a/modules/openxr/scene/openxr_composition_layer_equirect.h b/modules/openxr/scene/openxr_composition_layer_equirect.h
index 66f8b0a91ce..af6cd92cbe5 100644
--- a/modules/openxr/scene/openxr_composition_layer_equirect.h
+++ b/modules/openxr/scene/openxr_composition_layer_equirect.h
@@ -51,6 +51,8 @@ protected:
void _notification(int p_what);
+ void update_transform();
+
virtual Ref _create_fallback_mesh() override;
public:
diff --git a/modules/openxr/scene/openxr_composition_layer_quad.cpp b/modules/openxr/scene/openxr_composition_layer_quad.cpp
index 8c5b8ec26bb..21919496d65 100644
--- a/modules/openxr/scene/openxr_composition_layer_quad.cpp
+++ b/modules/openxr/scene/openxr_composition_layer_quad.cpp
@@ -50,6 +50,7 @@ OpenXRCompositionLayerQuad::OpenXRCompositionLayerQuad() {
{ (float)quad_size.x, (float)quad_size.y }, // size
};
openxr_layer_provider = memnew(OpenXRViewportCompositionLayerProvider((XrCompositionLayerBaseHeader *)&composition_layer));
+ XRServer::get_singleton()->connect("reference_frame_changed", callable_mp(this, &OpenXRCompositionLayerQuad::update_transform));
}
OpenXRCompositionLayerQuad::~OpenXRCompositionLayerQuad() {
@@ -72,14 +73,15 @@ Ref OpenXRCompositionLayerQuad::_create_fallback_mesh() {
void OpenXRCompositionLayerQuad::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- Transform3D transform = get_transform();
- Quaternion quat(transform.basis.orthonormalized());
- composition_layer.pose.orientation = { (float)quat.x, (float)quat.y, (float)quat.z, (float)quat.w };
- composition_layer.pose.position = { (float)transform.origin.x, (float)transform.origin.y, (float)transform.origin.z };
+ update_transform();
} break;
}
}
+void OpenXRCompositionLayerQuad::update_transform() {
+ composition_layer.pose = get_openxr_pose();
+}
+
void OpenXRCompositionLayerQuad::set_quad_size(const Size2 &p_size) {
quad_size = p_size;
composition_layer.size = { (float)quad_size.x, (float)quad_size.y };
diff --git a/modules/openxr/scene/openxr_composition_layer_quad.h b/modules/openxr/scene/openxr_composition_layer_quad.h
index 21bb9b2d85c..0c3172dbb27 100644
--- a/modules/openxr/scene/openxr_composition_layer_quad.h
+++ b/modules/openxr/scene/openxr_composition_layer_quad.h
@@ -47,6 +47,8 @@ protected:
void _notification(int p_what);
+ void update_transform();
+
virtual Ref _create_fallback_mesh() override;
public:
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index 2cfe98ea1e1..a4e68afee08 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -98,6 +98,8 @@ void XRServer::_bind_methods() {
BIND_ENUM_CONSTANT(RESET_BUT_KEEP_TILT);
BIND_ENUM_CONSTANT(DONT_RESET_ROTATION);
+ ADD_SIGNAL(MethodInfo("reference_frame_changed"));
+
ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING_NAME, "interface_name")));
ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING_NAME, "interface_name")));
@@ -213,11 +215,13 @@ void XRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) {
reference_frame = new_reference_frame.inverse();
set_render_reference_frame(reference_frame);
+ emit_signal(SNAME("reference_frame_changed"));
}
void XRServer::clear_reference_frame() {
reference_frame = Transform3D();
set_render_reference_frame(reference_frame);
+ emit_signal(SNAME("reference_frame_changed"));
}
void XRServer::_set_render_reference_frame(const Transform3D &p_reference_frame) {