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}