【问题标题】:What is the fastest way to find the point of intersection between a ray and a polygon?找到射线和多边形之间交点的最快方法是什么?
【发布时间】:2010-09-23 15:54:41
【问题描述】:

与问题要求的差不多。最好用伪代码回答并引用。正确答案应该重视速度而不是简单。

【问题讨论】:

    标签: algorithm polygon raytracing


    【解决方案1】:

    Intersections of Rays, Segments, Planes and Triangles in 3D。您可以找到对多边形进行三角剖分的方法。

    如果您真的需要射线/多边形相交,它位于 Real-Time Rendering 的 16.9(第二版为 13.8)。

    我们首先计算交集 在射线和[平面的 ploygon]pie_p,这很容易做到 通过用射线替换x

     n_p DOT (o + td) + d_p = 0 <=> t = (-d_p - n_p DOT o) / (n_p DOT d)
    

    如果分母|n_p DOT d| &lt; epsilon,其中epsilon非常小 数,则考虑射线 平行于多边形平面并且没有 发生交叉。否则,该 射线的交点p 和 计算多边形平面:p = o + td。此后,问题 判断p 是否在 多边形从三个减少到两个 尺寸...

    请参阅本书了解更多详情。

    【讨论】:

    • 这更像是一个一般性的参考问题,但是 soft surfer 确实拥有最新的算法。
    【解决方案2】:
    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
    }

    【讨论】:

      【解决方案3】:

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

      • 光线追踪简介,编辑。安德鲁·S·格拉斯纳,ISBN 0122861604

      【讨论】:

      • 好书,我根据它编写了自己的光线追踪器。
      • 我也是 :) 不过它还没有做多边形!
      【解决方案4】:
      function Collision(PlaneOrigin,PlaneDirection,RayOrigin,RayDirection)
          return RayOrigin-RayDirection*Dot(PlaneDirection,RayOrigin-PlaneOrigin)/Dot(PlaneDirection,RayDirection)
      end
      

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

      【讨论】:

        猜你喜欢
        • 2010-09-10
        • 1970-01-01
        • 2014-08-24
        • 1970-01-01
        • 2021-11-12
        • 2011-09-26
        • 2016-03-07
        • 2019-12-07
        • 2015-09-21
        相关资源
        最近更新 更多