Skip to main content

dynamis_world/
lib.rs

1mod arena;
2mod backend;
3mod body;
4mod clock;
5mod colliders;
6mod commands;
7mod constraint;
8mod event;
9mod ids;
10mod query;
11mod query_pool;
12mod readback;
13mod rows;
14mod shape;
15mod shape_pool;
16mod snapshot;
17mod soft;
18mod step;
19mod upload;
20mod view;
21
22use backend::Backend;
23use body::Bodies;
24use clock::Clock;
25use colliders::ColliderPool;
26use commands::BodyCommand;
27use constraint::Constraints;
28use dynamis_gpu::EVENT_SLOTS;
29use dynamis_gpu::{GpuBuffer, GpuContext, WarmupBudget, WarmupProgress};
30use dynamis_model::{BodyHandle, PhysicsConfig};
31use event::Events;
32use query::Queries;
33use shape::Shapes;
34use soft::SoftBodies;
35use view::View;
36
37pub use backend::StreamCapacity;
38pub use dynamis_rigid::RigidShape;
39pub use dynamis_soft::SoftCapacity;
40pub use dynamis_state::{ShapeCapacity, StateCapacity};
41pub use query_pool::{QueryHandle, QueryHit};
42pub use readback::{ConstraintForce, ContactManifold, ContactPoint};
43pub use snapshot::Snapshot;
44
45pub struct World {
46    config: PhysicsConfig,
47
48    clock: Clock,
49    backend: Backend,
50    bodies: Bodies,
51    colliders: ColliderPool,
52    constraints: Constraints,
53    shapes: Shapes,
54    queries: Queries,
55    events: Events,
56    view: View,
57    soft: SoftBodies,
58}
59
60impl World {
61    pub fn new(gpu: GpuContext, config: PhysicsConfig) -> Self {
62        config.assert_valid();
63        let shapes = Shapes::new();
64        let backend = Backend::new(gpu);
65        Self {
66            config,
67            clock: Clock::new(),
68            backend,
69            bodies: Bodies::new(),
70            colliders: ColliderPool::new(),
71            constraints: Constraints::new(),
72            shapes,
73            queries: Queries::new(),
74            events: Events::new(),
75            view: View::new(),
76            soft: SoftBodies::new(),
77        }
78    }
79
80    pub fn config(&self) -> &PhysicsConfig {
81        &self.config
82    }
83
84    pub fn set_config(&mut self, config: PhysicsConfig) {
85        config.assert_valid();
86        self.config = config;
87        self.wake_all();
88    }
89
90    pub fn set_gravity(&mut self, gravity: [f32; 3]) {
91        self.config.gravity = gravity;
92        self.wake_all();
93    }
94
95    fn wake_all(&mut self) {
96        for row in 0..self.bodies.alive.len() as u32 {
97            self.bodies.commands.push(BodyCommand::Wake { row });
98        }
99        self.soft.wake_all();
100    }
101
102    pub fn stream_capacity(&self) -> StreamCapacity {
103        self.backend.streams.capacity()
104    }
105
106    pub fn bodies(&self) -> &[BodyHandle] {
107        &self.bodies.alive
108    }
109
110    pub fn count(&self) -> usize {
111        self.bodies.alive.len()
112    }
113
114    pub fn is_idle(&self) -> bool {
115        !self.backend.published && !self.busy(&self.host_work())
116    }
117
118    pub fn state_buffer(&self) -> &GpuBuffer {
119        self.backend.streams.state.body_states.gpu()
120    }
121
122    pub fn collider_buffer(&self) -> &GpuBuffer {
123        self.backend.streams.state.colliders.gpu()
124    }
125
126    pub fn gpu(&self) -> &GpuContext {
127        &self.backend.gpu
128    }
129
130    pub fn warmup(&self, budget: WarmupBudget) -> WarmupProgress {
131        self.backend.gpu.warmup(budget)
132    }
133
134    pub fn is_warm(&self) -> bool {
135        self.backend.gpu.is_warm()
136    }
137
138    pub fn pass_labels(&self) -> Vec<&'static str> {
139        self.backend
140            .passes
141            .declared()
142            .iter()
143            .map(|pass| pass.label)
144            .collect()
145    }
146
147    pub(crate) fn event_slot_of(&self, step: u64) -> u32 {
148        (step % EVENT_SLOTS as u64) as u32
149    }
150}