Do sample rodando à ponte em C++
A quinzena anterior fechou o arco conceitual do multicorpo; a reunião de 10 de agosto aterrissou isso em quatro tarefas concretas, agrupadas em duas faixas. A faixa A — rodar o Jolt de verdade e medir o que o Godot não alcança — está concluída e publicada.
Esta página foi estendida até 7 de setembro pra cobrir a faixa B, que mudou de natureza depois da reunião: não é mais ler a doc do GDExtension, é escrever C++, compilar uma extensão e usar o Jolt de verdade por trás dela. O modo deixa de ser exploratório e passa a ser construtivo — mínimo, mas construtivo.
Os dois entregáveis-âncora
Comparativo formal Jolt × Godot
O documento feature a feature que fundamenta a decisão arquitetural — raycast × juntas × ponte C++. Não é uma opinião sobre qual caminho seguir: é a tabela que mostra, item por item, o que o Jolt entrega e o que o módulo embutido do Godot deixa passar. Publicado em O tanque do Jolt e o teto do Godot, com a mecânica interna destrinchada em Um corpo só, quatro bengalas.
Uma GDExtension mínima com o Jolt de verdade por trás
Um nó custom em C++ que carrega no editor e roda um PhysicsSystem do Jolt próprio, compilado por mim — não o módulo embutido do motor. Mínima de propósito: o valor não está no que ela simula, e sim em provar que o caminho existe e que eu alcanço as classes que o Godot não expõe, a começar pela VehicleConstraint.
Duas faixas em paralelo
Os quatro pontos da reunião se agrupam em dois movimentos: primeiro medir o limite do Godot na prática, depois olhar o caminho que existe pra passar por cima dele.
Faixa A · Provar até onde o Godot vai
Rodar o Jolt de verdade, mapear o gap feature a feature e testar o limite do Godot na prática — replicando no editor o mesmo cenário que o sample roda em C++.
Resultado: o gap tem nome e sobrenome. O VehicleBody3D não é a VehicleConstraint, e o módulo embutido não expõe nem ela, nem os VehicleCollisionTester, nem os controllers.
Faixa B · A ponte C++ pra além do Godot
Construir a ponte, não só ler sobre ela: montar o ambiente do godot-cpp, compilar uma extensão mínima, subir um mundo do Jolt próprio dentro dela e chegar na VehicleConstraint — a classe que a faixa A provou estar fora de alcance pelo caminho normal.
O GDChrono do professor é o molde: ele já fez exatamente isso ligando o Godot ao Project Chrono.
A sprint, dia a dia
Segunda a quarta na faixa A, a reunião de 17/ago no meio, e a faixa B retomada em 5/set com horizonte na segunda dia 7. Os três primeiros dias já aconteceram — ficam aqui como registro do que sustentou a virada.
Rodar um sample do Jolt
- Clonar
github.com/jrouwe/JoltPhysics. - Atalho sem build: abrir a página de demos web (JoltPhysics.js) e passar o olho nos samples — em especial os de Constraints e Vehicle (veículo de esteira com hinge, moto).
- Nativo: compilar o app
Samples(precisa de CMake 3.23+; no Windows é o caminho mais direto — usa DirectX; se der erro de GPU, ativar "Graphics Tools" nas features opcionais). Alternativa mínima: só a pastaHelloWorld. - Controles: começa pausado (P despausa), ESC → Select Test / Run All Tests.
- Escolher O sample-âncora da semana — de preferência um de Constraints/Vehicle, que casa direto com o hinge do meu
teste_junta.
Porquê: sem ver o Jolt rodando, o comparativo vira achismo. Fixar o sample agora trava o alvo do resto da semana.
↳ Jolt clonado + rodando + 1 sample escolhidoComparativo feature a feature
- Pro sample escolhido, listar as features que ele usa: tipo de constraint, motor, limites, callbacks, integrador.
- Pra cada uma, responder: o Jolt expõe? · o módulo Jolt embutido do Godot 4.6 expõe? (ex.:
VehicleConstraint— o Jolt tem, o Godot não expõe). - Montar a tabela: Feature | Jolt | Godot (módulo Jolt) | Observação.
Porquê: é literalmente o comparativo formal que saiu da reunião — o entregável-âncora tomando forma.
↳ Rascunho da tabela comparativaReplicar o sample no Godot
- Cena isolada nova (na linha do meu
teste_junta.tscn): reconstruir o mesmo cenário do sample com nósJoint3D(HingeJoint3D/Generic6DOFJoint3D). - Medir: o que reproduz 1:1, o que só dá pra aproximar e onde bate no limite do achado de terça.
- Cada limite encontrado volta anotado pra tabela do comparativo.
Porquê: fecha o par achado teórico → prova prática, e conecta direto com o hinge que eu já testei na quinzena passada.
↳ Cena Godot replicando o sample + limites anotadosLer a doc do GDExtension
- Ler a doc oficial do godot-cpp (docs.godotengine.org → C++ / "GDExtension C++ example") — foco no conceito, não em construir uma extensão de produção.
- Entender as peças: ABI estável, o arquivo
.gdextension,compatibility_minimum,godot-cpp+godot-cpp-template. - Anotar o essencial: o que é preciso pra expor pro Godot algo que o motor não expõe — é o caminho pra, um dia, alcançar a
VehicleConstraintdo Jolt.
Porquê: é a ponte que, no futuro, resolve o gap que o comparativo vai apontar. Ler, não implementar.
↳ Notas de conceito do GDExtensionEspelhar o GDChrono → Jolt
- Estudar a GDExtension do professor (GDChrono): como ele liga o Godot ao Project Chrono — estrutura, o que expôs, como bindou as classes.
- Traçar o raciocínio equivalente pro Jolt: se fosse um "GDJolt", que classe/constraint eu precisaria expor pra fechar o gap do comparativo? (ex.:
VehicleConstraint). - Não construir — só mapear o paralelo. Mesmo espírito do ponto 2 ("pegar um sample e replicar"), agora pela via da extensão.
Porquê: casa o ponto 2 (replicar) com o ponto 3 (GDExtension), e mostra o caminho concreto usando um exemplo que já existe dentro do meu grupo.
↳ Esboço "GDChrono → GDJolt": o que eu espelhariaConsolidar as notas
- Passar a tabela comparativa e as notas a limpo → rascunho de uma entrada nova no dossiê do Docusaurus.
- Escrever com minhas palavras, a partir do que levantei na semana.
Fechamento: o que eu levo
Os três entregáveis da semana chegam juntos — o comparativo é o que importa, os outros dois são a evidência que o sustenta.
A faixa A vira documentação publicada
O material foi passado a limpo em duas entradas novas da frente multicorpo: o comparativo Jolt × Godot e a leitura do código-fonte que destrincha a VehicleConstraint por dentro. É de lá que sai o alvo da faixa B — o nome exato da classe que precisa ser alcançada.
↳ Pontos 1 e 2 fechados e no arA faixa B deixa de ser leitura
O combinado passou a ser usar o GDExtension e o C++ pra testar o Jolt. O ponto 3 vira etapa de ambiente (compilar de fato) e o ponto 4 vira arquitetura — o GDChrono deixa de ser curiosidade e vira o molde do que eu construo.
Consequência prática: o clone em ~/Projects/JoltPhysics deixa de ser material de leitura e vira dependência de build do meu projeto.
Levantar o ambiente e ver um nó meu no editor
Sem física nenhuma ainda: instalar o scons, clonar o godot-cpp na branch da versão do editor, compilar o template e ver a classe aparecer na lista de nós. É a prova de que a ponte existe antes de ter o que passar por ela.
Onde eu cheguei
As cinco etapas saíram: extensão carregando no editor, o Jolt compilando e rodando fora do Godot, e o nó JoltVehicle com a VehicleConstraint dirigível dentro da cena. Está tudo em Dois mundos, uma cena, com vídeo.
O bloqueio caiu: o GDChrono chegou e foi lido. A decisão de arquitetura que eu tinha tomado sozinha bate com a do professor — mundo de física próprio, o mesmo formato de nó — e rendeu três pontos a copiar, além de mostrar o rover Viper sobre terreno SCM já rodando no código dele.
Faixa B · o plano de execução
Cinco etapas, em ordem de dependência: cada uma só faz sentido se a anterior fechou. As três primeiras cabem no fim de semana; a 3 é o que eu levo pra conversa; a 4 é o entregável do ciclo seguinte.
O ambiente de build
- Instalar o
scons— a máquina já temg++epython3; falta ele e, pro Jolt, ocmake. - Clonar
godotengine/godot-cppna branch que casa com a versão do editor — os projetos aqui estão em Godot 4.7. - Compilar em debug (
scons platform=linux target=template_debug) e conferir que o binário saiu. - Partir do
godot-cpp-template, apontar o arquivo.gdextensionpro binário e abrir o projeto no editor.
Porquê: é o único passo que, se falhar, invalida todos os outros. Erro aqui quase sempre é versão do godot-cpp × versão do editor — vale conferir isso antes de culpar o código.
↳ Binário compilado + .gdextension carregando sem erro no consoleUm nó que só existe
- Declarar uma classe
JoltProbeherdando deNode3D, com a macroGDCLASS, e registrá-la comGDREGISTER_CLASS. - Em
_bind_methods(), expor um método e uma propriedade — e ver essa propriedade aparecer no Inspector. - Implementar
_physics_processimprimindo odelta: confirma que o Godot chama o meu C++ a cada passo de física.
Porquê: as peças do GDExtension (.gdextension, compatibility_minimum, registro de classe, binding de métodos) só ficam claras quando o Inspector responde. É a leitura do ponto 3, só que verificada.
Jolt puro, sem o Godot no caminho
- Compilar o
HelloWorld/HelloWorld.cppdo clone (CMake) — valida a biblioteca sozinha, sem nenhuma ponte envolvida. - Trocar a esfera caindo por um
VehicleConstraintde quatro rodas:WheeledVehicleController+VehicleCollisionTesterRayem chão plano. O gabarito éSamples/Tests/Vehicle/VehicleConstraintTest.cpp. - Rodar N passos e imprimir, por roda:
mSuspensionLength, o impulso de suspensão e o impulso lateral.
Porquê: isola o problema. Se mais adiante a extensão der errado, eu já sei se o Jolt sozinho estava certo. E é a primeira vez que eu escrevo a VehicleConstraint em vez de só ler o header dela.
A decisão de arquitetura
- Escrever a escolha entre os dois desenhos (tabela abaixo) e o porquê — com a evidência da faixa A sustentando o descarte.
- Anotar as consequências: as flags de compilação do Jolt precisam bater entre a lib e a extensão (senão a ABI quebra em silêncio), o passo tem que ser fixo, e é preciso definir quem é dono do estado.
- Pedir o GDChrono ao professor e comparar a minha escolha com a que ele já fez.
Porquê: é o ponto 4 na sua forma útil. Não é mais "espelhar o raciocínio": é decidir o desenho do meu projeto tendo o dele como referência.
↳ Página de decisão publicada + pedido do GDChrono enviadoJuntar as duas metades
- Um nó
JoltVehicleque chamaPhysicsSystem::Updatecom passo fixo dentro do_physics_process. - Copiar as transforms do corpo e das quatro rodas pros
MeshInstance3Dda cena — o Godot só desenha. - Ligar o input do Godot em
SetDriverInput(forward, right, brake, handBrake).
Porquê: é a prova visual de que a ponte fechou o vão que o comparativo apontou — o veículo do Jolt rodando dentro do Godot, com a suspensão que o VehicleBody3D não dá.
PhysicsSystem; o Godot vira renderizador e input. Acesso total à VehicleConstraint e aos testers. É o caminho.O que o GDChrono respondeu — e o que sobrou
- Respondido: a arquitetura. O professor também roda um mundo de física próprio dentro da extensão, com o mesmo formato de nó. A escolha da etapa 3 estava certa.
- Respondido de graça: onde isso chega. O código dele já tem o rover Viper articulado sobre SCMTerrain deformável — o destino das frentes de roda–solo e validação, em código legível.
- Ainda em aberto: se vale migrar o build todo para CMake, como ele fez — na estrutura dele o problema de paridade de ABI não existe, em vez de ser administrado.
- Ainda em aberto: quando saltar do veículo de um corpo para o rover articulado. Agora dá pra fazer a pergunta com o exemplo dele na mão.
O que sai desta sprint
Pra reunião de 17 de agosto · ✔ entregue
- Comparativo formal Jolt × Godot — a decisão arquitetural fundamentada feature a feature (o entregável-âncora da faixa A).
- Cena Godot replicando o sample — com os limites do módulo Jolt anotados onde eu bati na parede.
- Três entradas publicadas na frente multicorpo, incluindo a leitura do código-fonte da
VehicleConstraint.
Pra segunda, 7 de setembro · em execução
- GDExtension mínima carregando no editor — nó custom em C++ com propriedade no Inspector (etapas 0 e 1).
- Jolt compilado fora do Godot rodando um
VehicleConstraintde quatro rodas, com telemetria no terminal (etapa 2). - A decisão de arquitetura escrita — mundo Jolt próprio, com as consequências de build anotadas (etapa 3).
- O pedido do GDChrono feito ao professor — o item bloqueante, que sai primeiro.
Na faixa B eu NÃO vou
Construir, sim — mas o mínimo que prova o caminho. A extensão existe pra demonstrar acesso, não pra virar produto.
- Montar o rover articulado em multicorpo
- Mexer em powertrain, suspensão ou terreno deformável
- Empacotar a extensão pra produção — multiplataforma, CI, release
- Reescrever a
VehicleConstraint(usar a do Jolt, não refazer) - Trocar ou aposentar o protótipo raycast
De onde eu parto
O arco conceitual está fechado e publicado em Constraints, juntas e o Jolt por dentro: penalidade × constraint, a tabela de GDL das juntas do Godot, o experimento TesteJunta com HingeJoint3D e o levantamento das lacunas do módulo Jolt embutido.
Ou seja: eu já sabia qual era o gap no papel. A faixa A provou esse gap rodando o Jolt de verdade e o transformou numa tabela. A faixa B é o passo seguinte — atravessar o gap, em vez de continuar medindo ele.