2011-08-10 20 views
8

Quiero simular una caída libre y una colisión con el suelo (por ejemplo, una pelota que rebota). El objeto caerá en el vacío: se puede omitir la resistencia del aire. Una colisión con el suelo debería causar cierta pérdida de energía, por lo que finalmente el objeto dejará de moverse. Uso JOGL para representar un punto que es mi objeto que cae. Una gravedad es constante (-9.8 m/s^2).simulación de gravedad

he encontrado un método de Euler para calcular una nueva posición del punto:

deltaTime = currentTime - previousTime; 
vel += acc * deltaTime; 
pos += vel * deltaTime; 

pero estoy haciendo algo mal. El punto rebota un par de veces y luego se mueve hacia abajo (muy lento).

Aquí es un pseudocódigo (inicial pos = (0.0f, 2.0f, 0.0f), vel inicial (0.0f, 0.0f, 0.0f), la gravedad = -9.8f):

display() 
{ 
    calculateDeltaTime(); 
    velocity.y += gravity * deltaTime; 
    pos.y += velocity.y * deltaTime; 

    if(pos.y < -2.0f) //a collision with the ground 
    { 
     velocity.y = velocity.y * energyLoss * -1.0f; 
    } 

} 

¿Cuál es la mejor manera de lograr un efecto realista? ¿Cómo se refiere el método euler a las ecuaciones de aceleración constante?

+0

¿Qué sucede si simplemente elimina la pérdida de energía de la ecuación? – redbmk

+0

aparte de la respuesta de Yochai, puede considerar establecer 'pos.y' en el nivel del suelo en su caso de colisión para evitar errores de recorte –

+0

Sin pérdida de energía, el punto también deja de rebotar después de un período de tiempo y baja muy lentamente. – Vert

Respuesta

6

Como los puntos flotantes no se redondean muy bien, nunca obtendrás una velocidad en realidad 0. Probablemente obtendrás algo así como -0.00000000000001 o algo así.

necesita hacerlo 0.0 cuando esté lo suficientemente cerca. (definir algunos delta)

2

Para ampliar mi comentario anterior, y para responder Tobias, voy a agregar una respuesta completa aquí.

Tras la inspección inicial, determiné que estaba perdiendo la velocidad de sangre a velocidad. En pocas palabras, la relación entre la energía cinética y la velocidad es E = m v^2 /2, por lo que después de tomar la derivada con respecto a la velocidad se obtiene

delta_E = m v delta_v 

Luego, dependiendo de cómo se define energyloss, se puede establecer la relación entre delta_E y energyloss. Por ejemplo, en la mayoría de los casos energyloss = delta_E/E_initial, entonces la relación anterior se puede simplificar como

delta_v = energyloss*v_initial/2 

Esto es suponiendo que el intervalo de tiempo es pequeño lo que le permite reemplazar v en la primera ecuación con v_initial, por lo que debe ser capaz de salirse con la tuya por lo que estás haciendo. Para que quede claro, delta_v se resta de velocity.y dentro de su bloque de colisión en lugar de lo que tiene.

En cuanto a la cuestión de la adición de resistencia al aire o no, la respuesta es que depende. Para alturas iniciales de caída pequeñas, no importará, pero puede comenzar a importar con pérdidas de energía más pequeñas debido al rebote y a mayores puntos de caída. Para un diámetro de 1 gramo, 1 pulgada (2,54 cm), esfera lisa, he trazado diferencia de tiempo entre con y sin fricción del aire vs. altura de caída:

difference in time with and without air-drag vs. drop height

Para materiales de baja pérdida de energía (80 - 90+ % de energía retenida), consideraría agregarlo a una altura de caída de 10 metros o superior. Pero, si las gotas son de 2 a 3 metros, no me molestaría.

Si alguien quiere los cálculos, los compartiré.

+0

+1 gracias por esta respuesta. Creo que esta es una buena solución, también. A diferencia de la implementación original de colisión de Vert, la suya es para una colisión "más suave" donde el cuerpo colisiona con el suelo y se queda allí (como una almohada) mientras que la versión de Vert es un rebote con pérdidas. Cuál elegir depende, por supuesto, del comportamiento físico deseado. Y tienes razón, incluso la fricción del aire sería exagerada. –

+0

@Tobias, este es un rebote con pérdida también, solo un poco más suave de un rebote. – rcollyer

+0

@Vert, nunca me di cuenta cuando lo publiqué, pero dejé 'energyloss' de mi resultado para' delta_v'. Está arreglado ahora. – rcollyer