2008-10-15 20 views
9

Mam obiekt, który jest skierowany w określonym kierunku z (na przykład) polem widzenia 45 stopni i ograniczonym zasięgiem widzenia. Zrobiłem wszystkie początkowe sprawdzenia (węzeł Quadtree i odległość), ale teraz muszę sprawdzić, czy dany obiekt znajduje się w tym stożku widoku (w tym przypadku zdecydować się tylko na podążanie za tym obiektem, jeśli możemy go zobaczyć).Jak mogę sprawdzić, czy jeden obiekt gry może zobaczyć inny?

Oprócz rzucania promienia dla każdego stopnia od Direction - (FieldOfView/2) do Direction + (FieldOfView/2) (robię to w tej chwili i to jest okropne), jaki jest najlepszy sposób na sprawdzenie widoczności?

Odpowiedz

9

Oblicz kąt między kierunkiem widoku (rozumianym jako wektor) a wektorem rozpoczynającym się od Ciebie i kończącym na obiekcie. Jeśli znajduje się w polu FieldOfView/2, możesz wyświetlić obiekt.

Ten kąt jest:

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

Dzięki, dokładnie to, czego szukałem. Myślę, że jest to prawdopodobnie najprostszy sposób osiągnięcia tego na podstawie tego, co już mam. – AshtonKJ

2

Jeśli robisz 3D i może określić zakres widzenia jako frustrum, a następnie można użyć coś podobnego do tego Frustrum Culling techniką.

3

Umożliwia uzyskanie kąta między wektorem nagłówka przeglądarki a wektorem od widza do celu. Jeśli ten kąt jest mniejszy niż (FieldOfView/2), to cel znajduje się w polu widzenia widza.

Jeśli Twoje wektory to 2d lub 3d, to działa tak samo. (W 3D, jeśli masz zamiast stożka widok ścięty stożek, musisz rozdzielić kąty na dwa składniki.) Musisz tylko znaleźć kąt pomiędzy dwoma wektorami.

Jeśli chcesz przetestować obiekty, które są większe niż pojedynczy punkt, potrzebujesz wielu punktów dla każdego celu, na przykład narożników obwiedni. Jeśli wektor z przeglądarki do któregoś z tych punktów daje kąt w polu widzenia, wówczas widoczny jest ten narożnik pola.

10

Pracowałem w branży gier wideo i mogę powiedzieć, że wykonywanie funkcji wyzwalania, takich jak arccos, jest mniej niż idealne. Zamiast tego wcześniej obliczyć cosinus kąta stożka:

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

Następnie, każda klatka można szybko sprawdzić, czy punkt znajduje się wewnątrz tego stożka, porównując to z iloczynu skalarnego stożka a.

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; 

Brak funkcji wyzwalania, tylko niektóre mnożenie, dzielenie i dodawanie. Większość silników gier ma zoptymalizowaną funkcję normalizacji() dla wektorów.

To działa, ponieważ tego równania:

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

Jeśli normalizacji wektorów (A -> An), równanie jest uproszczona:

An · Bn = cos(Θ) 
+0

Dzięki za to. Podoba mi się pomysł ograniczenia funkcji trygraficznych na klatkę. Zdecydowanie popracuję nad wypróbowaniem tego jednego (Niestety, tylko po zakończeniu egzaminów). – AshtonKJ

+0

Uwielbiam tę odpowiedź. Na marginesie, to rozwiązanie wykona jedynie "test punktu ściętego frustum" i nie zajmie się okluzją ścian i innych obiektów. –

1

dobre odpowiedzi już, ale ja po prostu chciałem podają link do bloga Wolfire'a. Niedawno rozpoczęli serię algebry, która przyjmuje równanie "pola widzenia" jako jeden z przykładów. Go read it, dobrze napisana i łatwa.

Powiązane problemy