Fix constraints resolution with non-identity relative collider position.
This commit is contained in:
@@ -104,8 +104,8 @@ impl PositionConstraint {
|
|||||||
let mut local_p2 = [Point::origin(); MAX_MANIFOLD_POINTS];
|
let mut local_p2 = [Point::origin(); MAX_MANIFOLD_POINTS];
|
||||||
|
|
||||||
for l in 0..manifold_points.len() {
|
for l in 0..manifold_points.len() {
|
||||||
local_p1[l] = manifold_points[l].local_p1 + shift1;
|
local_p1[l] = manifold.delta1 * (manifold_points[l].local_p1 + shift1);
|
||||||
local_p2[l] = manifold_points[l].local_p2 + shift2;
|
local_p2[l] = manifold.delta2 * (manifold_points[l].local_p2 + shift2);
|
||||||
}
|
}
|
||||||
|
|
||||||
let constraint = PositionConstraint {
|
let constraint = PositionConstraint {
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ impl WPositionConstraint {
|
|||||||
let radius1 = SimdFloat::from(array![|ii| manifolds[ii].kinematics.radius1; 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 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 rb1 = array![|ii| rbs1[ii].active_set_offset; SIMD_WIDTH];
|
||||||
let rb2 = array![|ii| rbs2[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 =
|
let local_p2 =
|
||||||
Point::from(array![|ii| manifold_points[ii][i].local_p2; SIMD_WIDTH]);
|
Point::from(array![|ii| manifold_points[ii][i].local_p2; SIMD_WIDTH]);
|
||||||
|
|
||||||
constraint.local_p1[i] = local_p1 + shift1;
|
constraint.local_p1[i] = delta1 * (local_p1 + shift1);
|
||||||
constraint.local_p2[i] = local_p2 + shift2;
|
constraint.local_p2[i] = delta2 * (local_p2 + shift2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if push {
|
if push {
|
||||||
|
|||||||
@@ -34,22 +34,30 @@ impl PositionGroundConstraint {
|
|||||||
|
|
||||||
let local_n1;
|
let local_n1;
|
||||||
let local_n2;
|
let local_n2;
|
||||||
|
let delta1;
|
||||||
|
let delta2;
|
||||||
|
|
||||||
if flip {
|
if flip {
|
||||||
std::mem::swap(&mut rb1, &mut rb2);
|
std::mem::swap(&mut rb1, &mut rb2);
|
||||||
local_n1 = manifold.local_n2;
|
local_n1 = manifold.local_n2;
|
||||||
local_n2 = manifold.local_n1;
|
local_n2 = manifold.local_n1;
|
||||||
|
delta1 = &manifold.delta2;
|
||||||
|
delta2 = &manifold.delta1;
|
||||||
} else {
|
} else {
|
||||||
local_n1 = manifold.local_n1;
|
local_n1 = manifold.local_n1;
|
||||||
local_n2 = manifold.local_n2;
|
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 shift1 = local_n1 * -manifold.kinematics.radius1;
|
||||||
let shift2 = local_n2 * -manifold.kinematics.radius2;
|
let shift2 = local_n2 * -manifold.kinematics.radius2;
|
||||||
|
let n1 = coll_pos1 * local_n1;
|
||||||
let radius =
|
let radius =
|
||||||
manifold.kinematics.radius1 + manifold.kinematics.radius2 /* - params.allowed_linear_error */;
|
manifold.kinematics.radius1 + manifold.kinematics.radius2 /* - params.allowed_linear_error */;
|
||||||
|
|
||||||
for (l, manifold_points) in manifold
|
for (l, manifold_contacts) in manifold
|
||||||
.active_contacts()
|
.active_contacts()
|
||||||
.chunks(MAX_MANIFOLD_POINTS)
|
.chunks(MAX_MANIFOLD_POINTS)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@@ -59,16 +67,16 @@ impl PositionGroundConstraint {
|
|||||||
|
|
||||||
if flip {
|
if flip {
|
||||||
// Don't forget that we already swapped rb1 and rb2 above.
|
// 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.
|
// be swapped.
|
||||||
for k in 0..manifold_points.len() {
|
for k in 0..manifold_contacts.len() {
|
||||||
p1[k] = rb1.predicted_position * (manifold_points[k].local_p2 + shift1);
|
p1[k] = coll_pos1 * (manifold_contacts[k].local_p2 + shift1);
|
||||||
local_p2[k] = manifold_points[k].local_p1 + shift2;
|
local_p2[k] = delta2 * (manifold_contacts[k].local_p1 + shift2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for k in 0..manifold_points.len() {
|
for k in 0..manifold_contacts.len() {
|
||||||
p1[k] = rb1.predicted_position * (manifold_points[k].local_p1 + shift1);
|
p1[k] = coll_pos1 * (manifold_contacts[k].local_p1 + shift1);
|
||||||
local_p2[k] = manifold_points[k].local_p2 + shift2;
|
local_p2[k] = delta2 * (manifold_contacts[k].local_p2 + shift2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,11 +84,11 @@ impl PositionGroundConstraint {
|
|||||||
rb2: rb2.active_set_offset,
|
rb2: rb2.active_set_offset,
|
||||||
p1,
|
p1,
|
||||||
local_p2,
|
local_p2,
|
||||||
n1: rb1.predicted_position * local_n1,
|
n1,
|
||||||
radius,
|
radius,
|
||||||
im2: rb2.mass_properties.inv_mass,
|
im2: rb2.mass_properties.inv_mass,
|
||||||
ii2: rb2.world_inv_inertia_sqrt.squared(),
|
ii2: rb2.world_inv_inertia_sqrt.squared(),
|
||||||
num_contacts: manifold_points.len() as u8,
|
num_contacts: manifold_contacts.len() as u8,
|
||||||
erp: params.erp,
|
erp: params.erp,
|
||||||
max_linear_correction: params.max_linear_correction,
|
max_linear_correction: params.max_linear_correction,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,16 +54,24 @@ impl WPositionGroundConstraint {
|
|||||||
array![|ii| if flipped[ii] { manifolds[ii].local_n1 } else { manifolds[ii].local_n2 }; SIMD_WIDTH],
|
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 radius1 = SimdFloat::from(array![|ii| manifolds[ii].kinematics.radius1; SIMD_WIDTH]);
|
||||||
let radius2 = SimdFloat::from(array![|ii| manifolds[ii].kinematics.radius2; 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 rb2 = array![|ii| rbs2[ii].active_set_offset; SIMD_WIDTH];
|
||||||
|
|
||||||
let radius = radius1 + radius2 /*- SimdFloat::splat(params.allowed_linear_error)*/;
|
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) {
|
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];
|
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],
|
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.p1[i] = coll_pos1 * local_p1 - n1 * radius1;
|
||||||
constraint.local_p2[i] = local_p2 - local_n2 * radius2;
|
constraint.local_p2[i] = delta2 * (local_p2 - local_n2 * radius2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if push {
|
if push {
|
||||||
|
|||||||
@@ -148,7 +148,9 @@ impl VelocityConstraint {
|
|||||||
let rb2 = &bodies[manifold.body_pair.body2];
|
let rb2 = &bodies[manifold.body_pair.body2];
|
||||||
let mj_lambda1 = rb1.active_set_offset;
|
let mj_lambda1 = rb1.active_set_offset;
|
||||||
let mj_lambda2 = rb2.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;
|
let warmstart_coeff = manifold.warmstart_multiplier * params.warmstart_coeff;
|
||||||
|
|
||||||
for (l, manifold_points) in manifold
|
for (l, manifold_points) in manifold
|
||||||
@@ -215,8 +217,8 @@ impl VelocityConstraint {
|
|||||||
|
|
||||||
for k in 0..manifold_points.len() {
|
for k in 0..manifold_points.len() {
|
||||||
let manifold_point = &manifold_points[k];
|
let manifold_point = &manifold_points[k];
|
||||||
let dp1 = (rb1.position * manifold_point.local_p1) - rb1.world_com;
|
let dp1 = (pos_coll1 * manifold_point.local_p1) - rb1.world_com;
|
||||||
let dp2 = (rb2.position * manifold_point.local_p2) - rb2.world_com;
|
let dp2 = (pos_coll2 * manifold_point.local_p2) - rb2.world_com;
|
||||||
|
|
||||||
let vel1 = rb1.linvel + rb1.angvel.gcross(dp1);
|
let vel1 = rb1.linvel + rb1.angvel.gcross(dp1);
|
||||||
let vel2 = rb2.linvel + rb2.angvel.gcross(dp2);
|
let vel2 = rb2.linvel + rb2.angvel.gcross(dp2);
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ impl WVelocityConstraint {
|
|||||||
let rbs1 = array![|ii| &bodies[manifolds[ii].body_pair.body1]; SIMD_WIDTH];
|
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 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 im1 = SimdFloat::from(array![|ii| rbs1[ii].mass_properties.inv_mass; SIMD_WIDTH]);
|
||||||
let ii1: AngularInertia<SimdFloat> =
|
let ii1: AngularInertia<SimdFloat> =
|
||||||
AngularInertia::from(array![|ii| rbs1[ii].world_inv_inertia_sqrt; SIMD_WIDTH]);
|
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 linvel1 = Vector::from(array![|ii| rbs1[ii].linvel; SIMD_WIDTH]);
|
||||||
let angvel1 = AngVector::<SimdFloat>::from(array![|ii| rbs1[ii].angvel; 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 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]);
|
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 linvel2 = Vector::from(array![|ii| rbs2[ii].linvel; SIMD_WIDTH]);
|
||||||
let angvel2 = AngVector::<SimdFloat>::from(array![|ii| rbs2[ii].angvel; 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 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_lambda1 = array![|ii| rbs1[ii].active_set_offset; SIMD_WIDTH];
|
||||||
let mj_lambda2 = array![|ii| rbs2[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 {
|
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.
|
// 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]);
|
* 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]);
|
* 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]);
|
let dist = SimdFloat::from(array![|ii| manifold_points[ii][k].dist; SIMD_WIDTH]);
|
||||||
|
|||||||
@@ -66,20 +66,22 @@ impl VelocityGroundConstraint {
|
|||||||
let mut rb1 = &bodies[manifold.body_pair.body1];
|
let mut rb1 = &bodies[manifold.body_pair.body1];
|
||||||
let mut rb2 = &bodies[manifold.body_pair.body2];
|
let mut rb2 = &bodies[manifold.body_pair.body2];
|
||||||
let flipped = !rb2.is_dynamic();
|
let flipped = !rb2.is_dynamic();
|
||||||
|
let force_dir1;
|
||||||
|
let coll_pos1;
|
||||||
|
let coll_pos2;
|
||||||
|
|
||||||
if flipped {
|
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);
|
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 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;
|
let warmstart_coeff = manifold.warmstart_multiplier * params.warmstart_coeff;
|
||||||
|
|
||||||
for (l, manifold_points) in manifold
|
for (l, manifold_points) in manifold
|
||||||
@@ -144,15 +146,15 @@ impl VelocityGroundConstraint {
|
|||||||
let manifold_point = &manifold_points[k];
|
let manifold_point = &manifold_points[k];
|
||||||
let (p1, p2) = if flipped {
|
let (p1, p2) = if flipped {
|
||||||
// NOTE: we already swapped rb1 and rb2
|
// 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,
|
coll_pos1 * manifold_point.local_p2,
|
||||||
rb2.position * manifold_point.local_p1,
|
coll_pos2 * manifold_point.local_p1,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
rb1.position * manifold_point.local_p1,
|
coll_pos1 * manifold_point.local_p1,
|
||||||
rb2.position * manifold_point.local_p2,
|
coll_pos2 * manifold_point.local_p2,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let dp2 = p2 - rb2.world_com;
|
let dp2 = p2 - rb2.world_com;
|
||||||
|
|||||||
@@ -86,13 +86,23 @@ impl WVelocityGroundConstraint {
|
|||||||
let linvel2 = Vector::from(array![|ii| rbs2[ii].linvel; SIMD_WIDTH]);
|
let linvel2 = Vector::from(array![|ii| rbs2[ii].linvel; SIMD_WIDTH]);
|
||||||
let angvel2 = AngVector::<SimdFloat>::from(array![|ii| rbs2[ii].angvel; 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 pos1 = Isometry::from(array![|ii| rbs1[ii].position; 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 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_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 world_com2 = Point::from(array![|ii| rbs2[ii].world_com; SIMD_WIDTH]);
|
||||||
|
|
||||||
let force_dir1 = position1
|
let force_dir1 = coll_pos1
|
||||||
* -Vector::from(
|
* -Vector::from(
|
||||||
array![|ii| if flipped[ii] { manifolds[ii].local_n2 } else { manifolds[ii].local_n1 }; SIMD_WIDTH],
|
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 {
|
for k in 0..num_points {
|
||||||
let p1 = position1
|
let p1 = coll_pos1
|
||||||
* Point::from(
|
* Point::from(
|
||||||
array![|ii| if flipped[ii] { manifold_points[ii][k].local_p2 } else { manifold_points[ii][k].local_p1 }; SIMD_WIDTH],
|
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(
|
* Point::from(
|
||||||
array![|ii| if flipped[ii] { manifold_points[ii][k].local_p1 } else { manifold_points[ii][k].local_p2 }; SIMD_WIDTH],
|
array![|ii| if flipped[ii] { manifold_points[ii][k].local_p1 } else { manifold_points[ii][k].local_p2 }; SIMD_WIDTH],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -273,16 +273,21 @@ pub struct ContactManifold {
|
|||||||
/// The pair of subshapes involved in this contact manifold.
|
/// The pair of subshapes involved in this contact manifold.
|
||||||
pub subshape_index_pair: (usize, usize),
|
pub subshape_index_pair: (usize, usize),
|
||||||
pub(crate) warmstart_multiplier: f32,
|
pub(crate) warmstart_multiplier: f32,
|
||||||
// We put the friction and restitution here because
|
// The two following are set by the constraints solver.
|
||||||
// this avoids reading the colliders inside of the
|
pub(crate) constraint_index: usize,
|
||||||
|
pub(crate) position_constraint_index: usize,
|
||||||
|
// We put the following fields here to avoids reading the colliders inside of the
|
||||||
// contact preparation method.
|
// contact preparation method.
|
||||||
/// The friction coefficient for of all the contacts on this contact manifold.
|
/// The friction coefficient for of all the contacts on this contact manifold.
|
||||||
pub friction: f32,
|
pub friction: f32,
|
||||||
/// The restitution coefficient for all the contacts on this contact manifold.
|
/// The restitution coefficient for all the contacts on this contact manifold.
|
||||||
pub restitution: f32,
|
pub restitution: f32,
|
||||||
// The following are set by the constraints solver.
|
/// The relative position between the first collider and its parent at the time the
|
||||||
pub(crate) constraint_index: usize,
|
/// contact points were generated.
|
||||||
pub(crate) position_constraint_index: usize,
|
pub delta1: Isometry<f32>,
|
||||||
|
/// The relative position between the second collider and its parent at the time the
|
||||||
|
/// contact points were generated.
|
||||||
|
pub delta2: Isometry<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContactManifold {
|
impl ContactManifold {
|
||||||
@@ -290,6 +295,8 @@ impl ContactManifold {
|
|||||||
pair: ColliderPair,
|
pair: ColliderPair,
|
||||||
subshapes: (usize, usize),
|
subshapes: (usize, usize),
|
||||||
body_pair: BodyPair,
|
body_pair: BodyPair,
|
||||||
|
delta1: Isometry<f32>,
|
||||||
|
delta2: Isometry<f32>,
|
||||||
friction: f32,
|
friction: f32,
|
||||||
restitution: f32,
|
restitution: f32,
|
||||||
) -> ContactManifold {
|
) -> ContactManifold {
|
||||||
@@ -308,6 +315,8 @@ impl ContactManifold {
|
|||||||
warmstart_multiplier: Self::min_warmstart_multiplier(),
|
warmstart_multiplier: Self::min_warmstart_multiplier(),
|
||||||
friction,
|
friction,
|
||||||
restitution,
|
restitution,
|
||||||
|
delta1,
|
||||||
|
delta2,
|
||||||
constraint_index: 0,
|
constraint_index: 0,
|
||||||
position_constraint_index: 0,
|
position_constraint_index: 0,
|
||||||
}
|
}
|
||||||
@@ -329,6 +338,8 @@ impl ContactManifold {
|
|||||||
warmstart_multiplier: self.warmstart_multiplier,
|
warmstart_multiplier: self.warmstart_multiplier,
|
||||||
friction: self.friction,
|
friction: self.friction,
|
||||||
restitution: self.restitution,
|
restitution: self.restitution,
|
||||||
|
delta1: self.delta1,
|
||||||
|
delta2: self.delta2,
|
||||||
constraint_index: self.constraint_index,
|
constraint_index: self.constraint_index,
|
||||||
position_constraint_index: self.position_constraint_index,
|
position_constraint_index: self.position_constraint_index,
|
||||||
}
|
}
|
||||||
@@ -349,6 +360,8 @@ impl ContactManifold {
|
|||||||
pair,
|
pair,
|
||||||
(subshape1, subshape2),
|
(subshape1, subshape2),
|
||||||
BodyPair::new(coll1.parent, coll2.parent),
|
BodyPair::new(coll1.parent, coll2.parent),
|
||||||
|
*coll1.delta(),
|
||||||
|
*coll2.delta(),
|
||||||
(coll1.friction + coll2.friction) * 0.5,
|
(coll1.friction + coll2.friction) * 0.5,
|
||||||
(coll1.restitution + coll2.restitution) * 0.5,
|
(coll1.restitution + coll2.restitution) * 0.5,
|
||||||
)
|
)
|
||||||
@@ -391,6 +404,7 @@ impl ContactManifold {
|
|||||||
self.pair = self.pair.swap();
|
self.pair = self.pair.swap();
|
||||||
self.body_pair = self.body_pair.swap();
|
self.body_pair = self.body_pair.swap();
|
||||||
self.subshape_index_pair = (self.subshape_index_pair.1, self.subshape_index_pair.0);
|
self.subshape_index_pair = (self.subshape_index_pair.1, self.subshape_index_pair.0);
|
||||||
|
std::mem::swap(&mut self.delta1, &mut self.delta2);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update_warmstart_multiplier(&mut self) {
|
pub(crate) fn update_warmstart_multiplier(&mut self) {
|
||||||
|
|||||||
@@ -10,10 +10,8 @@ pub fn generate_contacts_cuboid_cuboid(ctxt: &mut PrimitiveContactGenerationCont
|
|||||||
generate_contacts(
|
generate_contacts(
|
||||||
ctxt.prediction_distance,
|
ctxt.prediction_distance,
|
||||||
cube1,
|
cube1,
|
||||||
ctxt.collider1.position_wrt_parent(),
|
|
||||||
ctxt.position1,
|
ctxt.position1,
|
||||||
cube2,
|
cube2,
|
||||||
ctxt.collider2.position_wrt_parent(),
|
|
||||||
ctxt.position2,
|
ctxt.position2,
|
||||||
ctxt.manifold,
|
ctxt.manifold,
|
||||||
);
|
);
|
||||||
@@ -28,19 +26,15 @@ pub fn generate_contacts_cuboid_cuboid(ctxt: &mut PrimitiveContactGenerationCont
|
|||||||
pub fn generate_contacts<'a>(
|
pub fn generate_contacts<'a>(
|
||||||
prediction_distance: f32,
|
prediction_distance: f32,
|
||||||
mut cube1: &'a Cuboid<f32>,
|
mut cube1: &'a Cuboid<f32>,
|
||||||
mut origin1: &'a Isometry<f32>,
|
|
||||||
mut pos1: &'a Isometry<f32>,
|
mut pos1: &'a Isometry<f32>,
|
||||||
mut cube2: &'a Cuboid<f32>,
|
mut cube2: &'a Cuboid<f32>,
|
||||||
mut origin2: &'a Isometry<f32>,
|
|
||||||
mut pos2: &'a Isometry<f32>,
|
mut pos2: &'a Isometry<f32>,
|
||||||
manifold: &mut ContactManifold,
|
manifold: &mut ContactManifold,
|
||||||
) {
|
) {
|
||||||
let mut pos12 = pos1.inverse() * pos2;
|
let mut pos12 = pos1.inverse() * pos2;
|
||||||
let mut pos21 = pos12.inverse();
|
let mut pos21 = pos12.inverse();
|
||||||
let mut orig_pos12 = origin1 * pos12 * origin2.inverse();
|
|
||||||
let mut orig_pos21 = orig_pos12.inverse();
|
|
||||||
|
|
||||||
if manifold.try_update_contacts(&orig_pos12) {
|
if manifold.try_update_contacts(&pos12) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,9 +81,8 @@ pub fn generate_contacts<'a>(
|
|||||||
if sep2.0 > sep1.0 && sep2.0 > sep3.0 {
|
if sep2.0 > sep1.0 && sep2.0 > sep3.0 {
|
||||||
// The reference shape will be the second shape.
|
// The reference shape will be the second shape.
|
||||||
std::mem::swap(&mut cube1, &mut cube2);
|
std::mem::swap(&mut cube1, &mut cube2);
|
||||||
|
std::mem::swap(&mut pos1, &mut pos2);
|
||||||
std::mem::swap(&mut pos12, &mut pos21);
|
std::mem::swap(&mut pos12, &mut pos21);
|
||||||
std::mem::swap(&mut orig_pos12, &mut orig_pos21);
|
|
||||||
std::mem::swap(&mut origin1, &mut origin2);
|
|
||||||
manifold.swap_identifiers();
|
manifold.swap_identifiers();
|
||||||
best_sep = sep2;
|
best_sep = sep2;
|
||||||
swapped = true;
|
swapped = true;
|
||||||
@@ -104,49 +97,46 @@ pub fn generate_contacts<'a>(
|
|||||||
|
|
||||||
// Now the reference feature is from `cube1` and the best separation is `best_sep`.
|
// Now the reference feature is from `cube1` and the best separation is `best_sep`.
|
||||||
// Everything must be expressed in the local-space of `cube1` for contact clipping.
|
// Everything must be expressed in the local-space of `cube1` for contact clipping.
|
||||||
let mut feature1 = cuboid::support_feature(cube1, best_sep.1);
|
let feature1 = cuboid::support_feature(cube1, best_sep.1);
|
||||||
feature1.transform_by(origin1);
|
|
||||||
let mut feature2 = cuboid::support_feature(cube2, pos21 * -best_sep.1);
|
let mut feature2 = cuboid::support_feature(cube2, pos21 * -best_sep.1);
|
||||||
feature2.transform_by(&pos12);
|
feature2.transform_by(&pos12);
|
||||||
feature2.transform_by(origin1);
|
|
||||||
let n1 = origin1 * best_sep.1;
|
|
||||||
|
|
||||||
match (&feature1, &feature2) {
|
match (&feature1, &feature2) {
|
||||||
(CuboidFeature::Face(f1), CuboidFeature::Vertex(v2)) => {
|
(CuboidFeature::Face(f1), CuboidFeature::Vertex(v2)) => {
|
||||||
CuboidFeature::face_vertex_contacts(f1, &n1, v2, &orig_pos21, manifold)
|
CuboidFeature::face_vertex_contacts(f1, &best_sep.1, v2, &pos21, manifold)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dim3")]
|
#[cfg(feature = "dim3")]
|
||||||
(CuboidFeature::Face(f1), CuboidFeature::Edge(e2)) => CuboidFeature::face_edge_contacts(
|
(CuboidFeature::Face(f1), CuboidFeature::Edge(e2)) => CuboidFeature::face_edge_contacts(
|
||||||
prediction_distance,
|
prediction_distance,
|
||||||
f1,
|
f1,
|
||||||
&n1,
|
&best_sep.1,
|
||||||
e2,
|
e2,
|
||||||
&orig_pos21,
|
&pos21,
|
||||||
manifold,
|
manifold,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
(CuboidFeature::Face(f1), CuboidFeature::Face(f2)) => CuboidFeature::face_face_contacts(
|
(CuboidFeature::Face(f1), CuboidFeature::Face(f2)) => CuboidFeature::face_face_contacts(
|
||||||
prediction_distance,
|
prediction_distance,
|
||||||
f1,
|
f1,
|
||||||
&n1,
|
&best_sep.1,
|
||||||
f2,
|
f2,
|
||||||
&orig_pos21,
|
&pos21,
|
||||||
manifold,
|
manifold,
|
||||||
),
|
),
|
||||||
#[cfg(feature = "dim3")]
|
#[cfg(feature = "dim3")]
|
||||||
(CuboidFeature::Edge(e1), CuboidFeature::Edge(e2)) => {
|
(CuboidFeature::Edge(e1), CuboidFeature::Edge(e2)) => {
|
||||||
CuboidFeature::edge_edge_contacts(e1, &n1, e2, &orig_pos21, manifold)
|
CuboidFeature::edge_edge_contacts(e1, &best_sep.1, e2, &pos21, manifold)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dim3")]
|
#[cfg(feature = "dim3")]
|
||||||
(CuboidFeature::Edge(e1), CuboidFeature::Face(f2)) => {
|
(CuboidFeature::Edge(e1), CuboidFeature::Face(f2)) => {
|
||||||
// Since f2 is also expressed in the local-space of the first
|
// Since f2 is also expressed in the local-space of the first
|
||||||
// feature, the position we provide here is orig_pos21.
|
// feature, the position we provide here is pos21.
|
||||||
CuboidFeature::face_edge_contacts(
|
CuboidFeature::face_edge_contacts(
|
||||||
prediction_distance,
|
prediction_distance,
|
||||||
f2,
|
f2,
|
||||||
&-n1,
|
&-best_sep.1,
|
||||||
e1,
|
e1,
|
||||||
&orig_pos21,
|
&pos21,
|
||||||
manifold,
|
manifold,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
@@ -154,8 +144,8 @@ pub fn generate_contacts<'a>(
|
|||||||
_ => unreachable!(), // The other cases are not possible.
|
_ => unreachable!(), // The other cases are not possible.
|
||||||
}
|
}
|
||||||
|
|
||||||
manifold.local_n1 = n1;
|
manifold.local_n1 = best_sep.1;
|
||||||
manifold.local_n2 = orig_pos21 * -n1;
|
manifold.local_n2 = pos21 * -best_sep.1;
|
||||||
manifold.kinematics.category = KinematicsCategory::PlanePoint;
|
manifold.kinematics.category = KinematicsCategory::PlanePoint;
|
||||||
manifold.kinematics.radius1 = 0.0;
|
manifold.kinematics.radius1 = 0.0;
|
||||||
manifold.kinematics.radius2 = 0.0;
|
manifold.kinematics.radius2 = 0.0;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use rapier::dynamics::{
|
|||||||
IntegrationParameters, JointParams, JointSet, RigidBodyHandle, RigidBodySet,
|
IntegrationParameters, JointParams, JointSet, RigidBodyHandle, RigidBodySet,
|
||||||
};
|
};
|
||||||
use rapier::geometry::{Collider, ColliderSet, Shape};
|
use rapier::geometry::{Collider, ColliderSet, Shape};
|
||||||
use rapier::math::{Isometry, Vector};
|
use rapier::math::Vector;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
#[cfg(feature = "dim3")]
|
#[cfg(feature = "dim3")]
|
||||||
use {ncollide::shape::TriMesh, nphysics::joint::BallConstraint};
|
use {ncollide::shape::TriMesh, nphysics::joint::BallConstraint};
|
||||||
|
|||||||
Reference in New Issue
Block a user