diff --git a/core/templates/interpolated_property.h b/core/templates/interpolated_property.h index d55c1f8d6a..240bed5fad 100644 --- a/core/templates/interpolated_property.h +++ b/core/templates/interpolated_property.h @@ -46,6 +46,12 @@ class InterpolatedProperty { // Only needs interpolating / updating the servers when // curr and prev are different. bool _needs_interpolating = false; + + // Each time we hit a physics tick, curr = prev, + // BUT the server may be out of date, and needs an update + // on the next frame, OR taking the node off the property update list. + bool _server_stale = false; + T _interpolated; T curr; T prev; @@ -57,6 +63,7 @@ public: void pump() { prev = curr; _needs_interpolating = false; + _server_stale = true; } void reset() { pump(); } @@ -64,13 +71,18 @@ public: _interpolated = p_val; } const T &interpolated() const { return _interpolated; } - bool needs_interpolating() const { return _needs_interpolating; } + // Returns true if an update to the server is needed. bool interpolate(float p_interpolation_fraction) { if (_needs_interpolating) { _interpolated = InterpolatedPropertyFuncs::lerp(prev, curr, p_interpolation_fraction); return true; } + if (_server_stale) { + _interpolated = curr; + _server_stale = false; + return true; + } return false; } diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index a42abf59fb..fa7cf3b7b3 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -70,22 +70,28 @@ void Camera3D::fti_update_servers_property() { if (camera.is_valid()) { float f = Engine::get_singleton()->get_physics_interpolation_fraction(); + bool update_fov = fov.interpolate(f); + bool update_near = _near.interpolate(f); + bool update_far = _far.interpolate(f); + bool update_size = size.interpolate(f); + bool update_frustum_offset = frustum_offset.interpolate(f); + + // If there have been changes due to interpolated values, OR we are forcing an update, update the servers. switch (mode) { default: break; case PROJECTION_PERSPECTIVE: { - // If there have been changes due to interpolation, update the servers. - if (fov.interpolate(f) || _near.interpolate(f) || _far.interpolate(f)) { + if (update_fov || update_near || update_far) { RS::get_singleton()->camera_set_perspective(camera, fov.interpolated(), _near.interpolated(), _far.interpolated()); } } break; case PROJECTION_ORTHOGONAL: { - if (size.interpolate(f) || _near.interpolate(f) || _far.interpolate(f)) { + if (update_size || update_near || update_far) { RS::get_singleton()->camera_set_orthogonal(camera, size.interpolated(), _near.interpolated(), _far.interpolated()); } } break; case PROJECTION_FRUSTUM: { - if (size.interpolate(f) || frustum_offset.interpolate(f) || _near.interpolate(f) || _far.interpolate(f)) { + if (update_size || update_frustum_offset || update_near || update_far) { RS::get_singleton()->camera_set_frustum(camera, size.interpolated(), frustum_offset.interpolated(), _near.interpolated(), _far.interpolated()); } } break;