Mekansal karma ve dörtlü ağaçlara 2D Mekansal bölümleme alternatifleri


11

Oyunumda bir uzamsal bölümleme algoritması uygulamaya çalışıyorum, ancak hem uzamsal karmalar hem de dörtlüler aradığım şey değil.

Seviyemin büyüklüğünün bir sınırı olmaması gerekiyordu (sadece Int32 sınırları). Ben bir "Seviye Genişliği" ve "Seviye Yüksekliği" gerekmez bir mekansal bölümleme algoritması gerekir.

Çok sayıda hareketli fiziksel nesnem var. 500+ nesneleri desteklemek için yeterince hızlı olmak için algoritmaya ihtiyacım var.

Alternatif var mı?

Yanıtlar:


13

Dinamik Ağaç

Box2D , deneyimli bir fizik / oyun programcısı tarafından tasarlanmış iyi optimize edilmiş bir motordur . Başlangıçta Box2D sabit bir yükseklik ve genişlik gerektiren bir karma ızgara kullanıyordu.

Erin daha iyi bir geniş faz algoritmasına yükseldiğinde Nathanael Presson'un btDbvt ile gitti. Bu, Bullet Physics tarafından kullanılan geniş faz. Erin algoritmayı 2d için değiştirdi ve optimize etti.

Box2D kılavuzunda süper yüksek seviyeli bir mesajı okuyabilirsiniz (§4.11 veya Dinamik Ağacı arayabilirsiniz).

Kod içi dokümantasyon dışında (genel API'nin bir parçası olmadığı düşünülürse çok iyi).

Nathanael Presson'un btDbvt'sinden esinlenen dinamik bir AABB ağacı geniş fazı. Dinamik bir ağaç, hacim sorguları ve ışın yayınları gibi sorguları hızlandırmak için ikili bir ağaçtaki verileri düzenler. Yapraklar AABB'li vekillerdir. Ağaçta, AABB proxy'sinin istemci nesnesinden daha büyük olması için b2_fatAABBFactor tarafından proxy AABB'yi genişletiyoruz. Bu, istemci nesnesinin bir ağaç güncelleştirmesini tetiklemeden küçük miktarlarda hareket etmesini sağlar.

Düğümler toplanır ve yeniden konumlandırılabilir olduğundan, işaretçiler yerine düğüm dizinleri kullanırız.

Dinamik Ağacın algoritmasını anlamam bu. Dinamik ağaç, klasik bir avl ikili ağacı ile dörtlü arasındaki çarpıdır. Son etki, yalnızca her düğümü ikiye ayıran ve bölünmüş çizginin sabit olmadığı bir dörtlüdür (iki yarım dörtlü bir ağaç gibi eşit büyüklükte değildir). AVL devreye girer çünkü dinamik bölmeli dörtlü esasen bir listeye (O (n) arama hızı) dejenere olabilir. AVL, alt ağaçların yeniden dengelenmesinde kullanılır, böylece O lg (N) arama hızını sağlar.

Tüm kodların en iyisi MIT'dir, bu nedenle kopyalamaktan / türetilmiş / utanmadan çalmaktan vb. Çekinmeyin.


Görünüşe göre ... karmaşık! Yine de bir göz atacağım. Birisi bana "süpürme ve kurulama" veya "sıralama ve süpürme" tekniğini kullanarak önerdi ama bir C # veya .NET uygulaması hakkında hiçbir şey bulamadım. C ++ örneği buldum ama kafa karıştırıcı ve işe yaramadı (Yine de uygulamaya çalıştım). SAP'nin uygulanması daha kolay olur mu? .NET uygulaması var mı?
Vittorio Romeo

8

Bu, Gamedev'de sorulan benzer bir soruya çok yakın , ancak dosya depolama yerine performansla ilgilendiğinizi görünce, belki de cevabım size daha fazla fayda sağlayacaktır. Tamlık için buraya büyük bir kısmını ekleyeceğim, ancak orijinal cevap, içine bakmak istiyorsanız biraz daha derinlik sağlar.

Benzer bir sorunla karşılaştım ve verileri işlemek için kendi yapımı oluşturmaya karar verdim. Bir dörtlüğe dayanır, ancak her yönden sonsuz (en azından bir Int kadar büyük) genişletilebilirliğe sahiptir. Minecraft'ın şimdi yaptığı gibi merkezi bir noktadan genişleyen ızgara tabanlı verileri işlemek için tasarlanmıştır. Hafızada yerden tasarruf sağlar ve çok hızlıdır.

Kodumu burada bulabilirsiniz . Kod tamamlandı, test edildi (birim ve yük testleri) ve oldukça optimize edildi. Bununla birlikte, iç çalışmalar henüz çok iyi belgelenmemiştir, ancak tüm kamu yöntemleri bu nedenle kullanılabilir olmalıdır. Birisi denemeye karar verirse, soru veya yorumlarınız için benimle iletişime geçmekten çekinmeyin.


1

Nispeten az sayıda (<binlerce) ufacık nesnelerle çalışırken (çoğu nesne potansiyel olarak diğer birçok nesneyle çarpışacak kadar büyük değildir) Eksenel olarak hizalanmış sınırlayıcı kutuların (AABB'ler) basit bir x-sıralı listesinin işe yaradığını görüyorum çok iyi. Sadece nesneleri bir listeye koydum, sonra nesneleri taşıdıktan sonra her kare, listeyi x değerine göre hızlı bir şekilde sıralıyorum, sonra AABB yakınlığını kontrol eden liste içinden bir geçiş yapıyorum. Her nesne için, listenin sonuna veya x aralığının dışında bir nesneye ulaşıncaya kadar listede önündeki nesnelere karşı kontrol ederim; yani, sol kenarın x değeri, test edilen nesnenin sağ kenarının> x değeridir. Temel olarak alanı dinamik olarak bazen çakışan AABB-x-genişlikli dilimlere böler. O'


0

Belki de r-ağacı algoritması aradığınız şeydir.

Statik geometri için gerçekten iyi çalışıyorum, ancak nesneleri yeni konumlarında kaldırarak ve ekleyerek nesneleri taşımak için de kullanabilirsiniz.


Bir C # uygulaması denedim ve performans "yeni konumlarında nesneleri kaldırma ve ekleme" çok kötü oldu.
Vittorio Romeo

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.