¿Gráfico de escena como contenedor de objetos?

8

El gráfico de escena contiene nodos de juego que representan objetos del juego. A primera vista, puede parecer práctico usar Scene Graph como contenedor físico para objetos en el juego, en lugar de std :: vector <> por ejemplo.

Mi pregunta es, ¿ es práctico usar Scene Graph para contener los objetos del juego , o debería usarse solo para definir enlaces de objetos / nodos de escena, mientras se mantienen los objetos almacenados en contenedores separados, como std :: vector <>?

Bunkai.Satori
fuente
Alguien tiene una idea? Tengo la intención de utilizar Scene Graph para organizar los actores / nodos del juego y luego Vector para realizar varias clasificaciones que deberían ser más rápidas que la clasificación de un árbol SceneGraph de múltiples vías.
Bunkai.Satori
@ Todos: Tengo una pregunta más: ¿SceneGraph contiene todo el mapa, o debería contener solo una parte del mapa, digamos su área visible? Obviamente, el gráfico de escena se actualizará continuamente, a medida que el jugador se mueva sobre el mapa.
Bunkai.Satori

Respuestas:

5

Decidir qué tipo de gestión de escena usar depende en gran medida del tipo de lógica que intente ejecutar. Considere los diferentes consumidores de su escena:

Representación del consumidor

El procesador probablemente solo quiera saber qué es visible actualmente para el usuario en cualquier punto dado. Quiere una jerarquía de volumen delimitador para el sacrificio rápido ( artículo de BVH wiki) para que pueda descubrir que no es necesario dibujar una silla dentro de un bote porque los límites del bote están fuera del tronco de la vista. Esto podría estar incrustado en un octree .

También es posible que desee tener una idea de que la silla está boca arriba dentro del bote, y que el bote está rodando hacia arriba y hacia abajo en algunas olas cuando finalmente aparece. De esa manera, para encontrar las coordenadas mundiales finales de los vértices de la silla, puede concatenar la silla y las transformaciones del barco y terminar con esto (esto también facilita su trabajo como programador).

Sin embargo, otra forma de ver este problema es que el procesador probablemente esté ejecutando una buena carta y, en última instancia, solo quiere un montón de triángulos ordenados para minimizar la textura, el sombreador, el material, la iluminación y los cambios de estado de transformación. Esto último probablemente lo ayudará más que un BVH, en cuanto a rendimiento.

Game Logic Consumer

La lógica del juego probablemente solo quiere una lista plana de cosas que pueden comunicarse entre sí mediante un sistema de mensajería, por lo que un std :: vector probablemente esté bien.

El juego también puede querer una forma de hacer un seguimiento de quién está más cerca de qué, por lo que algún tipo de información [vecino más cercano] [3] podría ser útil en ese caso. Esto también puede ser proporcionado por un BVH, pero tener que subir y bajar el gráfico puede ser molesto.

El juego podría incluso querer saber que cuando mueve A, el elemento B de A también debería moverse ... en cuyo caso volvemos a una especie de jerarquía de transformación.

Consumidor de Física

La física del juego puede querer tener una [representación especial] [4] de espacios interiores para una detección de colisión muy rápida. Alternativamente, podría usar algún tipo de octree o [hashing espacial] [5] para encontrar eficientemente cosas que podrían colisionar.

Ninguna de las estructuras de datos de física anteriores se parece realmente a un "gráfico de escena" en el sentido de Java3D.

Consumidor de audio

Un motor de audio solo quiere geometría, quizás un conjunto potencialmente visible (audible), o algún tipo de jerarquía de volumen delimitador para calcular la atenuación y la propagación del sonido. Nuevamente, no es realmente un tipo de gráfico de escena normal, aunque puede ser un gráfico de geometría en su escena.

En última instancia ... ... realmente depende de las necesidades exactas de su aplicación. Para empezar, sugiero usar una lista plana y ver dónde surgen sus problemas. Incluso podría intentar una lista plana con una jerarquía de transformación, porque ese es quizás el único tipo de escena útil por razones distintas a la eficiencia.

¡Buena suerte!

ChrisE
fuente
@ChrisE: +1 por excelente pregunta. En mi opinión, esta es la mejor respuesta aquí, permítanme marcarla como la Respuesta aceptada . Si entendí correctamente, probaste que Scene Graph no siempre es la solución definitiva. Especialmente en Game Logic, ¿ves un gráfico de escena como la forma correcta de actualizar la transformación (escala, traducción) de objetos relacionados? Ejemplo, una silla está en el bote, ¿entonces las coordenadas de la silla se actualizan a medida que el bote se mueve? Alternativamente, ¿ve alguna solución mejor para la actualización de coordenadas relativas?
Bunkai.Satori
@ChrisE: además de lo mencionado anteriormente, en el caso de que se use Scene Graph, ¿puede usarse como el único soporte de objetos para la escena o recomendaría tener otro contenedor (digamos std :: vector <>) además de Scene ¿Grafico?
Bunkai.Satori
2
En realidad estaba en el proceso de sugerir exactamente eso. Intentaría mantener una jerarquía de transformación (aquí, un árbol n-ario donde los nodos tienen un padre y varios hijos, y no se comparten hijos entre los nodos) con cada nodo que contiene una referencia al objeto del juego. Los objetos del juego se mantienen en una matriz plana y separada (por ejemplo, std :: vector).
ChrisE
Durante la actualización, puede avanzar sobre la lista plana y realizar la lógica del juego, y cada vez que se produce un movimiento relativo (por ejemplo, la silla se empuja hacia adelante en el bote), usa la jerarquía de transformación para encontrar la transformación final de local a mundo caminando hasta los padres de tu objeto y concatenando sus transformaciones. Esto utiliza la jerarquía de transformación para lo que es mejor (simplificar el movimiento relativo), y aún le permite mantener una lista conveniente de objetos.
ChrisE
Una mejora adicional es mantener en cada objeto una bandera sucia y una transformación de todo lo que está arriba en la jerarquía de transformación. La transformación en caché de padre a mundo (esa transformación que acabo de mencionar) significa que para cualquier actualización de posición de objeto solo tiene que hacer una multiplicación de matriz (la transformación relativa a padre con la transformación de padre a mundo). Cada vez que actualiza la transformación relativa, también actualiza su bandera sucia.
ChrisE
3

Hay una buena razón para no usar el gráfico de escena como contenedor de objetos del juego, y eso es una instancia. Si desea reutilizar algunos recursos, tiene mucho más sentido referirse al recurso de su gráfico de escena varias veces que tener varias copias reales.

Jari Komppa
fuente
@Jari: +1 por buena respuesta. Según tengo entendido, el enfoque general es tener un contenedor separado de mallas renderizables. El gráfico de escena normalmente se refiere al contenedor de mallas renderizables, para tomar información de la forma del objeto. Además de eso, cada nodo de gráfico de escena contiene información de transformación. Jari, que tiene ese diseño, me gustaría saber, si todavía se recomienda tener un contenedor std :: vector <> separado para los nodos del juego, digamos con el fin de una clasificación más rápida u otras razones ...
Bunkai.Satori
2
Depende: puede ser útil tener varias listas lineales de nodos para un procesamiento más rápido de IA, física, lo que sea. Pero iría allí después de ver si hay un problema de lo contrario.
Jari Komppa
Por lo tanto, para concluir, debería ser aceptable para el comienzo tener solo un SceneGraph, que contendría todos los objetos en la escena. ¿Puede aconsejarme si las cámaras, las luces y los disparadores también deberían estar en el gráfico de la escena?
Bunkai.Satori
Todo lo que se ve afectado por la jerarquía de transformación tiene que estar en el gráfico de la escena, pero todavía no le daría la propiedad al gráfico de la escena, sino que los almacenaría en otro lugar para un procesamiento más fácil (animación, física, etc.).
Jari Komppa
Entendido Jari. Gracias. Comenzaré con una versión más pequeña y agregaré otros contenedores para un procesamiento más fácil más tarde según sea necesario.
Bunkai.Satori
2

Por lo general, es una buena idea separar su modelo de objeto y el modelo de vista (su scenegraph).

Ver este artículo sobre el tema.

Entre muchas cosas, esto permitirá el uso de agrupaciones de objetos. Lo que podría ser esencial para una gestión eficiente de la memoria.

Fabricante de clavos
fuente
+1 por buena contribución. Repasé el artículo. Discute los patrones de programación, y si entendí correctamente, ¿el Modelo de objetos mantendría la lista de objetos en la escena organizada en una especie de contenedor std: vector <>, mientras que ViewModel contendría los mismos objetos organizados en el Gráfico de escena? Sin embargo, ¿solo los objetos que se muestran actualmente estarían contenidos en el Gráfico de escena?
Bunkai.Satori
¿Y qué hay de las cámaras, disparadores, luces? ¿Serían parte del gráfico de escena también?
Bunkai.Satori
@ Bunkai.Satori Bueno, podrías tener cosas en la escena que no se muestran en la pantalla. Construye su scenegraph, luego puede ejecutar un algoritmo de eliminación en el scenegraph antes de representar los nodos visibles. Las luces y los disparadores de las cámaras podrían existir tanto en el modelo como en el modelo de vista.
Clavador
Gracias por su respuesta. Como usted ha mencionado el sacrificio , ¿cómo se hace en la práctica? ¿Se incluye toda la escena en el gráfico de escena o solo hay una parte visible? Si toda la escena está en el Gráfico de escena, ¿se recorre todo el gráfico de escena por fotograma para enviar solo el área visible a la API OpenGL / DirectX? Dudo que toda la escena se envíe a la API por cuadro, ya que la parte visible suele ser inferior al 5% de la escena completa. Alternativamente, ¿está organizado el gráfico de escena de alguna manera, para recuperar rápidamente las áreas más cercanas sin viajero completo por cuadro?
Bunkai.Satori
Pon toda tu escena en el scenegraph. Equilibre el gráfico en función de cierto criterio (por ejemplo, podría hacer un oc-tree con él). Atraviese el árbol y determine qué nodos son "Visibles", "Parcialmente visibles" e "Invisibles" en función de si los cuadros delimitadores son, en su opinión, frustum. Puede crear un "gráfico de visibilidad" súper ligero que básicamente consiste en referencias a nodos SG y una bandera. Después del sacrificio de frustum, puede atravesar el árbol nuevamente para realizar el sacrificio de oclusión. Vuelva a realizar el sacrificio de cada fotograma o cada fotograma donde la cámara o escena se haya marcado como "sucia".
Clavador