Physics Interpolation - Move 3D FTI to SceneTree

Moves 3D interpolation from server to the client code (`SceneTree`).
Complete rework of 3D physics interpolation, but using the same user API.
This commit is contained in:
lawnjelly
2025-03-14 10:02:43 +00:00
parent 8954125990
commit ae04a3a5dd
30 changed files with 1030 additions and 432 deletions

View File

@@ -58,10 +58,6 @@ void VisualInstance3D::_update_visibility() {
RS::get_singleton()->instance_set_visible(instance, visible);
}
void VisualInstance3D::_physics_interpolated_changed() {
RenderingServer::get_singleton()->instance_set_interpolated(instance, is_physics_interpolated());
}
void VisualInstance3D::set_instance_use_identity_transform(bool p_enable) {
// Prevent sending instance transforms when using global coordinates.
_set_use_identity_transform(p_enable);
@@ -77,6 +73,12 @@ void VisualInstance3D::set_instance_use_identity_transform(bool p_enable) {
}
}
void VisualInstance3D::fti_update_servers_xform() {
if (!_is_using_identity_transform()) {
RS::get_singleton()->instance_set_transform(get_instance(), _get_cached_global_transform_interpolated());
}
}
void VisualInstance3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
@@ -86,33 +88,19 @@ void VisualInstance3D::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
if (_is_vi_visible() || is_physics_interpolated_and_enabled()) {
if (!_is_using_identity_transform()) {
RenderingServer::get_singleton()->instance_set_transform(instance, get_global_transform());
// For instance when first adding to the tree, when the previous transform is
// unset, to prevent streaking from the origin.
if (_is_physics_interpolation_reset_requested() && is_physics_interpolated_and_enabled() && is_inside_tree()) {
if (_is_vi_visible()) {
_notification(NOTIFICATION_RESET_PHYSICS_INTERPOLATION);
}
_set_physics_interpolation_reset_requested(false);
}
}
// ToDo : Can we turn off notify transform for physics interpolated cases?
if (_is_vi_visible() && !(is_inside_tree() && get_tree()->is_physics_interpolation_enabled()) && !_is_using_identity_transform()) {
// Physics interpolation global off, always send.
RenderingServer::get_singleton()->instance_set_transform(instance, get_global_transform());
}
} break;
case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
if (_is_vi_visible() && is_physics_interpolated() && is_inside_tree()) {
// We must ensure the RenderingServer transform is up to date before resetting.
// This is because NOTIFICATION_TRANSFORM_CHANGED is deferred,
// and cannot be relied to be called in order before NOTIFICATION_RESET_PHYSICS_INTERPOLATION.
if (!_is_using_identity_transform()) {
RenderingServer::get_singleton()->instance_set_transform(instance, get_global_transform());
}
if (_is_vi_visible() && is_inside_tree()) {
// Allow resetting motion vectors etc
// at the same time as resetting physics interpolation,
// giving users one common interface.
RenderingServer::get_singleton()->instance_teleport(instance);
RenderingServer::get_singleton()->instance_reset_physics_interpolation(instance);
}
} break;