Physics Interpolation - refactor client interpolation pump

* Move client interpolation pump to earlier in the iteration before 3D physics synced
* Allow `get_global_transform_interpolated()` to prime the client interpolation inside a physics tick
This commit is contained in:
lawnjelly 2024-06-19 07:36:06 +01:00
parent 12781e4554
commit d80b206643
4 changed files with 17 additions and 9 deletions

View file

@ -24,6 +24,7 @@
<description> <description>
When using physics interpolation, there will be circumstances in which you want to know the interpolated (displayed) transform of a node rather than the standard transform (which may only be accurate to the most recent physics tick). When using physics interpolation, there will be circumstances in which you want to know the interpolated (displayed) transform of a node rather than the standard transform (which may only be accurate to the most recent physics tick).
This is particularly important for frame-based operations that take place in [method Node._process], rather than [method Node._physics_process]. Examples include [Camera]s focusing on a node, or finding where to fire lasers from on a frame rather than physics tick. This is particularly important for frame-based operations that take place in [method Node._process], rather than [method Node._physics_process]. Examples include [Camera]s focusing on a node, or finding where to fire lasers from on a frame rather than physics tick.
[b]Note:[/b] This function creates an interpolation pump on the [Spatial] the first time it is called, which can respond to physics interpolation resets. If you get problems with "streaking" when initially following a [Spatial], be sure to call [method get_global_transform_interpolated] at least once [i]before[/i] resetting the [Spatial] physics interpolation.
</description> </description>
</method> </method>
<method name="get_parent_spatial" qualifiers="const"> <method name="get_parent_spatial" qualifiers="const">

View file

@ -2367,14 +2367,14 @@ bool Main::iteration() {
uint64_t physics_begin = OS::get_singleton()->get_ticks_usec(); uint64_t physics_begin = OS::get_singleton()->get_ticks_usec();
PhysicsServer::get_singleton()->flush_queries();
// Prepare the fixed timestep interpolated nodes // Prepare the fixed timestep interpolated nodes
// BEFORE they are updated by the physics 2D, // BEFORE they are updated by the physics,
// otherwise the current and previous transforms // otherwise the current and previous transforms
// may be the same, and no interpolation takes place. // may be the same, and no interpolation takes place.
OS::get_singleton()->get_main_loop()->iteration_prepare(); OS::get_singleton()->get_main_loop()->iteration_prepare();
PhysicsServer::get_singleton()->flush_queries();
Physics2DServer::get_singleton()->sync(); Physics2DServer::get_singleton()->sync();
Physics2DServer::get_singleton()->flush_queries(); Physics2DServer::get_singleton()->flush_queries();

View file

@ -407,7 +407,14 @@ Transform Spatial::get_global_transform_interpolated() {
// Pass through if physics interpolation is switched off. // Pass through if physics interpolation is switched off.
// This is a convenience, as it allows you to easy turn off interpolation // This is a convenience, as it allows you to easy turn off interpolation
// without changing any code. // without changing any code.
if (Engine::get_singleton()->is_in_physics_frame() || !is_physics_interpolated_and_enabled()) { if (!is_physics_interpolated_and_enabled()) {
return get_global_transform();
}
// If we are in the physics frame, the interpolated global transform is meaningless.
// However, there is an exception, we may want to use this as a means of starting off the client
// interpolation pump if not already started (when _is_physics_interpolated_client_side() is false).
if (Engine::get_singleton()->is_in_physics_frame() && _is_physics_interpolated_client_side()) {
return get_global_transform(); return get_global_transform();
} }

View file

@ -559,6 +559,11 @@ void SceneTree::iteration_prepare() {
// are flushed before pumping the interpolation prev and currents. // are flushed before pumping the interpolation prev and currents.
flush_transform_notifications(); flush_transform_notifications();
VisualServer::get_singleton()->tick(); VisualServer::get_singleton()->tick();
// Any objects performing client physics interpolation
// should be given an opportunity to keep their previous transforms
// up to date before each new physics tick.
_client_physics_interpolation.physics_process();
} }
} }
@ -575,11 +580,6 @@ bool SceneTree::iteration(float p_time) {
current_frame++; current_frame++;
// Any objects performing client physics interpolation
// should be given an opportunity to keep their previous transforms
// up to take before each new physics tick.
_client_physics_interpolation.physics_process();
flush_transform_notifications(); flush_transform_notifications();
if (MainLoop::iteration(p_time)) { if (MainLoop::iteration(p_time)) {