如何检查一个游戏对象是否可以看到另一个游戏对象?

时间:2022-11-23 07:29:45

I have an object, that is facing a particular direction with (for instance) a 45 degree field of view, and a limit view range. I have done all the initial checks (Quadtree node, and distance), but now I need to check if a particular object is within that view cone, (In this case to decide only to follow that object if we can see it).

我有一个物体,面向特定方向(例如)45度视野和极限视野范围。我已经完成了所有初始检查(四叉树节点和距离),但现在我需要检查特定对象是否在该视锥内(在这种情况下,如果我们可以看到它,则决定只跟随该对象)。

Apart from casting a ray for each degree from Direction - (FieldOfView / 2) to Direction + (FieldOfView / 2) (I am doing that at the moment and it is horrible), what is the best way to do this visibility check?

除了从Direction - (FieldOfView / 2)到Direction +(FieldOfView / 2)每个度数投射一条光线(我现在这样做并且它很可怕),进行这种可见性检查的最佳方法是什么?

5 个解决方案

#1


9  

Compute the angle between your view direction (understood as a vector) and the vector that starts at you and ends at the object. If it falls under FieldOfView/2, you can view the object.

计算视图方向(理解为矢量)与从您开始并在对象处结束的矢量之间的角度。如果它属于FieldOfView / 2,则可以查看该对象。

That angle is:

那个角度是:

arccos(scalarProduct(viewDirection, (object - you)) / (norm(viewDirection)*norm(object - you))).

#2


10  

I've worked in the video game industry, and I can say that doing trig functions like arccos every frame is less than ideal. Instead, you precompute the cosine of the angle for the cone:

我曾经在视频游戏行业工作,我可以说每帧都像arccos这样的触发功能并不理想。相反,您预先计算锥体角度的余弦:

float cos_angle = cos(PI/4); // 45 degrees, for example

Then, each frame you can quickly check if a point falls inside that cone by comparing that with the dot product of the cone and the .

然后,通过将点与锥体的点积进行比较,您可以快速检查每个帧是否落入锥体内部。

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;

There are no trig functions, just some multiplication, division, and addition. Most game engines have an optimized normalize() function for vectors.

没有触发功能,只有一些乘法,除法和加法。大多数游戏引擎都具有针对向量的优化的normalize()函数。

This works because of this equation:

这是因为这个等式:

A · B = |A| * |B| * cos(Θ)

If you normalize the vectors (A -> An), the equation is simplified:

如果对矢量进行归一化(A - > An),则简化等式:

An · Bn = cos(Θ)

#3


3  

Get the angle between the viewer's heading vector and the vector from viewer to target. If that angle is less than (FieldOfView/2), then the target is in the viewer's field of view.

获取查看者的标题向量与从查看者到目标的向量之间的角度。如果该角度小于(FieldOfView / 2),则目标位于查看器的视野中。

If your vectors are 2d or 3d this will work the same way. (In 3D, if you have a view frustum instead of cone, then you'll need to separate the angles into two components.) You just need to find the angle between the two vectors.

如果你的向量是2d或3d,这将以相同的方式工作。 (在3D中,如果你有视锥体而不是锥体,那么你需要将角度分成两个部分。)你只需要找到两个矢量之间的角度。

If you want to test targets which are larger than a single point, you'll need multiple points for each target, such as the corners of a bounding box. If the vector from viewer to any of these points gives an angle inside the field of view, then that corner of the box is visible.

如果要测试大于单个点的目标,则每个目标需要多个点,例如边界框的角。如果从观察者到任何这些点的矢量在视野内给出一个角度,那么该框的那个角是可见的。

#4


2  

If you're doing 3D and can define the viewing range as a frustrum, then you can use something similar to this Frustrum Culling technique.

如果你正在做3D并且可以将观看范围定义为截头体,那么你可以使用类似于这种Frustrum Culling技术的东西。

#5


1  

Good answers already but I just wanted to give you a link to the Wolfire blog, they recently started a algebra series that take the "field of view" equation as one example. Go read it, its well written and easy.

已经很好的答案,但我只想给你一个Wolfire博客的链接,他们最近开始了一个以“视野”方程为例的代数系列。去读它,写得好而且容易。

#1


9  

Compute the angle between your view direction (understood as a vector) and the vector that starts at you and ends at the object. If it falls under FieldOfView/2, you can view the object.

计算视图方向(理解为矢量)与从您开始并在对象处结束的矢量之间的角度。如果它属于FieldOfView / 2,则可以查看该对象。

That angle is:

那个角度是:

arccos(scalarProduct(viewDirection, (object - you)) / (norm(viewDirection)*norm(object - you))).

#2


10  

I've worked in the video game industry, and I can say that doing trig functions like arccos every frame is less than ideal. Instead, you precompute the cosine of the angle for the cone:

我曾经在视频游戏行业工作,我可以说每帧都像arccos这样的触发功能并不理想。相反,您预先计算锥体角度的余弦:

float cos_angle = cos(PI/4); // 45 degrees, for example

Then, each frame you can quickly check if a point falls inside that cone by comparing that with the dot product of the cone and the .

然后,通过将点与锥体的点积进行比较,您可以快速检查每个帧是否落入锥体内部。

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;

There are no trig functions, just some multiplication, division, and addition. Most game engines have an optimized normalize() function for vectors.

没有触发功能,只有一些乘法,除法和加法。大多数游戏引擎都具有针对向量的优化的normalize()函数。

This works because of this equation:

这是因为这个等式:

A · B = |A| * |B| * cos(Θ)

If you normalize the vectors (A -> An), the equation is simplified:

如果对矢量进行归一化(A - > An),则简化等式:

An · Bn = cos(Θ)

#3


3  

Get the angle between the viewer's heading vector and the vector from viewer to target. If that angle is less than (FieldOfView/2), then the target is in the viewer's field of view.

获取查看者的标题向量与从查看者到目标的向量之间的角度。如果该角度小于(FieldOfView / 2),则目标位于查看器的视野中。

If your vectors are 2d or 3d this will work the same way. (In 3D, if you have a view frustum instead of cone, then you'll need to separate the angles into two components.) You just need to find the angle between the two vectors.

如果你的向量是2d或3d,这将以相同的方式工作。 (在3D中,如果你有视锥体而不是锥体,那么你需要将角度分成两个部分。)你只需要找到两个矢量之间的角度。

If you want to test targets which are larger than a single point, you'll need multiple points for each target, such as the corners of a bounding box. If the vector from viewer to any of these points gives an angle inside the field of view, then that corner of the box is visible.

如果要测试大于单个点的目标,则每个目标需要多个点,例如边界框的角。如果从观察者到任何这些点的矢量在视野内给出一个角度,那么该框的那个角是可见的。

#4


2  

If you're doing 3D and can define the viewing range as a frustrum, then you can use something similar to this Frustrum Culling technique.

如果你正在做3D并且可以将观看范围定义为截头体,那么你可以使用类似于这种Frustrum Culling技术的东西。

#5


1  

Good answers already but I just wanted to give you a link to the Wolfire blog, they recently started a algebra series that take the "field of view" equation as one example. Go read it, its well written and easy.

已经很好的答案,但我只想给你一个Wolfire博客的链接,他们最近开始了一个以“视野”方程为例的代数系列。去读它,写得好而且容易。