From 08654ad8d8b4ccbdacccf7dd607d990f9f4ef214 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Sun, 4 Feb 2024 01:21:07 +0000 Subject: [PATCH] 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 --- .../src/core_2d/camera_2d.rs | 18 ++---------------- crates/bevy_render/src/camera/projection.rs | 17 +++++++++++++++++ crates/bevy_render/src/view/visibility/mod.rs | 9 +-------- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs index be3c23b57d..471512d0bb 100644 --- a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs +++ b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs @@ -45,14 +45,7 @@ impl Default for Camera2dBundle { ..Default::default() }; let transform = Transform::default(); - let view_projection = - projection.get_projection_matrix() * transform.compute_matrix().inverse(); - let frustum = Frustum::from_view_projection_custom_far( - &view_projection, - &transform.translation, - &transform.back(), - projection.far(), - ); + let frustum = projection.compute_frustum(&GlobalTransform::from(transform)); Self { camera_render_graph: CameraRenderGraph::new(SubGraph2d), projection, @@ -84,14 +77,7 @@ impl Camera2dBundle { ..Default::default() }; let transform = Transform::from_xyz(0.0, 0.0, far - 0.1); - let view_projection = - projection.get_projection_matrix() * transform.compute_matrix().inverse(); - let frustum = Frustum::from_view_projection_custom_far( - &view_projection, - &transform.translation, - &transform.back(), - projection.far(), - ); + let frustum = projection.compute_frustum(&GlobalTransform::from(transform)); Self { camera_render_graph: CameraRenderGraph::new(SubGraph3d), projection, diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 27f90559d6..449702e6ec 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -1,12 +1,14 @@ use std::marker::PhantomData; use std::ops::{Div, DivAssign, Mul, MulAssign}; +use crate::primitives::Frustum; use bevy_app::{App, Plugin, PostStartup, PostUpdate}; use bevy_ecs::{prelude::*, reflect::ReflectComponent}; use bevy_math::{AspectRatio, Mat4, Rect, Vec2, Vec3A}; use bevy_reflect::{ std_traits::ReflectDefault, GetTypeRegistration, Reflect, ReflectDeserialize, ReflectSerialize, }; +use bevy_transform::components::GlobalTransform; use serde::{Deserialize, Serialize}; /// 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 far(&self) -> f32; 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. diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index 4427b408e1..e060864617 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -281,14 +281,7 @@ pub fn update_frusta( >, ) { for (transform, projection, mut frustum) in &mut views { - let view_projection = - projection.get_projection_matrix() * transform.compute_matrix().inverse(); - *frustum = Frustum::from_view_projection_custom_far( - &view_projection, - &transform.translation(), - &transform.back(), - projection.far(), - ); + *frustum = projection.compute_frustum(transform); } }