2008-10-15 4 views
9

У меня есть объект, который сталкивается с определенным направлением (например) с 45-градусным полем зрения и диапазоном пределов. Я выполнил все начальные проверки (узел Quadtree и расстояние), но теперь мне нужно проверить, находится ли какой-либо конкретный объект внутри этого конуса представления (в этом случае решать только следовать за этим объектом, если мы можем его увидеть).Как проверить, может ли один игровой объект видеть другой?

Помимо литья лучей для каждой степени от Direction - (FieldOfView/2) до Direction + (FieldOfView/2) (я делаю это в данный момент, и это ужасно), что является лучшим способом сделать эту проверку видимости?

ответ

9

Вычислить угол между вашим направлением просмотра (понимаемым как вектор) и вектором, который начинается с вас и заканчивается на объекте. Если он попадает под FieldOfView/2, вы можете просмотреть объект.

Этот угла:

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

Спасибо, именно то, что я искал. Я думаю, что это, вероятно, самый простой способ добиться этого, основываясь на том, что у меня уже есть. – AshtonKJ 2008-10-15 05:42:27

2

Если вы делаете 3D и можете определить диапазон просмотра как усеченные, то вы можете использовать что-то подобное этому Frustrum Culling техники.

3

Получить угол между вектором заголовка зрителя и вектором от зрителя до цели. Если этот угол меньше (FieldOfView/2), то цель находится в поле зрения зрителя.

Если ваши векторы 2d или 3d, это будет работать одинаково. (В 3D, если у вас есть усечение вместо конуса, тогда вам нужно разделить углы на два компонента.) Вам просто нужно найти угол между двумя векторами.

Если вы хотите проверить цели, превышающие одну точку, вам понадобятся несколько точек для каждой цели, например, углы ограничивающей рамки. Если вектор из зрителя в любую из этих точек дает угол внутри поля зрения, то этот угол окна виден.

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(Θ) 

Если нормировать векторы (А -> Ап), то уравнение упрощается:

An · Bn = cos(Θ) 
+0

Спасибо за это. Мне нравится идея ограничить количество триггерных функций на кадр. Я обязательно посмотрю, как это сделать (к сожалению, только после того, как экзамены закончены). – AshtonKJ 2008-11-03 05:21:48

1

Хорошие ответы уже, но я просто хотел дают вам ссылку на блог Wolfira, они недавно начали серию алгебр, в качестве одного из которых принято уравнение «поля зрения». Go read it, его хорошо написано и легко.