diff --git a/crates/nexus_python3d/src/nexus.rs b/crates/nexus_python3d/src/nexus.rs index 0cee52f..6a56091 100644 --- a/crates/nexus_python3d/src/nexus.rs +++ b/crates/nexus_python3d/src/nexus.rs @@ -282,6 +282,13 @@ impl NexusState { self.0.set_rbd_steps_per_frame(steps); } + /// Overrides the per-environment collision-pair capacity (default 4096) + /// used when the GPU state is allocated at `finalize`. Lower it for many + /// small batched envs; pair-keyed buffers scale as capacity × envs. + fn set_rbd_collisions_capacity(&mut self, capacity: u32) { + self.0.set_rbd_collisions_capacity(capacity); + } + fn set_rbd_gravity(&mut self, viewer: PyRef, gravity: Vec3) { self.0 .set_rbd_gravity(viewer.backend(), [gravity.0.x, gravity.0.y, gravity.0.z]); diff --git a/src/state.rs b/src/state.rs index e4dd821..625141e 100644 --- a/src/state.rs +++ b/src/state.rs @@ -160,6 +160,15 @@ impl NexusState { self.rbd_steps_per_frame = steps.max(1); } + /// Overrides the per-environment collision-pair capacity used when the + /// GPU rigid-body state is (re)allocated at `finalize`. The default (4096) + /// is sized for one busy scene, not thousands of small batched envs — + /// pair-keyed workspaces scale as `capacity x num_envs x sizeof(manifold)`, + /// which at 2048 envs binds ~9 GiB unless this is lowered. + pub fn set_rbd_collisions_capacity(&mut self, capacity: u32) { + self.capacities.rbd.collisions_capacity = capacity.max(1); + } + /// Number of rigid-body solver steps per [`NexusPipeline::simulate`](crate::pipeline::NexusPipeline::simulate) call. pub fn rbd_steps_per_frame(&self) -> u32 { self.rbd_steps_per_frame