bugfix, cso gjk cast
This commit is contained in:
parent
ed068d8857
commit
8030c3458a
@ -881,11 +881,11 @@ bool b3GJKRayCast(b3GJKRayCastOutput* output,
|
||||
return false;
|
||||
}
|
||||
|
||||
b3Vec3 n = gjkOut.point2 - gjkOut.point1;
|
||||
n /= d;
|
||||
|
||||
if (d < radius + tolerance)
|
||||
{
|
||||
b3Vec3 n = gjkOut.point2 - gjkOut.point1;
|
||||
n /= d;
|
||||
|
||||
// Touch
|
||||
output->t = t;
|
||||
output->point = gjkOut.point1 + r1 * n;
|
||||
@ -920,6 +920,14 @@ bool b3GJKRayCast(b3GJKRayCastOutput* output,
|
||||
gjkOut = b3GJK(txf1, proxy1, txf2, proxy2, false, &cache);
|
||||
d = gjkOut.distance;
|
||||
|
||||
if (d == 0.0f)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
n = gjkOut.point2 - gjkOut.point1;
|
||||
n /= d;
|
||||
|
||||
if (d < radius + tolerance)
|
||||
{
|
||||
break;
|
||||
@ -934,12 +942,186 @@ bool b3GJKRayCast(b3GJKRayCastOutput* output,
|
||||
}
|
||||
}
|
||||
|
||||
b3Vec3 n = gjkOut.point2 - gjkOut.point1;
|
||||
n /= d;
|
||||
if (d > 0.0f)
|
||||
{
|
||||
n = gjkOut.point2 - gjkOut.point1;
|
||||
n /= d;
|
||||
}
|
||||
|
||||
output->t = t;
|
||||
output->point = gjkOut.point1 + r1 * n;
|
||||
output->normal = n;
|
||||
output->iterations = iter;
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Gino van der Bergen
|
||||
// "Smooth Mesh Contacts with GJK"
|
||||
// Game Physics Pearls 2010, page 99
|
||||
bool b3GJKShapeCast(b3GJKRayCastOutput* output,
|
||||
const b3Transform& xf1, const b3GJKProxy& proxy1,
|
||||
const b3Transform& xf2, const b3GJKProxy& proxy2, const b3Vec3& translation2)
|
||||
{
|
||||
float32 r1 = proxy1.radius;
|
||||
float32 r2 = proxy2.radius;
|
||||
float32 radius = r1 + r2;
|
||||
|
||||
b3Vec3 r = translation2;
|
||||
|
||||
float32 t = 0.0f;
|
||||
b3Vec3 n = b3Vec3_zero;
|
||||
|
||||
u32 index1 = proxy1.GetSupportIndex(b3MulT(xf1.rotation, -r));
|
||||
u32 index2 = proxy2.GetSupportIndex(b3MulT(xf2.rotation, r));
|
||||
b3Vec3 w1 = xf1 * proxy1.GetVertex(index1);
|
||||
b3Vec3 w2 = xf2 * proxy2.GetVertex(index2);
|
||||
b3Vec3 v = w1 - w2;
|
||||
|
||||
b3Simplex simplex;
|
||||
simplex.m_count = 0;
|
||||
|
||||
b3SimplexVertex* vertices = simplex.m_vertices;
|
||||
|
||||
u32 save1[4], save2[4];
|
||||
u32 saveCount = 0;
|
||||
|
||||
const u32 kMaxIters = 20;
|
||||
const float32 kTolerance = 10.0f * B3_EPSILON;
|
||||
|
||||
float32 maxTolerance = 1.0f;
|
||||
|
||||
u32 iter = 0;
|
||||
while (iter < kMaxIters && b3Abs(b3LengthSquared(v) - radius * radius) > kTolerance * maxTolerance)
|
||||
{
|
||||
// Support in direction -v
|
||||
index1 = proxy1.GetSupportIndex(b3MulT(xf1.rotation, -v));
|
||||
index2 = proxy2.GetSupportIndex(b3MulT(xf2.rotation, v));
|
||||
w1 = xf1 * proxy1.GetVertex(index1);
|
||||
w2 = xf2 * proxy2.GetVertex(index2);
|
||||
b3Vec3 p = w1 - w2;
|
||||
|
||||
// Support plane on boundary of CSO is (-v, p)
|
||||
// -v is normal at p
|
||||
float32 vp = b3Dot(v, p);
|
||||
float32 vr = b3Dot(v, r);
|
||||
|
||||
if (vp - radius > t * vr)
|
||||
{
|
||||
if (vr > 0.0f)
|
||||
{
|
||||
t = (vp - radius) / vr;
|
||||
|
||||
if (t > 1.0f)
|
||||
{
|
||||
output->iterations = iter;
|
||||
return false;
|
||||
}
|
||||
|
||||
n = -v;
|
||||
|
||||
// Flush the simplex
|
||||
simplex.m_count = 0;
|
||||
saveCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
output->iterations = iter;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy simplex so we can identify duplicates.
|
||||
saveCount = simplex.m_count;
|
||||
for (u32 i = 0; i < saveCount; ++i)
|
||||
{
|
||||
save1[i] = vertices[i].index1;
|
||||
save2[i] = vertices[i].index2;
|
||||
}
|
||||
|
||||
// Unite p - s to simplex
|
||||
b3Vec3 s = t * r;
|
||||
|
||||
b3SimplexVertex* vertex = vertices + simplex.m_count;
|
||||
vertex->index1 = index1;
|
||||
vertex->point1 = w1;
|
||||
vertex->index2 = index2;
|
||||
vertex->point2 = w2;
|
||||
vertex->point = p - s;
|
||||
|
||||
// If we found a duplicate support point we must exit to avoid cycling.
|
||||
bool duplicate = false;
|
||||
for (u32 i = 0; i < saveCount; ++i)
|
||||
{
|
||||
if (vertex->index1 == save1[i] && vertex->index2 == save2[i])
|
||||
{
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (duplicate)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++simplex.m_count;
|
||||
|
||||
// Compute tolerance
|
||||
maxTolerance = -B3_EPSILON;
|
||||
for (u32 i = 0; i < simplex.m_count; ++i)
|
||||
{
|
||||
maxTolerance = b3Max(maxTolerance, b3LengthSquared(vertices[i].point));
|
||||
}
|
||||
|
||||
// Sub-solve
|
||||
const b3Vec3 origin = b3Vec3_zero;
|
||||
|
||||
switch (simplex.m_count)
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
simplex.Solve2(origin);
|
||||
break;
|
||||
case 3:
|
||||
simplex.Solve3(origin);
|
||||
break;
|
||||
case 4:
|
||||
simplex.Solve4(origin);
|
||||
break;
|
||||
default:
|
||||
B3_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (simplex.m_count == 4)
|
||||
{
|
||||
// Overlap
|
||||
output->iterations = iter;
|
||||
return false;
|
||||
}
|
||||
|
||||
v = simplex.GetClosestPoint();
|
||||
|
||||
++iter;
|
||||
}
|
||||
|
||||
// Prepare output.
|
||||
b3Vec3 point1, point2;
|
||||
simplex.GetClosestPoints(&point1, &point2);
|
||||
|
||||
if (b3LengthSquared(v) > B3_EPSILON * B3_EPSILON)
|
||||
{
|
||||
n = -v;
|
||||
}
|
||||
|
||||
n.Normalize();
|
||||
|
||||
output->t = t;
|
||||
output->point = point1 + r1 * n;
|
||||
output->normal = n;
|
||||
output->iterations = iter;
|
||||
return true;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user