Skip to content

Commit

Permalink
CameraProjection::compute_frustum (bevyengine#11139)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
2 people authored and tjamaan committed Feb 6, 2024
1 parent 94ab2ab commit 3434510
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 24 deletions.
18 changes: 2 additions & 16 deletions crates/bevy_core_pipeline/src/core_2d/camera_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
17 changes: 17 additions & 0 deletions crates/bevy_render/src/camera/projection.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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.
Expand Down
9 changes: 1 addition & 8 deletions crates/bevy_render/src/view/visibility/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,7 @@ pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>(
>,
) {
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);
}
}

Expand Down

0 comments on commit 3434510

Please sign in to comment.