Hi all,
Trying to implement SAT in my code to detect collisions (binary yes/no is fine for the moment - no requirement to get the actual contact point). However I'm having an issue that the objects seem to intersect a small amount before the collision is detected.
Below is my code, and attached is a screenshot and I would very much appreciate it if someone could point me in the right direction. I must be doing something silly somewhere as it seems so close.
I'm implementing SAT as described here: http://www.dyn4j.org/2010/01/sat/
I'm aware that the code is quite messy and obviously not optimised (that's for a later stage )
const std::vector<Vector>& vertices1 = entity1RigidBody->GetCollisionVertices();
const std::vector<Vector>& faces1 = entity1RigidBody->GetCollisionFaces();
const std::vector<Vector>& normals1 = entity1RigidBody->GetCollisionFaceNormals();
const std::vector<Vector>& vertices2 = entity2RigidBody->GetCollisionVertices();
const std::vector<Vector>& faces2 = entity2RigidBody->GetCollisionFaces();
const std::vector<Vector>& normals2 = entity2RigidBody->GetCollisionFaceNormals();
glm::mat4 entity1TransformMatrix = entity1Transform->GetTransform().GetMatrix();
glm::mat4 entity2TransformMatrix = entity2Transform->GetTransform().GetMatrix();
if(vertices1.size() == 0 || faces1.size() == 0 || normals1.size() == 0) {
return false;
}
if(vertices2.size() == 0 || faces2.size() == 0 || normals2.size() == 0) {
return false;
}
std::vector<Vector> axes;
for(unsigned int i = 0; i < normals1.size(); i++) {
glm::vec4 vector(normals1[i].x, normals1[i].y, normals1[i].z, 0.0f);
vector = vector * entity1TransformMatrix; // Transform the vertices
Vector axis(vector.x, vector.y, vector.z);
axes.push_back(axis);
}
for(unsigned int i = 0; i < normals2.size(); i++) {
glm::vec4 vector(normals2[i].x, normals2[i].y, normals2[i].z, 0.0f);
vector = vector * entity2TransformMatrix; // Transform the vertices
Vector axis(vector.x, vector.y, vector.z);
axes.push_back(axis);
}
// We have all the axes from the Normals (this should probably only be computed once...)
// For each axis, lets get a projection from each vertex onto each axis (!!!!)
for(unsigned int a = 0; a < axes.size(); a++) {
double min1 = 0;
double max1 = 0;
double min2 = 0;
double max2 = 0;
Vector axis = axes[a];
for(unsigned int face = 0; face < faces1.size(); face++) {
Vector faceIndices = faces1[face];
Vector faceVertices[3];
faceVertices[0] = vertices1[faceIndices.x];
faceVertices[1] = vertices1[faceIndices.y];
faceVertices[2] = vertices1[faceIndices.z];
for(unsigned int vert = 0; vert < 3; vert++) {
Vector vertex = faceVertices[vert];
glm::vec4 v(vertex.x, vertex.y, vertex.z, 0.0f);
glm::vec4 transformedV = (v * entity1TransformMatrix); // Transform the vertices
vertex.x = transformedV.x;
vertex.y = transformedV.y;
vertex.z = transformedV.z;
double p = Vector::Dot(axis, vertex);
if(p < min1) {
min1 = p;
} else if (p > max1) {
max1 = 0;
}
}
}
for(unsigned int face = 0; face < faces2.size(); face++) {
Vector faceIndices = faces2[face];
Vector faceVertices[3];
faceVertices[0] = vertices2[faceIndices.x];
faceVertices[1] = vertices2[faceIndices.y];
faceVertices[2] = vertices2[faceIndices.z];
for(unsigned int vert = 0; vert < 3; vert++) {
Vector vertex = faceVertices[vert];
glm::vec4 v(vertex.x, vertex.y, vertex.z, 0.0f);
glm::vec4 transformedV = (v * entity2TransformMatrix); // Transform the vertices
vertex.x = transformedV.x;
vertex.y = transformedV.y;
vertex.z = transformedV.z;
double p = Vector::Dot(axis, vertex);
if(p < min2) {
min2 = p;
} else if (p > max1) {
max2 = 0;
}
}
}
// Check if they overlap
if(min1 < min2 && max1 < min2) {
// No Overlap
return false;
}
if(min1 > max2 && max1 > max2) {
// No Overlap
return false;
}
}
// We've reached this far - there must be a collision
return true;