Hey guys,
Iv been trying to get some SAT collision working but I cant seem to get it working.
I have been following this guys (http://www.jkh.me/files/tutorials/Separating%20Axis%20Theorem%20for%20Oriented%20Bounding%20Boxes.pdf) to try and convert the maths to code. ATM I'm just trying to get the code working with the long drawn out version (as you will see) as I have a much better understanding of doing it that way and I just want it working for now.
The code I have is as follows
bool OBB::collisontest(OBB *B)
{
glm::mat3 Brotation = B->returnrotation();
glm::vec3 Bhalf = B->returnlenghts();
glm::vec3 Bcenter = B->returncenter();
glm::vec3 T = Bcenter - centerpos;
float Aside;
float bside;
float projection;
for (int i = 0; i < 3; i++)
{
projection = glm::dot(T, rotation[i]);
Aside = glm::dot(halfwaylenghts[0] * rotation[0], rotation[i]) + glm::dot(halfwaylenghts[1] * rotation[1], rotation[i]) + glm::dot(halfwaylenghts[2] * rotation[2], rotation[i]);
bside = glm::dot(Bhalf[0] * Brotation[0], rotation[i]) + glm::dot(Bhalf[1] * Brotation[1], rotation[i]) + glm::dot(Bhalf[2] * Brotation[2], rotation[i]);
if (projection > Aside + bside)
{
return false;
}
}
for (int i = 0; i < 3; i++)
{
projection = glm::dot(T, Brotation[i]);
Aside = glm::dot(halfwaylenghts[0] * rotation[0], rotation[i]) + glm::dot(halfwaylenghts[1] * rotation[1], rotation[i]) + glm::dot(halfwaylenghts[2] * rotation[2], rotation[i]);
bside = glm::dot(Bhalf[0] * Brotation[0], rotation[i]) + glm::dot(Bhalf[1] * Brotation[1], rotation[i]) + glm::dot(Bhalf[2] * Brotation[2], rotation[i]);
if (projection > Aside + bside)
{
return false;
}
}
glm::vec3 crossaxis = glm::cross(rotation[0], Brotation[0]);
projection = glm::dot(T, glm::cross(rotation[0],Brotation[0]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
crossaxis = glm::cross(rotation[0], Brotation[1]);
projection = glm::dot(T, glm::cross(rotation[0], Brotation[1]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
crossaxis = glm::cross(rotation[0], Brotation[2]);
projection = glm::dot(T, glm::cross(rotation[0], Brotation[2]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
crossaxis = glm::cross(rotation[1], Brotation[0]);
projection = glm::dot(T, glm::cross(rotation[1], Brotation[0]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
crossaxis = glm::cross(rotation[1], Brotation[1]);
projection = glm::dot(T, glm::cross(rotation[1], Brotation[1]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
crossaxis = glm::cross(rotation[1], Brotation[2]);
projection = glm::dot(T, glm::cross(rotation[1], Brotation[2]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
crossaxis = glm::cross(rotation[2], Brotation[0]);
projection = glm::dot(T, glm::cross(rotation[2], Brotation[0]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
crossaxis = glm::cross(rotation[2], Brotation[1]);
projection = glm::dot(T, glm::cross(rotation[2], Brotation[1]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
crossaxis = glm::cross(rotation[2], Brotation[2]);
projection = glm::dot(T, glm::cross(rotation[2], Brotation[2]));
Aside = glm::dot(halfwaylenghts[0] * rotation[0], crossaxis) + glm::dot(halfwaylenghts[1] * rotation[1], crossaxis) + glm::dot(halfwaylenghts[2] * rotation[2], crossaxis);
bside = glm::dot(Bhalf[0] * Brotation[0], crossaxis) + glm::dot(Bhalf[1] * Brotation[1], crossaxis) + glm::dot(Bhalf[2] * Brotation[2], crossaxis);
if (projection > Aside + bside)
{
return false;
}
return true;
}
Does anything look incorrect, from what I understand of it (projecting the vector between the 2 on a plane of an axis (made by the x,y,z rotation vectors or the cross between object A and B) and then projecting the closes parts of both object on that plane added together to see if they are bigger then the difference projected) I cant see anything wrong myself. Just for additional info, it is a crossproduct axis test that causes the test to fail if 2 are clearly on top of each other.
Here is how i create my OBB just incase that might be wrong
void OBB::obbsetup(std::vector<glm::vec3> vetrices)
{
glm::vec3 tempmin = glm::vec3(0.0f,0.0f,0.0f);
glm::vec3 tempmax = glm::vec3(0.0f,0.0f,0.0f);
for(int i = 0; i < vetrices.size(); i++)
{
if(vetrices[i].x < tempmin.x)
{
tempmin.x = vetrices[i].x;
}
if(vetrices[i].y < tempmin.y)
{
tempmin.y = vetrices[i].y;
}
if(vetrices[i].z < tempmin.z)
{
tempmin.z = vetrices[i].z;
}
if(vetrices[i].x > tempmax.x)
{
tempmax.x = vetrices[i].x;
}
if(vetrices[i].y > tempmax.y)
{
tempmax.y = vetrices[i].y;
}
if(vetrices[i].z > tempmax.z)
{
tempmax.z = vetrices[i].z;
}
}
center.x = (tempmax.x - fabs(tempmin.x)) / 2;
center.y = (tempmax.y - fabs(tempmin.y)) / 2;
center.z = (tempmax.z - fabs(tempmin.z)) / 2;
halfwaylenghts.x = tempmax.x - center.x;
halfwaylenghts.y = tempmax.y - center.y;
halfwaylenghts.z = tempmax.z - center.z;
}
and for updating
void OBB::update(glm::vec3 pos,glm::quat newqu)
{
centerpos = pos + center;
myquad = newqu;
rotation = glm::toMat3(myquad);
}
(am using the GLM library)
Thanks for the time :)