Gráfico de cena como contêiner de objeto?

8

O gráfico de cena contém nós do jogo que representam objetos do jogo. À primeira vista, pode parecer prático usar o Scene Graph como contêiner físico para objetos do jogo, em vez de std :: vector <> por exemplo.

Minha pergunta é: é prático usar o Scene Graph para conter os objetos do jogo ou deve ser usado apenas para definir as conexões entre objetos e nós da cena, mantendo os objetos armazenados em um contêiner separado, como std :: vector <>?

Bunkai.Satori
fonte
Alguém tem uma ideia? Eu pretendo usar o Scene Graph para organizar os Atores / Nós do Jogo e o Vector para executar várias classificações que devem ser mais rápidas do que classificar uma árvore SceneGraph de várias vias.
Backai.Satori
@ Todos: Tenho mais uma pergunta: o SceneGraph contém o mapa inteiro ou deve conter apenas uma parte do mapa, por exemplo, sua área visível? Obviamente, o Gráfico de Cena será atualizado continuamente, à medida que o jogador se mover sobre o mapa.
Bunkai.Satori

Respostas:

5

A decisão sobre que tipo de gerenciamento de cena usar depende muito do tipo de lógica que você está tentando executar. Considere os diferentes consumidores da sua cena:

Consumidor de renderização

O renderizador provavelmente só quer saber o que está atualmente visível para o usuário em um determinado momento. Ele quer uma hierarquia delimitadora de volume para seleção rápida ( artigo da BVH), para que possa descobrir que uma cadeira dentro de um barco não precisa ser puxada porque os limites do barco estão fora do ponto de vista da vista. Isso pode ser incorporado em uma octree .

Ele também pode querer ter uma idéia de que a cadeira está de costas para dentro do barco e que o barco está rolando para cima e para baixo em algumas ondas quando finalmente aparece. Dessa forma, para encontrar as coordenadas finais do mundo dos vértices da cadeira, ele pode concatenar as transformações da cadeira e do barco e terminar com isso (isso também facilita o seu trabalho como programador).

Ainda outra maneira de encarar esse problema é que o renderizador provavelmente está executando um bom cartão e, no final das contas, quer apenas uma pilha de triângulos classificados para minimizar a textura, o sombreamento, o material, a iluminação e transformar as mudanças de estado. Este último provavelmente o ajudará mais do que um BVH, em termos de desempenho.

Consumidor de lógica de jogo

A lógica do jogo provavelmente só quer uma lista simples de coisas que possam se comunicar por meio de um sistema de mensagens; portanto, um vetor std :: provavelmente é bom.

O jogo também pode querer uma maneira de rastrear quem está mais próximo do quê, então algum tipo de informação do [vizinho mais próximo] [3] pode ser útil nesse caso. Isso também pode ser fornecido por uma BVH, mas ter que subir e descer o gráfico pode ser irritante.

O jogo pode até querer saber que, quando se move A, o item B de A também deve se mover ... nesse caso, voltamos a uma espécie de hierarquia de transformação.

Consumidor de Física

A física do seu jogo pode querer ter uma [representação especial] [4] de espaços internos para uma detecção de colisão muito rápida. Como alternativa, ele pode usar algum tipo de octree ou [hash espacial] [5] para encontrar com eficiência coisas que podem colidir.

Nenhuma estrutura de dados físicos acima realmente se parece com um "gráfico de cena" no sentido Java3D.

Consumidor de áudio

Um mecanismo de áudio deseja apenas geometria, talvez um conjunto potencialmente visível (audível) ou algum tipo de hierarquia de volume delimitadora para calcular a atenuação e a propagação do som. Novamente, não é realmente um tipo normal de gráfico de cena, embora possa muito bem ser um gráfico de geometria em sua cena.

Em última análise ... ... realmente depende apenas das necessidades exatas da sua aplicação. Sugiro usar uma lista simples para começar e ver onde seus problemas surgem. Você pode até tentar uma lista simples com uma hierarquia de transformação, porque esse talvez seja o tipo de gráfico de cenário útil por outros motivos que não a eficiência.

Boa sorte!

ChrisE
fonte
@ Chris: +1 para uma excelente pergunta. Na minha opinião, esta é a melhor resposta aqui, deixe-me, portanto, marcar esta como Resposta Aceita . Se entendi direito, você provou que o Scene Graph nem sempre é a solução definitiva. Especialmente na Game Logic, você vê um Scene Graph como a maneira correta de atualizar a transformação (escala, tradução) de objetos relacionados? Por exemplo, uma cadeira está no barco, então as coordenadas da cadeira são atualizadas à medida que o barco se move? Como alternativa, você vê alguma solução melhor para atualizar as coordenadas relativas?
Bunkai.Satori
@ Chris: Além do mencionado acima, no caso de o Scene Graph ser usado, ele próprio pode ser usado como o único suporte de objetos para a cena, ou você recomendaria ter outro contêiner (digamos std :: vector <>) além da Scene Gráfico?
Bunkai.Satori
2
Na verdade, eu estava sugerindo exatamente isso. Eu tentaria manter uma hierarquia de transformação (aqui, uma árvore n-ária em que os nós têm um pai e vários filhos e nenhum filho é compartilhado entre os nós) com cada nó contendo uma referência ao objeto do jogo. Os objetos do jogo são mantidos em uma matriz plana e separada (digamos, std :: vector).
ChrisE
Durante a atualização, você pode percorrer a lista simples e executar a lógica do jogo e sempre que ocorrer um movimento relativo (por exemplo, a cadeira é empurrada para a frente no barco), você usa a hierarquia de transformação para encontrar a transformação local de mundo final andando os pais do seu objeto e concatenando as transformações deles. Isso usa a hierarquia de transformação para o que é melhor (simplificando o movimento relativo) e ainda permite manter uma lista conveniente de objetos.
8119 ChrisE
Uma melhoria adicional é manter em cada objeto um sinalizador sujo e uma transformação de tudo acima dele na hierarquia de transformações. A transformação pai-mundo em cache (essa transformação que acabei de mencionar) significa que, para qualquer atualização de posição do objeto, você só precisa fazer uma multiplicação de matriz (a transformação relativa para pai com a transformação pai-para-mundo). Sempre que você atualiza a conversão relativa, também atualiza seu sinalizador sujo.
8119 ChrisE
3

Há uma boa razão para não usar o gráfico de cena como o recipiente para objetos do jogo, e isso é instanciação. Se você deseja reutilizar alguns recursos, faz muito mais sentido referir-se ao recurso do gráfico de cena várias vezes do que ter várias cópias reais.

Jari Komppa
fonte
@Jari: +1 para uma boa resposta. Pelo que entendi, a abordagem geral é ter um contêiner separado de malhas renderizáveis. O gráfico de cena normalmente se refere ao contêiner de malhas renderizáveis, para obter informações sobre a forma do objeto. Além disso, cada nó do gráfico de cena contém informações de transformação. Jari, com esse design, gostaria de saber, se ainda é recomendável ter um contêiner std :: vector <> separado para nós do jogo, digamos com o objetivo de classificar mais rapidamente ou por outros motivos ..
Bunkai.Satori
2
Depende - pode ser útil ter várias listas lineares de nós para um processamento mais rápido de IA, física, qualquer que seja. Mas eu iria lá depois de ver se há algum problema.
Jari Komppa
Portanto, para concluir, deve ser aceitável que o começo tenha apenas um SceneGraph, que conteria todos os objetos na cena. Você pode aconselhar, se câmeras, luzes e gatilhos também devem estar no gráfico de cena?
Backai.Satori
Tudo o que é afetado pela hierarquia de transformação deve estar no gráfico de cena, mas eu ainda não daria a propriedade ao gráfico de cena, mas os armazenaria em outro lugar para um processamento mais fácil (animação, física, etc.).
Jari Komppa
Jari entendido. Obrigado. Começarei com uma versão menor e adicionarei outros contêineres para facilitar o processamento posteriormente, conforme necessário.
Bunkai.Satori
2

Separar seu modelo de objeto e modelo de exibição (seu gráfico de cenário) geralmente é uma boa idéia.

Veja este artigo sobre o assunto.

Entre muitas coisas, isso permitirá o uso de pools de objetos. O que pode ser essencial para o gerenciamento eficiente da memória.

Nailer
fonte
+1 para uma boa contribuição. Eu examinei o artigo. Ele discute os padrões de programação e, se eu entendi corretamente, o Object Model manteria a lista de objetos da cena organizada em uma espécie de container std: vector <>, enquanto o ViewModel conteria os mesmos objetos organizados no Scene Graph? No entanto, apenas os objetos exibidos atualmente estariam contidos no Gráfico de cena?
Backai.Satori
E quanto a câmeras, gatilhos, luzes? eles também fariam parte do gráfico da cena?
Backai.Satori
@ Bunkai.Satori Bem, você pode potencialmente ter coisas no gráfico de cenário que não são exibidas na tela. Você constrói seu gráfico de cenário e pode executar um algoritmo de seleção no gráfico de cenário antes de renderizar os nós visíveis. As luzes e os gatilhos das câmeras podem existir tanto no modelo quanto no modelo de exibição.
Nailer
obrigado pela sua resposta. Como você mencionou o abate , como é feito na prática? a cena inteira está incluída no gráfico de cenas ou existe apenas a parte visível? Se a cena inteira estiver no gráfico de cenas, o gráfico de cenas é atravessado por quadro para enviar apenas a área visível para a API do OpenGL / DirectX? Duvido que toda a cena seja enviada à API por quadro, pois a parte visível geralmente é inferior a 5% da cena completa. Como alternativa, o gráfico de cena está organizado de alguma forma, para recuperar rapidamente as áreas mais próximas sem deslocamento total da viagem por quadro?
Bunkai.Satori
Coloque toda a sua cena no cenário gráfico. Equilibre o gráfico com base em determinado critério (por exemplo, você pode criar uma oc-tree). Percorra a árvore e determine quais nós são "Visíveis", "Parcialmente visíveis" e "Invisíveis" com base em se as caixas delimitadoras estão no seu modo de exibição. Você pode criar um "gráfico de visibilidade" super leve que basicamente consiste apenas em referências a nós SG e um sinalizador. Após o abate de frustum, você pode atravessar a árvore novamente para fazer o abate de oclusão. Refaça a seleção de todos os quadros ou todos os quadros em que a câmera ou cena foi marcada como "suja".
Nailer