Merge pull request #20 from dimforge/benchbot

Split benchmarks from examples
This commit is contained in:
Sébastien Crozet
2020-09-28 10:58:35 +02:00
committed by GitHub
53 changed files with 1170 additions and 195 deletions

View File

@@ -1,12 +1,12 @@
[workspace] [workspace]
members = [ "build/rapier2d", "build/rapier_testbed2d", "examples2d", members = [ "build/rapier2d", "build/rapier_testbed2d", "examples2d", "benchmarks2d",
"build/rapier3d", "build/rapier_testbed3d", "examples3d" ] "build/rapier3d", "build/rapier_testbed3d", "examples3d", "benchmarks3d" ]
[patch.crates-io] [patch.crates-io]
#wrapped2d = { git = "https://github.com/Bastacyclop/rust_box2d.git" } #wrapped2d = { git = "https://github.com/Bastacyclop/rust_box2d.git" }
[profile.release] [profile.release]
debug = false #debug = true
codegen-units = 1 codegen-units = 1
#opt-level = 1 #opt-level = 1
#lto = true #lto = true

27
benchmarks2d/Cargo.toml Normal file
View File

@@ -0,0 +1,27 @@
[package]
name = "rapier-benchmarks-2d"
version = "0.1.0"
authors = [ "Sébastien Crozet <developer@crozet.re>" ]
edition = "2018"
[features]
parallel = [ "rapier2d/parallel", "rapier_testbed2d/parallel" ]
simd-stable = [ "rapier2d/simd-stable" ]
simd-nightly = [ "rapier2d/simd-nightly" ]
other-backends = [ "rapier_testbed2d/other-backends" ]
enhanced-determinism = [ "rapier2d/enhanced-determinism" ]
[dependencies]
rand = "0.7"
Inflector = "0.11"
nalgebra = "0.22"
[dependencies.rapier_testbed2d]
path = "../build/rapier_testbed2d"
[dependencies.rapier2d]
path = "../build/rapier2d"
[[bin]]
name = "all_benchmarks2"
path = "./all_benchmarks2.rs"

View File

@@ -0,0 +1,82 @@
#![allow(dead_code)]
extern crate nalgebra as na;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
use inflector::Inflector;
use rapier_testbed2d::Testbed;
use std::cmp::Ordering;
mod balls2;
mod boxes2;
mod capsules2;
mod heightfield2;
mod joint_ball2;
mod joint_fixed2;
mod joint_prismatic2;
mod pyramid2;
fn demo_name_from_command_line() -> Option<String> {
let mut args = std::env::args();
while let Some(arg) = args.next() {
if &arg[..] == "--example" {
return args.next();
}
}
None
}
#[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))]
fn demo_name_from_url() -> Option<String> {
None
// let window = stdweb::web::window();
// let hash = window.location()?.search().ok()?;
// Some(hash[1..].to_string())
}
#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
fn demo_name_from_url() -> Option<String> {
None
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
pub fn main() {
let demo = demo_name_from_command_line()
.or_else(|| demo_name_from_url())
.unwrap_or(String::new())
.to_camel_case();
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
("Balls", balls2::init_world),
("Boxes", boxes2::init_world),
("Capsules", capsules2::init_world),
("Heightfield", heightfield2::init_world),
("Pyramid", pyramid2::init_world),
("(Stress test) joint ball", joint_ball2::init_world),
("(Stress test) joint fixed", joint_fixed2::init_world),
(
"(Stress test) joint prismatic",
joint_prismatic2::init_world,
),
];
// Lexicographic sort, with stress tests moved at the end of the list.
builders.sort_by(|a, b| match (a.0.starts_with("("), b.0.starts_with("(")) {
(true, true) | (false, false) => a.0.cmp(b.0),
(true, false) => Ordering::Greater,
(false, true) => Ordering::Less,
});
let i = builders
.iter()
.position(|builder| builder.0.to_camel_case().as_str() == demo.as_str())
.unwrap_or(0);
let testbed = Testbed::from_builders(i, builders);
testbed.run()
}

View File

@@ -50,7 +50,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new(status).translation(x, y).build(); let rigid_body = RigidBodyBuilder::new(status).translation(x, y).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }

View File

@@ -55,7 +55,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }

View File

@@ -56,9 +56,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::capsule_y(rad * 1.5, rad) let collider = ColliderBuilder::capsule_y(rad * 1.5, rad).build();
.density(1.0)
.build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }

View File

@@ -0,0 +1,72 @@
use na::{DVector, Point2, Vector2};
use rapier2d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier2d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed2d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Ground
*/
let ground_size = Vector2::new(50.0, 1.0);
let nsubdivs = 2000;
let heights = DVector::from_fn(nsubdivs + 1, |i, _| {
if i == 0 || i == nsubdivs {
80.0
} else {
(i as f32 * ground_size.x / (nsubdivs as f32)).cos() * 2.0
}
});
let rigid_body = RigidBodyBuilder::new_static().build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::heightfield(heights, ground_size).build();
colliders.insert(collider, handle, &mut bodies);
/*
* Create the cubes
*/
let num = 26;
let rad = 0.5;
let shift = rad * 2.0;
let centerx = shift * (num / 2) as f32;
let centery = shift / 2.0;
for i in 0..num {
for j in 0usize..num * 5 {
let x = i as f32 * shift - centerx;
let y = j as f32 * shift + centery + 3.0;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build();
let handle = bodies.insert(rigid_body);
if j % 2 == 0 {
let collider = ColliderBuilder::cuboid(rad, rad).build();
colliders.insert(collider, handle, &mut bodies);
} else {
let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, handle, &mut bodies);
}
}
}
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point2::new(0.0, 50.0), 10.0);
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Heightfield", init_world)]);
testbed.run()
}

View File

@@ -37,7 +37,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(fk * shift, -fi * shift) .translation(fk * shift, -fi * shift)
.build(); .build();
let child_handle = bodies.insert(rigid_body); let child_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, child_handle, &mut bodies); colliders.insert(collider, child_handle, &mut bodies);
// Vertical joint. // Vertical joint.

View File

@@ -42,7 +42,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(x + fk * shift, y - fi * shift) .translation(x + fk * shift, y - fi * shift)
.build(); .build();
let child_handle = bodies.insert(rigid_body); let child_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, child_handle, &mut bodies); colliders.insert(collider, child_handle, &mut bodies);
// Vertical joint. // Vertical joint.

60
benchmarks2d/pyramid2.rs Normal file
View File

@@ -0,0 +1,60 @@
use na::Point2;
use rapier2d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier2d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed2d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Ground
*/
let ground_size = 100.0;
let ground_thickness = 1.0;
let rigid_body = RigidBodyBuilder::new_static().build();
let ground_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(ground_size, ground_thickness).build();
colliders.insert(collider, ground_handle, &mut bodies);
/*
* Create the cubes
*/
let num = 100;
let rad = 0.5;
let shift = rad * 2.0;
let centerx = shift * (num as f32) / 2.0;
let centery = shift / 2.0 + ground_thickness + rad * 1.5;
for i in 0usize..num {
for j in i..num {
let fj = j as f32;
let fi = i as f32;
let x = (fi * shift / 2.0) + (fj - fi) * shift - centerx;
let y = fi * shift + centery;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad).build();
colliders.insert(collider, handle, &mut bodies);
}
}
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point2::new(0.0, 2.5), 5.0);
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Balls", init_world)]);
testbed.run()
}

27
benchmarks3d/Cargo.toml Normal file
View File

@@ -0,0 +1,27 @@
[package]
name = "rapier-benchmarks-3d"
version = "0.1.0"
authors = [ "Sébastien Crozet <developer@crozet.re>" ]
edition = "2018"
[features]
parallel = [ "rapier3d/parallel", "rapier_testbed3d/parallel" ]
simd-stable = [ "rapier3d/simd-stable" ]
simd-nightly = [ "rapier3d/simd-nightly" ]
other-backends = [ "rapier_testbed3d/other-backends" ]
enhanced-determinism = [ "rapier3d/enhanced-determinism" ]
[dependencies]
rand = "0.7"
Inflector = "0.11"
nalgebra = "0.22"
[dependencies.rapier_testbed3d]
path = "../build/rapier_testbed3d"
[dependencies.rapier3d]
path = "../build/rapier3d"
[[bin]]
name = "all_benchmarks3"
path = "all_benchmarks3.rs"

View File

@@ -0,0 +1,91 @@
#![allow(dead_code)]
extern crate nalgebra as na;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
use inflector::Inflector;
use rapier_testbed3d::Testbed;
use std::cmp::Ordering;
mod balls3;
mod boxes3;
mod capsules3;
mod compound3;
mod heightfield3;
mod joint_ball3;
mod joint_fixed3;
mod joint_prismatic3;
mod joint_revolute3;
mod keva3;
mod pyramid3;
mod stacks3;
mod trimesh3;
enum Command {
Run(String),
List,
RunAll,
}
fn parse_command_line() -> Command {
let mut args = std::env::args();
while let Some(arg) = args.next() {
if &arg[..] == "--example" {
return Command::Run(args.next().unwrap_or(String::new()));
} else if &arg[..] == "--list" {
return Command::List;
}
}
Command::RunAll
}
pub fn main() {
let command = parse_command_line();
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
("Balls", balls3::init_world),
("Boxes", boxes3::init_world),
("Capsules", capsules3::init_world),
("Compound", compound3::init_world),
("Heightfield", heightfield3::init_world),
("Stacks", stacks3::init_world),
("Pyramid", pyramid3::init_world),
("Trimesh", trimesh3::init_world),
("Joint ball", joint_ball3::init_world),
("Joint fixed", joint_fixed3::init_world),
("Joint revolute", joint_revolute3::init_world),
("Joint prismatic", joint_prismatic3::init_world),
("Keva tower", keva3::init_world),
];
// Lexicographic sort, with stress tests moved at the end of the list.
builders.sort_by(|a, b| match (a.0.starts_with("("), b.0.starts_with("(")) {
(true, true) | (false, false) => a.0.cmp(b.0),
(true, false) => Ordering::Greater,
(false, true) => Ordering::Less,
});
match command {
Command::Run(demo) => {
if let Some(i) = builders
.iter()
.position(|builder| builder.0.to_camel_case().as_str() == demo.as_str())
{
Testbed::from_builders(0, vec![builders[i]]).run()
} else {
eprintln!("Invalid example to run provided: '{}'", demo);
}
}
Command::RunAll => Testbed::from_builders(0, builders).run(),
Command::List => {
for builder in &builders {
println!("{}", builder.0.to_camel_case())
}
}
}
}

58
benchmarks3d/balls3.rs Normal file
View File

@@ -0,0 +1,58 @@
use na::Point3;
use rapier3d::dynamics::{BodyStatus, JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Create the balls
*/
let num = 20;
let rad = 1.0;
let shift = rad * 2.0 + 1.0;
let centerx = shift * (num as f32) / 2.0;
let centery = shift / 2.0;
let centerz = shift * (num as f32) / 2.0;
for i in 0..num {
for j in 0usize..num {
for k in 0..num {
let x = i as f32 * shift - centerx;
let y = j as f32 * shift + centery;
let z = k as f32 * shift - centerz;
let status = if j == 0 {
BodyStatus::Static
} else {
BodyStatus::Dynamic
};
let density = 0.477;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new(status).translation(x, y, z).build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(density).build();
colliders.insert(collider, handle, &mut bodies);
}
}
}
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin());
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Balls", init_world)]);
testbed.run()
}

View File

@@ -47,7 +47,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }

View File

@@ -48,7 +48,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::capsule_y(rad, rad).density(1.0).build(); let collider = ColliderBuilder::capsule_y(rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }

76
benchmarks3d/compound3.rs Normal file
View File

@@ -0,0 +1,76 @@
use na::Point3;
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Ground
*/
let ground_size = 200.1;
let ground_height = 0.1;
let rigid_body = RigidBodyBuilder::new_static()
.translation(0.0, -ground_height, 0.0)
.build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size).build();
colliders.insert(collider, handle, &mut bodies);
/*
* Create the cubes
*/
let num = 8;
let rad = 0.2;
let shift = rad * 4.0 + rad;
let centerx = shift * (num / 2) as f32;
let centery = shift / 2.0;
let centerz = shift * (num / 2) as f32;
let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5;
for j in 0usize..25 {
for i in 0..num {
for k in 0usize..num {
let x = i as f32 * shift * 5.0 - centerx + offset;
let y = j as f32 * (shift * 5.0) + centery + 3.0;
let z = k as f32 * shift * 2.0 - centerz + offset;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body);
let collider1 = ColliderBuilder::cuboid(rad * 10.0, rad, rad).build();
let collider2 = ColliderBuilder::cuboid(rad, rad * 10.0, rad)
.translation(rad * 10.0, rad * 10.0, 0.0)
.build();
let collider3 = ColliderBuilder::cuboid(rad, rad * 10.0, rad)
.translation(-rad * 10.0, rad * 10.0, 0.0)
.build();
colliders.insert(collider1, handle, &mut bodies);
colliders.insert(collider2, handle, &mut bodies);
colliders.insert(collider3, handle, &mut bodies);
}
}
offset -= 0.05 * rad * (num as f32 - 1.0);
}
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin());
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Boxes", init_world)]);
testbed.run()
}

View File

@@ -0,0 +1,78 @@
use na::{DMatrix, Point3, Vector3};
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Ground
*/
let ground_size = Vector3::new(200.0, 1.0, 200.0);
let nsubdivs = 20;
let heights = DMatrix::from_fn(nsubdivs + 1, nsubdivs + 1, |i, j| {
if i == 0 || i == nsubdivs || j == 0 || j == nsubdivs {
10.0
} else {
let x = i as f32 * ground_size.x / (nsubdivs as f32);
let z = j as f32 * ground_size.z / (nsubdivs as f32);
x.sin() + z.cos()
}
});
let rigid_body = RigidBodyBuilder::new_static().build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::heightfield(heights, ground_size).build();
colliders.insert(collider, handle, &mut bodies);
/*
* Create the cubes
*/
let num = 8;
let rad = 1.0;
let shift = rad * 2.0 + rad;
let centerx = shift * (num / 2) as f32;
let centery = shift / 2.0;
let centerz = shift * (num / 2) as f32;
for j in 0usize..47 {
for i in 0..num {
for k in 0usize..num {
let x = i as f32 * shift - centerx;
let y = j as f32 * shift + centery + 3.0;
let z = k as f32 * shift - centerz;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body);
if j % 2 == 0 {
let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
colliders.insert(collider, handle, &mut bodies);
} else {
let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, handle, &mut bodies);
}
}
}
}
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin());
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Boxes", init_world)]);
testbed.run()
}

View File

@@ -32,7 +32,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(fk * shift, 0.0, fi * shift) .translation(fk * shift, 0.0, fi * shift)
.build(); .build();
let child_handle = bodies.insert(rigid_body); let child_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, child_handle, &mut bodies); colliders.insert(collider, child_handle, &mut bodies);
// Vertical joint. // Vertical joint.

View File

@@ -45,7 +45,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(x + fk * shift, y, z + fi * shift) .translation(x + fk * shift, y, z + fi * shift)
.build(); .build();
let child_handle = bodies.insert(rigid_body); let child_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, child_handle, &mut bodies); colliders.insert(collider, child_handle, &mut bodies);
// Vertical joint. // Vertical joint.

View File

@@ -48,9 +48,7 @@ pub fn build_block(
) )
.build(); .build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(dim.x, dim.y, dim.z) let collider = ColliderBuilder::cuboid(dim.x, dim.y, dim.z).build();
.density(1.0)
.build();
colliders.insert(collider, handle, bodies); colliders.insert(collider, handle, bodies);
testbed.set_body_color(handle, color0); testbed.set_body_color(handle, color0);
@@ -73,9 +71,7 @@ pub fn build_block(
) )
.build(); .build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(dim.x, dim.y, dim.z) let collider = ColliderBuilder::cuboid(dim.x, dim.y, dim.z).build();
.density(1.0)
.build();
colliders.insert(collider, handle, bodies); colliders.insert(collider, handle, bodies);
testbed.set_body_color(handle, color0); testbed.set_body_color(handle, color0);
std::mem::swap(&mut color0, &mut color1); std::mem::swap(&mut color0, &mut color1);

View File

@@ -28,9 +28,7 @@ fn create_pyramid(
let rigid_body_handle = bodies.insert(rigid_body); let rigid_body_handle = bodies.insert(rigid_body);
let collider = let collider =
ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z) ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z).build();
.density(1.0)
.build();
colliders.insert(collider, rigid_body_handle, bodies); colliders.insert(collider, rigid_body_handle, bodies);
} }
} }

191
benchmarks3d/stacks3.rs Normal file
View File

@@ -0,0 +1,191 @@
use na::{Point3, Translation3, UnitQuaternion, Vector3};
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
fn create_tower_circle(
bodies: &mut RigidBodySet,
colliders: &mut ColliderSet,
offset: Vector3<f32>,
stack_height: usize,
nsubdivs: usize,
half_extents: Vector3<f32>,
) {
let ang_step = std::f32::consts::PI * 2.0 / nsubdivs as f32;
let radius = 1.3 * nsubdivs as f32 * half_extents.x / std::f32::consts::PI;
let shift = half_extents * 2.0;
for i in 0usize..stack_height {
for j in 0..nsubdivs {
let fj = j as f32;
let fi = i as f32;
let y = fi * shift.y;
let pos = Translation3::from(offset)
* UnitQuaternion::new(Vector3::y() * (fi / 2.0 + fj) * ang_step)
* Translation3::new(0.0, y, radius);
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().position(pos).build();
let handle = bodies.insert(rigid_body);
let collider =
ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z).build();
colliders.insert(collider, handle, bodies);
}
}
}
fn create_wall(
bodies: &mut RigidBodySet,
colliders: &mut ColliderSet,
offset: Vector3<f32>,
stack_height: usize,
half_extents: Vector3<f32>,
) {
let shift = half_extents * 2.0;
for i in 0usize..stack_height {
for j in i..stack_height {
let fj = j as f32;
let fi = i as f32;
let x = offset.x;
let y = fi * shift.y + offset.y;
let z = (fi * shift.z / 2.0) + (fj - fi) * shift.z + offset.z
- stack_height as f32 * half_extents.z;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body);
let collider =
ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z).build();
colliders.insert(collider, handle, bodies);
}
}
}
fn create_pyramid(
bodies: &mut RigidBodySet,
colliders: &mut ColliderSet,
offset: Vector3<f32>,
stack_height: usize,
half_extents: Vector3<f32>,
) {
let shift = half_extents * 2.0;
for i in 0usize..stack_height {
for j in i..stack_height {
for k in i..stack_height {
let fi = i as f32;
let fj = j as f32;
let fk = k as f32;
let x = (fi * shift.x / 2.0) + (fk - fi) * shift.x + offset.x
- stack_height as f32 * half_extents.x;
let y = fi * shift.y + offset.y;
let z = (fi * shift.z / 2.0) + (fj - fi) * shift.z + offset.z
- stack_height as f32 * half_extents.z;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body);
let collider =
ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z).build();
colliders.insert(collider, handle, bodies);
}
}
}
}
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Ground
*/
let ground_size = 200.0;
let ground_height = 0.1;
let rigid_body = RigidBodyBuilder::new_static()
.translation(0.0, -ground_height, 0.0)
.build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size).build();
colliders.insert(collider, handle, &mut bodies);
/*
* Create the cubes
*/
let cube_size = 1.0;
let hext = Vector3::repeat(cube_size);
let bottomy = cube_size * 50.0;
create_pyramid(
&mut bodies,
&mut colliders,
Vector3::new(-110.0, bottomy, 0.0),
12,
hext,
);
create_pyramid(
&mut bodies,
&mut colliders,
Vector3::new(-80.0, bottomy, 0.0),
12,
hext,
);
create_pyramid(
&mut bodies,
&mut colliders,
Vector3::new(-50.0, bottomy, 0.0),
12,
hext,
);
create_pyramid(
&mut bodies,
&mut colliders,
Vector3::new(-20.0, bottomy, 0.0),
12,
hext,
);
create_wall(
&mut bodies,
&mut colliders,
Vector3::new(-2.0, bottomy, 0.0),
12,
hext,
);
create_wall(
&mut bodies,
&mut colliders,
Vector3::new(4.0, bottomy, 0.0),
12,
hext,
);
create_wall(
&mut bodies,
&mut colliders,
Vector3::new(10.0, bottomy, 0.0),
12,
hext,
);
create_tower_circle(
&mut bodies,
&mut colliders,
Vector3::new(25.0, bottomy, 0.0),
8,
24,
hext,
);
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin());
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Boxes", init_world)]);
testbed.run()
}

88
benchmarks3d/trimesh3.rs Normal file
View File

@@ -0,0 +1,88 @@
use na::Point3;
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Ground
*/
let ground_size = 200.0f32;
let ground_height = 1.0;
let nsubdivs = 20;
let quad = rapier3d::ncollide::procedural::quad(ground_size, ground_size, nsubdivs, nsubdivs);
let indices = quad
.flat_indices()
.chunks(3)
.map(|is| Point3::new(is[0], is[2], is[1]))
.collect();
let mut vertices = quad.coords;
// ncollide generates a quad with `z` as the normal.
// so we switch z and y here and set a random altitude at each point.
for p in vertices.iter_mut() {
p.z = p.y;
p.y = (p.x.sin() + p.z.cos()) * ground_height;
if p.x.abs() == ground_size / 2.0 || p.z.abs() == ground_size / 2.0 {
p.y = 10.0;
}
}
let rigid_body = RigidBodyBuilder::new_static().build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::trimesh(vertices, indices).build();
colliders.insert(collider, handle, &mut bodies);
/*
* Create the cubes
*/
let num = 8;
let rad = 1.0;
let shift = rad * 2.0 + rad;
let centerx = shift * (num / 2) as f32;
let centery = shift / 2.0;
let centerz = shift * (num / 2) as f32;
for j in 0usize..47 {
for i in 0..num {
for k in 0usize..num {
let x = i as f32 * shift - centerx;
let y = j as f32 * shift + centery + 3.0;
let z = k as f32 * shift - centerz;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body);
if j % 2 == 0 {
let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
colliders.insert(collider, handle, &mut bodies);
} else {
let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, handle, &mut bodies);
}
}
}
}
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin());
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Boxes", init_world)]);
testbed.run()
}

View File

@@ -36,6 +36,7 @@ nphysics2d = { version = "0.17", optional = true }
crossbeam = "0.7" crossbeam = "0.7"
bincode = "1" bincode = "1"
flexbuffers = "0.1" flexbuffers = "0.1"
Inflector = "0.11"
md5 = "0.7" md5 = "0.7"

View File

@@ -39,6 +39,7 @@ bincode = "1"
flexbuffers = "0.1" flexbuffers = "0.1"
serde_cbor = "0.11" serde_cbor = "0.11"
md5 = "0.7" md5 = "0.7"
Inflector = "0.11"
serde = { version = "1", features = [ "derive" ] } serde = { version = "1", features = [ "derive" ] }
[dependencies.rapier3d] [dependencies.rapier3d]

View File

@@ -15,7 +15,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(0.0, 10.0) .translation(0.0, 10.0)
.build(); .build();
let handle = physics.bodies.insert(rigid_body); let handle = physics.bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad).build();
physics physics
.colliders .colliders
.insert(collider, handle, &mut physics.bodies); .insert(collider, handle, &mut physics.bodies);

View File

@@ -11,18 +11,12 @@ use rapier_testbed2d::Testbed;
use std::cmp::Ordering; use std::cmp::Ordering;
mod add_remove2; mod add_remove2;
mod balls2;
mod boxes2;
mod capsules2;
mod debug_box_ball2; mod debug_box_ball2;
mod heightfield2; mod heightfield2;
mod joints2; mod joints2;
mod kinematic2; mod platform2;
mod pyramid2; mod pyramid2;
mod sensor2; mod sensor2;
mod stress_joint_ball2;
mod stress_joint_fixed2;
mod stress_joint_prismatic2;
fn demo_name_from_command_line() -> Option<String> { fn demo_name_from_command_line() -> Option<String> {
let mut args = std::env::args(); let mut args = std::env::args();
@@ -58,21 +52,12 @@ pub fn main() {
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![ let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
("Add remove", add_remove2::init_world), ("Add remove", add_remove2::init_world),
("Balls", balls2::init_world),
("Boxes", boxes2::init_world),
("Capsules", capsules2::init_world),
("Heightfield", heightfield2::init_world), ("Heightfield", heightfield2::init_world),
("Joints", joints2::init_world), ("Joints", joints2::init_world),
("Kinematic", kinematic2::init_world), ("Platform", platform2::init_world),
("Pyramid", pyramid2::init_world), ("Pyramid", pyramid2::init_world),
("Sensor", sensor2::init_world), ("Sensor", sensor2::init_world),
("(Debug) box ball", debug_box_ball2::init_world), ("(Debug) box ball", debug_box_ball2::init_world),
("(Stress test) joint ball", stress_joint_ball2::init_world),
("(Stress test) joint fixed", stress_joint_fixed2::init_world),
(
"(Stress test) joint prismatic",
stress_joint_prismatic2::init_world,
),
]; ];
// Lexicographic sort, with stress tests moved at the end of the list. // Lexicographic sort, with stress tests moved at the end of the list.

View File

@@ -28,7 +28,7 @@ pub fn init_world(testbed: &mut Testbed) {
.can_sleep(false) .can_sleep(false)
.build(); .build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
/* /*

View File

@@ -19,7 +19,7 @@ pub fn init_world(testbed: &mut Testbed) {
let heights = DVector::from_fn(nsubdivs + 1, |i, _| { let heights = DVector::from_fn(nsubdivs + 1, |i, _| {
if i == 0 || i == nsubdivs { if i == 0 || i == nsubdivs {
80.0 8.0
} else { } else {
(i as f32 * ground_size.x / (nsubdivs as f32)).cos() * 2.0 (i as f32 * ground_size.x / (nsubdivs as f32)).cos() * 2.0
} }
@@ -33,7 +33,7 @@ pub fn init_world(testbed: &mut Testbed) {
/* /*
* Create the cubes * Create the cubes
*/ */
let num = 26; let num = 20;
let rad = 0.5; let rad = 0.5;
let shift = rad * 2.0; let shift = rad * 2.0;
@@ -41,7 +41,7 @@ pub fn init_world(testbed: &mut Testbed) {
let centery = shift / 2.0; let centery = shift / 2.0;
for i in 0..num { for i in 0..num {
for j in 0usize..num * 5 { for j in 0usize..num {
let x = i as f32 * shift - centerx; let x = i as f32 * shift - centerx;
let y = j as f32 * shift + centery + 3.0; let y = j as f32 * shift + centery + 3.0;
@@ -50,10 +50,10 @@ pub fn init_world(testbed: &mut Testbed) {
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
if j % 2 == 0 { if j % 2 == 0 {
let collider = ColliderBuilder::cuboid(rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} else { } else {
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }
@@ -63,7 +63,7 @@ pub fn init_world(testbed: &mut Testbed) {
* Set up the testbed. * Set up the testbed.
*/ */
testbed.set_world(bodies, colliders, joints); testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point2::new(0.0, 50.0), 10.0); testbed.look_at(Point2::new(0.0, 0.0), 10.0);
} }
fn main() { fn main() {

View File

@@ -19,8 +19,8 @@ pub fn init_world(testbed: &mut Testbed) {
// in order to be able to compare rapier with Box2D, // in order to be able to compare rapier with Box2D,
// we set it to 0.4. // we set it to 0.4.
let rad = 0.4; let rad = 0.4;
let numi = 100; // Num vertical nodes. let numi = 10; // Num vertical nodes.
let numk = 100; // Num horizontal nodes. let numk = 10; // Num horizontal nodes.
let shift = 1.0; let shift = 1.0;
let mut body_handles = Vec::new(); let mut body_handles = Vec::new();
@@ -30,7 +30,7 @@ pub fn init_world(testbed: &mut Testbed) {
let fk = k as f32; let fk = k as f32;
let fi = i as f32; let fi = i as f32;
let status = if i == 0 && (k % 4 == 0 || k == numk - 1) { let status = if i == 0 && k == 0 {
BodyStatus::Static BodyStatus::Static
} else { } else {
BodyStatus::Dynamic BodyStatus::Dynamic
@@ -40,7 +40,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(fk * shift, -fi * shift) .translation(fk * shift, -fi * shift)
.build(); .build();
let child_handle = bodies.insert(rigid_body); let child_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, child_handle, &mut bodies); colliders.insert(collider, child_handle, &mut bodies);
// Vertical joint. // Vertical joint.
@@ -66,7 +66,7 @@ pub fn init_world(testbed: &mut Testbed) {
* Set up the testbed. * Set up the testbed.
*/ */
testbed.set_world(bodies, colliders, joints); testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point2::new(numk as f32 * rad, numi as f32 * -rad), 5.0); testbed.look_at(Point2::new(numk as f32 * rad, numi as f32 * -rad), 20.0);
} }
fn main() { fn main() {

View File

@@ -35,14 +35,14 @@ pub fn init_world(testbed: &mut Testbed) {
let centery = shift / 2.0 + 3.04; let centery = shift / 2.0 + 3.04;
for i in 0usize..num { for i in 0usize..num {
for j in 0usize..num * 50 { for j in 0usize..num {
let x = i as f32 * shift - centerx; let x = i as f32 * shift - centerx;
let y = j as f32 * shift + centery; let y = j as f32 * shift + centery;
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }
@@ -54,9 +54,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(-10.0 * rad, 1.5 + 0.8) .translation(-10.0 * rad, 1.5 + 0.8)
.build(); .build();
let platform_handle = bodies.insert(platform_body); let platform_handle = bodies.insert(platform_body);
let collider = ColliderBuilder::cuboid(rad * 10.0, rad) let collider = ColliderBuilder::cuboid(rad * 10.0, rad).build();
.density(1.0)
.build();
colliders.insert(collider, platform_handle, &mut bodies); colliders.insert(collider, platform_handle, &mut bodies);
/* /*

View File

@@ -14,7 +14,7 @@ pub fn init_world(testbed: &mut Testbed) {
/* /*
* Ground * Ground
*/ */
let ground_size = 100.0; let ground_size = 10.0;
let ground_thickness = 1.0; let ground_thickness = 1.0;
let rigid_body = RigidBodyBuilder::new_static().build(); let rigid_body = RigidBodyBuilder::new_static().build();
@@ -25,7 +25,7 @@ pub fn init_world(testbed: &mut Testbed) {
/* /*
* Create the cubes * Create the cubes
*/ */
let num = 100; let num = 10;
let rad = 0.5; let rad = 0.5;
let shift = rad * 2.0; let shift = rad * 2.0;
@@ -42,7 +42,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }
@@ -51,7 +51,7 @@ pub fn init_world(testbed: &mut Testbed) {
* Set up the testbed. * Set up the testbed.
*/ */
testbed.set_world(bodies, colliders, joints); testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point2::new(0.0, 2.5), 5.0); testbed.look_at(Point2::new(0.0, 2.5), 20.0);
} }
fn main() { fn main() {

View File

@@ -40,7 +40,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
testbed.set_body_color(handle, Point3::new(0.5, 0.5, 1.0)); testbed.set_body_color(handle, Point3::new(0.5, 0.5, 1.0));
@@ -58,7 +58,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Solid cube attached to the sensor which // Solid cube attached to the sensor which
// other colliders can touch. // other colliders can touch.
let collider = ColliderBuilder::cuboid(rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad).build();
colliders.insert(collider, sensor_handle, &mut bodies); colliders.insert(collider, sensor_handle, &mut bodies);
// We create a collider desc without density because we don't // We create a collider desc without density because we don't

View File

@@ -15,7 +15,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(0.0, 10.0, 0.0) .translation(0.0, 10.0, 0.0)
.build(); .build();
let handle = physics.bodies.insert(rigid_body); let handle = physics.bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
physics physics
.colliders .colliders
.insert(collider, handle, &mut physics.bodies); .insert(collider, handle, &mut physics.bodies);

View File

@@ -11,24 +11,17 @@ use rapier_testbed3d::Testbed;
use std::cmp::Ordering; use std::cmp::Ordering;
mod add_remove3; mod add_remove3;
mod balls3;
mod boxes3;
mod capsules3;
mod compound3; mod compound3;
mod debug_boxes3; mod debug_boxes3;
mod debug_triangle3; mod debug_triangle3;
mod domino3; mod domino3;
mod heightfield3; mod heightfield3;
mod joints3; mod joints3;
mod kinematic3; mod keva3;
mod pyramid3; mod platform3;
mod primitives3;
mod sensor3; mod sensor3;
mod stacks3; mod stacks3;
mod stress_joint_ball3;
mod stress_joint_fixed3;
mod stress_joint_prismatic3;
mod stress_joint_revolute3;
mod stress_keva3;
mod trimesh3; mod trimesh3;
fn demo_name_from_command_line() -> Option<String> { fn demo_name_from_command_line() -> Option<String> {
@@ -69,31 +62,18 @@ pub fn main() {
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![ let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
("Add remove", add_remove3::init_world), ("Add remove", add_remove3::init_world),
("Balls", balls3::init_world), ("Primitives", primitives3::init_world),
("Boxes", boxes3::init_world),
("Capsules", capsules3::init_world),
("Compound", compound3::init_world), ("Compound", compound3::init_world),
("Domino", domino3::init_world), ("Domino", domino3::init_world),
("Heightfield", heightfield3::init_world), ("Heightfield", heightfield3::init_world),
("Joints", joints3::init_world), ("Joints", joints3::init_world),
("Kinematic", kinematic3::init_world), ("Platform", platform3::init_world),
("Stacks", stacks3::init_world), ("Stacks", stacks3::init_world),
("Pyramid", pyramid3::init_world),
("Sensor", sensor3::init_world), ("Sensor", sensor3::init_world),
("Trimesh", trimesh3::init_world), ("Trimesh", trimesh3::init_world),
("Keva tower", keva3::init_world),
("(Debug) boxes", debug_boxes3::init_world), ("(Debug) boxes", debug_boxes3::init_world),
("(Debug) triangle", debug_triangle3::init_world), ("(Debug) triangle", debug_triangle3::init_world),
("(Stress test) joint ball", stress_joint_ball3::init_world),
("(Stress test) joint fixed", stress_joint_fixed3::init_world),
(
"(Stress test) joint revolute",
stress_joint_revolute3::init_world,
),
(
"(Stress test) joint prismatic",
stress_joint_prismatic3::init_world,
),
("(Stress test) keva tower", stress_keva3::init_world),
]; ];
// Lexicographic sort, with stress tests moved at the end of the list. // Lexicographic sort, with stress tests moved at the end of the list.

View File

@@ -1,29 +0,0 @@
use na::Point3;
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
let rb = RigidBodyBuilder::new_dynamic().build();
let co = ColliderBuilder::cuboid(0.5, 0.5, 0.5).build();
let h = bodies.insert(rb);
colliders.insert(co, h, &mut bodies);
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin());
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Balls", init_world)]);
testbed.run()
}

View File

@@ -14,7 +14,7 @@ pub fn init_world(testbed: &mut Testbed) {
/* /*
* Ground * Ground
*/ */
let ground_size = 200.1; let ground_size = 50.0;
let ground_height = 0.1; let ground_height = 0.1;
let rigid_body = RigidBodyBuilder::new_static() let rigid_body = RigidBodyBuilder::new_static()
@@ -37,7 +37,7 @@ pub fn init_world(testbed: &mut Testbed) {
let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5; let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5;
for j in 0usize..25 { for j in 0usize..15 {
for i in 0..num { for i in 0..num {
for k in 0usize..num { for k in 0usize..num {
let x = i as f32 * shift * 5.0 - centerx + offset; let x = i as f32 * shift * 5.0 - centerx + offset;

View File

@@ -31,7 +31,7 @@ pub fn init_world(testbed: &mut Testbed) {
.can_sleep(false) .can_sleep(false)
.build(); .build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(2.0, 0.1, 1.0).density(1.0).build(); let collider = ColliderBuilder::cuboid(2.0, 0.1, 1.0).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
/* /*

View File

@@ -32,7 +32,7 @@ pub fn init_world(testbed: &mut Testbed) {
.can_sleep(false) .can_sleep(false)
.build(); .build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(20.0, 0.1, 1.0).density(1.0).build(); let collider = ColliderBuilder::cuboid(20.0, 0.1, 1.0).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
/* /*

View File

@@ -58,9 +58,7 @@ pub fn init_world(testbed: &mut Testbed) {
* rot; * rot;
let rigid_body = RigidBodyBuilder::new_dynamic().position(position).build(); let rigid_body = RigidBodyBuilder::new_dynamic().position(position).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(thickness, width * 2.0, width) let collider = ColliderBuilder::cuboid(thickness, width * 2.0, width).build();
.density(1.0)
.build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
testbed.set_body_color(handle, colors[i % 2]); testbed.set_body_color(handle, colors[i % 2]);
} else { } else {

View File

@@ -14,7 +14,7 @@ pub fn init_world(testbed: &mut Testbed) {
/* /*
* Ground * Ground
*/ */
let ground_size = Vector3::new(200.0, 1.0, 200.0); let ground_size = Vector3::new(100.0, 1.0, 100.0);
let nsubdivs = 20; let nsubdivs = 20;
let heights = DMatrix::from_fn(nsubdivs + 1, nsubdivs + 1, |i, j| { let heights = DMatrix::from_fn(nsubdivs + 1, nsubdivs + 1, |i, j| {
@@ -43,7 +43,7 @@ pub fn init_world(testbed: &mut Testbed) {
let centery = shift / 2.0; let centery = shift / 2.0;
let centerz = shift * (num / 2) as f32; let centerz = shift * (num / 2) as f32;
for j in 0usize..47 { for j in 0usize..20 {
for i in 0..num { for i in 0..num {
for k in 0usize..num { for k in 0usize..num {
let x = i as f32 * shift - centerx; let x = i as f32 * shift - centerx;
@@ -55,10 +55,10 @@ pub fn init_world(testbed: &mut Testbed) {
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
if j % 2 == 0 { if j % 2 == 0 {
let collider = ColliderBuilder::cuboid(rad, rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} else { } else {
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }

View File

@@ -150,7 +150,7 @@ fn create_fixed_joints(
.translation(origin.x + fk * shift, origin.y, origin.z + fi * shift) .translation(origin.x + fk * shift, origin.y, origin.z + fi * shift)
.build(); .build();
let child_handle = bodies.insert(rigid_body); let child_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, child_handle, bodies); colliders.insert(collider, child_handle, bodies);
// Vertical joint. // Vertical joint.
@@ -205,7 +205,7 @@ fn create_ball_joints(
.translation(fk * shift, 0.0, fi * shift) .translation(fk * shift, 0.0, fi * shift)
.build(); .build();
let child_handle = bodies.insert(rigid_body); let child_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, child_handle, bodies); colliders.insert(collider, child_handle, bodies);
// Vertical joint. // Vertical joint.

144
examples3d/keva3.rs Normal file
View File

@@ -0,0 +1,144 @@
use na::{Point3, Vector3};
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
pub fn build_block(
testbed: &mut Testbed,
bodies: &mut RigidBodySet,
colliders: &mut ColliderSet,
half_extents: Vector3<f32>,
shift: Vector3<f32>,
mut numx: usize,
numy: usize,
mut numz: usize,
) {
let dimensions = [half_extents.xyz(), half_extents.zyx()];
let block_width = 2.0 * half_extents.z * numx as f32;
let block_height = 2.0 * half_extents.y * numy as f32;
let spacing = (half_extents.z * numx as f32 - half_extents.x) / (numz as f32 - 1.0);
let mut color0 = Point3::new(0.7, 0.5, 0.9);
let mut color1 = Point3::new(0.6, 1.0, 0.6);
for i in 0..numy {
std::mem::swap(&mut numx, &mut numz);
let dim = dimensions[i % 2];
let y = dim.y * i as f32 * 2.0;
for j in 0..numx {
let x = if i % 2 == 0 {
spacing * j as f32 * 2.0
} else {
dim.x * j as f32 * 2.0
};
for k in 0..numz {
let z = if i % 2 == 0 {
dim.z * k as f32 * 2.0
} else {
spacing * k as f32 * 2.0
};
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic()
.translation(
x + dim.x + shift.x,
y + dim.y + shift.y,
z + dim.z + shift.z,
)
.build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(dim.x, dim.y, dim.z).build();
colliders.insert(collider, handle, bodies);
testbed.set_body_color(handle, color0);
std::mem::swap(&mut color0, &mut color1);
}
}
}
// Close the top.
let dim = half_extents.zxy();
for i in 0..(block_width / (dim.x as f32 * 2.0)) as usize {
for j in 0..(block_width / (dim.z as f32 * 2.0)) as usize {
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic()
.translation(
i as f32 * dim.x * 2.0 + dim.x + shift.x,
dim.y + shift.y + block_height,
j as f32 * dim.z * 2.0 + dim.z + shift.z,
)
.build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(dim.x, dim.y, dim.z).build();
colliders.insert(collider, handle, bodies);
testbed.set_body_color(handle, color0);
std::mem::swap(&mut color0, &mut color1);
}
}
}
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Ground
*/
let ground_size = 50.0;
let ground_height = 0.1;
let rigid_body = RigidBodyBuilder::new_static()
.translation(0.0, -ground_height, 0.0)
.build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size).build();
colliders.insert(collider, handle, &mut bodies);
/*
* Create the cubes
*/
let half_extents = Vector3::new(0.02, 0.1, 0.4) / 2.0 * 10.0;
let mut block_height = 0.0;
// These should only be set to odd values otherwise
// the blocks won't align in the nicest way.
let numy = [0, 9, 13, 17, 21, 41];
let mut num_blocks_built = 0;
for i in (1..=5).rev() {
let numx = i;
let numy = numy[i];
let numz = numx * 3 + 1;
let block_width = numx as f32 * half_extents.z * 2.0;
build_block(
testbed,
&mut bodies,
&mut colliders,
half_extents,
Vector3::new(-block_width / 2.0, block_height, -block_width / 2.0),
numx,
numy,
numz,
);
block_height += numy as f32 * half_extents.y * 2.0 + half_extents.x * 2.0;
num_blocks_built += numx * numy * numz;
}
println!("Num keva blocks: {}", num_blocks_built);
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin());
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Boxes", init_world)]);
testbed.run()
}

View File

@@ -45,7 +45,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }
@@ -58,9 +58,7 @@ pub fn init_world(testbed: &mut Testbed) {
.translation(0.0, 1.5 + 0.8, -10.0 * rad) .translation(0.0, 1.5 + 0.8, -10.0 * rad)
.build(); .build();
let platform_handle = bodies.insert(platform_body); let platform_handle = bodies.insert(platform_body);
let collider = ColliderBuilder::cuboid(rad * 10.0, rad, rad * 10.0) let collider = ColliderBuilder::cuboid(rad * 10.0, rad, rad * 10.0).build();
.density(1.0)
.build();
colliders.insert(collider, platform_handle, &mut bodies); colliders.insert(collider, platform_handle, &mut bodies);
/* /*

75
examples3d/primitives3.rs Normal file
View File

@@ -0,0 +1,75 @@
use na::Point3;
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
use rapier3d::geometry::{ColliderBuilder, ColliderSet};
use rapier_testbed3d::Testbed;
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let joints = JointSet::new();
/*
* Ground
*/
let ground_size = 100.1;
let ground_height = 0.1;
let rigid_body = RigidBodyBuilder::new_static()
.translation(0.0, -ground_height, 0.0)
.build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size).build();
colliders.insert(collider, handle, &mut bodies);
/*
* Create the cubes
*/
let num = 8;
let rad = 1.0;
let shift = rad * 2.0 + rad;
let centerx = shift * (num / 2) as f32;
let centery = shift / 2.0;
let centerz = shift * (num / 2) as f32;
let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5;
for j in 0usize..20 {
for i in 0..num {
for k in 0usize..num {
let x = i as f32 * shift - centerx + offset;
let y = j as f32 * shift + centery + 3.0;
let z = k as f32 * shift - centerz + offset;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body);
let collider = match j % 2 {
0 => ColliderBuilder::cuboid(rad, rad, rad).build(),
1 => ColliderBuilder::ball(rad).build(),
// 2 => ColliderBuilder::capsule_y(rad, rad).build(),
_ => unreachable!(),
};
colliders.insert(collider, handle, &mut bodies);
}
}
offset -= 0.05 * rad * (num as f32 - 1.0);
}
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, joints);
testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin());
}
fn main() {
let testbed = Testbed::from_builders(0, vec![("Boxes", init_world)]);
testbed.run()
}

View File

@@ -43,7 +43,7 @@ pub fn init_world(testbed: &mut Testbed) {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
testbed.set_body_color(handle, Point3::new(0.5, 0.5, 1.0)); testbed.set_body_color(handle, Point3::new(0.5, 0.5, 1.0));
@@ -56,13 +56,13 @@ pub fn init_world(testbed: &mut Testbed) {
// Rigid body so that the sensor can move. // Rigid body so that the sensor can move.
let sensor = RigidBodyBuilder::new_dynamic() let sensor = RigidBodyBuilder::new_dynamic()
.translation(0.0, 10.0, 0.0) .translation(0.0, 5.0, 0.0)
.build(); .build();
let sensor_handle = bodies.insert(sensor); let sensor_handle = bodies.insert(sensor);
// Solid cube attached to the sensor which // Solid cube attached to the sensor which
// other colliders can touch. // other colliders can touch.
let collider = ColliderBuilder::cuboid(rad, rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
colliders.insert(collider, sensor_handle, &mut bodies); colliders.insert(collider, sensor_handle, &mut bodies);
// We create a collider desc without density because we don't // We create a collider desc without density because we don't

View File

@@ -27,9 +27,8 @@ fn create_tower_circle(
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().position(pos).build(); let rigid_body = RigidBodyBuilder::new_dynamic().position(pos).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z) let collider =
.density(1.0) ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z).build();
.build();
colliders.insert(collider, handle, bodies); colliders.insert(collider, handle, bodies);
} }
} }
@@ -55,9 +54,8 @@ fn create_wall(
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z) let collider =
.density(1.0) ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z).build();
.build();
colliders.insert(collider, handle, bodies); colliders.insert(collider, handle, bodies);
} }
} }
@@ -88,9 +86,7 @@ fn create_pyramid(
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
let collider = let collider =
ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z) ColliderBuilder::cuboid(half_extents.x, half_extents.y, half_extents.z).build();
.density(1.0)
.build();
colliders.insert(collider, handle, bodies); colliders.insert(collider, handle, bodies);
} }
} }
@@ -124,27 +120,7 @@ pub fn init_world(testbed: &mut Testbed) {
let cube_size = 1.0; let cube_size = 1.0;
let hext = Vector3::repeat(cube_size); let hext = Vector3::repeat(cube_size);
let bottomy = cube_size * 50.0; let bottomy = cube_size * 50.0;
create_pyramid(
&mut bodies,
&mut colliders,
Vector3::new(-110.0, bottomy, 0.0),
12,
hext,
);
create_pyramid(
&mut bodies,
&mut colliders,
Vector3::new(-80.0, bottomy, 0.0),
12,
hext,
);
create_pyramid(
&mut bodies,
&mut colliders,
Vector3::new(-50.0, bottomy, 0.0),
12,
hext,
);
create_pyramid( create_pyramid(
&mut bodies, &mut bodies,
&mut colliders, &mut colliders,

View File

@@ -14,7 +14,7 @@ pub fn init_world(testbed: &mut Testbed) {
/* /*
* Ground * Ground
*/ */
let ground_size = 200.0f32; let ground_size = 100.0f32;
let ground_height = 1.0; let ground_height = 1.0;
let nsubdivs = 20; let nsubdivs = 20;
@@ -53,7 +53,7 @@ pub fn init_world(testbed: &mut Testbed) {
let centery = shift / 2.0; let centery = shift / 2.0;
let centerz = shift * (num / 2) as f32; let centerz = shift * (num / 2) as f32;
for j in 0usize..47 { for j in 0usize..20 {
for i in 0..num { for i in 0..num {
for k in 0usize..num { for k in 0usize..num {
let x = i as f32 * shift - centerx; let x = i as f32 * shift - centerx;
@@ -65,10 +65,10 @@ pub fn init_world(testbed: &mut Testbed) {
let handle = bodies.insert(rigid_body); let handle = bodies.insert(rigid_body);
if j % 2 == 0 { if j % 2 == 0 {
let collider = ColliderBuilder::cuboid(rad, rad, rad).density(1.0).build(); let collider = ColliderBuilder::cuboid(rad, rad, rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} else { } else {
let collider = ColliderBuilder::ball(rad).density(1.0).build(); let collider = ColliderBuilder::ball(rad).build();
colliders.insert(collider, handle, &mut bodies); colliders.insert(collider, handle, &mut bodies);
} }
} }

View File

@@ -212,7 +212,7 @@ pub struct ColliderBuilder {
/// The shape of the collider to be built. /// The shape of the collider to be built.
pub shape: Shape, pub shape: Shape,
/// The density of the collider to be built. /// The density of the collider to be built.
pub density: f32, density: Option<f32>,
/// The friction coefficient of the collider to be built. /// The friction coefficient of the collider to be built.
pub friction: f32, pub friction: f32,
/// The restitution coefficient of the collider to be built. /// The restitution coefficient of the collider to be built.
@@ -228,7 +228,7 @@ impl ColliderBuilder {
pub fn new(shape: Shape) -> Self { pub fn new(shape: Shape) -> Self {
Self { Self {
shape, shape,
density: 1.0, density: None,
friction: Self::default_friction(), friction: Self::default_friction(),
restitution: 0.0, restitution: 0.0,
delta: Isometry::identity(), delta: Isometry::identity(),
@@ -236,6 +236,12 @@ impl ColliderBuilder {
} }
} }
/// The density of the collider being built.
pub fn get_density(&self) -> f32 {
let default_density = if self.is_sensor { 0.0 } else { 1.0 };
self.density.unwrap_or(default_density)
}
/// Initialize a new collider builder with a ball shape defined by its radius. /// Initialize a new collider builder with a ball shape defined by its radius.
pub fn ball(radius: f32) -> Self { pub fn ball(radius: f32) -> Self {
Self::new(Shape::Ball(Ball::new(radius))) Self::new(Shape::Ball(Ball::new(radius)))
@@ -349,7 +355,7 @@ impl ColliderBuilder {
/// Sets the density of the collider this builder will build. /// Sets the density of the collider this builder will build.
pub fn density(mut self, density: f32) -> Self { pub fn density(mut self, density: f32) -> Self {
self.density = density; self.density = Some(density);
self self
} }
@@ -395,9 +401,11 @@ impl ColliderBuilder {
/// Buildes a new collider attached to the given rigid-body. /// Buildes a new collider attached to the given rigid-body.
pub fn build(&self) -> Collider { pub fn build(&self) -> Collider {
let density = self.get_density();
Collider { Collider {
shape: self.shape.clone(), shape: self.shape.clone(),
density: self.density, density,
friction: self.friction, friction: self.friction,
restitution: self.restitution, restitution: self.restitution,
delta: self.delta, delta: self.delta,

View File

@@ -230,7 +230,6 @@ pub struct Testbed {
gravity: Vector<f32>, gravity: Vector<f32>,
integration_parameters: IntegrationParameters, integration_parameters: IntegrationParameters,
physics: PhysicsState, physics: PhysicsState,
window: Option<Box<Window>>,
graphics: GraphicsManager, graphics: GraphicsManager,
nsteps: usize, nsteps: usize,
camera_locked: bool, // Used so that the camera can remain the same before and after we change backend or press the restart button. camera_locked: bool, // Used so that the camera can remain the same before and after we change backend or press the restart button.
@@ -244,7 +243,7 @@ pub struct Testbed {
// cursor_pos: Point2<f32>, // cursor_pos: Point2<f32>,
events: PhysicsEvents, events: PhysicsEvents,
event_handler: ChannelEventCollector, event_handler: ChannelEventCollector,
ui: TestbedUi, ui: Option<TestbedUi>,
state: TestbedState, state: TestbedState,
#[cfg(all(feature = "dim2", feature = "other-backends"))] #[cfg(all(feature = "dim2", feature = "other-backends"))]
box2d: Option<Box2dWorld>, box2d: Option<Box2dWorld>,
@@ -274,17 +273,8 @@ type CallbacksFluids = Vec<
impl Testbed { impl Testbed {
pub fn new_empty() -> Testbed { pub fn new_empty() -> Testbed {
let graphics = GraphicsManager::new(); let graphics = GraphicsManager::new();
#[cfg(feature = "dim3")]
let mut window = Box::new(Window::new("rapier: 3d demo"));
#[cfg(feature = "dim2")]
let mut window = Box::new(Window::new("rapier: 2d demo"));
window.set_background_color(0.85, 0.85, 0.85);
window.set_framerate_limit(Some(60));
window.set_light(Light::StickToCamera);
let flags = TestbedStateFlags::SLEEP; let flags = TestbedStateFlags::SLEEP;
let ui = TestbedUi::new(&mut window); let ui = None;
#[allow(unused_mut)] #[allow(unused_mut)]
let mut backend_names = vec!["rapier"]; let mut backend_names = vec!["rapier"];
@@ -352,7 +342,6 @@ impl Testbed {
callbacks: Vec::new(), callbacks: Vec::new(),
#[cfg(feature = "fluids")] #[cfg(feature = "fluids")]
callbacks_fluids: Vec::new(), callbacks_fluids: Vec::new(),
window: Some(window),
graphics, graphics,
nsteps: 1, nsteps: 1,
camera_locked: false, camera_locked: false,
@@ -754,7 +743,8 @@ impl Testbed {
} }
// Write the result as a csv file. // Write the result as a csv file.
let filename = format!("{}.csv", builder.0); use inflector::Inflector;
let filename = format!("{}.csv", builder.0.to_camel_case());
let mut file = BufWriter::new(File::create(filename).unwrap()); let mut file = BufWriter::new(File::create(filename).unwrap());
write!(file, "{}", backend_names[0]).unwrap(); write!(file, "{}", backend_names[0]).unwrap();
@@ -772,7 +762,14 @@ impl Testbed {
} }
} }
} else { } else {
let window = mem::replace(&mut self.window, None).unwrap(); #[cfg(feature = "dim3")]
let mut window = Window::new("rapier: 3d demo");
#[cfg(feature = "dim2")]
let mut window = Window::new("rapier: 2d demo");
window.set_background_color(0.85, 0.85, 0.85);
window.set_framerate_limit(Some(60));
window.set_light(Light::StickToCamera);
self.ui = Some(TestbedUi::new(&mut window));
window.render_loop(self); window.render_loop(self);
} }
} }
@@ -1206,8 +1203,9 @@ impl State for Testbed {
} }
fn step(&mut self, window: &mut Window) { fn step(&mut self, window: &mut Window) {
self.ui if let Some(ui) = &mut self.ui {
.update(window, &mut self.integration_parameters, &mut self.state); ui.update(window, &mut self.integration_parameters, &mut self.state);
}
// Handle UI actions. // Handle UI actions.
{ {