Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_gizmos/src/frustum.rs
9443 views
1
//! Module for the drawing of [`Frustum`]s.
2
//!
3
//! Camera entities are spawned with a [`Frustum`] component,
4
//! which describes a camera's field of vision. With this module,
5
//! a camera's frustum can be drawn with gizmos. This is useful
6
//! for debugging what a camera can see and what entities in the scene
7
//! will be subject to the camera's frustum culling, especially when
8
//! combined with drawing [`Aabb`](bevy_camera::primitives::Aabb)
9
//! [`gizmos`](crate::aabb).
10
//!
11
//! There are two ways to enable gizmo drawing of a [`Frustum`]:
12
//! 1) The [`ShowFrustumGizmo`] component can be added to individual camera
13
//! entities.
14
//! ```rust
15
//! # use bevy_gizmos::frustum::ShowFrustumGizmo;
16
//! # use bevy_camera::Camera2d;
17
//! # use bevy_ecs::system::Commands;
18
//! fn setup(mut commands: Commands) {
19
//! commands.spawn((Camera2d, ShowFrustumGizmo::default()));
20
//! }
21
//! ```
22
//! 2) Setting the [`FrustumGizmoConfigGroup`] configuration's `draw_all`
23
//! field to `true` will draw every frustum. Note that this will include
24
//! drawing `bevy_light` `SpotLight` [`Frustum`]s.
25
//! ```rust
26
//! # use bevy_ecs::prelude::*;
27
//! # use bevy_gizmos::prelude::*;
28
//! fn turn_on_frustum_gizmos(mut config: ResMut<GizmoConfigStore>) {
29
//! config.config_mut::<FrustumGizmoConfigGroup>().1.draw_all = true;
30
//! }
31
//! ```
32
33
use bevy_app::{Plugin, PostUpdate};
34
use bevy_camera::{primitives::Frustum, visibility::VisibilitySystems};
35
use bevy_color::Color;
36
use bevy_ecs::{
37
component::Component,
38
entity::Entity,
39
query::Without,
40
reflect::ReflectComponent,
41
schedule::{IntoScheduleConfigs, SystemSet},
42
system::{Query, Res},
43
};
44
use bevy_reflect::{std_traits::ReflectDefault, Reflect, ReflectFromReflect};
45
46
use crate::{
47
color_from_entity,
48
config::{GizmoConfigGroup, GizmoConfigStore},
49
gizmos::Gizmos,
50
AppGizmoBuilder,
51
};
52
53
/// A [`Plugin`] that provides visualization of [`Frustum`]s for debugging.
54
pub struct FrustumGizmoPlugin;
55
56
/// Frustum Gizmo system set. This exists in [`PostUpdate`].
57
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
58
pub struct FrustumGizmoSystems;
59
60
impl Plugin for FrustumGizmoPlugin {
61
fn build(&self, app: &mut bevy_app::App) {
62
app.init_gizmo_group::<FrustumGizmoConfigGroup>()
63
.add_systems(
64
PostUpdate,
65
(
66
draw_frustum_gizmos,
67
draw_all_frustum_gizmos.run_if(|config: Res<GizmoConfigStore>| {
68
config.config::<FrustumGizmoConfigGroup>().1.draw_all
69
}),
70
)
71
.in_set(FrustumGizmoSystems)
72
.after(VisibilitySystems::UpdateFrusta),
73
);
74
}
75
}
76
77
/// The [`GizmoConfigGroup`] used for debug visualizations of [`Frustum`] components on entities
78
#[derive(Clone, Default, Reflect, GizmoConfigGroup)]
79
#[reflect(Clone, Default)]
80
pub struct FrustumGizmoConfigGroup {
81
/// Draws all frusta in the scene when set to `true`.
82
///
83
/// To draw a specific entity's frustum, you can add the [`ShowFrustumGizmo`] component.
84
///
85
/// Defaults to `false`.
86
pub draw_all: bool,
87
/// The default color for frustum gizmos.
88
///
89
/// A random color is chosen per frustum if `None`.
90
///
91
/// Defaults to `None`.
92
pub default_color: Option<Color>,
93
}
94
95
/// Add this [`Component`] to an entity to draw its [`Frustum`] component.
96
#[derive(Component, Reflect, Default, Debug)]
97
#[reflect(Component, FromReflect, Default)]
98
pub struct ShowFrustumGizmo {
99
/// The color of the frustum.
100
///
101
/// The default color from the [`FrustumGizmoConfigGroup`] resource is used if `None`,
102
pub color: Option<Color>,
103
}
104
105
fn draw_frustum_gizmos(
106
query: Query<(Entity, &Frustum, &ShowFrustumGizmo)>,
107
mut gizmos: Gizmos<FrustumGizmoConfigGroup>,
108
) {
109
for (entity, &frustum, gizmo) in &query {
110
let color = gizmo
111
.color
112
.or(gizmos.config_ext.default_color)
113
.unwrap_or_else(|| color_from_entity(entity));
114
115
frustum_inner(&frustum, color, &mut gizmos);
116
}
117
}
118
119
fn draw_all_frustum_gizmos(
120
query: Query<(Entity, &Frustum), Without<ShowFrustumGizmo>>,
121
mut gizmos: Gizmos<FrustumGizmoConfigGroup>,
122
) {
123
for (entity, &frustum) in &query {
124
let color = gizmos
125
.config_ext
126
.default_color
127
.unwrap_or_else(|| color_from_entity(entity));
128
129
frustum_inner(&frustum, color, &mut gizmos);
130
}
131
}
132
133
fn frustum_inner(frustum: &Frustum, color: Color, gizmos: &mut Gizmos<FrustumGizmoConfigGroup>) {
134
let Some([tln, trn, brn, bln, tlf, trf, brf, blf]) = frustum.corners() else {
135
return;
136
};
137
138
gizmos.linestrip(
139
[
140
tln, trn, brn, bln, // Near
141
tln, tlf, // Top Left Near to Far
142
trf, brf, blf, tlf, // Far
143
],
144
color,
145
);
146
gizmos.line(trn, trf, color); // Top Right Near to Far
147
gizmos.line(brn, brf, color); // Bottom Right Near to Far
148
gizmos.line(bln, blf, color); // Bottom Left Near to Far
149
}
150
151