bevy_mod_raycast/
lib.rs

1//! A small `bevy` plugin for raycasting against [`Mesh`](bevy_render::mesh::Mesh)es.
2//!
3//! ```
4//! # use bevy::prelude::*;
5//! use bevy_mod_raycast::prelude::*;
6//!
7//! fn raycast_system(mut raycast: Raycast) {
8//!     let ray = Ray3d::new(Vec3::ZERO, Vec3::X);
9//!     let hits = raycast.cast_ray(ray, &RaycastSettings::default());
10//! }
11//! ```
12//!
13//! *An example of the immediate mode raycasting API.*
14//!
15//! # Getting Started
16//!
17//! The plugin provides two ways of raycasting:
18//! - An [immediate-mode API](immediate), which allows you to raycast into the scene on-demand in
19//!   any system. Intersections are returned immediately as a sorted `Vec`.
20//! - A [deferred API](deferred), where raycasts are performed once every frame based on entities
21//!    tagged with specific components. Intersections can be queried from the ECS.
22//!
23//! The plugin also provides the [`CursorRayPlugin`] for automatically generating a world space 3D
24//! ray corresponding to the mouse cursor. This is useful for mouse picking.
25//!
26//! ## Choosing an API
27//!
28//! While the deferred API requires adding components on entities, in return it's generally more
29//! "hands-off". Once you add the components to entities, the plugin will run raycasts for you every
30//! frame, and you can query your [`RaycastSource`]s to see what they have intersected that frame.
31//!
32//! You can also think of this as being the "declarative" API. Instead of defining how the raycast
33//! happens, you instead describe what you want. For example, "this entity should cast rays in the
34//! direction it faces", and you can then query that entity to find out what it hit.
35//!
36//! By comparison, the immediate mode API is more imperative. You must define the raycast directly,
37//! but in return you are immediately given the results of the raycast without needing to wait for
38//! the scheduled raycasting system to run and query the results.
39//!
40//! # Use Cases
41//!
42//! This plugin is well suited for use cases where you don't want to use a full physics engine, you
43//! are putting together a simple prototype, or you just want the simplest-possible API. Using the
44//! [`Raycast`] system param requires no added components or plugins. You can just start raycasting
45//! in your systems.
46//!
47//! ## Limitations
48//!
49//! This plugin runs entirely on the CPU, with minimal acceleration structures, and without support
50//! for skinned meshes. However, there is a good chance that this simply won't be an issue for your
51//! application. The provided `stress_test` example is a worst-case scenario that can help you judge
52//! if the plugin will meet your performance needs. Using a laptop with an i7-11800H, I am able to
53//! reach 110-530 fps in the stress test, raycasting against 1,000 monkey meshes.
54
55#![allow(clippy::type_complexity)]
56
57pub mod cursor;
58pub mod deferred;
59pub mod immediate;
60pub mod markers;
61pub mod primitives;
62pub mod raycast;
63
64use bevy_utils::default;
65
66#[allow(unused_imports)] // Needed for docs
67use prelude::*;
68
69pub mod prelude {
70    pub use crate::{cursor::*, deferred::*, immediate::*, markers::*, primitives::*, raycast::*};
71
72    #[cfg(feature = "debug")]
73    pub use crate::debug::*;
74}
75
76/// Used for examples to reduce picking latency. Not relevant code for the examples.
77#[doc(hidden)]
78#[allow(dead_code)]
79pub fn low_latency_window_plugin() -> bevy_window::WindowPlugin {
80    bevy_window::WindowPlugin {
81        primary_window: Some(bevy_window::Window {
82            present_mode: bevy_window::PresentMode::AutoNoVsync,
83            ..default()
84        }),
85        ..default()
86    }
87}