【问题标题】:Pathtracing Ray Triangle Intersection路径追踪射线三角交点
【发布时间】:2019-04-12 04:35:50
【问题描述】:

我目前正在编写一个路径跟踪器。现在我想实现射线 - 三角形相交。所以我的三角形由三个点 (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;
}

那么这段代码正确吗?

【问题讨论】:

    标签: graphics geometry raytracing


    【解决方案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/ 使用第二个重心坐标,看起来你在这部分做了类似的事情

    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
    

    看起来你根本没有检查射线平面的交点,你是在不同的函数中做的吗?如果是这种情况,我认为您实际上不需要射线方向进行三角形测试。

    【讨论】:

      【解决方案2】:

      您实现的是著名的Möller-Trumbore 交集算法。代码是正确的。如果您的代码没有检测到这一点,可能是因为它检查了背面剔除。您可以通过将第一个 if-test 更改为 if (a == 0.0f) 来删除该测试。

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

      【讨论】:

        猜你喜欢
        • 2015-05-05
        • 1970-01-01
        • 1970-01-01
        • 2015-03-25
        • 1970-01-01
        • 2021-07-24
        • 2012-10-21
        • 2019-12-01
        相关资源
        最近更新 更多