Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only use the AABB center for mesh visibility range testing if specified. #16468

Merged
merged 3 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions crates/bevy_render/src/view/visibility/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl Plugin for VisibilityRangePlugin {
/// that the `end_margin` of a higher LOD is always identical to the
/// `start_margin` of the next lower LOD; this is important for the crossfade
/// effect to function properly.
#[derive(Component, Clone, PartialEq, Reflect)]
#[derive(Component, Clone, PartialEq, Default, Reflect)]
#[reflect(Component, PartialEq, Hash)]
pub struct VisibilityRange {
/// The range of distances, in world units, between which this entity will
Expand All @@ -131,6 +131,17 @@ pub struct VisibilityRange {
///
/// `end_margin.start` must be greater than or equal to `start_margin.end`.
pub end_margin: Range<f32>,

/// True if Bevy should use the center of the axis-aligned bounding box
pcwalton marked this conversation as resolved.
Show resolved Hide resolved
/// ([`Aabb`]) as the position of the mesh, or false if the origin of the
/// mesh should be considered the mesh's position.
///
/// Usually you will want to leave this set to false, because different LODs
/// may have different AABBs, and smooth crossfades between LOD levels
/// require that all LODs of a mesh be at *precisely* the same position. If
/// you aren't using crossfading, however, and your meshes aren't centered
/// around their origins, then this flag may be useful.
pub use_aabb: bool,
}

impl Eq for VisibilityRange {}
Expand Down Expand Up @@ -160,6 +171,7 @@ impl VisibilityRange {
Self {
start_margin: start..start,
end_margin: end..end,
use_aabb: false,
}
}

Expand Down Expand Up @@ -390,14 +402,17 @@ pub fn check_visibility_ranges(
for (entity, entity_transform, maybe_model_aabb, visibility_range) in entity_query.iter_mut() {
let mut visibility = 0;
for (view_index, &(_, view_position)) in views.iter().enumerate() {
let model_pos = if let Some(model_aabb) = maybe_model_aabb {
let world_from_local = entity_transform.affine();
world_from_local.transform_point3a(model_aabb.center)
} else {
entity_transform.translation_vec3a()
// If instructed to use the AABB and the model has one, use its
// center as the model position. Otherwise, use the model's
// translation.
let model_position = match (visibility_range.use_aabb, maybe_model_aabb) {
(true, Some(model_aabb)) => entity_transform
.affine()
.transform_point3a(model_aabb.center),
_ => entity_transform.translation_vec3a(),
};

if visibility_range.is_visible_at_all((view_position - model_pos).length()) {
if visibility_range.is_visible_at_all((view_position - model_position).length()) {
visibility |= 1 << view_index;
}
}
Expand Down
4 changes: 4 additions & 0 deletions examples/3d/visibility_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,27 @@ const MIN_ZOOM_DISTANCE: f32 = 0.5;
static NORMAL_VISIBILITY_RANGE_HIGH_POLY: VisibilityRange = VisibilityRange {
start_margin: 0.0..0.0,
end_margin: 3.0..4.0,
use_aabb: false,
};
static NORMAL_VISIBILITY_RANGE_LOW_POLY: VisibilityRange = VisibilityRange {
start_margin: 3.0..4.0,
end_margin: 8.0..9.0,
use_aabb: false,
};

// A visibility model that we use to always show a model (until the camera is so
// far zoomed out that it's culled entirely).
static SINGLE_MODEL_VISIBILITY_RANGE: VisibilityRange = VisibilityRange {
start_margin: 0.0..0.0,
end_margin: 8.0..9.0,
use_aabb: false,
};

// A visibility range that we use to completely hide a model.
static INVISIBLE_VISIBILITY_RANGE: VisibilityRange = VisibilityRange {
start_margin: 0.0..0.0,
end_margin: 0.0..0.0,
use_aabb: false,
};

// Allows us to identify the main model.
Expand Down