Con solo 30 objetos como máximo, no debería necesitar mucha optimización para no comparar los mismos dos pares entre sí más de una vez por cuadro. Que cubrirá el siguiente ejemplo de código. Pero si le interesan las diferentes optimizaciones que usaría un motor de física, continúe leyendo el resto de esta publicación.
Lo que necesitará es una implementación de partición espacial , como un Octree (para juegos 3D) o Quadtree (para juegos 2D). Estos dividen el mundo en subsecciones, y luego cada subsección se divide más en la misma mansión, hasta que se hayan subdividido en un tamaño mínimo. Esto le permite verificar rápidamente qué otros objetos están en la misma región del mundo que otro, lo que limita la cantidad de colisiones con las que debe verificar.
Además de la partición espacial, recomendaría crear un AABB ( cuadro delimitador alineado con el eje ) para cada uno de sus objetos de física. Esto le permite verificar el AABB de un objeto contra otro, lo cual es mucho más rápido que una verificación detallada por poli entre objetos.
Esto puede llevarse un paso más allá para objetos físicos complicados o grandes, donde puede subdividir la malla física en sí, dando a cada subforma su propio AABB con el que puede verificar solo si los AABB de dos objetos se superponen.
La mayoría de los motores de física desactivarán la simulación física activa en los cuerpos físicos una vez que se detengan. Cuando un cuerpo de física está desactivado, solo necesita verificar la colisión contra su AABB en cada cuadro, y si algo choca con el AABB, entonces se reactivará y realizará una verificación de colisión más granular. Esto mantiene bajos los tiempos de simulación.
Además, muchos motores de física usan 'islas de simulación', que es donde se agrupa un grupo de cuerpos de física que están muy juntos. Si todo en la isla de simulación está en reposo, entonces la misma isla de simulación está desactivada. El beneficio de la isla de simulación es que todos los cuerpos dentro de ella pueden dejar de verificar colisiones una vez que la isla está inactiva, y la única verificación de cada cuadro es ver si algo ingresó al AABB de la isla. Solo una vez que algo ingrese al AABB de la isla, cada uno de los cuerpos dentro de la isla deberá verificar las colisiones. La isla de simulación también se reactiva si algún cuerpo dentro de ella comienza a moverse nuevamente por sí solo. Si un cuerpo se mueve lo suficientemente lejos del centro del grupo, se elimina de la isla.
Al final te queda algo como esto (en pseudocódigo):
// 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.
{
}
}
}
}
También recomendaría no tener tantos bucles dentro de bucles como este, la muestra anterior fue solo para que usted tenga la idea, lo dividiría en múltiples funciones que le brindan la misma funcionalidad que algo como lo que se muestra arriba.
Además, asegúrese de no alterar el contenedor AABBNodes mientras lo recorre, ya que eso podría significar verificaciones de colisión perdidas. Esto puede sonar a sentido común, pero se sorprendería de lo fácil que es hacer que las cosas reaccionen a colisiones que causan cambios que no anticiparía. Por ejemplo, si una colisión provoca que uno de los objetos en colisión cambie de posición lo suficiente como para eliminarlos del AABB del nodo Octree que estaba comprobando, podría alterar ese contenedor. Para resolver esto, recomiendo mantener una lista de todos los eventos de colisión que ocurren durante las verificaciones, y luego, después de completar todas las verificaciones, revise la lista y envíe cualquier evento de colisión.