Quando quem calcula a força deixa de ser eu.
O protótipo raycast mantém o rover de pé porque eu calculo e aplico uma força a cada quadro. Esta quinzena foi entender o paradigma oposto — o multicorpo: corpos rígidos ligados por juntas, onde eu apenas declaro a relação e o solver do motor de física descobre sozinho o impulso que a mantém. O arco vai do conceito até duas caixas oscilando numa cena de teste, e termina no que o Godot não me deixa alcançar do Jolt.
A quinzena, etapa por etapa
O roadmap desta quinzena está em 27 jul–10 ago · Rumo ao multicorpo. Ele foi montado pra semana de 27/jul e esticado pelas duas semanas seguintes — e foi assim que aconteceu na prática: quatro etapas de estudo espalhadas pelo período, e não um bloco por dia. Abaixo, o que cada etapa cobriu e quando.
O conceito: corpo rígido, junta, penalidade × constraint
Definir sistema multicorpo e situar o protótipo raycast dentro do quadro maior. Blocos 01 a 03.
Graus de liberdade e as cinco juntas do Godot
A régua que mede o que uma junta permite, e a assinatura de GDL de cada Joint3D. Bloco 04.
Experimento mínimo: dois corpos e uma dobradiça
A cena TesteJunta rodando — restrição de GDL funcionando sem uma linha de código. Bloco 05.
O Jolt por dentro e os limites do Godot
Solver de impulsos sequenciais, as lacunas da API Joint3D e a exploração do repositório oficial. Blocos 06 a 08.
Consolidação · esta entrada
Mapear as juntas pro rover no papel, escrever esta doc — e a reunião do dia, que abriu a segunda metade do roadmap.
A outra metade do roadmap
Comparativo Jolt × Godot a partir de um Sample, replicar esse sample no Godot, ler a doc do GDExtension e espelhar o GDChrono do professor pro Jolt. Nada disso entrou nesta entrada.
Os dois tijolos: corpo rígido e junta
27–28 julAntes de definir "multicorpo", dois conceitos que sustentam tudo o que vem depois — e um número que atravessa a quinzena inteira: seis.
Não se deforma — logo, 6 números bastam
Um corpo rígido é um objeto em que a distância entre quaisquer dois pontos nunca muda. Pra descrevê-lo por completo bastam duas informações: onde está (posição) e como está orientado (rotação) — três eixos cada. Daí os 6 GDL de um corpo livre no espaço 3D.
Uma conexão que proíbe movimento
Uma junta (joint, ou constraint) liga dois corpos e proíbe parte do movimento relativo entre eles. A dobradiça de porta é o exemplo direto: liga porta e batente e permite exatamente um movimento — girar em torno de um eixo.
Sistema multicorpo, em uma frase
Um conjunto de corpos rígidos conectados por juntas, em que cada junta restringe o movimento relativo entre os corpos que ela liga.
A analogia que fixa a ideia é o esqueleto (ou uma marionete): os ossos são os corpos; as articulações, as juntas. O joelho é quase uma dobradiça pura — um eixo só; o ombro é mais livre, girando dentro de um cone. E ninguém precisa "empurrar" o antebraço pra ele continuar preso ao braço: a articulação garante isso por construção, não por uma força aplicada o tempo todo.
O contraste central: penalidade × constraint
27–28 julEste é o núcleo conceitual da quinzena, e o que separa o protótipo raycast do paradigma que estudei aqui. As duas abordagens querem o mesmo resultado — manter uma relação física válida entre partes de um sistema — mas chegam nele por caminhos opostos.
Eu meço o erro e aplico uma força
A cada quadro eu meço o quanto a situação está "errada" (o quanto a mola está comprimida além do repouso, o quanto a roda desliza em vez de rolar) e calculo uma força corretiva. Quem escolhe e dimensiona essa força sou eu — a relação vale de forma aproximada, na medida em que eu tenha acertado a intensidade.
Eu declaro a relação e o solver resolve
Em vez de calcular força, eu declaro a relação geométrica ("estes dois corpos só giram um em relação ao outro em torno deste eixo"). O solver do motor calcula, a cada passo, o impulso exato que mantém a declaração verdadeira. A junta não tenta segurar — ela simplesmente não permite o movimento proibido.
| Penalidade (raycast) | Constraint (multicorpo) | |
|---|---|---|
| Quem calcula a força | Eu, a cada quadro | O solver do motor de física |
| Natureza da relação | Aproximada — depende do ajuste da força | Exata, por construção |
| Risco característico | Divergência, se a força corretiva for mal dimensionada | Não há força a calibrar — a violação é impedida |
| Analogia | Elástico segurando a porta | Dobradiça de metal |
Esse risco não é teórico — eu já vivi ele no protótipo raycast, na implementação do atrito lateral:
O rover era ejetado da cena
Ao implementar o atrito lateral, o corpo saía violentamente arremessado em vez de assentar.
Integrador explícito divergindo
A força corretiva de um quadro cancelava mais velocidade do que existia: o erro invertia de sinal e crescia no quadro seguinte. A solução foi ancorar a força num limite físico real — o clamp do círculo de atrito (μ · N), que impede por construção que a correção passe do fisicamente possível. É a manifestação prática do risco da penalidade.
O raycast é um multicorpo achatado
28 julUma correção conceitual importante, que evita um erro comum: o protótipo raycast não tem juntas escondidas. É o contrário — ele substitui as juntas por forças que eu calculo à mão.
Suspensão ⇄ slider joint
A força de mola-amortecedor faz, de forma aproximada, o papel de um SliderJoint3D: restringir o movimento relativo entre chassi e roda a um único eixo de translação.
Tração e grip ⇄ hinge joint + contato pneu-solo
As forças longitudinal e lateral fazem o papel de um HingeJoint3D no eixo da roda somado a um modelo de contato pneu-solo.
O VehicleBody3D é da mesma família
Testado e descartado antes do raycast atual, ele também é — por baixo da abstração — um veículo raycast: corpo único, raios nas rodas, modelo de pneu embutido como caixa-preta. A diferença é só o nível de exposição: ele esconde a física dentro do nó; o ground_contact.gd a deixa à vista.
Graus de liberdade e as cinco juntas do Godot
29–30 julO bloco 01 disse que a junta restringe o movimento relativo, mas deixou em aberto: restringir como, exatamente? A resposta é a régua do grau de liberdade — e ela transforma "escolher como limitar" e "escolher qual junta usar" na mesma decisão.
Uma dobradiça de porta não impede a casa inteira de se mover; ela impede que a porta se mova em relação ao batente, exceto pela única rotação que permite. Com essa régua, cada junta do Godot vira uma assinatura fixa de GDL:
| Junta (Godot) | Análogo mecânico | GDL que sobram | Uso no rover |
|---|---|---|---|
| PinJoint3D | rótula / junta esférica | 3 rotações livres | articulação sem restrição de giro |
| HingeJoint3D | dobradiça / revoluta | 1 rotação | eixo da roda; braço de suspensão |
| SliderJoint3D | prismática | 1 translação | curso vertical da suspensão |
| ConeTwistJoint3D | ombro / esférica limitada | rotação limitada (cone + torção) | juntas com batente angular |
| Generic6DOFJoint3D | configurável | escolhido eixo a eixo | casos gerais; combinações; motores |
SliderJoint3D pode opcionalmente liberar também a torção ao longo do mesmo eixo — pro caso da suspensão, o uso pretendido é translação pura. E o ConeTwistJoint3D, diferente das duas anteriores, não deixa um GDL totalmente livre: restringe a uma faixa.Esclarecimento: junta é nó, não função
Ao ver PinJoint3D ou HingeJoint3D pela primeira vez, a dúvida natural é se são funções do GDScript. Não são: são nós — classes que a engine oferece pra pendurar na árvore da cena, da mesma família de RigidBody3D e RayCast3D, que eu já uso no rover. Joint3D é a classe-base; as cinco são subtipos que herdam o "ligar dois corpos" e acrescentam seu padrão próprio de travamento.
Adicionar o nó e preencher dois campos
Adiciono o nó à árvore e preencho, no Inspector, node_a e node_b, apontando pros dois RigidBody3D. Toda junta do Godot liga exatamente dois corpos — é a implementação literal do "linkar dois corpos rígidos".
Como tipo instanciável
Em código o nome aparece como classe, instanciada da forma usual. GDScript é a linguagem; HingeJoint3D é um tipo que a engine disponibiliza — não uma função embutida.
# HingeJoint3D é a classe; .new() é o construtor
var junta = HingeJoint3D.new()Experimento mínimo: dois corpos e uma dobradiça
31 julHora de sair da teoria. Objetivo: ver uma restrição de GDL funcionando de verdade — dois RigidBody3D ligados por um HingeJoint3D — sem escrever código e sem aplicar nenhuma força. A cena não tem relação nenhuma com o rover; o isolamento é deliberado, no mesmo espírito de ter separado o ground_contact.gd.
A Âncora é um corpo congelado, não um tipo especial de nó
Usei um RigidBody3D com Freeze ligado: ele deixa de ser afetado pela simulação (não cai, não se move), mas continua sendo um corpo físico válido, apto a servir de ponto fixo pra junta — o "prego na parede", sem o Godot precisar de um nó dedicado a isso.
CollisionShape3D é a forma que a física reconhece; MeshInstance3D é a que é desenhada.O Pêndulo é idêntico, menos o Freeze
Mesmo par de filhos, posição espelhada em X, mesma altura. A única diferença relevante: sem freeze — livre e sujeito à gravidade.
A junta não mora dentro de nenhum dos corpos
O HingeJoint3D é filho direto da raiz, posicionado no ponto médio entre os dois corpos — o ponto físico em torno do qual a rotação relativa acontece. Sua função inteira é apontar pros dois corpos, via Node A e Node B no Inspector.
Conferir o motor antes de rodar
Em Project Settings → Advanced → Physics → 3D → Physics Engine, confirmei Jolt (padrão no Godot 4.6) — garantindo que quem resolve a restrição é mesmo o motor que estudei na quinzena.
Ao rodar (F6): o Pêndulo caiu por um instante, foi contido pela junta e passou a oscilar em torno do pivô, como um pêndulo físico real.
Achado: por que os dois corpos se atravessam
O Pêndulo atravessa a Âncora
Durante a oscilação os dois corpos se interpenetram em vez de colidir. Parece bug — não é.
Exclude Nodes From Collision, ligada por padrão
Toda junta derivada de Joint3D tem essa propriedade ligada por padrão: os dois corpos que ela conecta deixam de colidir entre si, mesmo com as formas sobrepostas.
HingeJoint3D no eixo vão, quase com certeza, ter formas de colisão sobrepostas ali. O comportamento desejável é justamente o padrão do Godot: excluir a colisão mútua e deixar só a junta governar a relação.HingeJoint3D no editor pra ver o plano da oscilação mudar, e ativar o Angular Limit (lower/upper) pra restringir ainda mais o único GDL que a junta permite. Fica registrado como pendência — não considerar concluído..tscn fica isolada dentro do projeto Godot (Teste_junta/, na raiz do repo, fora do Docusaurus); o registro visual do experimento vive junto desta doc, em src/components/DossieMulticorpo/img/. Optei deliberadamente por não criar uma página só pro experimento — ele é uma seção desta entrada consolidada.Como o Jolt resolve um constraint
03–07 agoO experimento produziu a restrição funcionando; a semana 2 foi investigar o que acontece por dentro desse resultado — e a primeira coisa é que o mecanismo nem sequer é uma força.
Age ao longo de um intervalo
Uma força atua continuamente durante o passo de tempo. É o que eu faço a cada quadro: calculo uma força e deixo ela agir por delta. O efeito na velocidade é indireto — vem da integração.
Muda a velocidade de uma vez
Um impulso é uma mudança instantânea na velocidade. O solver não empurra aos poucos: pergunta quanta velocidade na direção proibida existe, e remove exatamente isso. Não há parâmetro de "intensidade" — a pergunta tem uma resposta matemática.
O loop iterativo — e por que é "sequencial"
Dentro de um único passo de física o solver refaz esse cálculo várias vezes — tipicamente de 4 a 10 iterações — antes de avançar. Isso só é necessário quando um corpo participa de mais de uma constraint ao mesmo tempo: corrigir a junta 1 perturba de leve a relação que a junta 2 já tinha corrigido. A técnica se chama solver de impulsos sequenciais e é o que praticamente todo motor de jogo usa — Jolt, Bullet, PhysX.
HingeJoint3D.Solver Iterations, ajustável — mais iterações, mais estabilidade, menos desempenho.O que o Godot esconde do Jolt
03–07 agoO Godot 4.6 tornou o Jolt o motor 3D padrão — mas o que chega até mim, pela API de nós, é bem menos do que a biblioteca oferece. Vale entender por quê.
O que estou usando
Incorporado ao motor a partir da 4.4 e padrão na 4.6. É o mais conveniente — e, hoje, o mais limitado dos dois.
Mais completo, mas em manutenção
Extensão da comunidade, anterior à incorporação, hoje mantida só pra correção de bugs. O próprio repositório afirma que o módulo do motor ainda não tem paridade com ela — faltam, por exemplo, os nós de junta específicos do Jolt (JoltHingeJoint3D e equivalentes).
Joint3D, criada pro GodotPhysics3D e reaproveitada pro Jolt. O sistema de constraints do Jolt, mais rico, precisa caber num molde que não foi desenhado pra ele.PinJoint3D (por design, é uma junta propositalmente barata) — então o módulo recorre, silenciosamente, a uma junta 6DOF por baixo sempre que esses limites são configurados.Não existe junta fixa nativa
Sem forma direta de criar uma fixed constraint. A solução de contorno documentada é montar uma Generic6DOFJoint3D com os seis eixos travados na mão. Há PR em aberto propondo suporte nativo.
Não dá pra fazer juntas quebráveis
A API não expõe forma de ler a força ou o torque que uma junta está sofrendo — o que impede juntas que se rompem ao passar de um limiar. As funções existem no Jolt em C++, mas não chegam nem ao GDScript nem ao PhysicsServer3D.
A VehicleConstraint não é exposta
O modelo de veículo pronto do Jolt — reconhecido pela própria comunidade como bem superior ao VehicleBody3D nativo — não existe como nó. Há discussão aberta propondo incorporá-lo, com o autor relatando ter implementado por conta própria.
O que o repositório do Jolt revela
06–07 agoPor fim, uma exploração direta do jrouwe/JoltPhysics — sem compilar nada, só reconhecendo o que a biblioteca entrega além do que chega ao Godot.
| Pasta | Conteúdo |
|---|---|
| Jolt/ | todo o código-fonte da biblioteca |
| Docs/ | documentação, incluindo o catálogo de demonstrações |
| Samples/ | aplicativo de demonstração, com um teste por funcionalidade |
| HelloWorld/ | exemplo mínimo de integração |
| UnitTests/ | testes de validação do comportamento físico |
| Assets, Build, JoltViewer… | infraestrutura de apoio |
E a seção "Features" do README, cruzada com os cinco nós do Godot, torna a lacuna numérica:
| Constraint no Jolt | Exposta como nó no Godot? |
|---|---|
| Point | ✓ PinJoint3D |
| Hinge | ✓ HingeJoint3D |
| Slider | ✓ SliderJoint3D |
| Cone / Swing-twist | ✓ ConeTwistJoint3D (parcial) |
| 6 DOF | ✓ Generic6DOFJoint3D |
| Fixed | ✕ contorno: 6DOF com tudo travado |
| Distance (com molas) | ✕ |
| Gear · Rack and pinion · Pulley | ✕ |
| Path (trajetórias suaves) | ✕ |
| Veículos (rodas, esteiras, motos) | ✕ VehicleConstraint não exposta |
O catálogo de demonstrações (Docs/Samples.md)
A lacuna, em vídeo
Demonstrações de constraints que o Godot não expõe — Path, Swing-Twist, Gear, Rack and pinion, Pulley. Confirmação visual direta do bloco 07.
O esqueleto de volta
Estruturas articuladas com hinge e swing-twist — a mesma analogia do esqueleto do bloco 01, agora rodando.
VehicleConstraint e que eles usam raycasts ou shapecasts pra detectar o solo, simulando o veículo completo com motor, câmbio, diferenciais e suspensão. Ou seja, com fonte primária: o próprio modelo de veículo do Jolt combina raycast (contato pneu-solo) com o solver de constraints (estrutura do chassi, suspensão, transmissão). Raycast e multicorpo não são concorrentes — coexistem dentro do motor que fundamenta a quinzena inteira.Síntese e o que ficou em aberto
10 agoO paradigma
Corpo rígido livre = 6 GDL. Junta = travar parte dos 6 GDL relativos entre dois corpos; o que sobra é o que ela permite. Escolher a junta é escolher como restringir.
A autoria da força
Penalidade: eu calculo e aplico; relação aproximada; risco de divergência (caso concreto: a ejeção por atrito, resolvida com o clamp). Constraint: eu declaro; o solver calcula o impulso exato; relação exata por construção.
O raycast não foi trabalho perdido
Ele é uma versão lumped do modelo multicorpo formal — e o próprio veículo do Jolt mistura os dois. Migrar pra juntas no futuro não invalida nada do que já construí.
O experimento
TesteJunta rodou: pêndulo oscilando sem código nem força. Achado de bônus: Exclude Nodes From Collision — relevante direto pra futura junta chassi-roda.
O limite da ferramenta
O Godot expõe o Jolt por uma API Joint3D genérica e anterior a ele: implementa errado vários parâmetros e deixa de fora recursos inteiros — junta fixa, juntas quebráveis e, sobretudo, a VehicleConstraint.
Sample, replicar esse sample no Godot com nós Joint3D, ler a doc do GDExtension e espelhar o GDChrono do professor pro Jolt. Também ficaram pendentes os dois testes do bloco 05 (girar o eixo do hinge e ativar o Angular Limit).