2015-04-29 108 views
1

我要实现的穆勒& Trumbore算法,通过解释雷(平面)三角形相交

http://geomalgorithms.com/a06-_intersect-2.html

到我的项目了openFrameworks。

这是我的功能看起来如何

bool ofApp::intersectRayTriangle(Ray ray, Triangle triangle, ofVec3f* intersect) { 

// u, v are triangle vectors - n is plane normal 
ofVec3f u, v, n; 

// ray vectors 
ofVec3f w0, w; 

// params to calc ray-plane intersect 
float r, a, b; 

u = triangle.v1 - triangle.v0; 
u.normalize(); 

v = triangle.v2 - triangle.v0; 
v.normalize(); 

n = u.cross(v); 
n.normalize(); 

if(n == ofVec3f(0.0f, 0.0f, 0.0f)) // triangle is degenerate 
    return false; 

w0 = ray.origin - triangle.v0; 

a = -dot(n, w0); 
b = dot(n, ray.direction); 

if(fabs(b) < SMALL_NUM) 
{ 
    if(a == 0.0f) 
     return false; // ray lies in triangle plane 
    else  
     return false; // ray disjoint from plane 
} 

r = a/b; 
if(r < 0.0f) 
    return false; // ray goes away from triangle 

// intersect is the intersection point with the ray and the plane 
*intersect = ray.origin + r * ray.direction; 

// UNTIL HERE ITS ONLY PLANE INTERSECTION 
//return true; 

// Is plane intersection point inside the triangle? 
float uu, uv, vv, wu, wv, D; 

uu = dot(u,u); 
uv = dot(u,v); 
vv = dot(v,v); 
w = *intersect - triangle.v0; 
w.normalize(); 
wu = dot(w,u); 
wv = dot(w,v); 
D = uv * uv - uu * vv; 

// get and test parametric coords 
float s, t; 
s = (uv * wv - vv * wu)/D; 
if (s < 0.0f || s > 1.0f)   // I is outside T 
    return false; 
t = (uv * wu - uu * wv)/D; 
if (t < 0.0f || (s + t) > 1.0f) // I is outside T 
    return false; 

return true;      // I is in T} 

第一部分检查的射线相交的三角给出的平面。第二部分检查交点是否在三角形内部以验证三角形交点。

我的问题是,与飞机,我得到这样

// intersect is the intersection point with the ray and the plane 
*intersect = ray.origin + r * ray.direction; 

交点已经是错了,在测试不同的平面相交的光线使我与平面相交正确的结果,如果我返回true权后...

我一直在想一个正常化(或不正常化)的错误,但我不知道它。

三角形的坐标为:

triangle.v0 = ofVec3f(100.0, 50.0, 0.0); 
triangle.v1 = ofVec3f(50.0, 150.0, 0.0); 
triangle.v2 = ofVec3f(150.0, 150.0, 0.0); 

和射线,这应该相交

rayHit.origin = ofVec3f (100, 100, -100); 
rayHit.direction = ofVec3f (1, 1, 1); 

和射线,其不应相交

rayNoHit.origin = ofVec3f (200, 100, -100); 
rayNoHit.direction = ofVec3f (1, 1, 1); 

而射线其甚至没有通过飞机验证我的功能相交飞机

rayNoPlaneHit.origin = ofVec3f(300, 100, -100); 
rayNoPlaneHit.direction = ofVec3f(1, 1, 0); 

我在这里看到关于光线投射三角形或平面许多不同的问题,但我真的觉得我得到它已经,只是缺少一点点的事情,这已经花费了我小时。

如果有人能帮助我,我会很开心。 谢谢,最好的问候

+0

可能是一个符号错误。该算法实现了定向交叉,以便只记录从前面撞击三角形的光线;那是你要的吗?此外,第一条射线将以(200,200,0)结束,所以它不会与三角形相交。 – cfh

+0

不熟悉算法,但是您不必对w0进行归一化处理吗? – starmole

回答

0

我可以看到两个错误:首先,你指定了顺时针顺序的三角形,所以它的法线将指向负z方向;与射线指向相同的方向,所以命中不会注册,因为代码检查方向。

其次,你的rayHit与z平面相交于(200, 200, 0),所以你假设它与三角相交是错误的。

+0

我应该改变三角形顺时针顺序,我怎么可以点它?无法得到为什么要改变这一点。非常感谢您的帮助! – vachee

+0

如果我现在逆时针指定三角形,如 'triangle.v0 = ofVec3f(100.0,50.0,0.0); \t triangle.v1 = ofVec3f(150.0,150.0,0.0); \t triangle.v2 = ofVec3f(50.0,150.0,0.0);' 我得到一个** ** FAIL导致与'rayHit'和** ** SUCCESS与导致'rayNoHit' ~~困惑 – vachee

0

谢谢cfh正确提示我的rayHit与z平面相交于(200,200,0)。我做错了,并且rayHit现在有正确的方向rayHit.direction = ofVec3f (0, 0, 1);

因此,我可以验证相交三角形平面现在的功能!

但我仍然算法返回结果,我(也修正)

rayNoHit.origin = ofVec3f (200, 100, -100); 
rayNoHit.direction = ofVec3f (0, 0, 1); 

也是在三角形内,我仍然有我无法验证点在三角形的右侧里面的问题办法。我在重心坐标解决方案中有错误还是错过算法下半部分的其他内容?