CameraProjection::compute_frustum (#11139)
Frustum computation is nontrivial amount of code private in `update_frusta` system. Make it public. This is needed to decide which entities to spawn/despawn in `Update` based on camera changes. But if `Update` also changed camera, frustum is not yet recomputed. Technically it is probably possible to run an iteration of `update_frusta` system by a user in `Update` schedule after propagating `GlobalTransform` to the cameras, but it is easier to just compute frustum manually using API added in this PR. Also replace two places where this code is used. --------- Co-authored-by: vero <email@atlasdostal.com>
This commit is contained in:
		
							parent
							
								
									1974723a63
								
							
						
					
					
						commit
						08654ad8d8
					
				@ -45,14 +45,7 @@ impl Default for Camera2dBundle {
 | 
				
			|||||||
            ..Default::default()
 | 
					            ..Default::default()
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let transform = Transform::default();
 | 
					        let transform = Transform::default();
 | 
				
			||||||
        let view_projection =
 | 
					        let frustum = projection.compute_frustum(&GlobalTransform::from(transform));
 | 
				
			||||||
            projection.get_projection_matrix() * transform.compute_matrix().inverse();
 | 
					 | 
				
			||||||
        let frustum = Frustum::from_view_projection_custom_far(
 | 
					 | 
				
			||||||
            &view_projection,
 | 
					 | 
				
			||||||
            &transform.translation,
 | 
					 | 
				
			||||||
            &transform.back(),
 | 
					 | 
				
			||||||
            projection.far(),
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            camera_render_graph: CameraRenderGraph::new(SubGraph2d),
 | 
					            camera_render_graph: CameraRenderGraph::new(SubGraph2d),
 | 
				
			||||||
            projection,
 | 
					            projection,
 | 
				
			||||||
@ -84,14 +77,7 @@ impl Camera2dBundle {
 | 
				
			|||||||
            ..Default::default()
 | 
					            ..Default::default()
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let transform = Transform::from_xyz(0.0, 0.0, far - 0.1);
 | 
					        let transform = Transform::from_xyz(0.0, 0.0, far - 0.1);
 | 
				
			||||||
        let view_projection =
 | 
					        let frustum = projection.compute_frustum(&GlobalTransform::from(transform));
 | 
				
			||||||
            projection.get_projection_matrix() * transform.compute_matrix().inverse();
 | 
					 | 
				
			||||||
        let frustum = Frustum::from_view_projection_custom_far(
 | 
					 | 
				
			||||||
            &view_projection,
 | 
					 | 
				
			||||||
            &transform.translation,
 | 
					 | 
				
			||||||
            &transform.back(),
 | 
					 | 
				
			||||||
            projection.far(),
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            camera_render_graph: CameraRenderGraph::new(SubGraph3d),
 | 
					            camera_render_graph: CameraRenderGraph::new(SubGraph3d),
 | 
				
			||||||
            projection,
 | 
					            projection,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,14 @@
 | 
				
			|||||||
use std::marker::PhantomData;
 | 
					use std::marker::PhantomData;
 | 
				
			||||||
use std::ops::{Div, DivAssign, Mul, MulAssign};
 | 
					use std::ops::{Div, DivAssign, Mul, MulAssign};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::primitives::Frustum;
 | 
				
			||||||
use bevy_app::{App, Plugin, PostStartup, PostUpdate};
 | 
					use bevy_app::{App, Plugin, PostStartup, PostUpdate};
 | 
				
			||||||
use bevy_ecs::{prelude::*, reflect::ReflectComponent};
 | 
					use bevy_ecs::{prelude::*, reflect::ReflectComponent};
 | 
				
			||||||
use bevy_math::{AspectRatio, Mat4, Rect, Vec2, Vec3A};
 | 
					use bevy_math::{AspectRatio, Mat4, Rect, Vec2, Vec3A};
 | 
				
			||||||
use bevy_reflect::{
 | 
					use bevy_reflect::{
 | 
				
			||||||
    std_traits::ReflectDefault, GetTypeRegistration, Reflect, ReflectDeserialize, ReflectSerialize,
 | 
					    std_traits::ReflectDefault, GetTypeRegistration, Reflect, ReflectDeserialize, ReflectSerialize,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					use bevy_transform::components::GlobalTransform;
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Adds [`Camera`](crate::camera::Camera) driver systems for a given projection type.
 | 
					/// Adds [`Camera`](crate::camera::Camera) driver systems for a given projection type.
 | 
				
			||||||
@ -60,6 +62,21 @@ pub trait CameraProjection {
 | 
				
			|||||||
    fn update(&mut self, width: f32, height: f32);
 | 
					    fn update(&mut self, width: f32, height: f32);
 | 
				
			||||||
    fn far(&self) -> f32;
 | 
					    fn far(&self) -> f32;
 | 
				
			||||||
    fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8];
 | 
					    fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Compute camera frustum for camera with given projection and transform.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// This code is called by [`update_frusta`](crate::view::visibility::update_frusta) system
 | 
				
			||||||
 | 
					    /// for each camera to update its frustum.
 | 
				
			||||||
 | 
					    fn compute_frustum(&self, camera_transform: &GlobalTransform) -> Frustum {
 | 
				
			||||||
 | 
					        let view_projection =
 | 
				
			||||||
 | 
					            self.get_projection_matrix() * camera_transform.compute_matrix().inverse();
 | 
				
			||||||
 | 
					        Frustum::from_view_projection_custom_far(
 | 
				
			||||||
 | 
					            &view_projection,
 | 
				
			||||||
 | 
					            &camera_transform.translation(),
 | 
				
			||||||
 | 
					            &camera_transform.back(),
 | 
				
			||||||
 | 
					            self.far(),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A configurable [`CameraProjection`] that can select its projection type at runtime.
 | 
					/// A configurable [`CameraProjection`] that can select its projection type at runtime.
 | 
				
			||||||
 | 
				
			|||||||
@ -281,14 +281,7 @@ pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>(
 | 
				
			|||||||
    >,
 | 
					    >,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    for (transform, projection, mut frustum) in &mut views {
 | 
					    for (transform, projection, mut frustum) in &mut views {
 | 
				
			||||||
        let view_projection =
 | 
					        *frustum = projection.compute_frustum(transform);
 | 
				
			||||||
            projection.get_projection_matrix() * transform.compute_matrix().inverse();
 | 
					 | 
				
			||||||
        *frustum = Frustum::from_view_projection_custom_far(
 | 
					 | 
				
			||||||
            &view_projection,
 | 
					 | 
				
			||||||
            &transform.translation(),
 | 
					 | 
				
			||||||
            &transform.back(),
 | 
					 | 
				
			||||||
            projection.far(),
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user