Skip to content

Commit d6a4fe6

Browse files
committed
XR: Allow locking the camera to the XROrigin3D for benchmarking or automated testing
1 parent 0f5f3bc commit d6a4fe6

File tree

4 files changed

+26
-1
lines changed

4 files changed

+26
-1
lines changed

doc/classes/XRServer.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@
111111
</method>
112112
</methods>
113113
<members>
114+
<member name="camera_locked_to_origin" type="bool" setter="set_camera_locked_to_origin" getter="is_camera_locked_to_origin" default="false">
115+
If set to [code]true[/code], the scene will be rendered as if the camera is locked to the [XROrigin3D].
116+
[b]Note:[/b] This doesn't provide a very comfortable experience for users. This setting exists for doing benchmarking or automated testing, where you want to control what is rendered via code.
117+
</member>
114118
<member name="primary_interface" type="XRInterface" setter="set_primary_interface" getter="get_primary_interface">
115119
The primary [XRInterface] currently bound to the [XRServer].
116120
</member>

servers/rendering/renderer_scene_cull.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2773,6 +2773,8 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
27732773

27742774
camera_data.set_camera(transform, projection, is_orthogonal, is_frustum, vaspect, jitter, taa_frame_count, camera->visible_layers);
27752775
} else {
2776+
XRServer *xr_server = XRServer::get_singleton();
2777+
27762778
// Setup our camera for our XR interface.
27772779
// We can support multiple views here each with their own camera
27782780
Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS];
@@ -2783,7 +2785,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
27832785

27842786
float aspect = p_viewport_size.width / (float)p_viewport_size.height;
27852787

2786-
Transform3D world_origin = XRServer::get_singleton()->get_world_origin();
2788+
Transform3D world_origin = xr_server->get_world_origin();
27872789

27882790
// We ignore our camera position, it will have been positioned with a slightly old tracking position.
27892791
// Instead we take our origin point and have our XR interface add fresh tracking data! Whoohoo!
@@ -2792,6 +2794,14 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
27922794
projections[v] = p_xr_interface->get_projection_for_view(v, aspect, camera->znear, camera->zfar);
27932795
}
27942796

2797+
// If requested, we move the views to be rendered as if the HMD is at the XROrigin.
2798+
if (unlikely(xr_server->is_camera_locked_to_origin())) {
2799+
Transform3D camera_reset = p_xr_interface->get_camera_transform().affine_inverse() * xr_server->get_reference_frame().affine_inverse();
2800+
for (uint32_t v = 0; v < view_count; v++) {
2801+
transforms[v] *= camera_reset;
2802+
}
2803+
}
2804+
27952805
if (view_count == 1) {
27962806
camera_data.set_camera(transforms[0], projections[0], false, false, camera->vaspect, jitter, p_jitter_phase_count, camera->visible_layers);
27972807
} else if (view_count == 2) {

servers/xr_server.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ void XRServer::_bind_methods() {
6262
ClassDB::bind_method(D_METHOD("clear_reference_frame"), &XRServer::clear_reference_frame);
6363
ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &XRServer::center_on_hmd);
6464
ClassDB::bind_method(D_METHOD("get_hmd_transform"), &XRServer::get_hmd_transform);
65+
ClassDB::bind_method(D_METHOD("set_camera_locked_to_origin", "enabled"), &XRServer::set_camera_locked_to_origin);
66+
ClassDB::bind_method(D_METHOD("is_camera_locked_to_origin"), &XRServer::is_camera_locked_to_origin);
6567

6668
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale");
6769
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "world_origin"), "set_world_origin", "get_world_origin");
70+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "camera_locked_to_origin"), "set_camera_locked_to_origin", "is_camera_locked_to_origin");
6871

6972
ClassDB::bind_method(D_METHOD("add_interface", "interface"), &XRServer::add_interface);
7073
ClassDB::bind_method(D_METHOD("get_interface_count"), &XRServer::get_interface_count);
@@ -241,6 +244,10 @@ Transform3D XRServer::get_hmd_transform() {
241244
return hmd_transform;
242245
}
243246

247+
void XRServer::set_camera_locked_to_origin(bool p_enable) {
248+
camera_locked_to_origin = p_enable;
249+
}
250+
244251
void XRServer::add_interface(const Ref<XRInterface> &p_interface) {
245252
ERR_FAIL_COND(p_interface.is_null());
246253

servers/xr_server.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class XRServer : public Object {
9696
double world_scale = 1.0; /* scale by which we multiply our tracker positions */
9797
Transform3D world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */
9898
Transform3D reference_frame; /* our reference frame */
99+
bool camera_locked_to_origin = false;
99100

100101
// As we may be updating our main state for our next frame while we're still rendering our previous frame,
101102
// we need to keep copies around.
@@ -198,6 +199,9 @@ class XRServer : public Object {
198199
*/
199200
Transform3D get_hmd_transform();
200201

202+
void set_camera_locked_to_origin(bool p_enable);
203+
inline bool is_camera_locked_to_origin() const { return camera_locked_to_origin; }
204+
201205
/*
202206
Interfaces are objects that 'glue' Godot to an AR or VR SDK such as the Oculus SDK, OpenVR, OpenHMD, etc.
203207
*/

0 commit comments

Comments
 (0)