aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2020-09-01 14:02:59 +0200
committerSébastien Crozet <developer@crozet.re>2020-09-01 14:02:59 +0200
commit9622827dc6aadb391512b95381edb1efc26b1b90 (patch)
tree3b15362d6f7736f8d30bc78b6e33ff51c893751f /src/dynamics
parent03b437f278bbcbd391acd23a4d8fa074915eb00c (diff)
downloadrapier-9622827dc6aadb391512b95381edb1efc26b1b90.tar.gz
rapier-9622827dc6aadb391512b95381edb1efc26b1b90.tar.bz2
rapier-9622827dc6aadb391512b95381edb1efc26b1b90.zip
Fix constraints resolution with non-identity relative collider position.
Diffstat (limited to 'src/dynamics')
-rw-r--r--src/dynamics/solver/position_constraint.rs4
-rw-r--r--src/dynamics/solver/position_constraint_wide.rs7
-rw-r--r--src/dynamics/solver/position_ground_constraint.rs28
-rw-r--r--src/dynamics/solver/position_ground_constraint_wide.rs16
-rw-r--r--src/dynamics/solver/velocity_constraint.rs8
-rw-r--r--src/dynamics/solver/velocity_constraint_wide.rs18
-rw-r--r--src/dynamics/solver/velocity_ground_constraint.rs28
-rw-r--r--src/dynamics/solver/velocity_ground_constraint_wide.rs20
8 files changed, 84 insertions, 45 deletions
diff --git a/src/dynamics/solver/position_constraint.rs b/src/dynamics/solver/position_constraint.rs
index 608a342..69fcf57 100644
--- a/src/dynamics/solver/position_constraint.rs
+++ b/src/dynamics/solver/position_constraint.rs
@@ -104,8 +104,8 @@ impl PositionConstraint {
let mut local_p2 = [Point::origin(); MAX_MANIFOLD_POINTS];
for l in 0..manifold_points.len() {
- local_p1[l] = manifold_points[l].local_p1 + shift1;
- local_p2[l] = manifold_points[l].local_p2 + shift2;
+ local_p1[l] = manifold.delta1 * (manifold_points[l].local_p1 + shift1);
+ local_p2[l] = manifold.delta2 * (manifold_points[l].local_p2 + shift2);
}
let constraint = PositionConstraint {
diff --git a/src/dynamics/solver/position_constraint_wide.rs b/src/dynamics/solver/position_constraint_wide.rs
index 8828c3d..0633926 100644
--- a/src/dynamics/solver/position_constraint_wide.rs
+++ b/src/dynamics/solver/position_constraint_wide.rs
@@ -51,6 +51,9 @@ impl WPositionConstraint {
let radius1 = SimdFloat::from(array![|ii| manifolds[ii].kinematics.radius1; SIMD_WIDTH]);
let radius2 = SimdFloat::from(array![|ii| manifolds[ii].kinematics.radius2; SIMD_WIDTH]);
+ let delta1 = Isometry::from(array![|ii| manifolds[ii].delta1; SIMD_WIDTH]);
+ let delta2 = Isometry::from(array![|ii| manifolds[ii].delta2; SIMD_WIDTH]);
+
let rb1 = array![|ii| rbs1[ii].active_set_offset; SIMD_WIDTH];
let rb2 = array![|ii| rbs2[ii].active_set_offset; SIMD_WIDTH];
@@ -85,8 +88,8 @@ impl WPositionConstraint {
let local_p2 =
Point::from(array![|ii| manifold_points[ii][i].local_p2; SIMD_WIDTH]);
- constraint.local_p1[i] = local_p1 + shift1;
- constraint.local_p2[i] = local_p2 + shift2;
+ constraint.local_p1[i] = delta1 * (local_p1 + shift1);
+ constraint.local_p2[i] = delta2 * (local_p2 + shift2);
}
if push {
diff --git a/src/dynamics/solver/position_ground_constraint.rs b/src/dynamics/solver/position_ground_constraint.rs
index e6e83c6..dcd2d64 100644
--- a/src/dynamics/solver/position_ground_constraint.rs
+++ b/src/dynamics/solver/position_ground_constraint.rs
@@ -34,22 +34,30 @@ impl PositionGroundConstraint {
let local_n1;
let local_n2;
+ let delta1;
+ let delta2;
if flip {
std::mem::swap(&mut rb1, &mut rb2);
local_n1 = manifold.local_n2;
local_n2 = manifold.local_n1;
+ delta1 = &manifold.delta2;
+ delta2 = &manifold.delta1;
} else {
local_n1 = manifold.local_n1;
local_n2 = manifold.local_n2;
+ delta1 = &manifold.delta1;
+ delta2 = &manifold.delta2;
};
+ let coll_pos1 = rb1.position * delta1;
let shift1 = local_n1 * -manifold.kinematics.radius1;
let shift2 = local_n2 * -manifold.kinematics.radius2;
+ let n1 = coll_pos1 * local_n1;
let radius =
manifold.kinematics.radius1 + manifold.kinematics.radius2 /* - params.allowed_linear_error */;
- for (l, manifold_points) in manifold
+ for (l, manifold_contacts) in manifold
.active_contacts()
.chunks(MAX_MANIFOLD_POINTS)
.enumerate()
@@ -59,16 +67,16 @@ impl PositionGroundConstraint {
if flip {
// Don't forget that we already swapped rb1 and rb2 above.
- // So if we flip, only manifold_points[k].{local_p1,local_p2} have to
+ // So if we flip, only manifold_contacts[k].{local_p1,local_p2} have to
// be swapped.
- for k in 0..manifold_points.len() {
- p1[k] = rb1.predicted_position * (manifold_points[k].local_p2 + shift1);
- local_p2[k] = manifold_points[k].local_p1 + shift2;
+ for k in 0..manifold_contacts.len() {
+ p1[k] = coll_pos1 * (manifold_contacts[k].local_p2 + shift1);
+ local_p2[k] = delta2 * (manifold_contacts[k].local_p1 + shift2);
}
} else {
- for k in 0..manifold_points.len() {
- p1[k] = rb1.predicted_position * (manifold_points[k].local_p1 + shift1);
- local_p2[k] = manifold_points[k].local_p2 + shift2;
+ for k in 0..manifold_contacts.len() {
+ p1[k] = coll_pos1 * (manifold_contacts[k].local_p1 + shift1);
+ local_p2[k] = delta2 * (manifold_contacts[k].local_p2 + shift2);
}
}
@@ -76,11 +84,11 @@ impl PositionGroundConstraint {
rb2: rb2.active_set_offset,
p1,
local_p2,
- n1: rb1.predicted_position * local_n1,
+ n1,
radius,
im2: rb2.mass_properties.inv_mass,
ii2: rb2.world_inv_inertia_sqrt.squared(),
- num_contacts: manifold_points.len() as u8,
+ num_contacts: manifold_contacts.len() as u8,
erp: params.erp,
max_linear_correction: params.max_linear_correction,
};
diff --git a/src/dynamics/solver/position_ground_constraint_wide.rs b/src/dynamics/solver/position_ground_constraint_wide.rs
index faa928b..e423c0a 100644
--- a/src/dynamics/solver/position_ground_constraint_wide.rs
+++ b/src/dynamics/solver/position_ground_constraint_wide.rs
@@ -54,16 +54,24 @@ impl WPositionGroundConstraint {
array![|ii| if flipped[ii] { manifolds[ii].local_n1 } else { manifolds[ii].local_n2 }; SIMD_WIDTH],
);
+ let delta1 = Isometry::from(
+ array![|ii| if flipped[ii] { manifolds[ii].delta2 } else { manifolds[ii].delta1 }; SIMD_WIDTH],
+ );
+ let delta2 = Isometry::from(
+ array![|ii| if flipped[ii] { manifolds[ii].delta1 } else { manifolds[ii].delta2 }; SIMD_WIDTH],
+ );
+
let radius1 = SimdFloat::from(array![|ii| manifolds[ii].kinematics.radius1; SIMD_WIDTH]);
let radius2 = SimdFloat::from(array![|ii| manifolds[ii].kinematics.radius2; SIMD_WIDTH]);
- let position1 = Isometry::from(array![|ii| rbs1[ii].predicted_position; SIMD_WIDTH]);
+ let coll_pos1 =
+ delta1 * Isometry::from(array![|ii| rbs1[ii].predicted_position; SIMD_WIDTH]);
let rb2 = array![|ii| rbs2[ii].active_set_offset; SIMD_WIDTH];
let radius = radius1 + radius2 /*- SimdFloat::splat(params.allowed_linear_error)*/;
- let n1 = position1 * local_n1;
+ let n1 = coll_pos1 * local_n1;
for l in (0..manifolds[0].num_active_contacts()).step_by(MAX_MANIFOLD_POINTS) {
let manifold_points = array![|ii| &manifolds[ii].active_contacts()[l..]; SIMD_WIDTH];
@@ -90,8 +98,8 @@ impl WPositionGroundConstraint {
array![|ii| if flipped[ii] { manifold_points[ii][i].local_p1 } else { manifold_points[ii][i].local_p2 }; SIMD_WIDTH],
);
- constraint.p1[i] = position1 * local_p1 - n1 * radius1;
- constraint.local_p2[i] = local_p2 - local_n2 * radius2;
+ constraint.p1[i] = coll_pos1 * local_p1 - n1 * radius1;
+ constraint.local_p2[i] = delta2 * (local_p2 - local_n2 * radius2);
}
if push {
diff --git a/src/dynamics/solver/velocity_constraint.rs b/src/dynamics/solver/velocity_constraint.rs
index eb80018..190076d 100644
--- a/src/dynamics/solver/velocity_constraint.rs
+++ b/src/dynamics/solver/velocity_constraint.rs
@@ -148,7 +148,9 @@ impl VelocityConstraint {
let rb2 = &bodies[manifold.body_pair.body2];
let mj_lambda1 = rb1.active_set_offset;
let mj_lambda2 = rb2.active_set_offset;
- let force_dir1 = rb1.position * (-manifold.local_n1);
+ let pos_coll1 = rb1.position * manifold.delta1;
+ let pos_coll2 = rb2.position * manifold.delta2;
+ let force_dir1 = pos_coll1 * (-manifold.local_n1);
let warmstart_coeff = manifold.warmstart_multiplier * params.warmstart_coeff;
for (l, manifold_points) in manifold
@@ -215,8 +217,8 @@ impl VelocityConstraint {
for k in 0..manifold_points.len() {
let manifold_point = &manifold_points[k];
- let dp1 = (rb1.position * manifold_point.local_p1) - rb1.world_com;
- let dp2 = (rb2.position * manifold_point.local_p2) - rb2.world_com;
+ let dp1 = (pos_coll1 * manifold_point.local_p1) - rb1.world_com;
+ let dp2 = (pos_coll2 * manifold_point.local_p2) - rb2.world_com;
let vel1 = rb1.linvel + rb1.angvel.gcross(dp1);
let vel2 = rb2.linvel + rb2.angvel.gcross(dp2);
diff --git a/src/dynamics/solver/velocity_constraint_wide.rs b/src/dynamics/solver/velocity_constraint_wide.rs
index 4204e68..f515d5e 100644
--- a/src/dynamics/solver/velocity_constraint_wide.rs
+++ b/src/dynamics/solver/velocity_constraint_wide.rs
@@ -72,6 +72,9 @@ impl WVelocityConstraint {
let rbs1 = array![|ii| &bodies[manifolds[ii].body_pair.body1]; SIMD_WIDTH];
let rbs2 = array![|ii| &bodies[manifolds[ii].body_pair.body2]; SIMD_WIDTH];
+ let delta1 = Isometry::from(array![|ii| manifolds[ii].delta1; SIMD_WIDTH]);
+ let delta2 = Isometry::from(array![|ii| manifolds[ii].delta2; SIMD_WIDTH]);
+
let im1 = SimdFloat::from(array![|ii| rbs1[ii].mass_properties.inv_mass; SIMD_WIDTH]);
let ii1: AngularInertia<SimdFloat> =
AngularInertia::from(array![|ii| rbs1[ii].world_inv_inertia_sqrt; SIMD_WIDTH]);
@@ -79,7 +82,7 @@ impl WVelocityConstraint {
let linvel1 = Vector::from(array![|ii| rbs1[ii].linvel; SIMD_WIDTH]);
let angvel1 = AngVector::<SimdFloat>::from(array![|ii| rbs1[ii].angvel; SIMD_WIDTH]);
- let position1 = Isometry::from(array![|ii| rbs1[ii].position; SIMD_WIDTH]);
+ let pos1 = Isometry::from(array![|ii| rbs1[ii].position; SIMD_WIDTH]);
let world_com1 = Point::from(array![|ii| rbs1[ii].world_com; SIMD_WIDTH]);
let im2 = SimdFloat::from(array![|ii| rbs2[ii].mass_properties.inv_mass; SIMD_WIDTH]);
@@ -89,10 +92,13 @@ impl WVelocityConstraint {
let linvel2 = Vector::from(array![|ii| rbs2[ii].linvel; SIMD_WIDTH]);
let angvel2 = AngVector::<SimdFloat>::from(array![|ii| rbs2[ii].angvel; SIMD_WIDTH]);
- let position2 = Isometry::from(array![|ii| rbs2[ii].position; SIMD_WIDTH]);
+ let pos2 = Isometry::from(array![|ii| rbs2[ii].position; SIMD_WIDTH]);
let world_com2 = Point::from(array![|ii| rbs2[ii].world_com; SIMD_WIDTH]);
- let force_dir1 = position1 * -Vector::from(array![|ii| manifolds[ii].local_n1; SIMD_WIDTH]);
+ let coll_pos1 = pos1 * delta1;
+ let coll_pos2 = pos2 * delta2;
+
+ let force_dir1 = coll_pos1 * -Vector::from(array![|ii| manifolds[ii].local_n1; SIMD_WIDTH]);
let mj_lambda1 = array![|ii| rbs1[ii].active_set_offset; SIMD_WIDTH];
let mj_lambda2 = array![|ii| rbs2[ii].active_set_offset; SIMD_WIDTH];
@@ -120,11 +126,11 @@ impl WVelocityConstraint {
};
for k in 0..num_points {
- // FIXME: can we avoid the multiplications by position1/position2 here?
+ // FIXME: can we avoid the multiplications by coll_pos1/coll_pos2 here?
// By working as much as possible in local-space.
- let p1 = position1
+ let p1 = coll_pos1
* Point::from(array![|ii| manifold_points[ii][k].local_p1; SIMD_WIDTH]);
- let p2 = position2
+ let p2 = coll_pos2
* Point::from(array![|ii| manifold_points[ii][k].local_p2; SIMD_WIDTH]);
let dist = SimdFloat::from(array![|ii| manifold_points[ii][k].dist; SIMD_WIDTH]);
diff --git a/src/dynamics/solver/velocity_ground_constraint.rs b/src/dynamics/solver/velocity_ground_constraint.rs
index 65a61bd..d9229ff 100644
--- a/src/dynamics/solver/velocity_ground_constraint.rs
+++ b/src/dynamics/solver/velocity_ground_constraint.rs
@@ -66,20 +66,22 @@ impl VelocityGroundConstraint {
let mut rb1 = &bodies[manifold.body_pair.body1];
let mut rb2 = &bodies[manifold.body_pair.body2];
let flipped = !rb2.is_dynamic();
+ let force_dir1;
+ let coll_pos1;
+ let coll_pos2;
if flipped {
+ coll_pos1 = rb2.position * manifold.delta2;
+ coll_pos2 = rb1.position * manifold.delta1;
+ force_dir1 = coll_pos1 * (-manifold.local_n2);
std::mem::swap(&mut rb1, &mut rb2);
+ } else {
+ coll_pos1 = rb1.position * manifold.delta1;
+ coll_pos2 = rb2.position * manifold.delta2;
+ force_dir1 = coll_pos1 * (-manifold.local_n1);
}
let mj_lambda2 = rb2.active_set_offset;
- let force_dir1 = if flipped {
- // NOTE: we already swapped rb1 and rb2
- // so we multiply by rb1.position.
- rb1.position * (-manifold.local_n2)
- } else {
- rb1.position * (-manifold.local_n1)
- };
-
let warmstart_coeff = manifold.warmstart_multiplier * params.warmstart_coeff;
for (l, manifold_points) in manifold
@@ -144,15 +146,15 @@ impl VelocityGroundConstraint {
let manifold_point = &manifold_points[k];
let (p1, p2) = if flipped {
// NOTE: we already swapped rb1 and rb2
- // so we multiply by rb2.position.
+ // so we multiply by coll_pos1/coll_pos2.
(
- rb1.position * manifold_point.local_p2,
- rb2.position * manifold_point.local_p1,
+ coll_pos1 * manifold_point.local_p2,
+ coll_pos2 * manifold_point.local_p1,
)
} else {
(
- rb1.position * manifold_point.local_p1,
- rb2.position * manifold_point.local_p2,
+ coll_pos1 * manifold_point.local_p1,
+ coll_pos2 * manifold_point.local_p2,
)
};
let dp2 = p2 - rb2.world_com;
diff --git a/src/dynamics/solver/velocity_ground_constraint_wide.rs b/src/dynamics/solver/velocity_ground_constraint_wide.rs
index af2e1e9..18e9257 100644
--- a/src/dynamics/solver/velocity_ground_constraint_wide.rs
+++ b/src/dynamics/solver/velocity_ground_constraint_wide.rs
@@ -86,13 +86,23 @@ impl WVelocityGroundConstraint {
let linvel2 = Vector::from(array![|ii| rbs2[ii].linvel; SIMD_WIDTH]);
let angvel2 = AngVector::<SimdFloat>::from(array![|ii| rbs2[ii].angvel; SIMD_WIDTH]);
- let position1 = Isometry::from(array![|ii| rbs1[ii].position; SIMD_WIDTH]);
- let position2 = Isometry::from(array![|ii| rbs2[ii].position; SIMD_WIDTH]);
+ let pos1 = Isometry::from(array![|ii| rbs1[ii].position; SIMD_WIDTH]);
+ let pos2 = Isometry::from(array![|ii| rbs2[ii].position; SIMD_WIDTH]);
+
+ let delta1 = Isometry::from(
+ array![|ii| if flipped[ii] { manifolds[ii].delta2 } else { manifolds[ii].delta1 }; SIMD_WIDTH],
+ );
+ let delta2 = Isometry::from(
+ array![|ii| if flipped[ii] { manifolds[ii].delta1 } else { manifolds[ii].delta2 }; SIMD_WIDTH],
+ );
+
+ let coll_pos1 = pos1 * delta1;
+ let coll_pos2 = pos2 * delta2;
let world_com1 = Point::from(array![|ii| rbs1[ii].world_com; SIMD_WIDTH]);
let world_com2 = Point::from(array![|ii| rbs2[ii].world_com; SIMD_WIDTH]);
- let force_dir1 = position1
+ let force_dir1 = coll_pos1
* -Vector::from(
array![|ii| if flipped[ii] { manifolds[ii].local_n2 } else { manifolds[ii].local_n1 }; SIMD_WIDTH],
);
@@ -120,11 +130,11 @@ impl WVelocityGroundConstraint {
};
for k in 0..num_points {
- let p1 = position1
+ let p1 = coll_pos1
* Point::from(
array![|ii| if flipped[ii] { manifold_points[ii][k].local_p2 } else { manifold_points[ii][k].local_p1 }; SIMD_WIDTH],
);
- let p2 = position2
+ let p2 = coll_pos2
* Point::from(
array![|ii| if flipped[ii] { manifold_points[ii][k].local_p1 } else { manifold_points[ii][k].local_p2 }; SIMD_WIDTH],
);