2014-12-27 64 views
1

我目前正在寫一個路徑追蹤器。現在我想要實現光線 - 三角形的交集。所以我的三角形由三個點組成(v0,v1,v2)。我看了關於這個主題的其他帖子(Raytracing - 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 

注意,得到交點與下飛機後在三角形的功能點被調用,它應該返回一個布爾值。我有我的方法是從:使用第二重心coordiantes http://www.blackpawn.com/texts/pointinpoly/,它看起來像你正在做這部分類似

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-test更改爲if (a == 0.0f)來刪除該測試。

此外,在第四行Vector3D e1e2 = e1.cross(e2).normalize();,您正在計算不需要的三角形平面的法向量。