Czy istnieje znany „najbardziej wydajny” algorytm wykrywania kolizji AABB vs Ray?
Niedawno natknąłem się na algorytm kolizji AABB vs Sfera Arvo i zastanawiam się, czy istnieje podobny podobny algorytm.
Warunkiem tego algorytmu jest to, że muszę mieć możliwość zapytania wyniku o odległość od początku promienia do punktu zderzenia. Powiedziawszy to, jeśli istnieje inny, szybszy algorytm, który nie zwraca odległości, to oprócz opublikowania takiego, który to robi, również wysłanie tego algorytmu byłoby bardzo pomocne.
Podaj również, jaki jest argument return funkcji i jak go używasz do zwracania odległości lub przypadku braku kolizji. Na przykład, czy ma parametr out dla odległości, a także wartość powrotu bool? czy po prostu zwraca liczbę zmiennoprzecinkową wraz z odległością względem wartości -1 dla braku kolizji?
(Dla tych, którzy nie wiedzą: AABB = Wyrównana oś ograniczająca)
źródło
Odpowiedzi:
Andrew Woo, który wraz z Johnem Amanatidesem opracował algorytm raymarchingowy (DDA) powszechnie stosowany w raytracerach, napisał „Fast Ray-Box Intersection” ( tutaj alternatywne źródło ), który został opublikowany w Graphics Gems, 1990, ss. 395-396. Algorytm ten nie jest budowany specjalnie do integracji przez siatkę (np. Objętość wokseli) w postaci DDA (patrz odpowiedź zacharmarz), szczególnie nadaje się do światów, które nie są równomiernie podzielone, takich jak typowy świat wielościanów w większości 3D Gry.
Podejście to zapewnia obsługę 3D i opcjonalnie eliminuje backface. Algorytm wywodzi się z tych samych zasad integracji, które są stosowane w DDA, więc jest bardzo szybki. Więcej szczegółów można znaleźć w oryginalnym tomie Graphics Gems (1990).
Wiele innych podejść do Ray-AABB można znaleźć na stronie realtimerendering.com .
EDYCJA: Alternatywne podejście bez rozgałęzień - które byłoby pożądane zarówno na GPU, jak i CPU - można znaleźć tutaj .
źródło
Czego używałem wcześniej w moim raytracerze:
Jeśli to zwraca wartość true, to przecina się, jeśli zwraca false, to nie przecina się.
Jeśli użyjesz tego samego promienia wiele razy, możesz wykonać obliczenia wstępne
dirfrac
(tylko podział w całym teście przecięcia). A potem jest naprawdę szybko. I masz również długość promienia do skrzyżowania (przechowywane wt
).źródło
Nikt nie opisał tutaj algorytmu, ale algorytm Graphics Gems jest po prostu:
Za pomocą wektora kierunku promienia określ, które 3 z 6 kandydujących samolotów zostaną trafione jako pierwsze . Jeśli twoim (nietypowym) wektorem kierunku promienia jest (-1, 1, -1), wówczas 3 płaszczyzny, które można trafić, to + x, -y i + z.
Z 3 kandydujących samolotów znajdź wartość t dla przecięcia dla każdego. Zaakceptuj płaszczyznę, która otrzymuje największą wartość t, jako płaszczyznę, która została trafiona, i sprawdź, czy trafienie jest w polu . Schemat w tekście wyjaśnia to:
Moja realizacja:
źródło
To jest moje skrzyżowanie 3D ray / AABox, którego używałem:
źródło
tnear
itfar
?Oto zoptymalizowana wersja powyższego, której używam do GPU:
źródło
Jedną z rzeczy, które możesz chcieć zbadać, jest rasteryzacja przedniej i tylnej ściany obwiedni w dwóch osobnych buforach. Renderuj wartości x, y, z jako rgb (działa najlepiej dla ramki granicznej z jednym rogiem na (0,0,0) i przeciwnie na (1,1,1).
Oczywiście ma to ograniczone zastosowanie, ale uważam, że świetnie nadaje się do renderowania prostych woluminów.
Aby uzyskać więcej szczegółów i kod:
http://www.daimi.au.dk/~trier/?page_id=98
źródło
Oto kod Line vs. AABB, którego używałem:
źródło
Wygląda to podobnie do kodu opublikowanego przez zacharmarz.
Kod ten otrzymałem z książki Christer Ericson w książce „Wykrywanie kolizji w czasie rzeczywistym” w części „5.3.3 Przecinające się promienie lub segmenty przeciw pudełku”
źródło
Dziwi mnie, że Tavian nie wspomniał o bez rozgałęzionej płycie
Pełne wyjaśnienie: https://tavianator.com/fast-branchless-raybounding-box-intersections/
źródło
Dodałem do odpowiedzi @zacharmarz, aby obsłużyć, gdy początek promienia znajduje się w AABB. W takim przypadku tmin będzie ujemne i za promieniem, więc tmax jest pierwszym przecięciem promienia i AABB.
źródło