Küçük, Yüksek Hızlı Nesne Çarpışmaları: Tünelden Kaçınma


14

DÜZENLEME / GÜNCELLEME: Şu anda en büyük sorum 3. adımın "t = ..." denkleminin iyi bir fikir mi yoksa bunu yapmanın daha iyi bir yolu olup olmadığı. Diğer sorunların birçoğu kısmen veya tamamen ele alınmıştır, ancak bu konuda gerçekten herhangi bir yorum veya yanıt dokunmamıştır. Yine, bir analitik çözüm muhtemelen gereklidir, hızlar ve mesafeler çok büyüktür ve nesneler çok küçüktür, düşünebileceğim herhangi bir yinelemeli / özyinelemeli çözüm (yorumlarda aşağıda birkaç tavsiye edilir) bu tür durumları iyi idare edecek özel bir yinelemeli / özyinelemeli çözüm o zaman kesinlikle buna açıkım). Şimdiye kadar yardımlarınız için çok teşekkür ederim, hepiniz harikasınız ve düşüncelerinizi ve yardımlarınızı gerçekten takdir ediyorum!

Küçük, yüksek hızlı nesneler arasındaki çarpışmaları tespit etmeye çalışıyorum. Bu, tünellemenin nispeten düşük hızlarda bile çok kolay gerçekleşebileceği bir durumdur.

Işın dökümü çalışmaz, çünkü bu, bir nesne ile sabit bir duvar arasında değil, iki yüksek hızlı nesne arasındaki bir çarpışmayı tespit eder. (Işın döküm yanlış anlamadıysanız?) Performans ÇOK ÇOK bir husustur; mümkünse, büyük bir performans isabetinden kaçınmak istiyorum. Zaten işlevsel ve çok etkili bir dörtlü ( http://en.wikipedia.org/wiki/Quadtree ) uyguladım, bu yüzden aşağıda açıklandığı gibi değiştirip kullanacağım.

Düzenleme: Zaman aralığını azaltmak işe yaramaz. Bu çözüm için hızlar çok yüksek, bu da tünel çarpışmalarının büyük çoğunluğunu kaçırırken performans vuruşlarının çok büyük olacağı anlamına geliyor . (Örneğin, zaman aralığı başına milyonlarca birim olarak ölçülen bir hızda yaklaşık 1 birim büyüklüğünde bir nesnem olabilir ...)

ÖNERİLEN ÇÖZÜM:

Aşama 1:

Her nesnenin hareketi etrafında bir kutu oluşturun, sonra olası çarpışmaların ilk listesini oluşturmak için bu kutuları dörtlü ağaçlara besleyin. Aşağıdaki resme bakın (bu resim, bir konumdan diğerine hareket eden bir daire nesnesini ve dörtgene beslenecek bir dikdörtgen oluşturan hareketi gösterir):Hareketle Oluşturulan Dikdörtgen

2. Adım: (bu adımı atlamak isteyebilir misiniz?)

Dörtlü tarafından üretilen olası çarpışmalar listesini gözden geçirin. Dikdörtgenlerin olası her çarpışmada kesişip kesişmediğine bakın. Öyleyse, 3. adıma geçin.

EDIT: Aşağıda, Sean Middleditch süpürülmüş hacimler / kapsüllerin kesişimi kullanılmasını önerdi (nesneler daireler ise). Bu üç seçenek bırakır: 1) 2. adımı tamamen atlayın. 2) 2. adımı kendi yöntemimle yapın. 3) Sean'ın yolunu yap. Sean'ın yolu kutu fikrimden daha hesaplı olarak pahalı olacak, ancak benim yolumdan daha yanlış pozitifler ayıklayacak ve onların son adıma geçmelerini engelleyecek.

Herkes bu 3 seçenekten hangisinin en iyisi olduğu konusunda deneyimlerden konuşabilir mi? (Bu fizik motorunu birkaç farklı şey için kullanmayı planlıyorum, bu yüzden hangi çözümü kolayca ölçebileceğim tek bir test vakası değil, en geniş çeşitlilikte en hızlı çalışan "genellikle en iyi" çözümü arıyorum en hızlı).

Aşama 3:

Diskriminant (yani karekök altındaki parça) negatif veya 0 ise, çarpışma yoksa, aşağıdaki t = denklemini kullanın, eğer pozitifse t değerini çarpışma zamanı olarak kullanın (bundan sonra pozisyonları buna göre ayarlamak kolaydır. Çarpışmadan sonra her iki nesne de var olmaya devam ederse). Denklem:

t = (-1/2 metrekare ((2 a w-2 a x + 2 b y-2 b z-2 c w + 2 c x-2 d y + 2 dz) ^ 2-4 (w ^ 2- 2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2) (a ^ 2-2 a c + b ^ 2-2 b d + c ^ 2 + d ^ 2-r ^ 2-2 r ss ^ 2)) - a w + a xb y + b z + c wc x + d yd z) / (w ^ 2-2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2 ) .

(1 ve 2, 1 ve 2 nesnelerini belirtmek için kullanılır):

t, 0 ile -1 arasında negatif bir zaman değeridir; burada 0, geçerli karedir ve -1, bir önceki karedir;

a = x konum 1;

b = y konum 1;

c = x konum 2;

d = y konum 2;

w = x hız 1;

x = x hız 2;

y = y hız 1;

z = y hız 2;

r = yarıçap 1;

s = yarıçap 2;

Türev: (^ 2, kare anlamına gelir)

Nesnelerin hareketleri için parametrik denklemler (örneğin, newxpos1 = a + t w) alın ve bunları uzaklık formülüne takın (her iki tarafın karesi): kare formülü karesi = (a + t w - (c + t x)) ^ 2 + (b + t y - (d + t * z)) ^ 2. Unutmayın, t negatif olacaktır. İki dairesel nesnenin çarpışma zamanını bulmak için sol tarafı (r + s) ^ 2'ye eşit olarak ayarladık. İkinci dereceden denklemi (ve çok fazla sıkıcı cebiri) kullanarak t için çözerek yukarıdaki "t = ..." denklemini elde ederiz.

Sorularım:

1) Bunu yapmanın iyi bir yolu var mı? Hiç işe yarayacak mı? Öngörülemeyen herhangi bir sorunla karşılaşacak mıyım? (Bir seferde 2'den fazla nesne çarpıştığında sorun yaşayacağımı biliyorum, ama gerçekten itiraz ettiğim tek durum düşük göreceli hızlara sahip oldukları zaman (göreceli hızlar yüksekse) umurumda değil. daha sonra algoritmanın verdiği "aptal" çözüm "yeterince iyi" olacaktır ve bir insanın hatayı görmesi imkansız olacaktır) ve aynı zaman adımında düşük göreceli hızlarla ikiden fazla çarpışırsa, çoğu çözüm zaten yeterince yakın ol, çünkü bir sürü esnek olmayan çarpışmayı planlamıyorum)

2) Performansım çok acı çekecek mi? Bunun olacağını düşünmüyorum, ama eğer yapacaksa, bunu yapmanın daha iyi bir yolu var mı?

3) Adım 2'yi atlamalı ve adım 1 ila 3'ten doğrudan mı gideyim? Açıkçası 2. adım hayati değildir, ancak performansa yardımcı olabilir (VEYA tasarruf ettiğinden daha fazla CPU zamanına mal olabilir).

Diğer tüm yorum, öneri veya eleştirilere açığız. Yardımın için teşekkürler!


1
Christer Ericson, turuncu kitabında süpürülmüş küre / küre testi hakkında bilgi sahibidir. Sorunu çözmenin birkaç yolu var, ancak en çok yarı ara vermeyi seveceğinizi düşünüyorum. Bu şeyleri kendi başınıza türetmeye çalışmak iyidir, ancak gerçekten iyi bir tespit rutini almak ve daha fazla bilgi edinmek için turuncu kitaba bakıp karşılaştırmanız gerekir.
RandyGaul

Zaten bir planınız var gibi görünüyor .. bir deneyin ve nasıl çalıştığını görün?
Trevor Powell

Bence "olağan" yol delta zaman küçük bir maksimum aralığı olması. 1000 ms'lik elapınız varsa, sadece 10x 100ms (veya 100x 10ms veya 33x 30ms veya benzer bir şey) simülasyonu yapın.
ashes999

@RandyGaul 215-218. Sayfada, özellikle de 218. sayfada (Google önizleme) açıklanan algoritmayı inceledim. Tüm etkileri, güçlü ve zayıf yönleri hakkında henüz düşünmemiş olmama rağmen oldukça zarif. Benimkinden çok daha hızlı olacak mı? Öyleyse, algoritmamın hangi kısmı Ericsson'un özyinelemesine göre yavaş? 3. adımdaki denklem çok yavaş mı olacak? Özyineleme beni tereddüt ettiriyor, çünkü bazı nesneler ÇOK hızlı hareket ediyor olabilir ve bu nedenle bazı durumlarda büyük özyineleme gerekebilir. (Ayrıca, OUCH, bu kitap için 70 $ ...)
MindSeeker

1
@MindSeeker Türevinize bakmak için zamanım yok, ancak Ericsson'un kitabındaki algoritmaların herhangi birinin gerçekten iyi çalışacağından ve muhtemelen öğelerinizden daha hızlı ve daha sağlam olacağından eminim. Diğer sayfaları tanıtmak istiyorsanız, PDF sürümlerini çevrimiçi olarak ücretsiz bulabilirsiniz. Ayrıca sık sık çarpışma tespiti yapacaksanız, turuncu kitap bir elyaftır.
RandyGaul

Yanıtlar:


9

Esasen süpürülmüş hacimlerin biraz aşırı hevesli bir versiyonunu yarattınız .

Nesnenin iki pozisyonunu alın. Nesneyi başından sonuna kadar "süpürün". Bir küre için, bu bir kapsül yaratacaktır. Bir kutu için bu bir altıgen oluşturur (ya da daha uzun bir kutu hareket tek bir eksen üzerindedir). Genel dışbükey çokgenler için bu, farklı bir dışbükey çokgen oluşturacaktır.

Artık bu süpürme birimini kullanarak kavşak testleri (dörtlü sorgular dahil) yapabilirsiniz. Çarpışmanın ne zaman gerçekleştiğini hesaplayabilir, simülasyonu başlangıç ​​zamanından çarpışma zamanına doğru ilerletebilir ve tekrarlayabilirsiniz.

Başka bir seçenek, biraz daha basit, @ ashes999'un belirttiklerini yapmak ve sadece daha küçük bir zaman aralığı veya daha küçük hızlar kullanmaktır. Tek bir fizik bütünleşmesinde hiçbir nesnenin en dar kenarından daha fazla hareket edemeyeceği aralıktan türetilmiş ideal bir maksimum hız vardır. Özellikle küçük veya özellikle hızlı nesneler için iyi performans gösteren oldukça küçük bir aralık bulamayabilirsiniz.

Çarpışmaları algılama konusunda daha iyi tanıtım / aracı kitaplardan biri için Gerçek Zamanlı Çarpışma Tespiti bölümüne bakın .


Harika giriş için teşekkürler! Bu konuda soru sorabilmem için cevabınızı yıkıyorum: "Nesneyi başından sonuna kadar süpür". Şimdiye kadar izliyorum; kesinlikle benim kutu yöntemi üzerinde bir gelişme. Bu şekilleri dörtlü olarak besleyeceğim ve sonra daha kesin çarpışmalar olup olmadığını kontrol edeceğim. "Çarpışmanın ne zaman gerçekleştiğini hesaplayabilirsiniz." Haha söylemesi yapmaktan daha kolay :) Adım için 3. adımdaki denklemime sadık kalmamı önerir misin? Yoksa daha iyi bir yol var mı? Bu gerçekten kritik kısım.
MindSeeker

[devamı] “Başka bir seçenek ...” Bu seçeneği düşündüm, ancak maalesef hızlar çok yüksek. @ Ashes999'a yaptığım yorum yanıtımı görün ve daha fazla bilgi için yukarıda düzenleyin. Yardımın için çok teşekkürler!
MindSeeker

Performansı bilmenin tek yolu onu denemek, ölçmek ve görmek. Bazı "bariz" verimsiz kod, genellikle oldukça sezgisel olmayan nedenlerle, daha önce verimli sürümleri kitlesel olarak out-out gördüm. En hızlı olanı sorma; test edin ve öğrenin.
Sean Middleditch

Yeterince adil, devam edip önerdiğim gibi değiştirilmiş yöntemimi deneyeceğim. Yorumdaki sorum hala devam ediyor: "Çarpışmanın ne zaman gerçekleştiğini hesaplayabilirsiniz." Bu adım için 3. adımdaki denklemime bağlı kalmamı tavsiye ediyor musunuz? Yoksa daha iyi bir yol var mı? Bence sorunun en zor kısmı bu. Süpürülen hacimler, doğru bir şekilde anlarsam, nesnelerin yollarının kesiştiğini söyleyebilir, ancak nesnelerin kendilerinin çarpışıp çarpışmadığını / ne zaman çarpıştığını söyleyemez.
MindSeeker

1
@MindSeeker Süpürülen geometri, ışın yerine şekli dökmeniz dışında yeniden yayılıyor. Bu nedenle yöntem, sabit bir nesneye karşı tek bir ışın yerine tüm hızlı hareket eden nesneler için "ışınlarla" ışın dökümü kullanmaya benzer görünmelidir. "Işınlar" dan potansiyel çarpışmalar belirledikten sonra aynı anda aynı noktada olduklarından emin olmak için her iki "ışın" üzerinde zaman için çözmeniz gerekir.
stonemetal

2

Soruda önerilen algoritma harika çalışıyor: Nesneler aşırı hızlarda olsa bile hızlı ve tamamen doğru . Uygulanan bir quadtree var, bu yüzden adım 1'den quadtree'ye kutuları besledikten sonra, 2. adımı gereksiz buldum: programım neredeyse eskisi kadar hızlı çalışıyordu.

Bu algoritmayı birkaç aydır kullanıyorum ve çarpışma zamanını belirlemede mükemmel bir doğru gibi görünüyor. Web üzerinde daha iyi bir şey yok gibi görünüyor, bu bir kullanmanızı tavsiye ederim. (Yukarıdaki diğer cevaplarda ve yorumlarda yer alan cevapların bazıları harika, ama ya soruda belirtildiği gibi ihtiyaçları tam olarak karşılamıyorlar ya da yazar bir şey hakkında çok belirsizdi ve belirsizlik hakkında sorgulandığında asla cevap vermedi. ).


1

Henüz yorum yapmak için yeterli üne sahip değilim, ama sadece yukarıda belirtilen Sean Middleditch kullanarak "t" hesaplamak mümkün kıldığını eklemek istiyorum. En azından cevabını anladıysam ve doğru sorguladıysan.

İşte sam hocevar'ın şimdiye kadar bulduğum en iyi açıklamayı veren müthiş bir cevabının bağlantısı (o da resim çizdi, yaşasın!)

/gamedev//a/55991/112940

Bu, kendi yönteminizden daha hızlıysa söyleyemem, ancak onu uygulamak ve kendinizle karşılaştırmak için ihtiyacınız olan her şeyi size verir.

Sadece bir "sadece link cevap" bırakmaktan kaçınmak için, onun fikrinin kısa bir özetini sunacağım:

  1. İki sınırlayıcı kutu arasındaki Minkowski Farkını hesaplayın
  2. o zaman arasındaki göreceli hızı kullanarak, kavşak noktasını elde etmek için başlangıç ​​noktasından Minkowski Farkı tarafından oluşturulan kutuya bir ışın / çizgi parçası dökün
  3. Işın çarparsa, ışınının kat ettiği mesafeyi göreli hızı temsil eden vektörün uzunluğuna bölün ve "t"
  4. Yukarıda verdiğim bağlantıya tıklayın ve sam tüm bunların güzel bir açıklama, birçok resim ile bakın. Bu mükemmel.
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.