我的射线三角交点代码是不是正确?

Posted

技术标签:

【中文标题】我的射线三角交点代码是不是正确?【英文标题】:Is my Ray-Triangle Intersection code correct?我的射线三角交点代码是否正确? 【发布时间】:2020-01-25 19:19:39 【问题描述】:

我在这里问是否有人可以检查我的 Ray-Triangle 交叉代码是否正确,或者我是否有一些错误,因为它似乎没有按预期工作。

Vector3f:

struct Vector3f

    Vector3f(): x(0), y(0), z(0)  
    Vector3f(GLfloat a, GLfloat b, GLfloat c): x(a), y(b), z(c)  

    GLfloat x, y, z;
;

交叉产品和内部产品:

Vector3f CMath::CrossProduct(Vector3f a, Vector3f b)

    Vector3f result;

    result.x = (a.y * b.z) - (a.z * b.y);
    result.y = (a.z * b.x) - (a.x * b.z);
    result.z = (a.x * b.y) - (a.y * b.x);

    return result;

GLfloat CMath::InnerProduct(Vector3f a, Vector3f b)

    return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);

Ray-Triangle 相交检查:

bool CMath::RayIntersectsTriangle(Vector3f p, Vector3f d, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f &hitLocation)

    Vector3f e1, e2, h, s, q;
    GLfloat a, f, u, v, t;

    e1.x = v1.x - v0.x;
    e1.y = v1.y - v0.y;
    e1.z = v1.z - v0.z;

    e2.x = v2.x - v0.x;
    e2.y = v2.y - v0.y;
    e2.z = v2.z - v0.z;

    h = CrossProduct(d,e2);
    a = InnerProduct(e1,h);
    if(a > -0.00001 && a < 0.00001)
        return false;

    f = 1 / a;
    s.x = p.x - v0.x;
    s.y = p.y - v0.y;
    s.z = p.z - v0.z;
    u = f * InnerProduct(s,h);
    if(u < 0.0 || u > 1.0)
        return false;

    q = CrossProduct(s,e1);
    v = f * InnerProduct(d,q);
    if(v < 0.0 || u + v > 1.0)
        return false;

    t = f * InnerProduct(e2,d);
    if(t > 0.00001)
    
        hitLocation.x = p.x + t * d.x;
        hitLocation.y = p.y + t * d.y;
        hitLocation.z = p.z + t * d.z;

        return true;
    
    else
        return false;

只需检查这些函数是否有任何问题,以了解我的问题是否出在其他地方。 提前感谢您的帮助。

【问题讨论】:

您是否考虑过使用一些预定义的向量(测试数据)和预期的结果编写一些(自动)测试来检查此功能? 我试过了,但我认为问题出在这些函数或我的代码上。不过,感谢您的评论,将尝试使用空白项目来确保它。我以前使用过这些相同的功能,它们工作得很好,但不记得我是否在大约 2 年前改变了它们。 【参考方案1】:

首先我建议将InnerProduct 重命名为DotProduct(参见Dot product)。

您有一个由 3 个点 v0v1v2 定义的平面和一个由一个点 p 和一个方向 d 定义的射线。 在伪代码中,平面与射线的交点为:

n = cross(v1-v0, v2-v0)        // normal vector of the plane
t = dot(v0 - p, n) / dot(d, n) // t scale d to the distance along d between p and the plane 
hitLocation = p + d * t

另见Intersect a ray with a triangle in GLSL C++

当您将其应用于您的代码时,这意味着

Vector3f n = CrossProduct(e1, e2);

注意,由于sp - v0(而不是v0 - p),因此必须反转光线方向的比例:

t = - InnerProduct(s, n) / InnerProduct(d, n)

【讨论】:

谢谢,我不知道 GLSL 内置了这些功能。还没有真正进入着色器。我会更多地研究 GLSL,也感谢您的解释

以上是关于我的射线三角交点代码是不是正确?的主要内容,如果未能解决你的问题,请参考以下文章

平面/射线交点与点/平面投影的差异

光线投射算法(如何计算一个坐标点是不是在一个多边形内)

以编程方式查找射线和平面的交点?

射线箱相交理论

三角形求交算法

用射线法实现判断点是否在多边形内部