aboutsummaryrefslogtreecommitdiff
path: root/src_testbed
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2020-12-22 16:23:41 +0100
committerGitHub <noreply@github.com>2020-12-22 16:23:41 +0100
commitfd3b4801b63fd56369ff37bdc2e5189db159e8ff (patch)
treea2017a39480dcd9045da00dbf0ff9c60d6b16259 /src_testbed
parentd7cd20d3e4b0fdd963705bbef42520dc05811a56 (diff)
parent496f4e32588d4f5efd821e7834ddd0d7b0dd1acc (diff)
downloadrapier-fd3b4801b63fd56369ff37bdc2e5189db159e8ff.tar.gz
rapier-fd3b4801b63fd56369ff37bdc2e5189db159e8ff.tar.bz2
rapier-fd3b4801b63fd56369ff37bdc2e5189db159e8ff.zip
Merge pull request #81 from rezural/harness
Introduce a run harness, to make running salva with rapier easier with headless.
Diffstat (limited to 'src_testbed')
-rw-r--r--src_testbed/harness/mod.rs186
-rw-r--r--src_testbed/harness/plugin.rs15
-rw-r--r--src_testbed/lib.rs5
3 files changed, 205 insertions, 1 deletions
diff --git a/src_testbed/harness/mod.rs b/src_testbed/harness/mod.rs
new file mode 100644
index 0000000..fa6c4c6
--- /dev/null
+++ b/src_testbed/harness/mod.rs
@@ -0,0 +1,186 @@
+use crate::physics::{PhysicsEvents, PhysicsState};
+use plugin::HarnessPlugin;
+use rapier::dynamics::{IntegrationParameters, JointSet, RigidBodySet};
+use rapier::geometry::{BroadPhase, ColliderSet, NarrowPhase};
+use rapier::math::Vector;
+use rapier::pipeline::{ChannelEventCollector, PhysicsPipeline, QueryPipeline};
+
+pub mod plugin;
+
+pub struct HarnessState {
+ #[cfg(feature = "parallel")]
+ pub thread_pool: rapier::rayon::ThreadPool,
+ pub timestep_id: usize,
+}
+
+pub struct Harness {
+ physics: PhysicsState,
+ max_steps: usize,
+ callbacks: Callbacks,
+ plugins: Vec<Box<dyn HarnessPlugin>>,
+ time: f32,
+ events: PhysicsEvents,
+ event_handler: ChannelEventCollector,
+ pub state: HarnessState,
+}
+
+type Callbacks = Vec<Box<dyn FnMut(&mut PhysicsState, &PhysicsEvents, &HarnessState, f32)>>;
+
+#[allow(dead_code)]
+impl Harness {
+ pub fn new_empty() -> Self {
+ #[cfg(feature = "parallel")]
+ let num_threads = num_cpus::get_physical();
+
+ #[cfg(feature = "parallel")]
+ let thread_pool = rapier::rayon::ThreadPoolBuilder::new()
+ .num_threads(num_threads)
+ .build()
+ .unwrap();
+
+ let contact_channel = crossbeam::channel::unbounded();
+ let proximity_channel = crossbeam::channel::unbounded();
+ let event_handler = ChannelEventCollector::new(proximity_channel.0, contact_channel.0);
+ let events = PhysicsEvents {
+ contact_events: contact_channel.1,
+ proximity_events: proximity_channel.1,
+ };
+ let physics = PhysicsState::new();
+ let state = HarnessState {
+ #[cfg(feature = "parallel")]
+ thread_pool,
+ timestep_id: 0,
+ };
+
+ Self {
+ physics,
+ max_steps: 1000,
+ callbacks: Vec::new(),
+ plugins: Vec::new(),
+ time: 0.0,
+ events,
+ event_handler,
+ state,
+ }
+ }
+
+ pub fn new(bodies: RigidBodySet, colliders: ColliderSet, joints: JointSet) -> Self {
+ let mut res = Self::new_empty();
+ res.set_world(bodies, colliders, joints);
+ res
+ }
+
+ pub fn set_max_steps(&mut self, max_steps: usize) {
+ self.max_steps = max_steps
+ }
+
+ pub fn integration_parameters_mut(&mut self) -> &mut IntegrationParameters {
+ &mut self.physics.integration_parameters
+ }
+
+ pub fn physics_state_mut(&mut self) -> &mut PhysicsState {
+ &mut self.physics
+ }
+
+ pub fn set_world(&mut self, bodies: RigidBodySet, colliders: ColliderSet, joints: JointSet) {
+ self.set_world_with_gravity(bodies, colliders, joints, Vector::y() * -9.81)
+ }
+
+ pub fn set_world_with_gravity(
+ &mut self,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ joints: JointSet,
+ gravity: Vector<f32>,
+ ) {
+ // println!("Num bodies: {}", bodies.len());
+ // println!("Num joints: {}", joints.len());
+ self.physics.gravity = gravity;
+ self.physics.bodies = bodies;
+ self.physics.colliders = colliders;
+ self.physics.joints = joints;
+ self.physics.broad_phase = BroadPhase::new();
+ self.physics.narrow_phase = NarrowPhase::new();
+ self.time = 0.0;
+ self.state.timestep_id = 0;
+ self.physics.query_pipeline = QueryPipeline::new();
+ self.physics.pipeline = PhysicsPipeline::new();
+ self.physics.pipeline.counters.enable();
+ }
+
+ pub fn add_plugin(&mut self, plugin: impl HarnessPlugin + 'static) {
+ self.plugins.push(Box::new(plugin));
+ }
+
+ pub fn add_callback<
+ F: FnMut(&mut PhysicsState, &PhysicsEvents, &HarnessState, f32) + 'static,
+ >(
+ &mut self,
+ callback: F,
+ ) {
+ self.callbacks.push(Box::new(callback));
+ }
+
+ pub fn step(&mut self) {
+ #[cfg(feature = "parallel")]
+ {
+ let physics = &mut self.physics;
+ let event_handler = &self.event_handler;
+ self.state.thread_pool.install(|| {
+ physics.pipeline.step(
+ &physics.gravity,
+ &physics.integration_parameters,
+ &mut physics.broad_phase,
+ &mut physics.narrow_phase,
+ &mut physics.bodies,
+ &mut physics.colliders,
+ &mut physics.joints,
+ None,
+ None,
+ event_handler,
+ );
+ });
+ }
+
+ #[cfg(not(feature = "parallel"))]
+ self.physics.pipeline.step(
+ &self.physics.gravity,
+ &self.physics.integration_parameters,
+ &mut self.physics.broad_phase,
+ &mut self.physics.narrow_phase,
+ &mut self.physics.bodies,
+ &mut self.physics.colliders,
+ &mut self.physics.joints,
+ None,
+ None,
+ &self.event_handler,
+ );
+
+ self.physics
+ .query_pipeline
+ .update(&self.physics.bodies, &self.physics.colliders);
+
+ for plugin in &mut self.plugins {
+ plugin.step(&mut self.physics)
+ }
+
+ for f in &mut self.callbacks {
+ f(&mut self.physics, &self.events, &self.state, self.time)
+ }
+
+ for plugin in &mut self.plugins {
+ plugin.run_callbacks(&mut self.physics, &self.events, &self.state, self.time)
+ }
+
+ self.events.poll_all();
+
+ self.time += self.physics.integration_parameters.dt();
+ }
+
+ pub fn run(&mut self) {
+ for _ in 0..self.max_steps {
+ self.step();
+ self.state.timestep_id += 1;
+ }
+ }
+}
diff --git a/src_testbed/harness/plugin.rs b/src_testbed/harness/plugin.rs
new file mode 100644
index 0000000..078219e
--- /dev/null
+++ b/src_testbed/harness/plugin.rs
@@ -0,0 +1,15 @@
+use crate::harness::HarnessState;
+use crate::physics::PhysicsEvents;
+use crate::PhysicsState;
+
+pub trait HarnessPlugin {
+ fn run_callbacks(
+ &mut self,
+ physics: &mut PhysicsState,
+ events: &PhysicsEvents,
+ harness_state: &HarnessState,
+ t: f32,
+ );
+ fn step(&mut self, physics: &mut PhysicsState);
+ fn profiling_string(&self) -> String;
+}
diff --git a/src_testbed/lib.rs b/src_testbed/lib.rs
index e7475f0..5358e7c 100644
--- a/src_testbed/lib.rs
+++ b/src_testbed/lib.rs
@@ -22,16 +22,19 @@ extern crate bitflags;
extern crate log;
pub use crate::engine::GraphicsManager;
+pub use crate::harness::plugin::HarnessPlugin;
+pub use crate::physics::PhysicsState;
pub use crate::plugin::TestbedPlugin;
pub use crate::testbed::Testbed;
#[cfg(all(feature = "dim2", feature = "other-backends"))]
mod box2d_backend;
mod engine;
+pub mod harness;
#[cfg(feature = "other-backends")]
mod nphysics_backend;
pub mod objects;
-mod physics;
+pub mod physics;
#[cfg(all(feature = "dim3", feature = "other-backends"))]
mod physx_backend;
mod plugin;