Skip to content

Commit

Permalink
Account for near clipping plane in sprite backend (#293)
Browse files Browse the repository at this point in the history
* Account for near clipping plane in sprite backend

* Correctly subtract z transform

* Improve docs

* Update changelog

* formatting

---------

Co-authored-by: Aevyrie <[email protected]>
  • Loading branch information
teodosin and aevyrie authored Feb 24, 2024
1 parent ec249c3 commit f1a64e2
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# UNRELEASED

- Fixed: sprite picking depth is now consistent with other picking backends.
- Fixed: entities with identical depth could be dropped due to the use of a BTreeMap to sort
entities by depth. This has been changed to use a sorted Vec, to allow entities with the same
depth to coexist.
Expand Down
16 changes: 8 additions & 8 deletions backends/bevy_picking_sprite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl Plugin for SpriteBackend {
/// Checks if any sprite entities are under each pointer
pub fn sprite_picking(
pointers: Query<(&PointerId, &PointerLocation)>,
cameras: Query<(Entity, &Camera, &GlobalTransform)>,
cameras: Query<(Entity, &Camera, &GlobalTransform, &OrthographicProjection)>,
primary_window: Query<Entity, With<PrimaryWindow>>,
images: Res<Assets<Image>>,
texture_atlas: Res<Assets<TextureAtlas>>,
Expand Down Expand Up @@ -63,10 +63,10 @@ pub fn sprite_picking(
pointer_location.location().map(|loc| (pointer, loc))
}) {
let mut blocked = false;
let Some((cam_entity, camera, cam_transform)) = cameras
let Some((cam_entity, camera, cam_transform, cam_ortho)) = cameras
.iter()
.filter(|(_, camera, _)| camera.is_active)
.find(|(_, camera, _)| {
.filter(|(_, camera, _, _)| camera.is_active)
.find(|(_, camera, _, _)| {
camera
.target
.normalize(Some(primary_window.single()))
Expand Down Expand Up @@ -123,10 +123,10 @@ pub fn sprite_picking(
blocked =
is_cursor_in_sprite && pickable.map(|p| p.should_block_lower) != Some(false);

is_cursor_in_sprite.then_some((
entity,
HitData::new(cam_entity, sprite_transform.translation().z, None, None),
))
// HitData requires a depth as calculated from the camera's near clipping plane
let depth = -cam_ortho.near - sprite_transform.translation().z;

is_cursor_in_sprite.then_some((entity, HitData::new(cam_entity, depth, None, None)))
})
.collect();

Expand Down
10 changes: 5 additions & 5 deletions crates/bevy_picking_core/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,16 @@ impl PointerHits {
}
}

/// Holds data from a successful pointer hit test.
///
/// `depth` only needs to be self-consistent with other [`PointerHits`]s using the same
/// [`RenderTarget`](bevy_render::camera::RenderTarget).
/// Holds data from a successful pointer hit test. See [`HitData::depth`] for important details.
#[derive(Clone, Debug, PartialEq, Reflect)]
pub struct HitData {
/// The camera entity used to detect this hit. Useful when you need to find the ray that was
/// casted for this hit when using a raycasting backend.
pub camera: Entity,
/// The distance from the pointer to the entity into the screen, or depth.
/// `depth` only needs to be self-consistent with other [`PointerHits`]s using the same
/// [`RenderTarget`](bevy_render::camera::RenderTarget). However, it is recommended to use the
/// distance from the pointer to the hit, measured from the near plane of the camera, to the
/// point, in world space.
pub depth: f32,
/// The position of the intersection in the world, if the data is available from the backend.
pub position: Option<Vec3>,
Expand Down

0 comments on commit f1a64e2

Please sign in to comment.