我有一个物体,它面向一个特定的方向(例如)45度视野和极限视野范围。我已完成所有初始检查(四叉树节点和距离),但现在我需要检查特定对象是否在该视锥内(在这种情况下,如果我们可以看到它,则决定仅跟随该对象)。
除了为Direction - (FieldOfView / 2)
到Direction + (FieldOfView / 2)
的每个学位投射一条光线(我现在正在这样做而且很可怕),进行这种可见性检查的最佳方法是什么?
答案 0 :(得分:10)
我曾经在视频游戏行业工作,我可以说每帧都像arccos这样的触发功能并不理想。相反,您预先计算锥体角度的余弦值:
float cos_angle = cos(PI/4); // 45 degrees, for example
然后,通过将该点与锥体的点积相比较,您可以快速检查每个帧是否落入该锥体内。
vector test_point_vector = normalize(test_point_loc - cone_origin);
float dot_product = dot(normalized_cone_vector, text_point_vector);
bool inside_code = dot_product > cos_angle;
没有触发功能,只有一些乘法,除法和加法。大多数游戏引擎都有一个优化的矢量normalize()函数。
这是因为这个等式:
A · B = |A| * |B| * cos(Θ)
如果对矢量进行归一化(A - > An),则简化等式:
An · Bn = cos(Θ)
答案 1 :(得分:9)
计算视图方向(理解为矢量)与从您开始并在对象处结束的矢量之间的角度。如果它属于FieldOfView / 2,则可以查看该对象。
这个角度是:
arccos(scalarProduct(viewDirection, (object - you)) / (norm(viewDirection)*norm(object - you))).
答案 2 :(得分:3)
获取观察者的标题向量与从观察者到目标的向量之间的角度。如果该角度小于(FieldOfView / 2),则目标位于查看者的视野中。
如果你的向量是2d或3d,这将以相同的方式工作。 (在3D中,如果你有视锥体而不是锥体,那么你需要将角度分成两个部分。)你只需要找到两个矢量之间的角度。
如果要测试大于单个点的目标,则每个目标需要多个点,例如边界框的角。如果从观察者到任何这些点的矢量在视野内给出一个角度,那么该框的那个角是可见的。
答案 3 :(得分:2)
如果你正在做3D并且可以将视角范围定义为平截头体,那么你可以使用类似于Frustrum Culling技术的东西。
答案 4 :(得分:1)
已经有了很好的答案,但我只想给你一个Wolfire博客的链接,他们最近开始了一个以“视野”方程为例的代数系列。 Go read it,写得好而且容易。