Don't mark a previous mesh transform as changed if it didn't actually change. (#17688)

This patch fixes a bug whereby we're re-extracting every mesh every
frame. It's a regression from PR #17413. The code in question has
actually been in the tree with this bug for quite a while; it's that
just the code didn't actually run unless the renderer considered the
previous view transforms necessary. Occlusion culling expanded the set
of circumstances under which Bevy computes the previous view transforms,
causing this bug to appear more often.

This patch fixes the issue by checking to see if the previous transform
of a mesh actually differs from the current transform before copying the
current transform to the previous transform.
This commit is contained in:
Patrick Walton 2025-02-05 09:35:19 -08:00 committed by GitHub
parent 642e016aef
commit 48049f7256
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -226,7 +226,7 @@ pub fn update_previous_view_data(
}
}
#[derive(Component, Default)]
#[derive(Component, PartialEq, Default)]
pub struct PreviousGlobalTransform(pub Affine3A);
#[cfg(not(feature = "meshlet"))]
@ -237,15 +237,19 @@ type PreviousMeshFilter = Or<(With<Mesh3d>, With<MeshletMesh3d>)>;
pub fn update_mesh_previous_global_transforms(
mut commands: Commands,
views: Query<&Camera, Or<(With<Camera3d>, With<ShadowView>)>>,
meshes: Query<(Entity, &GlobalTransform), PreviousMeshFilter>,
meshes: Query<(Entity, &GlobalTransform, Option<&PreviousGlobalTransform>), PreviousMeshFilter>,
) {
let should_run = views.iter().any(|camera| camera.is_active);
if should_run {
for (entity, transform) in &meshes {
commands
.entity(entity)
.try_insert(PreviousGlobalTransform(transform.affine()));
for (entity, transform, old_previous_transform) in &meshes {
let new_previous_transform = PreviousGlobalTransform(transform.affine());
// Make sure not to trigger change detection on
// `PreviousGlobalTransform` if the previous transform hasn't
// changed.
if old_previous_transform != Some(&new_previous_transform) {
commands.entity(entity).try_insert(new_previous_transform);
}
}
}
}