¿KD-Tree completamente dinámico contra Quadtree?

11

Trabajando en mi juego, estoy en el punto donde necesito rastrear todas las unidades del mundo para poder hacer controles de combate del vecino más cercano. Este es un juego similar a RTS, con potencialmente miles de pequeñas unidades automatizadas moviéndose.

He estado buscando en KD-Trees y Quadtrees (especialmente Point Quadtrees). Todavía estoy tratando de aprender los detalles de cómo funcionan, pero hasta ahora Point Quadtrees tiene más sentido para mí. Sin embargo, tengo la impresión de que los árboles KD son más rápidos de buscar, lo cual es importante con la cantidad de puntos que tendré en el árbol.

Por otro lado, en mi caso, voy a estar rastreando una gran cantidad de unidades que siempre están en movimiento. De cuadro a cuadro, sus posiciones siempre serán diferentes. Los quadtrees son aparentemente más rápidos para reequilibrar que KD-Trees, pero no sé si eso es aplicable cuando se reequilibra cada punto del árbol.

Me pregunto si sería mejor en este caso simplemente desechar el árbol de cada cuadro y reconstruirlo desde cero, en lugar de tratar de reequilibrar cada punto del árbol. Si un Quadtree es más rápido para reequilibrar, ¿eso también significa que es más rápido construir desde cero? Si es así, eso podría ser más importante para el rendimiento que la velocidad de búsqueda del KD-Tree, dependiendo de la carga que supone crear el árbol, pero no sé ...

Nairou
fuente

Respuestas:

12

Los árboles KD definitivamente no son lo suficientemente dinámicos para ser considerados, honestamente. Mover unas pocas unidades puede requerir fácilmente que reconstruyas todo el KD-Tree. Además, un árbol KD es muy eficiente para las consultas, pero no tanto para la búsqueda de vecinos.

Un quadtree es más flexible con el tiempo, ya que la modificación se mantiene más localmente. La desventaja es que si tiene muchas unidades en un lugar que se mueven con frecuencia, puede subdividirse demasiado y requerir muchas actualizaciones debido al movimiento de las unidades. Puede establecer un umbral por debajo del cual, no pueden ocurrir subdivisiones. Pero cuidado, eso implica que muchas unidades podrían estar potencialmente en el mismo cuadrado de hoja.

Sin embargo, si solo está interesado en encontrar todas las unidades dentro de un radio constante r , no necesita quadtree y kd-tree de inmediato. Simplemente puede crear una matriz 2D de celdas de lado de longitud r y apilar sus unidades en cada celda según su posición. De esa manera, siempre tiene en el peor de los 9 celdas para buscar. Solo si su mapa es enorme , dicha cuadrícula sería demasiado grande para implementar.

Hay dos estructuras más completamente diferentes de las que no hablamos: AABB jerárquicos y tabla hash sensible a lo local. Si el origen de cada AABB jerárquico se describe en relación con el AABB padre, tiene la ventaja de que si un gran grupo de unidades mantiene su formación, entonces no es necesario actualizar los AABB más pequeños, ya que mantienen las mismas posiciones relativas. Por supuesto, rotar la formación podría causar muchas actualizaciones, en ese caso el uso de otros volúmenes delimitadores como esferas o cuadros de delimitación orientados (OBB) puede ser más eficiente.

Las tablas hash locales sensibles solo ofrecen soluciones aproximadas de manera eficiente, por lo que no me molestaría con ellas.

Que debería hacer ? Probablemente comenzaría con una cuadrícula simple, y cuando lo necesite, lo actualizaría a un quadtree y, si lo necesito, lo combinaré con una jerarquía de volumen delimitador por debajo de cierto umbral: los quadtrees funcionan bien a gran escala. escala, los volúmenes relativos delimitadores funcionan bien a pequeña escala. Haciéndolo gradualmente, no tengo que pasar horas desde el principio para obtener la mejor estructura de datos de inmediato .

Lærne
fuente
¡Gracias! No había oído hablar de AABB jerárquicos y tablas hash sensibles a lo local, los examinaré para el futuro. Por ahora voy con una grilla simple y la expandiré si es necesario, como mencionaste. :)
Nairou
4

Las sugerencias de Lærne son geniales, pero también sugeriría un árbol de volumen dinámico delimitador de AABB. Conceptualmente, el árbol de volumen delimitador dinámico mantiene un árbol equilibrado de nodos que pueden consultarse en cualquier momento para elementos cercanos al pasar un AABB y recuperar un par superpuesto. El árbol no se reconstruye en cada cuadro. En cambio, el AABB de cada nodo se infla ligeramente cuando se coloca en el árbol, y el árbol solo se reconstruye cuando el AABB inflado ya no contiene el AABB real del nodo. Lo uso en mi motor de física y funciona muy bien.

El código fuente de Box2D tiene una gran implementación.

https://github.com/erincatto/Box2D/blob/master/Box2D/Box2D/Collision/b2DynamicTree.h

Aquí hay una buena revisión de su implementación:

http://www.randygaul.net/2013/08/06/dynamic-aabb-tree/

Steven
fuente
Sí, eso es más o menos lo que quise decir con AABB jerárquico, no era muy preciso. Ah, y en la unidad RTSes a menudo son móviles, pero en formaciones. Por lo tanto, el uso de coordenadas relativas al nodo AABB padre puede ser bastante eficiente, con el margen de error de "inflación".
Lærne
¿Podrías actualizar el enlace del código de Google?
kolenda