Menyelesaikan tabrakan dengan kekuatan

14

Dalam mesin fisika 2D saya, saya dapat mendeteksi tabrakan AABB vs AABB, dan mengatasinya dengan menemukan vektor penetrasi terpendek dan menambahkannya ke posisi AABB.

Melakukan ini "mendorong" AABB pertama di luar AABB kedua, tetapi sama sekali tidak berurusan dengan perubahan kecepatan / akselerasi.

Jika saya menambahkan percepatan gravitasi ke simulasi saya, kecepatan AABB dinamis pertama terus tumbuh bahkan ketika itu berada di atas AABB statis kedua. Akhirnya, kecepatan akan menjadi terlalu besar dan tumbukan tidak akan terdeteksi (AABB dinamis akan jatuh melalui yang statis).

Saya mencoba mengatur kecepatan ke nol setelah resolusi, tetapi jelas tidak bekerja dengan baik, dan menciptakan simulasi yang tidak realistis.

Saya membaca secara online bahwa menyelesaikan tabrakan dengan bekerja secara manual pada posisi atau kecepatannya tidak benar. Saya mencoba menerapkan kekuatan (massa adalah "hardcoded" 1 untuk saat ini):

void Body::applyForce(sf::Vector2f mForce) { acceleration += mForce; }

void Body::integrate(float mFrameTime)
{
    velocity += acceleration * mFrameTime;
    position += velocity * mFrameTime;

    acceleration = {0, 0};
}

Jika saya menerapkan vektor penetrasi terpendek sebagai kekuatan selama resolusi tabrakan, AABB dinamis akan "didorong keluar" dari yang statis, tetapi kecepatannya tidak akan pernah berkurang dalam simulasi tanpa gravitasi dan akan terus bergerak selamanya.

Apakah ada cara untuk menerapkan kekuatan "sementara"? Suatu kekuatan yang berurusan dengan mendorong AABB pertama dari AABB kedua, lalu berhenti ketika AABB tidak bertabrakan lagi?

Seluruh kode sumber tersedia di sini: https://github.com/SuperV1234/SSVSCollision

Vittorio Romeo
sumber
1
Saya tertarik dengan ini. Sudahkah Anda menemukan solusi?
TravisG
@ TravisG: sayangnya, belum. Saya akan menambahkan hadiah besok jika saya tidak mendapat balasan.
Vittorio Romeo
Kekuatan tidak sama dengan akselerasi, pertama-tama. Anda perlu massa untuk menghitung akselerasi. Jika Anda memodifikasi posisi untuk menghentikan penetrasi dua benda, Anda harus menggunakan massa juga dan menggerakkan kedua badan berdasarkan itu. Menerapkan gaya yang sama dengan vektor penetrasi tidak memiliki kelebihan. Box2D berbasis impuls, ia bekerja pada kecepatan secara langsung, mungkin tidak "benar", tetapi cukup baik. Berurusan dengan perubahan kecepatan pada mesin berbasis impuls sangat sederhana, jadi dapatkah Anda menentukan jika Anda menginginkan solusi berbasis gaya, atau solusi berbasis impuls yang jauh lebih baik cukup baik.
dreta
Secara pribadi, saya sarankan mengambil buku tentang mesin fisika, setidaknya membaca beberapa bab pertama tentang fisika Newton. Asumsi Anda salah dan mencoba menjawab pertanyaan ini berarti harus mengajarkan dasar-dasar fisika sambil mencoba menjelaskan algoritma tingkat tinggi untuk menyelesaikan tabrakan.
dreta
@dreta asumsinya baik-baik saja. Dia menunjukkan bahwa massanya untuk semua objek hanyalah "1" untuk saat ini, yang membuat bagian kode-nya valid. Ngomong-ngomong, meskipun Box2D dapat menangani kecepatan secara langsung, entah bagaimana ia harus berurusan dengan masalah yang sama. Jika alih-alih menerapkan gaya, Box2D menerapkan impuls, entah bagaimana ia masih harus berurusan dengan fakta bahwa impuls tidak hilang begitu saja begitu objek dipisahkan. Meskipun, mungkin saja itu memang tidak berurusan dengan ini sama sekali dan membiarkan benda-benda menyimpan energi mereka (akan seperti ini di dunia nyata setelah semuanya)
TravisG

Jawaban:

13

Pertama, saya sarankan menggunakan perpustakaan fisika open-source gratis seperti Box2D dan hanya berfokus pada aspek permainan Anda yang membuatnya unik! Jika Anda bersikeras menciptakan kembali roda, baca terus ... perhatikan semua mesin fisika adalah perkiraan, dan sementara metode yang saya uraikan di bawah ini akan lebih akurat daripada model Anda saat ini, hasil Box2D akan jauh lebih realistis.


Untuk cara cepat memodelkan resolusi tabrakan yang lebih akurat dari dua objek A dan B:

  1. Temukan posisi tepat sebelum tabrakan.Anda sudah memperkirakan ini dengan: "menemukan vektor penetrasi terpendek dan menambahkannya ke posisi AABB."
  2. Temukan kecepatan tepat setelah tabrakan menggunakan fisika Newton :
    • Untuk kasus di mana massa dikodekan sebagai 1, cukup tukar kecepatan (ini tidak berlaku untuk objek statis yang harus memiliki massa tak terbatas):
      • Av = Bu
      • Bv = Au
    • Jika benda A dan B memiliki massa yang berbeda:
      • Av = (Au * (Am - Bm) + (2 * Bm * Bu)) / (Am + Bm)
      • Bv = (Bu * (Bm - Am) + (2 * Am * Au)) / (Am + Bm)
    • dimana:
      • v: kecepatan setelah tabrakan
      • u: kecepatan sebelum tumbukan
      • m: massa (gunakan jumlah terbesar yang mungkin untuk massa objek tetap dan statis)
  3. Atur akselerasi ke 0: Akselerasi dari tumbukan dihitung di atas dengan perhitungan kecepatan pada langkah nomor 2.

Silakan lihat contoh program asteroid saya yang menunjukkan konsep-konsep ini.


Selanjutnya, akun untuk objek yang ditumpuk:

Seperti yang telah Anda catat, menggunakan kecepatan untuk mensimulasikan objek bertumpuk / beristirahat tidak berfungsi dengan baik: kecepatan adalah kecepatan suatu objek bergerak, jadi jika ia bersandar pada objek statis, kecepatannya harus mendekati 0. Tidak masuk akal untuk meningkatkan kecepatan suatu objek untuk membuatnya tampak diam:

Jika saya menambahkan percepatan gravitasi ke simulasi saya, kecepatan AABB dinamis pertama terus tumbuh bahkan ketika itu berada di atas AABB statis kedua. Akhirnya, kecepatan akan menjadi terlalu besar dan tumbukan tidak akan terdeteksi (AABB dinamis akan jatuh melalui yang statis).

Apa yang seharusnya benar-benar terjadi adalah gaya percepatan yang bergerak ke arah yang berlawanan karena gravitasi harus membatalkan gravitasi keluar. (Ini disebut kekuatan kontak normal). Cara pintas adalah dengan tidak menerapkan gravitasi pada benda yang tidak ada di udara:

  • Salah satu metode untuk melakukan ini adalah menjaga kondisi "membumi":
    • Jangan menerapkan gravitasi ke benda-benda dalam keadaan membumi.
    • Jika sebuah objek bertabrakan dengan objek dari bawah dan kecepatannya sangat kecil, ia memasuki kondisi ground.
    • Sebuah objek keluar dari kondisi ground ketika kecepatan vertikalnya melebihi nilai positif tertentu.

Memperbarui:

  • Dalam istilah awam, fisika Newton mengatakan energi total sebelum dan sesudah tabrakan harus cocok. Ketika dua benda saling menabrak, energi mereka didistribusikan kembali. Energi adalah kombinasi antara kecepatan dan berat: benda yang lebih berat dan lebih cepat memiliki lebih banyak energi. Itu intuitif. Namun, apa yang tidak intuitif adalah bagaimana bobot yang tepat mempengaruhi redistribusi energi.
  • Kecepatan swapping adalah jalan pintas hanya untuk dua benda dinamis dan tidak tetap yang memiliki massa yang sama (benda statis, tetap memiliki massa yang sangat besar dan tak terbatas).
  • Jalan pintas ketika satu badan statis diperbaiki adalah: badan dinamis dan tidak tetap lainnya tetap dengan kecepatan yang sama; hanya sudut yang diubah (bayangkan meja biliar ketika bola menyentuh rel. Pada dasarnya rel memiliki massa yang sangat besar dan tidak terbatas).
  • Untuk kasus lain, seperti tiga objek atau lebih, persamaan gerak Newtonian penuh harus diselesaikan (kekekalan momentum dan kekekalan energi kinetik).
  • Saya tidak yakin apakah persamaan Newton untuk gerak dapat diselesaikan untuk lebih dari dua benda. Untungnya, bagaimanapun, tiga benda hampir tidak pernah bertabrakan pada saat yang bersamaan. Cukup untuk menangani dua benda pertama yang bertabrakan, kemudian menangani setiap tabrakan berikut menggunakan kecepatan baru dari resolusi tabrakan sebelumnya. Ini adalah alasan yang baik untuk menjaga langkah waktu fisika Anda sekecil mungkin dan menangani tabrakan sebelum terjadi penetrasi.
  • Anda akan melihat di demo asteroid saya banyak benda dibuat karena batu yang lebih besar terbelah menjadi yang lebih kecil. Namun, saya selalu menangani tabrakan di antara pasangan tubuh; tidak pernah secara eksplisit menangani tabrakan dengan lebih dari dua badan.
Leftium
sumber
Terima kasih atas jawaban rinci. Ada sesuatu yang saya tidak mengerti: bertukar kecepatan bekerja dengan baik dalam tabrakan dengan 2 benda - namun, saya tidak melihat bagaimana itu bisa bekerja ketika banyak benda (dan juga benda statis) semua bertabrakan pada saat yang bersamaan. Bahkan tanpa gravitasi, memiliki tubuh dinamis bertabrakan pada saat yang sama dengan tubuh statis dan tubuh dinamis lain menyebabkan masalah. Karena kecepatan ditukar, itu semua tergantung pada urutan tabrakan. Jika tubuh statis bertabrakan terakhir, tubuh akan berhenti bergerak. Jika dinamis, tubuh akan bergerak lagi. Bagaimana ini diperbaiki?
Vittorio Romeo
@ Ve: pertanyaan bagus! Tiga tubuh + dan badan statis adalah dua masalah yang terpisah. Saya membahas keduanya dalam pembaruan. Ringkasan: menangani tabrakan dua objek sekaligus; benda statis memiliki massa yang sangat besar dan tidak terbatas.
Leftium
Model Anda untuk mengistirahatkan kontak adalah aneh. Kontak istirahat bukan hanya untuk gravitasi, mereka harus bekerja untuk kekuatan apa pun. Cara termudah yang bekerja adalah dengan hanya menghapus kecepatan yang diperoleh karena akselerasi pada frame sebelumnya saat kontak. Juga untuk kecepatan kecil Anda dapat menghapus restitusi sepenuhnya, meskipun perhitungan Anda tidak memperhitungkan restitusi. Pendekatan ini bekerja untuk semua kekuatan, mudah diimplementasikan dan terlihat cukup baik.
dreta
16

Menyelesaikan masalah ini membutuhkan penyesuaian posisi dan kemungkinan kecepatan. Mesin fisika benda tegar memiliki pemecah benda yang bergerak maju dalam waktu menggunakan hukum gerak Newton sambil juga memecahkan kendala dan gesekan non-penetrasi. Mesin ini dapat menghitung kombinasi yang tepat dari gerakan linier dan sudut untuk menciptakan lintasan yang masuk akal.

Jika Anda hanya ingin menyelesaikan tumpang tindih, Anda dapat menggunakan kecepatan semu yang menghasilkan lintasan terpisah tanpa menambah momentum. Ini dilakukan pada pemecah posisi Box2D.

Saya merekomendasikan untuk mendapatkan presentasi GDC saya dari tahun 2006 dan 2007 di sini:

http://code.google.com/p/box2d/downloads/list

Juga, Anda dapat melihat Box2D Lite untuk implementasi yang disederhanakan.

Erin Catto
sumber
Beri +1 untuk pernyataan perlu untuk menyesuaikan posisi juga. Hanya sedikit orang yang menikmati ini, tetapi untuk menambah stabilitas simulasi, sebagian besar mesin curang dengan menyesuaikan posisi secara langsung. Secara keseluruhan, jika itu masuk akal, itu berfungsi untuk game.
teodron
Terima kasih atas jawabannya. Saya ingin tahu sesuatu yang mungkin saya lewatkan dalam presentasi: apakah badan statis ditangani dengan cara khusus di Box2D? Maksud saya - apa yang terjadi ketika tubuh dinamis mengenai tubuh statis?
Vittorio Romeo
2

masukkan deskripsi gambar di sini

Di dunia nyata, tidak ada kekuatan yang "mendorong" satu tubuh di luar tubuh lain karena benda tidak pernah saling menembus. Hal yang paling dekat adalah kekuatan normal : diciptakan pada saat terjadi kontak dalam bentrokan di dunia nyata, ia mencegah penetrasi sejak awal.

Sudut dari gaya normal ini adalah tegak lurus terhadap permukaan kontak dari dua benda yang bertabrakan. Besarnya tergantung pada seberapa besar kekuatan yang dibutuhkan untuk mencegah penetrasi. (Catat hanya komponen y dari gaya normal yang harus digunakan kecuali jika gaya lain seperti gaya gesek juga dimodelkan).

Meskipun dimungkinkan untuk memodelkan gaya normal secara eksplisit, lebih mudah memodelkan efeknya saja:

  1. Cegah persimpangan objek dengan:
    • Menyesuaikan kecepatan dengan menyelesaikan tabrakan pada saat tumbukan. (terbaik)
    • Secara manual menyesuaikan posisi tubuh sehingga tidak berpotongan. (lebih mudah) Anda sudah melakukan ini "dengan menemukan vektor penetrasi terpendek dan menambahkannya ke posisi AABB."
  2. Jangan menerapkan gravitasi di mana akan ada gaya normal yang membatalkan gaya gravitasi.
    • Objek yang bersentuhan dengan objek lain di bawahnya tunduk pada gaya normal. Jadi itu adalah masalah melacak benda-benda itu. (Sebenarnya benda apa pun yang bersentuhan harus memiliki gaya normal yang diterapkan, tetapi tidak semua ini akan memiliki efek bersih sehubungan dengan gravitasi.)
    • Jika Anda ingin menambahkan objek yang dapat meluncur ke bawah objek lain yang miring, Anda harus menambahkan gaya gesek dan komponen x dari gaya normal.

Saya menggambarkan ini sedikit berbeda dalam jawaban saya yang lain yang lebih banyak tentang tabrakan secara umum .

Leftium
sumber