#c #algorithm #collision-detection #game-development #glm-math
#c #алгоритм #обнаружение столкновений #разработка игр #glm-математика
Вопрос:
Я пытаюсь выполнить разделяющую теорему оси для двух треугольников, чтобы проверить наличие столкновений между ними, однако это не работает.
Мой соответствующий код:
glm::vec3 CalcSurfaceNormal(glm::vec3 tri1, glm::vec3 tri2, glm::vec3 tri3)
{
//Get surface normal of a triangle
glm::vec3 u = tri2 - tri1;
glm::vec3 v = tri3 - tri1;
glm::vec3 nrmcross = glm::cross(u, v);
nrmcross = glm::normalize(nrmcross);
return nrmcross;
}
bool SATTriangleCheck(glm::vec3 axis, glm::vec3 tri1vert1, glm::vec3 tri1vert2, glm::vec3 tri1vert3, glm::vec3 tri2vert1, glm::vec3 tri2vert2, glm::vec3 tri2vert3)
{
//Dot each vertex with the axis and get the min and max
int t1v1 = glm::dot(axis, tri1vert1);
int t1v2 = glm::dot(axis, tri1vert2);
int t1v3 = glm::dot(axis, tri1vert3);
int t2v1 = glm::dot(axis, tri2vert1);
int t2v2 = glm::dot(axis, tri2vert2);
int t2v3 = glm::dot(axis, tri2vert3);
int t1min = glm::min(t1v1, glm::min(t1v2, t1v3));
int t1max = glm::min(t1v1, glm::min(t1v2, t1v3));
int t2min = glm::min(t2v1, glm::min(t2v2, t2v3));
int t2max = glm::min(t2v1, glm::min(t2v2, t2v3));
//Test for overlaps
if ((t1min < t2max amp;amp; t1min > t2min) || (t1max < t2max amp;amp; t1max > t2min) || (t2min < t1max amp;amp; t2min > t1min) || (t2max < t1max amp;amp; t2max > t1min))
return true;
return false;
}
bool CollisionHelper::isTriangleIntersectingTriangle(glm::vec3 tri1, glm::vec3 tri2, glm::vec3 tri3, glm::vec3 otherTri1, glm::vec3 otherTri2, glm::vec3 otherTri3)
{
//Triangle surface normals, 2 axes to test
glm::vec3 tri1FaceNrml = CalcSurfaceNormal(tri1, tri2, tri3);
glm::vec3 tri2FaceNrml = CalcSurfaceNormal(otherTri1, otherTri2, otherTri3);
//Calculate edges
glm::vec3 tri1Edge1 = tri2 - tri1;
glm::vec3 tri1Edge2 = tri3 - tri1;
glm::vec3 tri1Edge3 = tri3 - tri2;
glm::vec3 tri2Edge1 = otherTri2 - otherTri1;
glm::vec3 tri2Edge2 = otherTri3 - otherTri1;
glm::vec3 tri2Edge3 = otherTri3 - otherTri2;
//Calculate all axes
glm::vec3 axis1 = tri1FaceNrml;
glm::vec3 axis2 = tri2FaceNrml;
glm::vec3 axis3 = glm::normalize(glm::cross(tri1Edge1, tri2Edge1));
glm::vec3 axis4 = glm::normalize(glm::cross(tri1Edge1, tri2Edge2));
glm::vec3 axis5 = glm::normalize(glm::cross(tri1Edge1, tri2Edge3));
glm::vec3 axis6 = glm::normalize(glm::cross(tri1Edge2, tri2Edge1));
glm::vec3 axis7 = glm::normalize(glm::cross(tri1Edge2, tri2Edge2));
glm::vec3 axis8 = glm::normalize(glm::cross(tri1Edge2, tri2Edge3));
glm::vec3 axis9 = glm::normalize(glm::cross(tri1Edge3, tri2Edge1));
glm::vec3 axis10 = glm::normalize(glm::cross(tri1Edge3, tri2Edge2));
glm::vec3 axis11 = glm::normalize(glm::cross(tri1Edge3, tri2Edge3));
//Perform SAT
if (SATTriangleCheck(axis1, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis2, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis3, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis4, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis5, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis6, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis7, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis8, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis9, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis10, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
if (SATTriangleCheck(axis11, tri1, tri2, tri3, otherTri1, otherTri2, otherTri3)) return true;
return false;
}
Код, который вызывает и проверяет эти функции, находится в основном игровом цикле каждый кадр, который проходит в координатах x, y и z обоих треугольников:
if (CollisionHelper::isTriangleIntersectingTriangle(glm::vec3(tri11.x, tri11.y, tri11.z), glm::vec3(tri22.x, tri22.y, tri22.z), glm::vec3(tri33.x, tri33.y, tri33.z), glm::vec3(othertri11.x, othertri11.y, othertri11.z), glm::vec3(othertri22.x, othertri22.y, othertri22.z), glm::vec3(othertri33.x, othertri33.y, othertri33.z)))
{
std::cout << "Triangle intersectionn";
}
Я никогда ничего не печатаю на консоли. Один из треугольников повернут на 90 градусов от другого
Комментарии:
1.
int t2v1 = glm::dot(axis, tri2vert2);
кажется подозрительным. Вы имели в видуint t2v1 = glm::dot(axis, tri2vert1)
здесь?2. Спасибо, что поймали это, я исправил это, и это все еще не работает.
3. Кроме того, чтобы предотвратить опечатки, я бы подумал об использовании обозначения массива для ваших веток и циклов для их обработки. Сокращает ошибки вырезания и вставки.
4. Пожалуйста, не редактируйте вещи, когда вы их исправляете. Либо сделайте ответ, либо добавьте комментарий в оригинал, чтобы комментарии имели смысл для других пользователей, которые могут захотеть помочь.
5. Мой плохой. Спасибо за отзыв.