¿Cómo soluciono los objetos "explotando" o temblando en el motor de física?

11

Tengo un motor de física simple que resuelve colisiones simplemente corrigiendo la posición de los cuerpos superpuestos (solo círculos por ahora) directamente, en lugar de simplemente cambiar la velocidad o aplicar un impulso. La velocidad solo cambia después de que los impactos ya se han resuelto, o durante la parte de integración.

He tenido el problema de que en los montones de objetos los objetos superiores aplican demasiada presión (esto existe implícitamente, no hay modelado de presión en el algoritmo) sobre los objetos en la parte inferior del montón, lo que hace que sean empujados a través de los pisos, etc.

Quería arreglar esto ordenando los objetos por su coordenada y, para que las colisiones se resuelvan de abajo hacia arriba. Pero ahora, el motor muestra un comportamiento de estallido extraño para los objetos que realmente deberían estar en reposo (ver gif)

ingrese la descripción de la imagen aquí

Sin solo darle el código fuente, ¿qué podría ser?

TravisG
fuente
55
En general, esto es similar a resolver un sistema lineal de ecuaciones de manera iterativa (o sistema no lineal, dependiendo de sus restricciones / condiciones / etc.). En cualquier caso, estás viendo estos artefactos porque son numéricamente lo correcto: estados intermedios de un proceso convergente. Evitar esto es bastante difícil y podría implicar muchos trucos desagradables (de todos modos, esto sucede en la vida real, a nivel molecular, y eso es lo que tienes allí para parecerte mejor a algo en la vida real :)). Probablemente sea bueno investigar box2d para ver su solución para la dinámica basada en impulsos.
teodron
@TravisG ¿cómo resolvió el problema? Estoy viendo un problema similar cuando intento implementar un motor de física muy simple.
cheesus dice que dejen de disparar mods el
1
@cheeesus Ha pasado un tiempo desde que trabajé en él, pero creo que acabo de usar más iteraciones con pasos de tiempo más pequeños.
TravisG

Respuestas:

5

Una solución que he encontrado al usar la corrección de posición es tener algunas iteraciones y variar la fuerza con cada iteración.

doPhysics();

int num_iterations = 5;
for(int iteration=0; iteration<num_iterations; ++iteration)
{
    float strength = float(iteration+1)/num_iterations;
    correctPositions(strength);
}

Entonces, la primera iteración tiene una fuerza de 1 / num_iterations y la última tiene una fuerza de 1. Esto hace que mis simulaciones sean más fluidas y estables que simplemente usar el mismo número de iteraciones con una fuerza fija.

DaleyPaley
fuente
2
Buena solución, pero ¿por qué funciona?
Gustavo Maciel
5

Su problema radica en el hecho de que no tiene un estado de "reposo" para sus cuerpos. Cualquier sistema de física tiene una cantidad de energía, ya sea cinética, térmica, etc. En realidad, los objetos sólidos se deforman ligeramente y transforman parte de la energía cinética en calor, aunque difícilmente se puede medir. También vale la pena señalar que, en realidad, no existe un objeto completamente sólido. Incluso los materiales densos, como el diamante, tienen espacio entre los átomos, dando espacio a la estructura atómica para flexionarse y absorber energía cinética.

Para que esto sea relevante, los cuerpos en reposo se encuentran en un estado en el que las únicas fuerzas vigentes son la "fuerza normal", es decir, la fuerza que impide que los cuerpos floten entre sí. La magnitud de esa fuerza normal es proporcional a la densidad de los objetos, y hasta qué punto se han penetrado entre sí.

Los motores de física llaman a este valor "slop".

Aquí está el truco: calcule la pendiente, corrija la posición de los cuerpos y aplique la fuerza normal, en función de la velocidad relativa de los dos cuerpos. Durante la actualización de los propios cuerpos, calcule la energía cinética de cada cuerpo. Si está por debajo de un valor mínimo, entonces duerma el cuerpo, hasta que se le aplique una fuerza de magnitud suficiente. (generalmente el doble del valor mínimo).

Ian Young
fuente
0

¿Por qué no agregarles una superficie "pegajosa" y hacer que se peguen a una posición de reposo gradualmente y cuando otro objeto lo golpea transfiere algo de energía hacia él haciendo que se mueva, pero la superficie pegajosa hará que pierda algo de esta energía y se detenga en posición de reposo Parece que el gif no tiene fricción.

luego
fuente