如何找到射线和三角形的交点?

时间:2018-08-11 08:05:29

标签: c# intersection point

我通过重心坐标找到了交点坐标的三线性坐标。重心坐标正确(看似正确)。

<form action='newspeciescheck.py' method='post' enctype="multipart/form-data">
  • rayOrigin-射线的开始。
  • vert0,vert1,vert2-坐标 三角形的。

我使用此单元测试来检查:

    private const double Epsilon = 0.000001d;

    public static Vector3? GetPointIntersectionRayAndTriangle(Vector3 rayOrigin, Vector3 rayDirection, Vector3 vert0, Vector3 vert1, Vector3 vert2)
    {
        Vector3 edge1 = new Vector3();
        Vector3 edge2 = new Vector3();

        Vector3 tvec = new Vector3();
        Vector3 pvec = new Vector3();
        Vector3 qvec = new Vector3();

        double det, invDet;

        edge1 = vert1 - vert0;
        edge2 = vert2 - vert0;

        pvec = Cross(rayDirection, edge2);

        det = Dot(edge1, pvec);

        if (det > -Epsilon && det < Epsilon)
        {
            return null;
        }

        invDet = 1d / det;

        tvec = rayOrigin - vert0;

        double t, u, v;

        u = Dot(tvec, pvec) * invDet;

        if (u < 0 || u > 1)
        {
            return null;
        }

        qvec = Cross(tvec, edge1);

        v = Dot(rayDirection, qvec) * invDet;

        if (v < 0 || u + v > 1)
        {
            return null;
        }

        t = Dot(edge2, qvec) * invDet;

        return GetTrilinearCoordinates(t, u, v, vert0, vert1, vert2);
    }

    private static double Dot(Vector3 v1, Vector3 v2)
    {
        return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
    }

    private static Vector3 Cross(Vector3 v1, Vector3 v2)
    {
        Vector3 dest;

        dest.X = v1.Y * v2.Z - v1.Z * v2.Y;
        dest.Y = v1.Z * v2.X - v1.X * v2.Z;
        dest.Z = v1.X * v2.Y - v1.Y * v2.X;

        return dest;
    }

    private static Vector3 GetTrilinearCoordinates(double t, double u, double v, Vector3 vert0, Vector3 vert1, Vector3 vert2)
    {
        float a = (vert0 - vert1).Length();
        float b = (vert1 - vert2).Length();
        float c = (vert2 - vert0).Length();

        return new Vector3((float)t / a, (float)u / b, (float)v / c);
    }

还有其他方法可以找到射线与三角形的交点吗?最好没有重心坐标。

2 个答案:

答案 0 :(得分:1)

t不是重心坐标,而是从原点到交叉点的距离,因此不应传递给GetTrilinearCoordinates。相反,您应该传递1 - u - v,因为Moller-Trumbore返回归一化的重心坐标。

答案 1 :(得分:0)

这是用于找到射线撞击三角形的点的工作代码。如果光束没有碰到三角形,GetTimeAndUvCoord返回null

函数GetTimeAndUvCoord查找T和UV。 GetTrilinearCoordinateOfTheHit函数返回XYZ。

    private const double Epsilon = 0.000001d;

    public static Vector3? GetTimeAndUvCoord(Vector3 rayOrigin, Vector3 rayDirection, Vector3 vert0, Vector3 vert1, Vector3 vert2)
    {
        var edge1 = vert1 - vert0;
        var edge2 = vert2 - vert0;

        var pvec = Cross(rayDirection, edge2);

        var det = Dot(edge1, pvec);

        if (det > -Epsilon && det < Epsilon)
        {
            return null;
        }

        var invDet = 1d / det;

        var tvec = rayOrigin - vert0;

        var u = Dot(tvec, pvec) * invDet;

        if (u < 0 || u > 1)
        {
            return null;
        }

        var qvec = Cross(tvec, edge1);

        var v = Dot(rayDirection, qvec) * invDet;

        if (v < 0 || u + v > 1)
        {
            return null;
        }

        var t = Dot(edge2, qvec) * invDet;

        return new Vector3((float)t, (float)u, (float)v);
    }

    private static double Dot(Vector3 v1, Vector3 v2)
    {
        return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
    }

    private static Vector3 Cross(Vector3 v1, Vector3 v2)
    {
        Vector3 dest;

        dest.X = v1.Y * v2.Z - v1.Z * v2.Y;
        dest.Y = v1.Z * v2.X - v1.X * v2.Z;
        dest.Z = v1.X * v2.Y - v1.Y * v2.X;

        return dest;
    }

    public static Vector3 GetTrilinearCoordinateOfTheHit(float t, Vector3 rayOrigin, Vector3 rayDirection)
    {
        return rayDirection * t + rayOrigin;
    }