Проблема с разделением теоремы оси C

#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. Мой плохой. Спасибо за отзыв.