diff --git a/crates/bevy_pbr/src/meshlet/instance_manager.rs b/crates/bevy_pbr/src/meshlet/instance_manager.rs index 94d03a925a490..5817ff4a49eed 100644 --- a/crates/bevy_pbr/src/meshlet/instance_manager.rs +++ b/crates/bevy_pbr/src/meshlet/instance_manager.rs @@ -92,7 +92,7 @@ impl InstanceManager { aabb: MeshletAabb, bvh_depth: u32, transform: &GlobalTransform, - previous_transform: Option<&PreviousGlobalTransform>, + previous_transform: &PreviousGlobalTransform, render_layers: Option<&RenderLayers>, mesh_material_ids: &RenderMaterialInstances, render_material_bindings: &RenderMaterialBindings, @@ -101,7 +101,7 @@ impl InstanceManager { ) { // Build a MeshUniform for the instance let transform = transform.affine(); - let previous_transform = previous_transform.map(|t| t.0).unwrap_or(transform); + let previous_transform = previous_transform.0; let mut flags = if not_shadow_receiver { MeshFlags::empty() } else { @@ -201,7 +201,7 @@ pub fn extract_meshlet_mesh_entities( Entity, &MeshletMesh3d, &GlobalTransform, - Option<&PreviousGlobalTransform>, + &PreviousGlobalTransform, Option<&RenderLayers>, Has, Has, diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 66de219a90186..3273f2f7eb71d 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -241,10 +241,12 @@ pub fn update_mesh_previous_global_transforms( let should_run = views.iter().any(|camera| camera.is_active); if should_run { + // Initialize PreviousGlobalTransform for new mesh entities to current GlobalTransform for (entity, transform) in &new_meshes { let new_previous_transform = PreviousGlobalTransform(transform.affine()); commands.entity(entity).try_insert(new_previous_transform); } + // Update previous transforms to current transform values for next frame meshes.par_iter_mut().for_each(|(transform, mut previous)| { previous.set_if_neq(PreviousGlobalTransform(transform.affine())); }); diff --git a/examples/test_previous_transform.rs b/examples/test_previous_transform.rs new file mode 100644 index 0000000000000..4a6142d0873d2 --- /dev/null +++ b/examples/test_previous_transform.rs @@ -0,0 +1,84 @@ +//! Test example that verifies PreviousGlobalTransform is correctly initialized +//! to match GlobalTransform on the first frame for new entities. + +use bevy::pbr::PreviousGlobalTransform; +use bevy::prelude::*; + +fn main() { + App::new() + .add_plugins(DefaultPlugins) + .add_systems(Startup, setup) + .add_systems(Update, check_transforms) + .run(); +} + +fn setup( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + // Camera + commands.spawn(( + Camera3d::default(), + Transform::from_xyz(3.0, 3.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y), + )); + + // Light + commands.spawn(( + DirectionalLight::default(), + Transform::from_rotation(Quat::from_euler(EulerRot::XYZ, -0.5, -0.5, 0.0)), + )); + + // Spawn a mesh entity - this should trigger PreviousGlobalTransform initialization + commands.spawn(( + Mesh3d(meshes.add(Sphere::new(1.0))), + MeshMaterial3d(materials.add(StandardMaterial::default())), + Transform::from_xyz(1.0, 2.0, 3.0), + TestEntity, + )); +} + +#[derive(Component)] +struct TestEntity; + +fn check_transforms( + query: Query<(&GlobalTransform, Option<&PreviousGlobalTransform>), With>, + mut frame_count: Local, +) { + *frame_count += 1; + + for (global_transform, maybe_previous) in &query { + println!( + "Frame {}: GlobalTransform: {:?}", + *frame_count, + global_transform.translation() + ); + if let Some(previous) = maybe_previous { + println!( + "Frame {}: PreviousGlobalTransform exists: {:?}", + *frame_count, previous.0.translation + ); + + // On the first frame, previous should equal current + if *frame_count == 1 { + let current_affine = global_transform.affine(); + if (previous.0.translation - current_affine.translation).length() < 0.001 { + println!( + "SUCCESS: PreviousGlobalTransform correctly initialized to GlobalTransform" + ); + } else { + println!("FAIL: PreviousGlobalTransform not initialized correctly"); + println!("Current: {:?}", current_affine.translation); + println!("Previous: {:?}", previous.0.translation); + } + } + } else { + println!("Frame {}: PreviousGlobalTransform missing", *frame_count); + } + } + + // Exit after a few frames + if *frame_count >= 3 { + std::process::exit(0); + } +}