Properly allowing for rotated box vs plane checking.
parent
cd57d8aa7e
commit
0624a7e1ac
|
@ -94,6 +94,13 @@ void SimShapeSupport(
|
||||||
ccdVec3Add(v, &pos);
|
ccdVec3Add(v, &pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sSwapCollisionInfoShapeOrder(CollisionInfo &cinfo) {
|
||||||
|
cinfo.dir *= -1.;
|
||||||
|
Vector3d temp_pos = cinfo.posA;
|
||||||
|
cinfo.posA = cinfo.posB;
|
||||||
|
cinfo.posB = temp_pos;
|
||||||
|
}
|
||||||
|
|
||||||
bool CheckPenetration(
|
bool CheckPenetration(
|
||||||
const SimShape& shape_a,
|
const SimShape& shape_a,
|
||||||
const SimShape& shape_b,
|
const SimShape& shape_b,
|
||||||
|
@ -105,10 +112,7 @@ bool CheckPenetration(
|
||||||
}
|
}
|
||||||
if (shape_b.mType == SimShape::Sphere && shape_a.mType == SimShape::Plane) {
|
if (shape_b.mType == SimShape::Sphere && shape_a.mType == SimShape::Plane) {
|
||||||
bool result = CheckPenetrationSphereVsPlane(shape_b, shape_a, cinfo);
|
bool result = CheckPenetrationSphereVsPlane(shape_b, shape_a, cinfo);
|
||||||
cinfo.dir *= -1.;
|
sSwapCollisionInfoShapeOrder(cinfo);
|
||||||
Vector3d temp_pos = cinfo.posA;
|
|
||||||
cinfo.posA = cinfo.posB;
|
|
||||||
cinfo.posB = temp_pos;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (shape_a.mType == SimShape::Sphere && shape_b.mType == SimShape::Sphere) {
|
if (shape_a.mType == SimShape::Sphere && shape_b.mType == SimShape::Sphere) {
|
||||||
|
@ -117,6 +121,11 @@ bool CheckPenetration(
|
||||||
if (shape_a.mType == SimShape::Box && shape_b.mType == SimShape::Plane) {
|
if (shape_a.mType == SimShape::Box && shape_b.mType == SimShape::Plane) {
|
||||||
return CheckPenetrationBoxVsPlane(shape_a, shape_b, cinfo);
|
return CheckPenetrationBoxVsPlane(shape_a, shape_b, cinfo);
|
||||||
}
|
}
|
||||||
|
if (shape_a.mType == SimShape::Plane && shape_b.mType == SimShape::Box) {
|
||||||
|
bool result = CheckPenetrationBoxVsPlane(shape_a, shape_b, cinfo);
|
||||||
|
sSwapCollisionInfoShapeOrder(cinfo);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ccd_t ccd;
|
ccd_t ccd;
|
||||||
CCD_INIT(&ccd);
|
CCD_INIT(&ccd);
|
||||||
|
@ -181,7 +190,8 @@ bool CheckPenetrationSphereVsPlane(
|
||||||
(shape_a.orientation - Quaternion(0., 0., 0., 1.)).squaredNorm()
|
(shape_a.orientation - Quaternion(0., 0., 0., 1.)).squaredNorm()
|
||||||
< cCollisionEps);
|
< cCollisionEps);
|
||||||
|
|
||||||
Vector3d plane_normal = shape_b.orientation.conjugate().rotate(Vector3d (0., 1., 0.));
|
Vector3d plane_normal =
|
||||||
|
shape_b.orientation.conjugate().rotate(Vector3d(0., 1., 0.));
|
||||||
Vector3d plane_point = shape_b.pos;
|
Vector3d plane_point = shape_b.pos;
|
||||||
Vector3d sphere_point_to_plane =
|
Vector3d sphere_point_to_plane =
|
||||||
shape_a.pos - plane_normal * shape_a.scale[0] * 0.5;
|
shape_a.pos - plane_normal * shape_a.scale[0] * 0.5;
|
||||||
|
@ -229,13 +239,19 @@ bool CheckPenetrationBoxVsPlane (
|
||||||
aabb.pos.setZero();
|
aabb.pos.setZero();
|
||||||
aabb.orientation = Quaternion(0., 0., 0., 1.);
|
aabb.orientation = Quaternion(0., 0., 0., 1.);
|
||||||
|
|
||||||
plane.pos = shape_a.orientation.rotate(shape_b.pos - shape_a.pos);
|
const Matrix3d shape_a_rot = shape_a.orientation.toMatrix();
|
||||||
Quaternion rot_rel_box = shape_a.orientation.conjugate() * shape_b.orientation;
|
plane.pos = shape_a_rot * (shape_b.pos - shape_a.pos);
|
||||||
|
Quaternion rot_rel_box =
|
||||||
|
shape_a.orientation.conjugate() * shape_b.orientation;
|
||||||
plane.orientation = rot_rel_box;
|
plane.orientation = rot_rel_box;
|
||||||
|
|
||||||
bool result = CheckPenetrationAABBVsPlane(aabb, plane, cinfo);
|
bool result = CheckPenetrationAABBVsPlane(aabb, plane, cinfo);
|
||||||
|
|
||||||
// TODO: transform values back into world space
|
cinfo.posA = shape_a_rot.transpose() * (cinfo.posA) + shape_a.pos;
|
||||||
|
cinfo.posB = shape_a_rot.transpose() * (cinfo.posB) + shape_a.pos;
|
||||||
|
cinfo.dir = shape_a_rot.transpose() * (cinfo.dir);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckPenetrationAABBVsPlane(
|
bool CheckPenetrationAABBVsPlane(
|
||||||
|
@ -246,7 +262,8 @@ bool CheckPenetrationAABBVsPlane(
|
||||||
assert(shape_b.mType == SimShape::Plane);
|
assert(shape_b.mType == SimShape::Plane);
|
||||||
cinfo.mNumManifoldPoints = 0;
|
cinfo.mNumManifoldPoints = 0;
|
||||||
|
|
||||||
Vector3d plane_normal = shape_b.orientation.conjugate().rotate(Vector3d (0., 1., 0.));
|
Vector3d plane_normal =
|
||||||
|
shape_b.orientation.conjugate().rotate(Vector3d(0., 1., 0.));
|
||||||
Vector3d plane_pos = shape_b.pos;
|
Vector3d plane_pos = shape_b.pos;
|
||||||
Vector3d dir_min, dir_max;
|
Vector3d dir_min, dir_max;
|
||||||
|
|
||||||
|
@ -263,12 +280,15 @@ bool CheckPenetrationAABBVsPlane(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Separation direction clear: we would need to push the plane along its
|
||||||
|
// negative plane normal for separation.
|
||||||
|
cinfo.dir = -plane_normal;
|
||||||
|
|
||||||
// If center is below plane, return that
|
// If center is below plane, return that
|
||||||
double center_distance = (Vector3d::Zero() - plane_pos).dot(plane_normal);
|
double center_distance = (Vector3d::Zero() - plane_pos).dot(plane_normal);
|
||||||
if (center_distance < cCollisionEps) {
|
if (center_distance < cCollisionEps) {
|
||||||
cinfo.posA = Vector3d::Zero();
|
cinfo.posA = Vector3d::Zero();
|
||||||
cinfo.posB = Vector3d::Zero();
|
cinfo.posB = Vector3d::Zero();
|
||||||
cinfo.dir = -plane_normal;
|
|
||||||
cinfo.depth = center_distance - cCollisionEps;
|
cinfo.depth = center_distance - cCollisionEps;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -340,9 +360,7 @@ bool CheckPenetrationAABBVsPlane(
|
||||||
cinfo.posA += cinfo.mManifoldPoints[i];
|
cinfo.posA += cinfo.mManifoldPoints[i];
|
||||||
}
|
}
|
||||||
cinfo.posA = cinfo.posA / (double)cinfo.mNumManifoldPoints;
|
cinfo.posA = cinfo.posA / (double)cinfo.mNumManifoldPoints;
|
||||||
|
|
||||||
cinfo.posB = cinfo.posA;
|
cinfo.posB = cinfo.posA;
|
||||||
cinfo.dir = -plane_normal;
|
|
||||||
cinfo.depth = max_depth;
|
cinfo.depth = max_depth;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -89,6 +89,7 @@ TEST_CASE ("AABB vs Plane", "[Collision]") {
|
||||||
|
|
||||||
REQUIRE(cresult == true);
|
REQUIRE(cresult == true);
|
||||||
REQUIRE((cinfo.posA - Vector3d(0, -0.5, -0.5)).norm() < 1.0e-12);
|
REQUIRE((cinfo.posA - Vector3d(0, -0.5, -0.5)).norm() < 1.0e-12);
|
||||||
|
REQUIRE((cinfo.dir - Vector3d(0, -sqrt(2.) * 0.5, -sqrt(2.) * 0.5)).norm() < 1.0e-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Unit AABB Intersecting Contact Rotated Plane") {
|
SECTION("Unit AABB Intersecting Contact Rotated Plane") {
|
||||||
|
@ -100,14 +101,17 @@ TEST_CASE ("AABB vs Plane", "[Collision]") {
|
||||||
REQUIRE((cinfo.posA - Vector3d(0, -0.4, -0.4)).norm() < 1.0e-12);
|
REQUIRE((cinfo.posA - Vector3d(0, -0.4, -0.4)).norm() < 1.0e-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("RotatedBox Touching Plane") {
|
SECTION("Rotated Unit Box Touching Plane") {
|
||||||
box.orientation = Quaternion::fromAxisAngle(Vector3d (1.0, 0.0, 0.0), M_PI * 0.25);
|
box.orientation = Quaternion::fromAxisAngle(Vector3d (1.0, 0.0, 0.0), M_PI * 0.25);
|
||||||
plane.pos.set(0., -sqrt(2.) * 0.5, -sqrt(2.) * 0.5);
|
plane.pos.set(0., -sqrt(2.) * 0.5, -sqrt(2.) * 0.5);
|
||||||
plane.orientation = Quaternion(0., 0., 0., 1.);
|
plane.orientation = Quaternion(0., 0., 0., 1.);
|
||||||
cresult = CheckPenetrationBoxVsPlane(box, plane, cinfo);
|
cresult = CheckPenetrationBoxVsPlane(box, plane, cinfo);
|
||||||
|
|
||||||
REQUIRE(cresult == true);
|
REQUIRE(cresult == true);
|
||||||
// REQUIRE((cinfo.posA - Vector3d(0, -0.4, -0.4)).norm() < 1.0e-12);
|
REQUIRE(fabs(cinfo.depth) <= cCollisionEps);
|
||||||
|
REQUIRE((cinfo.posA - Vector3d(0, -sqrt(2.) * 0.5, 0.)).norm() < 1.0e-12);
|
||||||
|
REQUIRE((cinfo.posB - Vector3d(0, -sqrt(2.) * 0.5, 0.)).norm() < 1.0e-12);
|
||||||
|
REQUIRE((cinfo.dir - Vector3d(0, -1., 0.)).norm() < 1.0e-12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue