Bir küre ile bir düzlem arasındaki çarpışma tepkisini nasıl hesaplayabilirim?


9

Basit bir 3D oyun oluşturmaya çalışıyorum ve oyuncuyu oyun dünyasının sınırları dahilinde kısıtlamam gerekiyor. Oyuncu dünyanın yanlarına çarptığında oyuncunun gemisinin hafifçe zıplamasını istiyorum.

Aslında oyuncuyu bir kutu içinde tutmaya ve yanlardan kaçmalarını engellemeye çalışıyorum ...

Gameworld'ün sınırlarını, normaller ve mesafelerden uzaktaki bir uçak koleksiyonu olarak tanımlamayı başardım. Oyuncunun küresel bir sınırlama küresi var ve bu web sitesini takip ederek http://www.gamasutra.com/view/feature/3383/simple_intersection_tests_for_games.php Çarpışmaları tespit etmeyi başardım.

Şimdi bir çarpışma tespit edildiğinde ne yapacağımı tam olarak anlayamıyorum. Yönetebileceğim en iyi şey, uçakta sıkışıp kalmak, dümdüz gitmek ya da gerçekten hızlı bir şekilde tekrar tekrar zıplamak.

Sağduyu bana normalin kullanarak uçaktan yansıyan açıyı hesaplamam gerektiğini söylüyor ve bunu oyuncunun hızına uyguluyor. egzersiz yapmak.

Yanıtlar:


4

Nesnenize bir itki uygulamanız gerekecek, bu da süratinde hemen bir değişiklik. Gerçek dünyada, nesneye çok kısa bir zaman zarfında güçlü bir kuvvet uygulanarak, ivmesini tersine çevirerek ve hızının değişmesine neden olur. Ancak, ayrık bir dünyada çalıştığımız için, bu ani yön değişikliğini simüle etmek için biraz hile yapmak zorundayız. Bir küre ve bir uçak için oldukça basittir. En temel çarpışma tepkisi, kürenin hızını uçağın normali etrafında yansıtmaktır ve daha sonra sonuç kürenin yeni hızıdır. Sahte kod şöyle görünecektir:

reflected = 2 * plane.normal * (plane.normal * sphere.velocity)
sphere.velocity -= reflected

Oradan, ısıya veya sürtünmeye kaybedilen enerjiyi hesaba katmak için biraz sönümleme ekleyebilirsiniz (0.9 gibi bir katsayı ile çarpın). Açısal hızı dahil etmek istiyorsanız (belki de küreniz dönüyorsa), denklemler biraz daha karmaşıklaşır.

Daha fazla bilgi için sizi Chris Hecker'in Sert Vücut Dinamikleri hakkındaki makalelerine yönlendireceğim . Daha önce Chris Hecker'ı duymadıysanız, oyun fiziği ve Spore'daki prosedürel karakter üretimi ve animasyon konusundaki çalışmaları ile ünlüdür.


4
Bu esasen doğru yoludur, ancak etki zamanını (TOI) hesaplamak, çerçeveler dalgalanma veya düşme nedeniyle işleri daha doğru hale getirebilir. Mevcut hıza bağlı olarak, etkinin ne kadar zaman önce meydana geldiğini bilmek, bir etki zamanını hesaplamanıza yardımcı olabilir ve bunu kullanarak küreyi çarpma anında konumuna geri getirebilir ve oradan hızı ayarlayabilirsiniz. Etki noktasından konumu ve hızı ayarladıktan sonra, darbe anında yeni hız boyunca TOI'ye gitmek için çıkardığınız süre kadar hareket edersiniz.
Nic Foster

Tamam bu çoğunlukla işe yarıyor gibi görünüyor, ama biraz ... garip. Ben bu benim kod yanlış noktada yapıyor olabilir düşünüyorum. Tüm nesnelerim arasında dolaşmalı ve onları taşımadan önce çarpışıp çarpışmayacaklarını test etmeli miyim (bir sonraki kare olacakları yere göre) ya da onları taşıyıp sonra çarpışmaları test etmeli miyim?
Piku

@Piku, çarpışıp çarpışmayacaklarını tespit etme. Bir çarpışma meydana gelirse, iki nesnenin gerçek çarpışmanın gerçekleşeceği yerin çok ötesinde üst üste gelme şansının olduğunu unutmayın. Temel olarak, çarpışmanın nerede meydana geldiğini bulmanız gerekir (ki sizde) sonsuz kare hızınız var ve nesneyi, çarpışmanın başlangıçta olacağı konuma geri taşımalısınız. Bu gibi nesneleri ayırmazsanız, sürekli aynı çarpışmaya tepki verirsiniz ve nesne sıkışır.
Jonathan Dickinson

@Piku ve bunu yapmak için geçmişte çarpışmanın gerçekleştiği zamanı (TOI / etki zamanı denir) anlıyoruz. Elimize geçtikten sonra, nesnenin hızını geri taşımak için kullanabiliriz ( distance = speed * timegenellikle hatadan kaçınmak için çok küçük bir mesafeyle) ve ardından çarpışma sonucunun hızına göre hızını güncelleyebiliriz.
Jonathan Dickinson

@Piku ayrıca bir sonraki karede nerede olacağımızı da bilmiyoruz (bunu kişisel olarak yapıldığını hiç görmedim), ancak genellikle çarpışma tespiti ve yanıtı yapıyoruz: BU çerçeve için yeni pozisyonu hesapladıktan SONRA, ancak ÖNCE BU çerçeve için yeni konumu uyguluyoruz.
Jonathan Dickinson

1

F = ma veya a = F / m. Küre ve düzlem arasındaki çarpışma noktasını hesaplayın. Bu genellikle Küre merkezidir - normal * yarıçap. Daha fazla doğruluk istiyorsanız, kürenin düzleme ne kadar nüfuz ettiğini hesaplayın ve hesaplamanızı ayarlayın. Gerçekten doğru fizik istemiyorsanız, bu elbette büyük ölçüde isteğe bağlıdır. Şimdi normal boyunca göreceli hızı hesaplayın. Statik bir düzlem için: Vball Dot N. Sonra VballDotN'yi -1 ile çarpın ve kütle ile çarpın. Bu aşamada fizikte bunu da restitüsyon katsayısıyla (sıçrama faktörü) çarparsınız. Bu skaleri N ile çarpın ve gücünüz var.

Vball'u ayarlarken, kuvveti tekrar kütleye bölün ve son ivmeye sahip olun, bu yüzden bunu sadece hıza ekleyin ve çarpışma sonrası hızınıza sahipsiniz.

vec3 Vrel = Ball.getVelocity();
float vDotN = Vrel.Dot(CollisionNormal);
vec3 F = -(1.0f+Ball.getRestitution())*vDotN;
F*=Ball.getMass();
Ball.accelerate(F/Ball.getMass());

Bu yöntem çarpışma tepkisi formülleri için doğrudur. Daha da fazla doğruluk istiyorsanız, sürtünmeyi hesaba katmak isteyeceksiniz, bu da topun dönmesine neden olacak, ancak oyunda bunu isteyip istemediğinizi bilmiyorum. Bunu yaparsanız, teğetsel gücü şu şekilde hesaplarsınız:

vec3 Ft = -(Ball.getvelocity()+(vDotN*CollisionNormal));
Ft*=Ball.getKineticFriction()+Wall.getKineticFriction(); //you could fudge these numbers
Ft*=Ball.getMass();
vec3 vec2Centre = Ball.getPosition()-ContactPoint;
vec3 Torque = cross(vec2Centre,Ft);
Ball.AngularAccelerate(Torque/Ball.getMomentofInertia(glm::normalize(Torque)));

Herhangi bir doğrusal efekt uygulamadan önce Ft değerini hesapladığınızdan emin olun, aksi takdirde sürtünme doğru olmaz.


3 olmak satır gerekmiyor: vec3 F = -CollisionNormal * (1.0f+Ball.getRestitution())*vDotN;?
Shital Shah

Gerçekten evet, o kısmı kaçırdım. Gösterdiğiniz için teşekkürler.
Ian Young

0

Size önce uçaktan olan mesafeyi hesaplamanızı öneririm; ve sonra yarıçapa olan mesafe = = çarpışma reaksiyonunu gerçekleştirdiğinde.

Daha sonra mesafeyi hesaplamak için bunu değiştirebilirsiniz ve mesafe yarıçaptan daha azsa (nesnenin üst üste geldiği anlamına gelir) topların konumunu değiştirin ve çarpışma reaksiyonunu gerçekleştirin.

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.