I'm developing a game engine for a university project and I can't get the collision detection system to work. I've found this paper that explains an algorithm for triangle-triangle collision detection created by Chaman-Leopoldj, but somehow I can't implement it. I know it is a bit long but the algorithm can be found at pages 8 and 22-24
here is the code I wrote:
this is the wrapper function
bool Octree::triangleTriangleIntersection(glm::vec3 A, glm::vec3 B, glm::vec3 C, glm::vec3 P, glm::vec3 Q, glm::vec3 R) {
glm::vec3 U = B - A;
glm::vec3 V = C - A;
glm::vec3 S = Q - P;
glm::vec3 T = R - P;
glm::vec3 AP = P - A;
float sigma = dot(U * V, U * V);
glm::vec3 alpha = (S * (U * V)) / sigma;
glm::vec3 beta = (T * (U * V)) / sigma;
glm::vec3 gamma = (AP * (U * V)) / sigma;
float alphau = dot(alpha, U);
float alphav = dot(alpha, V);
float alphauv = dot(alpha, U - V);
float gammau = dot(gamma, U);
float gammav = dot(gamma, V);
float gammauv = dot(gamma, U - V);
float betau = dot(beta, U);
float betav = dot(beta, V);
float betauv = dot(beta, U - V);
float Xm, XM, Sm = 0, SM = 1;
float Ym, YM, Tm = 0, TM = 1;
if (findSolution_x(-gammau, alphau, betau, 1 - gammau, -1 - gammav, alphav, betav, -gammav, Xm, XM)) {
if (Xm > Sm) Sm = Xm;
if (XM < SM) SM = XM;
}
else {
return false;
}
if (findSolution_x(-gammau, alphau, betau, 1 - gammau, -gammauv, alphauv, betauv, 1 - gammauv, Xm, XM)) {
if (Xm > Sm) Sm = Xm;
if (XM < SM) SM = XM;
}
else {
return false;
}
if (findSolution_x(-1 - gammav, alphav, betav, -gammav, -gammauv, alphauv, betauv, 1 - gammauv, Xm, XM)) {
if (Xm > Sm) Sm = Xm;
if (XM < SM) SM = XM;
}
else {
return false;
}
if (Sm > SM)
return false;
else {
float delta = (SM - Sm) / 20;
for (float s = Sm; s <= SM; s += delta) {
if (findSolution_y(-gammau, alphau, betau, 1 - gammau, -1 - gammav, alphav, betav, -gammav, s, Ym, YM)) {
if (Ym > Tm) Tm = Ym;
if (YM < TM) TM = YM;
}
else {
return false;
}
if (findSolution_y(-gammau, alphau, betau, 1 - gammau, -gammauv, alphauv, betauv, 1 - gammauv, s, Ym, YM)) {
if (Ym > Tm) Tm = Ym;
if (YM < TM) TM = YM;
}
else {
return false;
}
if (findSolution_y(-1 - gammav, alphav, betav, -gammav, -gammauv, alphauv, betauv, 1 - gammauv, s, Ym, YM)) {
if (Ym > Tm) Tm = Ym;
if (YM < TM) TM = YM;
}
else {
return false;
}
if (Tm > TM)
return false;
else
return true;
}
}
return false;}
solve_x
bool Octree::findSolution_x(float m, float a, float b, float n, float M, float A, float B, float N, float& Xm, float& XM) {
const float epsilon = 0.00001;
float denom = (a*B- A* b);
float Sm1, SM1;
Sm1 = (m* B- N* b);
SM1 = (n* B- M* b);
if (b< 0 || B< 0) {
Sm1 *= -1;
SM1 *= -1;
}
Sm1 /= denom;
SM1 /= denom;
float Sm1Rounded = round(Sm1);
float SM1Rounded = round(SM1);
if (abs(Sm1Rounded - Sm1 <= epsilon)) Sm1 = Sm1Rounded;
if (abs(SM1Rounded - SM1 <= epsilon)) SM1 = SM1Rounded;
Xm = Sm1;
XM = SM1;
if (denom == 0) {
Xm *= -1;
}
return true;}
solve_y
bool Octree::findSolution_y(float m, float a, float b, float n, float M, float A, float B, float N, float x, float& Ym, float& YM) {
const float epsilon = 0.00001;
float Sm1, SM1, Sm2, SM2;
Sm1 = m- (a* x);
Sm2 = M- (A* x);
SM1 = n- (a* x);
SM2 = N- (A* x);
if (b< 0 || B< 0) {
Sm1 *= -1;
SM1 *= -1;
Sm2 *= -1;
SM2 *= -1;
}
if (Sm1 > SM1 || Sm2 > SM2) return false;
Sm1 /= b;
SM1 /= b;
Sm2 /= B;
SM2 /= B;
float Sm1Rounded = round(Sm1);
float SM1Rounded = round(SM1);
float Sm2Rounded = round(Sm2);
float SM2Rounded = round(SM2);
if (abs(Sm1Rounded - Sm1 <= epsilon)) Sm1 = Sm1Rounded;
if (abs(SM1Rounded - SM1 <= epsilon)) SM1 = SM1Rounded;
if (abs(Sm2Rounded - Sm2 <= epsilon)) Sm2 = Sm2Rounded;
if (abs(SM2Rounded - SM2 <= epsilon)) SM2 = SM2Rounded;
if (param2 > 0 && param6 > 0) {
Sm1 >= Sm2 ? Ym = Sm1 : Ym = Sm2;
SM1 >= SM2 ? YM = SM2 : YM = SM1;
}
else if (param2 > 0) {
Ym = Sm1;
YM = SM1;
}
else if (param6 > 0) {
Ym = Sm2;
YM = SM2;
}
return true;}
I suspect I've put wrong conditions in one of my ifs but I just followed the guide lines of the paper so I really don't know. Hope you guys can help me.
EDIT: the epsilon is needed to round values below certain error. this is a problem deriving from assimp not reading values of OBJs properly, turning a 1.000000 into 1.0000045 for example.