@genex-ai/cli-demo 0.23.0 → 0.24.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/dist/index.js CHANGED
@@ -1668,7 +1668,7 @@ async function poll(apiUrl, token, id, onProgress) {
1668
1668
  function printHint(kind, files, log) {
1669
1669
  const url = files[0]?.url ?? "";
1670
1670
  const hint = {
1671
- model: `Load with GLTFLoader from the URL and add it to the scene \u2014 see the genex-ai-model skill. url = "${url}"`,
1671
+ model: `Meshopt-compressed GLB \u2014 wire the decoder once (loader.setMeshoptDecoder(MeshoptDecoder)), then load with GLTFLoader from the URL \u2014 see the genex-ai-model skill. url = "${url}"`,
1672
1672
  skybox: `Load as an equirectangular texture \u2192 scene.background + scene.environment \u2014 see genex-ai-skybox. url = "${url}"`,
1673
1673
  sfx: `Load with AudioLoader into a THREE.PositionalAudio (camera needs an AudioListener) \u2014 see genex-ai-sfx. url = "${url}"`,
1674
1674
  texture: `Load each map with TextureLoader (RepeatWrapping) into a MeshStandardMaterial \u2014 see genex-ai-texture. Use the URLs above by role.`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genex-ai/cli-demo",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "Set up your ~/.claude workspace, authorize, create a game project, generate AI assets, and publish (genex CLI).",
5
5
  "type": "module",
6
6
  "bin": {
@@ -63,13 +63,18 @@ side — reads as broken at a glance.
63
63
 
64
64
  ## Load it into the scene
65
65
 
66
- Use Three.js `GLTFLoader` with the URL the command printed (R2 sends the right CORS
67
- headers, so cross-origin loading just works):
66
+ Generated model GLBs are **meshopt-compressed** on the Genex servers before
67
+ storage (same visuals, several times smaller faster loads on every play).
68
+ Wire the decoder once — it's harmless for uncompressed files — then use
69
+ Three.js `GLTFLoader` with the URL the command printed (R2 sends the right
70
+ CORS headers, so cross-origin loading just works):
68
71
 
69
72
  ```ts
70
73
  import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
74
+ import { MeshoptDecoder } from "three/addons/libs/meshopt_decoder.module.js";
71
75
 
72
76
  const loader = new GLTFLoader();
77
+ loader.setMeshoptDecoder(MeshoptDecoder); // required for genex model GLBs
73
78
  // the URL `npx genex model` printed:
74
79
  const MODEL_URL = "https://assets.genex.technology/generations/<id>/model-glb";
75
80
  const gltf = await loader.loadAsync(MODEL_URL);
@@ -273,10 +273,13 @@ and a gate capture is NOT visual evidence.
273
273
  - Do NOT work around the gate: don't dig through the SDK's internals for
274
274
  undocumented URL fragments, and don't drive the user's own signed-in
275
275
  browser.
276
- - For the visual pass on a draft, hand it off plainly: "open your draft page
277
- and tell me what you see" the owner's view is the real check. Once the
278
- game is **published**, any fresh browser gets in as a guest, so your own
279
- test browser works again for full visual validation.
276
+ - For the visual pass on a draft, the owner IS the QA loop not a fallback:
277
+ push `genex preview` at each playable milestone and hand it off plainly
278
+ ("check the draft you can now X; ping me if something feels off"), then
279
+ keep building while they look. Their run-around catches exactly what the
280
+ gate hides from you: facing, proportions, feel. Once the game is
281
+ **published**, any fresh browser gets in as a guest, so your own test
282
+ browser works again for full visual validation.
280
283
 
281
284
  ## Checklist
282
285
 
@@ -96,21 +96,32 @@ treat the player as drivable ground.
96
96
  ## Custom generated bodies (`npx genex model`)
97
97
 
98
98
  A generated GLB works as the visual chassis — add it under `car.chassisObject`
99
- exactly like `carBodyMesh` above. Two rules keep it looking right:
100
-
101
- - **Generate the body WITHOUT wheels** prompt it explicitly, e.g.
102
- `npx genex model "red sports car body, no wheels"`. Wheels are code-driven:
103
- each `ShapeCastWheel` steers, bounces, and spins whatever sits in
104
- `wheel.modelObject`, so wheels baked into the body mesh stand frozen while
105
- the invisible real wheels do the work it reads as a broken car.
106
- - **Wheel-less is a valid look.** The suspension shapecasts need no wheel
107
- visuals at all: a body with empty `modelObject`s sits and drives correctly.
108
- Add per-corner wheel meshes (the cylinder in the wiring above, or a small
109
- generated wheel model) only when you want wheels visible.
110
-
111
- Scale and center the GLB to hug the chassis colliders, and mind the
112
- +Z-forward convention when orienting it. Collider strategy for GLBs lives in
113
- `$genex-threejs-physics-rapier`.
99
+ exactly like `carBodyMesh` above. Generated car models arrive as ONE mesh with
100
+ the wheels baked in (prompting "no wheels" does not reliably remove them) —
101
+ that is the expected input. Three rules make it read right:
102
+
103
+ - **Never add visible wheel meshes to a generated body.** Leave every
104
+ `wheel.modelObject` empty the suspension shapecasts drive the body
105
+ correctly with no wheel visuals, and code wheels next to the baked-in ones
106
+ read as a six-wheeled monster truck. The baked wheels simply don't spin;
107
+ at game speed that's the accepted look. (The cylinder wheels in the wiring
108
+ above are for hand-built box-chassis cars only.)
109
+ - **Fit the invisible wheels to the body, not the body to the preset.**
110
+ Scale the GLB by LENGTH toward the preset's footprint (body length ≈
111
+ wheelbase + 1.5 m; race-grip/muscle-drift wheelbase is 3.0 m, track
112
+ 1.7 m) never a min-axis bounding-box fit, which shrinks the body and
113
+ strands the wheel slots outside its silhouette. Then move the wheel slots
114
+ to the model's own wheel arches (from its bounding box: axles at roughly
115
+ ±0.33 × body length on z, x at ±(half width − 0.1)) and set
116
+ `rayShapeR`/`wheelModelRadius` so the body STANDS on the road — baked
117
+ tires touching the ground, nothing floating.
118
+ - **Verify the facing before anything else.** +Z must be the nose:
119
+ generation regularly comes back rotated 180° (the classic "car drives
120
+ backward" bug) — apply the one-time yaw wrapper from `$genex-ai-model`,
121
+ then confirm in your smoke test that the NOSE leads under forward input.
122
+
123
+ Center the GLB over the chassis colliders. Collider strategy for GLBs lives
124
+ in `$genex-threejs-physics-rapier`.
114
125
 
115
126
  ## Presets and provenance
116
127
 
@@ -41,6 +41,12 @@ this is the whole acceptance gate, and it is also the minimum for every game:
41
41
  direction, and NPCs driven by chase/aim code face their target. A model
42
42
  rotated 90° reads as broken — `$genex-ai-model` has the one-time facing
43
43
  fix.
44
+ 5. Vehicles get one extra pass: drive forward once and confirm the NOSE
45
+ leads (a 180° body is this bug's favorite disguise), and check the body
46
+ stands ON the road with its wheels inside the silhouette — a body
47
+ floating above detached wheels means the model was box-fit against the
48
+ preset's wheelbase (the vehicle skill's "Custom generated bodies" rules
49
+ fix it).
44
50
 
45
51
  Everything deeper (baselines, seed sweeps, mosaics, budgets) belongs to
46
52
  visual-system work — the sequence above.