Fix clippy and enable clippy on CI

This commit is contained in:
Sébastien Crozet
2024-01-27 16:49:53 +01:00
committed by Sébastien Crozet
parent aef873f20e
commit da92e5c283
81 changed files with 420 additions and 468 deletions

View File

@@ -23,6 +23,12 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- run: sudo apt-get install -y cmake libxcb-composite0-dev - run: sudo apt-get install -y cmake libxcb-composite0-dev
- name: Clippy
run: cargo clippy
- name: Clippy rapier2d
run: cargo clippy -p rapier-examples-2d --features parallel,simd-stable
- name: Clippy rapier3d
run: cargo clippy -p rapier-examples-3d --features parallel,simd-stable
- name: Build rapier2d - name: Build rapier2d
run: cargo build --verbose -p rapier2d; run: cargo build --verbose -p rapier2d;
- name: Build rapier3d - name: Build rapier3d

View File

@@ -46,8 +46,8 @@ fn demo_name_from_url() -> Option<String> {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))] #[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
pub fn main() { pub fn main() {
let demo = demo_name_from_command_line() let demo = demo_name_from_command_line()
.or_else(|| demo_name_from_url()) .or_else(demo_name_from_url)
.unwrap_or(String::new()) .unwrap_or_default()
.to_camel_case(); .to_camel_case();
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![ let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
@@ -66,7 +66,7 @@ pub fn main() {
]; ];
// Lexicographic sort, with stress tests moved at the end of the list. // 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("(")) { builders.sort_by(|a, b| match (a.0.starts_with('('), b.0.starts_with(')')) {
(true, true) | (false, false) => a.0.cmp(b.0), (true, true) | (false, false) => a.0.cmp(b.0),
(true, false) => Ordering::Greater, (true, false) => Ordering::Greater,
(false, true) => Ordering::Less, (false, true) => Ordering::Less,

View File

@@ -36,7 +36,7 @@ fn parse_command_line() -> Command {
while let Some(arg) = args.next() { while let Some(arg) = args.next() {
if &arg[..] == "--example" { if &arg[..] == "--example" {
return Command::Run(args.next().unwrap_or(String::new())); return Command::Run(args.next().unwrap_or_default());
} else if &arg[..] == "--list" { } else if &arg[..] == "--list" {
return Command::List; return Command::List;
} }
@@ -68,7 +68,7 @@ pub fn main() {
]; ];
// Lexicographic sort, with stress tests moved at the end of the list. // 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("(")) { builders.sort_by(|a, b| match (a.0.starts_with('('), b.0.starts_with('(')) {
(true, true) | (false, false) => a.0.cmp(b.0), (true, true) | (false, false) => a.0.cmp(b.0),
(true, false) => Ordering::Greater, (true, false) => Ordering::Greater,
(false, true) => Ordering::Less, (false, true) => Ordering::Less,

View File

@@ -7,9 +7,7 @@ pub fn build_block(
colliders: &mut ColliderSet, colliders: &mut ColliderSet,
half_extents: Vector<f32>, half_extents: Vector<f32>,
shift: Vector<f32>, shift: Vector<f32>,
mut numx: usize, (mut numx, numy, mut numz): (usize, usize, usize),
numy: usize,
mut numz: usize,
) { ) {
let dimensions = [half_extents.xyz(), half_extents.zyx()]; let dimensions = [half_extents.xyz(), half_extents.zyx()];
let block_width = 2.0 * half_extents.z * numx as f32; let block_width = 2.0 * half_extents.z * numx as f32;
@@ -56,8 +54,8 @@ pub fn build_block(
// Close the top. // Close the top.
let dim = half_extents.zxy(); let dim = half_extents.zxy();
for i in 0..(block_width / (dim.x as f32 * 2.0)) as usize { for i in 0..(block_width / (dim.x * 2.0)) as usize {
for j in 0..(block_width / (dim.z as f32 * 2.0)) as usize { for j in 0..(block_width / (dim.z * 2.0)) as usize {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::dynamic().translation(vector![ let rigid_body = RigidBodyBuilder::dynamic().translation(vector![
i as f32 * dim.x * 2.0 + dim.x + shift.x, i as f32 * dim.x * 2.0 + dim.x + shift.x,
@@ -114,9 +112,7 @@ pub fn init_world(testbed: &mut Testbed) {
&mut colliders, &mut colliders,
half_extents, half_extents,
vector![-block_width / 2.0, block_height, -block_width / 2.0], vector![-block_width / 2.0, block_height, -block_width / 2.0],
numx, (numx, numy, numz),
numy,
numz,
); );
block_height += numy as f32 * half_extents.y * 2.0 + half_extents.x * 2.0; block_height += numy as f32 * half_extents.y * 2.0 + half_extents.x * 2.0;
num_blocks_built += numx * numy * numz; num_blocks_built += numx * numy * numz;

View File

@@ -57,8 +57,8 @@ fn demo_name_from_url() -> Option<String> {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))] #[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
pub fn main() { pub fn main() {
let demo = demo_name_from_command_line() let demo = demo_name_from_command_line()
.or_else(|| demo_name_from_url()) .or_else(demo_name_from_url)
.unwrap_or(String::new()) .unwrap_or_default()
.to_camel_case(); .to_camel_case();
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![ let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
@@ -85,7 +85,7 @@ pub fn main() {
]; ];
// Lexicographic sort, with stress tests moved at the end of the list. // 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("(")) { builders.sort_by(|a, b| match (a.0.starts_with('('), b.0.starts_with('(')) {
(true, true) | (false, false) => a.0.cmp(b.0), (true, true) | (false, false) => a.0.cmp(b.0),
(true, false) => Ordering::Greater, (true, false) => Ordering::Greater,
(false, true) => Ordering::Less, (false, true) => Ordering::Less,

View File

@@ -104,7 +104,7 @@ pub fn init_world(testbed: &mut Testbed) {
testbed.look_at(point![0.0, 20.0], 17.0); testbed.look_at(point![0.0, 20.0], 17.0);
} }
const RAPIER_SVG_STR: &'static str = r#" const RAPIER_SVG_STR: &str = r#"
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 527 131" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"> <svg width="100%" height="100%" viewBox="0 0 527 131" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
<g transform="matrix(1,0,0,1,1,-673)"> <g transform="matrix(1,0,0,1,1,-673)">

View File

@@ -43,15 +43,15 @@ fn demo_name_from_url() -> Option<String> {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))] #[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
pub fn main() { pub fn main() {
let demo = demo_name_from_command_line() let demo = demo_name_from_command_line()
.or_else(|| demo_name_from_url()) .or_else(demo_name_from_url)
.unwrap_or(String::new()) .unwrap_or_default()
.to_camel_case(); .to_camel_case();
let mut builders: Vec<(_, fn(&mut Testbed))> = let mut builders: Vec<(_, fn(&mut Testbed))> =
vec![("(Debug) serialized", debug_serialized3::init_world)]; vec![("(Debug) serialized", debug_serialized3::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.
builders.sort_by(|a, b| match (a.0.starts_with("("), b.0.starts_with("(")) { builders.sort_by(|a, b| match (a.0.starts_with('('), b.0.starts_with('(')) {
(true, true) | (false, false) => a.0.cmp(b.0), (true, true) | (false, false) => a.0.cmp(b.0),
(true, false) => Ordering::Greater, (true, false) => Ordering::Greater,
(false, true) => Ordering::Less, (false, true) => Ordering::Less,

View File

@@ -86,8 +86,8 @@ fn demo_name_from_url() -> Option<String> {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))] #[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
pub fn main() { pub fn main() {
let demo = demo_name_from_command_line() let demo = demo_name_from_command_line()
.or_else(|| demo_name_from_url()) .or_else(demo_name_from_url)
.unwrap_or(String::new()) .unwrap_or_default()
.to_camel_case(); .to_camel_case();
let mut builders: Vec<(_, fn(&mut Testbed))> = vec![ let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
@@ -157,7 +157,7 @@ pub fn main() {
]; ];
// Lexicographic sort, with stress tests moved at the end of the list. // 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("(")) { builders.sort_by(|a, b| match (a.0.starts_with('('), b.0.starts_with('(')) {
(true, true) | (false, false) => a.0.cmp(b.0), (true, true) | (false, false) => a.0.cmp(b.0),
(true, false) => Ordering::Greater, (true, false) => Ordering::Greater,
(false, true) => Ordering::Less, (false, true) => Ordering::Less,

View File

@@ -27,9 +27,9 @@ fn create_wall(
colliders.insert_with_parent(collider, handle, bodies); colliders.insert_with_parent(collider, handle, bodies);
k += 1; k += 1;
if k % 2 == 0 { if k % 2 == 0 {
testbed.set_initial_body_color(handle, [255. / 255., 131. / 255., 244.0 / 255.]); testbed.set_initial_body_color(handle, [1., 131. / 255., 244.0 / 255.]);
} else { } else {
testbed.set_initial_body_color(handle, [131. / 255., 255. / 255., 244.0 / 255.]); testbed.set_initial_body_color(handle, [131. / 255., 1., 244.0 / 255.]);
} }
} }
} }

View File

@@ -482,7 +482,7 @@ fn create_actuated_revolute_joints(
} else if i == num - 1 { } else if i == num - 1 {
let stiffness = 200.0; let stiffness = 200.0;
let damping = 100.0; let damping = 100.0;
joint = joint.motor_position(3.14 / 2.0, stiffness, damping); joint = joint.motor_position(std::f32::consts::FRAC_PI_2, stiffness, damping);
} }
if i == 1 { if i == 1 {
@@ -541,7 +541,7 @@ fn create_actuated_spherical_joints(
colliders.insert_with_parent(collider, child_handle, bodies); colliders.insert_with_parent(collider, child_handle, bodies);
if i > 0 { if i > 0 {
let mut joint = joint_template.clone(); let mut joint = joint_template;
if i == 1 { if i == 1 {
joint = joint joint = joint
@@ -554,7 +554,12 @@ fn create_actuated_spherical_joints(
joint = joint joint = joint
.motor_position(JointAxis::AngX, 0.0, stiffness, damping) .motor_position(JointAxis::AngX, 0.0, stiffness, damping)
.motor_position(JointAxis::AngY, 1.0, stiffness, damping) .motor_position(JointAxis::AngY, 1.0, stiffness, damping)
.motor_position(JointAxis::AngZ, 3.14 / 2.0, stiffness, damping); .motor_position(
JointAxis::AngZ,
std::f32::consts::FRAC_PI_2,
stiffness,
damping,
);
} }
if use_articulations { if use_articulations {

View File

@@ -7,9 +7,7 @@ pub fn build_block(
colliders: &mut ColliderSet, colliders: &mut ColliderSet,
half_extents: Vector<f32>, half_extents: Vector<f32>,
shift: Vector<f32>, shift: Vector<f32>,
mut numx: usize, (mut numx, numy, mut numz): (usize, usize, usize),
numy: usize,
mut numz: usize,
) { ) {
let dimensions = [half_extents.xyz(), half_extents.zyx()]; let dimensions = [half_extents.xyz(), half_extents.zyx()];
let block_width = 2.0 * half_extents.z * numx as f32; let block_width = 2.0 * half_extents.z * numx as f32;
@@ -56,8 +54,8 @@ pub fn build_block(
// Close the top. // Close the top.
let dim = half_extents.zxy(); let dim = half_extents.zxy();
for i in 0..(block_width / (dim.x as f32 * 2.0)) as usize { for i in 0..(block_width / (dim.x * 2.0)) as usize {
for j in 0..(block_width / (dim.z as f32 * 2.0)) as usize { for j in 0..(block_width / (dim.z * 2.0)) as usize {
// Build the rigid body. // Build the rigid body.
let rigid_body = RigidBodyBuilder::dynamic().translation(vector![ let rigid_body = RigidBodyBuilder::dynamic().translation(vector![
i as f32 * dim.x * 2.0 + dim.x + shift.x, i as f32 * dim.x * 2.0 + dim.x + shift.x,
@@ -114,9 +112,7 @@ pub fn init_world(testbed: &mut Testbed) {
&mut colliders, &mut colliders,
half_extents, half_extents,
vector![-block_width / 2.0, block_height, -block_width / 2.0], vector![-block_width / 2.0, block_height, -block_width / 2.0],
numx, (numx, numy, numz),
numy,
numz,
); );
block_height += numy as f32 * half_extents.y * 2.0 + half_extents.x * 2.0; block_height += numy as f32 * half_extents.y * 2.0 + half_extents.x * 2.0;
num_blocks_built += numx * numy * numz; num_blocks_built += numx * numy * numz;

View File

@@ -67,7 +67,7 @@ pub fn init_world(testbed: &mut Testbed) {
let collider = ColliderBuilder::cuboid(0.15, 0.3, 0.15); let collider = ColliderBuilder::cuboid(0.15, 0.3, 0.15);
colliders.insert_with_parent(collider, character_handle, &mut bodies); colliders.insert_with_parent(collider, character_handle, &mut bodies);
testbed.set_initial_body_color(character_handle, [255. / 255., 131. / 255., 244.0 / 255.]); testbed.set_initial_body_color(character_handle, [1., 131. / 255., 244.0 / 255.]);
/* /*
* Tethered Ball * Tethered Ball

View File

@@ -32,9 +32,11 @@ pub fn init_world(testbed: &mut Testbed) {
let collider = ColliderBuilder::cuboid(hw * 2.0, hh, hw).density(100.0); let collider = ColliderBuilder::cuboid(hw * 2.0, hh, hw).density(100.0);
colliders.insert_with_parent(collider, vehicle_handle, &mut bodies); colliders.insert_with_parent(collider, vehicle_handle, &mut bodies);
let mut tuning = WheelTuning::default(); let tuning = WheelTuning {
tuning.suspension_stiffness = 100.0; suspension_stiffness: 100.0,
tuning.suspension_damping = 10.0; suspension_damping: 10.0,
..WheelTuning::default()
};
let mut vehicle = DynamicRayCastVehicleController::new(vehicle_handle); let mut vehicle = DynamicRayCastVehicleController::new(vehicle_handle);
let wheel_positions = [ let wheel_positions = [
point![hw * 1.5, -hh, hw], point![hw * 1.5, -hh, hw],

View File

@@ -582,7 +582,7 @@ impl DynamicRayCastVehicleController {
wheel.side_impulse = resolve_single_bilateral( wheel.side_impulse = resolve_single_bilateral(
&bodies[self.chassis], &bodies[self.chassis],
&wheel.raycast_info.contact_point_ws, &wheel.raycast_info.contact_point_ws,
&ground_body, ground_body,
&wheel.raycast_info.contact_point_ws, &wheel.raycast_info.contact_point_ws,
&self.axle[i], &self.axle[i],
); );
@@ -664,11 +664,9 @@ impl DynamicRayCastVehicleController {
if sliding { if sliding {
for wheel in &mut self.wheels { for wheel in &mut self.wheels {
if wheel.side_impulse != 0.0 { if wheel.side_impulse != 0.0 && wheel.skid_info < 1.0 {
if wheel.skid_info < 1.0 { wheel.forward_impulse *= wheel.skid_info;
wheel.forward_impulse *= wheel.skid_info; wheel.side_impulse *= wheel.skid_info;
wheel.side_impulse *= wheel.skid_info;
}
} }
} }
} }

View File

@@ -269,7 +269,7 @@ impl<T> Arena<T> {
self.free_list_head = next_free; self.free_list_head = next_free;
self.len += 1; self.len += 1;
Some(Index { Some(Index {
index: i as u32, index: i,
generation: self.generation, generation: self.generation,
}) })
} }

View File

@@ -106,8 +106,7 @@ impl<T> PubSub<T> {
/// Read the i-th message not yet read by the given subsciber. /// Read the i-th message not yet read by the given subsciber.
pub fn read_ith(&self, sub: &Subscription<T>, i: usize) -> Option<&T> { pub fn read_ith(&self, sub: &Subscription<T>, i: usize) -> Option<&T> {
let cursor = &self.cursors[sub.id as usize]; let cursor = &self.cursors[sub.id as usize];
self.messages self.messages.get(cursor.next(self.deleted_messages) + i)
.get(cursor.next(self.deleted_messages) as usize + i)
} }
/// Get the messages not yet read by the given subscriber. /// Get the messages not yet read by the given subscriber.

View File

@@ -52,32 +52,27 @@ impl CCDSolver {
/// ///
/// The `impacts` should be the result of a previous call to `self.predict_next_impacts`. /// The `impacts` should be the result of a previous call to `self.predict_next_impacts`.
pub fn clamp_motions(&self, dt: Real, bodies: &mut RigidBodySet, impacts: &PredictedImpacts) { pub fn clamp_motions(&self, dt: Real, bodies: &mut RigidBodySet, impacts: &PredictedImpacts) {
match impacts { if let PredictedImpacts::Impacts(tois) = impacts {
PredictedImpacts::Impacts(tois) => { for (handle, toi) in tois {
for (handle, toi) in tois { let rb = bodies.index_mut_internal(*handle);
let rb = bodies.index_mut_internal(*handle); let local_com = &rb.mprops.local_mprops.local_com;
let local_com = &rb.mprops.local_mprops.local_com;
let min_toi = (rb.ccd.ccd_thickness let min_toi = (rb.ccd.ccd_thickness
* 0.15 * 0.15
* crate::utils::inv(rb.ccd.max_point_velocity(&rb.integrated_vels))) * crate::utils::inv(rb.ccd.max_point_velocity(&rb.integrated_vels)))
.min(dt); .min(dt);
// println!( // println!(
// "Min toi: {}, Toi: {}, thick: {}, max_vel: {}", // "Min toi: {}, Toi: {}, thick: {}, max_vel: {}",
// min_toi, // min_toi,
// toi, // toi,
// rb.ccd.ccd_thickness, // rb.ccd.ccd_thickness,
// rb.ccd.max_point_velocity(&rb.integrated_vels) // rb.ccd.max_point_velocity(&rb.integrated_vels)
// ); // );
let new_pos = rb.integrated_vels.integrate( let new_pos =
toi.max(min_toi), rb.integrated_vels
&rb.pos.position, .integrate(toi.max(min_toi), &rb.pos.position, local_com);
&local_com, rb.pos.next_position = new_pos;
);
rb.pos.next_position = new_pos;
}
} }
_ => {}
} }
} }

View File

@@ -169,13 +169,15 @@ impl TOIEntry {
impl PartialOrd for TOIEntry { impl PartialOrd for TOIEntry {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
(-self.toi).partial_cmp(&(-other.toi)) Some(self.cmp(other))
} }
} }
impl Ord for TOIEntry { impl Ord for TOIEntry {
fn cmp(&self, other: &Self) -> std::cmp::Ordering { fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).unwrap() (-self.toi)
.partial_cmp(&(-other.toi))
.unwrap_or(std::cmp::Ordering::Equal)
} }
} }

View File

@@ -7,10 +7,11 @@ use crate::math::Real;
/// Each collider has its combination rule of type /// Each collider has its combination rule of type
/// `CoefficientCombineRule`. And the rule /// `CoefficientCombineRule`. And the rule
/// actually used is given by `max(first_combine_rule as usize, second_combine_rule as usize)`. /// actually used is given by `max(first_combine_rule as usize, second_combine_rule as usize)`.
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub enum CoefficientCombineRule { pub enum CoefficientCombineRule {
/// The two coefficients are averaged. /// The two coefficients are averaged.
#[default]
Average = 0, Average = 0,
/// The smallest coefficient is chosen. /// The smallest coefficient is chosen.
Min, Min,
@@ -20,12 +21,6 @@ pub enum CoefficientCombineRule {
Max, Max,
} }
impl Default for CoefficientCombineRule {
fn default() -> Self {
CoefficientCombineRule::Average
}
}
impl CoefficientCombineRule { impl CoefficientCombineRule {
pub(crate) fn combine(coeff1: Real, coeff2: Real, rule_value1: u8, rule_value2: u8) -> Real { pub(crate) fn combine(coeff1: Real, coeff2: Real, rule_value1: u8, rule_value2: u8) -> Real {
let effective_rule = rule_value1.max(rule_value2); let effective_rule = rule_value1.max(rule_value2);

View File

@@ -71,8 +71,7 @@ impl IntegrationParameters {
/// NOTE: this resets [`Self::erp`], [`Self::damping_ratio`], [`Self::joint_erp`], /// NOTE: this resets [`Self::erp`], [`Self::damping_ratio`], [`Self::joint_erp`],
/// [`Self::joint_damping_ratio`] to their former default values. /// [`Self::joint_damping_ratio`] to their former default values.
pub fn switch_to_standard_pgs_solver(&mut self) { pub fn switch_to_standard_pgs_solver(&mut self) {
self.num_internal_pgs_iterations = self.num_internal_pgs_iterations *= self.num_solver_iterations.get();
self.num_solver_iterations.get() * self.num_internal_pgs_iterations;
self.num_solver_iterations = NonZeroUsize::new(1).unwrap(); self.num_solver_iterations = NonZeroUsize::new(1).unwrap();
self.erp = 0.8; self.erp = 0.8;
self.damping_ratio = 0.25; self.damping_ratio = 0.25;

View File

@@ -134,7 +134,7 @@ impl IslandManager {
} }
#[inline(always)] #[inline(always)]
pub(crate) fn iter_active_bodies<'a>(&'a self) -> impl Iterator<Item = RigidBodyHandle> + 'a { pub(crate) fn iter_active_bodies(&self) -> impl Iterator<Item = RigidBodyHandle> + '_ {
self.active_dynamic_set self.active_dynamic_set
.iter() .iter()
.copied() .copied()

View File

@@ -84,9 +84,9 @@ impl FixedJoint {
} }
} }
impl Into<GenericJoint> for FixedJoint { impl From<FixedJoint> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: FixedJoint) -> GenericJoint {
self.data val.data
} }
} }
@@ -143,8 +143,8 @@ impl FixedJointBuilder {
} }
} }
impl Into<GenericJoint> for FixedJointBuilder { impl From<FixedJointBuilder> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: FixedJointBuilder) -> GenericJoint {
self.0.into() val.0.into()
} }
} }

View File

@@ -1,3 +1,5 @@
#![allow(clippy::bad_bit_mask)] // Clippy will complain about the bitmasks due to JointAxesMask::FREE_FIXED_AXES being 0.
use crate::dynamics::solver::MotorParameters; use crate::dynamics::solver::MotorParameters;
use crate::dynamics::{FixedJoint, MotorModel, PrismaticJoint, RevoluteJoint, RopeJoint}; use crate::dynamics::{FixedJoint, MotorModel, PrismaticJoint, RevoluteJoint, RopeJoint};
use crate::math::{Isometry, Point, Real, Rotation, UnitVector, Vector, SPATIAL_DIM}; use crate::math::{Isometry, Point, Real, Rotation, UnitVector, Vector, SPATIAL_DIM};
@@ -704,8 +706,8 @@ impl GenericJointBuilder {
} }
} }
impl Into<GenericJoint> for GenericJointBuilder { impl From<GenericJointBuilder> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: GenericJointBuilder) -> GenericJoint {
self.0 val.0
} }
} }

View File

@@ -105,8 +105,8 @@ impl ImpulseJointSet {
} }
/// Iterates through all the impulse joints attached to the given rigid-body. /// Iterates through all the impulse joints attached to the given rigid-body.
pub fn map_attached_joints_mut<'a>( pub fn map_attached_joints_mut(
&'a mut self, &mut self,
body: RigidBodyHandle, body: RigidBodyHandle,
mut f: impl FnMut(RigidBodyHandle, RigidBodyHandle, ImpulseJointHandle, &mut ImpulseJoint), mut f: impl FnMut(RigidBodyHandle, RigidBodyHandle, ImpulseJointHandle, &mut ImpulseJoint),
) { ) {
@@ -282,7 +282,7 @@ impl ImpulseJointSet {
&self, &self,
islands: &IslandManager, islands: &IslandManager,
bodies: &RigidBodySet, bodies: &RigidBodySet,
out: &mut Vec<Vec<JointIndex>>, out: &mut [Vec<JointIndex>],
) { ) {
for out_island in &mut out[..islands.num_islands()] { for out_island in &mut out[..islands.num_islands()] {
out_island.clear(); out_island.clear();

View File

@@ -1,23 +1,18 @@
use crate::math::Real; use crate::math::Real;
/// The spring-like model used for constraints resolution. /// The spring-like model used for constraints resolution.
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub enum MotorModel { pub enum MotorModel {
/// The solved spring-like equation is: /// The solved spring-like equation is:
/// `acceleration = stiffness * (pos - target_pos) + damping * (vel - target_vel)` /// `acceleration = stiffness * (pos - target_pos) + damping * (vel - target_vel)`
#[default]
AccelerationBased, AccelerationBased,
/// The solved spring-like equation is: /// The solved spring-like equation is:
/// `force = stiffness * (pos - target_pos) + damping * (vel - target_vel)` /// `force = stiffness * (pos - target_pos) + damping * (vel - target_vel)`
ForceBased, ForceBased,
} }
impl Default for MotorModel {
fn default() -> Self {
MotorModel::AccelerationBased
}
}
impl MotorModel { impl MotorModel {
/// Combines the coefficients used for solving the spring equation. /// Combines the coefficients used for solving the spring equation.
/// ///

View File

@@ -127,8 +127,9 @@ impl Multibody {
let mut link_id2new_id = vec![usize::MAX; self.links.len()]; let mut link_id2new_id = vec![usize::MAX; self.links.len()];
for (i, mut link) in self.links.0.into_iter().enumerate() { for (i, mut link) in self.links.0.into_iter().enumerate() {
let is_new_root = (!joint_only && (i == 0 || link.parent_internal_id == to_remove)) let is_new_root = i == 0
|| (joint_only && (i == 0 || i == to_remove)); || !joint_only && link.parent_internal_id == to_remove
|| joint_only && i == to_remove;
if !joint_only && i == to_remove { if !joint_only && i == to_remove {
continue; continue;
@@ -492,7 +493,7 @@ impl Multibody {
parent_to_world = parent_link.local_to_world; parent_to_world = parent_link.local_to_world;
let (link_j, parent_j) = self.body_jacobians.index_mut_const(i, parent_id); let (link_j, parent_j) = self.body_jacobians.index_mut_const(i, parent_id);
link_j.copy_from(&parent_j); link_j.copy_from(parent_j);
{ {
let mut link_j_v = link_j.fixed_rows_mut::<DIM>(0); let mut link_j_v = link_j.fixed_rows_mut::<DIM>(0);
@@ -602,12 +603,12 @@ impl Multibody {
let (coriolis_v, parent_coriolis_v) = self.coriolis_v.index_mut2(i, parent_id); let (coriolis_v, parent_coriolis_v) = self.coriolis_v.index_mut2(i, parent_id);
let (coriolis_w, parent_coriolis_w) = self.coriolis_w.index_mut2(i, parent_id); let (coriolis_w, parent_coriolis_w) = self.coriolis_w.index_mut2(i, parent_id);
coriolis_v.copy_from(&parent_coriolis_v); coriolis_v.copy_from(parent_coriolis_v);
coriolis_w.copy_from(&parent_coriolis_w); coriolis_w.copy_from(parent_coriolis_w);
// [c1 - c0].gcross() * (JDot + JDot/u * qdot)" // [c1 - c0].gcross() * (JDot + JDot/u * qdot)"
let shift_cross_tr = link.shift02.gcross_matrix_tr(); let shift_cross_tr = link.shift02.gcross_matrix_tr();
coriolis_v.gemm(1.0, &shift_cross_tr, &parent_coriolis_w, 1.0); coriolis_v.gemm(1.0, &shift_cross_tr, parent_coriolis_w, 1.0);
// JDot (but the 2.0 originates from the sum of two identical terms in JDot and JDot/u * gdot) // JDot (but the 2.0 originates from the sum of two identical terms in JDot and JDot/u * gdot)
let dvel_cross = (rb.vels.angvel.gcross(link.shift02) let dvel_cross = (rb.vels.angvel.gcross(link.shift02)
@@ -663,7 +664,7 @@ impl Multibody {
{ {
// [c3 - c2].gcross() * (JDot + JDot/u * qdot) // [c3 - c2].gcross() * (JDot + JDot/u * qdot)
let shift_cross_tr = link.shift23.gcross_matrix_tr(); let shift_cross_tr = link.shift23.gcross_matrix_tr();
coriolis_v.gemm(1.0, &shift_cross_tr, &coriolis_w, 1.0); coriolis_v.gemm(1.0, &shift_cross_tr, coriolis_w, 1.0);
// JDot // JDot
let dvel_cross = rb.vels.angvel.gcross(link.shift23).gcross_matrix_tr(); let dvel_cross = rb.vels.angvel.gcross(link.shift23).gcross_matrix_tr();
@@ -696,16 +697,16 @@ impl Multibody {
{ {
let mut i_coriolis_dt_w = self.i_coriolis_dt.fixed_rows_mut::<ANG_DIM>(DIM); let mut i_coriolis_dt_w = self.i_coriolis_dt.fixed_rows_mut::<ANG_DIM>(DIM);
// NOTE: this is just an axpy, but on row columns. // NOTE: this is just an axpy, but on row columns.
i_coriolis_dt_w.zip_apply(&coriolis_w, |o, x| *o = x * dt * rb_inertia); i_coriolis_dt_w.zip_apply(coriolis_w, |o, x| *o = x * dt * rb_inertia);
} }
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
{ {
let mut i_coriolis_dt_w = self.i_coriolis_dt.fixed_rows_mut::<ANG_DIM>(DIM); let mut i_coriolis_dt_w = self.i_coriolis_dt.fixed_rows_mut::<ANG_DIM>(DIM);
i_coriolis_dt_w.gemm(dt, &rb_inertia, &coriolis_w, 0.0); i_coriolis_dt_w.gemm(dt, &rb_inertia, coriolis_w, 0.0);
} }
self.acc_augmented_mass self.acc_augmented_mass
.gemm_tr(1.0, &rb_j, &self.i_coriolis_dt, 1.0); .gemm_tr(1.0, rb_j, &self.i_coriolis_dt, 1.0);
} }
/* /*

View File

@@ -393,10 +393,10 @@ impl MultibodyJointSet {
/// Iterate through the handles of all the rigid-bodies attached to this rigid-body /// Iterate through the handles of all the rigid-bodies attached to this rigid-body
/// by a multibody_joint. /// by a multibody_joint.
pub fn attached_bodies<'a>( pub fn attached_bodies(
&'a self, &self,
body: RigidBodyHandle, body: RigidBodyHandle,
) -> impl Iterator<Item = RigidBodyHandle> + 'a { ) -> impl Iterator<Item = RigidBodyHandle> + '_ {
self.rb2mb self.rb2mb
.get(body.0) .get(body.0)
.into_iter() .into_iter()
@@ -406,10 +406,10 @@ impl MultibodyJointSet {
/// Iterate through the handles of all the rigid-bodies attached to this rigid-body /// Iterate through the handles of all the rigid-bodies attached to this rigid-body
/// by an enabled multibody_joint. /// by an enabled multibody_joint.
pub fn bodies_attached_with_enabled_joint<'a>( pub fn bodies_attached_with_enabled_joint(
&'a self, &self,
body: RigidBodyHandle, body: RigidBodyHandle,
) -> impl Iterator<Item = RigidBodyHandle> + 'a { ) -> impl Iterator<Item = RigidBodyHandle> + '_ {
self.attached_bodies(body).filter(move |other| { self.attached_bodies(body).filter(move |other| {
if let Some((_, _, link)) = self.joint_between(body, *other) { if let Some((_, _, link)) = self.joint_between(body, *other) {
link.joint.data.is_enabled() link.joint.data.is_enabled()

View File

@@ -152,9 +152,9 @@ impl PrismaticJoint {
} }
} }
impl Into<GenericJoint> for PrismaticJoint { impl From<PrismaticJoint> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: PrismaticJoint) -> GenericJoint {
self.data val.data
} }
} }
@@ -263,8 +263,8 @@ impl PrismaticJointBuilder {
} }
} }
impl Into<GenericJoint> for PrismaticJointBuilder { impl From<PrismaticJointBuilder> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: PrismaticJointBuilder) -> GenericJoint {
self.0.into() val.0.into()
} }
} }

View File

@@ -17,6 +17,7 @@ pub struct RevoluteJoint {
impl RevoluteJoint { impl RevoluteJoint {
/// Creates a new revolute joint allowing only relative rotations. /// Creates a new revolute joint allowing only relative rotations.
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
#[allow(clippy::new_without_default)] // For symmetry with 3D which cant have a Default impl.
pub fn new() -> Self { pub fn new() -> Self {
let data = GenericJointBuilder::new(JointAxesMask::LOCKED_REVOLUTE_AXES); let data = GenericJointBuilder::new(JointAxesMask::LOCKED_REVOLUTE_AXES);
Self { data: data.build() } Self { data: data.build() }
@@ -137,9 +138,9 @@ impl RevoluteJoint {
} }
} }
impl Into<GenericJoint> for RevoluteJoint { impl From<RevoluteJoint> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: RevoluteJoint) -> GenericJoint {
self.data val.data
} }
} }
@@ -153,6 +154,7 @@ pub struct RevoluteJointBuilder(pub RevoluteJoint);
impl RevoluteJointBuilder { impl RevoluteJointBuilder {
/// Creates a new revolute joint builder. /// Creates a new revolute joint builder.
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
#[allow(clippy::new_without_default)] // For symmetry with 3D which cant have a Default impl.
pub fn new() -> Self { pub fn new() -> Self {
Self(RevoluteJoint::new()) Self(RevoluteJoint::new())
} }
@@ -241,8 +243,8 @@ impl RevoluteJointBuilder {
} }
} }
impl Into<GenericJoint> for RevoluteJointBuilder { impl From<RevoluteJointBuilder> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: RevoluteJointBuilder) -> GenericJoint {
self.0.into() val.0.into()
} }
} }

View File

@@ -134,9 +134,9 @@ impl RopeJoint {
} }
} }
impl Into<GenericJoint> for RopeJoint { impl From<RopeJoint> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: RopeJoint) -> GenericJoint {
self.data val.data
} }
} }
@@ -231,8 +231,8 @@ impl RopeJointBuilder {
} }
} }
impl Into<GenericJoint> for RopeJointBuilder { impl From<RopeJointBuilder> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: RopeJointBuilder) -> GenericJoint {
self.0.into() val.0.into()
} }
} }

View File

@@ -164,9 +164,9 @@ impl SphericalJoint {
} }
} }
impl Into<GenericJoint> for SphericalJoint { impl From<SphericalJoint> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: SphericalJoint) -> GenericJoint {
self.data val.data
} }
} }
@@ -288,8 +288,8 @@ impl SphericalJointBuilder {
} }
} }
impl Into<GenericJoint> for SphericalJointBuilder { impl From<SphericalJointBuilder> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: SphericalJointBuilder) -> GenericJoint {
self.0.into() val.0.into()
} }
} }

View File

@@ -94,9 +94,9 @@ impl SpringJoint {
// } // }
} }
impl Into<GenericJoint> for SpringJoint { impl From<SpringJoint> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: SpringJoint) -> GenericJoint {
self.data val.data
} }
} }
@@ -165,8 +165,8 @@ impl SpringJointBuilder {
} }
} }
impl Into<GenericJoint> for SpringJointBuilder { impl From<SpringJointBuilder> for GenericJoint {
fn into(self) -> GenericJoint { fn from(val: SpringJointBuilder) -> GenericJoint {
self.0.into() val.0.into()
} }
} }

View File

@@ -300,16 +300,16 @@ impl RigidBody {
wake_up: bool, wake_up: bool,
) { ) {
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
if self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_X) == !allow_translation_x if self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_X) != allow_translation_x
&& self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_Y) == !allow_translation_y && self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_Y) != allow_translation_y
{ {
// Nothing to change. // Nothing to change.
return; return;
} }
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
if self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_X) == !allow_translation_x if self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_X) != allow_translation_x
&& self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_Y) == !allow_translation_y && self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_Y) != allow_translation_y
&& self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_Z) == !allow_translation_z && self.mprops.flags.contains(LockedAxes::TRANSLATION_LOCKED_Z) != allow_translation_z
{ {
// Nothing to change. // Nothing to change.
return; return;
@@ -850,13 +850,11 @@ impl RigidBody {
/// ///
/// This does nothing on non-dynamic bodies. /// This does nothing on non-dynamic bodies.
pub fn add_force(&mut self, force: Vector<Real>, wake_up: bool) { pub fn add_force(&mut self, force: Vector<Real>, wake_up: bool) {
if !force.is_zero() { if !force.is_zero() && self.body_type == RigidBodyType::Dynamic {
if self.body_type == RigidBodyType::Dynamic { self.forces.user_force += force;
self.forces.user_force += force;
if wake_up { if wake_up {
self.wake_up(true); self.wake_up(true);
}
} }
} }
} }
@@ -866,13 +864,11 @@ impl RigidBody {
/// This does nothing on non-dynamic bodies. /// This does nothing on non-dynamic bodies.
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
pub fn add_torque(&mut self, torque: Real, wake_up: bool) { pub fn add_torque(&mut self, torque: Real, wake_up: bool) {
if !torque.is_zero() { if !torque.is_zero() && self.body_type == RigidBodyType::Dynamic {
if self.body_type == RigidBodyType::Dynamic { self.forces.user_torque += torque;
self.forces.user_torque += torque;
if wake_up { if wake_up {
self.wake_up(true); self.wake_up(true);
}
} }
} }
} }
@@ -882,13 +878,11 @@ impl RigidBody {
/// This does nothing on non-dynamic bodies. /// This does nothing on non-dynamic bodies.
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
pub fn add_torque(&mut self, torque: Vector<Real>, wake_up: bool) { pub fn add_torque(&mut self, torque: Vector<Real>, wake_up: bool) {
if !torque.is_zero() { if !torque.is_zero() && self.body_type == RigidBodyType::Dynamic {
if self.body_type == RigidBodyType::Dynamic { self.forces.user_torque += torque;
self.forces.user_torque += torque;
if wake_up { if wake_up {
self.wake_up(true); self.wake_up(true);
}
} }
} }
} }
@@ -897,14 +891,12 @@ impl RigidBody {
/// ///
/// This does nothing on non-dynamic bodies. /// This does nothing on non-dynamic bodies.
pub fn add_force_at_point(&mut self, force: Vector<Real>, point: Point<Real>, wake_up: bool) { pub fn add_force_at_point(&mut self, force: Vector<Real>, point: Point<Real>, wake_up: bool) {
if !force.is_zero() { if !force.is_zero() && self.body_type == RigidBodyType::Dynamic {
if self.body_type == RigidBodyType::Dynamic { self.forces.user_force += force;
self.forces.user_force += force; self.forces.user_torque += (point - self.mprops.world_com).gcross(force);
self.forces.user_torque += (point - self.mprops.world_com).gcross(force);
if wake_up { if wake_up {
self.wake_up(true); self.wake_up(true);
}
} }
} }
} }
@@ -1379,8 +1371,8 @@ impl RigidBodyBuilder {
} }
} }
impl Into<RigidBody> for RigidBodyBuilder { impl From<RigidBodyBuilder> for RigidBody {
fn into(self) -> RigidBody { fn from(val: RigidBodyBuilder) -> RigidBody {
self.build() val.build()
} }
} }

View File

@@ -399,7 +399,7 @@ impl RigidBodyMassProps {
/// Update the world-space mass properties of `self`, taking into account the new position. /// Update the world-space mass properties of `self`, taking into account the new position.
pub fn update_world_mass_properties(&mut self, position: &Isometry<Real>) { pub fn update_world_mass_properties(&mut self, position: &Isometry<Real>) {
self.world_com = self.local_mprops.world_com(&position); self.world_com = self.local_mprops.world_com(position);
self.effective_inv_mass = Vector::repeat(self.local_mprops.inv_mass); self.effective_inv_mass = Vector::repeat(self.local_mprops.inv_mass);
self.effective_world_inv_inertia_sqrt = self.effective_world_inv_inertia_sqrt =
self.local_mprops.world_inv_inertia_sqrt(&position.rotation); self.local_mprops.world_inv_inertia_sqrt(&position.rotation);
@@ -707,7 +707,6 @@ impl std::ops::Add<RigidBodyVelocity> for RigidBodyVelocity {
} }
impl std::ops::AddAssign<RigidBodyVelocity> for RigidBodyVelocity { impl std::ops::AddAssign<RigidBodyVelocity> for RigidBodyVelocity {
#[must_use]
fn add_assign(&mut self, rhs: Self) { fn add_assign(&mut self, rhs: Self) {
self.linvel += rhs.linvel; self.linvel += rhs.linvel;
self.angvel += rhs.angvel; self.angvel += rhs.angvel;
@@ -788,7 +787,7 @@ impl RigidBodyForces {
gravity: &Vector<Real>, gravity: &Vector<Real>,
mass: &Vector<Real>, mass: &Vector<Real>,
) { ) {
self.force = self.user_force + gravity.component_mul(&mass) * self.gravity_scale; self.force = self.user_force + gravity.component_mul(mass) * self.gravity_scale;
self.torque = self.user_torque; self.torque = self.user_torque;
} }
@@ -877,7 +876,7 @@ impl RigidBodyCcd {
} }
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash)] #[derive(Default, Clone, Debug, Copy, PartialEq, Eq, Hash)]
/// Internal identifiers used by the physics engine. /// Internal identifiers used by the physics engine.
pub struct RigidBodyIds { pub struct RigidBodyIds {
pub(crate) active_island_id: usize, pub(crate) active_island_id: usize,
@@ -886,19 +885,8 @@ pub struct RigidBodyIds {
pub(crate) active_set_timestamp: u32, pub(crate) active_set_timestamp: u32,
} }
impl Default for RigidBodyIds {
fn default() -> Self {
Self {
active_island_id: 0,
active_set_id: 0,
active_set_offset: 0,
active_set_timestamp: 0,
}
}
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Default, Clone, Debug, PartialEq, Eq)]
/// The set of colliders attached to this rigid-bodies. /// The set of colliders attached to this rigid-bodies.
/// ///
/// This should not be modified manually unless you really know what /// This should not be modified manually unless you really know what
@@ -906,12 +894,6 @@ impl Default for RigidBodyIds {
/// to a game engine using its component-based interface). /// to a game engine using its component-based interface).
pub struct RigidBodyColliders(pub Vec<ColliderHandle>); pub struct RigidBodyColliders(pub Vec<ColliderHandle>);
impl Default for RigidBodyColliders {
fn default() -> Self {
Self(vec![])
}
}
impl RigidBodyColliders { impl RigidBodyColliders {
/// Detach a collider from this rigid-body. /// Detach a collider from this rigid-body.
pub fn detach_collider( pub fn detach_collider(
@@ -987,16 +969,10 @@ impl RigidBodyColliders {
} }
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Default, Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// The dominance groups of a rigid-body. /// The dominance groups of a rigid-body.
pub struct RigidBodyDominance(pub i8); pub struct RigidBodyDominance(pub i8);
impl Default for RigidBodyDominance {
fn default() -> Self {
RigidBodyDominance(0)
}
}
impl RigidBodyDominance { impl RigidBodyDominance {
/// The actual dominance group of this rigid-body, after taking into account its type. /// The actual dominance group of this rigid-body, after taking into account its type.
pub fn effective_group(&self, status: &RigidBodyType) -> i16 { pub fn effective_group(&self, status: &RigidBodyType) -> i16 {

View File

@@ -44,7 +44,7 @@ impl RigidBodySet {
} }
pub(crate) fn take_modified(&mut self) -> Vec<RigidBodyHandle> { pub(crate) fn take_modified(&mut self) -> Vec<RigidBodyHandle> {
std::mem::replace(&mut self.modified_bodies, vec![]) std::mem::take(&mut self.modified_bodies)
} }
/// The number of rigid bodies on this set. /// The number of rigid bodies on this set.

View File

@@ -192,7 +192,7 @@ impl ContactConstraintsSet {
.interaction_groups .interaction_groups
.simd_interactions .simd_interactions
.chunks_exact(SIMD_WIDTH) .chunks_exact(SIMD_WIDTH)
.map(|i| ConstraintsCounts::from_contacts(&manifolds_all[i[0]]).num_constraints) .map(|i| ConstraintsCounts::from_contacts(manifolds_all[i[0]]).num_constraints)
.sum(); .sum();
unsafe { unsafe {
@@ -211,7 +211,7 @@ impl ContactConstraintsSet {
.chunks_exact(SIMD_WIDTH) .chunks_exact(SIMD_WIDTH)
{ {
let num_to_add = let num_to_add =
ConstraintsCounts::from_contacts(&manifolds_all[manifolds_i[0]]).num_constraints; ConstraintsCounts::from_contacts(manifolds_all[manifolds_i[0]]).num_constraints;
let manifold_id = gather![|ii| manifolds_i[ii]]; let manifold_id = gather![|ii| manifolds_i[ii]];
let manifolds = gather![|ii| &*manifolds_all[manifolds_i[ii]]]; let manifolds = gather![|ii| &*manifolds_all[manifolds_i[ii]]];
@@ -238,7 +238,7 @@ impl ContactConstraintsSet {
.interaction_groups .interaction_groups
.nongrouped_interactions .nongrouped_interactions
.iter() .iter()
.map(|i| ConstraintsCounts::from_contacts(&manifolds_all[*i]).num_constraints) .map(|i| ConstraintsCounts::from_contacts(manifolds_all[*i]).num_constraints)
.sum(); .sum();
unsafe { unsafe {
@@ -278,7 +278,7 @@ impl ContactConstraintsSet {
let total_num_constraints = self let total_num_constraints = self
.generic_two_body_interactions .generic_two_body_interactions
.iter() .iter()
.map(|i| ConstraintsCounts::from_contacts(&manifolds_all[*i]).num_constraints) .map(|i| ConstraintsCounts::from_contacts(manifolds_all[*i]).num_constraints)
.sum(); .sum();
self.generic_velocity_constraints_builder.resize( self.generic_velocity_constraints_builder.resize(
@@ -321,7 +321,7 @@ impl ContactConstraintsSet {
let total_num_constraints = self let total_num_constraints = self
.generic_one_body_interactions .generic_one_body_interactions
.iter() .iter()
.map(|i| ConstraintsCounts::from_contacts(&manifolds_all[*i]).num_constraints) .map(|i| ConstraintsCounts::from_contacts(manifolds_all[*i]).num_constraints)
.sum(); .sum();
self.generic_velocity_one_body_constraints_builder.resize( self.generic_velocity_one_body_constraints_builder.resize(
total_num_constraints, total_num_constraints,
@@ -362,7 +362,7 @@ impl ContactConstraintsSet {
.one_body_interaction_groups .one_body_interaction_groups
.simd_interactions .simd_interactions
.chunks_exact(SIMD_WIDTH) .chunks_exact(SIMD_WIDTH)
.map(|i| ConstraintsCounts::from_contacts(&manifolds_all[i[0]]).num_constraints) .map(|i| ConstraintsCounts::from_contacts(manifolds_all[i[0]]).num_constraints)
.sum(); .sum();
unsafe { unsafe {
@@ -384,7 +384,7 @@ impl ContactConstraintsSet {
.chunks_exact(SIMD_WIDTH) .chunks_exact(SIMD_WIDTH)
{ {
let num_to_add = let num_to_add =
ConstraintsCounts::from_contacts(&manifolds_all[manifolds_i[0]]).num_constraints; ConstraintsCounts::from_contacts(manifolds_all[manifolds_i[0]]).num_constraints;
let manifold_id = gather![|ii| manifolds_i[ii]]; let manifold_id = gather![|ii| manifolds_i[ii]];
let manifolds = gather![|ii| &*manifolds_all[manifolds_i[ii]]]; let manifolds = gather![|ii| &*manifolds_all[manifolds_i[ii]]];
SimdOneBodyConstraintBuilder::generate( SimdOneBodyConstraintBuilder::generate(
@@ -408,7 +408,7 @@ impl ContactConstraintsSet {
.one_body_interaction_groups .one_body_interaction_groups
.nongrouped_interactions .nongrouped_interactions
.iter() .iter()
.map(|i| ConstraintsCounts::from_contacts(&manifolds_all[*i]).num_constraints) .map(|i| ConstraintsCounts::from_contacts(manifolds_all[*i]).num_constraints)
.sum(); .sum();
unsafe { unsafe {

View File

@@ -59,7 +59,7 @@ impl GenericOneBodyConstraintBuilder {
let rb1 = handle1 let rb1 = handle1
.map(|h| SolverBody::from(&bodies[h])) .map(|h| SolverBody::from(&bodies[h]))
.unwrap_or_else(SolverBody::default); .unwrap_or_default();
let rb2 = &bodies[handle2.unwrap()]; let rb2 = &bodies[handle2.unwrap()];
let (vels2, mprops2) = (&rb2.vels, &rb2.mprops); let (vels2, mprops2) = (&rb2.vels, &rb2.mprops);
@@ -265,7 +265,7 @@ impl GenericOneBodyConstraint {
solve_restitution: bool, solve_restitution: bool,
solve_friction: bool, solve_friction: bool,
) { ) {
let solver_vel2 = self.inner.solver_vel2 as usize; let solver_vel2 = self.inner.solver_vel2;
let elements = &mut self.inner.elements[..self.inner.num_contacts as usize]; let elements = &mut self.inner.elements[..self.inner.num_contacts as usize];
OneBodyConstraintElement::generic_solve_group( OneBodyConstraintElement::generic_solve_group(

View File

@@ -382,15 +382,15 @@ impl GenericTwoBodyConstraint {
solve_friction: bool, solve_friction: bool,
) { ) {
let mut solver_vel1 = if self.generic_constraint_mask & 0b01 == 0 { let mut solver_vel1 = if self.generic_constraint_mask & 0b01 == 0 {
GenericRhs::SolverVel(solver_vels[self.inner.solver_vel1 as usize]) GenericRhs::SolverVel(solver_vels[self.inner.solver_vel1])
} else { } else {
GenericRhs::GenericId(self.inner.solver_vel1 as usize) GenericRhs::GenericId(self.inner.solver_vel1)
}; };
let mut solver_vel2 = if self.generic_constraint_mask & 0b10 == 0 { let mut solver_vel2 = if self.generic_constraint_mask & 0b10 == 0 {
GenericRhs::SolverVel(solver_vels[self.inner.solver_vel2 as usize]) GenericRhs::SolverVel(solver_vels[self.inner.solver_vel2])
} else { } else {
GenericRhs::GenericId(self.inner.solver_vel2 as usize) GenericRhs::GenericId(self.inner.solver_vel2)
}; };
let elements = &mut self.inner.elements[..self.inner.num_contacts as usize]; let elements = &mut self.inner.elements[..self.inner.num_contacts as usize];
@@ -415,11 +415,11 @@ impl GenericTwoBodyConstraint {
); );
if let GenericRhs::SolverVel(solver_vel1) = solver_vel1 { if let GenericRhs::SolverVel(solver_vel1) = solver_vel1 {
solver_vels[self.inner.solver_vel1 as usize] = solver_vel1; solver_vels[self.inner.solver_vel1] = solver_vel1;
} }
if let GenericRhs::SolverVel(solver_vel2) = solver_vel2 { if let GenericRhs::SolverVel(solver_vel2) = solver_vel2 {
solver_vels[self.inner.solver_vel2 as usize] = solver_vel2; solver_vels[self.inner.solver_vel2] = solver_vel2;
} }
} }

View File

@@ -114,7 +114,7 @@ impl TwoBodyConstraintTangentPart<Real> {
j_id1, j_id1,
ndofs1, ndofs1,
jacobians, jacobians,
&tangents1[0], tangents1[0],
&self.gcross1[0], &self.gcross1[0],
solver_vels, solver_vels,
) + solver_vel2.dvel( ) + solver_vel2.dvel(
@@ -135,7 +135,7 @@ impl TwoBodyConstraintTangentPart<Real> {
ndofs1, ndofs1,
dlambda, dlambda,
jacobians, jacobians,
&tangents1[0], tangents1[0],
&self.gcross1[0], &self.gcross1[0],
solver_vels, solver_vels,
im1, im1,
@@ -158,7 +158,7 @@ impl TwoBodyConstraintTangentPart<Real> {
j_id1, j_id1,
ndofs1, ndofs1,
jacobians, jacobians,
&tangents1[0], tangents1[0],
&self.gcross1[0], &self.gcross1[0],
solver_vels, solver_vels,
) + solver_vel2.dvel( ) + solver_vel2.dvel(
@@ -173,7 +173,7 @@ impl TwoBodyConstraintTangentPart<Real> {
j_id1 + j_step, j_id1 + j_step,
ndofs1, ndofs1,
jacobians, jacobians,
&tangents1[1], tangents1[1],
&self.gcross1[1], &self.gcross1[1],
solver_vels, solver_vels,
) + solver_vel2.dvel( ) + solver_vel2.dvel(
@@ -199,7 +199,7 @@ impl TwoBodyConstraintTangentPart<Real> {
ndofs1, ndofs1,
dlambda[0], dlambda[0],
jacobians, jacobians,
&tangents1[0], tangents1[0],
&self.gcross1[0], &self.gcross1[0],
solver_vels, solver_vels,
im1, im1,
@@ -209,7 +209,7 @@ impl TwoBodyConstraintTangentPart<Real> {
ndofs1, ndofs1,
dlambda[1], dlambda[1],
jacobians, jacobians,
&tangents1[1], tangents1[1],
&self.gcross1[1], &self.gcross1[1],
solver_vels, solver_vels,
im1, im1,
@@ -258,7 +258,7 @@ impl TwoBodyConstraintNormalPart<Real> {
let j_id1 = j_id1(j_id, ndofs1, ndofs2); let j_id1 = j_id1(j_id, ndofs1, ndofs2);
let j_id2 = j_id2(j_id, ndofs1, ndofs2); let j_id2 = j_id2(j_id, ndofs1, ndofs2);
let dvel = solver_vel1.dvel(j_id1, ndofs1, jacobians, &dir1, &self.gcross1, solver_vels) let dvel = solver_vel1.dvel(j_id1, ndofs1, jacobians, dir1, &self.gcross1, solver_vels)
+ solver_vel2.dvel(j_id2, ndofs2, jacobians, &-dir1, &self.gcross2, solver_vels) + solver_vel2.dvel(j_id2, ndofs2, jacobians, &-dir1, &self.gcross2, solver_vels)
+ self.rhs; + self.rhs;
@@ -271,7 +271,7 @@ impl TwoBodyConstraintNormalPart<Real> {
ndofs1, ndofs1,
dlambda, dlambda,
jacobians, jacobians,
&dir1, dir1,
&self.gcross1, &self.gcross1,
solver_vels, solver_vels,
im1, im1,
@@ -323,7 +323,7 @@ impl TwoBodyConstraintElement<Real> {
cfm_factor, cfm_factor,
nrm_j_id, nrm_j_id,
jacobians, jacobians,
&dir1, dir1,
im1, im1,
im2, im2,
ndofs1, ndofs1,
@@ -339,7 +339,7 @@ impl TwoBodyConstraintElement<Real> {
// Solve friction. // Solve friction.
if solve_friction { if solve_friction {
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
let tangents1 = [tangent1, &dir1.cross(&tangent1)]; let tangents1 = [tangent1, &dir1.cross(tangent1)];
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
let tangents1 = [&dir1.orthonormal_vector()]; let tangents1 = [&dir1.orthonormal_vector()];
let mut tng_j_id = tangent_j_id(j_id, ndofs1, ndofs2); let mut tng_j_id = tangent_j_id(j_id, ndofs1, ndofs2);

View File

@@ -76,7 +76,7 @@ impl OneBodyConstraintBuilder {
let rb1 = handle1 let rb1 = handle1
.map(|h| SolverBody::from(&bodies[h])) .map(|h| SolverBody::from(&bodies[h]))
.unwrap_or_else(SolverBody::default); .unwrap_or_default();
let rb2 = &bodies[handle2.unwrap()]; let rb2 = &bodies[handle2.unwrap()];
let vels2 = &rb2.vels; let vels2 = &rb2.vels;
@@ -334,7 +334,7 @@ impl OneBodyConstraint {
solve_normal: bool, solve_normal: bool,
solve_friction: bool, solve_friction: bool,
) { ) {
let mut solver_vel2 = solver_vels[self.solver_vel2 as usize]; let mut solver_vel2 = solver_vels[self.solver_vel2];
OneBodyConstraintElement::solve_group( OneBodyConstraintElement::solve_group(
self.cfm_factor, self.cfm_factor,
@@ -349,7 +349,7 @@ impl OneBodyConstraint {
solve_friction, solve_friction,
); );
solver_vels[self.solver_vel2 as usize] = solver_vel2; solver_vels[self.solver_vel2] = solver_vel2;
} }
// FIXME: duplicated code. This is exactly the same as in the two-body velocity constraint. // FIXME: duplicated code. This is exactly the same as in the two-body velocity constraint.

View File

@@ -204,7 +204,7 @@ impl<N: SimdRealCopy> OneBodyConstraintElement<N> {
AngVector<N>: SimdDot<AngVector<N>, Result = N>, AngVector<N>: SimdDot<AngVector<N>, Result = N>,
{ {
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
let tangents1 = [tangent1, &dir1.cross(&tangent1)]; let tangents1 = [tangent1, &dir1.cross(tangent1)];
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
let tangents1 = [&dir1.orthonormal_vector()]; let tangents1 = [&dir1.orthonormal_vector()];
@@ -213,7 +213,7 @@ impl<N: SimdRealCopy> OneBodyConstraintElement<N> {
for element in elements.iter_mut() { for element in elements.iter_mut() {
element element
.normal_part .normal_part
.solve(cfm_factor, &dir1, im2, solver_vel2); .solve(cfm_factor, dir1, im2, solver_vel2);
let limit = limit * element.normal_part.impulse; let limit = limit * element.normal_part.impulse;
let part = &mut element.tangent_part; let part = &mut element.tangent_part;
part.apply_limit(tangents1, im2, limit, solver_vel2); part.apply_limit(tangents1, im2, limit, solver_vel2);

View File

@@ -308,12 +308,8 @@ impl OneBodyConstraintSimd {
solve_friction: bool, solve_friction: bool,
) { ) {
let mut solver_vel2 = SolverVel { let mut solver_vel2 = SolverVel {
linear: Vector::from(gather![ linear: Vector::from(gather![|ii| solver_vels[self.solver_vel2[ii]].linear]),
|ii| solver_vels[self.solver_vel2[ii] as usize].linear angular: AngVector::from(gather![|ii| solver_vels[self.solver_vel2[ii]].angular]),
]),
angular: AngVector::from(gather![
|ii| solver_vels[self.solver_vel2[ii] as usize].angular
]),
}; };
OneBodyConstraintElement::solve_group( OneBodyConstraintElement::solve_group(
@@ -330,8 +326,8 @@ impl OneBodyConstraintSimd {
); );
for ii in 0..SIMD_WIDTH { for ii in 0..SIMD_WIDTH {
solver_vels[self.solver_vel2[ii] as usize].linear = solver_vel2.linear.extract(ii); solver_vels[self.solver_vel2[ii]].linear = solver_vel2.linear.extract(ii);
solver_vels[self.solver_vel2[ii] as usize].angular = solver_vel2.angular.extract(ii); solver_vels[self.solver_vel2[ii]].angular = solver_vel2.angular.extract(ii);
} }
} }

View File

@@ -380,8 +380,8 @@ impl TwoBodyConstraint {
solve_normal: bool, solve_normal: bool,
solve_friction: bool, solve_friction: bool,
) { ) {
let mut solver_vel1 = solver_vels[self.solver_vel1 as usize]; let mut solver_vel1 = solver_vels[self.solver_vel1];
let mut solver_vel2 = solver_vels[self.solver_vel2 as usize]; let mut solver_vel2 = solver_vels[self.solver_vel2];
TwoBodyConstraintElement::solve_group( TwoBodyConstraintElement::solve_group(
self.cfm_factor, self.cfm_factor,
@@ -398,8 +398,8 @@ impl TwoBodyConstraint {
solve_friction, solve_friction,
); );
solver_vels[self.solver_vel1 as usize] = solver_vel1; solver_vels[self.solver_vel1] = solver_vel1;
solver_vels[self.solver_vel2 as usize] = solver_vel2; solver_vels[self.solver_vel2] = solver_vel2;
} }
pub fn writeback_impulses(&self, manifolds_all: &mut [&mut ContactManifold]) { pub fn writeback_impulses(&self, manifolds_all: &mut [&mut ContactManifold]) {

View File

@@ -243,7 +243,7 @@ impl<N: SimdRealCopy> TwoBodyConstraintElement<N> {
AngVector<N>: SimdDot<AngVector<N>, Result = N>, AngVector<N>: SimdDot<AngVector<N>, Result = N>,
{ {
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
let tangents1 = [tangent1, &dir1.cross(&tangent1)]; let tangents1 = [tangent1, &dir1.cross(tangent1)];
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
let tangents1 = [&dir1.orthonormal_vector()]; let tangents1 = [&dir1.orthonormal_vector()];
@@ -252,7 +252,7 @@ impl<N: SimdRealCopy> TwoBodyConstraintElement<N> {
for element in elements.iter_mut() { for element in elements.iter_mut() {
element element
.normal_part .normal_part
.solve(cfm_factor, &dir1, im1, im2, solver_vel1, solver_vel2); .solve(cfm_factor, dir1, im1, im2, solver_vel1, solver_vel2);
let limit = limit * element.normal_part.impulse; let limit = limit * element.normal_part.impulse;
let part = &mut element.tangent_part; let part = &mut element.tangent_part;
part.apply_limit(tangents1, im1, im2, limit, solver_vel1, solver_vel2); part.apply_limit(tangents1, im1, im2, limit, solver_vel1, solver_vel2);

View File

@@ -292,21 +292,13 @@ impl TwoBodyConstraintSimd {
solve_friction: bool, solve_friction: bool,
) { ) {
let mut solver_vel1 = SolverVel { let mut solver_vel1 = SolverVel {
linear: Vector::from(gather![ linear: Vector::from(gather![|ii| solver_vels[self.solver_vel1[ii]].linear]),
|ii| solver_vels[self.solver_vel1[ii] as usize].linear angular: AngVector::from(gather![|ii| solver_vels[self.solver_vel1[ii]].angular]),
]),
angular: AngVector::from(gather![
|ii| solver_vels[self.solver_vel1[ii] as usize].angular
]),
}; };
let mut solver_vel2 = SolverVel { let mut solver_vel2 = SolverVel {
linear: Vector::from(gather![ linear: Vector::from(gather![|ii| solver_vels[self.solver_vel2[ii]].linear]),
|ii| solver_vels[self.solver_vel2[ii] as usize].linear angular: AngVector::from(gather![|ii| solver_vels[self.solver_vel2[ii]].angular]),
]),
angular: AngVector::from(gather![
|ii| solver_vels[self.solver_vel2[ii] as usize].angular
]),
}; };
TwoBodyConstraintElement::solve_group( TwoBodyConstraintElement::solve_group(
@@ -325,12 +317,12 @@ impl TwoBodyConstraintSimd {
); );
for ii in 0..SIMD_WIDTH { for ii in 0..SIMD_WIDTH {
solver_vels[self.solver_vel1[ii] as usize].linear = solver_vel1.linear.extract(ii); solver_vels[self.solver_vel1[ii]].linear = solver_vel1.linear.extract(ii);
solver_vels[self.solver_vel1[ii] as usize].angular = solver_vel1.angular.extract(ii); solver_vels[self.solver_vel1[ii]].angular = solver_vel1.angular.extract(ii);
} }
for ii in 0..SIMD_WIDTH { for ii in 0..SIMD_WIDTH {
solver_vels[self.solver_vel2[ii] as usize].linear = solver_vel2.linear.extract(ii); solver_vels[self.solver_vel2[ii]].linear = solver_vel2.linear.extract(ii);
solver_vels[self.solver_vel2[ii] as usize].angular = solver_vel2.angular.extract(ii); solver_vels[self.solver_vel2[ii]].angular = solver_vel2.angular.extract(ii);
} }
} }

View File

@@ -25,7 +25,7 @@ impl<'a> PairInteraction for &'a mut ContactManifold {
} }
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
impl<'a> PairInteraction for JointGraphEdge { impl PairInteraction for JointGraphEdge {
fn body_pair(&self) -> (Option<RigidBodyHandle>, Option<RigidBodyHandle>) { fn body_pair(&self) -> (Option<RigidBodyHandle>, Option<RigidBodyHandle>) {
(Some(self.weight.body1), Some(self.weight.body2)) (Some(self.weight.body1), Some(self.weight.body2))
} }
@@ -470,11 +470,11 @@ impl InteractionGroups {
(bucket.0)[SIMD_LAST_INDEX] = *interaction_i; (bucket.0)[SIMD_LAST_INDEX] = *interaction_i;
self.simd_interactions.extend_from_slice(&bucket.0); self.simd_interactions.extend_from_slice(&bucket.0);
bucket.1 = 0; bucket.1 = 0;
occupied_mask = occupied_mask & (!target_mask_bit); occupied_mask &= !target_mask_bit;
} else { } else {
(bucket.0)[bucket.1] = *interaction_i; (bucket.0)[bucket.1] = *interaction_i;
bucket.1 += 1; bucket.1 += 1;
occupied_mask = occupied_mask | target_mask_bit; occupied_mask |= target_mask_bit;
} }
// NOTE: fixed bodies don't transmit forces. Therefore they don't // NOTE: fixed bodies don't transmit forces. Therefore they don't

View File

@@ -399,7 +399,7 @@ impl JointConstraintsSet {
) { ) {
for builder in &mut self.generic_velocity_constraints_builder { for builder in &mut self.generic_velocity_constraints_builder {
builder.update( builder.update(
&params, params,
multibodies, multibodies,
solver_bodies, solver_bodies,
&mut self.generic_jacobians, &mut self.generic_jacobians,
@@ -409,7 +409,7 @@ impl JointConstraintsSet {
for builder in &mut self.generic_velocity_one_body_constraints_builder { for builder in &mut self.generic_velocity_one_body_constraints_builder {
builder.update( builder.update(
&params, params,
multibodies, multibodies,
solver_bodies, solver_bodies,
&mut self.generic_jacobians, &mut self.generic_jacobians,
@@ -418,17 +418,17 @@ impl JointConstraintsSet {
} }
for builder in &mut self.velocity_constraints_builder { for builder in &mut self.velocity_constraints_builder {
builder.update(&params, solver_bodies, &mut self.velocity_constraints); builder.update(params, solver_bodies, &mut self.velocity_constraints);
} }
#[cfg(feature = "simd-is-enabled")] #[cfg(feature = "simd-is-enabled")]
for builder in &mut self.simd_velocity_constraints_builder { for builder in &mut self.simd_velocity_constraints_builder {
builder.update(&params, solver_bodies, &mut self.simd_velocity_constraints); builder.update(params, solver_bodies, &mut self.simd_velocity_constraints);
} }
for builder in &mut self.velocity_one_body_constraints_builder { for builder in &mut self.velocity_one_body_constraints_builder {
builder.update( builder.update(
&params, params,
solver_bodies, solver_bodies,
&mut self.velocity_one_body_constraints, &mut self.velocity_one_body_constraints,
); );
@@ -437,7 +437,7 @@ impl JointConstraintsSet {
#[cfg(feature = "simd-is-enabled")] #[cfg(feature = "simd-is-enabled")]
for builder in &mut self.simd_velocity_one_body_constraints_builder { for builder in &mut self.simd_velocity_one_body_constraints_builder {
builder.update( builder.update(
&params, params,
solver_bodies, solver_bodies,
&mut self.simd_velocity_one_body_constraints, &mut self.simd_velocity_one_body_constraints,
); );

View File

@@ -219,6 +219,7 @@ impl JointGenericTwoBodyConstraintBuilder {
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[allow(clippy::large_enum_variant)]
pub enum JointGenericOneBodyConstraintBuilder { pub enum JointGenericOneBodyConstraintBuilder {
Internal(JointGenericVelocityOneBodyInternalConstraintBuilder), Internal(JointGenericVelocityOneBodyInternalConstraintBuilder),
External(JointGenericVelocityOneBodyExternalConstraintBuilder), External(JointGenericVelocityOneBodyExternalConstraintBuilder),

View File

@@ -332,13 +332,13 @@ impl JointTwoBodyConstraint<Real, 1> {
} }
pub fn solve(&mut self, solver_vels: &mut [SolverVel<Real>]) { pub fn solve(&mut self, solver_vels: &mut [SolverVel<Real>]) {
let mut solver_vel1 = solver_vels[self.solver_vel1[0] as usize]; let mut solver_vel1 = solver_vels[self.solver_vel1[0]];
let mut solver_vel2 = solver_vels[self.solver_vel2[0] as usize]; let mut solver_vel2 = solver_vels[self.solver_vel2[0]];
self.solve_generic(&mut solver_vel1, &mut solver_vel2); self.solve_generic(&mut solver_vel1, &mut solver_vel2);
solver_vels[self.solver_vel1[0] as usize] = solver_vel1; solver_vels[self.solver_vel1[0]] = solver_vel1;
solver_vels[self.solver_vel2[0] as usize] = solver_vel2; solver_vels[self.solver_vel2[0]] = solver_vel2;
} }
pub fn writeback_impulses(&self, joints_all: &mut [JointGraphEdge]) { pub fn writeback_impulses(&self, joints_all: &mut [JointGraphEdge]) {
@@ -399,29 +399,21 @@ impl JointTwoBodyConstraint<SimdReal, SIMD_WIDTH> {
pub fn solve(&mut self, solver_vels: &mut [SolverVel<Real>]) { pub fn solve(&mut self, solver_vels: &mut [SolverVel<Real>]) {
let mut solver_vel1 = SolverVel { let mut solver_vel1 = SolverVel {
linear: Vector::from(gather![ linear: Vector::from(gather![|ii| solver_vels[self.solver_vel1[ii]].linear]),
|ii| solver_vels[self.solver_vel1[ii] as usize].linear angular: AngVector::from(gather![|ii| solver_vels[self.solver_vel1[ii]].angular]),
]),
angular: AngVector::from(gather![
|ii| solver_vels[self.solver_vel1[ii] as usize].angular
]),
}; };
let mut solver_vel2 = SolverVel { let mut solver_vel2 = SolverVel {
linear: Vector::from(gather![ linear: Vector::from(gather![|ii| solver_vels[self.solver_vel2[ii]].linear]),
|ii| solver_vels[self.solver_vel2[ii] as usize].linear angular: AngVector::from(gather![|ii| solver_vels[self.solver_vel2[ii]].angular]),
]),
angular: AngVector::from(gather![
|ii| solver_vels[self.solver_vel2[ii] as usize].angular
]),
}; };
self.solve_generic(&mut solver_vel1, &mut solver_vel2); self.solve_generic(&mut solver_vel1, &mut solver_vel2);
for ii in 0..SIMD_WIDTH { for ii in 0..SIMD_WIDTH {
solver_vels[self.solver_vel1[ii] as usize].linear = solver_vel1.linear.extract(ii); solver_vels[self.solver_vel1[ii]].linear = solver_vel1.linear.extract(ii);
solver_vels[self.solver_vel1[ii] as usize].angular = solver_vel1.angular.extract(ii); solver_vels[self.solver_vel1[ii]].angular = solver_vel1.angular.extract(ii);
solver_vels[self.solver_vel2[ii] as usize].linear = solver_vel2.linear.extract(ii); solver_vels[self.solver_vel2[ii]].linear = solver_vel2.linear.extract(ii);
solver_vels[self.solver_vel2[ii] as usize].angular = solver_vel2.angular.extract(ii); solver_vels[self.solver_vel2[ii]].angular = solver_vel2.angular.extract(ii);
} }
} }
@@ -682,9 +674,9 @@ impl JointOneBodyConstraint<Real, 1> {
} }
pub fn solve(&mut self, solver_vels: &mut [SolverVel<Real>]) { pub fn solve(&mut self, solver_vels: &mut [SolverVel<Real>]) {
let mut solver_vel2 = solver_vels[self.solver_vel2[0] as usize]; let mut solver_vel2 = solver_vels[self.solver_vel2[0]];
self.solve_generic(&mut solver_vel2); self.solve_generic(&mut solver_vel2);
solver_vels[self.solver_vel2[0] as usize] = solver_vel2; solver_vels[self.solver_vel2[0]] = solver_vel2;
} }
pub fn writeback_impulses(&self, joints_all: &mut [JointGraphEdge]) { pub fn writeback_impulses(&self, joints_all: &mut [JointGraphEdge]) {
@@ -751,19 +743,15 @@ impl JointOneBodyConstraint<SimdReal, SIMD_WIDTH> {
pub fn solve(&mut self, solver_vels: &mut [SolverVel<Real>]) { pub fn solve(&mut self, solver_vels: &mut [SolverVel<Real>]) {
let mut solver_vel2 = SolverVel { let mut solver_vel2 = SolverVel {
linear: Vector::from(gather![ linear: Vector::from(gather![|ii| solver_vels[self.solver_vel2[ii]].linear]),
|ii| solver_vels[self.solver_vel2[ii] as usize].linear angular: AngVector::from(gather![|ii| solver_vels[self.solver_vel2[ii]].angular]),
]),
angular: AngVector::from(gather![
|ii| solver_vels[self.solver_vel2[ii] as usize].angular
]),
}; };
self.solve_generic(&mut solver_vel2); self.solve_generic(&mut solver_vel2);
for ii in 0..SIMD_WIDTH { for ii in 0..SIMD_WIDTH {
solver_vels[self.solver_vel2[ii] as usize].linear = solver_vel2.linear.extract(ii); solver_vels[self.solver_vel2[ii]].linear = solver_vel2.linear.extract(ii);
solver_vels[self.solver_vel2[ii] as usize].angular = solver_vel2.angular.extract(ii); solver_vels[self.solver_vel2[ii]].angular = solver_vel2.angular.extract(ii);
} }
} }

View File

@@ -7,17 +7,17 @@ pub(crate) use self::island_solver::IslandSolver;
// #[cfg(feature = "parallel")] // #[cfg(feature = "parallel")]
// pub(self) use self::parallel_velocity_solver::ParallelVelocitySolver; // pub(self) use self::parallel_velocity_solver::ParallelVelocitySolver;
// #[cfg(not(feature = "parallel"))] // #[cfg(not(feature = "parallel"))]
pub(self) use self::solver_constraints_set::SolverConstraintsSet; use self::solver_constraints_set::SolverConstraintsSet;
// #[cfg(not(feature = "parallel"))] // #[cfg(not(feature = "parallel"))]
pub(self) use self::velocity_solver::VelocitySolver; use self::velocity_solver::VelocitySolver;
pub(self) use contact_constraint::*; use contact_constraint::*;
pub(self) use interaction_groups::*; use interaction_groups::*;
pub(crate) use joint_constraint::MotorParameters; pub(crate) use joint_constraint::MotorParameters;
pub use joint_constraint::*; pub use joint_constraint::*;
pub(self) use solver_body::SolverBody; use solver_body::SolverBody;
pub(self) use solver_constraints_set::{AnyConstraintMut, ConstraintTypes}; use solver_constraints_set::{AnyConstraintMut, ConstraintTypes};
pub(self) use solver_vel::SolverVel; use solver_vel::SolverVel;
mod categorization; mod categorization;
mod contact_constraint; mod contact_constraint;

View File

@@ -175,8 +175,8 @@ impl VelocitySolver {
/* /*
* Update & solve constraints. * Update & solve constraints.
*/ */
joint_constraints.update(&params, multibodies, &self.solver_bodies); joint_constraints.update(params, multibodies, &self.solver_bodies);
contact_constraints.update(&params, substep_id, multibodies, &self.solver_bodies); contact_constraints.update(params, substep_id, multibodies, &self.solver_bodies);
for _ in 0..params.num_internal_pgs_iterations { for _ in 0..params.num_internal_pgs_iterations {
joint_constraints.solve(&mut self.solver_vels, &mut self.generic_solver_vels); joint_constraints.solve(&mut self.solver_vels, &mut self.generic_solver_vels);
@@ -196,7 +196,7 @@ impl VelocitySolver {
/* /*
* Integrate positions. * Integrate positions.
*/ */
self.integrate_positions(&params, is_last_substep, bodies, multibodies); self.integrate_positions(params, is_last_substep, bodies, multibodies);
/* /*
* Resolution without bias. * Resolution without bias.

View File

@@ -445,9 +445,8 @@ impl BroadPhase {
); );
} }
let need_region_propagation = !layer.created_regions.is_empty(); // Returns true if propagation is needed.
!layer.created_regions.is_empty()
need_region_propagation
} }
/// Updates the broad-phase, taking into account the new collider positions. /// Updates the broad-phase, taking into account the new collider positions.

View File

@@ -2,12 +2,12 @@ pub use self::broad_phase::BroadPhase;
pub use self::broad_phase_pair_event::{BroadPhasePairEvent, ColliderPair}; pub use self::broad_phase_pair_event::{BroadPhasePairEvent, ColliderPair};
pub use self::sap_proxy::SAPProxyIndex; pub use self::sap_proxy::SAPProxyIndex;
pub(self) use self::sap_axis::*; use self::sap_axis::*;
pub(self) use self::sap_endpoint::*; use self::sap_endpoint::*;
pub(self) use self::sap_layer::*; use self::sap_layer::*;
pub(self) use self::sap_proxy::*; use self::sap_proxy::*;
pub(self) use self::sap_region::*; use self::sap_region::*;
pub(self) use self::sap_utils::*; use self::sap_utils::*;
mod broad_phase; mod broad_phase;
mod broad_phase_pair_event; mod broad_phase_pair_event;

View File

@@ -65,9 +65,8 @@ impl SAPAxis {
proxy.aabb, proxy.aabb,
self.min_bound self.min_bound
); );
let start_endpoint = let start_endpoint = SAPEndpoint::start_endpoint(proxy.aabb.mins[dim], *proxy_id);
SAPEndpoint::start_endpoint(proxy.aabb.mins[dim], *proxy_id as u32); let end_endpoint = SAPEndpoint::end_endpoint(proxy.aabb.maxs[dim], *proxy_id);
let end_endpoint = SAPEndpoint::end_endpoint(proxy.aabb.maxs[dim], *proxy_id as u32);
self.new_endpoints.push((start_endpoint, 0)); self.new_endpoints.push((start_endpoint, 0));
self.new_endpoints.push((end_endpoint, 0)); self.new_endpoints.push((end_endpoint, 0));

View File

@@ -15,10 +15,7 @@ pub enum SAPProxyData {
impl SAPProxyData { impl SAPProxyData {
pub fn is_region(&self) -> bool { pub fn is_region(&self) -> bool {
match self { matches!(self, SAPProxyData::Region(_))
SAPProxyData::Region(_) => true,
_ => false,
}
} }
pub fn as_region(&self) -> &SAPRegion { pub fn as_region(&self) -> &SAPRegion {
@@ -102,7 +99,7 @@ impl SAPProxies {
} }
pub fn insert(&mut self, proxy: SAPProxy) -> SAPProxyIndex { pub fn insert(&mut self, proxy: SAPProxy) -> SAPProxyIndex {
let result = if self.first_free != NEXT_FREE_SENTINEL { if self.first_free != NEXT_FREE_SENTINEL {
let proxy_id = self.first_free; let proxy_id = self.first_free;
self.first_free = self.elements[proxy_id as usize].next_free; self.first_free = self.elements[proxy_id as usize].next_free;
self.elements[proxy_id as usize] = proxy; self.elements[proxy_id as usize] = proxy;
@@ -110,15 +107,13 @@ impl SAPProxies {
} else { } else {
self.elements.push(proxy); self.elements.push(proxy);
self.elements.len() as u32 - 1 self.elements.len() as u32 - 1
}; }
result
} }
pub fn remove(&mut self, proxy_id: SAPProxyIndex) { pub fn remove(&mut self, proxy_id: SAPProxyIndex) {
let proxy = &mut self.elements[proxy_id as usize]; let proxy = &mut self.elements[proxy_id as usize];
proxy.next_free = self.first_free; proxy.next_free = self.first_free;
self.first_free = proxy_id as u32; self.first_free = proxy_id;
} }
// NOTE: this must not take holes into account. // NOTE: this must not take holes into account.

View File

@@ -73,6 +73,7 @@ impl SAPRegion {
old old
} }
#[allow(clippy::vec_box)] // PERF: see if Box actually makes it faster (due to less copying).
pub fn recycle_or_new(bounds: Aabb, pool: &mut Vec<Box<Self>>) -> Box<Self> { pub fn recycle_or_new(bounds: Aabb, pool: &mut Vec<Box<Self>>) -> Box<Self> {
if let Some(old) = pool.pop() { if let Some(old) = pool.pop() {
Self::recycle(bounds, old) Self::recycle(bounds, old)

View File

@@ -157,10 +157,7 @@ impl Collider {
/// Is this collider enabled? /// Is this collider enabled?
pub fn is_enabled(&self) -> bool { pub fn is_enabled(&self) -> bool {
match self.flags.enabled { matches!(self.flags.enabled, ColliderEnabled::Enabled)
ColliderEnabled::Enabled => true,
_ => false,
}
} }
/// Sets whether or not this collider is enabled. /// Sets whether or not this collider is enabled.
@@ -916,8 +913,8 @@ impl ColliderBuilder {
} }
} }
impl Into<Collider> for ColliderBuilder { impl From<ColliderBuilder> for Collider {
fn into(self) -> Collider { fn from(val: ColliderBuilder) -> Collider {
self.build() val.build()
} }
} }

View File

@@ -24,11 +24,11 @@ impl ColliderSet {
} }
pub(crate) fn take_modified(&mut self) -> Vec<ColliderHandle> { pub(crate) fn take_modified(&mut self) -> Vec<ColliderHandle> {
std::mem::replace(&mut self.modified_colliders, vec![]) std::mem::take(&mut self.modified_colliders)
} }
pub(crate) fn take_removed(&mut self) -> Vec<ColliderHandle> { pub(crate) fn take_removed(&mut self) -> Vec<ColliderHandle> {
std::mem::replace(&mut self.removed_colliders, vec![]) std::mem::take(&mut self.removed_colliders)
} }
/// An always-invalid collider handle. /// An always-invalid collider handle.

View File

@@ -1,3 +1,5 @@
#![allow(clippy::bad_bit_mask)] // Clippy will complain about the bitmasks due to Group::NONE being 0.
/// Pairwise filtering using bit masks. /// Pairwise filtering using bit masks.
/// ///
/// This filtering method is based on two 32-bit values: /// This filtering method is based on two 32-bit values:

View File

@@ -126,7 +126,7 @@ impl NarrowPhase {
/// The returned contact pairs identify pairs of colliders with intersecting bounding-volumes. /// The returned contact pairs identify pairs of colliders with intersecting bounding-volumes.
/// To check if any geometric contact happened between the collider shapes, check /// To check if any geometric contact happened between the collider shapes, check
/// [`ContactPair::has_any_active_contact`]. /// [`ContactPair::has_any_active_contact`].
pub fn contact_pairs_with<'a>( pub fn contact_pairs_with(
&self, &self,
collider: ColliderHandle, collider: ColliderHandle,
) -> impl Iterator<Item = &ContactPair> { ) -> impl Iterator<Item = &ContactPair> {
@@ -324,7 +324,7 @@ impl NarrowPhase {
&mut self, &mut self,
intersection_graph_id: ColliderGraphIndex, intersection_graph_id: ColliderGraphIndex,
contact_graph_id: ColliderGraphIndex, contact_graph_id: ColliderGraphIndex,
mut islands: Option<&mut IslandManager>, islands: Option<&mut IslandManager>,
colliders: &mut ColliderSet, colliders: &mut ColliderSet,
bodies: &mut RigidBodySet, bodies: &mut RigidBodySet,
prox_id_remap: &mut HashMap<ColliderHandle, ColliderGraphIndex>, prox_id_remap: &mut HashMap<ColliderHandle, ColliderGraphIndex>,
@@ -332,7 +332,7 @@ impl NarrowPhase {
events: &dyn EventHandler, events: &dyn EventHandler,
) { ) {
// Wake up every body in contact with the deleted collider and generate Stopped collision events. // Wake up every body in contact with the deleted collider and generate Stopped collision events.
if let Some(islands) = islands.as_deref_mut() { if let Some(islands) = islands {
for (a, b, pair) in self.contact_graph.interactions_with(contact_graph_id) { for (a, b, pair) in self.contact_graph.interactions_with(contact_graph_id) {
if let Some(parent) = colliders.get(a).and_then(|c| c.parent.as_ref()) { if let Some(parent) = colliders.get(a).and_then(|c| c.parent.as_ref()) {
islands.wake_up(bodies, parent.handle, true) islands.wake_up(bodies, parent.handle, true)
@@ -539,18 +539,17 @@ impl NarrowPhase {
// Emit an intersection lost event if we had an intersection before removing the edge. // Emit an intersection lost event if we had an intersection before removing the edge.
if let Some(mut intersection) = intersection { if let Some(mut intersection) = intersection {
if intersection.intersecting { if intersection.intersecting
if (co1.flags.active_events | co2.flags.active_events) && (co1.flags.active_events | co2.flags.active_events)
.contains(ActiveEvents::COLLISION_EVENTS) .contains(ActiveEvents::COLLISION_EVENTS)
{ {
intersection.emit_stop_event( intersection.emit_stop_event(
bodies, bodies,
colliders, colliders,
pair.collider1, pair.collider1,
pair.collider2, pair.collider2,
events, events,
) )
}
} }
} }
} else { } else {
@@ -588,15 +587,14 @@ impl NarrowPhase {
if let (Some(co1), Some(co2)) = if let (Some(co1), Some(co2)) =
(colliders.get(pair.collider1), colliders.get(pair.collider2)) (colliders.get(pair.collider1), colliders.get(pair.collider2))
{ {
if co1.parent.map(|p| p.handle) == co2.parent.map(|p| p.handle) { if co1.parent.map(|p| p.handle) == co2.parent.map(|p| p.handle) && co1.parent.is_some()
if co1.parent.is_some() { {
// Same parents. Ignore collisions. // Same parents. Ignore collisions.
return; return;
}
// These colliders have no parents - continue.
} }
// These colliders have no parents - continue.
let (gid1, gid2) = self.graph_indices.ensure_pair_exists( let (gid1, gid2) = self.graph_indices.ensure_pair_exists(
pair.collider1.0, pair.collider1.0,
pair.collider2.0, pair.collider2.0,
@@ -712,7 +710,7 @@ impl NarrowPhase {
let co2 = &colliders[handle2]; let co2 = &colliders[handle2];
// TODO: remove the `loop` once labels on blocks is stabilized. // TODO: remove the `loop` once labels on blocks is stabilized.
'emit_events: loop { 'emit_events: {
if !co1.changes.needs_narrow_phase_update() if !co1.changes.needs_narrow_phase_update()
&& !co2.changes.needs_narrow_phase_update() && !co2.changes.needs_narrow_phase_update()
{ {
@@ -813,7 +811,7 @@ impl NarrowPhase {
let co2 = &colliders[pair.collider2]; let co2 = &colliders[pair.collider2];
// TODO: remove the `loop` once labels on blocks are supported. // TODO: remove the `loop` once labels on blocks are supported.
'emit_events: loop { 'emit_events: {
if !co1.changes.needs_narrow_phase_update() if !co1.changes.needs_narrow_phase_update()
&& !co2.changes.needs_narrow_phase_update() && !co2.changes.needs_narrow_phase_update()
{ {
@@ -979,7 +977,7 @@ impl NarrowPhase {
// Apply the user-defined contact modification. // Apply the user-defined contact modification.
if active_hooks.contains(ActiveHooks::MODIFY_SOLVER_CONTACTS) { if active_hooks.contains(ActiveHooks::MODIFY_SOLVER_CONTACTS) {
let mut modifiable_solver_contacts = let mut modifiable_solver_contacts =
std::mem::replace(&mut manifold.data.solver_contacts, Vec::new()); std::mem::take(&mut manifold.data.solver_contacts);
let mut modifiable_user_data = manifold.data.user_data; let mut modifiable_user_data = manifold.data.user_data;
let mut modifiable_normal = manifold.data.normal; let mut modifiable_normal = manifold.data.normal;
@@ -1009,13 +1007,13 @@ impl NarrowPhase {
let active_events = co1.flags.active_events | co2.flags.active_events; let active_events = co1.flags.active_events | co2.flags.active_events;
if pair.has_any_active_contact != had_any_active_contact { if pair.has_any_active_contact != had_any_active_contact
if active_events.contains(ActiveEvents::COLLISION_EVENTS) { && active_events.contains(ActiveEvents::COLLISION_EVENTS)
if pair.has_any_active_contact { {
pair.emit_start_event(bodies, colliders, events); if pair.has_any_active_contact {
} else { pair.emit_start_event(bodies, colliders, events);
pair.emit_stop_event(bodies, colliders, events); } else {
} pair.emit_stop_event(bodies, colliders, events);
} }
} }
}); });
@@ -1029,7 +1027,7 @@ impl NarrowPhase {
bodies: &RigidBodySet, bodies: &RigidBodySet,
out_contact_pairs: &mut Vec<TemporaryInteractionIndex>, out_contact_pairs: &mut Vec<TemporaryInteractionIndex>,
out_manifolds: &mut Vec<&'a mut ContactManifold>, out_manifolds: &mut Vec<&'a mut ContactManifold>,
out: &mut Vec<Vec<ContactManifoldIndex>>, out: &mut [Vec<ContactManifoldIndex>],
) { ) {
for out_island in &mut out[..islands.num_islands()] { for out_island in &mut out[..islands.num_islands()] {
out_island.clear(); out_island.clear();

View File

@@ -12,6 +12,9 @@
#![deny(bare_trait_objects)] #![deny(bare_trait_objects)]
#![warn(missing_docs)] // FIXME: deny that #![warn(missing_docs)] // FIXME: deny that
#![allow(clippy::too_many_arguments)]
#![allow(clippy::needless_range_loop)] // TODO: remove this? I find that in the math code using indices adds clarity.
#![allow(clippy::module_inception)]
#[cfg(all(feature = "dim2", feature = "f32"))] #[cfg(all(feature = "dim2", feature = "f32"))]
pub extern crate parry2d as parry; pub extern crate parry2d as parry;

View File

@@ -149,7 +149,7 @@ impl CollisionPipeline {
bodies, bodies,
colliders, colliders,
&modified_colliders[..], &modified_colliders[..],
&mut removed_colliders, &removed_colliders,
hooks, hooks,
events, events,
true, true,

View File

@@ -79,12 +79,10 @@ pub trait DebugRenderBackend {
self.draw_line(object, a, b, color); self.draw_line(object, a, b, color);
} }
if closed { if closed && vertices.len() > 2 {
if vertices.len() > 2 { let a = transform * (Scale::from(*scale) * vertices[0]);
let a = transform * (Scale::from(*scale) * vertices[0]); let b = transform * (Scale::from(*scale) * vertices.last().unwrap());
let b = transform * (Scale::from(*scale) * vertices.last().unwrap()); self.draw_line(object, a, b, color);
self.draw_line(object, a, b, color);
}
} }
} }
} }

View File

@@ -41,12 +41,17 @@ impl Default for DebugRenderMode {
} }
} }
#[cfg(feature = "dim2")]
type InstancesMap = HashMap<TypeId, Vec<Point<Real>>>;
#[cfg(feature = "dim3")]
type InstancesMap = HashMap<TypeId, (Vec<Point<Real>>, Vec<[u32; 2]>)>;
/// Pipeline responsible for rendering the state of the physics engine for debugging purpose. /// Pipeline responsible for rendering the state of the physics engine for debugging purpose.
pub struct DebugRenderPipeline { pub struct DebugRenderPipeline {
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
instances: HashMap<TypeId, Vec<Point<Real>>>, instances: InstancesMap,
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
instances: HashMap<TypeId, (Vec<Point<Real>>, Vec<[u32; 2]>)>, instances: InstancesMap,
/// The style used to compute the line colors for each element /// The style used to compute the line colors for each element
/// to render. /// to render.
pub style: DebugRenderStyle, pub style: DebugRenderStyle,

View File

@@ -5,4 +5,4 @@ pub use self::debug_render_style::{DebugColor, DebugRenderStyle};
mod debug_render_backend; mod debug_render_backend;
mod debug_render_pipeline; mod debug_render_pipeline;
mod debug_render_style; mod debug_render_style;
pub(self) mod outlines; mod outlines;

View File

@@ -17,6 +17,7 @@ pub fn instances(nsubdivs: u32) -> HashMap<TypeId, Vec<Point<Real>>> {
} }
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
#[allow(clippy::type_complexity)]
pub fn instances(nsubdivs: u32) -> HashMap<TypeId, (Vec<Point<Real>>, Vec<[u32; 2]>)> { pub fn instances(nsubdivs: u32) -> HashMap<TypeId, (Vec<Point<Real>>, Vec<[u32; 2]>)> {
let mut result = HashMap::new(); let mut result = HashMap::new();
result.insert( result.insert(

View File

@@ -69,7 +69,7 @@ impl<'a> ContactModificationContext<'a> {
// Test the allowed normal with the local-space contact normal that // Test the allowed normal with the local-space contact normal that
// points towards the exterior of context.collider1. // points towards the exterior of context.collider1.
let contact_is_ok = self.manifold.local_n1.dot(&allowed_local_n1) >= cang; let contact_is_ok = self.manifold.local_n1.dot(allowed_local_n1) >= cang;
match *self.user_data { match *self.user_data {
CONTACT_CONFIGURATION_UNKNOWN => { CONTACT_CONFIGURATION_UNKNOWN => {

View File

@@ -212,7 +212,7 @@ impl PhysicsPipeline {
rb.mprops.update_world_mass_properties(&rb.pos.position); rb.mprops.update_world_mass_properties(&rb.pos.position);
let effective_mass = rb.mprops.effective_mass(); let effective_mass = rb.mprops.effective_mass();
rb.forces rb.forces
.compute_effective_force_and_torque(&gravity, &effective_mass); .compute_effective_force_and_torque(gravity, &effective_mass);
} }
self.counters.stages.update_time.pause(); self.counters.stages.update_time.pause();
@@ -270,14 +270,13 @@ impl PhysicsPipeline {
.enumerate() .enumerate()
.for_each(|(island_id, solver)| { .for_each(|(island_id, solver)| {
let bodies: &mut RigidBodySet = let bodies: &mut RigidBodySet =
unsafe { std::mem::transmute(bodies.load(Ordering::Relaxed)) }; unsafe { &mut *bodies.load(Ordering::Relaxed) };
let manifolds: &mut Vec<&mut ContactManifold> = let manifolds: &mut Vec<&mut ContactManifold> =
unsafe { std::mem::transmute(manifolds.load(Ordering::Relaxed)) }; unsafe { &mut *manifolds.load(Ordering::Relaxed) };
let impulse_joints: &mut Vec<JointGraphEdge> = let impulse_joints: &mut Vec<JointGraphEdge> =
unsafe { std::mem::transmute(impulse_joints.load(Ordering::Relaxed)) }; unsafe { &mut *impulse_joints.load(Ordering::Relaxed) };
let multibody_joints: &mut MultibodyJointSet = unsafe { let multibody_joints: &mut MultibodyJointSet =
std::mem::transmute(multibody_joints.load(Ordering::Relaxed)) unsafe { &mut *multibody_joints.load(Ordering::Relaxed) };
};
let mut counters = Counters::new(false); let mut counters = Counters::new(false);
solver.init_and_solve( solver.init_and_solve(

View File

@@ -114,6 +114,7 @@ pub struct QueryFilter<'a> {
/// If set, any collider attached to this rigid-body will be excluded from the scene query. /// If set, any collider attached to this rigid-body will be excluded from the scene query.
pub exclude_rigid_body: Option<RigidBodyHandle>, pub exclude_rigid_body: Option<RigidBodyHandle>,
/// If set, any collider for which this closure returns false will be excluded from the scene query. /// If set, any collider for which this closure returns false will be excluded from the scene query.
#[allow(clippy::type_complexity)] // Type doesnt look really complex?
pub predicate: Option<&'a dyn Fn(ColliderHandle, &Collider) -> bool>, pub predicate: Option<&'a dyn Fn(ColliderHandle, &Collider) -> bool>,
} }
@@ -668,10 +669,10 @@ impl QueryPipeline {
/// the shape is penetrating another shape at its starting point **and** its trajectory is such /// the shape is penetrating another shape at its starting point **and** its trajectory is such
/// that its on a path to exist that penetration state. /// that its on a path to exist that penetration state.
/// * `filter`: set of rules used to determine which collider is taken into account by this scene query. /// * `filter`: set of rules used to determine which collider is taken into account by this scene query.
pub fn cast_shape<'a>( pub fn cast_shape(
&self, &self,
bodies: &RigidBodySet, bodies: &RigidBodySet,
colliders: &'a ColliderSet, colliders: &ColliderSet,
shape_pos: &Isometry<Real>, shape_pos: &Isometry<Real>,
shape_vel: &Vector<Real>, shape_vel: &Vector<Real>,
shape: &dyn Shape, shape: &dyn Shape,
@@ -746,10 +747,10 @@ impl QueryPipeline {
/// * `shape` - The shape to test. /// * `shape` - The shape to test.
/// * `filter`: set of rules used to determine which collider is taken into account by this scene query. /// * `filter`: set of rules used to determine which collider is taken into account by this scene query.
/// * `callback` - A function called with the handles of each collider intersecting the `shape`. /// * `callback` - A function called with the handles of each collider intersecting the `shape`.
pub fn intersections_with_shape<'a>( pub fn intersections_with_shape(
&self, &self,
bodies: &RigidBodySet, bodies: &RigidBodySet,
colliders: &'a ColliderSet, colliders: &ColliderSet,
shape_pos: &Isometry<Real>, shape_pos: &Isometry<Real>,
shape: &dyn Shape, shape: &dyn Shape,
filter: QueryFilter, filter: QueryFilter,

View File

@@ -111,15 +111,13 @@ pub(crate) fn handle_user_changes_to_rigid_bodies(
} }
// Update the active kinematic set. // Update the active kinematic set.
if changes.contains(RigidBodyChanges::POSITION) if (changes.contains(RigidBodyChanges::POSITION)
|| changes.contains(RigidBodyChanges::COLLIDERS) || changes.contains(RigidBodyChanges::COLLIDERS))
&& rb.is_kinematic()
&& islands.active_kinematic_set.get(ids.active_set_id) != Some(handle)
{ {
if rb.is_kinematic() ids.active_set_id = islands.active_kinematic_set.len();
&& islands.active_kinematic_set.get(ids.active_set_id) != Some(handle) islands.active_kinematic_set.push(*handle);
{
ids.active_set_id = islands.active_kinematic_set.len();
islands.active_kinematic_set.push(*handle);
}
} }
// Push the body to the active set if it is not // Push the body to the active set if it is not

View File

@@ -25,7 +25,7 @@ impl SimdRealCopy for SimdReal {}
const INV_EPSILON: Real = 1.0e-20; const INV_EPSILON: Real = 1.0e-20;
pub(crate) fn inv(val: Real) -> Real { pub(crate) fn inv(val: Real) -> Real {
if val >= -INV_EPSILON && val <= INV_EPSILON { if (-INV_EPSILON..=INV_EPSILON).contains(&val) {
0.0 0.0
} else { } else {
1.0 / val 1.0 / val

View File

@@ -35,6 +35,7 @@ impl Default for OrbitCamera {
// Adapted from the 3D orbit camera from bevy-orbit-controls // Adapted from the 3D orbit camera from bevy-orbit-controls
pub struct OrbitCameraPlugin; pub struct OrbitCameraPlugin;
impl OrbitCameraPlugin { impl OrbitCameraPlugin {
#[allow(clippy::type_complexity)]
fn update_transform_system( fn update_transform_system(
mut query: Query<(&OrbitCamera, &mut Transform), (Changed<OrbitCamera>, With<Camera>)>, mut query: Query<(&OrbitCamera, &mut Transform), (Changed<OrbitCamera>, With<Camera>)>,
) { ) {

View File

@@ -46,6 +46,7 @@ impl Default for OrbitCamera {
pub struct OrbitCameraPlugin; pub struct OrbitCameraPlugin;
impl OrbitCameraPlugin { impl OrbitCameraPlugin {
#[allow(clippy::type_complexity)]
fn update_transform_system( fn update_transform_system(
mut query: Query<(&OrbitCamera, &mut Transform), (Changed<OrbitCamera>, With<Camera>)>, mut query: Query<(&OrbitCamera, &mut Transform), (Changed<OrbitCamera>, With<Camera>)>,
) { ) {

View File

@@ -1,3 +1,5 @@
#![allow(clippy::unnecessary_cast)] // Casts are needed for switching between f32/f64.
use crate::harness::Harness; use crate::harness::Harness;
use bevy::gizmos::gizmos::Gizmos; use bevy::gizmos::gizmos::Gizmos;
use bevy::prelude::*; use bevy::prelude::*;
@@ -36,8 +38,8 @@ impl<'a> DebugRenderBackend for BevyLinesRenderBackend<'a> {
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
fn draw_line(&mut self, _: DebugRenderObject, a: Point<Real>, b: Point<Real>, color: [f32; 4]) { fn draw_line(&mut self, _: DebugRenderObject, a: Point<Real>, b: Point<Real>, color: [f32; 4]) {
self.gizmos.line( self.gizmos.line(
[a.x as f32, a.y as f32, 1.0e-8 as f32].into(), [a.x as f32, a.y as f32, 1.0e-8].into(),
[b.x as f32, b.y as f32, 1.0e-8 as f32].into(), [b.x as f32, b.y as f32, 1.0e-8].into(),
Color::hsla(color[0], color[1], color[2], color[3]), Color::hsla(color[0], color[1], color[2], color[3]),
) )
} }

View File

@@ -253,7 +253,7 @@ impl GraphicsManager {
// } // }
// } // }
let nodes = self.b2sn.entry(handle).or_insert_with(Vec::new); let nodes = self.b2sn.entry(handle).or_default();
nodes.append(&mut new_nodes.clone()); nodes.append(&mut new_nodes.clone());
@@ -276,10 +276,7 @@ impl GraphicsManager {
.copied() .copied()
.unwrap_or(self.ground_color); .unwrap_or(self.ground_color);
let color = self.c2color.get(&handle).copied().unwrap_or(color); let color = self.c2color.get(&handle).copied().unwrap_or(color);
let mut nodes = std::mem::replace( let mut nodes = std::mem::take(self.b2sn.entry(collider_parent).or_default());
self.b2sn.entry(collider_parent).or_insert(vec![]),
Vec::new(),
);
self.add_shape( self.add_shape(
commands, commands,
meshes, meshes,

View File

@@ -1,3 +1,5 @@
#![allow(clippy::unnecessary_cast)] // Casts are needed for switching between f32/f64.
use crate::{ use crate::{
physics::{PhysicsEvents, PhysicsState}, physics::{PhysicsEvents, PhysicsState},
TestbedGraphics, TestbedGraphics,
@@ -22,6 +24,12 @@ pub struct RunState {
pub time: f32, pub time: f32,
} }
impl Default for RunState {
fn default() -> Self {
Self::new()
}
}
impl RunState { impl RunState {
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
pub fn new() -> Self { pub fn new() -> Self {
@@ -33,7 +41,7 @@ impl RunState {
.unwrap(); .unwrap();
Self { Self {
thread_pool: thread_pool, thread_pool,
num_threads, num_threads,
timestep_id: 0, timestep_id: 0,
time: 0.0, time: 0.0,

View File

@@ -1,3 +1,5 @@
#![allow(clippy::too_many_arguments)]
extern crate nalgebra as na; extern crate nalgebra as na;
#[macro_use] #[macro_use]

View File

@@ -1,3 +1,5 @@
#![allow(clippy::unnecessary_cast)] // Casts are needed for switching between f32/f64.
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::mesh::{Indices, VertexAttributeValues}; use bevy::render::mesh::{Indices, VertexAttributeValues};

View File

@@ -86,6 +86,12 @@ pub struct PhysicsState {
pub hooks: Box<dyn PhysicsHooks>, pub hooks: Box<dyn PhysicsHooks>,
} }
impl Default for PhysicsState {
fn default() -> Self {
Self::new()
}
}
impl PhysicsState { impl PhysicsState {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@@ -113,7 +119,7 @@ pub struct PhysicsEvents {
impl PhysicsEvents { impl PhysicsEvents {
pub fn poll_all(&self) { pub fn poll_all(&self) {
while let Ok(_) = self.collision_events.try_recv() {} while self.collision_events.try_recv().is_ok() {}
while let Ok(_) = self.contact_force_events.try_recv() {} while self.contact_force_events.try_recv().is_ok() {}
} }
} }

View File

@@ -1,3 +1,5 @@
#![allow(clippy::bad_bit_mask)] // otherwsie clippy complains because of TestbedStateFlags::NONE which is 0.
use std::env; use std::env;
use std::mem; use std::mem;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
@@ -107,6 +109,8 @@ pub enum RapierSolverType {
StandardPgs, StandardPgs,
} }
pub type SimulationBuilders = Vec<(&'static str, fn(&mut Testbed))>;
#[derive(Resource)] #[derive(Resource)]
pub struct TestbedState { pub struct TestbedState {
pub running: RunMode, pub running: RunMode,
@@ -135,7 +139,7 @@ pub struct TestbedState {
} }
#[derive(Resource)] #[derive(Resource)]
struct SceneBuilders(Vec<(&'static str, fn(&mut Testbed))>); struct SceneBuilders(SimulationBuilders);
#[cfg(feature = "other-backends")] #[cfg(feature = "other-backends")]
struct OtherBackends { struct OtherBackends {
@@ -237,7 +241,7 @@ impl TestbedApp {
} }
} }
pub fn from_builders(default: usize, builders: Vec<(&'static str, fn(&mut Testbed))>) -> Self { pub fn from_builders(default: usize, builders: SimulationBuilders) -> Self {
let mut res = TestbedApp::new_empty(); let mut res = TestbedApp::new_empty();
res.state res.state
.action_flags .action_flags
@@ -247,7 +251,7 @@ impl TestbedApp {
res res
} }
pub fn set_builders(&mut self, builders: Vec<(&'static str, fn(&mut Testbed))>) { pub fn set_builders(&mut self, builders: SimulationBuilders) {
self.state.example_names = builders.iter().map(|e| e.0).collect(); self.state.example_names = builders.iter().map(|e| e.0).collect();
self.builders = SceneBuilders(builders) self.builders = SceneBuilders(builders)
} }
@@ -280,7 +284,7 @@ impl TestbedApp {
use std::io::{BufWriter, Write}; use std::io::{BufWriter, Write};
// Don't enter the main loop. We will just step the simulation here. // Don't enter the main loop. We will just step the simulation here.
let mut results = Vec::new(); let mut results = Vec::new();
let builders = mem::replace(&mut self.builders.0, Vec::new()); let builders = mem::take(&mut self.builders.0);
let backend_names = self.state.backend_names.clone(); let backend_names = self.state.backend_names.clone();
for builder in builders { for builder in builders {
@@ -423,8 +427,7 @@ impl TestbedApp {
impl<'a, 'b, 'c, 'd, 'e, 'f> TestbedGraphics<'a, 'b, 'c, 'd, 'e, 'f> { impl<'a, 'b, 'c, 'd, 'e, 'f> TestbedGraphics<'a, 'b, 'c, 'd, 'e, 'f> {
pub fn set_body_color(&mut self, body: RigidBodyHandle, color: [f32; 3]) { pub fn set_body_color(&mut self, body: RigidBodyHandle, color: [f32; 3]) {
self.graphics self.graphics.set_body_color(self.materials, body, color);
.set_body_color(&mut self.materials, body, color);
} }
pub fn add_body( pub fn add_body(
@@ -466,7 +469,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> TestbedGraphics<'a, 'b, 'c, 'd, 'e, 'f> {
} }
pub fn keys(&self) -> &Input<KeyCode> { pub fn keys(&self) -> &Input<KeyCode> {
&*self.keys self.keys
} }
} }
@@ -497,7 +500,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
} }
pub fn harness_mut(&mut self) -> &mut Harness { pub fn harness_mut(&mut self) -> &mut Harness {
&mut self.harness self.harness
} }
pub fn set_world( pub fn set_world(
@@ -1110,30 +1113,30 @@ fn update_testbed(
// Handle inputs // Handle inputs
{ {
let graphics_context = TestbedGraphics { let graphics_context = TestbedGraphics {
graphics: &mut *graphics, graphics: &mut graphics,
commands: &mut commands, commands: &mut commands,
meshes: &mut *meshes, meshes: &mut *meshes,
materials: &mut *materials, materials: &mut *materials,
components: &mut gfx_components, components: &mut gfx_components,
camera_transform: *cameras.single().1, camera_transform: *cameras.single().1,
camera: &mut cameras.single_mut().2, camera: &mut cameras.single_mut().2,
keys: &*keys, keys: &keys,
}; };
let mut testbed = Testbed { let mut testbed = Testbed {
graphics: Some(graphics_context), graphics: Some(graphics_context),
state: &mut *state, state: &mut state,
harness: &mut *harness, harness: &mut harness,
#[cfg(feature = "other-backends")] #[cfg(feature = "other-backends")]
other_backends: &mut *other_backends, other_backends: &mut other_backends,
plugins: &mut *plugins, plugins: &mut plugins,
}; };
testbed.handle_common_events(&*keys); testbed.handle_common_events(&keys);
testbed.update_character_controller(&*keys); testbed.update_character_controller(&keys);
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
{ {
testbed.update_vehicle_controller(&*keys); testbed.update_vehicle_controller(&keys);
} }
} }
@@ -1144,7 +1147,7 @@ fn update_testbed(
for plugin in &mut plugins.0 { for plugin in &mut plugins.0 {
plugin.update_ui( plugin.update_ui(
&mut ui_context, &ui_context,
harness, harness,
&mut graphics, &mut graphics,
&mut commands, &mut commands,
@@ -1190,10 +1193,10 @@ fn update_testbed(
.set(TestbedActionFlags::EXAMPLE_CHANGED, false); .set(TestbedActionFlags::EXAMPLE_CHANGED, false);
clear(&mut commands, &mut state, &mut graphics, &mut plugins); clear(&mut commands, &mut state, &mut graphics, &mut plugins);
harness.clear_callbacks(); harness.clear_callbacks();
for plugin in (*plugins).0.iter_mut() { for plugin in plugins.0.iter_mut() {
plugin.clear_graphics(&mut graphics, &mut commands); plugin.clear_graphics(&mut graphics, &mut commands);
} }
(*plugins).0.clear(); plugins.0.clear();
if state.selected_example != prev_example { if state.selected_example != prev_example {
harness.physics.integration_parameters = IntegrationParameters::default(); harness.physics.integration_parameters = IntegrationParameters::default();
@@ -1219,16 +1222,16 @@ fn update_testbed(
components: &mut gfx_components, components: &mut gfx_components,
camera_transform: *cameras.single().1, camera_transform: *cameras.single().1,
camera: &mut cameras.single_mut().2, camera: &mut cameras.single_mut().2,
keys: &*keys, keys: &keys,
}; };
let mut testbed = Testbed { let mut testbed = Testbed {
graphics: Some(graphics_context), graphics: Some(graphics_context),
state: &mut *state, state: &mut state,
harness: &mut *harness, harness: &mut harness,
#[cfg(feature = "other-backends")] #[cfg(feature = "other-backends")]
other_backends: &mut *other_backends, other_backends: &mut other_backends,
plugins: &mut *plugins, plugins: &mut plugins,
}; };
builders.0[selected_example].1(&mut testbed); builders.0[selected_example].1(&mut testbed);
@@ -1371,7 +1374,7 @@ fn update_testbed(
components: &mut gfx_components, components: &mut gfx_components,
camera_transform: *cameras.single().1, camera_transform: *cameras.single().1,
camera: &mut cameras.single_mut().2, camera: &mut cameras.single_mut().2,
keys: &*keys, keys: &keys,
}; };
harness.step_with_graphics(Some(&mut testbed_graphics)); harness.step_with_graphics(Some(&mut testbed_graphics));
@@ -1425,8 +1428,8 @@ fn update_testbed(
for (camera, camera_pos, _) in cameras.iter_mut() { for (camera, camera_pos, _) in cameras.iter_mut() {
highlight_hovered_body( highlight_hovered_body(
&mut *materials, &mut *materials,
&mut *graphics, &mut graphics,
&mut *state, &mut state,
&harness.physics, &harness.physics,
window, window,
camera, camera,

View File

@@ -44,22 +44,18 @@ pub fn update_ui(
} }
ui.horizontal(|ui| { ui.horizontal(|ui| {
if ui.button("<").clicked() { if ui.button("<").clicked() && state.selected_example > 0 {
if state.selected_example > 0 { state.selected_example -= 1;
state.selected_example -= 1; state
state .action_flags
.action_flags .set(TestbedActionFlags::EXAMPLE_CHANGED, true)
.set(TestbedActionFlags::EXAMPLE_CHANGED, true)
}
} }
if ui.button(">").clicked() { if ui.button(">").clicked() && state.selected_example + 1 < state.example_names.len() {
if state.selected_example + 1 < state.example_names.len() { state.selected_example += 1;
state.selected_example += 1; state
state .action_flags
.action_flags .set(TestbedActionFlags::EXAMPLE_CHANGED, true)
.set(TestbedActionFlags::EXAMPLE_CHANGED, true)
}
} }
let mut changed = false; let mut changed = false;