Apa cara tercepat memeriksa apakah dua AABB yang bergerak berpotongan?

12

Saya memiliki dua AABB yang bergerak, apa cara tercepat untuk memeriksa apakah mereka akan berpotongan di bawah bingkai?

Dengan memindahkan maksud saya bukan hanya untuk memeriksa dengan metode persimpangan persegi panjang yang biasa, maksud saya semacam tes mudah disapu sederhana yang hanya mengembalikan boolean, tidak ada waktu hit atau apa pun.

Apa yang saya pikirkan adalah melakukannya seperti ini:

Ini

Tetapi Hexagon itu cukup kompleks dan saya tidak tahu bagaimana cara menghitung persimpangan AABB - Polygon, apakah mungkin ada cara yang lebih mudah?

Bahasa pemrograman apa pun yang paling Anda sukai, saya dapat dengan mudah porting itu.

Terima kasih.

super
sumber
3
Saya bingung. Anda secara khusus menyebutkan "tes sapuan", apakah Anda sudah mencoba tes sapuan AABB yang khas? Itu tepat seperti yang Anda inginkan.
SomeWrites Dipulihkan
1
Saya setuju dengan komentar di atas - apa yang salah dengan tes "klasik"? Selain itu, sebagian besar solusi yang diusulkan di sini jelas lebih lambat dari itu ... ditambah beberapa dari mereka dapat memberikan hasil yang salah (tidak kuat).
Keajaiban
Anda bisa mencoba permainan Separating Axis Test gamedevelopment.tutsplus.com/tutorials/...
Pharap

Jawaban:

8

Gunakan jumlah Minkowski

Cara yang baik untuk menyelesaikan masalah ini adalah dengan mempertimbangkan persimpangan antara garis gerak ( v ) yang diterjemahkan ke titik asal ( v ' ) dan jumlah Minkowski dari A yang diputar 180 derajat pada titik asal ( A' ) dan rintangannya (hanya B dalam kasus ini): A'B .

Dalam gambar berikut saya tempat A smack-dab di asal sewenang-wenang sistem koordinat. Ini menyederhanakan pemahaman karena memutar A sebesar 180 derajat menghasilkan A ' , dan v yang diterjemahkan ke asal sama dengan v' .

Jumlah Minkowski adalah persegi panjang hijau, dan titik persimpangan A bergerak dan B stasioner dapat ditemukan dengan melakukan persimpangan garis-AABB . Titik-titik ini ditandai dengan lingkaran biru.

Minkowski sum - kasus degenerasi

Dalam gambar berikut asal yang berbeda digunakan dan titik persimpangan yang sama ditemukan.

Minkowski sum - kasus yang lebih umum

Beberapa AABB bergerak

Untuk membuat karya ini untuk dua AABBs bahwa langkah secara linear selama periode waktu tertentu Anda akan kurangi B 's kecepatan vektor dari A ' vektor kecepatan dan penggunaan yang sebagai segmen garis untuk persimpangan line-AABB.

Kode palsu

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)

Respon tabrakan

Bergantung pada gameplay Anda akan melakukan deteksi tabrakan lebih halus (mungkin AABB mengandung jerat), atau bergerak maju ke fase berikutnya: respon tabrakan.

Ketika ada tabrakan, algoritma garis-AABB-persimpangan akan mengembalikan 1 atau 2 titik persimpangan tergantung pada apakah A mengakhiri gerakannya di dalam B atau melewatinya, masing-masing. (Ini mengabaikan kasus yang merosot di mana A menyerempet B di sepanjang sisinya atau di salah satu sudutnya masing-masing.)

Either way, titik persimpangan pertama sepanjang segmen garis adalah titik tumbukan, Anda akan menerjemahkan ini kembali ke posisi yang benar dalam sistem koordinat dunia (lingkaran biru muda pertama di gambar kedua sepanjang v asli , sebut saja p ) dan kemudian memutuskan (misalnya, untuk tumbukan elastis dengan merefleksikan v sepanjang tumbukan normal pada p ) apa posisi sebenarnya untuk A pada akhir bingkai akan ( Pada +1 ).

Respon tabrakan

Jika ada lebih dari 2 colliders, ini akan menjadi sedikit lebih rumit, karena Anda ingin melakukan deteksi tabrakan untuk bagian kedua, yang direfleksikan, dari v juga.

Eric
sumber
Terima kasih, paling menarik. Bisakah Anda jelaskan bagaimana Anda menangani kasing ketika A dan B berpotongan saat bergerak, tetapi akhiri langkah tanpa persimpangan?
GameAlchemist
@GameAlchemist Itu akan menjadi respons tabrakan, dan tidak begitu banyak deteksi tabrakan (subjek asli pertanyaan). Tapi saya suka Paint, jadi periksa hasil editnya. :-)
Eric
Terima kasih atas pembaruan (dan hurra untuk skema :-)), ini bukan pertanyaan saya tetapi membantu saya memahami bahwa algoritma Anda sudah menangani kasus ketika A benar-benar melewati B.
GameAlchemist
5

OBB - Kotak pembatas yang berorientasi. Ini tutorialnya

Secara efektif, kotak pembatas selaras dengan vektor Velocity objek A sebagai sumbu y (atas). Lebar dan tingginya dapat dihitung dengan titik awal dan akhir objek A. Anda kemudian membandingkannya dengan AABB objek B (memperlakukannya sebagai OOBB), dan emas Anda.

Jika Anda hanya mencari tes persimpangan cepat untuk melihat JIKA mereka BISA mungkin berpotongan, Anda bisa membuat AABB yang mengelilingi AABB objek A di posisi awal dan akhir. Jika AABB tidak-berpotongan dengan ini semua mencakup AABB, maka tidak ada persimpangan; Namun, ini bisa mengarah ke positif palsu, jadi Anda hanya boleh menggunakannya sebagai tes awal.

Wolfgang Skyler
sumber
4

Anda tidak perlu OOB dan Anda tidak perlu menggunakan deteksi tabrakan stepping time. Cukup gunakan tes menyapu AABB normal, lihat tautan ini . Pada dasarnya itu tidak persis apa yang Anda miliki dalam diagram Anda: AABB bergerak adalah "menyapu" dari titik awal ke titik akhir dan kemudian yang digunakan untuk deteksi tabrakan terhadap AABB statis lainnya.

Jika Anda khawatir tes sapuan ini lebih mahal karena mengembalikan "waktu tumbukan", saya pikir Anda mengoptimalkan secara prematur.

Informasi lebih mendalam tentang tes sapu dapat ditemukan dalam buku yang sangat baik: Deteksi Tabrakan Real-Time oleh Christer Ericson.

SomeWritesResterved
sumber
3

Kelemahan tepi kasus aproksimasi AABB

Anda harus menguraikan gerakan menjadi langkah-langkah yang lebih kecil dan menggunakan informasi itu untuk menghitung AABB tingkat tinggi. Jika AABB besar berpotongan, Anda kemudian dapat memeriksa langkah-langkah kecil agar lebih akurat.

Memperkirakan apakah mungkin ada tabrakan dengan memeriksa AABB (atau OOBB) hanya dengan menggunakan posisi awal dan akhir dapat melewatkan tabrakan jika salah satu objek berputar dengan cepat dan lebih lama dalam satu dimensi daripada yang lain.

Untuk menghitung estimasi AABB yang lebih akurat, dekomposisi pergerakan menjadi langkah-langkah yang lebih kecil, dan hanya menggunakan AABB awal (bukan mesh objek), putar AABB (sekarang hanya sebuah kotak, bukan sumbu yang disejajarkan) karena objek akan berputar dan bergerak di setiap langkah. Maks dan titik min untuk setiap sumbu akan memberi Anda AABB yang melingkupi seluruh gerakan objek.

Jika ada persimpangan dengan AABB yang lebih besar, Anda kemudian dapat menggunakan AABB yang lebih kecil yang sudah dihitung untuk menentukan di mana tabrakan mungkin. Untuk masing-masing AABB kecil yang bersinggungan dengan objek lain, Anda dapat melakukan deteksi persimpangan jala yang lebih mahal.

Constablebrew
sumber
2
atau hitung ulang lebar maks BB untuk rotasi apa pun dan gunakan itu
ratchet freak
2

Anda harus menguraikan gerakan menjadi langkah-langkah gerakan yang lebih kecil. Sebagai contoh:

Anda ingin menguraikan gerakan menggunakan komponen yang lebih besar (dalam hal ini, sumbu X), dan kemudian memeriksa tabrakan di setiap langkah.

Ini mungkin terlihat terlalu mahal, tetapi pertimbangkan bahwa suatu objek bergerak lebih cepat dari lebar sendiri setiap siklus akan sangat LUAR BIASA, jadi skenario ini tidak seperti yang biasa Anda pikirkan.

Leo
sumber
2
Metode ini buruk, karena tidak akan menangkap beberapa kasus (misalnya kotak yang dekat dengan yang pertama dan kedua yang Anda gambar) dan meningkatkan pengambilan sampel akan berlebihan. Tes Polygon sederhana menggunakan SAT harus cukup cepat dan dapat diandalkan.
Sopel
1
Ya, ini solusi OK tapi tidak terlalu bagus. Akurasi menurun dengan cepat ketika tumbukan mendekati sudut-sudut objek, kinerja menurun ketika kecepatan meningkat (atau akurasi, tergantung pada implementasinya), dan itu hanya perlu diretas.
BWG
2

Anda juga harus menggunakan kecepatan relatif untuk pemeriksaan tabrakan sehingga satu AABB "statis" dan yang lainnya bergerak dengan kecepatan kecepatannya sendiri dikurangi kecepatan "statis".

Cara tercepat untuk melihat apakah mereka mungkin berpotongan adalah untuk hanya memperluas AABB bergerak dengan kecepatan.

misalnya AABB bergerak ke kanan dengan bingkai 0,1 x /, maka Anda memperpanjangnya sehingga tepi kiri tetap sama dan tepi kanan 0,1 lebih lanjut. Kemudian Anda dapat memeriksa dengan AABB baru. Jika salah maka tidak ada tabrakan. (pengembalian awal dan akurat untuk kecepatan kecil).

Kemudian Anda dapat memeriksa apakah ujung dan mulai AABB dari objek yang bergerak bersinggungan. jika benar maka kembalikan benar.

Kalau tidak, Anda perlu memeriksa apakah diagonal memotong ABB statis.

Ini melibatkan mendapatkan koordinat diagonal di mana x = tepi kiri statis dan tepi kanan melihat apakah y berada di dalam bagian bawah dan atas. (ulangi sebaliknya)

aneh ratchet
sumber