2015-07-02 2 views
0

Я хотел бы получить точку пересечения треугольника, когда луч проходит через него. Я следовал онлайновому учебнику и выполнял функцию, но я не мог получить правильные координаты точки пересечения.Как получить точку пересечения? Ray Triangle Intersection C++

Например, я должен получить точку пересечения (0, 3, -1), если я использую начало луча (0, 2, -1), направление луча (0, 1, 0), треугольные вершины p0 (0, 3, 0), p1 (-0,5, 3, -1), p2 (0,5, 3, -1). Однако у меня есть точка пересечения (0, 7, -1), что неверно.

Я ценю ваше время и помощь. :-)

float kEpsilon = 0.000001; 

V3f crossProduct(V3f point1, V3f point2){ 

    V3f vector; 

    vector.x = point1.y * point2.z - point2.y * point1.z; 
    vector.y = point2.x * point1.z - point1.x * point2.z; 
    vector.z = point1.x * point2.y - point1.y * point2.x; 

    return vector; 
} 

float dotProduct(V3f dot1, V3f dot2){ 

    float dot = dot1.x * dot2.x + dot1.y * dot2.y + dot1.z * dot2.z; 

    return dot; 
} 

//orig: ray origin, dir: ray direction, Triangle vertices: p0, p1, p2. 
bool rayTriangleIntersect(V3f orig, V3f dir, V3f p0, V3f p1, V3f p2){ 

// compute plane's normal 

    V3f p0p1, p0p2; 

    p0p1.x = p1.x - p0.x; 
    p0p1.y = p1.y - p0.y; 
    p0p1.z = p1.z - p0.z; 

    p0p2.x = p2.x - p0.x; 
    p0p2.y = p2.y - p0.y; 
    p0p2.z = p2.z - p0.z; 

    // no need to normalize 
    V3f N = crossProduct(p0p1, p0p2); // N 

    // Step 1: finding P 

    // check if ray and plane are parallel ? 
    float NdotRayDirection = dotProduct(N, dir); // if the result is 0, the function will return the value false (no intersection). 

    if (fabs(NdotRayDirection) < kEpsilon){ // almost 0 

     return false; // they are parallel so they don't intersect ! 
    } 

    // compute d parameter using equation 2 
    float d = dotProduct(N, p0); 

    // compute t (equation P=O+tR P intersection point ray origin O and its direction R) 

    float t = (dotProduct(N, orig) + d)/NdotRayDirection; 

    // check if the triangle is in behind the ray 
    //if (t < 0){ return false; } // the triangle is behind 

    // compute the intersection point using equation 
    V3f P; 

    //this part should do the work, but it does not work. 
    P.x = orig.x + t * dir.x; 
    P.y = orig.y + t * dir.y; 
    P.z = orig.z + t * dir.z; 


    // Step 2: inside-outside test 
    V3f C; // vector perpendicular to triangle's plane 

    // edge 0 
    V3f edge0; 

    edge0.x = p1.x - p0.x; 
    edge0.y = p1.y - p0.y; 
    edge0.z = p1.z - p0.z; 

    V3f vp0; 

    vp0.x = P.x - p0.x; 
    vp0.y = P.y - p0.y; 
    vp0.z = P.z - p0.z; 

    C = crossProduct(edge0, vp0); 

    if (dotProduct(N, C) < 0) { return false; }// P is on the right side 

    // edge 1 
    V3f edge1; 

    edge1.x = p2.x - p1.x; 
    edge1.y = p2.y - p1.y; 
    edge1.z = p2.z - p1.z; 

    V3f vp1; 

    vp1.x = P.x - p1.x; 
    vp1.y = P.y - p1.y; 
    vp1.z = P.z - p1.z; 

    C = crossProduct(edge1, vp1); 

    if (dotProduct(N, C) < 0) { return false; } // P is on the right side 

    // edge 2 
    V3f edge2; 

    edge2.x = p0.x - p2.x;  
    edge2.y = p0.y - p2.y; 
    edge2.z = p0.z - p2.z; 

    V3f vp2; 

    vp2.x = P.x - p2.x; 
    vp2.y = P.y - p2.y; 
    vp2.z = P.z - p2.z; 

    C = crossProduct(edge2, vp2); 

    if (dotProduct(N, C) < 0) { return false; } // P is on the right side; 

    return true; // this ray hits the triangle 
} 

Благодарим за помощь.

+2

Если вы не хотите изобретать колесо, посмотрите на [Геометрические инструменты] (http://www.geometrictools.com/). – Angew

+1

, какой онлайн-учебник вы использовали? – user463035818

+0

Hi Angew and tobi303, Спасибо за ваши ответы. Angew, я очень новичок в компьютерной графике, и я не смог найти соответствующий код на этом веб-сайте. tobi303, это ссылка (http://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/ray-triangle-intersection-geometric-solution). Спасибо за помощь. – Ming

ответ

1

Вы получили t = 5 и получили (0,7, -1), но правильный номер для t равен 1, и причина в том, что у вас есть float t = (dotProduct(N, orig) + d)/NdotRayDirection;, а правильный код - float t = -((dotProduct(N, orig) - d)/NdotRayDirection);. Это позволит решить вашу проблему, надеюсь.

+0

Привет, удачи, Спасибо за ваш ответ. Я попробовал ваше предложение. Я использовал начало луча (0, 2, -1), направление луча (0, 1, 0), вершины треугольника p0 (0, 3, 0), p1 (-0,5, 3, -1), p2 (0,5, 3 , -1), но я получил 't = -1', а точка пересечения -' (0, 1, -1) ', что было неверно. У тебя есть идеи? Благодарю. :-) – Ming

+0

Привет, удачи, Спасибо за ваш ответ. Он работает сейчас, но я не совсем понимаю, почему мы используем это уравнение. Что случилось со старым? В онлайн-учебнике показано «float t = (точка (N, orig) + D)/dot (N, dir);' Не могли бы вы дать мне более подробную информацию о вашем ответе? Мне жаль, что я очень новичок в компьютерной графике. Благодарю. :-) – Ming

+1

Привет Минг, я не совсем уверен в учебнике, поскольку я его не читал ... Мое предположение заключается в том, что они рассматривают другой отрицательный коэффициент для добавления к точке .... Обычно то, что я дал вы один человек, включая меня ... Пожалуйста, примите ответ, если ваша проблема решена. –

Смежные вопросы