Algorithm 找到光线和多边形之间交点的最快方法是什么?
正如问题所问。答案最好是伪代码和参考。正确答案应该重视速度而不是简单性。请参阅。您可以找到三角化多边形的方法 如果您真的需要光线/多边形相交,它位于16.9 of(第二版为13.8) 我们首先计算交点 在光线和[平面]之间 polygon]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) 向前推这一点 把这一点放在
饼图
,这很容易做到
通过用射线替换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