Algorithm 找到光线和多边形之间交点的最快方法是什么?

Algorithm 找到光线和多边形之间交点的最快方法是什么?,algorithm,polygon,raytracing,Algorithm,Polygon,Raytracing,正如问题所问。答案最好是伪代码和参考。正确答案应该重视速度而不是简单性。请参阅。您可以找到三角化多边形的方法 如果您真的需要光线/多边形相交,它位于16.9 of(第二版为13.8) 我们首先计算交点 在光线和[平面]之间 polygon]饼图,这很容易做到 通过用射线替换x n_p点(o+td)+d_p=0t=(-d_p-n_p点o)/(n_p点d) 如果分母|n|p点d |0) bool prev_point_over=(点积(测试_轴,测试_point)>0) 向前推这一点 把这一点放在

正如问题所问。答案最好是伪代码和参考。正确答案应该重视速度而不是简单性。

请参阅。您可以找到三角化多边形的方法

如果您真的需要光线/多边形相交,它位于16.9 of(第二版为13.8)

我们首先计算交点 在光线和[平面]之间 polygon]
饼图
,这很容易做到 通过用射线替换
x

n_p点(o+td)+d_p=0t=(-d_p-n_p点o)/(n_p点d)
如果分母
|n|p点d |
,其中
epsilon
非常小 编号,则考虑光线 平行于多边形平面且没有 发生交叉。否则 射线和射线的交点,
p
计算多边形平面:
p=o+td
。此后,问题 决定
p
是否在 多边形从三个减少到两个 尺寸


有关更多详细信息,请参阅本书。

整本书的章节都专门讨论了这一特殊要求-这里描述合适的算法太长了。我建议阅读计算机图形学方面的任何参考著作,特别是:

  • 光线追踪导论,安德鲁·S·格拉斯纳主编,ISBN 0122861604
结构点
{
浮动x
浮子
浮动z
}
结构射线
{
R1点
R2点
}
结构多边形
{
点P[]
整数计数
}
浮点数积(点A、点B)
{
返回A.x*B.x+A.y*B.y+A.z*B.z
}
点叉积(点A、点B)
{
返回点(A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x)
}
点矢量子(点A、点B)
{
返回点(A.x-B.x,A.y-B.y,A.z-B.z)
}
点scalarMult(浮点a,点B)
{
返回点(a*B.x,a*B.y,a*B.z)
}
布尔findIntersection(光线、多边形多边形、点和答案)
{
点平面_法线=叉积(vectorSub(Poly.P[1],Poly.P[0]),vectorSub(Poly.P[2],Poly.P[0]))
浮点分母=点积(vectorSub(Ray.R2,Poly.P[0]),平面_法线)
如果(分母==0){return FALSE}//光线与多边形平行
浮点射线标量=点积(向量子(多边形P[0],射线R1),平面法向)
答案=矢量添加(Ray.R1,scalarMult(Ray_scalar,Ray.R2))
//确认该点位于多边形内
点测试线=矢量子(答案,多边形P[0])
点测试轴=叉积(平面、法线、测试线)
布尔点在内部=假
点测试_点=矢量子(多边形P[1],答案)
bool prev_point_ahead=(点积(测试线,测试点)>0)
bool prev_point_over=(点积(测试_轴,测试_point)>0)
向前推这一点
把这一点放在上面
int指数=2;
while(索引<多边形计数)
{
测试点=vectorSub(Poly.P[index],答案)
此点向前=(点积(测试线,测试点)>0)
如果(前一点或前一点)
{
上面的测试点=(点积(测试点轴,测试点)>0)
if(上一个点或上一个点)
{
点在里面=!点在里面
}
}
上一点前方=该点前方
上一点=上一点
索引++
}
返回点在内部
}

(PlaneDirection是垂直于平面的单位向量)

好书,我写了我自己的光线跟踪器。我也是:)但它还不做多边形!这更像是一个一般性的参考问题,但确实,soft surfer拥有最新的算法。
 n_p DOT (o + td) + d_p = 0 <=> t = (-d_p - n_p DOT o) / (n_p DOT d)
struct point
{
    float x
    float y
    float z
}

struct ray
{
    point R1
    point R2
}

struct polygon
{
    point P[]
    int count
}

float dotProduct(point A, point B)
{
    return A.x*B.x + A.y*B.y + A.z*B.z
}

point crossProduct(point A, point B)
{
    return point(A.y*B.z-A.z*B.y, A.z*B.x-A.x*B.z, A.x*B.y-A.y*B.x)
}

point vectorSub(point A, point B)
{
    return point(A.x-B.x, A.y-B.y, A.z-B.z) 
}

point scalarMult(float a, Point B)
{
    return point(a*B.x, a*B.y, a*B.z)
}

bool findIntersection(ray Ray, polygon Poly, point& Answer)
{
    point plane_normal = crossProduct(vectorSub(Poly.P[1], Poly.P[0]), vectorSub(Poly.P[2], Poly.P[0]))

    float denominator = dotProduct(vectorSub(Ray.R2, Poly.P[0]), plane_normal)

    if (denominator == 0) { return FALSE } // ray is parallel to the polygon

    float ray_scalar = dotProduct(vectorSub(Poly.P[0], Ray.R1), plane_normal)

    Answer = vectorAdd(Ray.R1, scalarMult(ray_scalar, Ray.R2))

    // verify that the point falls inside the polygon

    point test_line = vectorSub(Answer, Poly.P[0])
    point test_axis = crossProduct(plane_normal, test_line)

    bool point_is_inside = FALSE

    point test_point = vectorSub(Poly.P[1], Answer)
    bool prev_point_ahead = (dotProduct(test_line, test_point) > 0)
    bool prev_point_above = (dotProduct(test_axis, test_point) > 0)

    bool this_point_ahead
    bool this_point_above

    int index = 2;
    while (index < Poly.count)
    {
        test_point = vectorSub(Poly.P[index], Answer)
        this_point_ahead = (dotProduct(test_line, test_point) > 0)

        if (prev_point_ahead OR this_point_ahead)
        {
            this_point_above = (dotProduct(test_axis, test_point) > 0)

            if (prev_point_above XOR this_point_above)
            {
                point_is_inside = !point_is_inside
            }
        }

        prev_point_ahead = this_point_ahead
        prev_point_above = this_point_above
        index++
    }

    return point_is_inside
}
function Collision(PlaneOrigin,PlaneDirection,RayOrigin,RayDirection)
    return RayOrigin-RayDirection*Dot(PlaneDirection,RayOrigin-PlaneOrigin)/Dot(PlaneDirection,RayDirection)
end