Skip to content

Physics interpolation is broken on XR nodes and XRServer #103232

@Asaduji

Description

@Asaduji

Tested versions

System information

Godot v4.4.rc.mono (0e3dbba) - Windows 11 (build 26100) - Multi-window, 1 monitor - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4090 (NVIDIA; 32.0.15.7247) - AMD Ryzen 9 7950X3D 16-Core Processor (32 threads)

Issue description

Physics interpolation is broken in XR in general, causing the following issues:

  • XROrigin3D updates XRServer::world_origin only when the transform changes, which means XRServer::world_origin never has the interpolated value for the transform on each render frame. XRServer::world_origin is used to know where the camera is in the world and to render properly, if it isn't also interpolated then there's is a mismatch between the active XROrigin3D transform and what XRServer has saved. This results in the following behavior:
current.mov
  • All XR nodes that have a XRPositionalTracker will update their position every time the "pose_changed" signal is triggered. This happens every time XRServer::_process gets called because it asks the active XR interface to poll events and it happens every render frame. Tracked nodes being updated every frame make sense because if we instead poll events on each physics frame and interpolate them the motion sickness on something like the HMD would be unreal, and you don't want your hand trackers to lag behind your real hands. However, when interpolation is enabled the engine really doesn't want you to be updating your transforms on render frame and this causes the childs of those tracked nodes to jitter a bit.

Here is an example in the attached MRP, when the "hand" is interpolated, it follows the parent just fine but the childs aren't smooth at all (also spams in the console the warning that an interpolated transform was set outside physics process)

2025-02-24.18-04-54.mp4

Disabling interpolation in the hand results in really smooth child movement but then when it comes to following the parent everything falls apart:

2025-02-24.18-05-37.mp4

I created a WIP pull request (#103233) with a fix for the XRServer::world_origin interpolation where it works as expected:

fix.mov

However for the second issue I'm out of ideas about how to proceed. Disabling interpolation on the tracked node makes it jitter because it will now follow the non interpolated transform of the parent even if the parent is set as interpolated.

Steps to reproduce

Enable interpolation in a project and make XROrigin3D a child of any physics object

Minimal reproduction project (MRP)

It can be reproduced on the official openxr_character_centric_movement demo, modifying start_vr.gd to remove the line Engine.physics_ticks_per_second = current_refresh_rate so the physics FPS can be different than the target framerate
https://github.com/godotengine/godot-demo-projects/tree/master/xr/openxr_character_centric_movement
However here I include a modified version that just adds a moving platform where you can easily see the problem

MRP.zip

Here is an MRP to test the tracker issue with a fake hand for anyone who wants to test without XR hardware:

tracking_mrp.zip

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions