En fazla 30 nesne ile, aynı iki çifti her karede bir kereden fazla kontrol etmekten başka optimizasyona ihtiyacınız olmamalıdır. Aşağıdaki kod örneği kapsayacaktır. Ancak bir fizik motorunun kullanacağı farklı optimizasyonlarla ilgileniyorsanız, bu yazının geri kalanını okumaya devam edin.
İhtiyacınız olan şey , Octree (3D oyunlar için) veya Quadtree (2D oyunlar için ) gibi bir uzamsal bölümleme uygulamasıdır . Bunlar dünyayı alt bölümlere ayırır ve daha sonra her alt bölüm, en az boyuta bölünene kadar aynı malikanede daha fazla bölümlenir. Bu, dünyanın hangi bölgesinde bulunan diğer nesnelerin diğeriyle aynı bölgede olduğunu çok hızlı bir şekilde kontrol etmenizi sağlar, bu da kontrol etmeniz gereken çarpışma miktarını sınırlar.
Uzamsal bölümlemeye ek olarak , fizik nesnelerinizin her biri için bir AABB ( Eksen hizalı sınırlama kutusu ) oluşturmanızı öneririm . Bu, bir nesnenin AABB'sini başka bir nesneye karşı kontrol etmenizi sağlar; bu, nesneler arasında ayrıntılı bir çoklu denetimden daha hızlıdır.
Bu, karmaşık veya büyük fizik nesneleri için başka bir adım daha ileri gidebilir, burada fizik ağını alt bölümlere ayırabilir ve her alt şekle, yalnızca iki nesnenin AABB'leri çakışıyorsa kontrol edebileceğiniz kendi AABB'sini verir.
Çoğu fizik motoru, dinlendikten sonra fizik bedenlerindeki aktif fizik simülasyonunu devre dışı bırakır. Bir fizik gövdesi devre dışı bırakıldığında, sadece her karesinde AABB'ye karşı çarpışma olup olmadığını kontrol etmelidir ve AABB ile bir şey çarpışırsa, o zaman yeniden etkinleştirilir ve daha ayrıntılı bir çarpışma kontrolü yapar. Bu simülasyon sürelerini azaltır.
Ayrıca, birçok fizik motoru birbirine yakın olan bir grup fizik bedeninin birlikte gruplandığı 'simülasyon adaları' kullanır. Simülasyon adasındaki her şey dinleniyorsa, simülasyon adasının kendisi deaktiftir. Simülasyon adasının yararı, içindeki tüm cesetlerin, ada aktif olmadığında çarpışma kontrolünü durdurabilmesidir ve her çerçevenin tek kontrolü, adanın AABB'sine bir şey girip girmediğini kontrol etmektir. Adanın AABB'sine yalnızca bir şey girdiğinde, adanın içindeki cesetlerin her birinin çarpışmaları kontrol etmesi gerekir. Simülasyon adası, içindeki herhangi bir vücut kendi kendine tekrar hareket etmeye başlarsa da yeniden etkinleştirilir. Bir vücut grubun merkezinden yeterince uzaklaşırsa, adadan kaldırılır.
Sonunda böyle bir şey kaldı (sözde kodda):
// Go through each leaf node in the octree. This could be more efficient
// by keeping a list of leaf nodes with objects in it.
for ( node in octreeLeafNodes )
{
// We only need to check for collision if more than one object
// or island is in the bounds of this octree node.
if ( node.numAABBsInBounds > 1)
{
for ( int i = 0; i < AABBNodes.size(); ++i )
{
// Using i+1 here allows us to skip duplicate checks between AABBS
// e.g (If there are 5 bodies, and i = 0, we only check i against
// indexes 1,2,3,4. Once i = 1, we only check i against indexes
// 2,3,4)
for ( int j = i + 1; j < AABBNodes.size(); ++j )
{
if ( AABBOverlaps( AABBNodes[i], AABBNodes[j] ) )
{
// If the AABB we checked against was a simulation island
// then we now check against the nodes in the simulation island
// Once you find overlaps between two actual object AABBs
// you can now check sub-nodes with each object, if you went
// that far in optimizing physics meshes.
{
}
}
}
}
Ayrıca böyle döngüler içinde çok fazla döngüye sahip olmamanızı tavsiye ederim, yukarıdaki örnek sadece fikri aldım, size yukarıda gösterilen gibi aynı işlevselliği veren birden fazla işleve ayırırdım.
Ayrıca, döngü sırasında AABBNodes kapsayıcısını değiştirmediğinizden emin olun; bu, kaçırılan çarpışma kontrolleri anlamına gelebilir. Bu sağduyu gibi gelebilir, ancak çarpışmalara tepki veren şeylerin tahmin etmediğiniz değişikliklere neden olmasının ne kadar kolay olduğuna şaşıracaksınız. Örneğin, bir çarpışma, çarpışan nesnelerden birinin, onları kontrol etmekte olduğunuz Octree düğümünün AABB'sinden çıkarmak için yeterince pozisyon değiştirmesine neden olduysa, o kap değiştirebilir. Bunu çözmek için, kontroller sırasında meydana gelen tüm çarpışma olaylarının bir listesini tutmanızı ve ardından tüm kontroller tamamlandıktan sonra listeden geçip herhangi bir çarpışma olayını göndermenizi tavsiye ederim.