Fix clippy and enable clippy on CI
This commit is contained in:
committed by
Sébastien Crozet
parent
aef873f20e
commit
da92e5c283
6
.github/workflows/rapier-ci-build.yml
vendored
6
.github/workflows/rapier-ci-build.yml
vendored
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)">
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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.]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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],
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 can’t 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 can’t 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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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]) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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(
|
||||||
¶ms,
|
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(
|
||||||
¶ms,
|
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(¶ms, 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(¶ms, 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(
|
||||||
¶ms,
|
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(
|
||||||
¶ms,
|
params,
|
||||||
solver_bodies,
|
solver_bodies,
|
||||||
&mut self.simd_velocity_one_body_constraints,
|
&mut self.simd_velocity_one_body_constraints,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -175,8 +175,8 @@ impl VelocitySolver {
|
|||||||
/*
|
/*
|
||||||
* Update & solve constraints.
|
* Update & solve constraints.
|
||||||
*/
|
*/
|
||||||
joint_constraints.update(¶ms, multibodies, &self.solver_bodies);
|
joint_constraints.update(params, multibodies, &self.solver_bodies);
|
||||||
contact_constraints.update(¶ms, 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(¶ms, is_last_substep, bodies, multibodies);
|
self.integrate_positions(params, is_last_substep, bodies, multibodies);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resolution without bias.
|
* Resolution without bias.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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 => {
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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 doesn’t 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 it’s on a path to exist that penetration state.
|
/// that it’s 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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>)>,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -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>)>,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -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]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::too_many_arguments)]
|
||||||
|
|
||||||
extern crate nalgebra as na;
|
extern crate nalgebra as na;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|
||||||
|
|||||||
@@ -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() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user