Optimized collision detection

This commit is contained in:
Matthias Schiffer 2010-01-04 21:34:56 +01:00
parent 9d152e2773
commit 648ce1d454

View file

@ -64,18 +64,31 @@ bool Collision::testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmm
if(rootSq < 0) if(rootSq < 0)
return false; return false;
float root = std::sqrt(rootSq); float minRoot = -a - b_2;
float maxRoot = a*MathUtil::EPSILON - b_2;
*distance = -(b_2 + root)/a; if(minRoot < 0)
minRoot = 0;
float edgeFact = edge.dot(m + move*(*distance) - v1); if(maxRoot < 0)
if(edgeFact < 0 || edgeFact > edge.squared_length())
return false; return false;
if(*distance > -MathUtil::EPSILON && *distance < 1) if(rootSq < minRoot*minRoot || rootSq >= maxRoot*maxRoot)
return true;
else
return false; return false;
minRoot = a*(edge.dot(m - v1) - edge.squared_length())/edge.dot(move) - b_2;
maxRoot = a*edge.dot(m - v1)/edge.dot(move) - b_2;
if(minRoot < 0)
minRoot = 0;
if(maxRoot < 0)
return false;
if(rootSq < minRoot*minRoot || rootSq > maxRoot*maxRoot)
return false;
*distance = -(b_2 + std::sqrt(rootSq))/a;
return true;
} }
bool Collision::testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { bool Collision::testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) {
@ -87,24 +100,33 @@ bool Collision::testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r,
if(rootSq < 0) if(rootSq < 0)
return false; return false;
float root = std::sqrt(rootSq); float minRoot = -a - b_2;
float maxRoot = a*MathUtil::EPSILON - b_2;
*distance = -(b_2 + root)/a; if(minRoot < 0)
minRoot = 0;
if(*distance > -MathUtil::EPSILON && *distance < 1) if(maxRoot < 0)
return true;
else
return false; return false;
if(rootSq <= minRoot*minRoot || rootSq >= maxRoot*maxRoot)
return false;
*distance = -(b_2 + std::sqrt(rootSq))/a;
return true;
} }
bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) {
if(move.squared_length() == 0)
return false;
float d; float d;
if(test(t, MathUtil::Ray(m - r*t.computeNormal(), move), &d) && d > -MathUtil::EPSILON) { if(test(t, MathUtil::Ray(m - r*t.computeNormal(), move), &d) && d > -MathUtil::EPSILON) {
if(distance)
*distance = d;
if(d < 1) { if(d < 1) {
if(distance)
*distance = d;
return true; return true;
} }
else { else {