2014-12-27 2 views
1

В настоящее время я пишу трайтре. Теперь я хочу реализовать пересечение лучей треугольника. Таким образом, мой треугольник состоит из трех точек (v0, v1, v2). Я смотрел другие сообщения по этой теме (Raytracing - Ray/Triangle Intersection). К сожалению, он работает неправильно, поэтому я хочу проверить, есть ли проблема на стороне пересечения. Вот мои две функции треугольника:Pathtracing Ray Triangle Intersection

public float intersect(Ray ray){ 
    Vector3D e1 = v1.sub(v0); 
    Vector3D e2 = v2.sub(v0); 
    Vector3D e1e2 = e1.cross(e2).normalize(); 

    Vector3D p = ray.direction.cross(e2); 

    float a = e1.dot(p); 
    if(a < 0.0) 
     return -1.0f; 

    float f = 1.0f/a; 
    Vector3D s = ray.origin.sub(v0); 
    float u = f*(s.dot(p)); 
    if(u < 0.0 || u > 1.0) 
     return -1.0f; //no hit 

    Vector3D q = s.cross(e1); 
    float v = f * (ray.direction.dot(q)); 
    if(v < 0.0 || v > 1.0) 
     return -1.0f; //no hit 

    float t = f * (e2.dot(q)); //distance 
    return t; 
} 

public Vector3D normal(Vector3D nVec){ 
    Vector3D e1 = v1.sub(v0); 
    Vector3D e2 = v2.sub(v0); 
    Vector3D e1e2 = e1.cross(e2).normalize(); 
    return e1e2; 
} 

Так выглядит этот код правильно?

ответ

1

Я честно считаю, что ваш код довольно трудно читать, потому что вы не используете очень описательные имена. Я собираюсь дать вам то, что я сделал в псевдокоде:

//1.Find intersection point of the ray and the infinite Plane created by triangle, 
//or find if the ray is parralel to the plane (no intersection Point) 
//2.Find out if the intersection point is within the triangle itself 

Triangle: Vector A, Vector B, Vector C 
ray: Vector rayOrig, Vector rayDir 
Intersection: boolean hasHit = false, Vector hitPoint, float t 

Vector normal = (B-A)CrossProduct(C-A) //I think you had basically the same with e1e2 
float d = (normal)DotProduct(A) 
float nd = (normal)DotProduct(rayDir) 
if(nd!=0) 
{ //The ray hits the triangles plane 
    Intersection.t=(d- (normal).DotProduct(rayOrig))/nd 
    Intersection.hitPoint=rayOrig+(rayDir*Intersection.t) 
    if (pointInTriangle(Intersection.hitPoint, A, B, C)) 
    { 
     Intersection.hasHit = true 
    } 
} 
return Intersection 

Обратите внимание, что после получения точки пересечения с плоскостью точка функции в треугольнике называется, который должен возвращать логическое значение. Я получил свой метод, что из: http://www.blackpawn.com/texts/pointinpoly/ с использованием вторых барицентрических coordiantes, похоже, что вы делаете что-то подобное в этой части

if(u < 0.0 || u > 1.0) 
    return -1.0f; //no hit 

Vector3D q = s.cross(e1); 
float v = f * (ray.direction.dot(q)); 
if(v < 0.0 || v > 1.0) 
    return -1.0f; //no hit 

Он не смотрит как вы проверяете для луча плоскости пересечения вообще, хотя, вы делая это в другой функции? Если это так, я не думаю, что вам действительно нужно направление лучей для теста треугольника.

1

Что вы реализовали - это известный алгоритм пересечения Möller-Trumbore. Код правильный. Если ваш код не обнаруживает некоторые из них, это может быть связано с тем, что он проверяет обратную обработку. Вы можете удалить этот тест, изменив первый if-тест на if (a == 0.0f).

Также, на четвертой строке, Vector3D e1e2 = e1.cross(e2).normalize();, вы вычисляете нормальный вектор плоскости треугольника, который не нужен.