@genex-ai/cli-demo 0.11.0 → 0.14.2

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.
Files changed (42) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +203 -4
  3. package/package.json +7 -2
  4. package/templates/controllers/NOTICE.md +65 -0
  5. package/templates/controllers/assets/animation-library.glb +0 -0
  6. package/templates/controllers/assets/character.glb +0 -0
  7. package/templates/controllers/assets/default-avatar.vrm +0 -0
  8. package/templates/controllers/character/character-animations.ts +682 -0
  9. package/templates/controllers/character/character-controller.ts +1636 -0
  10. package/templates/controllers/character/follow-camera.ts +644 -0
  11. package/templates/controllers/character/keyboard-input.ts +277 -0
  12. package/templates/controllers/character/presets.ts +176 -0
  13. package/templates/controllers/character/touch-joystick.ts +387 -0
  14. package/templates/controllers/character/vrm/capsule-fit.ts +52 -0
  15. package/templates/controllers/character/vrm/foot-ik.ts +341 -0
  16. package/templates/controllers/character/vrm/vrm-loader.ts +44 -0
  17. package/templates/controllers/character/vrm/vrm-retarget.ts +195 -0
  18. package/templates/controllers/drone/drone-controller.ts +1073 -0
  19. package/templates/controllers/drone/presets.ts +225 -0
  20. package/templates/controllers/interact/enter-exit.ts +502 -0
  21. package/templates/controllers/shared/colliders.ts +456 -0
  22. package/templates/controllers/shared/math.ts +230 -0
  23. package/templates/controllers/shared/physics-world.ts +622 -0
  24. package/templates/controllers/vehicle/presets.ts +297 -0
  25. package/templates/controllers/vehicle/vehicle-controller.ts +615 -0
  26. package/templates/controllers/vehicle/wheel.ts +1200 -0
  27. package/templates/skills/genex-getting-started/SKILL.md +5 -0
  28. package/templates/skills/genex-threejs-character-controller/SKILL.md +205 -0
  29. package/templates/skills/genex-threejs-character-controller/references/animations.md +235 -0
  30. package/templates/skills/genex-threejs-character-controller/references/tuning-and-presets.md +102 -0
  31. package/templates/skills/genex-threejs-character-controller/references/wiring.md +198 -0
  32. package/templates/skills/genex-threejs-embed-auth/SKILL.md +126 -54
  33. package/templates/skills/genex-threejs-multiplayer/SKILL.md +17 -11
  34. package/templates/skills/genex-threejs-physics-rapier/SKILL.md +128 -0
  35. package/templates/skills/genex-threejs-physics-rapier/references/colliders-from-assets.md +202 -0
  36. package/templates/skills/genex-threejs-physics-rapier/references/physics-setup.md +207 -0
  37. package/templates/skills/genex-threejs-skill-router/SKILL.md +3 -0
  38. package/templates/skills/genex-threejs-skill-router/references/routing-map.md +15 -7
  39. package/templates/skills/genex-threejs-vehicle-controllers/SKILL.md +110 -0
  40. package/templates/skills/genex-threejs-vehicle-controllers/references/car.md +162 -0
  41. package/templates/skills/genex-threejs-vehicle-controllers/references/drone.md +150 -0
  42. package/templates/skills/genex-threejs-vehicle-controllers/references/enter-exit.md +199 -0
@@ -0,0 +1,297 @@
1
+ // SPDX-FileCopyrightText: 2023-2026 Erdong Chen
2
+ // SPDX-License-Identifier: MIT
3
+ // Vanilla-TypeScript port of the ecctrl vehicle controller (React/R3F removed).
4
+ // Pure data: named vehicle presets. `arcade-kart` and `muscle-drift` are
5
+ // verbatim from the upstream MIT demo's two tuned vehicles; `offroad-bouncy`
6
+ // and `race-grip` are Genex-authored starting points derived from them.
7
+
8
+ import type { CarConfig } from "./vehicle-controller.ts";
9
+ import type { WheelOptions } from "./wheel.ts";
10
+
11
+ /**
12
+ * One chassis collider (cuboid) to attach to `vehicle.body`, e.g. via
13
+ * `cuboidCollider(world, vehicle.body, [x, y, z], { position, density })`.
14
+ */
15
+ export type ChassisColliderSpec = {
16
+ /** Cuboid HALF extents (m). */
17
+ halfExtents: { x: number; y: number; z: number };
18
+ /** Collider offset from the body origin (m). */
19
+ offset: { x: number; y: number; z: number };
20
+ /** Collider density (kg/m^3). Chassis mass = volume x density. */
21
+ density: number;
22
+ };
23
+
24
+ /** One wheel mount: local position (+Z = front) plus per-wheel role flags. */
25
+ export type WheelSlotSpec = {
26
+ position: { x: number; y: number; z: number };
27
+ steerWheel?: boolean;
28
+ driveWheel?: boolean;
29
+ brakeWheel?: boolean;
30
+ driveTorqueWeight?: number;
31
+ maxBrakeTorque?: number;
32
+ };
33
+
34
+ /**
35
+ * A complete car recipe: chassis colliders, drivetrain config, shared wheel
36
+ * options, and the four wheel slots (order FL, FR, RL, RR; +Z = forward,
37
+ * +X = left).
38
+ *
39
+ * IMPORTANT: suspension `springK`/`dampingC` in `wheelShared` scale with
40
+ * chassis MASS — every preset states its `assumedChassisDensity` for the
41
+ * listed collider volumes. If your chassis is materially heavier/lighter,
42
+ * rescale springK proportionally and keep dampingC below
43
+ * `2*sqrt(springK * massPerWheel)`.
44
+ *
45
+ * Wiring sketch:
46
+ * ```ts
47
+ * const car = new VehicleController({ world, carConfig: preset.carConfig });
48
+ * for (const c of preset.chassisColliders)
49
+ * cuboidCollider(world, car.body, [c.halfExtents.x, c.halfExtents.y, c.halfExtents.z],
50
+ * { position: [c.offset.x, c.offset.y, c.offset.z], density: c.density });
51
+ * for (const slot of preset.wheelSlots)
52
+ * car.addWheel({ ...preset.wheelShared, ...slot,
53
+ * position: new THREE.Vector3(slot.position.x, slot.position.y, slot.position.z) });
54
+ * ```
55
+ */
56
+ export type VehiclePreset = {
57
+ name: string;
58
+ /** Density the spring constants were tuned against (see note above). */
59
+ assumedChassisDensity: number;
60
+ carConfig: Partial<CarConfig>;
61
+ /** Applied to every wheel (slots override per-wheel fields). */
62
+ wheelShared: Omit<Partial<WheelOptions>, "position">;
63
+ /** FL, FR, RL, RR. */
64
+ wheelSlots: WheelSlotSpec[];
65
+ chassisColliders: ChassisColliderSpec[];
66
+ };
67
+
68
+ /**
69
+ * Upstream demo "Vehicle 1", verbatim: an all-wheel-drive, front-steer kart
70
+ * with stiff suspension and forgiving grip. The safe default.
71
+ */
72
+ export const arcadeKart: VehiclePreset = {
73
+ name: "arcade-kart",
74
+ assumedChassisDensity: 200,
75
+ carConfig: {
76
+ engineHorsepower: 600,
77
+ engineMaxRPM: 6000,
78
+ gearRatios: [10],
79
+ finalDriveRatio: 1,
80
+ transmissionMode: "auto",
81
+ shiftUpRPM: 5200,
82
+ shiftDownRPM: 2200,
83
+ shiftCooldown: 0.35,
84
+ steerRate: Math.PI * 2,
85
+ maxSteerAngle: Math.PI / 6,
86
+ reverseTorqueScale: 1,
87
+ reverseRPMScale: 0.5,
88
+ },
89
+ wheelShared: {
90
+ springK: 38000,
91
+ dampingC: 4000,
92
+ rayShapeR: 0.5,
93
+ rayShapeH: 0.15,
94
+ rayLength: 0.5,
95
+ maxBrakeTorque: 3000,
96
+ tireGripFactor: 1.3,
97
+ wheelModelDensity: 100,
98
+ wheelModelRadius: 0.5,
99
+ },
100
+ wheelSlots: [
101
+ { position: { x: 0.9, y: 0, z: 1.8 }, steerWheel: true, driveWheel: true, brakeWheel: true },
102
+ { position: { x: -0.9, y: 0, z: 1.8 }, steerWheel: true, driveWheel: true, brakeWheel: true },
103
+ { position: { x: 0.9, y: 0, z: -1.8 }, driveWheel: true, brakeWheel: true },
104
+ { position: { x: -0.9, y: 0, z: -1.8 }, driveWheel: true, brakeWheel: true },
105
+ ],
106
+ chassisColliders: [
107
+ {
108
+ halfExtents: { x: 1, y: 0.4, z: 2.4 },
109
+ offset: { x: 0, y: 0.1, z: 0 },
110
+ density: 200,
111
+ },
112
+ ],
113
+ };
114
+
115
+ /**
116
+ * Upstream demo "Vehicle 2", verbatim: softer suspension, rear-biased drive
117
+ * torque (rear `driveTorqueWeight` 2) — power-oversteers into drifts under
118
+ * throttle.
119
+ */
120
+ export const muscleDrift: VehiclePreset = {
121
+ name: "muscle-drift",
122
+ assumedChassisDensity: 200,
123
+ carConfig: {
124
+ engineHorsepower: 600,
125
+ engineMaxRPM: 6000,
126
+ gearRatios: [10],
127
+ finalDriveRatio: 1,
128
+ transmissionMode: "auto",
129
+ shiftUpRPM: 5200,
130
+ shiftDownRPM: 2200,
131
+ shiftCooldown: 0.35,
132
+ steerRate: Math.PI * 2,
133
+ maxSteerAngle: Math.PI / 6,
134
+ reverseTorqueScale: 1,
135
+ reverseRPMScale: 0.5,
136
+ },
137
+ wheelShared: {
138
+ springK: 25000,
139
+ dampingC: 3200,
140
+ rayShapeR: 0.5,
141
+ rayShapeH: 0.15,
142
+ rayLength: 0.5,
143
+ tireGripFactor: 1.3,
144
+ wheelModelDensity: 100,
145
+ wheelModelRadius: 0.5,
146
+ },
147
+ wheelSlots: [
148
+ { position: { x: 0.85, y: 0, z: 1.5 }, steerWheel: true, driveWheel: true, brakeWheel: true, maxBrakeTorque: 2600 },
149
+ { position: { x: -0.85, y: 0, z: 1.5 }, steerWheel: true, driveWheel: true, brakeWheel: true, maxBrakeTorque: 2600 },
150
+ { position: { x: 0.85, y: 0, z: -1.5 }, driveWheel: true, brakeWheel: true, driveTorqueWeight: 2, maxBrakeTorque: 1800 },
151
+ { position: { x: -0.85, y: 0, z: -1.5 }, driveWheel: true, brakeWheel: true, driveTorqueWeight: 2, maxBrakeTorque: 1800 },
152
+ ],
153
+ chassisColliders: [
154
+ {
155
+ halfExtents: { x: 0.8, y: 0.17, z: 1 },
156
+ offset: { x: 0, y: 0.5, z: -0.6 },
157
+ density: 100,
158
+ },
159
+ {
160
+ halfExtents: { x: 1, y: 0.3, z: 2.4 },
161
+ offset: { x: 0, y: 0, z: 0 },
162
+ density: 200,
163
+ },
164
+ ],
165
+ };
166
+
167
+ /**
168
+ * Genex-authored starting point (no upstream source — TUNE IN TESTBED):
169
+ * softer, longer-travel suspension for a springy ride over bumps, bigger
170
+ * wheels, lower grip, wider steering. Derived from `arcade-kart`.
171
+ */
172
+ export const offroadBouncy: VehiclePreset = {
173
+ name: "offroad-bouncy",
174
+ assumedChassisDensity: 200,
175
+ carConfig: {
176
+ engineHorsepower: 450,
177
+ engineMaxRPM: 6000,
178
+ gearRatios: [10],
179
+ finalDriveRatio: 1,
180
+ transmissionMode: "auto",
181
+ shiftUpRPM: 5200,
182
+ shiftDownRPM: 2200,
183
+ shiftCooldown: 0.35,
184
+ steerRate: Math.PI * 2,
185
+ maxSteerAngle: Math.PI / 5,
186
+ reverseTorqueScale: 1,
187
+ reverseRPMScale: 0.5,
188
+ },
189
+ wheelShared: {
190
+ springK: 16000,
191
+ dampingC: 1600,
192
+ rayShapeR: 0.6,
193
+ rayShapeH: 0.15,
194
+ rayLength: 0.8,
195
+ maxBrakeTorque: 3000,
196
+ tireGripFactor: 1.0,
197
+ lowVelThreshold: 0.5,
198
+ rollingResistanceCoef: 0.012,
199
+ wheelModelDensity: 100,
200
+ wheelModelRadius: 0.6,
201
+ },
202
+ wheelSlots: [
203
+ { position: { x: 0.9, y: 0, z: 1.8 }, steerWheel: true, driveWheel: true, brakeWheel: true },
204
+ { position: { x: -0.9, y: 0, z: 1.8 }, steerWheel: true, driveWheel: true, brakeWheel: true },
205
+ { position: { x: 0.9, y: 0, z: -1.8 }, driveWheel: true, brakeWheel: true },
206
+ { position: { x: -0.9, y: 0, z: -1.8 }, driveWheel: true, brakeWheel: true },
207
+ ],
208
+ chassisColliders: [
209
+ {
210
+ halfExtents: { x: 1, y: 0.4, z: 2.4 },
211
+ offset: { x: 0, y: 0.1, z: 0 },
212
+ density: 200,
213
+ },
214
+ ],
215
+ };
216
+
217
+ /**
218
+ * Genex-authored starting point (no upstream source — tuned in the testbed):
219
+ * stiff rear-wheel-drive racer with high grip and a 4-speed gearbox so the
220
+ * RPM-threshold auto shift actually exercises. Chassis from `muscle-drift`.
221
+ *
222
+ * Gearing note: the tire model's rolling resistance grows with wheel speed,
223
+ * so each gear has a drag-limited equilibrium RPM (measured in the testbed:
224
+ * ~5500 / ~4900 / ~4100 for gears 1-3). `shiftUpRPM` must sit BELOW the
225
+ * next-lower gear's equilibrium or the shift point is never reached; 4300
226
+ * gives two clean upshifts on flat ground and post-shift RPM ~2800-3000
227
+ * (safely above `shiftDownRPM` — no hunting).
228
+ */
229
+ export const raceGrip: VehiclePreset = {
230
+ name: "race-grip",
231
+ assumedChassisDensity: 200,
232
+ carConfig: {
233
+ engineHorsepower: 800,
234
+ engineMaxRPM: 6000,
235
+ gearRatios: [20, 13, 9, 6.5],
236
+ finalDriveRatio: 1,
237
+ transmissionMode: "auto",
238
+ shiftUpRPM: 4300,
239
+ shiftDownRPM: 2400,
240
+ shiftCooldown: 0.35,
241
+ steerRate: Math.PI * 2,
242
+ maxSteerAngle: Math.PI / 7,
243
+ reverseTorqueScale: 1,
244
+ reverseRPMScale: 0.3,
245
+ },
246
+ wheelShared: {
247
+ springK: 42000,
248
+ dampingC: 5200,
249
+ rayShapeR: 0.5,
250
+ rayShapeH: 0.15,
251
+ rayLength: 0.5,
252
+ // Grip vs rollover (measured in the testbed): the lat slip curve keeps
253
+ // ~90% grip even in a full slide, so peak lateral acceleration is
254
+ // ~(groundFriction + tireGripFactor)/2 * latFrictionEllipseScale in g.
255
+ // Keep that at or below the static rollover threshold
256
+ // (halfTrack / comHeight, ~1.0 g for this chassis) or a handbrake slide
257
+ // trips the car over instead of drifting.
258
+ tireGripFactor: 1.5,
259
+ lngFrictionEllipseScale: 1.15,
260
+ latFrictionEllipseScale: 0.8,
261
+ // Low-resistance racing tires (library default 0.007): raises the
262
+ // drag-limited top speed per gear so the auto shift has headroom.
263
+ rollingResistanceCoef: 0.004,
264
+ wheelModelDensity: 100,
265
+ wheelModelRadius: 0.5,
266
+ },
267
+ wheelSlots: [
268
+ { position: { x: 0.85, y: 0, z: 1.5 }, steerWheel: true, brakeWheel: true, maxBrakeTorque: 2600 },
269
+ { position: { x: -0.85, y: 0, z: 1.5 }, steerWheel: true, brakeWheel: true, maxBrakeTorque: 2600 },
270
+ { position: { x: 0.85, y: 0, z: -1.5 }, driveWheel: true, brakeWheel: true, driveTorqueWeight: 1.5, maxBrakeTorque: 1800 },
271
+ { position: { x: -0.85, y: 0, z: -1.5 }, driveWheel: true, brakeWheel: true, driveTorqueWeight: 1.5, maxBrakeTorque: 1800 },
272
+ ],
273
+ chassisColliders: [
274
+ // Light cabin + low-slung main mass: keeps the CoM near axle height so
275
+ // hard cornering leans instead of tripping over.
276
+ {
277
+ halfExtents: { x: 0.8, y: 0.17, z: 1 },
278
+ offset: { x: 0, y: 0.5, z: -0.6 },
279
+ density: 60,
280
+ },
281
+ {
282
+ halfExtents: { x: 1, y: 0.3, z: 2.4 },
283
+ offset: { x: 0, y: -0.15, z: 0 },
284
+ density: 200,
285
+ },
286
+ ],
287
+ };
288
+
289
+ /** All presets by kebab-case name. */
290
+ export const vehiclePresets: Readonly<
291
+ Record<"arcade-kart" | "muscle-drift" | "offroad-bouncy" | "race-grip", VehiclePreset>
292
+ > = {
293
+ "arcade-kart": arcadeKart,
294
+ "muscle-drift": muscleDrift,
295
+ "offroad-bouncy": offroadBouncy,
296
+ "race-grip": raceGrip,
297
+ };