Является ли мой код пересечения Луч-Треугольник правильным? - PullRequest
1 голос
/ 25 января 2020

Я спрашиваю здесь, может ли кто-нибудь проверить, правильный ли мой код пересечения Луч-Треугольник, или у меня есть какая-то ошибка в нем, поскольку он, кажется, не работает должным образом.

Vector3f:

struct Vector3f
{
    Vector3f(): x(0), y(0), z(0) { }
    Vector3f(GLfloat a, GLfloat b, GLfloat c): x(a), y(b), z(c) { }

    GLfloat x, y, z;
};

CrossProduct & InnerProduct:

Vector3f CMath::CrossProduct(Vector3f a, Vector3f b)
{
    Vector3f result;

    result.x = (a.y * b.z) - (a.z * b.y);
    result.y = (a.z * b.x) - (a.x * b.z);
    result.z = (a.x * b.y) - (a.y * b.x);

    return result;
}
GLfloat CMath::InnerProduct(Vector3f a, Vector3f b)
{
    return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
}

Проверка пересечения треугольника и луча:

bool CMath::RayIntersectsTriangle(Vector3f p, Vector3f d, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f &hitLocation)
{
    Vector3f e1, e2, h, s, q;
    GLfloat a, f, u, v, t;

    e1.x = v1.x - v0.x;
    e1.y = v1.y - v0.y;
    e1.z = v1.z - v0.z;

    e2.x = v2.x - v0.x;
    e2.y = v2.y - v0.y;
    e2.z = v2.z - v0.z;

    h = CrossProduct(d,e2);
    a = InnerProduct(e1,h);
    if(a > -0.00001 && a < 0.00001)
        return false;

    f = 1 / a;
    s.x = p.x - v0.x;
    s.y = p.y - v0.y;
    s.z = p.z - v0.z;
    u = f * InnerProduct(s,h);
    if(u < 0.0 || u > 1.0)
        return false;

    q = CrossProduct(s,e1);
    v = f * InnerProduct(d,q);
    if(v < 0.0 || u + v > 1.0)
        return false;

    t = f * InnerProduct(e2,d);
    if(t > 0.00001)
    {
        hitLocation.x = p.x + t * d.x;
        hitLocation.y = p.y + t * d.y;
        hitLocation.z = p.z + t * d.z;

        return true;
    }
    else
        return false;
}

Просто проверяйте, есть ли что-то не так с этими функциями, чтобы узнать, лежит ли моя проблема где-нибудь еще. Заранее спасибо за помощь.

1 Ответ

0 голосов
/ 26 января 2020

Прежде всего, я рекомендую переименовать InnerProduct в DotProduct (см. Точечный продукт ).

У вас есть плоскость, определяемая 3 точками v0, v1 и v2 и луч, определенный точкой p и направлением d.
В псевдокоде точка пересечения плана и луча:

n = cross(v1-v0, v2-v0)        // normal vector of the plane
t = dot(v0 - p, n) / dot(d, n) // t scale d to the distance along d between p and the plane 
hitLocation = p + d * t

См. также Пересечь луч с треугольником в GLSL C ++

Когда вы применяете это к своему коду, это означает

Vector3f n = CrossProduct(e1, e2);

Примечание, поскольку s равно p - v0 ( вместо v0 - p), шкала для направления луча должна быть инвертирована:

t = - InnerProduct(s, n) / InnerProduct(d, n)
...