Użyj sumy Minkowskiego
Dobrym sposobem na rozwiązanie tego problemu jest rozważenie skrzyżowaniu linii ruchu ( v ) tłumaczone na pochodzenie ( V „ ) i suma Minkowski od A obrócony o 180 stopni na początku ( A” ) i jej przeszkód (tylko B w tym przypadku): A” ⊕ B .
W poniższym obrazku I miejsce A zadatki-DAB w początku układu współrzędnych arbitralny. Upraszcza to zrozumienie, że obrót A o 180 stopni daje A ' , a v przetłumaczone na początek równa się v' .
Suma Minkowskiego jest zielonym prostokątem, a punkty przecięcia ruchomego A i stacjonarnego B można znaleźć, wykonując przecięcie linii-AABB . Punkty te są oznaczone niebieskimi kółkami.
Na poniższym zdjęciu użyto innego początku i znaleziono te same punkty przecięcia.
Wiele ruchomych AABB
Aby to zadziałało dla dwóch AABB, które poruszają się liniowo w określonym czasie, odejmujesz wektor prędkości B od wektora prędkości A i używasz go jako odcinka linii dla przecięcia linii AABB.
Pseudo kod
def normalize(aabb):
return {x1: min(aabb.x1, aabb.x2), x2: max(aabb.x1, aabb.x2),
y1: min(aabb.y1, aabb.y2), y2: max(aabb.y1, aabb.y2),
def rotate_about_origin(aabb):
return normalize({x1: -aabb.x1, x2: -aabb.x2
y1: -aabb.y1, y2: -aabb.y2})
# given normalized aabb's
def minkowski_sum(aabb1, aabb2):
return {x1: aabb1.x1+aabb2.x1, x2: aabb1.x2+aabb2.x2,
y1: aabb1.y1+aabb2.y1, y2: aabb1.y2+aabb2.y2}
def get_line_segment_from_origin(v):
return {x1: 0, y1: 0, x2: v.x, y2: v.y}
def moving_objects_with_aabb_intersection(object1, object2):
A = object1.get_aabb()
B = object2.get_aabb()
# get A'⊕B
rotated_A = rotate_about_origin(A)
sum_aabb = minkowski_sum(rotated_A, B)
# get v'
total_relative_velocity = vector_subtract(object1.get_relative_velocity(), object2.get_relative_velocity())
line_segment = get_line_segment_from_origin(total_relative_velocity)
# call your favorite line clipping algorithm
return line_aabb_intersection(line_segment, sum_aabb)
Reakcja na zderzenie
W zależności od rozgrywki albo wykonasz dokładniejsze wykrywanie kolizji (być może AABB zawiera siatki), albo przejdziesz do następnej fazy: reakcji na kolizję.
Gdy dojdzie do kolizji, algorytm przecięcia linii AABB zwróci 1 lub 2 punkty przecięcia w zależności od tego, czy A odpowiednio zakończy ruch wewnątrz B, czy też go przejdzie. (Jest to pomijanie zdegenerowanych przypadków, w których A ociera się o B wzdłuż ich boków lub wzdłuż jednego z odpowiednich narożników.)
Tak czy inaczej, pierwszym punktem przecięcia wzdłuż odcinka linii jest punkt kolizji, przełożyłbyś to z powrotem do właściwej pozycji w światowym układzie współrzędnych (pierwszy jasnoniebieski okrąg na drugim zdjęciu wzdłuż oryginalnego v , nazwij go p ), a następnie zdecyduj (np. w przypadku zderzeń sprężystych, odbijając v wzdłuż normalnej kolizji w punkcie p ), jaka będzie rzeczywista pozycja dla A na końcu ramki ( At + 1 ).
Jeśli są więcej niż tylko 2 zderzacze, stanie się to nieco bardziej skomplikowane, ponieważ chcesz również wykonać wykrywanie kolizji dla drugiej, odzwierciedlonej części v .