Juego de física de tornados: cómo se implementa la aerodinámica en Just Cause 4 (tráfico)

Jacques Kerner es ingeniero de software sénior en Avalanche Studios.


Como si el juego no fuera lo suficientemente loco antes

Introduccion


La serie de juegos Just Cause y Avalanche Studios son conocidos por su tecnología de mundo abierto, que proporciona una jugabilidad variada y emocionante. La última versión del juego, Just Cause 4, agregó los desastres del viento y el clima, que se convirtieron en una novedad en la pila de tecnologías que profundizan el juego. Pero las condiciones ambientales extremas se concibieron originalmente no solo como una forma de simular un mundo más creíble. La furia de la naturaleza está controlada por las fuerzas del mal que se oponen a Rico Rodríguez. Teníamos la intención de hacer que el viento se manifestara más claramente y las condiciones climáticas extremas no parecían eventos repentinos ajenos a este mundo. Este artículo presenta las técnicas desarrolladas por nosotros para implementar el viento en todas sus manifestaciones desde un punto de vista físico, así como la reacción de todos los objetos.

[Debajo del gato unos archivos GIF de 120 MB]


Tormenta tropical JC4 - Concepto temprano (Volta)

Una oferta que no podemos rechazar.


A medida que el desarrollo de Just Cause 3 estaba a punto de completarse, la mayoría del equipo cambió a la preproducción de Just Cause 4, y el pequeño núcleo tuvo que trabajar en parches para JC3 y contenido descargable ("DLC"). Hamish Young y yo, programador principal y diseñador principal de vehículos, nos centramos en el DLC Mech Land Assault. Se suponía que éramos el diseñador líder de física (y la mecánica del jugador) y el programador líder de física JC4, pero el DLC nos absorbió por completo en el momento en que se creó el diseño de la nueva serie de franquicias, se determinaron sus características atractivas y funciones importantes. Esta vez se creó un prototipo a gran escala para probar la nueva mecánica básica y la reacción de Rico al viento. Se redactó un borrador de la trama, y ​​el editor Square Enix aprobó la dirección de desarrollo inicial. Lo único que quedaba era dominar el concepto. Pero, ¿cómo hacer esto sin comprometer el rendimiento? Tan pronto como comenzamos el proyecto, atacamos el problema desde dos frentes: 1. establecimos límites amplios para evitar los peores escenarios (spoiler: no tuvimos éxito) 2. lidió con diversas manifestaciones de condiciones climáticas extremas y, en particular, vientos huracanados, cree un sistema que proporcione un comportamiento realista, pero que se adapte bien al número y densidad de objetos deseados.


Tormenta de arena en JC4 - Arte conceptual temprano (Volta)

Control de daños


El cuello de botella en la simulación en tiempo real, y especialmente en los juegos de mundo abierto, es la cantidad de cuerpos físicos en colisión. Los principales gastos surgen debido al cálculo de colisiones de muchos cuerpos móviles que chocan entre sí y con un entorno estático (relieve, edificios). Es por eso que los motores físicos como Havok separan los cuerpos activos e inactivos. Los cuerpos activos son controlados por colisiones con otros cuerpos y requieren un costo computacional completo. Si el cuerpo activo no se mueve durante varios cuadros, entonces el motor físico lo marca como inactivo, y desde ese momento puede ser completamente ignorado hasta que el cuerpo activo que se acerca lo "despierte". Tales cuerpos inactivos generalmente descansan en el suelo y ya no se realizan controles de colisión entre ellos y la tierra. Es obvio que la presencia omnipresente de viento en el mundo abierto se convertirá en una amenaza para este sistema, por lo que era importante para nosotros asegurarnos de que el viento permaneciera moderado y puramente cosmético cuando se exponga a grandes áreas, o fuerte y se active físicamente cuando ocurra en pequeños volúmenes y lugares donde la cantidad Los cuerpos potencialmente activos son pequeños. Le hablé de estas limitaciones a nuestro departamento de diseño en las primeras etapas de desarrollo para que no quedara atrapado. Al principio, parecía que los diseñadores habían escuchado y decidido limitar las trayectorias de los fenómenos meteorológicos extremos a rutas de destrucción predeterminadas, dentro de las cuales deberían aplicarse reglas más estrictas para construir el mundo. Y observaron algunas de estas restricciones. Pero la tentación era demasiado grande, y la presión de los colegas que querían hacer que el juego fuera lo mejor posible resultó ser insuperable. ¿Qué estaba pensando? Inmediatamente después de eso, los diseñadores crearon un tornado de varios kilómetros de altura, pasando a través de la capital del país, la parte más densamente poblada de la isla. Este tornado audazmente no solo la mitad del capital, sino también algunos de los programadores desprevenidos que no se adhirieron a esta característica básica del juego demasiado estrictamente.


Ventisca en JC4 - Arte conceptual temprano (Volta)

Enfoque general


En general, la física climática extrema en JC4 requería los siguientes ingredientes:

  • Modelo aerodinámico de arrastre aplicado a todos los objetos dinámicos del mundo, teniendo en cuenta su forma y tamaño.
  • Fuentes de viento que corresponden en forma y distribución a condiciones climáticas extremas (tormenta, tornado), pero que también proporcionan patrones de propagación del viento en todo el mundo.
  • Optimización de los sistemas anteriores para que el juego se ajuste al presupuesto de las cargas informáticas.

Estos tres problemas debían resolverse simultáneamente y lo antes posible. Muchas decisiones de diseño dependían de la posibilidad de implementar los tres aspectos, y durante los primeros meses nos sentimos insatisfechos con los diseñadores que esperaban pacientemente la oportunidad de jugar con el sistema a gran escala.

Primero, creamos un modelo de resistencia aerodinámica. Después de su finalización, cada objeto de repente aprendió a responder de manera bastante realista al viento. Por ejemplo, si algún objeto se cae de un acantilado o es arrojado por una explosión, todos los objetos se ralentizan y giran de manera realista en el aire, lo que ya valió la pena. Pero en ausencia de fuentes de viento, era difícil decir cómo se comportarían en condiciones de viento extremo. Aunque estábamos orgullosos de nosotros mismos y del hecho de que la experiencia y la intuición nos ayudaron a encontrar rápidamente un enfoque para los dos primeros problemas que cumplían con los requisitos de rendimiento, decidimos que tuvimos mucha suerte cuando la primera versión del tornado comenzó a funcionar exactamente como esperábamos. Levantó todos los objetos dinámicos y los giró de una manera bastante realista, sin ocupar todo el tiempo del procesador. El director de JC4, Francesco Antollini, quien a menudo preguntaba sobre la situación del tornado, apareció justo al lado de mi lugar de trabajo y expresó su alivio: creo que perdí la oportunidad de avergonzarlo por dudar de mí; pero en realidad me sentí de la misma manera.

Desde un punto de vista físico, JC4 fue un gran avance en comparación con JC3: es un mundo más denso, lleno, vibrante y hermoso, que es mucho más interesante de destruir. Y todo esto fue posible en las mismas plataformas de destino (XBox One y PlayStation 4). No es sorprendente que la optimización llevara mucho tiempo. Nuestro director técnico Dave Barrett aprovechó de inmediato nuestra ventaja: teníamos los indicadores de rendimiento necesarios para JC3, por lo que el jefe del departamento de desarrollo de motores, Daniel Pieroni, recibió la tarea de determinar qué costos máximos de rendimiento y memoria se pueden usar para cada aspecto técnico. Nos dieron física unos generosos 8,5 ms en 4 subprocesos de 33 ms de tiempo de procesador, asignados para crear un marco con una frecuencia de 30 veces por segundo. Havok ocupó una gran parte de este presupuesto para reconocer posibles colisiones entre objetos, calcular contactos, resolver restricciones e "integrar" el movimiento de todos los cuerpos activos para determinar su posición después de 33 ms de tiempo simulado. Calculé aproximadamente que nuestro presupuesto para todos los cálculos relacionados con la aerodinámica y el viento debería ser de aproximadamente 1 ms en 4 hilos. Básicamente, logramos mantenernos dentro del presupuesto, aunque probablemente sea mejor preguntarle a Daniel sobre esto. La solución presentada a continuación es lo suficientemente rápida en tiempo real cuando se calculan varios cientos de objetos en CPU modernas. Por supuesto, como mucho más, se puede optimizar aún más al adaptarlo para que funcione en la GPU.

En el resto del artículo, hablaré brevemente sobre cómo resolvimos cada uno de los problemas, y para los interesados, presentaré en los apéndices detalles y cálculos matemáticos.


Viento en JC4 - Arte conceptual temprano (Ironklad Studios)

Modelo de resistencia


Nuestro objetivo al crear el modelo de resistencia era evaluar las fuerzas de resistencia y los pares, que se parecerían aproximadamente a las que se aplican a un cuerpo de forma arbitraria en el mundo real. Observe lo poco ambiciosos que estuvimos aquí: nadie exigió un gran realismo. Sin embargo, teníamos algunos requisitos. En primer lugar, las fuerzas de resistencia deben contrarrestar el movimiento del cuerpo. En segundo lugar, la fuerza debe calcularse a partir de la ecuación básica de resistencia aerodinámica, es decir. variar de acuerdo con el área de superficie de la figura y el cuadrado de la velocidad de movimiento a través del aire. Finalmente, de alguna manera, la forma y el tamaño del cuerpo deben tenerse en cuenta para que los objetos con la misma área de superficie pero con formas muy diferentes se comporten de manera diferente. Estuve tentado de simplemente aproximar la forma de cada cuerpo de acuerdo con el paralelogramo que lo describe, pero pensé que se necesitaba algo más, porque era obvio: la forma de muchos objetos puede diferir significativamente de una caja o incluso de una pequeña cantidad de cajas. Mi experiencia previa trabajando con sistemas que se aproximan aproximadamente al volumen de objetos 3D usando voxels o esferas me hizo buscar una mejor solución. Me ofrecieron seleccionar los coeficientes de resistencia para cada objeto manualmente, pero quería evitar una etapa más de ajuste manual en una tubería ya complicada. Por lo tanto, continué buscando una forma automatizada. Y me alegro de no haber retrocedido.

La forma más sencilla de evaluar la presión del viento en cada superficie de la forma de colisión de nuestros objetos es tener en cuenta solo el viento entrante, ignorando toda la circulación de aire alrededor de los objetos y la viscosidad del aire que los rodea. Como si la resistencia del aire consistiera solo en avanzar la masa de aire frente al objeto o, por otro lado, su absorción. Un primer prototipo mostró que este método era lo suficientemente bueno para nuestros propósitos.

El "único" problema era que la suma de las contribuciones de miles de triángulos para cada figura individual durante la ejecución del juego era un orden de magnitud mayor que el nivel de costo requerido. En escenas "pesadas", podríamos alcanzar fácilmente más de 100,000 caras. Sería genial si pudiéramos calcular las fuerzas de antemano. El primer método de "fuerza bruta" consistió en un cálculo preliminar de las fuerzas aerodinámicas y los pares que surgen cuando un cuerpo se mueve a diferentes velocidades en varias direcciones en aire quieto cuando gira a diferentes velocidades angulares en diferentes direcciones. Entonces obtuvimos una tabla de búsqueda de la cual podríamos tomar valores durante la ejecución del juego. Esto se puede imaginar como un túnel de viento virtual, incluido durante la compilación de nuestro contenido, en el que colocamos todos los objetos a su vez y los exponemos a diferentes velocidades de movimiento o rotación, colocando cada objeto en diferentes ángulos, y cada vez midiendo fuerzas y pares.

¿Cómo será esta mesa? Los valores conocidos en tiempo de ejecución son la velocidad lineal y angular del cuerpo, por lo tanto S=5, es decir, solo unos 300 KB por objeto. Y aún así, esto es al menos un orden de magnitud mayor que el consumo de memoria permitido.

Para reducir significativamente el número de muestras, utilicé dos técnicas. En primer lugar, convertí el cálculo a una forma lineal en la suma de contribuciones basadas en el cálculo preliminar de fuerzas y pares por separado solo para un cuerpo en movimiento y solo giratorio. En segundo lugar, aproximé esto a una fórmula analítica para extrapolar valores a velocidades arbitrarias basadas en una reacción calculada previamente y solo a una velocidad de 1 m / sy una velocidad de 1 rad / s. Esto redujo la tabla precalculada a solo 7 KB por objeto. Lamentablemente, para esto tuve que realizar varias aproximaciones. La razón del problema es que, incluso con un modelo muy simple de resistencia, nos enfrentamos al hecho de que las fuerzas aplicadas al cuerpo, es decir, la rotación y el desplazamiento, no son solo la suma de las fuerzas aplicadas individualmente para la rotación y el desplazamiento. Aunque tuve que agregar aproximaciones, logré guardar algunos de los términos causados ​​por una combinación de rotación al moverme, similar al componente Coriolis. La conclusión de la redacción se puede encontrar en el Apéndice 1. Como resultado, en lugar de almacenar directamente las fuerzas y los pares para cada muestra, almacenamos el vector de términos  mathcalA( hatu)utilizado en las fórmulas lineales. Cada muestra corresponde a una unidad de velocidad lineal relativa al aire a 1 m / so una unidad de velocidad angular relativa al aire a 1 rad / s, en cierta dirección. Los componentes de este vector se usan en la fórmula, que también tiene en cuenta las verdaderas velocidades lineales y angulares del objeto en relación con el aire al calcular las fuerzas y los pares que deben aplicarse al objeto. El Apéndice 1 detalla cómo sucede esto.

Para almacenar la tabla de búsqueda, utilizamos un mapa de cubos, es decir un cubo cuyas caras se dividen en cuadrículas de tamaño, digamos 3x3 celdas, como un cubo de Rubik. Almacenamos valores en las esquinas de las celdas, por lo que cada cara puede almacenar valores 4x4. En cada esquina de la celda, calculamos el vector que va del centro del cubo a la esquina, y normalizamos este vector para obtener la dirección de la unidad. Utilizamos este vector de dirección de la unidad como  mathcalA( hatu)para la esquina de la celda Como resultado, obtenemos 6 tablas (una por borde) de 16 elementos con 19 valores flotantes cada uno, que es un poco más de 7 KB, y esto es muy conveniente. Hay formas de reducir aún más el número de muestras, pero con este método es muy fácil interpolar la dirección de la velocidad arbitraria: dado que siempre cae en la celda, siempre es posible usar los valores en las cuatro esquinas de esta celda para realizar la interpolación bilineal para esta dirección específica. La técnica de los mapas cúbicos y la interpolación bilineal es muy utilizada en la representación, por lo que es muy fácil encontrar información al respecto y el código correspondiente.


Figura 1. Mapa cúbico de velocidades unitarias relativas al aire. En esta figura, resalté en rojo una celda separada de un mapa cúbico para ilustrar el principio. Tener velocidad lineal  hat omegaEn relación con el aire, nuevamente tomamos muestras del mismo mapa cúbico para encontrar la celda azul y usamos los 4 coeficientes almacenados en sus esquinas. Luego mezclamos todos los valores de acuerdo con la fórmula del Apéndice 1.

Aunque esto funcionó en la mayoría de los casos, nos encontramos con dificultades para cambiar el centro de masa o la escala de los objetos en tiempo de ejecución. Nuestras soluciones a estos problemas se pueden encontrar en los Apéndices 2 y 3.

Al desarrollar este modelo, no estaba seguro de la cantidad de muestras suficientes para obtener un buen comportamiento de los objetos que se mueven y giran en el aire, por lo que no sabía exactamente si tenía suficiente memoria en el disco durante el tiempo de ejecución. Paralelamente, comenzamos a crear nuevos activos de destrucción para Havok, con cientos de fragmentos de varios tamaños, a veces varios cientos de partes para un activo. Me di cuenta de que algunos de estos activos requerirían la misma cantidad de memoria, como muchos otros activos en total, si cada fragmento tuviera su propio mapa cúbico. El modelo general transmitía bien algunas características únicas de los objetos complejos, pero era demasiado para fragmentos pequeños. Además, no estaba seguro sobre el costo en tiempo de ejecución, y poder volver a un modelo de menor costo era una buena manera de reducir el riesgo. Por lo tanto, encontré una redacción muy compacta (haciendo aproximaciones generosas) basada solo en cuadros delimitadores de objetos. Se puede encontrar en el Apéndice 4.

Volumen del viento


Introdujimos el concepto de volúmenes de viento, respaldando la idea de que un viento de objetos fuertes y de activación física solo puede ocurrir en espacios finitos, y comenzamos a clasificarlos de acuerdo con la forma y distribución del viento. Dividimos los volúmenes de viento en los siguientes tipos principales:

  • Volumen de viento cilíndrico utilizado para ventiscas, tormentas de arena y tormentas tropicales.
  • Volumen de viento de tornado: un conjunto vertical de cilindros centrados en relación con una ranura vertical que se deforma con el tiempo
  • Túneles de viento formados por varias figuras conectadas en forma de cápsula (cápsulas con radios que difieren en diferentes extremos), formando algo así como un "agujero de gusano"

Esta restricción del viento por el volumen final fue criticada varias veces, y en el último momento casi la abandonaron, reemplazándola con un "viento topográfico".Se suponía que el viento en todas partes correspondía con el movimiento de las nubes en la atmósfera superior y proporcionaba al jugador un flujo de aire ascendente cuando se encontraba con una pendiente creciente del terreno. Lo implementamos, pero la falta de una visualización gráfica clara del viento nos obligó a abandonar esta función. Los chicos del departamento de renderizado ya tenían demasiadas tareas para implementar nubes, ríos, cascadas, actualizar a DirectX 12 y mucho más.

En retrospectiva, resultó que las tormentas se convirtieron en los volúmenes de viento más simples, tanto en términos de forma (cilindro) como de distribución del viento (casi unidireccional para una tormenta de arena, o girando alrededor de un eje central para una tormenta de nieve). Por otro lado, los tornados y los túneles de viento resultaron ser más complejos y merecen una explicación más detallada.

Tornado


Teníamos una idea clara y simple de cómo los objetos deberían rotar alrededor de un tornado, pero no estábamos de acuerdo en la distribución de los vientos necesarios para lograr este resultado. En lugar de un debate interminable, personalizamos los diversos componentes del campo de viento en tiempo de ejecución para que Hamish pudiera experimentar con ellos y encontrar rápidamente una opción de trabajo. Un tornado es esencialmente una pila de cilindros horizontales cuyos centros están ubicados en la ranura central, que se deforma con el tiempo. En estos cilindros horizontales, descomponemos el campo de viento del tornado en coordenadas cilíndricas con un componente tangente, un componente radial y un componente vertical. Cada componente se puede ajustar usando curvas variables.


2. — . , , . . , .

Al igual que con muchas otras características, y como suele ser el caso en nuestra industria, Hamish y yo a menudo pasamos de la configuración al código hasta que el resultado fue lo suficientemente bueno. Hamish ajustó las curvas a su gusto, arrojando docenas de contenedores de 12 metros a lo largo del tornado para observar su comportamiento. Utilizó la velocidad máxima registrada del viento (alrededor de 230 mph) para el tornado. Después de un tiempo, Hamish descubrió que su configuración era complicada porque era necesario hacer que el viento en todas partes correspondiera a un simple movimiento de rotación, pero al mismo tiempo atraía objetos hacia el centro. La velocidad angular ya era parte del campo, no solo empujando, sino también girando objetos en un tornado. Esto aseguró que, por ejemplo, los objetos atrapados en el centro rotarían en su lugar, como quisiéramos.Por lo tanto, Hamish pidió comenzar con el viento, en todas partes correspondiente a esta velocidad angular en el centro, es decir, comenzar con el campo de velocidad de un campo de rotación ideal, en el que se puede agregar un campo de viento personalizado. Después de esta última configuración, las curvas comenzaron a consistir en los siguientes componentes:

  • R(d)- factor de la componente radial (movimiento radial)
  • T(d)es el factor de la componente tangente (movimiento radial)
  • V(d)- factor de la componente vertical (movimiento radial)
  • H(h)- multiplicador de componentes horizontales (movimiento vertical)
  • Φ(h)- factor de la componente vertical (movimiento vertical)

Donde hes la altura sobre el fondo del tornado, yd es la distancia desde el centro. La velocidad del viento del tornado viene dada por la ecuación:

V→(d,h)=[VtT(d)H(h)+Ωd]t^+VrR(d)H(h)r^+VuV(d)Φ(h)up^


Cuando los objetos se aceleran a la velocidad tangente del tornado a una distancia dada, el componente tangente de las fuerzas de resistencia del aire es esencialmente cero, porque tanto el aire como el objeto se mueven a lo largo de la tangente al unísono. El resto de la velocidad del viento atrae al objeto hacia adentro, ya que el planeta atrae a los satélites para doblar su trayectoria para que permanezca en órbita; Además, los objetos se empujan hacia arriba para alcanzar mayores alturas. Empujar objetos hacia arriba es la optimización de rendimiento más importante, ya que evita cálculos costosos de los contactos de cientos de objetos y la tierra. También ayuda que con la altura del tornado aumente el radio mediante la distribución espacial de objetos para reducir la probabilidad de su colisión y cálculo de contacto. Un tornado en el mundo real se forma por el intercambio de aire cuando una capa de aire frío está encima de una capa de aire caliente.El aire caliente se eleva como un remolino alrededor del centro de un tornado, que es el aire frío que baja. Por lo tanto, en principio, en el centro del embudo, la velocidad del viento debe estar fuertemente dirigida hacia abajo. Como puede ver, esto no se implementa con nosotros para reducir la probabilidad de empujar objetos hacia el suelo y arrastrarlos a un tornado, de lo contrario, esto aumentaría el costoso cálculo de colisiones.


3. (), (). ΩdEl campo giratorio del viento con el que comenzamos, para comprender mejor si es necesario un campo adicional para la operación adecuada del tornado. En la versión de la derecha, se agrega un campo giratorio. En la distancia vemos un viento muy rápido, en cualquier punto dirigido a unos 45 grados del radio. La sección vertical de la izquierda muestra cuánto debe arrastrar el tornado hacia el centro. Luego hay un pequeño intervalo de transición en el que casi no hay viento, y detrás de él hay un fuerte campo giratorio en el centro. La fuerza del campo de viento se muestra en color, cuanto más rojo, más fuerte.


Figura 4. Líneas de los caminos alrededor del campo de viento de tornado: la estría central de la línea.

Un tornado directo parece aburrido. Para deformarlo, utilizamos 2 splines cúbicas conectadas por los extremos, 3 puntos de control de los cuales están en órbita y se mueven a diferentes velocidades alrededor de una línea vertical imaginaria. El perfil de tornado resultante cambia con el tiempo, por lo que cambia lentamente de la forma S a la forma C, y viceversa. El Apéndice 5 detalla cómo creamos splines. Curiosamente, el tornado en modo deformado no funcionó tan bien. Los objetos que circulaban en la órbita de un tornado directo ahora se dispersaron tan pronto como la división central del tornado se alejó de ellos, y tristemente cayeron al suelo. Para solucionar este problema, agregamos otro término a la velocidad debido a la deformación del tornado. Al final, esta deformación debería surgir principalmente debido al movimiento del aire, y nos pareció natural agregar este componente. Esto resolvió el problema maravillosamente, dándonos líneas de ruta muy similares a la imagen a continuación.


Figura 5. Líneas de caminos alrededor del campo de viento del tornado: la estría central se dobla con el tiempo


Figura 6. Un ejemplo de un tornado en un juego, destruye y absorbe todo a su paso. Este es el depurador visual Havok (VDB), una herramienta extremadamente útil que nos permite observar elementos simulados.

Túneles de viento


Los túneles de viento han sido diseñados para proporcionar control físico del viento en partes del mundo, como cañones y cuevas, así como columnas de humo frente a enormes ventiladores industriales y cañones de viento. Se pueden usar para guiar al jugador en ciertos espacios o misiones. Nuestros primeros prototipos utilizaron un cilindro tradicional con un campo vectorial uniforme de velocidad constante paralelo al eje de rotación del cilindro. Colocar todos estos cilindros en la escena fue una tarea minuciosa, por lo que en su lugar utilizamos una spline cúbica de Bezier alrededor de la cual se estira un círculo de radio variable. Esta forma se aproxima dividiendo la estría central en figuras en forma de cápsula, es decir. en cápsulas con diferentes radios alrededor de los bordes. El campo de velocidad en ellos también ha sufrido algunos cambios. Inicialmente, el viento en el túnel era tangente a la estría central. Establecimos las velocidades del viento en cada punto de control de la spline, y se interpolaron de un punto de control a otro a lo largo de un segmento de spline. Sin embargo, Joshua Espinosa (el diseñador que trabajó en los túneles de viento y los movimientos del jugador sobre ellos) pronto descubrió que necesitaba dos componentes más. Un componente es el flujo ascendente, que le da al jugador una elevación artificial adicional, siempre apuntando hacia arriba. Llamamos al otro componente "retracción", empuja al jugador hacia la ranura central, pero sobre todo en los bordes del túnel, cayendo al centro a cero. Finalmente, el límite de reducción en la parte externa del túnel aseguró una transición suave desde la parte externa hacia la parte externa del túnel. El grosor de este límite se especifica como un porcentaje del radio; Actúa a lo largo de todo el túnel de viento.


Figura 7. Túnel de viento dividido en una secuencia de figuras superpuestas en forma de cápsula. La separación se produce cuando cambia la dirección de la spline, o cuando ya no es posible realizar una interpolación longitudinal lineal de radio (A) o velocidad del viento (B). Calculamos la segunda derivada de estas variables a lo largo de la spline para determinar cuándo dividir.


Figura 8. Túneles de viento editados en el Motor Apex. El túnel de viento se divide en cápsulas de la manera correcta, dependiendo de la spline, los cambios en el radio y la velocidad del viento a lo largo de la spline. Como se indica en la siguiente sección, también puede ver la separación espacial que clasifica las figuras en forma de cápsula en curvas de Morton. Estos cálculos son lo suficientemente rápidos para actualizaciones en tiempo real; Además, puede interactuar rápidamente con el túnel de viento para probarlo. La herramienta de edición se realizó al reelaborar algunas partes de la herramienta de creación de ríos con la adición de la representación de depuración.


Figura 9. Un ejemplo de un túnel de viento largo que permite que un jugador se mueva río arriba a una montaña. La corriente del río empuja a Rick hacia el mar, y el viento puede regresarlo rápidamente dentro de la tierra en la cima del mismo río. El departamento de mecánica del jugador notó que los vientos laterales de Rico eran demasiado fuertes, por lo que la influencia principal del viento es acelerar al jugador (con viento suave) o frenar (viento en contra) y darle un impulso adicional (componente aguas arriba).


Figura 10. Rico en traje de alas en el mismo túnel de viento. Aquí el jugador no controló la dirección. Al principio, Rico pierde altitud hasta que alcanza la parte exterior del túnel de viento, lo que gradualmente disminuye su declive. Luego, la parte central crea un flujo ascendente suficiente para vencer la gravedad y la acelera rápidamente por el cañón. Joshua Espinosa, Hamish Young y Rickard Granfeld desarrollaron el código JC3 Wingsuit para una interacción adecuada con el viento.

Optimización de solicitud de viento


Con el potencial de cientos de cuerpos activos, calcular el viento local en su posición debería ser un proceso rápido. Comenzamos a optimizar las consultas calculando el AABB (cuadro de delimitación del eje alineado) para cada volumen de viento y almacenándolos en una matriz compacta. Esto permite el rechazo de la fuerza bruta porque es posible verificar rápidamente la posición con respecto a cada AABB sin errores de caché. En cada cuadro AABB, los volúmenes de viento en la matriz se actualizan para prepararse para la solicitud.

Si la posición está dentro del volumen de la tormenta, entonces calculamos directamente el efecto del viento usando una forma cilíndrica. Para un tornado, debe hacer más cálculos, porque en la parte superior es mucho más ancho que en la parte inferior, mientras que la mayor densidad de objetos se encuentra en la parte inferior. La solución AABB no corta muy bien los objetos cerca del tornado, por lo que utilizamos cilindros apilados uno encima del otro. Transmiten la forma del tornado mucho más cerca y se usan para recortar objetos antes de calcular el viento. La última optimización de tornado fue evitar proyectar la posición de consulta en la spline central. Esto fue posible porque aunque el tornado spline se interpola en puntos 3D y, por lo tanto, es una curva 3D paramétrica, en la práctica los puntos de control interpolados por él están distribuidos uniforme y secuencialmente a lo largo de la vertical, lo que nos da una curva bastante simple. En general, proyectar un punto en una spline 3D o encontrar un punto en esa spline con la misma altura requiere una búsqueda a lo largo de esa spline. Pero en cambio, decidimos cambiar la forma en que se muestrea la spline usando la altura sobre el fondo del tornado como parámetro de muestreo para la spline misma. Esto cambia ligeramente la forma de la spline, pero la spline aún pasa a través de los puntos de interpolación. Pero al mismo tiempo, para encontrar un punto en la ranura a la misma altura, se reduce a transferirle la altura de la posición de solicitud, seguido de fijar la altura del punto en la altura de la solicitud. Para los puntos de control ubicados de manera desigual a lo largo del eje vertical, la diferencia es notable, pero cuando están ubicados de manera uniforme, apenas es visible. También podríamos cambiar la forma en que se construye la curva central utilizando la función de altura cúbica en lugar de la curva paramétrica, pero, como muchas otras optimizaciones, esta apareció demasiado tarde.

Los túneles de viento también requirieron optimización, porque ni siquiera se consideró la proyección de cada punto de consulta en la ranura central de cada túnel de viento. Afortunadamente, logramos aprovechar la tecnología implementada simultáneamente para los ríos por Engin Silasun: una base de datos espacial dispersa. Dividimos el espacio en 32 O( log(n)). Si la celda no está en la base de datos espacial, entonces no hay viento en el punto de consulta causado por túneles de viento. Si se encuentra la celda, entonces debe realizar una verificación más costosa. Además, esta verificación debería ser bastante rápida, por lo que cortamos los túneles de viento a figuras en forma de cápsula. En el caso general, se usan cápsulas porque es posible calcular la distancia a su segmento central a bajo costo. Las figuras en forma de cápsula son un poco más caras, pero aún más rápidas que encontrar la distancia más corta a una spline cúbica. Otra propiedad de un sistema espacialmente holístico de túneles de viento es que podemos recordar el índice de celda de un determinado objeto ubicado en el marco anterior y usarlo como una pista para acelerar la consulta en el siguiente marco, porque lo más probable es que ya esté en este o en sus alrededores. celular.


Figura 11. Las figuras en forma de cápsula de los túneles de viento se ingresan en una base de datos espacial dispersa de acuerdo con las celdas que cruzan. El resultado es una matriz de 9 celdas, cada una de las cuales tiene solo unas pocas figuras en forma de cápsula.

En conclusión


La combinación de las técnicas que utilizamos ha demostrado ser altamente efectiva. Por sí mismas, estas técnicas se utilizan activamente en la programación. La mayor parte del trabajo radica en su selección y en asegurar su colaboración adecuada para resolver el problema actual. Esto es típico para la programación de videojuegos: está lleno de pequeños problemas que requieren soluciones simples pero confiables.

El modelo de resistencia al aire está extremadamente simplificado y no refleja algunas propiedades importantes del flujo de fluido real. Por ejemplo, una hoja en un ángulo de 45 grados generará más elevación que en nuestro modelo aproximado. Pero lo bueno de esto es que las fuerzas y los pares no se calculan en tiempo de ejecución, y una solución con un mapa cúbico evita una simulación más detallada. De hecho, verificamos los cálculos de fuerzas y pares generados en todo el mapa cúbico del objeto de prueba (un automóvil antiguo de JC4) usando el software de código abierto de dinámica de fluidos computacional (OpenFOAM). La comparación mostró que no estábamos demasiado lejos de los resultados correctos, pero la "forma" de los mapas cúbicos era diferente, y espero que difiera aún más para los objetos en forma de ala. Sin embargo, tomó varias horas calcular el software, por lo que es obvio que tal solución no es adecuada para usar en todos los objetos. Nuestro método tomó menos de un segundo por objeto. Pero creo que sería muy interesante para los juegos basados ​​en la física tener coeficientes aerodinámicos rápidos pero realistas para todos los objetos. Supongamos que Rico pudiera recolectar objetos en enormes bumeranes. Jugué brevemente con esta idea, observando la rápida caída y rotación de las semillas de helicóptero de arce, y creé un modelo en Maya para ver qué pasa. El resultado resultó ser mejor de lo esperado, y el objeto realmente giró lentamente cuando cayó. Pero me parece que para una rotación más rápida será necesario mejorar significativamente el modelo de resistencia al aire. Como sucede a menudo, simplemente no tuvimos suficiente tiempo.


Figura 12. Izquierda: todas las orientaciones de un automóvil petrolero antiguo de Just Cause 4, colocado en un túnel de viento virtual para llenar un mapa cúbico con una cuadrícula de 5x5 en cada cara. Derecha: los resultados visualizados de Paraview para dos orientaciones, en un ángulo arriba (arriba) y detrás (abajo). El rojo indica alta presión, el azul indica baja presión, las líneas indican flujos.

Los tornados y las tormentas funcionaron de manera muy efectiva. La deformación del tornado aún se puede mejorar. Si pasáramos más tiempo en esto, probablemente podríamos hacer tornados de agua (por supuesto, con tiburones en lugar de vacas), remolinos o tornados ardientes. Tuvimos otra idea: desarrollar un cañón que creara un mini tornado.

Los túneles de viento se han utilizado en diferentes partes del mundo para controlar el viento en una isla, como cañones, misiones, alrededor de algunas bases militares. Ayudan al jugador a cruzar las vastas extensiones de nuestro mundo abierto con vientos ascendentes ubicados estratégicamente. Pero creo que sería mejor utilizar la idea del viento topográfico, que no tuvimos tiempo de implementar. Sería más racional implementarlo primero, nos daría un viento sistemático omnipresente que casi no requiere ajuste, y los túneles de viento proporcionarían un control local sobre las desviaciones del mismo.

Y, finalmente, era una idea lógica usar barreras de viento como mecánica de juego. Implementamos un prototipo jugable de obstáculos, que se mostró dentro del equipo, pero lo abandonamos por falta de tiempo para la implementación correcta. Su física era solo una parte del costo total de esta característica, que supuestamente debía ser respaldada por la mayoría del equipo de desarrollo.

Pero nada puede distraerme de lo orgulloso que estoy de lo que logramos hacer en JC4. Nuestra visualización de condiciones climáticas extremas y, en particular, tornados, combinados con la capacidad de Rico de moverse en el espacio, hicieron posible crear un juego absolutamente único y sobresaliente. Espero que hayas disfrutado jugando JC4 tanto como nosotros cuando lo creamos.


Apéndice 1: Modelo de resistencia del aire


Vemos el cuerpo  mathcalBdefinido por la malla Ti,i en[0,N−1].


Figura 13. El cuerpo i en[0,N−1].

Considera un triángulo  vecVi:

 vecVi= vecV+ vec Omega times vecOCi=Vi  hatvi



Figura 14. Triángulo y velocidad en su centro.

Ahora necesitamos escribir fuerza elemental  vecFiactuando en este triángulo. Es aquí donde debemos tener en cuenta nuestros requisitos:

 vecFi=−Ai Vi ( vecVi cdot hatni)  hatni


Esto cumple bien con los requisitos, ya que la fuerza casi siempre se dirige hacia el lado contra la dirección del movimiento, proporcional al área de superficie del triángulo y proporcional al cuadrado de la velocidad del triángulo en relación con el aire. Para que la fuerza actúe sobre todo el cuerpo, es suficiente para nosotros resumir estas fuerzas:

 vecF= sum vecFi= sum−Ai Vi ( vecVi cdot hatni)  hatni$


Mientras nos esforzamos por reducir todo a 1 m / sy 1 rad / s, reescribamos con  hat omega:

 vecF= sum−Ai  |V hatv+ Omega hat omega times vecOCi |(V hatv+ Omega hat omega times vecOCi) cdot hatni  hatni


Y ahora la primera gran aproximación:

 |V hatv+ Omega hat omega times vecOCi | aprox.V+ Omega | hat omega times vecOCi |$


Esto es equivalente a aproximar la longitud de la hipotenusa de un triángulo por la suma de las longitudes de sus dos lados. Esta aproximación también se conoce como "distancia de cuadra de la ciudad" (distancia de Manhattan). Cuando estaba trabajando en esta tarea, estaba en Manhattan, por lo que sería una tontería no usarla. Entonces tenemos lo siguiente:

 vecF= sum−Ai (V+ Omega | hat omega times vecOCi |)(V hatv+ Omega hat omega times vecOCi) cdot hatni  hatni


Descomponemos:

 vecF=V2 sum−Ai hatv cdot hatni hatni+ Omega2 sum−Ai | hat omega times vecOCi |( hat omega times vecOCi) cdot hatni hatni+V Omega sum−Ai( hat omega times vecOCi) cdot hatni hatni+ OmegaV sum−Ai | hat omega times vecOCi |( hatv cdot hatni) hatni


Al principio, esto puede parecer intimidante. Pero luego te das cuenta de que esto es lo que estábamos buscando. Tenga en cuenta que solo se encuentran cantidades  | hat omega times vecOCi |con su valor promedio entre todos los triángulos:

 | hat omega times vecOCi | Avgpromedio( | hat omega times vecOCi |)i in[0,N−1]


Denotémoslo por  hat omega. Ahora finalmente podemos escribir:

 vecF=V(V+ Omega  overlinevr( hat omega)) vecFt( hatv)+ Omega2 vecFr( hat omega)+V Omega vecFc( hat omega)


donde:

\ begin {align *} \ vec {F} _t (\ hat {v}) & = \ sum {-A_i \ hat {v} \ cdot \ hat {n} _i \ \ hat {n} _i} \\ \ vec {F} _r (\ hat {\ omega}) & = \ sum {-A_i \ | \ hat {\ omega} \ times \ vec {OC_i} \ | (\ hat {\ omega} \ times \ vec { OC_i}) \ cdot \ hat {n} _i \ \ hat {n} _i} \\ \ vec {F} _c (\ hat {\ omega}) & = \ sum {-A_i (\ hat {\ omega} \ veces \ vec {OC_i}) \ cdot \ hat {n} _i \ \ hat {n} _i} \\ \ overline {v_r} (\ hat {\ omega}) & = {1 \ over N} \ sum {\ | \ hat {\ omega} \ times \ vec {OC_i} \ | } \ end {align *}


Momento de estas fuerzas en relación con el punto Oose puede obtener de manera similar. Y como resultado, obtenemos lo siguiente:

 left. vecM right|O( hatv, hatw)=V(V+ Omega  overlinevr( hat omega)) vecMt( hatv)+ Omega2 vecMr( hat omega)+V Omega vecMc( hat omega)


donde:

\ begin {align *} \ vec {M} _t (\ hat {v}) & = \ sum {-A_i \ hat {v} \ cdot \ hat {n} _i \ (\ vec {OC_i} \ times \ hat {n} _i)} \\ \ vec {M} _r (\ hat {\ omega}) & = \ sum {-A_i \ | \ hat {\ omega} \ times \ vec {OC_i} \ | (\ hat {\ omega} \ times \ vec {OC_i}) \ cdot \ hat {n} _i \ (\ vec {OC_i} \ times \ hat {n} _i)} \\ \ vec {M} _c (\ hat {\ omega}) & = \ sum {-A_i (\ hat {\ omega} \ times \ vec {OC_i}) \ cdot \ hat {n} _i \ (\ vec {OC_i} \ times \ hat {n} _i)} \ end {align *}


Dadas las definiciones anteriores, ahora podemos formar un vector  mathcalA( hatu):

 mathcalA( hatu)= beginbmatrix vecFt( hatu) vecFr( hatu) vecFc( hatu) vecMt( hatu) vecMr( hatu) vecMc( hatu) overlinevr( hatu) endbmatrix


Este es un vector de 19 valores y nos referimos a la tabla de muestra  hatw, pero podemos encontrar valores bastante cercanos y luego usarlos directamente o usarlos para interpolar la salida. Y en esta etapa, entra en juego el mapa cúbico descrito en el artículo.

Apéndice 2: centro de masa


Puede observar que los valores que se muestran arriba se calculan en relación con un punto arbitrario Pi. La fuerza total que actúa sobre el cuerpo es simplemente la suma de todas las fuerzas:

 vecF= sum vecfi



Momentos Ose establecen como:

 left. vecmi right|O= vecOPi times vecfi


y el momento total de estas fuerzas en relación con el punto Oes igual a:

M→|O=∑m→i|O=∑OPi→×f→i


Ahora es solo una definición matemática, una fórmula que no se puede usar directamente para cambiar el movimiento del cuerpo, porque el centro de gravedad Gen esta fórmula por el teorema de Schal es igual a:

M→|O=∑(OG→+GPi→)×f→i=∑OG→×f→i+∑GPi→×f→i


Reconocemos el momento de las fuerzas con respecto a F→, por lo tanto:

M→|O=OG→×F→+M→|G


Y es muy útil para nosotros si calculamos la fuerza total F→no cambió y aplicó el siguiente par al centro de masa:

M→|G=M→|O+GO→×F→


Al principio, decidí tomar el origen del cuerpo como un punto Oen el centro del paralelogramo delimitador del cuerpo, que aún debe estar cerca del centro de masa y localizar el muestreo del viento en el lugar más lógico en relación con el cuerpo.

Apéndice 3: Escalado


Otro defecto apareció cuando se introdujeron globos en el juego. Estas bolas son cuerpos esféricos, cuyo tamaño puede variar con un factor de 5 o 10. Como en el caso del centro de masa, era demasiado costoso volver a calcular las propiedades aerodinámicas en el tiempo de ejecución. ¿Es posible derivar una fórmula analítica?


Figura 15 Cuerpo OsCsi→=s OCi→

Considere una vez más el cuerpo , pero ahora para un objeto escalado. Obtenemos:F→

Fs→=V2∑−Aiv^⋅n^in^i+Ω2∑−Ai‖ω^×OCsi→‖(ω^×OCsi→)⋅n^in^i+VΩ∑−Ai(ω^×OCsi→)⋅n^in^i+ΩV∑−Ai‖ω^×OCsi→‖(v^⋅n^i)n^i


Usando las mismas aproximaciones que la primera vez, y reemplazando s OCi→obtenemos:

Fs→=V(Vs2+Ωs3 vr¯(ω^))F→t(v^)+Ω2s4F→r(ω^)+VΩs3F→c(ω^)


Para el centro de masa del cuerpo escamado Gs.

Apéndice 4: Modelo de resistencia simplificado para paralelogramo


Hay muchas formas de aproximar fuerzas y pares para un paralelogramo, y se pueden obtener diferentes fórmulas. Suficientemente compacto, fácil de implementar en código y cálculos en tiempo de ejecución, se puede inferir ignorando el efecto del movimiento angular sobre la fuerza lineal y el efecto de la velocidad lineal sobre el par. Tomando el tamaño del paralelogramo delimitadorez , podemos llegar a las siguientes fórmulas compactas:

F→=−ρV2⟨eyez,exez,exey⟩⋅v^


M→=−ρ6Ω2exeyezw^⋅⟨ey2+ez2,ex2+ez2,ex2+ey2⟩


Apéndice 5: Spline del Centro de Tornado


El tornado se centra alrededor de una curva central cuya forma cambia lentamente. Implementamos esto usando dos splines cúbicos Bezier consecutivos:C0 para el fondo y C1para la cima. SplineC0 tiene puntos de control P0, P1, P2y P3y C1controlado por puntos P4, P5, P6y P7. La posición del tornado en sí está en un punto P0en el suelo y el punto más alto P7Comienza justo por encima del nivel de la capa de nubes, pero llega tarde, siguiendo lentamente la posición en la tierra. Como las curvas están conectadas en un extremo,P3 y P4coinciden en el espacio. También utilizamos 3 órbitas de referencia horizontales para puntosP1 , P2y P5. Finalmente P3estaba ubicado exactamente en los puntos medios entre P2y P5y P6en el punto medio entre P5y P7.

Crear una spline central de tornadoEvolución de la ranura central del tornado en el tiempo

Referencias


  1. Solo causa 4
  2. Havok
  3. Fundamentos de estructuras de datos multidimensionales y métricas . Hanan samet
  4. Curva de orden Z
  5. Mapeo de cubos
  6. Espuma abierta
  7. Volta
  8. Estudios Ironklad

Source: https://habr.com/ru/post/441678/


All Articles