Bir çarpışmayı güçlerle çözme


14

2D fizik motorumda, AABB ve AABB çarpışmalarını tespit edebilir ve en kısa penetrasyon vektörünü bularak ve AABB'nin pozisyonuna ekleyerek bunları çözebilirim.

Bunu yapmak ilk AABB'yi ikinci AABB'nin dışına "iter", ancak hız / ivme değişiklikleriyle hiç ilgilenmez.

Simülasyonuma yerçekimi ivmesi eklersem, ilk dinamik AABB'nin hızı, ikinci statik AABB'nin üzerine otursa bile büyümeye devam eder. Sonunda, hız çok büyük olacak ve çarpışma algılanmayacak (dinamik AABB statik olandan düşecektir).

Çözünürlükten sonra hızı sıfıra ayarlamaya çalıştım, ama açıkçası işe yaramadı ve gerçekçi olmayan simülasyonlar yarattı.

Çevrimiçi olarak pozisyon veya hız üzerinde manuel olarak çalışarak çarpışmaların çözülmesinin doğru olmadığını okudum. Kuvvetleri uygulamayı denedim (kütle şimdilik "kodlanmış" 1):

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

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

    acceleration = {0, 0};
}

En kısa penetrasyon vektörünü çarpışma çözünürlüğü sırasında bir kuvvet olarak uygularsam, dinamik AABB statik olandan "dışarı itilir", ancak yerçekimsiz bir simülasyonda hızı asla düşmeyecek ve sonsuza kadar hareket etmeye devam edecektir.

"Geçici" bir kuvvet uygulamak için bir yol var mı? İlk AABB'yi ikinci AABB'nin dışına itme ile ilgilenen bir güç, daha sonra AABB artık çarpışmadığında durur mu?

Tüm kaynak kodu burada bulunabilir: https://github.com/SuperV1234/SSVSCollision


1
Bununla ilgileniyorum. Henüz bir çözüm buldunuz mu?
TravisG

@TravisG: ne yazık ki henüz değil. Herhangi bir cevap alamazsam yarın bir ödül ekleyeceğim.
Vittorio Romeo

Kuvvet, her şeyden önce ivmeye eşit değildir. Hızlanmayı hesaplamak için kütleye ihtiyacınız var. İki cismin nüfuz etmesini önlemek için pozisyonları değiştiriyorsanız, kütleyi de kullanmalı ve her iki cismi de buna göre taşımalısınız. Penetrasyon vektörüne eşit kuvvet uygulamanın bir değeri yoktur. Box2D dürtü tabanlıdır, doğrudan hızlarda çalışır, "doğru" olmayabilir, ancak yeterince iyi. Dürtü tabanlı bir motorda hız değişiklikleriyle uğraşmak çok basittir, bu yüzden kesinlikle kuvvet tabanlı bir çözüm isteyip istemediğinizi veya çok daha basit dürtü tabanlı çözümün yeterince iyi olup olmadığını belirtebilirsiniz.
dreta

Şahsen, fizik motorları hakkında bir kitap almanızı, en azından Newton fiziğinin ilk birkaç bölümünü okumanızı öneririm. Varsayımlarınız yanlıştır ve bu soruya cevap vermeye çalışmak, çarpışmaları çözmek için üst düzey algoritmaları açıklamaya çalışırken size fiziğin temellerini öğretmek zorunda kalacaktır.
dreta

@dreta varsayımları iyi. Tüm nesneler için kütlesinin şimdilik sadece "1" olduğuna dikkat çekti, bu da kod bölümlerini geçerli kıldı. Bu arada, Box2D hızları doğrudan ele alabilse de, bir şekilde aynı problemle başa çıkmak zorundadır. Eğer bir kuvvet uygulamak yerine, Box2D bir dürtü uygularsa, yine de bir şekilde nesneler ayrıldıktan sonra dürtünün sadece ortadan kalkmaması gerçeğiyle ilgilenmelidir. Bununla birlikte, aslında bununla hiç ilgilenmemesi ve sadece nesnelerin enerjilerini tutmasına izin vermesi mümkündür (sonuçta gerçek dünyada böyle olurdu)
TravisG

Yanıtlar:


13

İlk olarak, Box2D gibi ücretsiz, açık kaynaklı bir fizik kütüphanesi kullanmanızı ve oyununuzu benzersiz kılan yönlerine odaklanmanızı tavsiye ederim ! Tekerleği yeniden icat etmekte ısrar ediyorsanız, okumaya devam edin ... tüm fizik motorlarının yaklaşık olduğunu ve aşağıdaki ana hatlarıyla anlattığım yöntemin mevcut modelinizden daha doğru olmasına rağmen, Box2D'nin sonuçları çok daha gerçekçi olacaktır.


İki A ve B nesnesinin daha doğru çarpışma çözünürlüğünü modellemenin hızlı bir yolu için:

  1. Çarpışmadan hemen önceki konumları bulun. Bunu zaten şu şekilde tahmin ediyorsunuz: "en kısa penetrasyon vektörünü bulmak ve AABB'nin pozisyonuna eklemek."
  2. Newton fiziğini kullanarak çarpışmadan hemen sonra hızları bulun :
    • Kütlenin 1 olarak sabit kodlandığı durumda, sadece hızları değiştirin (bu sonsuz kütleye sahip olması gereken statik nesneler için geçerli değildir):
      • Av = Bu
      • Bv = Au
    • A ve B nesneleri farklı kütlelere sahipse:
      • Av = (Au * (Am - Bm) + (2 * Bm * Bu)) / (Am + Bm)
      • Bv = (Bu * (Bm - Am) + (2 * Am * Au)) / (Am + Bm)
    • nerede:
      • v: çarpışmadan sonraki hız
      • u: çarpışmadan önceki hız
      • m: kütle (sabit, statik bir nesnenin kütlesi için mümkün olan en büyük sayıyı kullanın)
  3. Hızlanmayı 0 olarak ayarlayın: Çarpışmadan kaynaklanan hızlanma, yukarıda adım 2'deki hız hesaplamaları ile açıklanmıştır.

Lütfen bu kavramları gösteren örnek asteroitler programımıza bir göz atın .


Ardından, yığılmış nesneleri hesaba katın:

Daha önce belirttiğiniz gibi, yığılmış / dinlenme nesnelerini simüle etmek için hızı kullanmak iyi çalışmaz: hız, bir nesnenin hareket ettiği hızdır, bu nedenle statik bir nesne üzerinde duruyorsa, hız 0'a yakın olmalıdır. bir nesnenin hareketsiz görünmesini sağlamak için hızı:

Simülasyonuma yerçekimi ivmesi eklersem, ilk dinamik AABB'nin hızı, ikinci statik AABB'nin üzerine otursa bile büyümeye devam eder. Sonunda, hız çok büyük olacak ve çarpışma algılanmayacak (dinamik AABB statik olandan düşecektir).

Gerçekte olması gereken şey, yerçekiminin yerçekimini ortadan kaldırması gerektiğinden zıt yöne giden bir ivme kuvvetidir. (Buna normal temas kuvveti denir). Kısayol, havada olmayan cisimlere yerçekimi uygulamamaktır:

  • Bunu yapmanın bir yolu "topraklanmış" bir durumdur:
    • Topraklanmış durumdaki nesnelere yerçekimi uygulamayın.
    • Bir nesne aşağıdan bir cisimle çarpışırsa ve hızı çok küçükse, topraklanmış duruma girer.
    • Bir nesne, dikey hızı belirli bir pozitif değeri aştığında topraklanmış durumdan çıkar.

Güncelleme:

  • Layman'ın deyimiyle Newton fiziği, bir çarpışmadan önceki ve sonraki toplam enerjinin eşleşmesi gerektiğini söylüyor. İki nesne birbirine çarptığında, enerjileri yeniden dağıtılır. Enerji, hız ve ağırlığın bir kombinasyonudur: daha ağır, daha hızlı şeylerin daha fazla enerjisi vardır. Bu sezgisel. Bununla birlikte, sezgisel olmayan, ağırlıkların enerji dağıtımını kesin olarak etkilemesidir.
  • Hızların değiştirilmesi, sadece aynı kütleye (statik, sabit nesneler çok büyük, sonsuz kütlelere sahiptir) sahip iki dinamik, sabitlenmemiş gövde için bir kısayoldur.
  • Bir statik gövde sabitlendiğinde kısayol şudur: diğer dinamik, sabitlenmemiş gövde aynı hızı korur; sadece açı değiştirilir (bir top raya çarptığında bir bilardo masası hayal edin. Ray aslında çok büyük, sonsuz bir kütleye sahiptir).
  • Üç veya daha fazla nesne gibi diğer durumlarda, tam Newton hareket denklemleri çözülmelidir (momentumun korunumu ve kinetik enerjinin korunumu).
  • Newtonian hareket denklemlerinin ikiden fazla cisim için çözülüp çözülemeyeceğinden emin değilim. Neyse ki, üç nesne neredeyse hiçbir zaman aynı anda çarpışmaz. Çarpışan ilk iki cismin ele alınması ve daha sonra önceki çarpışma kararlarının yeni hızlarını kullanarak aşağıdaki çarpışmaların üstesinden gelmek yeterlidir. Bu, fizik zaman adımlarınızı mümkün olduğunca küçük tutmak ve herhangi bir penetrasyon meydana gelmeden önce çarpışmaları ele almak için iyi bir nedendir.
  • Asteroitlerim demosunda, daha büyük kayalar küçük olanlara ayrıldıkça birçok cismin oluşturulduğunu fark edeceksiniz. Ancak, daima beden çiftleri arasındaki çarpışmaları ele alıyorum; ikiden fazla cisimle çarpışmayı asla açıkça ele alma.

Ayrıntılı cevap için teşekkürler. Yine de anlamadığım bir şey var: takas hızları 2 gövdeli bir çarpışmada iyi çalışıyor - ancak, birden fazla gövdenin (ve aynı zamanda statik gövdelerin) hepsi aynı anda çarpıştığında nasıl çalışabileceğini görmüyorum. Yerçekimi olmadan bile, dinamik bir gövdenin statik bir gövdeyle aynı anda çarpışması ve başka bir dinamik gövdenin olması sorunlara neden olur. Hız değiştirildiğinden, hepsi çarpışma sırasına bağlıdır. Statik gövde en son çarpışırsa, gövde hareket etmeyi durdurur. Dinamik olan ise, vücut tekrar hareket edecektir. Bu nasıl düzeltilir?
Vittorio Romeo

@Vee: Güzel sorular! Üç + cisim ve statik cisimler iki ayrı konudur. Her ikisini de bir güncellemede ele aldım. Özet: bir seferde iki nesne ile çarpışma; statik cisimler çok büyük, sonsuz kütleye sahiptir.
Leftium

Dinlenme kontakları modeliniz tuhaf. Dinlenme kontakları sadece yerçekimi için değil, herhangi bir kuvvet için çalışmalıdır. Çalışmanın en kolay yolu, temas halinde önceki çerçevede hızlanma nedeniyle kazanılan hızı kaldırmaktır. Ayrıca küçük hızlar için geri ödemeyi tamamen kaldırabilirsiniz, ancak hesaplamalarınız geri ödemeyi hesaba katmaz. Bu yaklaşım tüm güçler için geçerlidir, uygulanması kolaydır ve yeterince iyi görünür.
dreta

16

Bu sorunun çözülmesi, pozisyonun ve muhtemelen hızın ayarlanmasını gerektirir. Sert vücut fiziği motorları, Newton'un hareket yasalarını kullanarak nesneleri ileriye doğru yürüterek nüfuz etmeyen kısıtlamaları ve sürtünmeyi de çözen bir çözücüye sahiptir. Bu motorlar, makul yörüngeler oluşturmak için doğru doğrusal ve açısal hareket kombinasyonunu hesaplayabilir.

Yalnızca çakışmayı çözmek istiyorsanız, momentuma eklemeden ayırma yörüngeleri oluşturan sözde hızlar kullanabilirsiniz. Bu, Box2D'nin pozisyon çözücüde yapılır.

2006 ve 2007 yılları arasında GDC sunumlarımı almanızı tavsiye ederim:

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

Ayrıca, basitleştirilmiş bir uygulama için Box2D Lite'a bakabilirsiniz.


Konumu ayarlamak için gerekli olduğuna dair açıklama için +1. Birkaç kişi bunu şımartır, ancak simülasyon kararlılığına katkıda bulunmak için çoğu motor pozisyonları doğrudan ayarlayarak hile yapar. Sonuçta, eğer mantıklıysa, oyunlar için çalışır.
teodron

Cevap için teşekkürler. Sunumda muhtemelen kaçırdığım bir şeyi bilmek istedim: Box2D'de statik cisimler özel bir şekilde ele alınıyor mu? Yani - dinamik bir vücut statik bir vücuda çarptığında ne olur?
Vittorio Romeo

2

resim açıklamasını buraya girin

Gerçek dünyada, bir bedeni başka bir bedenin dışına "iten" bir kuvvet yoktur, çünkü nesneler birbirlerine asla nüfuz etmez. En yakın şey normal kuvvettir : gerçek dünya çarpışmalarında temas anında yaratılır, ilk etapta nüfuz etmeyi önler.

Bu normal kuvvetin açısı, iki çarpışan nesnenin temas yüzeyine diktir. Büyüklük, penetrasyonu önlemek için ne kadar kuvvetin gerekli olduğuna bağlıdır. (Sürtünme kuvveti gibi diğer kuvvetler de modellenmedikçe sadece normal kuvvetin y bileşenine dikkat edilmelidir).

Normal kuvveti açıkça modellemek mümkün olsa da, sadece etkilerini modellemek daha kolaydır:

  1. Aşağıdakilerden biri ile nesne kesişimini önleyin:
    • Darbe anında çarpışmaları çözerek hızları ayarlama. (en iyi)
    • Vücutların pozisyonlarını kesişmeyecek şekilde manuel olarak ayarlamak. (daha kolay) Bunu zaten "en kısa penetrasyon vektörünü bularak ve AABB'nin pozisyonuna ekleyerek" yapıyorsunuz.
  2. Yerçekimi kuvvetini iptal eden normal bir kuvvetin olduğu yerlere yerçekimi uygulamayın.
    • Altındaki başka bir nesneyle temas eden bir nesne normal kuvvete tabidir. Dolayısıyla bu nesneleri takip etme meselesidir. (Aslında temas halindeki nesneler normal bir kuvvete sahip olmalıdır, ancak bunların hepsinin yerçekimi açısından net bir etkisi olmayacaktır.)
    • Açıdaki diğer nesneleri aşağı kaydırabilen nesneler eklemek isterseniz, normal kuvvetin sürtünme kuvvetini ve x bileşenini eklemeniz gerekir.

Bunu genel olarak çarpışmalarla ilgili diğer cevabımda biraz farklı tanımladım .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.