@pose_flow/babylon 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +123 -3
- package/dist/AI_USAGE.md +291 -0
- package/dist/PUBLISHING.md +108 -0
- package/dist/babylon.d.ts +38 -0
- package/dist/babylon.js +201 -0
- package/dist/core/controller.d.ts +33 -0
- package/dist/core/controller.js +97 -0
- package/dist/core/database.d.ts +12 -0
- package/dist/core/database.js +95 -0
- package/dist/core/features.d.ts +15 -0
- package/dist/core/features.js +41 -0
- package/dist/core/profile.d.ts +54 -0
- package/dist/core/profile.js +89 -0
- package/dist/core/root-motion.d.ts +24 -0
- package/dist/core/root-motion.js +78 -0
- package/dist/core/schema.d.ts +56 -0
- package/dist/core/schema.js +123 -0
- package/dist/core/search.d.ts +17 -0
- package/dist/core/search.js +97 -0
- package/dist/core/types.d.ts +75 -0
- package/dist/core/types.js +3 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/offline/src/babylon.js +201 -0
- package/dist/offline/src/core/controller.js +97 -0
- package/dist/offline/src/core/database.js +95 -0
- package/dist/offline/src/core/features.js +41 -0
- package/dist/offline/src/core/profile.js +89 -0
- package/dist/offline/src/core/root-motion.js +78 -0
- package/dist/offline/src/core/schema.js +123 -0
- package/dist/offline/src/core/search.js +97 -0
- package/dist/offline/src/core/types.js +3 -0
- package/dist/offline/src/index.js +8 -0
- package/dist/offline/tools/bake.js +86 -0
- package/dist/offline/tools/cli.js +30 -0
- package/dist/offline/tools/glb.js +54 -0
- package/dist/offline/tools/prepare.js +165 -0
- package/dist/offline/tools/profile-assets.js +90 -0
- package/dist/offline/tools/rig.js +47 -0
- package/dist/offline/tools/validate-assets.js +43 -0
- package/package.json +48 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Motion Match contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,123 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# Motion Match · Babylon.js
|
|
2
|
+
|
|
3
|
+
O código original desta biblioteca é distribuído sob a [licença MIT](LICENSE), com aviso de copyright “2026 Motion Match contributors”. Dependências, modelos, texturas e animações de terceiros mantêm suas próprias licenças; este aviso não os relicencia. Consulte a [proveniência dos assets](docs/ASSETS.md).
|
|
4
|
+
|
|
5
|
+
Biblioteca TypeScript de Motion Matching clássico com Pose Search e laboratório 3D. Inspiração conceitual no Unreal Engine; implementação própria e inicial, sem paridade com o plugin da Epic.
|
|
6
|
+
|
|
7
|
+
O banco compara **pose visível + velocidade + trajetória desejada** e seleciona clipe/tempo. O controlador do jogo continua responsável por posição, colisões, orientação e combate.
|
|
8
|
+
|
|
9
|
+
**Prioridade atual: biblioteca reutilizável para diferentes personagens e jogos.** Modelo/rig/escala são definidos por perfis JSON v2, que referenciam schemas v1 e conjuntos de animações v1 separados, compartilhados pelo bake e laboratório. Veja [como adicionar um personagem](docs/PROFILES.md). Há também o exemplo Barbarian com escala e sample rate próprios.
|
|
10
|
+
|
|
11
|
+
O [roadmap revisado de Motion Matching + Pose Search](docs/ROADMAP.md) prioriza schemas configuráveis, preparação genérica de rigs/animações e conjuntos por contexto para chegar à versão estável. A Fase 1 está implementada: [schemas configuráveis e migração](docs/SCHEMAS.md). A Fase 2 está concluída no escopo documentado e inclui preparação GLB seletiva, recorte temporal, composição de loops medidos, hashes de assets, conferência de bind e CLI offline; retargeting automático continua futuro.
|
|
12
|
+
|
|
13
|
+
O MMORPG será usado como consumidor de teste durante o desenvolvimento, em paralelo ao laboratório. Ajustes e problemas com prints, código, logs e erros são acompanhados em [task/summary.md](task/summary.md); veja o [modelo e instruções](task/README.md). A integração prática não precisa aguardar o término do roadmap.
|
|
14
|
+
|
|
15
|
+
## Guias distribuídos com o pacote
|
|
16
|
+
|
|
17
|
+
- [Tutorial para IA integrar a biblioteca](dist/AI_USAGE.md) — fonte em docs/AI_USAGE.md.
|
|
18
|
+
- [Comandos de publicação](dist/PUBLISHING.md) — fonte em docs/PUBLISHING.md.
|
|
19
|
+
|
|
20
|
+
O build copia os guias para dist/ e prepack executa o build antes de empacotar. Implementações e correções devem atualizar o tutorial na mesma alteração, conforme AGENTS.md.
|
|
21
|
+
|
|
22
|
+
## Executar
|
|
23
|
+
|
|
24
|
+
```powershell
|
|
25
|
+
npm ci
|
|
26
|
+
npm run dev
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Abrir http://127.0.0.1:5173. WASD movimenta, Shift corre, arraste orbita e scroll aproxima. O seletor oferece Knight, Paladin, Barbarian e Knight com schema de mãos (33 dimensões). “Teste de locomoção” mantém um movimento ativo para inspeção, sem segurar teclas; voltar a “Manual” devolve o controle ao WASD. “Manter orientação” permite testar deslocamento lateral e para trás no modo manual. O painel mostra candidato, custo, tempo, transições e velocidade. O valor “Atualização MM” inclui o controlador e só inclui busca quando o intervalo vence.
|
|
30
|
+
|
|
31
|
+
Os GLB e bancos já foram gerados neste workspace. Para regenerar:
|
|
32
|
+
|
|
33
|
+
```powershell
|
|
34
|
+
npm run bake
|
|
35
|
+
npm run bake -- --paladin
|
|
36
|
+
npm run validate:assets -- --profile public/profiles/barbarian.json
|
|
37
|
+
npm run bake -- --profile public/profiles/barbarian.json
|
|
38
|
+
npm run bake -- --profile public/profiles/kaykit-hands.json
|
|
39
|
+
npm run typecheck
|
|
40
|
+
npm test
|
|
41
|
+
npm run build
|
|
42
|
+
npm run benchmark
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
O build produz `dist/` (biblioteca ESM + declarações) e `demo-dist/` (laboratório). O pacote npm inclui a biblioteca e os guias de integração/publicação, sem personagens. A publicação inicial 0.1.0 foi informada pelo mantenedor; os novos guias estarão disponíveis após a próxima publicação.
|
|
46
|
+
|
|
47
|
+
## Implementado
|
|
48
|
+
|
|
49
|
+
- Núcleo sem engine: schemas configuráveis de características (preset original de 27 dimensões e exemplo de 33), normalização compartilhada, busca exata ponderada em `Float32Array`, filtros de gait e banco versionado JSON + float32 little endian.
|
|
50
|
+
- Continuidade: avanço natural, loops, fim de clipe, intervalo de busca, tempo mínimo entre trocas e margem de melhora. Defaults de tuning, não parâmetros oficiais do Unreal.
|
|
51
|
+
- Predição com aceleração, frenagem e velocidade angular; horizontes configuráveis (preset: 0,2 / 0,4 / 0,6 s).
|
|
52
|
+
- Adaptador Babylon.js 7.54.3: leitura dos pés visíveis e reprodução com crossfade, incluindo saltos entre dois tempos do mesmo clipe.
|
|
53
|
+
- Bake offline via o mesmo carregador/interpolador Babylon usado na demonstração.
|
|
54
|
+
- Quatro bancos separados: **Knight com mãos, 174 poses / 6 clipes / 33 dimensões**; **Knight, 174 poses / 6 clipes**; **Paladin, 610 poses / 9 clipes**; **Barbarian, 138 poses / 6 clipes**. Todos têm idle, walk, run, backward, left, right; o Paladin inclui stop, turn-left e turn-right sem loop.
|
|
55
|
+
- Trajetória medida dos hips para os três novos clipes: posição, yaw contínuo, velocidade, interpolação e término sem repetir o início. Os dados extraídos alimentam apenas o bake; deslocamento e heading em runtime continuam definidos pelo controlador.
|
|
56
|
+
- Pipeline Blender 5.2 para inspecionar e converter os FBX locais do Paladin.
|
|
57
|
+
|
|
58
|
+
Banco/perfil agora são v2. decodeDatabase rejeita banco v1; usar migração explícita ou novo bake conforme [SCHEMAS.md](docs/SCHEMAS.md). API local ainda sem publicação; conferir os tipos e o guia da versão instalada.
|
|
59
|
+
|
|
60
|
+
## Features e coordenadas
|
|
61
|
+
|
|
62
|
+
A tabela abaixo descreve somente o preset original `LOCOMOTION_SCHEMA`. Para outros schemas, usar os offsets de `compileSchema`.
|
|
63
|
+
|
|
64
|
+
| Índices | Característica |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| 0–5 | Posição local dos dois pés, XYZ |
|
|
67
|
+
| 6–11 | Velocidade dos pés no mundo, expressa nos eixos locais, XYZ |
|
|
68
|
+
| 12–14 | Velocidade do controlador nos eixos locais, XYZ |
|
|
69
|
+
| 15–20 | Posições futuras locais, XZ, em três horizontes |
|
|
70
|
+
| 21–26 | Direções futuras locais, XZ, em três horizontes |
|
|
71
|
+
|
|
72
|
+
Metros, segundos, Y acima e Z frente. A demo e o bake usam `scene.useRightHandedSystem = true`. Nesse referencial, o lado anatômico esquerdo dos modelos olhando +Z aponta para +X; yaw positivo gira +Z em direção a +X. A direita da câmera é calculada por sua projeção, não por assumir +X. Query e banco precisam usar exatamente a mesma convenção e escala. Não mudar a convenção do MMORPG para importar a lib; adaptar seu referencial ou gerar banco compatível.
|
|
73
|
+
|
|
74
|
+
Peso inicial por dimensão: pose/velocidade 1, trajetória/direção 3. Dimensões com desvio abaixo de 0,0001 usam escala 1, evitando amplificar canais constantes em bancos sem giros. Filtros são opcionais; a demonstração pesquisa todos os clipes.
|
|
75
|
+
|
|
76
|
+
**Os conjuntos são reproduzidos in-place.** Nos seis loops básicos, velocidades em `tools/bake.ts` são parâmetros de autoria: frente 1,8/4,5 m/s; costas −1,5 m/s; strafe KayKit ±3,2 m/s; strafe Paladin ±1,8 m/s. São valores iniciais, não medidas. Esquerda usa +X e direita −X. O bake KayKit remove as mesmas trilhas de deslocamento/heading variável que o player. Orientação constante é parte da pose; o conjunto usa rootOrientation com yaw ±90° para alinhar os strafes originalmente diagonais (±60°) ao deslocamento lateral. O laboratório testa esses clipes na velocidade nominal declarada de 3,2 m/s.
|
|
77
|
+
|
|
78
|
+
Para **stop e giros do Paladin**, Blender registra posição planar e yaw dos hips antes de remover esses movimentos da animação. Os arquivos `.motion.json` são amostrados em relação ao heading atual; futuros além do fim ficam no último estado. A velocidade dos pés inclui a contribuição da rotação do referencial. O movimento vertical do esqueleto é preservado. A orientação é um proxy extraído da pelvis e inclui oscilação natural; não equivale a root motion limpo de produção. Foot sliding ainda pode acontecer.
|
|
79
|
+
|
|
80
|
+
O laboratório tem ciclos de parada e giros no seletor do Paladin. Filtros por estado disponibilizam parada durante frenagem e giro durante mudança de heading com baixa velocidade. A busca decide o clipe/tempo dentro dos candidatos permitidos. Clips concluídos ficam inelegíveis por 0,6 s (configurável em `reselectDelay`). `Query.excludedClips` permite outras exclusões explícitas. O painel exibe a origem da trajetória e as três últimas trocas.
|
|
81
|
+
|
|
82
|
+
## API
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { decodeDatabase, MotionMatcher, SchemaQueryBuilder, predictTrajectory } from '@pose_flow/babylon';
|
|
86
|
+
import { BabylonMotionPlayer, BabylonSchemaPoseReader } from '@pose_flow/babylon/babylon';
|
|
87
|
+
|
|
88
|
+
// manifest e bytes são carregados uma vez; sem bake durante o jogo.
|
|
89
|
+
const builder = new SchemaQueryBuilder(schema);
|
|
90
|
+
const database = decodeDatabase(manifest, bytes, builder.layout.schema);
|
|
91
|
+
const matcher = new MotionMatcher(database);
|
|
92
|
+
// sources: Map<clip.id, AnimationGroup>; nodes: Map<nome original do osso, TransformNode>.
|
|
93
|
+
// semanticNodes: Map<papel do schema, TransformNode>; schema carregado/validado offline.
|
|
94
|
+
const player = new BabylonMotionPlayer(scene, manifest.clips, sources, nodes);
|
|
95
|
+
const reader = new BabylonSchemaPoseReader(controllerRoot, semanticNodes, builder.layout.schema);
|
|
96
|
+
|
|
97
|
+
// A cada frame, usando a pose medida após a renderização anterior:
|
|
98
|
+
const future = predictTrajectory(trajectoryInput, builder.layout.horizons);
|
|
99
|
+
const query = builder.build(lastVisiblePose, future);
|
|
100
|
+
const playback = matcher.update(dt, query);
|
|
101
|
+
player.update(playback, dt); // antes de scene.render()
|
|
102
|
+
scene.render();
|
|
103
|
+
lastVisiblePose = reader.read(dt); // depois da avaliação de animações
|
|
104
|
+
|
|
105
|
+
// Em teleporte/reconciliação descontínua: reader.reset(); matcher.reset().
|
|
106
|
+
// Na remoção do personagem: player.dispose().
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Instalar localmente no jogo, quando integrar: `npm install D:/motion_match`. Copiar os assets/banco necessários para a pasta pública do jogo é uma etapa separada. Ver contrato e restrições em [docs/INTEGRATION.md](docs/INTEGRATION.md).
|
|
110
|
+
|
|
111
|
+
## Limites atuais
|
|
112
|
+
|
|
113
|
+
Ainda não há IK, foot locking, contato dos pés, inertialization, motion warping, root-motion-driven movement, worker, KD-tree ou PCA. Starts e giros em movimento ainda não foram preparados. Os três clipes medidos do perfil Paladin legado são sem loop; há composição de ciclos de trajetórias medidas no núcleo/bake, com caminhada medida do Paladin preparada e conferida no laboratório. A busca linear é apropriada para medir esta base pequena; não há garantia de orçamento em bancos grandes ou com muitos jogadores.
|
|
114
|
+
|
|
115
|
+
Schemas JSON configuráveis não incluem editor visual nem histórico temporal de ossos. Não há retargeting automático entre esqueletos diferentes. KayKit e Mixamo possuem bancos e mapas de ossos independentes. Crossfade de clips com trilhas ausentes exige preparação de cobertura dos ossos.
|
|
116
|
+
|
|
117
|
+
O laboratório tem um bundle de demonstração grande pelo carregamento amplo de Babylon; o build avisa sobre isso. O núcleo da lib não depende de Babylon, e sua entrada pública separada permite usá-lo sem importar o adaptador.
|
|
118
|
+
|
|
119
|
+
## Referências e proveniência
|
|
120
|
+
|
|
121
|
+
- [Epic: Motion Matching](https://dev.epicgames.com/documentation/en-us/unreal-engine/motion-matching-in-unreal-engine): banco, pose, trajetória e busca.
|
|
122
|
+
- [Babylon: Advanced Animations](https://doc.babylonjs.com/features/featuresDeepDive/animation/advanced_animations): grupos de animação e pesos. A implementação foi validada contra o código instalado da versão 7.54.3.
|
|
123
|
+
- [Assets locais](docs/ASSETS.md), [evidências e pendências](docs/VALIDATION.md), [referência fornecida pelo usuário](MOTION_MATCHING_POSE_SEARCH_WEB_BASE_REFERENCIAS.md).
|
package/dist/AI_USAGE.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# Tutorial de integração para IA — @pose_flow/babylon
|
|
2
|
+
|
|
3
|
+
Contrato local em desenvolvimento, revisado em 28/10/2026: Fases 1 e 2, com perfis v2, bancos v2 e schemas v1. A versão publicada 0.1.0 não contém estas APIs; conferir a versão instalada e a migração antes de integrar. **Ler este documento antes de integrar ou modificar o uso da biblioteca.** Conferir também os arquivos .d.ts da versão instalada. Não presumir recursos futuros a partir do nome “motion matching”.
|
|
4
|
+
|
|
5
|
+
Fonte mantida no repositório: docs/AI_USAGE.md. Build: dist/AI_USAGE.md. Após instalar pelo npm: node_modules/@pose_flow/babylon/dist/AI_USAGE.md. Também pode ser localizado com `import.meta.resolve('@pose_flow/babylon/AI_USAGE.md')` em Node ESM, sem importar o Markdown como JavaScript.
|
|
6
|
+
|
|
7
|
+
## 1. Escopo e instalação
|
|
8
|
+
|
|
9
|
+
Biblioteca TypeScript/ESM de busca de poses e reprodução de locomoção, com canais configuráveis de ossos e trajetória; os exemplos validados são bípedes. Não depende de MMORPG, servidor específico ou personagem específico. O núcleo não importa Babylon; o adaptador é uma entrada separada.
|
|
10
|
+
|
|
11
|
+
```powershell
|
|
12
|
+
npm install @pose_flow/babylon @babylonjs/core@7.54.3 @babylonjs/loaders@7.54.3
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Se Babylon já estiver instalado, respeitar as versões do projeto; a faixa peer atual é ^7.54.3, e a validação foi feita em 7.54.3. Não declarar compatibilidade com Babylon 8/9 sem teste.
|
|
16
|
+
|
|
17
|
+
O pacote local distribui runtime JS, tipos, licença, README, estes guias e CLI offline `pose-flow` para inspeção/preparação/validação/bake. Não inclui Blender, assets, perfis ou bancos prontos. A versão publicada ainda deve ser conferida. Os comandos `npm run bake` e `npm run validate:assets` abaixo são do repositório de desenvolvimento, não scripts automaticamente instalados no consumidor.
|
|
18
|
+
|
|
19
|
+
## 2. Contrato dos dados
|
|
20
|
+
|
|
21
|
+
Preparar uma vez, offline, um perfil JSON v2, um schema JSON v1, um conjunto de animações JSON v1, os GLB e um banco v2 com manifest.json + poses.bin. Servir esses arquivos pela pasta pública do projeto consumidor. Nunca reconstruir todo o banco em cada carregamento de avatar.
|
|
22
|
+
|
|
23
|
+
- Metros, segundos, Y acima, frente +Z. Bake/laboratório usam cena right-handed. Yaw positivo gira +Z para +X. +X coincide com a esquerda anatômica dos exemplos olhando +Z; não confundir com direita da câmera.
|
|
24
|
+
- Não mudar a convenção de toda uma cena existente para adaptar esta lib; adaptar os dados/referenciais do personagem ou gerar banco correspondente.
|
|
25
|
+
- Controller raiz deve ter escala 1; aplicar profile.scale nos rootNodes do modelo, não no controller. A escala das fontes no bake deve coincidir com a do modelo.
|
|
26
|
+
- `rig` mapeia papéis semânticos do schema aos nomes de nodes do modelo; `rig.root` continua obrigatório para validar o rig. boneMap associa nomes das fontes aos do modelo; não faz retargeting de bind pose, proporções ou orientação local.
|
|
27
|
+
- Animações são in-place. stripRoot é opcional e remove as trilhas de posição (inclusive componentes) e a variação de rotação do node indicado. Uma rotação constante de autoria integra a pose e é preservada; canais de rotação com tangentes não são considerados constantes. Usar apenas quando essa política reproduzir o que foi indexado no bake. Sem ele, passar string vazia ao player e fornecer clipes já preparados.
|
|
28
|
+
- Cada clipe usa nominalVelocity OU motionFile. Velocidade nominal é autoria em m/s finais, não uma medida. motionFile é entrada offline com trajetória medida de hips (proxy de pelvis) ou root dedicado; aceita looping com composição de ciclos.
|
|
29
|
+
- Features são definidas pelo schema. O preset `LOCOMOTION_SCHEMA` preserva 27 dimensões: pés XYZ (0–5), velocidades dos pés no mundo expressas localmente (6–11), velocidade do controller local (12–14), posições futuras XZ (15–20) e direções futuras XZ (21–26), em +0,2/+0,4/+0,6 s. Outros schemas usam dimensões/roles/horizontes próprios; usar `SchemaQueryBuilder`, sem offsets fixos.
|
|
30
|
+
- poses.bin guarda float32 normalizados little endian; manifest guarda mean/std usados também pela query. Usar decodeDatabase; não normalizar a query duas vezes.
|
|
31
|
+
|
|
32
|
+
Perfil v2 para um rig já compatível (trocar nomes e arquivos pelos reais):
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"version": 2, "id": "hero", "label": "Hero",
|
|
37
|
+
"assetBase": "/assets/hero/", "model": "Hero.glb", "database": "/mm/hero/",
|
|
38
|
+
"scale": 1, "sampleRate": 30,
|
|
39
|
+
"rig": { "root": "root", "leftFoot": "foot.l", "rightFoot": "foot.r" },
|
|
40
|
+
"stripRoot": "root",
|
|
41
|
+
"schema": "/schemas/biped-locomotion.json",
|
|
42
|
+
"animationSet": "/animation-sets/hero.json"
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
O arquivo do conjunto contém `{ "version": 1, "id": "hero-locomotion", "clips": [...] }`. Cada clipe mantém id/file/animation/gait/looping e nominalVelocity OU motionFile. Pode declarar rootOrientation: [x,y,z,w], quaternion unitário local absoluto para preparar a orientação estática do root indicado por stripRoot. Por exemplo: `{ "id":"walk", "file":"Locomotion.glb", "animation":"Walk", "gait":"walk", "looping":true, "nominalVelocity":[0,0,1.8] }`. Copiar o preset de schema do repositório; para fornecê-lo pelo runtime, serializar `LOCOMOTION_SCHEMA`. Os JSON externos não vêm no npm.
|
|
47
|
+
|
|
48
|
+
### Canais de schema v1
|
|
49
|
+
|
|
50
|
+
`{ version: 1, id: 'meu-schema', channels: [...] }`. Cada canal declara `id` único, `kind`, `weight` não negativo por dimensão e `normalization: 'standard' | 'none'`. Pelo menos um peso deve ser positivo.
|
|
51
|
+
|
|
52
|
+
| kind | Opções | Dimensões |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| bone-position | bone: papel semântico | XYZ atual, 3 |
|
|
55
|
+
| bone-velocity | bone: papel semântico | Velocidade no mundo em eixos atuais locais, 3 |
|
|
56
|
+
| root-velocity | nenhuma | Velocidade local do controller, 3 |
|
|
57
|
+
| trajectory-position | horizons: segundos futuros | XZ por horizonte, 2 × amostras |
|
|
58
|
+
| trajectory-facing | horizons: segundos futuros | Direção XZ por horizonte, 2 × amostras |
|
|
59
|
+
|
|
60
|
+
Exemplo de canal: `{ "id":"hand", "kind":"bone-position", "bone":"leftHand", "weight":0.5, "normalization":"standard" }`; mapear `leftHand` em `profile.rig`. Exemplo de trajetória: `{ "id":"path", "kind":"trajectory-position", "horizons":[0.15,0.35,0.75,1], "weight":3, "normalization":"standard" }`.
|
|
61
|
+
|
|
62
|
+
`standard` usa média/desvio por dimensão; desvio abaixo de 0,0001 recebe escala 1. `none` usa média 0/escala 1. Custo: soma de peso × diferença normalizada². Limites iniciais: até 128 canais, 64 horizontes por canal e na união global, em ordem crescente dentro de (0,10] s. Posição/velocidade de ossos são da pose atual; histórico/offsets temporais de ossos não estão implementados. Opções desconhecidas no schema são rejeitadas.
|
|
63
|
+
|
|
64
|
+
`compileSchema` deriva dimensões, offsets, roles e a união ordenada dos horizontes de todos os canais. Usar `predictTrajectory(input, builder.layout.horizons)`, inclusive se posição e direção tiverem horizontes distintos. Um schema só de ossos aceita trajetória vazia. `rootMotionFeatures(track,time,step,horizons)` aceita a mesma união no bake medido.
|
|
65
|
+
|
|
66
|
+
`SchemaQueryBuilder.build(pose, trajectory)` retorna features brutas + schemaSignature. `SchemaPose` contém `rootVelocity` e `bones: { [papel]: {position:[x,y,z], velocity:[x,y,z]} }`. O leitor Babylon genérico recebe `Map<papel, TransformNode>`. O manifest v2 embute schema completo, dimensões, horizontes e identidade canônica, além de mean/std. A identidade considera id, versão e conteúdo ordenado dos canais, incluindo pesos/normalização; não é um hash com perda. Não editá-la manualmente. Carregar com `decodeDatabase(manifest, bytes, expectedSchema)` e manter a assinatura produzida pelo builder na query. A busca rejeita incompatibilidades mesmo se as dimensões coincidirem.
|
|
67
|
+
|
|
68
|
+
### Migração da base 0.1.0
|
|
69
|
+
|
|
70
|
+
O decoder rejeita bancos v1: fazer novo bake com perfil v2 ou chamar explicitamente `migrateLegacyDatabase(oldManifest, oldBytes)`. Esse helper valida apenas o antigo preset de 27 dimensões/0,2/0,4/0,6 s e retorna Database v2 sem I/O, preservando estatísticas e features normalizadas. Para salvar, usar db.manifest e encodeFeatures(db). Não migra perfis/fingerprint nem transforma um banco para outro schema. Nunca trocar só a versão ou reinterpretar os bytes. O laboratório com perfil v2 exige novo bake.
|
|
71
|
+
|
|
72
|
+
Para migrar o perfil: mover clips para o JSON de conjunto v1, remover clips do perfil, declarar version:2, schema e animationSet. No carregamento, chamar parseProfile, carregar as duas referências e chamar resolveProfile; passar o perfil **resolvido** a profileSignature. Regenerar banco se mudar qualquer uma das configurações. O conteúdo dos GLB é registrado separadamente em assetHashes no manifesto.
|
|
73
|
+
|
|
74
|
+
Os helpers antigos featureVector/BabylonPoseReader e constantes DIMENSIONS/HORIZONS permanecem exclusivos do preset original. buildDatabase sem terceiro argumento e defaultWeights() selecionam esse preset; customizar com buildDatabase(metadata, raw, schema) e defaultWeights(schema). Queries sem schemaSignature só são aceitas no preset original exato. Novas integrações devem usar o builder. Esta mudança de formatos/perfis exige migração e deve ter versão 0.x apropriada antes de publicar; nenhum pacote novo foi publicado por esta implementação.
|
|
75
|
+
|
|
76
|
+
No repositório da lib, após copiar assets e perfil:
|
|
77
|
+
|
|
78
|
+
```powershell
|
|
79
|
+
npm run validate:assets -- --inspect public/assets/hero/Hero.glb
|
|
80
|
+
npm run validate:assets -- --profile public/profiles/hero.json
|
|
81
|
+
npm run bake -- --profile public/profiles/hero.json
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Inspeção sugere nomes, preserva ambiguidades e não transforma um rig incompatível. Registrar perfis em public/profiles/index.json apenas para o laboratório. Regenerar banco se alterar perfil, GLB, escala ou clipes. A fingerprint identifica configuração, não substitui hash dos arquivos GLB.
|
|
85
|
+
|
|
86
|
+
## 3. Exemplo completo do adaptador
|
|
87
|
+
|
|
88
|
+
O exemplo abaixo é um módulo TypeScript para o consumidor. O jogo fornece uma Scene já compatível e um controller TransformNode sem escala que ele próprio movimenta. Usar uma instância de player/matcher/reader por personagem; fontes e banco podem ser compartilhados numa integração mais avançada. Aqui os recursos são próprios para tornar o ciclo de vida explícito.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { SceneLoader, TransformNode, type Scene, type AnimationGroup, type AssetContainer } from '@babylonjs/core';
|
|
92
|
+
import '@babylonjs/loaders/glTF/index.js';
|
|
93
|
+
import {
|
|
94
|
+
parseProfile, resolveProfile, profileSignature, decodeDatabase, MotionMatcher,
|
|
95
|
+
SchemaQueryBuilder, predictTrajectory, filterLocomotionGaits, toLocal,
|
|
96
|
+
type DatabaseManifest, type TrajectoryInput, type Gait,
|
|
97
|
+
} from '@pose_flow/babylon';
|
|
98
|
+
import { BabylonMotionPlayer, BabylonSchemaPoseReader } from '@pose_flow/babylon/babylon';
|
|
99
|
+
|
|
100
|
+
export async function createMotionAvatar(scene: Scene, controller: TransformNode, profileUrl: string) {
|
|
101
|
+
if (!scene.useRightHandedSystem) throw new Error('Preparar banco/referencial compatível com a cena antes da integração.');
|
|
102
|
+
const json = async (url: string) => {
|
|
103
|
+
const response = await fetch(url);
|
|
104
|
+
if (!response.ok) throw new Error(`Falha ao carregar ${url}: ${response.status}`);
|
|
105
|
+
return response.json();
|
|
106
|
+
};
|
|
107
|
+
const config = parseProfile(await json(profileUrl));
|
|
108
|
+
const [schemaJSON, setJSON] = await Promise.all([json(config.schema), json(config.animationSet)]);
|
|
109
|
+
const profile = resolveProfile(config, schemaJSON, setJSON);
|
|
110
|
+
const builder = new SchemaQueryBuilder(profile.schemaDefinition);
|
|
111
|
+
const manifest = await json(profile.database + 'manifest.json') as DatabaseManifest;
|
|
112
|
+
if (manifest.profileId !== profile.id || manifest.profileSignature !== profileSignature(profile)) {
|
|
113
|
+
throw new Error('Banco e perfil divergentes. Regenerar offline.');
|
|
114
|
+
}
|
|
115
|
+
const response = await fetch(profile.database + 'poses.bin');
|
|
116
|
+
if (!response.ok) throw new Error('Banco binário ausente');
|
|
117
|
+
const db = decodeDatabase(manifest, await response.arrayBuffer(), builder.layout.schema);
|
|
118
|
+
const owned: AssetContainer[] = [];
|
|
119
|
+
let player: BabylonMotionPlayer | undefined;
|
|
120
|
+
try {
|
|
121
|
+
const body = await SceneLoader.LoadAssetContainerAsync(profile.assetBase, profile.model, scene);
|
|
122
|
+
owned.push(body); body.animationGroups.forEach(g => g.stop()); body.addAllToScene();
|
|
123
|
+
for (const node of body.rootNodes) {
|
|
124
|
+
node.parent = controller;
|
|
125
|
+
if (node instanceof TransformNode) node.scaling.scaleInPlace(profile.scale);
|
|
126
|
+
}
|
|
127
|
+
const nodes = new Map(body.transformNodes.map(n => [n.name, n]));
|
|
128
|
+
for (const name of Object.values(profile.rig)) if (!nodes.has(name)) throw new Error(`Osso ausente: ${name}`);
|
|
129
|
+
const targets = new Map(nodes);
|
|
130
|
+
for (const [source, target] of Object.entries(profile.boneMap ?? {})) {
|
|
131
|
+
const node = nodes.get(target); if (!node) throw new Error(`Destino ausente: ${target}`);
|
|
132
|
+
targets.set(source, node);
|
|
133
|
+
}
|
|
134
|
+
const sources = new Map<string, AnimationGroup>();
|
|
135
|
+
for (const file of new Set(manifest.clips.map(c => c.file))) {
|
|
136
|
+
const asset = await SceneLoader.LoadAssetContainerAsync(profile.assetBase, file, scene);
|
|
137
|
+
owned.push(asset); asset.animationGroups.forEach(g => g.stop());
|
|
138
|
+
for (const clip of manifest.clips.filter(c => c.file === file)) {
|
|
139
|
+
const group = asset.animationGroups.find(g => g.name === clip.animation);
|
|
140
|
+
if (!group) throw new Error(`Clipe ausente: ${clip.animation}`);
|
|
141
|
+
sources.set(clip.id, group);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const playback = new BabylonMotionPlayer(scene, manifest.clips, sources, targets, 0.15, profile.stripRoot ?? '');
|
|
145
|
+
player = playback;
|
|
146
|
+
const reader = new BabylonSchemaPoseReader(controller,
|
|
147
|
+
new Map(builder.layout.bones.map(role => [role, nodes.get(profile.rig[role])!])), builder.layout.schema);
|
|
148
|
+
const matcher = new MotionMatcher(db);
|
|
149
|
+
const available = new Set(manifest.clips.map(c => c.gait));
|
|
150
|
+
const initial = Math.max(0, manifest.clips.findIndex(c => c.gait === 'idle'));
|
|
151
|
+
playback.update({ clip: initial, time: 0, switched: true, match: null }, 0);
|
|
152
|
+
// Avaliar uma vez para obter a pose inicial antes de iniciar a query.
|
|
153
|
+
// Fazer durante inicialização, sem intercalar com um render loop concorrente.
|
|
154
|
+
scene.render();
|
|
155
|
+
let pose = reader.read(0);
|
|
156
|
+
return {
|
|
157
|
+
beforeRender(dt: number, input: TrajectoryInput, allowStop = false, allowTurn = false) {
|
|
158
|
+
const gaits = filterLocomotionGaits(available, Math.hypot(...input.velocity));
|
|
159
|
+
if (!allowStop) gaits.delete('stop'); if (!allowTurn) gaits.delete('turn');
|
|
160
|
+
const local = toLocal(input.velocity[0], input.velocity[1], input.yaw);
|
|
161
|
+
const state = matcher.update(dt, {
|
|
162
|
+
...builder.build({ ...pose, rootVelocity: [local[0], 0, local[1]] }, predictTrajectory(input, builder.layout.horizons)),
|
|
163
|
+
gaits: gaits as ReadonlySet<Gait>,
|
|
164
|
+
});
|
|
165
|
+
playback.update(state, dt); return state;
|
|
166
|
+
},
|
|
167
|
+
afterRender(dt: number) { pose = reader.read(dt); },
|
|
168
|
+
reset() { matcher.reset(); reader.reset(); pose = reader.read(0); },
|
|
169
|
+
dispose() { playback.dispose(); owned.forEach(asset => asset.dispose()); },
|
|
170
|
+
};
|
|
171
|
+
} catch (error) { player?.dispose(); owned.forEach(asset => asset.dispose()); throw error; }
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Ordem obrigatória por frame: **movimentar/rotacionar controller pelo gameplay → beforeRender → scene.render → afterRender**. Registrar afterRender só uma vez por frame lógico, mesmo com múltiplas câmeras. dt é em segundos. input.velocity e desiredVelocity são [X,Z] do mundo; yaw/desiredYaw são radianos; aceleração/frenagem são m/s² e turnSpeed rad/s. Derivar esses valores do controller do jogo, não da animação.
|
|
176
|
+
|
|
177
|
+
O exemplo não adiciona um render loop: integrar ao loop existente. Não usar setInterval para animação. Definir allowStop durante frenagem e allowTurn para mudança de heading em baixa velocidade conforme as capacidades reais do banco; eles disponibilizam gaits, não forçam um clipe. Não fazer `matcher.reset()` a cada frame. Resetar histórico em teleporte/reconciliação brusca; velocidades espúrias prejudicam a seleção.
|
|
178
|
+
|
|
179
|
+
## 4. API e comportamento que a IA deve preservar
|
|
180
|
+
|
|
181
|
+
- `PoseSearch.search({features,schemaSignature,gaits?,excludedClips?})` retorna melhor Match ou null. Features são brutas. Pesos e normalização vêm dos canais do schema; no preset original, pose/velocidade 1 e trajetória/direção 3 por dimensão. Para custo customizado no matcher, seus pesos estão em matcher.search.weights.
|
|
182
|
+
- `MotionMatcher.update(dt, query)` retorna clip/time/switched/match. clip é índice no manifest; clip < 0 indica ausência de playback. match é o último candidato da busca, que pode diferir do playback por continuidade/cooldown; não apresentá-lo sempre como o clipe renderizado.
|
|
183
|
+
- Defaults: searchInterval=0.1 s, minimumHold=0.12 s, improvement=0.1, jumpPenalty=0.5, timeSeparation=0.2 s, reselectDelay=0.6 s. Critérios de tuning locais; não parâmetros oficiais do Unreal.
|
|
184
|
+
- Sem loop: clamp no fim, exclusão temporária do clipe concluído. Loop: tempo circula na duração. Não somar dt novamente ao tempo retornado antes de chamar o player.
|
|
185
|
+
- `filterLocomotionGaits`: acima de 0.2 m/s retira idle se há marcha; abaixo de 0.05 retira marchas se há idle. Preserva fallback em conjuntos incompletos e não decide prioridades de combate.
|
|
186
|
+
- `BabylonMotionPlayer` cria grupos próprios e mistura tempos diferentes do mesmo clipe. Usar update antes de renderizar. Não iniciar as mesmas fontes sobre o personagem em paralelo. Grupos pausados + goToFrame com pesos são intencionais para Babylon 7.
|
|
187
|
+
- `BabylonSchemaPoseReader` lê ossos semânticos visíveis após avaliação/blending; o wrapper BabylonPoseReader continua para dois pés; não substituir por pose pura do banco quando houver crossfade.
|
|
188
|
+
- `parseProfile` valida perfil v2; `parseSchema`/`parseAnimationSet` validam os JSON independentes e `resolveProfile` confere roles requeridos; `suggestRig` só propõe nomes; `profileSignature` identifica configuração. Validar assets offline é uma etapa separada.
|
|
189
|
+
- `rootMotionFeatures` e `sampleRootMotion` operam em trajetórias medidas com yaw contínuo, clamp por padrão e composição de ciclos quando looping=true. Não aplicar seu deslocamento sobre a posição já simulada do controller.
|
|
190
|
+
|
|
191
|
+
## 5. Combate, multiplayer e recursos
|
|
192
|
+
|
|
193
|
+
Gameplay/servidor continuam responsáveis por colisões, posição, dano, hitbox, cooldowns e janelas de ação. Motion matching é apresentação de locomoção. Não transmitir clipId como autoridade de ataque/acerto.
|
|
194
|
+
|
|
195
|
+
O player deste pacote é de corpo inteiro, sem máscara de ossos. Não sobrepor seus grupos aos grupos de combate nos mesmos nodes. Para camadas, adaptar a seleção do núcleo ao player mascarado do projeto ou preparar um adaptador próprio. Suspender/dispor a reprodução de locomoção ao transferir controle de corpo inteiro a uma ação e reiniciar a seleção a partir da pose visível ao retornar.
|
|
196
|
+
|
|
197
|
+
Banco e fontes podem ser carregados uma vez por cena; player, matcher e histórico do leitor precisam ser individuais. Liberar grupos do player na remoção do avatar. Não dispor fontes compartilhadas antes de todos os consumidores. O exemplo possui seus próprios assets e não dispõe o controller fornecido pelo jogo.
|
|
198
|
+
|
|
199
|
+
## 6. Diagnóstico e verificação
|
|
200
|
+
|
|
201
|
+
| Sintoma | Conferir |
|
|
202
|
+
| --- | --- |
|
|
203
|
+
| Arquivos não encontrados | Perfil e assets devem ser servidos pelo consumidor; não vêm no npm |
|
|
204
|
+
| Banco desatualizado | Perfil/fingerprint e novo bake; substituição de GLB exige bake mesmo sem mudar perfil |
|
|
205
|
+
| Ossos ausentes/deformação | Nomes, boneMap, bind pose, retargeting prévio; não apenas renomear ossos |
|
|
206
|
+
| Sem animação/T-pose | Fontes corretas, bootstrap, update antes do render, leitura depois |
|
|
207
|
+
| Idle andando ou marcha parado | Gaits permitidos por velocidade, unidades, pesos e cobertura do banco |
|
|
208
|
+
| Pés deslizam | Velocidade nominal, escala, velocidade real, direção; não há foot locking/IK |
|
|
209
|
+
| Movimento duplicado | Root motion não removido ou aplicado junto ao controller |
|
|
210
|
+
| Direção invertida | Referencial da cena/câmera, yaw e transformação mundo→local |
|
|
211
|
+
| Muitos saltos | dt/unidades, reset indevido, pesos, minimumHold/improvement e qualidade dos clips |
|
|
212
|
+
|
|
213
|
+
No consumidor, testar idle, aceleração, walk/run, lados/costas quando disponíveis, frenagem, giro, transições, teleporte, múltiplos avatares e remoção. Medir no navegador alvo; resultados de benchmark Node não são orçamento de renderização. Um sample correto não prova qualidade de todo o ciclo.
|
|
214
|
+
|
|
215
|
+
Não implementados: retargeting automático, IK/foot locking, contatos de pés, inertialization, motion warping, movimento autoritativo por root motion, worker, PCA/KD-tree, quadrúpedes ou schema visual configurável. Não prometer eliminação de sliding ou paridade com Unreal.
|
|
216
|
+
|
|
217
|
+
Fase 1 implementa schemas configuráveis e arquivos de conjunto separados. O laboratório oferece biped-locomotion (27 dimensões) e biped-hands (33 dimensões, mãos/horizontes diferentes). Ainda não há tags arbitrárias, alternância contextual de conjuntos, variação automática de idles, intenção de olhar ou busca conjunta em múltiplos bancos. Preparação genérica GLB está implementada na Fase 2; retargeting automático continua futuro; os schemas não adaptam animações de rigs incompatíveis.
|
|
218
|
+
|
|
219
|
+
## 7. Manutenção obrigatória
|
|
220
|
+
|
|
221
|
+
Planejamento neural (28/10/2026): `docs/features/animacao-neural/README.md`, no repositório, analisa treinamento offline com animações do projeto, um híbrido de candidatos e a alternativa de síntese neural, com estimativas de esforço e custos separados entre preparação, navegador e servidor. Nada disso está implementado ou distribuído no npm. O plano recomenda execução no cliente, preservando a autoridade de gameplay/servidor; não há modelo inicial, treinamento automático, runtime neural ou novo comando/API disponível. As contas são cenários com premissas, não medições nem garantias de custo/desempenho.
|
|
222
|
+
|
|
223
|
+
Investigação documental (28/10/2026): no repositório, `docs/features/locomocao-web/README.md` reúne oportunidades de trajetória, transições, diagnóstico, múltiplos personagens e cenários repetíveis, com fontes e critérios de aceite. É planejamento, não uma API disponível; não acrescenta dependências, código externo, modelos neurais ou recursos ao runtime. Inertialization, worker, índices acelerados e novos diagnósticos continuam futuros. A pasta de pesquisa não acompanha o pacote npm atual.
|
|
224
|
+
|
|
225
|
+
Para toda implementação/correção na biblioteca, revisar e atualizar **este arquivo fonte na mesma alteração**, inclusive registrando correções internas relevantes aqui. Atualizar exemplos, contratos, limitações e diagnóstico afetados. Só descrever como validado o que foi executado. Não editar dist/AI_USAGE.md manualmente.
|
|
226
|
+
|
|
227
|
+
Rodar typecheck/testes/build conforme a mudança; `npm run check:docs` confirma que dist contém as cópias atuais. `prepack` recompila e copia os documentos antes de empacotar/publicar; isso não substitui a revisão semântica do tutorial. Usar docs/PUBLISHING.md para release; publicação exige pedido explícito do mantenedor.
|
|
228
|
+
|
|
229
|
+
Registro de manutenção (28/10/2026): tutorial inicial da série 0.1.x, entradas npm atualizadas para @pose_flow/babylon, perfis genéricos, bootstrap por pose animada, filtros de velocidade e políticas de root/blending documentados. Banco e perfis de exemplo continuam fora do npm. Guias passam a acompanhar build/pacote a partir da próxima versão publicada; não assumir que estavam na primeira 0.1.0.
|
|
230
|
+
|
|
231
|
+
Revisão do roadmap (28/10/2026): documentadas as diferenças entre perfis reutilizáveis atuais e schemas/conjuntos configuráveis planejados. Nenhuma API ou capacidade de animação foi alterada nesta revisão documental.
|
|
232
|
+
|
|
233
|
+
Complemento do roadmap (28/10/2026): explicitados o cenário de múltiplos idles com política de variação e a distinção entre deslocamento, orientação corporal e intenção de olhar. Alternância contextual de idles e seleção orientada pelo olhar continuam planejadas; cadastrar vários clipes não implementa essas políticas na API atual.
|
|
234
|
+
|
|
235
|
+
Marco de estabilidade (28/10/2026): o roadmap passa a exigir uma release estável 1.0.0, com API/dados versionados, migração, pipeline distribuível, múltiplos rigs, cenários visuais, desempenho e instalação em consumidor independente validados. O processo prevê versões candidatas antes da release. A base atual permanece 0.1.0; este marco não declara recursos futuros implementados nem autoriza publicação imediata. Consultar ROADMAP.md para o escopo e PUBLISHING.md para os critérios de release.
|
|
236
|
+
|
|
237
|
+
Fluxo de testes práticos (28/10/2026): o MMORPG será consumidor durante o desenvolvimento. No repositório da lib, task/summary.md lista relatos por prioridade e status PENDENTE/PARCIAL/CONCLUIDO; task/_modelo/ fornece o relato e pastas de evidências para copiar em task/task-NN/. Registrar versão instalada, perfil/banco, reprodução, esperado/observado e validações executadas. Problemas exclusivos do consumidor aguardam confirmação no cenário original antes de concluir. O acompanhamento é manual, não acompanha o npm e não implica integração já aplicada ou nova API.
|
|
238
|
+
|
|
239
|
+
Restrição de escopo (28/10/2026): neste projeto/chat é proibido alterar o jogo em D:\MMORP_WEB\mmorpg-polygon-multiplayer\mmorpg-polygon-multiplayer, inclusive assets, dependências, configuração e arquivos gerados, ou executar comandos que escrevam nele. Consultas para análise são somente de leitura. Corrigir a biblioteca aqui; se a causa for do consumidor, registrar diagnóstico/orientação na task. O usuário ou responsável pelo jogo realiza a integração e os testes práticos naquele projeto. Exemplos de integração deste guia são instruções para o consumidor, não autorização para este chat modificar o jogo.
|
|
240
|
+
|
|
241
|
+
Manutenção — Fase 1 (28/10/2026): formatos de banco/perfil v2; schema v1 com canais/normalização/horizontes configuráveis; identidade canônica e rejeição de incompatibilidades; migração explícita do banco v1; conjunto de animações separado; leitor Babylon genérico; bake usa o mesmo player/modelo alvo e política de root do runtime. Exemplos e ciclo de integração acima atualizados. Ferramentas, schemas/perfis/conjuntos e bancos continuam fora do npm; nenhuma publicação realizada. Evidências e limites da implementação estão em docs/VALIDATION.md no repositório.
|
|
242
|
+
|
|
243
|
+
Correção de strafe — task-05 (28/10/2026): preservada a orientação constante de autoria do root em bake/player, mantendo remoção de deslocamento e heading variável. Adicionado Clip.rootOrientation (e campo homônimo no conjunto): quaternion unitário local absoluto aplicado como parte da pose, com crossfade, sem alterar o controller. Exige stripRoot mapeado; sem override, preserva a rotação constante da fonte ou usa a orientação inicial do rig quando a rotação da fonte varia. Criar o player antes de animar o rig, para capturar a referência inicial correta. rootOrientation é preparação explícita da pose, não retargeting, IK, motion warping nem comando de yaw do gameplay. Alterá-la exige novo bake. Bancos anteriores desta base que removeram uma orientação constante também devem ser regenerados; a assinatura do schema não identifica mudanças no algoritmo de preparação.
|
|
244
|
+
|
|
245
|
+
O pack KayKit possui strafes de corrida com orientação de autoria ±60°, inadequada à trajetória lateral pura do exemplo. O conjunto kaykit configura rootOrientation com yaw ±90° para alinhar as pernas à direção lateral. Isso gira a pose do rig; não implementa controle independente de torso/olhar. O laboratório passa a testar strafes à velocidade nominal declarada (3,2 m/s nesses exemplos), inclusive A/D puro com Manter orientação quando houver clipe nominal alinhado. A velocidade é de autoria, não medição automática. A inspeção de pés próximos ao chão é somente diagnóstico offline, não contato/foot locking em runtime; sliding residual ainda pode existir, especialmente em transições e escalas diferentes.
|
|
246
|
+
|
|
247
|
+
## Manutenção — primeiro incremento da Fase 2 (28/10/2026, histórico)
|
|
248
|
+
|
|
249
|
+
Clipes aceitam `range: [inicio,fim]` em segundos. O bake guarda `sourceStart` e duração recortada; BabylonMotionPlayer aplica o mesmo intervalo, incluindo o primeiro frame da fonte e loops. Fazer novo bake.
|
|
250
|
+
|
|
251
|
+
`motionFile` aceita source `root` ou `hips` e looping. `sampleRootMotion(track,time,looping=false)` e `rootMotionFeatures(track,time,derivativeStep,horizons,looping=false)` compõem deslocamento e yaw dos ciclos, inclusive negativos. `cropRootMotion(track,start,end)` interpola limites. Velocidade nominal é autoria. A composição não corrige emenda de pose nem elimina sliding.
|
|
252
|
+
|
|
253
|
+
O manifesto v2 ganha `assetHashes` SHA-256 por URL de GLB/trajetória. A fingerprint continua somente configuração. O laboratório exige hashes e recusa assets alterados; bancos antigos exigem novo bake. `decodeDatabase` valida o formato, sem ler arquivos/rede. O consumidor externo deve conferir hashes ou controlar identidade dos assets na distribuição. O laboratório faz uma leitura extra dos bytes, além do carregamento Babylon.
|
|
254
|
+
|
|
255
|
+
CLI Node incluída no pacote local: `pose-flow inspect modelo.glb`, `pose-flow validate --profile public/profiles/rig.json`, `pose-flow bake --profile public/profiles/rig.json`. `--public-dir caminho` muda a raiz dos URLs públicos em validação/bake; `--profile` é caminho de arquivo. Caminhos relativos ao diretório atual do consumidor. Node 24.21.0 e Babylon 7.54.3 são o ambiente deste teste; o loader GLTF 7.54.3 é dependência do pacote. Não fazer bake no início do jogo. Assets, perfis e bancos são fornecidos pelo consumidor. Não houve publicação.
|
|
256
|
+
|
|
257
|
+
Consulte PROFILES.md para remoção de root e roteiro offline. Esse primeiro incremento foi parcial; as pendências de preparação foram atendidas na continuação abaixo. Retargeting automático, IK e inertialization não foram implementados.
|
|
258
|
+
|
|
259
|
+
## Manutenção — preparação e validação da Fase 2 (28/10/2026)
|
|
260
|
+
|
|
261
|
+
A CLI distribuída inclui `pose-flow prepare --config preparation.json`. JSON v1: input/output GLB distintos, animation, rootNode, source (`hips`/`root`), sampleRate (1–120), position (`horizontal`/`all`), heading boolean; opcionais unitScale positivo e yawOffset em radianos. Paths relativos ao diretório atual. Ver PROFILES.md para contrato, exemplo e limites. A ferramenta exporta um GLB com trilhas preparadas, `.motion.json` com a trajetória medida e `.preparation.json` com configuração/hash/proveniência técnica. Executar offline. A licença da fonte continua sendo responsabilidade de quem fornece o asset.
|
|
262
|
+
|
|
263
|
+
A política horizontal retira XZ e preserva bob Y; all fixa XYZ no ponto inicial. heading=true retira variação de yaw, preservando orientação inicial e inclinação. Dados são reamostrados linearmente na taxa configurada. unitScale/yawOffset são aplicados ao GLB e à medida em conjunto; não substituem a escala do perfil. GLB precisa ser autossuficiente, com um buffer, início zero, escalas positivas/uniformes e sem shear. Para scene roots animados, converter eixos/unidades antes. Seleção de osso, eixos e política é explícita, sem inferência por personagem. Não aplicar stripRoot novamente à trilha já retirada.
|
|
264
|
+
|
|
265
|
+
`pose-flow validate --profile ... --check-bind` compara geometria de bind relativa ao root e cobertura de joints; exige um skin e inverse bind matrices MAT4 float32. Falta de dados falha. Essa checagem detectou Medium → Large incompatível apesar dos mesmos nomes; Large → Large passou. Não equivale a retargeting nem valida contatos.
|
|
266
|
+
|
|
267
|
+
O descritor pode conter `averageVelocity`, média das velocidades locais medidas das amostras do bake. O laboratório usa essa referência para velocidade de teste de marcha; nominalVelocity continua autoria. O jogo continua responsável pelo deslocamento, colisões e combate. A câmera do laboratório se enquadra pelo tamanho do modelo, sem condições por nome.
|
|
268
|
+
|
|
269
|
+
Novas demonstrações por JSON: mannequin-large (126 poses, idle/walk/run próprios), paladin-measured (351 poses, caminhada medida em loop e parada sem loop preparada a 2×), mannequin-retarget (32 poses, experimento offline de caminhada Medium → Large). O último usa constraints/bake nativos do Blender configurados explicitamente, com bob sem recalibração de proporção; não é retargeting automático da biblioteca, não tem idle/contatos e não valida rigs arbitrários. A reprodução foi conferida no navegador. Os GLB/JSON/licenças não entram no pacote npm.
|
|
270
|
+
|
|
271
|
+
A preparação exige novo bake quando mudar bytes ou políticas. Foram comparadas as poses dos sete perfis e a velocidade das poses medidas num controller deslocando/girando, inclusive emenda: erro amostral máximo aproximadamente 0,003 m/s. Isso não garante suavidade de qualquer dataset nem ausência de sliding. Retargeting automático próprio, IK, foot locking e inertialization continuam futuros. Nenhuma alteração ou teste no MMORPG e nenhuma publicação.
|
|
272
|
+
|
|
273
|
+
## Manutenção — frenagem do laboratório (task-07, 28/10/2026)
|
|
274
|
+
|
|
275
|
+
`Query.velocityTolerance?: number` ativa uma faixa física de compatibilidade no canal root-velocity, em m/s, antes do custo ponderado de poses. Requer esse canal no schema; valores negativos/não finitos falham. Padrão ausente mantém a busca anterior. Filtros de gait/excludedClips são aplicados antes da faixa. Se nenhum candidato estiver dentro dela, comparar somente os de menor erro de velocidade, preservando fallback sem liberar indiscriminadamente poses paradas. O núcleo continua sem engine/I/O.
|
|
276
|
+
|
|
277
|
+
Quando o tempo corrente fica incompatível e há um candidato distante melhor em velocidade, MotionMatcher pode trocar após minimumHold, sem exigir a margem de melhora do custo de pose. Mantém searchInterval e timeSeparation; não reinicia por pequenas diferenças entre amostras próximas. A faixa não é garantia frame a frame: cobertura incompleta, avanço entre buscas e retenção podem produzir erro maior. Não altera o controller nem janelas de combate. A nova opção tem uma passagem adicional linear sobre os candidatos; `npm run benchmark -- --velocity-band` mede esse caminho em Node.
|
|
278
|
+
|
|
279
|
+
O laboratório usa faixa de 0,2 m/s ao frear e crossfade de 0,30 s. Exibe Ritmo do clipe (velocidade indexada, nominal ou medida conforme o descritor) para comparar com Velocidade do controller. Isso não mede contato dos pés.
|
|
280
|
+
|
|
281
|
+
A preparação aceita `playbackRate` opcional entre 0,25 e 4 (padrão 1). Valores acima de 1 encurtam o GLB e a trajetória, aumentando a velocidade medida, sem mover o controller em runtime. Todos os tempos dos canais LINEAR/STEP são reescalados; CUBICSPLINE em canais retidos exige reamostragem offline anterior quando rate difere de 1. O relatório e o bake registram a duração resultante. A taxa sampleRate é aplicada antes dessa alteração temporal. Alterar rate exige preparar e fazer bake novamente.
|
|
282
|
+
|
|
283
|
+
No perfil paladin-measured, a parada a 2× substitui a parada lenta no conjunto; o arquivo original e o perfil Paladin legado foram preservados. Não é nominalVelocity disfarçada: os samples e o GLB foram retimados em conjunto e o banco usa velocidades derivadas. O resultado reduz a seleção de poses quase estáticas durante o avanço, mas não implementa contatos, IK ou foot locking e não promete eliminar sliding residual de transições/datasets incompatíveis. Evidências e limites em task/task-07/task.md.
|
|
284
|
+
|
|
285
|
+
## Manutenção — tremida na saída (task-08, 28/10/2026)
|
|
286
|
+
|
|
287
|
+
`Query.allowTemporalReselection?: boolean` controla somente saltos de tempo dentro do mesmo clipe looping. O padrão true preserva o comportamento anterior. False deixa o ciclo corrente avançar normalmente e completar a emenda; a busca continua ativa e pode selecionar outro clipe. Não bloqueia trocas obrigatórias por gait/exclusão/término nem replanejamento de one-shots. Também não é uma trava de contatos ou uma escolha manual de clipId.
|
|
288
|
+
|
|
289
|
+
O laboratório define false quando a intenção está estável (erro de velocidade desejada/atual menor que 0,05 m/s e erro angular menor que 0,08 rad). Em aceleração, frenagem ou giro volta a permitir replanejamento. Esses limiares são política do consumidor de demonstração, não limites universais da biblioteca. Outros consumidores devem considerar também troca de contexto/ação, teleporte e reconciliação; não manter a fase protegida quando o estado da personagem exige uma nova decisão. Resetar matcher/reader nos casos já descritos no tutorial.
|
|
290
|
+
|
|
291
|
+
A investigação encontrou retrocessos repetidos de aproximadamente 0,7 para 0,5 s na caminhada, com feedback entre crossfade/velocidade da pose visível e nova busca. No cenário reproduzido, proteger a fase removeu 12 retrocessos amostrados em dois ciclos de caminhada. Os testes mantêm busca para outro clipe, retorno ao replanejamento, wrap natural e o cenário de frenagem corrigido. Dados/bancos não mudam por essa opção. Não há inertialization ou foot locking novos.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Publicar @pose_flow/babylon no npm
|
|
2
|
+
|
|
3
|
+
Fonte deste documento: `docs/PUBLISHING.md`. O build gera `dist/PUBLISHING.md`, incluído no pacote npm. Atualizar o documento de origem, nunca a cópia.
|
|
4
|
+
|
|
5
|
+
## Preparar uma atualização
|
|
6
|
+
|
|
7
|
+
Executar na raiz do repositório da biblioteca. Os comandos abaixo não pertencem ao projeto consumidor.
|
|
8
|
+
|
|
9
|
+
```powershell
|
|
10
|
+
Set-Location D:\motion_match
|
|
11
|
+
npm ci
|
|
12
|
+
npm run typecheck
|
|
13
|
+
npm test
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Antes da versão, atualizar `docs/AI_USAGE.md` para toda implementação/correção e este documento se o processo mudar. Não prosseguir se algum comando falhar.
|
|
17
|
+
|
|
18
|
+
## Aumentar a versão
|
|
19
|
+
|
|
20
|
+
### Marco planejado de estabilidade 1.0.0
|
|
21
|
+
|
|
22
|
+
O roadmap do repositório exige uma release estável 1.0.0 como entrega final. A série atual 0.1.x não recebe essa classificação por esta atualização documental. Não aumentar a versão agora por causa do planejamento.
|
|
23
|
+
|
|
24
|
+
Antes da 1.0.0, concluir os critérios de docs/ROADMAP.md, preparar candidatos 1.0.0-rc.N e verificar instalação, ferramentas offline e reprodução em consumidor independente. Registrar evidências, matriz de suporte, metas/resultados de desempenho, notas da versão e migração dos contratos 0.x. Defeitos críticos ou de alta severidade no escopo suportado bloqueiam a release. Executar as verificações abaixo para o pacote candidato e novamente para o pacote final; conferir a versão exata instalada, sem presumir que latest aponta para um candidato.
|
|
25
|
+
|
|
26
|
+
Após aprovação dos critérios, a entrega final deve ser 1.0.0, em vez de aplicar automaticamente o incremento patch descrito para manutenção de 0.x. Publicar somente mediante pedido explícito do mantenedor e conferir instalação da versão publicada. Após 1.0.0, preservar contratos em patch/minor; quebras exigem major e guia de migração. A topologia dos pacotes/CLI será definida na etapa de distribuição; os arquivos e comandos atuais abaixo descrevem somente o pacote existente.
|
|
27
|
+
|
|
28
|
+
### Mudança de formatos na Fase 1 (ainda sem publicação)
|
|
29
|
+
|
|
30
|
+
O código local usa banco/perfil v2 e schema v1. Antes da próxima release, escolher uma versão 0.x apropriada à quebra de contrato e publicar as instruções de migração incluídas em AI_USAGE.md; não tratar esta entrega como simples correção patch. A versão em package.json não foi aumentada nesta implementação. Esse era o conteúdo na Fase 1. A Fase 2 abaixo inclui CLI offline; JSON externos e bancos continuam fora do pacote.
|
|
31
|
+
|
|
32
|
+
### Manutenção da série atual
|
|
33
|
+
|
|
34
|
+
A publicação de 0.1.0 foi informada pelo mantenedor. Versões já publicadas não podem ser sobrescritas. A inclusão destes documentos exige uma nova publicação para chegar aos consumidores.
|
|
35
|
+
|
|
36
|
+
Para uma correção ou atualização de documentação, executar **uma única vez**:
|
|
37
|
+
|
|
38
|
+
```powershell
|
|
39
|
+
npm version patch --no-git-tag-version
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Se a versão local ainda for 0.1.0, isso gera 0.1.1 e atualiza package.json/package-lock.json, sem criar commit ou tag. Não repetir o comando se já aumentou a versão para essa entrega. Para funcionalidade compatível, avaliar `npm version minor --no-git-tag-version`; para quebra de contrato, planejar a versão e a migração explicitamente, especialmente enquanto a lib estiver em 0.x.
|
|
43
|
+
|
|
44
|
+
## Build e inspeção
|
|
45
|
+
|
|
46
|
+
```powershell
|
|
47
|
+
npm run build
|
|
48
|
+
npm run check:docs
|
|
49
|
+
npm pack --dry-run --ignore-scripts
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Conferir a versão e os arquivos listados: biblioteca JS/tipos em dist/, dist/AI_USAGE.md, dist/PUBLISHING.md, README.md, LICENSE e package.json. Personagens, animações, bancos, perfis de exemplo, testes e fontes TypeScript não entram no pacote. Ferramentas compiladas e seu runtime interno em dist/offline/ acompanham a CLI.
|
|
53
|
+
|
|
54
|
+
O `--ignore-scripts` acima é usado **somente após o build explícito**, para inspecionar sem compilá-lo novamente. No fluxo normal de `npm pack` e `npm publish`, o `prepack` executa o build e copia a documentação atual. Não usar `--ignore-scripts` na publicação normal.
|
|
55
|
+
|
|
56
|
+
Para gerar um .tgz local e testar a instalação antes de publicar:
|
|
57
|
+
|
|
58
|
+
```powershell
|
|
59
|
+
npm pack
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
No projeto de teste, instalar o caminho do .tgz exibido pelo comando anterior. Não assumir o nome/versão do arquivo. Testar imports do núcleo/adaptador e localizar o tutorial em node_modules/@pose_flow/babylon/dist/AI_USAGE.md.
|
|
63
|
+
|
|
64
|
+
## Autenticar e publicar
|
|
65
|
+
|
|
66
|
+
```powershell
|
|
67
|
+
npm login
|
|
68
|
+
npm whoami
|
|
69
|
+
npm publish --access public
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Verificar a conta e a permissão no escopo `pose_flow`. Concluir a autenticação de dois fatores solicitada pelo npm. Não armazenar senha, token ou códigos de recuperação no repositório/documentos. Uma IA só deve executar a publicação se o mantenedor pedir essa ação explicitamente; a autenticação interativa é feita pelo mantenedor.
|
|
73
|
+
|
|
74
|
+
Depois, conferir o registro:
|
|
75
|
+
|
|
76
|
+
```powershell
|
|
77
|
+
npm view @pose_flow/babylon version
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
No projeto consumidor:
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
npm install @pose_flow/babylon@latest
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Conferir a versão efetivamente instalada no lockfile e ler o tutorial daquela versão. Não copiar dist/ manualmente para node_modules.
|
|
87
|
+
|
|
88
|
+
## Erros comuns
|
|
89
|
+
|
|
90
|
+
- E403 com mensagem de 2FA: conferir 2FA da conta e autenticar novamente. Não é erro do conteúdo do tarball.
|
|
91
|
+
- Sem permissão no escopo: conferir acesso à organização pose_flow e nome do pacote.
|
|
92
|
+
- Versão já existente: consultar a versão publicada e preparar uma versão nova; não tentar sobrescrever.
|
|
93
|
+
- Tutorial ausente/desatualizado: editar docs/AI_USAGE.md, executar build e check:docs, inspecionar o pacote.
|
|
94
|
+
|
|
95
|
+
## Referências oficiais
|
|
96
|
+
|
|
97
|
+
- [npm publish](https://docs.npmjs.com/cli/v11/commands/npm-publish/): publicação e versões imutáveis.
|
|
98
|
+
- [npm version](https://docs.npmjs.com/cli/v11/commands/npm-version/): incremento de versão e opção sem tag Git.
|
|
99
|
+
- [Lifecycle scripts](https://docs.npmjs.com/cli/v11/using-npm/scripts/): prepack.
|
|
100
|
+
- [Configurar 2FA](https://docs.npmjs.com/configuring-two-factor-authentication/).
|
|
101
|
+
|
|
102
|
+
## CLI offline — Fase 2, sem publicação
|
|
103
|
+
|
|
104
|
+
O build agora executa também `tsc -p tsconfig.offline.json`. `bin.pose-flow` aponta para `dist/offline/tools/cli.js`; `dist/offline/src/` contém o runtime interno das ferramentas. Os exports públicos permanecem dist/index.js e dist/babylon.js. Não importar caminhos internos da CLI como API.
|
|
105
|
+
|
|
106
|
+
`@babylonjs/loaders@7.54.3` passou de devDependency para dependency para permitir inspeção/bake após instalar. Babylon core continua peerDependency. Lockfile atualizado; versão não alterada. Conferir CLI/runtime interno e ambos os guias no dry-run. Testar instalação em diretório independente e executar `npx --no-install pose-flow validate --profile public/profiles/rig.json` e `npx --no-install pose-flow bake --profile public/profiles/rig.json`. O teste deve ficar fora do MMORPG protegido.
|
|
107
|
+
|
|
108
|
+
A CLI agora inclui `prepare --config preparation.json`, com os módulos compilados prepare/glb/rig. Conferir esses módulos no pacote. Os scripts Python de conversão e o experimento Blender não são distribuídos; Blender não é dependência do runtime nem da CLI GLB. Testar também prepare → validate → bake no pacote instalado com GLB de entrada do consumidor. `--check-bind` é opcional e exige dados de skin/bind suportados. O pacote continua sem assets, perfis, bancos ou publicação automática.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AnimationGroup, TransformNode, type Scene } from '@babylonjs/core';
|
|
2
|
+
import type { Clip, Playback, Pose } from './index.js';
|
|
3
|
+
import { type PoseSchema, type SchemaPose } from './core/schema.js';
|
|
4
|
+
/** Clone onto a target rig. Two playback slots allow crossfade between times of the same clip. */
|
|
5
|
+
export declare class BabylonMotionPlayer {
|
|
6
|
+
private scene;
|
|
7
|
+
private clips;
|
|
8
|
+
private sources;
|
|
9
|
+
private nodes;
|
|
10
|
+
readonly fadeSeconds: number;
|
|
11
|
+
private rootName;
|
|
12
|
+
private tracks;
|
|
13
|
+
private active?;
|
|
14
|
+
private disposed;
|
|
15
|
+
private strippedRoot?;
|
|
16
|
+
private rootRestRotation?;
|
|
17
|
+
constructor(scene: Scene, clips: readonly Clip[], sources: ReadonlyMap<string, AnimationGroup>, nodes: ReadonlyMap<string, TransformNode>, fadeSeconds?: number, rootName?: string);
|
|
18
|
+
private create;
|
|
19
|
+
update(state: Playback, dt: number): void;
|
|
20
|
+
private clear;
|
|
21
|
+
dispose(): void;
|
|
22
|
+
}
|
|
23
|
+
/** Sample AFTER scene animation evaluation. Semantic roles are defined by the schema. */
|
|
24
|
+
export declare class BabylonSchemaPoseReader {
|
|
25
|
+
private root;
|
|
26
|
+
private previous?;
|
|
27
|
+
private nodes;
|
|
28
|
+
constructor(root: TransformNode, bones: ReadonlyMap<string, TransformNode>, schema: PoseSchema);
|
|
29
|
+
reset(): void;
|
|
30
|
+
read(dt: number): SchemaPose;
|
|
31
|
+
}
|
|
32
|
+
/** Compatibility reader for the original two-foot preset. */
|
|
33
|
+
export declare class BabylonPoseReader {
|
|
34
|
+
private reader;
|
|
35
|
+
constructor(root: TransformNode, left: TransformNode, right: TransformNode);
|
|
36
|
+
reset(): void;
|
|
37
|
+
read(dt: number): Pose;
|
|
38
|
+
}
|