Rapier, motor de física 2D e 3D escrito em Rust
(rapier.rs)- Rapier é um conjunto de motores de física baseado em Rust, voltado a aplicações que precisam de física em tempo real, como jogos, animação e robótica
- Tem como objetivo execução rápida e estabilidade e, quando necessário, oferece suporte opcional a determinismo multiplataforma
- Oferece recursos necessários para simulação física, como colisões e forças de corpos rígidos, restrições de juntas, eventos de contato e sensores, snapshots etc.
- Oferece bindings para JavaScript, permitindo usar o Rapier também em ambientes além do Rust
- É um software livre e open source gratuito sob a licença Apache 2.0, desenvolvido pela Dimforge e financiado via GitHub Sponsors
Casos de uso visados pelo Rapier
- Rapier é um conjunto de motores de física 2D e 3D escrito em Rust
- O público-alvo são aplicações que precisam de processamento de física em tempo real
- Videogames
- Animação
- Robótica
- O objetivo de design é uma operação rápida e estável, com suporte opcional a determinismo multiplataforma
Recursos oferecidos e forma de distribuição
- Inclui os principais recursos para simulação física
- Colisões de corpos rígidos e forças
- Restrições de juntas
- Eventos de contato e sensores
- Snapshots
- Determinismo multiplataforma opcional
- Bindings para JavaScript
- Rapier é gratuito e open source, distribuído sob a licença Apache 2.0
- O desenvolvimento é feito pela empresa open source Dimforge
- É possível apoiar o projeto via GitHub Sponsors
1 comentários
Opiniões do Hacker News
Fiz um jogo multiplayer online usando o modo determinístico do Rapier
Nele, os jogadores se revezam para arremessar insetos contra o time adversário e capturar colinas
Ainda não há modo single-player, e escrever a IA é mais complicado do que nos jogos estilo xadrez que fiz antes
O jogo pode ser visto em https://evrimzone.itch.io/crittershowdown, e o código-fonte da lógica de física/jogo está em https://github.com/evrimoztamur/crittershowdown/blob/e4d9a19...
Pretendo escrever depois sobre como integrei tudo e o que aprendi, mas, no geral, é uma biblioteca muito sólida, e o design de API bem ao estilo Rust me permitiu implementar tudo de que eu precisava
Gostaria de saber se foi compilado para WebAssembly ou se toda a lógica é hospedada em um servidor local
Há alguns meses me interessei por Álgebra Geométrica (Geometric Algebra), e ela me pareceu uma forma surpreendentemente concisa e intuitiva de lidar com geometrias muito variadas: 2D, 3D, 4D ou mais, não euclidianas etc.
Por isso fiquei me perguntando se a álgebra geométrica poderia ser uma boa base para um motor de física
Existem algumas bibliotecas em Rust que parecem interessantes [1][2], mas nenhuma parece receber muita atenção
Gostaria de saber se alguém já explorou esse assunto
[1]: https://crates.io/keywords/geometric-algebra
[2]: https://github.com/Lichtso/geometric_algebra
Se quiser começar, “Why can't you multiply vectors?”, da Freya Holmér, pode ser uma boa porta de entrada: https://www.youtube.com/watch?v=htYh-Tq7ZBI e https://bivector.net/index.html
A álgebra geométrica é isomórfica à álgebra vetorial “clássica” de Heaviside, e os problemas difíceis estão em áreas como tratamento de colisões, conservação de energia e estabilidade
Então criei uma biblioteca que permite gerar álgebras geométricas arbitrárias e realizar várias operações interessantes, e que também pode servir de base para um motor de física
Se tiver interesse, está aqui: https://cljdoc.org/d/net.clojars.jordibc/geometric-algebra/
Escrevi um guia do plugin Bevy Rapier para Rust: https://taintedcoders.com/bevy/rapier/
Como alternativa interessante no ecossistema Bevy, também há o Bevy XPBD, sobre o qual também escrevi: https://taintedcoders.com/bevy/xpbd/
“Sleeping” é descrito como uma técnica que aumenta a performance ao reduzir o custo de simulação de objetos que não estão se movendo, e pode ser ajustada com o recurso
SleepingThresholdO exemplo de valores padrão inclui
linear: 0.1eangular: 0.2Até agora houve um problema em que algumas colisões desapareciam por um frame, mas esse tipo de coisa é fácil de contornar e, melhor ainda, também pode ser reportado para ser corrigido
Ainda não consegui fazer a rotação funcionar direito, mas o restante dá a sensação de que a complexidade simplesmente derrete
Álgebra linear? Não precisa. É só
Vec3. Matrizes? Solvers? Basta satisfazer repetidamente todas as restrições, como se estivéssemos de volta a 1998Margem de colisão? Questão de habilidade. Broad phase? GJK? Não pense demais e deixe para as CPUs modernas
Depois de otimizar
collect_pairse perceber que o gargalo real eramalloc, corrigir isso faz com que cerca de 100 objetos sejam processados com folga. Não precisa de BulletA etapa de correção de velocidade também me confundiu no começo, mas, ao prototipar com AABB, acho que será possível transportá-la de volta para formas gerais
No começo pulei essa etapa, e todas as colisões acabavam se comportando de forma levemente elástica
A Dimforge está fazendo um trabalho realmente incrível
Seria muito empolgante se nalgebra + Rust pudesse substituir Eigen + C++ em áreas como localização e mapeamento em robótica
Em Rust, muita coisa simplesmente funciona. É uma pena, porém, que exista uma geração mais antiga que se recusa a investir em Rust e não arreda o pé
Sinceramente, há uma indústria enorme em torno de código de robótica em C++, então entendo o motivo
Fico curioso para saber se hoje existe algum framework de robótica utilizável em Rust
Ouvi dizer que o ROS2 está incorporando Rust aos poucos [1], mas não sei bem como isso avançou
Como a integração/abstração de hardware já é feita em C++, o ROS pode ser uma boa porta de entrada para fusão de sensores, mapeamento e localização
Também fico curioso se empresas estão usando isso
[1] https://github.com/ros2-rust/ros2_rust
Pelo que lembro de quando desenvolvi um motor de física de corpos rígidos décadas atrás, empilhamento (stacking) era um problema muito difícil
Na época, a melhor solução para evitar que objetos afundassem no chão era criar um grafo acíclico direcionado começando pelo chão e empurrando os objetos para fora
Era preciso repetir várias vezes para convergir, e parecia bastante gambiarra
Fico curioso se esse problema já foi resolvido hoje. Não encontrei menção a empilhamento neste projeto
O vídeo do autor linkado no fim do texto mostra como cada solver lida com vários problemas difíceis de empilhamento: https://youtu.be/sKHf_o_UCzI
Não é preciso um grafo acíclico; se você aumentar suficientemente o número de iterações do solver, ele converge
Considerando o número de restrições de contato e atrito, iterar várias vezes é natural, e, acompanhando o resíduo máximo, dá para rodar até chegar praticamente a zero
A parte um pouco problemática é que colisão e solver só rodam em uma taxa de atualização limitada
Se algo começa já em estado de penetração, isso precisa ser resolvido, mas objetos reais não penetram assim, então é um tratamento meio “fake”, e pode gerar movimento adicional que reduz a estabilidade da pilha
Ainda assim, há várias formas de contornar isso, e os motores de física populares têm alguma solução para esse caso
Rust parece continuar confirmando os estereótipos
Isso me lembra a piada de que existem 50 engines de jogos feitas em Rust, mas só 5 jogos feitos em Rust
Rapier não atende exatamente às necessidades que tenho, e não há uma boa alternativa
Então parece viável em jogos 2D pequenos que não exigem muito código de engine
Nesse caso, o jogo fazia a maior parte das coisas com SDL
Também fiz uma pequena demo web com Rapier: https://github.com/iErcann/NotRoblox
Não usei Rust
O que gostei foi que a documentação é melhor que a do AmmoJS. Com AmmoJS, eu precisava ler o pybullet
É relativamente moderno e pode rodar tanto no servidor (Node) quanto no cliente (navegador)
Aqui ele roda no lado do servidor, mas também seria possível rodar nos dois lados e implementar predição e correção no cliente
O bundle também é pequeno. Acho que o AmmoJS tinha algo em torno de 2 MB
Felizmente, ela está presa a uma versão anterior, então não é tão ruim
A interoperabilidade com JavaScript também é muito boa: https://www.rapier.rs/docs/user_guides/javascript/getting-st...
https://threlte.xyz/docs/reference/rapier/getting-started
A Dimforge tinha antes um motor de física chamado nphysics, que dava suporte a corpos deformáveis e multibodies
Agora ele foi descontinuado em favor do Rapier, mas o Rapier não dá suporte nem a metade desses recursos ou de outros que o nphysics tinha
Como resultado, o nphysics é antigo demais para ser usado com facilidade no ecossistema moderno, e o Rapier é novo demais e tem muito menos recursos
Algo parecido já aconteceu antes. Havia uma biblioteca de simulação de fluidos chamada Salva que oferecia acoplamento bidirecional com o nphysics e rodava em qualquer GPU/CPU, mas agora foi descontinuada em favor do Sparkl
Só que o Sparkl não tem esses recursos e só dá suporte a CUDA. Então o Salva ficou tão obsoleto quanto o nphysics, e o Sparkl é novo demais, tem muito menos recursos e não tem suporte multiplataforma
Parece até intencional. É como se tivessem “reescrito este código para torná-lo menos multiplataforma”
Espero que um dia essa sequência de reescritas pare e que eles se estabeleçam em algo que realmente dê suporte a todos os recursos necessários
Mas, se cada reescrita perde funcionalidades, não sei se o ecossistema Dimforge é adequado para mim
Como posso saber se o Rapier também não será descontinuado algum dia em favor de algo mais novo, e se esse novo motor não dará suporte nem à metade dos recursos do Rapier?
Entendo que, por ser um projeto novo, ele não consiga oferecer todos os recursos do nphysics maduro
Mas o problema é justamente que esse nphysics maduro foi completamente descontinuado e não é mais mantido
Se a Dimforge não tivesse esse histórico, essa preocupação seria irrealista, mas há precedentes
Talvez um dia o Rapier chegue ao nível de recursos que o nphysics já tinha cinco anos atrás, mas, para um desenvolvedor que quer construir algo sobre os recursos que hoje faltam, isso parece um retrocesso arbitrário de 5 anos