2011-02-13 31 views
29

2D çarpışma tespiti için bir quadtree kullanmaya çalışıyorum ama bunu nasıl uygulayacağımı biraz şaşırdım. Her şeyden önce, dört alt daireyi (her bir kadranı temsil eden) ve bir alt çerçeveye sığmayan nesnelerin bir koleksiyonunu içeren bir dörtgenim olurdu.2D çarpışma tespiti için Quadtree

  1. geçerli düğümdeki nesnelerle çarpışmaların için nesneyi kontrol edin: ağacında çarpışmaları için bir nesne kontrol ederken

    , böyle bir şey (QuadTree for 2D collision detection sayesinde) yapardı.

  2. Boşluğu nesneye bastıran herhangi bir alt ağaç için, tekrarlayın.

bir dörtlü ağaç ağacın içindeki tüm çarpışmalar bulmak için:

  1. Kontrol akımı düğüm birbirlerine nesneye karşı akım düğümün her nesne.
  2. Geçerli düğümdeki her nesneyi, her alt ağacın karşısına göre kontrol edin.

bir Dörtlüağaç içine eklemek için: nesne birden alt ağaçlar uyan

  1. , o anki düğüm ekleyebilir ve dönüş.
  2. Aksi takdirde, hangi alt ağacı içeriyorsa yineleyin. Her ağaca

    1. Recurse:

  3. bir quadtree güncellemek için.
  4. Geçerli düğümdeki herhangi bir öğe, geçerli ağaçta artık tam olarak uymuyorsa, ana öğeye taşıyın.
  5. Geçerli düğümdeki herhangi bir öğe bir alt ağacın içine sığarsa, bunu alt ağacın içine yerleştirin.

Bu doğru mu? Geliştirilebilir mi?

+1

Bunu açıkladığınız şekilde uygulayın, bu şekilde yaptım ve Dave O.'nin yaptığı gibi ve bu daha kolay kodlanabilir ve daha hızlıdır. Önünüzdeki tüm yaprakları takip etmek için daha fazla liste yönetmek önlenebilir ek yükü ekler. İşte benim sürümlerimden birine (Java'da): [Steerio] (https://github.com/ClickerMonkey/steerio/blob/master/Java/src/org/magnos/steer/spatial/quad/SpatialQuadNode. java) – ClickerMonkey

cevap

32

Dörtgen yapınız en uygun değil. Düğüm başına 4 alt simge kaydetme hakkınız vardır, ancak gerçek nesneler yalnızca iç düğümlerde değil, yaprakların içinde saklanmalıdır. Bu nedenle gerçek nesneleri tutan koleksiyonun yapraklara taşınması gerekir.

en operasyonların uygulanmasında bir göz atalım: Nesne geçerli düğümü kesiştiğini
Kontrol:
  1. Dörtlüağaç
    içine bir nesne sokun. Eğer öyleyse, tekrarlayın. Yaprak seviyesine ulaştıysanız, nesneyi koleksiyona ekleyin. nesneyi ekleme sanki
    aynı adımları yürütün, ancak ulaştığınızda yaprak düzeyi koleksiyonundan silin:
  2. Dörtlüağaç bir nesne silin.
  3. Testi bir nesne Dörtlüağaç içine herhangi bir nesne kesişiyor ise: nesne ekleme sanki
    aynı adımları yürütün, ancak koleksiyonundaki tüm nesnelerle çarpışma için yaprak düzeyi kontrolü ulaştınız zaman.
  4. Dörtgen içindeki tüm nesneler arasındaki tüm çakışmaların sınanması:
    Dörtlüdeki her nesne tek nesne çarpışma testini yürütür.
  5. Dörtgen'i güncelleştirin:
    Konumu değiştirilmiş olan dörtgen tüm nesneleri silin ve yeniden ekleyin.

Bu birçok avantajı vardır: sadece Dörtlüağaç işlemleri işlemek için (daha az özel durumlar) çok kolay yaprakları nesneleri saklayarak

  • quadtree ile yaprakları olabilir
  • Farklı derinlik, böylece kapsadığı uzamsal bölgeye bağlı olarak quadtree yoğunluğunu uyarlamanıza izin verir. Bu uyarlama çalışma zamanında gerçekleşebilir, böylece nesne/düğüm oranını en iyi şekilde koruyabilir.

Sadece disatvantage:

  • Nesneler Dörtlüağaç içinde çeşitli koleksiyonlarına ait olabilir. Her nesneyi çoğaltmadan numaralandırmak için quadtree dışında ekstra doğrusal bir koleksiyona ihtiyacınız olacak.
+1

Bu endişe ettiğim ekstra dezavantaj. Bu, B'nin birden fazla alt ağaçta olmasına rağmen, yalnızca B ile çarpıştığından emin olmak için ekstra kodun eklenmesine neden olur (quadtree dışındaki doğrusal koleksiyon gibi). – bfops

+0

@RobotGymnast Çarpışma, yalnızca doğru/yanlış döndürdüğünüzden ve bir nesne birden fazla kümeye aitse, hala aynıdır. Numaralandırmadır. Tüm nesnelerinizden geçmek için dörtlüleri kullanamazsınız, çünkü bazılarını birkaç kez ziyaret edersiniz. –

+0

Bu naif olabilir, ancak nesneye touched() tipi bir işlev eklemek ne demektir? Bu şekilde, incelenen bir nesne ne zaman dokunduğunuzda dokunduğunuzda bir bayrak ayarlayabilir ve böylece geri gelirse göz ardı edebilirsiniz? Oldukça temiz ve hatta zarif bir yöntem olmayabilir biliyorum ama yeterince basit görünüyor ve quadtree uygulamaları ile büyük etkisi için kullandım. –

0

Ben henüz, ama Tutulma benim göbek ikilisi üzerinde iyi çalışıyor gibi görünüyor nasıl cpu etkili emin değilim, hala temelde .. lol 2400 den fps'de

çalışır, ben bir liste eklendi nesneyle ilişkilendirdiğim dörtyüz düğüm nesnelerine başvuruları saklamak için katıştırılabilir nesnelere (quadtree'ye ekleyerek). Ayrıca, her bir dörtlü düğüme, o düğümün sınırları içinde kabul edilen herhangi bir nesneye referanslar depolayan bir liste ekledim. Böylece her düğümün her bir nesneden yalnızca bir tanesi olur. Her düğüm ayrıca, daha fazla çarpışma doğruluğu için inital düğümünden sonra herhangi birini kontrol etmek istesem, yakın düğümlere navigasyon için ana düğümüne bir referansı da saklar.

o bir hücreden diğer tüm nesnelere başvurular almak çok kolay: birisi yardım

list temp_checklist = object.cells[cell_index].objects 
//('objects' being some sort of array or list of object references as described above) 

umut;)

5

Quad ağaçları daima çarpışma tespiti için en iyi veri yapısı değildir. Dörtlülerin tepesi potansiyel olarak sınırsız olabilir (eğer ağacın derinliğini sınırlamazsanız) ve en kötü durumda hiç hız vermeyin. Bunun yerine, sadece birden fazla ağaç seviyesini geçmenin ekstra yükü olmadan bir dörtlükten daha iyi performans veren seyrek bir ızgara kullanmayı düşünebilirsiniz.

Daha da iyi olabilecek başka tamamen farklı yaklaşımlar da vardır.

da bunu daha ayrıntılı olarak bu konuları tartışmak yazdığı bazı makaleler:: Aşağıdaki modülünde olduğu gibi Örneğin,, Zomorodian ve Edelsbrunner algoritmasını uygulamayı da deneyebilirsiniz

, sen incelenen tüm kütüphanelerin göreceksiniz, dörtlü ağaçlar R-ağaçları gibi diğer çarpışma algılama yöntemlerine göre oldukça düşük performans eğiliminde, ızgaralar veya segment ağaçlar.