En primer lugar voy a explicar brevemente qué son los contraints.
Los constraints o restricciones son eso, restricciones. En este caso, de movimiento.
Imaginemos una barra de longitud L que cumpla las siguientes condiciones ideales, que no se pueda doblar, romper, estirar o comprimir (básicamente la definición de un cuerpo rígido ideal). Ahora, supongamos que tomamos 2 puntos cualesquiera de la misma, por motivos prácticos, en sus extremos.
Es claro que sin importar lo que ocurra, la distancia entre ambos puntos debe ser forzosamente L (la longitud de la barra), incluso aunque los movamos individualmente. Si pensamos esto en términos más normales o, mejor dicho, ejemplos palpables, esto resulta obvio y no requiere mayor explicación.
Supongamos que por motivos que no importan por el momento nos vemos obligados a mover las partículas y, también por motivos que no nos interesan por el momento, deseamos que las partículas permanezcan a la misma distancia.
En este caso, lo único que se conservaría es el ángulo que forman. Por lo tanto, si calculamos la distancia actual, le restamos la original (podría dar negativo, esto es correcto e importante) y la dividimos por 2, vamos a obtener cuánto debemos mover las partículas la una hacia la otra (el número negativo, haría que se alejen).
Paso a paso lo que hacemos es:
Calcular la distancia entre las partículas.
Calcular el ángulo que forman.
Calcular cuánto tenemos que moverlas.
Reubicarlas.
Si traducimos lo anterior a una función, obtenemos lo siguiente :
Aunque el código anterior está pensado para ser claro y simple de entender, realiza su trabajo como se supone que debe hacerlo.
Un ejemplo de cómo aplicamos el código anterior podría ser el siguiente:
En este caso, empleamos la variable elasticidad y obtenemos un efecto que podría tildarse de más orgánico (como en el juego Flow).
Además, empleamos una función que llama a la función constraints. La ventaja es que podemos fácilmente decidir cuántas iteraciones deseamos en el proceso de restringir.
Porqué tenemos que iterar? Es simple, el caso que veníamos analizando había sólo 2 partículas y un contraint. Con varios, la cosa se complica. Ya que satisfacer un constraint puede "desatisfacer" otro/s.
Cómo satisfacer todos los constraints al mismo tiempo? Bien, si uno lo analiza, es equivalente a resolver un sistema de ecuaciones bastante complejo. Pero, si satisfacemos una a una las restricciones, qué ocurre?
Exacto, el sistema se parece cada vez más a la solución final. Si repetimos el proceso infinitas veces, obtendríamos la posición exacta que deseamos.
Pero eso no es necesario, con 3 veces alcanza en la mayoría de los casos. Esto se debe a que este sistema no acumula errores. Un error pequeño al principio, significa un error menor luego de algunos fotogramas. Es decir, incluso con sólo una iteración obtendríamos el efecto deseado (aunque podría llegar a ser visualmente feo).
A estas alturas, ya puede resultar más clara la utilidad de la Integración de Verlet. Luego de modificar la posición de las partículas para satisfacer sus correspondientes sistemas de constraints, las hemos movido. Si además del código para las restricciones, le agregamos el que corresponde a la integración, vamos a ver cómo las partículas se unen para formar sólidos que rotan, rebotan, no se deforman y responden naturalmente a las colisiones.
Igualmente, el ejemplo anterior es solo eso, un ejemplo. En realidad, si quisieramos convertir lo anterior en nuestro propio Half-life 2, vamos a necesitar un milagro, evitar que los objetos vibren cuando deberían estar quietos y un mejor sistema de detección de colisiones. Pero no hace falta ser demasiado crédulo para observar que no falta mucho para crear nuestra propia simulación física creible (no realista, sólo creible).
muy bueno ! realmente te tomaste un trabajo importante ! gracias! Por:nicosantos_blog
Genial !!!... muy interesante Hernan... Realmente lograste capturar completamente mi atención. Lo que me deja solo una duda (( ojala y la pudieras contestar )), es posible conseguir que por ejemplo:...
HernanRivas :
.... a este ejemplo que posteaste, agregarle gravedad, es decir; que si tienes un constraint los demas caigan por el empuje de la gravedad, pero sigan manteniendo su distancia unos a otros.... Entiendo si mi pregunta esta muy gruesa, o si te incomoda responder!!!... En horabuena, te quedo muy buena !!!... Por:M@U
wow! fantastico Por:penholder_blog
M@U, lo que pedís lo explico en el tutorial anterior de Integración de Verlet (el link está en el primer párrafo).
Es más, el ejemplo de la caja que rebota hace precisamente eso. Las 4 esquinas de la caja se mantienen unidas usando 6 constraints y la gravedad se incluye dentro de la función de Verlet, que es la misma que se ocupa de los rebotes y la rotación de la caja. A esta función se le pueden agregar sin ningún problema aceleraciones en cualquier eje (es más, la función la escribí pensando en eso y hasta permite que cada punto tenga una aceleración distinta).
Te recomendaría que revisaras el .fla de la caja que cae y el tutorial anterior. Por:HernanRivas
Wow !!!... Muchas gracias Hernan, muy ingenioso lo de los constraints en la caja... Gracias otra vez... Por:M@U