fix sphere-sphere collisions for moving spheres

This commit is contained in:
David Rose 2008-06-18 22:08:35 +00:00
parent aa92d0c62e
commit 20197b6767

View File

@ -312,11 +312,9 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
DCAST_INTO_R(sphere, entry.get_from(), 0); DCAST_INTO_R(sphere, entry.get_from(), 0);
CPT(TransformState) wrt_space = entry.get_wrt_space(); CPT(TransformState) wrt_space = entry.get_wrt_space();
CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space();
const LMatrix4f &wrt_mat = wrt_space->get_mat(); const LMatrix4f &wrt_mat = wrt_space->get_mat();
LPoint3f from_a = sphere->get_center() * wrt_prev_space->get_mat();
LPoint3f from_b = sphere->get_center() * wrt_mat; LPoint3f from_b = sphere->get_center() * wrt_mat;
LPoint3f into_center(get_center()); LPoint3f into_center(get_center());
@ -331,45 +329,46 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
LPoint3f contact_point(into_intersection_point); LPoint3f contact_point(into_intersection_point);
float actual_t = 0.0f; float actual_t = 0.0f;
if (from_a != from_b) { LVector3f vec = from_b - into_center;
LVector3f from_direction = from_b - from_a; float dist2 = dot(vec, vec);
if (!intersects_line(t1, t2, from_a, from_direction, from_radius)) { if (dist2 > (into_radius + from_radius) * (into_radius + from_radius)) {
// No intersection. // No intersection with the current position. Check the delta
return NULL; // from the previous frame.
} CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space();
LPoint3f from_a = sphere->get_center() * wrt_prev_space->get_mat();
if (t2 < 0.0 || t1 > 1.0) { if (!from_a.almost_equal(from_b)) {
// Both intersection points are before the start of the segment or LVector3f from_direction = from_b - from_a;
// after the end of the segment. if (!intersects_line(t1, t2, from_a, from_direction, from_radius)) {
return NULL; // No intersection.
} return NULL;
}
// doubles, not floats, to satisfy min and max templates.
actual_t = min(1.0, max(0.0, t1)); if (t2 < 0.0 || t1 > 1.0) {
contact_point = from_a + actual_t * (from_b - from_a); // Both intersection points are before the start of the segment or
// after the end of the segment.
if (t1 < 0.0) { return NULL;
// Point a is within the sphere. The first intersection point is }
// point a itself.
into_intersection_point = from_a; // doubles, not floats, to satisfy min and max templates.
actual_t = min(1.0, max(0.0, t1));
contact_point = from_a + actual_t * (from_b - from_a);
if (t1 < 0.0) {
// Point a is within the sphere. The first intersection point is
// point a itself.
into_intersection_point = from_a;
} else {
// Point a is outside the sphere, and point b is either inside the
// sphere or beyond it. The first intersection point is at t1.
into_intersection_point = from_a + t1 * from_direction;
}
} else { } else {
// Point a is outside the sphere, and point b is either inside the // No delta, therefore no intersection.
// sphere or beyond it. The first intersection point is at t1.
into_intersection_point = from_a + t1 * from_direction;
}
} else {
LVector3f vec = from_a - into_center;
float dist2 = dot(vec, vec);
if (dist2 > (into_radius + from_radius) * (into_radius + from_radius)) {
// No intersection.
return NULL; return NULL;
} }
into_intersection_point = from_a;
t1 = 0.0f;
} }
if (collide_cat.is_debug()) { if (collide_cat.is_debug()) {
collide_cat.debug() collide_cat.debug()
<< "intersection detected from " << entry.get_from_node_path() << "intersection detected from " << entry.get_from_node_path()