我目前正在编写一个路径跟踪器。现在我想实现射线 - 三角形交集。所以我的三角形由三个点(v0,v1,v2)组成。我查看了有关此主题的其他帖子(光线跟踪 - 射线/三角形交叉点)。可悲的是它无法正常工作,所以我想检查问题是否在交叉路口一侧。这是我的两个三角形函数:
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.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/使用第二个重心坐标,看起来您在这一部分中正在做类似的事情
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
不过,看起来您根本不是在检查射线平面相交,您是否在不同的功能中这样做?如果是这样的话,我认为你实际上不需要光线方向来进行三角形测试。
你实现的是著名的Möller-Trumbore交集算法。代码正确。如果您的代码未检测到某些情况,则可能是因为它检查了背面剔除。您可以通过将第一个 if 测试更改为 if (a == 0.0f)
来删除该测试。
此外,在第四行,Vector3D e1e2 = e1.cross(e2).normalize();
,您正在计算三角形平面的法向量,这是不必要的。