Rapier, motor de física 2D y 3D escrito en Rust
(rapier.rs)- Rapier es un conjunto de motores de física basados en Rust, orientado a aplicaciones que requieren física en tiempo real, como juegos, animación y robótica
- Busca ofrecer ejecución rápida y estabilidad, con soporte opcional de determinismo multiplataforma cuando es necesario
- Proporciona funciones necesarias para la simulación física, como colisiones y fuerzas de cuerpos rígidos, restricciones de articulaciones, eventos de contacto y sensores, y snapshots
- Ofrece bindings para JavaScript, lo que permite usar Rapier también fuera del entorno de Rust
- Es software libre y de código abierto bajo licencia Apache 2.0, desarrollado por Dimforge y financiado mediante GitHub Sponsor
Casos de uso a los que apunta Rapier
- Rapier es un conjunto de motores de física 2D y 3D escrito en Rust
- Su objetivo principal son las aplicaciones que requieren procesamiento de física en tiempo real
- videojuegos
- animación
- robótica
- Su meta de diseño es ofrecer un funcionamiento rápido y estable, con soporte opcional para determinismo multiplataforma
Funcionalidades y forma de distribución
- Incluye funciones clave para simulación física
- colisiones de cuerpos rígidos y fuerzas
- restricciones de articulaciones
- eventos de contacto y sensores
- snapshots
- determinismo multiplataforma opcional
- bindings para JavaScript
- Rapier es software libre y de código abierto, distribuido bajo licencia Apache 2.0
- La entidad desarrolladora es la empresa de código abierto Dimforge
- Se puede apoyar el proyecto mediante GitHub Sponsor
1 comentarios
Opiniones de Hacker News
Hice un juego multijugador en línea con el modo determinista de Rapier
La mecánica consiste en que los jugadores se turnan para embestir bichos hacia el equipo contrario y capturar la colina
Todavía no hay modo de un solo jugador, y escribir la IA es más difícil que en los juegos tipo ajedrez que hice antes
El juego se puede ver en https://evrimzone.itch.io/crittershowdown, y el código fuente de la física/lógica del juego está en https://github.com/evrimoztamur/crittershowdown/blob/e4d9a19...
Más adelante pienso escribir sobre cómo lo integré y qué aprendí; en general es una biblioteca muy sólida, y gracias a su diseño de API muy al estilo Rust pude implementar todo lo que necesitaba
Me da curiosidad si lo compilaste a WebAssembly o si alojas toda la lógica en un servidor local
Hace unos meses me metí mucho en el álgebra geométrica (Geometric Algebra), y me pareció una forma sorprendentemente concisa e intuitiva de tratar geometrías muy diversas: 2D, 3D, 4D o más, no euclidianas, etc.
Por eso me preguntaba si el álgebra geométrica podría ser una buena base para un motor de física
Hay algunas bibliotecas de Rust que se ven interesantes [1][2], pero no parece que ninguna reciba mucha atención
Me pregunto si alguien exploró este tema
[1]: https://crates.io/keywords/geometric-algebra
[2]: https://github.com/Lichtso/geometric_algebra
Si quieres empezar, “Why can't you multiply vectors?” de Freya Holmér puede ser una buena puerta de entrada: https://www.youtube.com/watch?v=htYh-Tq7ZBI y https://bivector.net/index.html
El álgebra geométrica es isomorfa al álgebra vectorial “clásica” al estilo Heaviside, y los problemas difíciles están en cosas como el manejo de colisiones, la conservación de energía y la estabilidad
Así que hice una biblioteca que permite generar álgebras geométricas arbitrarias y realizar varias operaciones interesantes, y que también puede servir como base para un motor de física
Si te interesa, está aquí: https://cljdoc.org/d/net.clojars.jordibc/geometric-algebra/
Escribí una guía del plugin Bevy Rapier para Rust: https://taintedcoders.com/bevy/rapier/
Como alternativa interesante en el lado de Bevy también está Bevy XPBD, y también escribí sobre eso: https://taintedcoders.com/bevy/xpbd/
Dice que “Sleeping” es una técnica para mejorar el rendimiento reduciendo el costo de simular objetos inmóviles, y que se puede ajustar con el recurso
SleepingThresholdComo valores predeterminados de ejemplo incluye
linear: 0.1,angular: 0.2Hasta ahora solo tuve un problema en el que algunas colisiones desaparecen durante un frame, pero ese tipo de cosas se puede rodear fácilmente o, mejor aún, reportar para que se corrija
Todavía no logré que la rotación funcione bien, pero con lo demás siento que la complejidad se derrite
¿Álgebra lineal? No hace falta. Es solo
Vec3. ¿Matrices? ¿Solvers? Basta con satisfacer todas las restricciones iterativamente, como si hubiéramos vuelto a 1998¿Margen de colisión? Cuestión de habilidad. ¿Fase amplia? ¿GJK? No lo pienses de más y déjaselo a una CPU moderna
Después de optimizar
collect_pairs, te das cuenta de que el cuello de botella real eramallocy lo corriges; entonces maneja sin problemas unos 100 objetos. No hace falta BulletLa etapa de corrección de velocidad también me confundió al principio, pero al hacer un prototipo con AABB creo que podré trasladarla de nuevo a figuras generales
Al principio me salté esa etapa y todas las colisiones se comportaban como si fueran ligeramente elásticas
Dimforge está haciendo un trabajo realmente impresionante
Sería muy prometedor si nalgebra + Rust pudiera reemplazar a Eigen + C++ en áreas como la localización y el mapeo en robótica
En Rust muchas cosas simplemente funcionan. Lo lamentable es que hay una vieja guardia que se niega rotundamente a invertir en Rust
Honestamente, entiendo la razón: hay una industria enorme alrededor del código de robótica en C++
Me pregunto si actualmente existe algún framework de robótica usable en Rust
Escuché que ROS2 está incorporando Rust lentamente [1], pero no sé bien cómo ha avanzado
Como la integración/abstracción de hardware ya está hecha en C++, ROS puede ser una buena puerta de entrada hacia la fusión de sensores, el mapeo y la localización
También me da curiosidad si las empresas están usando esto
[1] https://github.com/ros2-rust/ros2_rust
Por lo que recuerdo de cuando hice un motor de física de cuerpos rígidos hace décadas, el apilamiento (stacking) era un problema muy difícil
En ese entonces, la mejor solución para evitar que los objetos se hundieran en el piso era construir un grafo acíclico dirigido que empezara desde el piso y empujara los objetos hacia afuera
Había que repetirlo varias veces para que convergiera, y se sentía bastante hacky
Me pregunto si hoy este problema ya está resuelto. No encontré ninguna mención al apilamiento en este proyecto
El video del autor enlazado al final del artículo muestra cómo cada solver maneja varios problemas difíciles de apilamiento: https://youtu.be/sKHf_o_UCzI
No se necesita un grafo acíclico; si aumentas lo suficiente la cantidad de iteraciones del solver, converge
Considerando la cantidad de restricciones de contacto y fricción, iterar varias veces es algo natural, y si se rastrea el residuo máximo se puede ejecutar hasta que llegue casi a cero
La parte que sigue algo rota es que la detección de colisiones y el solver solo corren a una tasa de actualización limitada
Si empiezas con objetos ya interpenetrados, hay que resolverlo, pero como los objetos reales no se interpenetran así, es un tratamiento algo “falso” y puede generar movimiento adicional que reduce la estabilidad de las pilas
Aun así, hay varias formas de evitarlo, y los motores de física populares tienen alguna solución de un tipo u otro
Rust parece seguir confirmando el estereotipo
Me recuerda el chiste de que hay 50 motores de juegos hechos en Rust, pero solo 5 juegos hechos en Rust
Rapier no cumple exactamente con lo que necesito, pero no hay buenas alternativas
Así que parece posible en juegos 2D pequeños donde no hace falta escribir mucho código de motor
Ese juego manejaba la mayor parte con SDL
También hice una pequeña demo web con Rapier: https://github.com/iErcann/NotRoblox
No usé Rust
Lo que me gustó es que la documentación es mejor que la de AmmoJS. Con AmmoJS tenía que leer pybullet
Es relativamente moderno y puede ejecutarse tanto en el servidor (Node) como en el cliente (navegador)
Aquí lo ejecuto del lado del servidor, pero también sería posible correrlo en ambos lados e implementar predicción y corrección del cliente
El bundle también es pequeño. Creo que AmmoJS pesaba alrededor de 2 MB
Por suerte estoy atado a una versión anterior, así que no es tan grave
La interoperabilidad con JavaScript también es realmente buena: https://www.rapier.rs/docs/user_guides/javascript/getting_st...
https://threlte.xyz/docs/reference/rapier/getting-started
Dimforge antes tenía un motor de física llamado nphysics, que soportaba cuerpos blandos y multicuerpos
Ahora fue abandonado en favor de Rapier, pero Rapier no soporta ni la mitad de esas funciones ni de otras cosas que hacía nphysics
Como resultado, nphysics es demasiado viejo y difícil de usar en el ecosistema moderno, mientras que Rapier es demasiado nuevo y le faltan muchas más funciones
Algo parecido ya pasó antes. Una biblioteca de simulación de fluidos llamada Salva soportaba acoplamiento bidireccional con nphysics y corría en cualquier GPU/CPU, pero ahora fue abandonada en favor de Sparkl
Pero Sparkl no tiene esas funciones y solo soporta CUDA. Así que Salva quedó tan vieja como nphysics, y Sparkl es demasiado nueva, tiene muchas menos funciones y tampoco tiene soporte multiplataforma
Incluso parece intencional. Es como si hubieran “reescrito este código para hacerlo menos multiplataforma”
Espero que algún día dejen de reescribir todo continuamente y se estabilicen en algo que realmente soporte todas las funciones necesarias
Pero si en cada reescritura se pierden funciones, no sé si el ecosistema de Dimforge sea adecuado para mí
¿Cómo puedo saber que Rapier no será abandonado algún día en favor de algo aún más nuevo, y que ese nuevo motor no soporte ni la mitad de las funciones de Rapier?
Entiendo que, al ser un proyecto nuevo, no pueda soportar todas las funciones del maduro nphysics
Pero el problema es precisamente que ese nphysics maduro fue abandonado por completo y ya no recibe mantenimiento
Si Dimforge no tuviera ya este precedente, sería una preocupación poco realista, pero el historial existe
Puede que algún día Rapier alcance el nivel de funciones que nphysics ya tenía hace 5 años, pero para un desarrollador que quiere construir algo sobre las funciones que hoy faltan, se siente como un retroceso arbitrario de 5 años