我有一个对象,它面向特定方向,(例如)45 度视野和极限视野范围。我已经完成了所有初始检查(四叉树节点和距离),但现在我需要检查特定对象是否在该视锥内(在这种情况下,如果我们能看到它,则决定只跟随该对象)。
除了从Direction - (FieldOfView / 2)
to的每个角度投射一条光线Direction + (FieldOfView / 2)
(我现在正在这样做,这太可怕了),进行这种可见性检查的最佳方法是什么?
我有一个对象,它面向特定方向,(例如)45 度视野和极限视野范围。我已经完成了所有初始检查(四叉树节点和距离),但现在我需要检查特定对象是否在该视锥内(在这种情况下,如果我们能看到它,则决定只跟随该对象)。
除了从Direction - (FieldOfView / 2)
to的每个角度投射一条光线Direction + (FieldOfView / 2)
(我现在正在这样做,这太可怕了),进行这种可见性检查的最佳方法是什么?
我在视频游戏行业工作过,我可以说每帧都做像 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(Θ)
计算您的视图方向(理解为向量)与从您开始到对象结束的向量之间的角度。如果它属于 FieldOfView/2,您可以查看该对象。
那个角度是:
arccos(scalarProduct(viewDirection, (object - you)) / (norm(viewDirection)*norm(object - you))).
获取查看器的航向矢量与查看器到目标的矢量之间的角度。如果该角度小于 (FieldOfView/2),则目标位于观察者的视野中。
如果您的向量是 2d 或 3d,这将以相同的方式工作。(在 3D 中,如果您有一个视锥体而不是圆锥体,那么您需要将角度分成两个分量。)您只需要找到两个向量之间的角度。
如果要测试大于单个点的目标,则每个目标都需要多个点,例如边界框的角。如果从观察者到任何这些点的矢量在视野内给出了一个角度,那么框的那个角是可见的。
如果您正在做 3D 并且可以将查看范围定义为视锥体,那么您可以使用类似于这种视锥体剔除技术的东西。
已经有了很好的答案,但我只是想给你一个 Wolfire 博客的链接,他们最近开始了一个代数系列,以“视野”方程为例。去读吧,它写得很好,很容易。