Alternativas de particionamento espacial 2D para hashes e quadríceps espaciais


11

Eu tenho tentado implementar um algoritmo de particionamento espacial no meu jogo, mas os hashes espaciais e os quadríceps não são o que estou procurando.

O tamanho do meu nível não deve ter um limite (apenas os limites do Int32). Eu preciso de um algoritmo de particionamento espacial que não precise de "Level Width" e "Level Height".

Eu tenho muitos objetos físicos em movimento. Eu preciso que o algoritmo seja rápido o suficiente para suportar mais de 500 objetos.

Alguma alternativa?

Respostas:


13

Árvore dinâmica

O Box2D é um mecanismo bem otimizado, projetado por um experiente programador de física / jogos . Originalmente, o Box2D usava uma grade de hash que exigia altura e largura fixas.

Quando Erin atualizou para um algoritmo de fase larga melhor, ele optou pelo btDbvt de Nathanael Presson. Esta é a fase larga usada pela Bullet Physics. Erin modificou e otimizou o algoritmo para 2d.

Você pode ler uma visão geral de nível super alto no manual do Box2D (§4.11, ou procurar Árvore Dinâmica).

Aqui está uma exceção da documentação do código (o que é muito bom, considerando que não faz parte da API pública).

Uma fase dinâmica de árvore dinâmica da AABB, inspirada no btDbvt de Nathanael Presson. Uma árvore dinâmica organiza dados em uma árvore binária para acelerar consultas, como consultas de volume e transmissões de raios. As folhas são proxies com um AABB. Na árvore, expandimos o proxy AABB por b2_fatAABBFactor para que o proxy AABB seja maior que o objeto do cliente. Isso permite que o objeto cliente se mova em pequenas quantidades sem acionar uma atualização em árvore.

Os nós são agrupados e realocáveis, portanto, usamos índices de nós em vez de ponteiros.

Meu entendimento do algoritmo da Árvore Dinâmica é esse. A árvore Dinâmica é o cruzamento entre uma árvore binária avl clássica e uma quadtree. O efeito final é um quadtree que divide apenas cada nó ao meio e a linha de divisão não é fixa (as duas metades não têm o mesmo tamanho de uma quad tree). O AVL entra porque o quadree com divisões dinâmicas pode degenerar para essencialmente uma lista (O (n) velocidade de pesquisa). O AVL é usado para reequilibrar as subárvores, de modo a garantir a velocidade de pesquisa de O lg (N).

O melhor de tudo é que o código é o MIT, então sinta-se livre para copiar / derivar / roubar vergonhamente / etc.


Parece ... complexo! Vou dar uma olhada nisso, no entanto. Alguém me sugeriu usar a técnica "varredura e remoção" ou "classificação e varredura", mas não consegui encontrar nada sobre uma implementação em C # ou .NET. Encontrei um exemplo de c ++, mas é confuso e não funcionou (tentei implementá-lo de qualquer maneira). Você acha que a SAP seria mais fácil de implementar? Existe implementação do .NET?
Vittorio Romeo

8

Isso está muito próximo de uma pergunta semelhante feita aqui no Gamedev, mas, como você está preocupado com o desempenho e não com o armazenamento de arquivos, talvez minha resposta seja mais útil para você. Incluírei a maior parte aqui para garantir a integridade, mas a resposta original fornece um pouco mais de profundidade se você quiser dar uma olhada.

Encontrei um problema semelhante e decidi criar minha própria estrutura para lidar com os dados. Baseia-se livremente em um quadtree, mas tem capacidade de expansão infinita (pelo menos tão grande quanto uma Int) em todas as direções. Ele foi projetado para lidar com dados baseados em grade que se expandiam a partir de um ponto central, assim como o Minecraft faz agora. É um espaço eficiente na memória e muito rápido.

Meu código pode ser encontrado aqui . O código está completo, testado (testes de unidade e carga) e bastante otimizado. No entanto, o funcionamento interno ainda não está muito bem documentado, mas todos os métodos públicos são, portanto, deve ser utilizável. Se alguém decidir experimentar, sinta-se à vontade para entrar em contato comigo com perguntas ou comentários.


1

Ao trabalhar com um número relativamente pequeno (<vários milhares) de objetos pequenos (a maioria dos objetos não é grande o suficiente para colidir com muitos outros objetos), acho que uma simples lista ordenada x de caixas delimitadoras alinhadas axialmente (AABBs) funciona muito bem. Acabei de colocar os objetos em uma lista e, em seguida, cada quadro depois de movê-los, classifico rapidamente a lista pelo valor de x e faço uma passagem pela lista, verificando a proximidade do AABB. Para cada objeto, comparo-o com os objetos à frente na lista até chegar ao final da lista ou a um objeto que esteja fora do intervalo x; isto é, o valor x da borda esquerda é> valor x da borda direita do objeto que está sendo testado. Ele basicamente divide dinamicamente o espaço em fatias do tamanho de AABB x largura, às vezes sobrepostas. Isto'


0

Talvez o algoritmo r-tree seja o que você está procurando.

Eu trabalho muito bem para geometria estática, mas você também pode usá-lo para mover objetos removendo e adicionando objetos em suas novas posições.


Tentei uma implementação em C # e o desempenho foi muito ruim ao "remover e adicionar objetos em sua nova posição".
Vittorio Romeo

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.