i have few question about implementing EPA in 2d.
in pseudocode:
For Each X Of P
construct_entry(X);
But what about case when origin is lying on line (simplex size = 2, W[0], W[1] )? We have ||e.V|| = 0,
and dot(V,W) - V become infinity.
How to blow up line into triangle case?
my base code for epa
Code: Select all
void GJK( Convex& A, Convex& B )
{
//...
// find W,P,Q.
}
bool closest_is_internal( const entry& e )
{
return e.s > 0 && e.t > 0;
}
entry construct_entry( const mt::vec3f& A, const mt::vec3f & B, const mt::vec3f & p0, const mt::vec3f & q0, const mt::vec3f & p1, const mt::vec3f & q1 )
{
entry e;
e.y0 = A;
e.y1 = B;
e.p0 = p0;
e.p1 = p1;
e.q0 = q0;
e.q1 = q1;
mt::vec3f ab = B - A;
float t = mt::dot_v3_v3(-A, ab) / ( mt::dot_v3_v3(ab, ab) );
if ( t < 0.0f )
{
t = 0.0f;
}
if ( t > 1.0f )
{
t = 1.0f;
}
e.s = 1-t;
e.t = t;
e.v = A + t * ab;
e.key = e.v.length();
return e;
}
mt::vec3f epa( Convex& A, Convex& B )
{
Qheap.clear();
if( size == 2) // simplex size = 2, line
{
// ???
}
for( int i = 0; i < size; i++ )
{
int next_i = (i+1) % size;
entry e = construct_entry(W[i],W[next_i],P[i],Q[i],P[next_i],Q[next_i]);
if (closest_is_internal(e))
{
Qheap.push_back( e );
}
}
bool close_enough = false;
int iteration = 0;
entry e;
do
{
e = Qheap.best();
Qheap.pop_best();
mt::vec3f v = e.v;
mt::vec3f P = A.support( v );
mt::vec3f Q = B.support( -v );
mt::vec3f w = P - Q;
float vl = v.length();
if(fabs(vl) <= eps)
{
// v == 0 ???
}
float dot = dot_v3_v3(v,w) / vl;
close_enough = (dot - vl) <= fabs(eps);
if(close_enough == false)
{
entry e1 = construct_entry(e.y0, w, e.p0, e.q0, P, Q );
if (closest_is_internal(e1))
{
Qheap.push_back( e1 );
}
entry e2 = construct_entry(e.y1, w, e.p1, e.q1, P, Q );
if (closest_is_internal(e2))
{
Qheap.push_back( e2 );
}
}
iteration++;
}
while(close_enough == false);
ClosestPoints[0] = e.s * e.p0 + e.t * e.p1;
ClosestPoints[1] = e.s * e.q0 + e.t * e.q1;
return e.v;
}