Added corner collision

This commit is contained in:
Matthias Schiffer 2010-01-03 19:52:54 +01:00
parent c85a39bb0f
commit 853d3978c5
2 changed files with 51 additions and 9 deletions

View file

@ -84,16 +84,16 @@ bool Collision::testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmm
vmml::vec3f cvec = v1 + vmml::dot(edge, m-v1)*edge / edge.squared_length() - m; vmml::vec3f cvec = v1 + vmml::dot(edge, m-v1)*edge / edge.squared_length() - m;
float a = avec.squared_length(); float a = avec.squared_length();
float b = vmml::dot(avec, cvec); float b_2 = vmml::dot(avec, cvec);
float c = cvec.squared_length() - r*r; float c = cvec.squared_length() - r*r;
float rootSq = b*b - a*c; float rootSq = b_2*b_2 - a*c;
if(rootSq < 0) if(rootSq < 0)
return false; return false;
float root = std::sqrt(rootSq); float root = std::sqrt(rootSq);
*distance = -(b + root)/a; *distance = -(b_2 + root)/a;
float edgeFact = edge.dot(m + move*(*distance) - v1); float edgeFact = edge.dot(m + move*(*distance) - v1);
if(edgeFact < 0 || edgeFact > edge.squared_length()) if(edgeFact < 0 || edgeFact > edge.squared_length())
@ -105,6 +105,25 @@ bool Collision::testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmm
return false; return false;
} }
bool Collision::testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) {
float a = move.squared_length();
float b_2 = vmml::dot(m-v, move);
float c = (m-v).squared_length() - r*r;
float rootSq = b_2*b_2 - a*c;
if(rootSq < 0)
return false;
float root = std::sqrt(rootSq);
*distance = -(b_2 + root)/a;
if(*distance > -MathUtil::EPSILON && *distance < 1)
return true;
else
return false;
}
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) {
float d; float d;
@ -120,20 +139,42 @@ bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmm
} }
} }
float minEdgeDistance = std::numeric_limits<float>::infinity(); bool collision = false;
float minDistance;
for(int i = 0; i < 3; ++i) { for(int i = 0; i < 3; ++i) {
if(testEdge(t.getVertex(i), t.getVertex((i+1)%3), m, r, move, &d)) { if(testEdge(t.getVertex(i), t.getVertex((i+1)%3), m, r, move, &d)) {
if(d < minEdgeDistance) { if(!collision || d < minDistance) {
minEdgeDistance = d; minDistance = d;
} }
} }
} }
if(collision) {
if(distance) if(distance)
*distance = minEdgeDistance; *distance = minDistance;
return (minEdgeDistance < 1); return true;
}
collision = false;
for(int i = 0; i < 3; ++i) {
if(testVertex(t.getVertex(i), m, r, move, &d)) {
if(!collision || d < minDistance) {
minDistance = d;
}
}
}
if(collision) {
if(distance)
*distance = minDistance;
return true;
}
else {
return false;
}
} }
} }

View file

@ -33,6 +33,7 @@ class Collision {
Collision(); Collision();
static bool testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance); static bool testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance);
static bool testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance);
static vmml::vec3f projectToEdge(const vmml::vec3f& p, const vmml::vec3f& v1, const vmml::vec3f& v2); static vmml::vec3f projectToEdge(const vmml::vec3f& p, const vmml::vec3f& v1, const vmml::vec3f& v2);
static vmml::vec3f projectToNearestEdge(const vmml::vec3f& p, const Triangle &t); static vmml::vec3f projectToNearestEdge(const vmml::vec3f& p, const Triangle &t);