First public release of Rapier.

This commit is contained in:
Sébastien Crozet
2020-08-25 22:10:25 +02:00
commit 754a48b7ff
175 changed files with 32819 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
use crate::counters::Timer;
use std::fmt::{Display, Formatter, Result};
/// Performance counters related to continuous collision detection (CCD).
#[derive(Default, Clone, Copy)]
pub struct CCDCounters {
/// The number of substeps actually performed by the CCD resolution.
pub num_substeps: usize,
/// The total time spent for TOI computation in the CCD resolution.
pub toi_computation_time: Timer,
/// The total time spent for force computation and integration in the CCD resolution.
pub solver_time: Timer,
/// The total time spent by the broad-phase in the CCD resolution.
pub broad_phase_time: Timer,
/// The total time spent by the narrow-phase in the CCD resolution.
pub narrow_phase_time: Timer,
}
impl CCDCounters {
/// Creates a new counter initialized to zero.
pub fn new() -> Self {
CCDCounters {
num_substeps: 0,
toi_computation_time: Timer::new(),
solver_time: Timer::new(),
broad_phase_time: Timer::new(),
narrow_phase_time: Timer::new(),
}
}
/// Resets this counter to 0.
pub fn reset(&mut self) {
self.num_substeps = 0;
self.toi_computation_time.reset();
self.solver_time.reset();
self.broad_phase_time.reset();
self.narrow_phase_time.reset();
}
}
impl Display for CCDCounters {
fn fmt(&self, f: &mut Formatter) -> Result {
writeln!(f, "Number of substeps: {}", self.num_substeps)?;
writeln!(f, "TOI computation time: {}", self.toi_computation_time)?;
writeln!(f, "Constraints solver time: {}", self.solver_time)?;
writeln!(f, "Broad-phase time: {}", self.broad_phase_time)?;
writeln!(f, "Narrow-phase time: {}", self.narrow_phase_time)
}
}

View File

@@ -0,0 +1,32 @@
use crate::counters::Timer;
use std::fmt::{Display, Formatter, Result};
/// Performance counters related to collision detection.
#[derive(Default, Clone, Copy)]
pub struct CollisionDetectionCounters {
/// Number of contact pairs detected.
pub ncontact_pairs: usize,
/// Time spent for the broad-phase of the collision detection.
pub broad_phase_time: Timer,
/// Time spent for the narrow-phase of the collision detection.
pub narrow_phase_time: Timer,
}
impl CollisionDetectionCounters {
/// Creates a new counter initialized to zero.
pub fn new() -> Self {
CollisionDetectionCounters {
ncontact_pairs: 0,
broad_phase_time: Timer::new(),
narrow_phase_time: Timer::new(),
}
}
}
impl Display for CollisionDetectionCounters {
fn fmt(&self, f: &mut Formatter) -> Result {
writeln!(f, "Number of contact pairs: {}", self.ncontact_pairs)?;
writeln!(f, "Broad-phase time: {}", self.broad_phase_time)?;
writeln!(f, "Narrow-phase time: {}", self.narrow_phase_time)
}
}

225
src/counters/mod.rs Normal file
View File

@@ -0,0 +1,225 @@
//! Counters for benchmarking various parts of the physics engine.
use std::fmt::{Display, Formatter, Result};
pub use self::ccd_counters::CCDCounters;
pub use self::collision_detection_counters::CollisionDetectionCounters;
pub use self::solver_counters::SolverCounters;
pub use self::stages_counters::StagesCounters;
pub use self::timer::Timer;
mod ccd_counters;
mod collision_detection_counters;
mod solver_counters;
mod stages_counters;
mod timer;
/// Aggregation of all the performances counters tracked by nphysics.
#[derive(Clone, Copy)]
pub struct Counters {
/// Whether thi counter is enabled or not.
pub enabled: bool,
/// Timer for a whole timestep.
pub step_time: Timer,
/// Timer used for debugging.
pub custom: Timer,
/// Counters of every satge of one time step.
pub stages: StagesCounters,
/// Counters of the collision-detection stage.
pub cd: CollisionDetectionCounters,
/// Counters of the constraints resolution and force computation stage.
pub solver: SolverCounters,
/// Counters for the CCD resolution stage.
pub ccd: CCDCounters,
}
impl Counters {
/// Create a new set of counters initialized to wero.
pub fn new(enabled: bool) -> Self {
Counters {
enabled,
step_time: Timer::new(),
custom: Timer::new(),
stages: StagesCounters::new(),
cd: CollisionDetectionCounters::new(),
solver: SolverCounters::new(),
ccd: CCDCounters::new(),
}
}
/// Enable all the counters.
pub fn enable(&mut self) {
self.enabled = true;
}
/// Return `true` if the counters are enabled.
pub fn enabled(&self) -> bool {
self.enabled
}
/// Disable all the counters.
pub fn disable(&mut self) {
self.enabled = false;
}
/// Notify that the time-step has started.
pub fn step_started(&mut self) {
if self.enabled {
self.step_time.start();
}
}
/// Notfy that the time-step has finished.
pub fn step_completed(&mut self) {
if self.enabled {
self.step_time.pause();
}
}
/// Total time spent for one of the physics engine.
pub fn step_time(&self) -> f64 {
self.step_time.time()
}
/// Notify that the custom operation has started.
pub fn custom_started(&mut self) {
if self.enabled {
self.custom.start();
}
}
/// Notfy that the custom operation has finished.
pub fn custom_completed(&mut self) {
if self.enabled {
self.custom.pause();
}
}
/// Total time of a custom event.
pub fn custom_time(&self) -> f64 {
self.custom.time()
}
/// Set the number of constraints generated.
pub fn set_nconstraints(&mut self, n: usize) {
self.solver.nconstraints = n;
}
/// Set the number of contacts generated.
pub fn set_ncontacts(&mut self, n: usize) {
self.solver.ncontacts = n;
}
/// Set the number of contact pairs generated.
pub fn set_ncontact_pairs(&mut self, n: usize) {
self.cd.ncontact_pairs = n;
}
}
macro_rules! measure_method {
($started:ident, $stopped:ident, $time:ident, $info:ident. $timer:ident) => {
impl Counters {
/// Start this timer.
pub fn $started(&mut self) {
if self.enabled {
self.$info.$timer.start()
}
}
/// Stop this timer.
pub fn $stopped(&mut self) {
if self.enabled {
self.$info.$timer.pause()
}
}
/// Gets the time elapsed for this timer.
pub fn $time(&self) -> f64 {
if self.enabled {
self.$info.$timer.time()
} else {
0.0
}
}
}
};
}
measure_method!(
update_started,
update_completed,
update_time,
stages.update_time
);
measure_method!(
collision_detection_started,
collision_detection_completed,
collision_detection_time,
stages.collision_detection_time
);
measure_method!(
island_construction_started,
island_construction_completed,
island_construction_time,
stages.island_construction_time
);
measure_method!(
solver_started,
solver_completed,
solver_time,
stages.solver_time
);
measure_method!(ccd_started, ccd_completed, ccd_time, stages.ccd_time);
measure_method!(
assembly_started,
assembly_completed,
assembly_time,
solver.velocity_assembly_time
);
measure_method!(
velocity_resolution_started,
velocity_resolution_completed,
velocity_resolution_time,
solver.velocity_resolution_time
);
measure_method!(
velocity_update_started,
velocity_update_completed,
velocity_update_time,
solver.velocity_update_time
);
measure_method!(
position_resolution_started,
position_resolution_completed,
position_resolution_time,
solver.position_resolution_time
);
measure_method!(
broad_phase_started,
broad_phase_completed,
broad_phase_time,
cd.broad_phase_time
);
measure_method!(
narrow_phase_started,
narrow_phase_completed,
narrow_phase_time,
cd.narrow_phase_time
);
impl Display for Counters {
fn fmt(&self, f: &mut Formatter) -> Result {
writeln!(f, "Total timestep time: {}", self.step_time)?;
self.stages.fmt(f)?;
self.cd.fmt(f)?;
self.solver.fmt(f)?;
writeln!(f, "Custom timer: {}", self.custom)
}
}
impl Default for Counters {
fn default() -> Self {
Self::new(false)
}
}

View File

@@ -0,0 +1,67 @@
use crate::counters::Timer;
use std::fmt::{Display, Formatter, Result};
/// Performance counters related to constraints resolution.
#[derive(Default, Clone, Copy)]
pub struct SolverCounters {
/// Number of constraints generated.
pub nconstraints: usize,
/// Number of contacts found.
pub ncontacts: usize,
/// Time spent for the resolution of the constraints (force computation).
pub velocity_resolution_time: Timer,
/// Time spent for the assembly of all the velocity constraints.
pub velocity_assembly_time: Timer,
/// Time spent for the update of the velocity of the bodies.
pub velocity_update_time: Timer,
/// Time spent for the assembly of all the position constraints.
pub position_assembly_time: Timer,
/// Time spent for the update of the position of the bodies.
pub position_resolution_time: Timer,
}
impl SolverCounters {
/// Creates a new counter initialized to zero.
pub fn new() -> Self {
SolverCounters {
nconstraints: 0,
ncontacts: 0,
velocity_assembly_time: Timer::new(),
velocity_resolution_time: Timer::new(),
velocity_update_time: Timer::new(),
position_assembly_time: Timer::new(),
position_resolution_time: Timer::new(),
}
}
/// Reset all the counters to zero.
pub fn reset(&mut self) {
self.nconstraints = 0;
self.ncontacts = 0;
self.velocity_resolution_time.reset();
self.velocity_assembly_time.reset();
self.velocity_update_time.reset();
self.position_assembly_time.reset();
self.position_resolution_time.reset();
}
}
impl Display for SolverCounters {
fn fmt(&self, f: &mut Formatter) -> Result {
writeln!(f, "Number of contacts: {}", self.ncontacts)?;
writeln!(f, "Number of constraints: {}", self.nconstraints)?;
writeln!(f, "Velocity assembly time: {}", self.velocity_assembly_time)?;
writeln!(
f,
"Velocity resolution time: {}",
self.velocity_resolution_time
)?;
writeln!(f, "Velocity update time: {}", self.velocity_update_time)?;
writeln!(f, "Position assembly time: {}", self.position_assembly_time)?;
writeln!(
f,
"Position resolution time: {}",
self.position_resolution_time
)
}
}

View File

@@ -0,0 +1,48 @@
use crate::counters::Timer;
use std::fmt::{Display, Formatter, Result};
/// Performance counters related to each stage of the time step.
#[derive(Default, Clone, Copy)]
pub struct StagesCounters {
/// Time spent for updating the kinematic and dynamics of every body.
pub update_time: Timer,
/// Total time spent for the collision detection (including both broad- and narrow- phases).
pub collision_detection_time: Timer,
/// Time spent for the computation of collision island and body activation/deactivation (sleeping).
pub island_construction_time: Timer,
/// Total time spent for the constraints resolution and position update.t
pub solver_time: Timer,
/// Total time spent for CCD and CCD resolution.
pub ccd_time: Timer,
}
impl StagesCounters {
/// Create a new counter intialized to zero.
pub fn new() -> Self {
StagesCounters {
update_time: Timer::new(),
collision_detection_time: Timer::new(),
island_construction_time: Timer::new(),
solver_time: Timer::new(),
ccd_time: Timer::new(),
}
}
}
impl Display for StagesCounters {
fn fmt(&self, f: &mut Formatter) -> Result {
writeln!(f, "Update time: {}", self.update_time)?;
writeln!(
f,
"Collision detection time: {}",
self.collision_detection_time
)?;
writeln!(
f,
"Island construction time: {}",
self.island_construction_time
)?;
writeln!(f, "Solver time: {}", self.solver_time)?;
writeln!(f, "CCD time: {}", self.ccd_time)
}
}

53
src/counters/timer.rs Normal file
View File

@@ -0,0 +1,53 @@
use std::fmt::{Display, Error, Formatter};
/// A timer.
#[derive(Copy, Clone, Debug, Default)]
pub struct Timer {
time: f64,
start: Option<f64>,
}
impl Timer {
/// Creates a new timer initialized to zero and not started.
pub fn new() -> Self {
Timer {
time: 0.0,
start: None,
}
}
/// Resets the timer to 0.
pub fn reset(&mut self) {
self.time = 0.0
}
/// Start the timer.
pub fn start(&mut self) {
self.time = 0.0;
self.start = Some(instant::now());
}
/// Pause the timer.
pub fn pause(&mut self) {
if let Some(start) = self.start {
self.time += instant::now() - start;
}
self.start = None;
}
/// Resume the timer.
pub fn resume(&mut self) {
self.start = Some(instant::now());
}
/// The measured time between the last `.start()` and `.pause()` calls.
pub fn time(&self) -> f64 {
self.time
}
}
impl Display for Timer {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}s", self.time)
}
}