@aura3d/engine 4.1.3 → 4.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.
Files changed (145) hide show
  1. package/README.md +3 -3
  2. package/dist/aura3d-cli/cli.d.ts.map +1 -1
  3. package/dist/aura3d-cli/cli.js +49 -17
  4. package/dist/aura3d-cli/cli.js.map +1 -1
  5. package/dist/aura3d-cli/pull-bridge/adapters.d.ts +9 -1
  6. package/dist/aura3d-cli/pull-bridge/adapters.d.ts.map +1 -1
  7. package/dist/aura3d-cli/pull-bridge/adapters.js +30 -7
  8. package/dist/aura3d-cli/pull-bridge/adapters.js.map +1 -1
  9. package/dist/aura3d-cli/pull-bridge/search.d.ts +5 -0
  10. package/dist/aura3d-cli/pull-bridge/search.d.ts.map +1 -1
  11. package/dist/aura3d-cli/pull-bridge/search.js +7 -1
  12. package/dist/aura3d-cli/pull-bridge/search.js.map +1 -1
  13. package/dist/aura3d-cli/pull-bridge.js +1 -1
  14. package/dist/aura3d-cli/pull-bridge.js.map +1 -1
  15. package/dist/aura3d-cli/resolve-ladder.d.ts +123 -0
  16. package/dist/aura3d-cli/resolve-ladder.d.ts.map +1 -0
  17. package/dist/aura3d-cli/resolve-ladder.js +410 -0
  18. package/dist/aura3d-cli/resolve-ladder.js.map +1 -0
  19. package/dist/create-aura3d/index.js +1 -1
  20. package/dist/debug/index.d.ts +2 -2
  21. package/dist/debug/index.d.ts.map +1 -1
  22. package/dist/debug/index.js +1 -1
  23. package/dist/debug/index.js.map +1 -1
  24. package/dist/debug/safety/frameBoundary.d.ts +33 -0
  25. package/dist/debug/safety/frameBoundary.d.ts.map +1 -0
  26. package/dist/debug/safety/frameBoundary.js +40 -0
  27. package/dist/debug/safety/frameBoundary.js.map +1 -0
  28. package/dist/debug/safety/index.d.ts +1 -0
  29. package/dist/debug/safety/index.d.ts.map +1 -1
  30. package/dist/debug/safety/index.js +1 -0
  31. package/dist/debug/safety/index.js.map +1 -1
  32. package/dist/engine/agent-api/app/actorBoneMatrixLookup.d.ts +22 -0
  33. package/dist/engine/agent-api/app/actorBoneMatrixLookup.d.ts.map +1 -0
  34. package/dist/engine/agent-api/app/actorBoneMatrixLookup.js +24 -0
  35. package/dist/engine/agent-api/app/actorBoneMatrixLookup.js.map +1 -0
  36. package/dist/engine/agent-api/app/canvas.d.ts +16 -0
  37. package/dist/engine/agent-api/app/canvas.d.ts.map +1 -1
  38. package/dist/engine/agent-api/app/canvas.js +15 -0
  39. package/dist/engine/agent-api/app/canvas.js.map +1 -1
  40. package/dist/engine/agent-api/app/createAuraApp.d.ts.map +1 -1
  41. package/dist/engine/agent-api/app/createAuraApp.js +21 -3
  42. package/dist/engine/agent-api/app/createAuraApp.js.map +1 -1
  43. package/dist/engine/agent-api/app/frameLoop.d.ts.map +1 -1
  44. package/dist/engine/agent-api/app/frameLoop.js +21 -3
  45. package/dist/engine/agent-api/app/frameLoop.js.map +1 -1
  46. package/dist/engine/agent-api/app/mountFailure.d.ts +6 -0
  47. package/dist/engine/agent-api/app/mountFailure.d.ts.map +1 -0
  48. package/dist/engine/agent-api/app/mountFailure.js +9 -0
  49. package/dist/engine/agent-api/app/mountFailure.js.map +1 -0
  50. package/dist/engine/agent-api/app/parentFit.d.ts +35 -0
  51. package/dist/engine/agent-api/app/parentFit.d.ts.map +1 -0
  52. package/dist/engine/agent-api/app/parentFit.js +36 -0
  53. package/dist/engine/agent-api/app/parentFit.js.map +1 -0
  54. package/dist/engine/agent-api/compiler/customMaterial.js +3 -2
  55. package/dist/engine/agent-api/compiler/customMaterial.js.map +1 -1
  56. package/dist/engine/agent-api/nodes/batched.d.ts +10 -0
  57. package/dist/engine/agent-api/nodes/batched.d.ts.map +1 -1
  58. package/dist/engine/agent-api/nodes/batched.js +7 -5
  59. package/dist/engine/agent-api/nodes/batched.js.map +1 -1
  60. package/dist/engine/agent-api/nodes/builder.d.ts +13 -0
  61. package/dist/engine/agent-api/nodes/builder.d.ts.map +1 -1
  62. package/dist/engine/agent-api/nodes/builder.js +7 -3
  63. package/dist/engine/agent-api/nodes/builder.js.map +1 -1
  64. package/dist/engine/agent-api/nodes/instancedMesh.d.ts +10 -0
  65. package/dist/engine/agent-api/nodes/instancedMesh.d.ts.map +1 -1
  66. package/dist/engine/agent-api/nodes/instancedMesh.js +7 -5
  67. package/dist/engine/agent-api/nodes/instancedMesh.js.map +1 -1
  68. package/dist/engine/lanes/prd06.d.ts.map +1 -1
  69. package/dist/engine/lanes/prd06.js +1 -16
  70. package/dist/engine/lanes/prd06.js.map +1 -1
  71. package/dist/engine/qa/fixedStepLoop.d.ts +2 -0
  72. package/dist/engine/qa/fixedStepLoop.d.ts.map +1 -1
  73. package/dist/engine/qa/fixedStepLoop.js +3 -0
  74. package/dist/engine/qa/fixedStepLoop.js.map +1 -1
  75. package/dist/game/evidence/textureStatus.d.ts +24 -0
  76. package/dist/game/evidence/textureStatus.d.ts.map +1 -0
  77. package/dist/game/evidence/textureStatus.js +27 -0
  78. package/dist/game/evidence/textureStatus.js.map +1 -0
  79. package/dist/game/index.d.ts +5 -0
  80. package/dist/game/index.d.ts.map +1 -1
  81. package/dist/game/index.js +3 -0
  82. package/dist/game/index.js.map +1 -1
  83. package/dist/game/motion/boneAttach.d.ts +42 -0
  84. package/dist/game/motion/boneAttach.d.ts.map +1 -0
  85. package/dist/game/motion/boneAttach.js +166 -0
  86. package/dist/game/motion/boneAttach.js.map +1 -0
  87. package/dist/game/motion/cameraClear.d.ts +35 -0
  88. package/dist/game/motion/cameraClear.d.ts.map +1 -0
  89. package/dist/game/motion/cameraClear.js +64 -0
  90. package/dist/game/motion/cameraClear.js.map +1 -0
  91. package/dist/game/motion/doubleFrame.d.ts +37 -0
  92. package/dist/game/motion/doubleFrame.d.ts.map +1 -0
  93. package/dist/game/motion/doubleFrame.js +59 -0
  94. package/dist/game/motion/doubleFrame.js.map +1 -0
  95. package/dist/game/motion/footSlide.d.ts +32 -0
  96. package/dist/game/motion/footSlide.d.ts.map +1 -0
  97. package/dist/game/motion/footSlide.js +59 -0
  98. package/dist/game/motion/footSlide.js.map +1 -0
  99. package/dist/game/motion/impact.d.ts +113 -0
  100. package/dist/game/motion/impact.d.ts.map +1 -0
  101. package/dist/game/motion/impact.js +233 -0
  102. package/dist/game/motion/impact.js.map +1 -0
  103. package/dist/game/motion/index.d.ts +19 -0
  104. package/dist/game/motion/index.d.ts.map +1 -0
  105. package/dist/game/motion/index.js +10 -0
  106. package/dist/game/motion/index.js.map +1 -0
  107. package/dist/game/motion/locomotion.d.ts +55 -0
  108. package/dist/game/motion/locomotion.d.ts.map +1 -0
  109. package/dist/game/motion/locomotion.js +107 -0
  110. package/dist/game/motion/locomotion.js.map +1 -0
  111. package/dist/game/motion/motionGate.d.ts +41 -0
  112. package/dist/game/motion/motionGate.d.ts.map +1 -0
  113. package/dist/game/motion/motionGate.js +71 -0
  114. package/dist/game/motion/motionGate.js.map +1 -0
  115. package/dist/game/motion/presenter.d.ts +37 -0
  116. package/dist/game/motion/presenter.d.ts.map +1 -0
  117. package/dist/game/motion/presenter.js +72 -0
  118. package/dist/game/motion/presenter.js.map +1 -0
  119. package/dist/game/motion/smoothing.d.ts +34 -0
  120. package/dist/game/motion/smoothing.d.ts.map +1 -0
  121. package/dist/game/motion/smoothing.js +92 -0
  122. package/dist/game/motion/smoothing.js.map +1 -0
  123. package/dist/game/session/warmPrograms.d.ts +58 -0
  124. package/dist/game/session/warmPrograms.d.ts.map +1 -0
  125. package/dist/game/session/warmPrograms.js +63 -0
  126. package/dist/game/session/warmPrograms.js.map +1 -0
  127. package/dist/rendering/environment/EnvironmentCache.d.ts.map +1 -1
  128. package/dist/rendering/environment/EnvironmentCache.js +6 -1
  129. package/dist/rendering/environment/EnvironmentCache.js.map +1 -1
  130. package/dist/rendering/environment/neutralEmbedded.d.ts +5 -0
  131. package/dist/rendering/environment/neutralEmbedded.d.ts.map +1 -0
  132. package/dist/rendering/environment/neutralEmbedded.js +1118 -0
  133. package/dist/rendering/environment/neutralEmbedded.js.map +1 -0
  134. package/dist/rendering/environment/neutralEmbeddedLoader.d.ts +5 -0
  135. package/dist/rendering/environment/neutralEmbeddedLoader.d.ts.map +1 -0
  136. package/dist/rendering/environment/neutralEmbeddedLoader.js +32 -0
  137. package/dist/rendering/environment/neutralEmbeddedLoader.js.map +1 -0
  138. package/package.json +25 -25
  139. package/templates/cinematic-scene/package.json +2 -2
  140. package/templates/mini-game/package.json +2 -2
  141. package/templates/product-viewer/package.json +2 -2
  142. package/templates/production-asset-inspector/package.json +1 -1
  143. package/templates/production-material-studio/package.json +1 -1
  144. package/templates/production-product-configurator/package.json +1 -1
  145. package/templates/production-product-viewer/package.json +1 -1
@@ -0,0 +1,59 @@
1
+ /** Two skinned meshes bound to one skeleton in the same frame draw the pose twice. */
2
+ export function detectSharedSkeleton(draws) {
3
+ const bySkeleton = new Map();
4
+ for (const d of draws) {
5
+ if (d.skeletonId === undefined)
6
+ continue;
7
+ const list = bySkeleton.get(d.skeletonId) ?? [];
8
+ if (!list.includes(d.meshId))
9
+ list.push(d.meshId);
10
+ bySkeleton.set(d.skeletonId, list);
11
+ }
12
+ const out = [];
13
+ for (const [skeleton, meshes] of bySkeleton) {
14
+ if (meshes.length > 1)
15
+ out.push({ kind: "shared-skeleton", detail: `skeleton ${skeleton} drives ${meshes.length} meshes`, ids: meshes });
16
+ }
17
+ return out;
18
+ }
19
+ /** Two instances of the same model at nearly the same place read as a ghost or doubled player. */
20
+ export function detectCoincidentModels(instances, epsilon = 0.08) {
21
+ const out = [];
22
+ for (let i = 0; i < instances.length; i += 1) {
23
+ for (let j = i + 1; j < instances.length; j += 1) {
24
+ const a = instances[i];
25
+ const b = instances[j];
26
+ if (a.modelId !== b.modelId)
27
+ continue;
28
+ const d = Math.hypot(a.position[0] - b.position[0], a.position[1] - b.position[1], a.position[2] - b.position[2]);
29
+ if (d <= epsilon)
30
+ out.push({ kind: "coincident-model", detail: `${a.id} and ${b.id} (${a.modelId}) are ${d.toFixed(3)} m apart`, ids: [a.id, b.id] });
31
+ }
32
+ }
33
+ return out;
34
+ }
35
+ /** Override layers summing past 1, or one clip applied on two layers, give the doubled look. */
36
+ export function detectDoubleBlend(layers) {
37
+ const out = [];
38
+ const active = layers.filter((l) => l.weight > 1e-3);
39
+ const overrideSum = active.filter((l) => (l.blendMode ?? "override") === "override").reduce((s, l) => s + l.weight, 0);
40
+ if (overrideSum > 1.001)
41
+ out.push({ kind: "double-blend", detail: `override layers sum to ${overrideSum.toFixed(3)}`, ids: active.map((l) => l.name) });
42
+ const byClip = new Map();
43
+ for (const l of active)
44
+ byClip.set(l.clip, [...(byClip.get(l.clip) ?? []), l.name]);
45
+ for (const [clip, names] of byClip) {
46
+ if (names.length > 1)
47
+ out.push({ kind: "double-blend", detail: `clip ${clip} is applied on ${names.length} layers`, ids: names });
48
+ }
49
+ return out;
50
+ }
51
+ export function checkDoubleFrame(input) {
52
+ const findings = [
53
+ ...detectSharedSkeleton(input.draws ?? []),
54
+ ...detectCoincidentModels(input.instances ?? [], input.epsilon),
55
+ ...detectDoubleBlend(input.layers ?? [])
56
+ ];
57
+ return { ok: findings.length === 0, findings };
58
+ }
59
+ //# sourceMappingURL=doubleFrame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doubleFrame.js","sourceRoot":"","sources":["../../../../../packages/game/src/motion/doubleFrame.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export interface FootSlideOptions {
2
+ /** A foot counts as planted when it is within this height of the ground (default 0.06 m). */
3
+ readonly plantedHeight?: number;
4
+ /** Planted foot horizontal speed limit in m/s (default 0.15). */
5
+ readonly threshold?: number;
6
+ /** Minimum foot lift range in metres expected when the body moves faster than `movingSpeed` (default 0.03). */
7
+ readonly minLift?: number;
8
+ readonly movingSpeed?: number;
9
+ }
10
+ export interface FootSlideReport {
11
+ readonly samples: number;
12
+ readonly plantedSamples: number;
13
+ readonly maxPlantedSpeed: number;
14
+ readonly meanPlantedSpeed: number;
15
+ readonly p95PlantedSpeed: number;
16
+ /** Highest minus lowest foot height seen while the body was moving. */
17
+ readonly liftRange: number;
18
+ /** The body moved but the foot never lifted: legs are not stepping. */
19
+ readonly notStepping: boolean;
20
+ readonly passed: boolean;
21
+ }
22
+ export interface FootSlideMeter {
23
+ feed(timeSeconds: number, foot: readonly [number, number, number], extra?: {
24
+ readonly groundHeight?: number;
25
+ readonly bodySpeed?: number;
26
+ }): void;
27
+ report(): FootSlideReport;
28
+ reset(): void;
29
+ }
30
+ /** Objective version of "he is just sliding": world speed of a planted foot, plus a legs-not-stepping check. */
31
+ export declare function createFootSlideMeter(options?: FootSlideOptions): FootSlideMeter;
32
+ //# sourceMappingURL=footSlide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"footSlide.d.ts","sourceRoot":"","sources":["../../../../../packages/game/src/motion/footSlide.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,6FAA6F;IAC7F,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,iEAAiE;IACjE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,+GAA+G;IAC/G,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClJ,MAAM,IAAI,eAAe,CAAC;IAC1B,KAAK,IAAI,IAAI,CAAC;CACf;AAED,gHAAgH;AAChH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,gBAAqB,GAAG,cAAc,CAyDnF"}
@@ -0,0 +1,59 @@
1
+ /** Objective version of "he is just sliding": world speed of a planted foot, plus a legs-not-stepping check. */
2
+ export function createFootSlideMeter(options = {}) {
3
+ const plantedHeight = options.plantedHeight ?? 0.06;
4
+ const threshold = options.threshold ?? 0.15;
5
+ const minLift = options.minLift ?? 0.03;
6
+ const movingSpeed = options.movingSpeed ?? 0.5;
7
+ let prev;
8
+ let speeds = [];
9
+ let samples = 0;
10
+ let loLift = Number.POSITIVE_INFINITY;
11
+ let hiLift = Number.NEGATIVE_INFINITY;
12
+ let movingSamples = 0;
13
+ return {
14
+ feed(t, foot, extra) {
15
+ const ground = extra?.groundHeight ?? 0;
16
+ const h = foot[1] - ground;
17
+ const planted = h <= plantedHeight;
18
+ samples += 1;
19
+ if ((extra?.bodySpeed ?? 0) >= movingSpeed) {
20
+ movingSamples += 1;
21
+ loLift = Math.min(loLift, h);
22
+ hiLift = Math.max(hiLift, h);
23
+ }
24
+ if (prev !== undefined && planted && prev.planted && t > prev.t) {
25
+ const dx = foot[0] - prev.p[0];
26
+ const dz = foot[2] - prev.p[2];
27
+ speeds.push(Math.hypot(dx, dz) / (t - prev.t));
28
+ }
29
+ prev = { t, p: foot, planted };
30
+ },
31
+ report() {
32
+ const sorted = [...speeds].sort((a, b) => a - b);
33
+ const max = sorted.length ? sorted[sorted.length - 1] : 0;
34
+ const mean = sorted.length ? sorted.reduce((s, v) => s + v, 0) / sorted.length : 0;
35
+ const p95 = sorted.length ? sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))] : 0;
36
+ const liftRange = movingSamples > 0 ? hiLift - loLift : 0;
37
+ const notStepping = movingSamples > 5 && liftRange < minLift;
38
+ return {
39
+ samples,
40
+ plantedSamples: sorted.length,
41
+ maxPlantedSpeed: max,
42
+ meanPlantedSpeed: mean,
43
+ p95PlantedSpeed: p95,
44
+ liftRange,
45
+ notStepping,
46
+ passed: !notStepping && p95 <= threshold
47
+ };
48
+ },
49
+ reset() {
50
+ prev = undefined;
51
+ speeds = [];
52
+ samples = 0;
53
+ loLift = Number.POSITIVE_INFINITY;
54
+ hiLift = Number.NEGATIVE_INFINITY;
55
+ movingSamples = 0;
56
+ }
57
+ };
58
+ }
59
+ //# sourceMappingURL=footSlide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"footSlide.js","sourceRoot":"","sources":["../../../../../packages/game/src/motion/footSlide.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ export type V3 = [number, number, number];
2
+ export interface ImpactBoxCollider {
3
+ readonly kind: "box";
4
+ readonly id: string;
5
+ readonly center: readonly [number, number, number];
6
+ readonly half: readonly [number, number, number];
7
+ /** Rotation about Y in radians. */
8
+ readonly yaw?: number;
9
+ readonly tag?: string;
10
+ readonly restitution?: number;
11
+ readonly friction?: number;
12
+ }
13
+ export interface ImpactSphereCollider {
14
+ readonly kind: "sphere";
15
+ readonly id: string;
16
+ readonly center: readonly [number, number, number];
17
+ readonly radius: number;
18
+ readonly tag?: string;
19
+ readonly restitution?: number;
20
+ readonly friction?: number;
21
+ }
22
+ export type ImpactCollider = ImpactBoxCollider | ImpactSphereCollider;
23
+ export interface ImpactBody {
24
+ position: V3;
25
+ velocity: V3;
26
+ radius: number;
27
+ }
28
+ export interface Impact {
29
+ readonly colliderId: string;
30
+ readonly tag: string | undefined;
31
+ readonly point: V3;
32
+ /** Unit normal pointing out of the collider, towards the body. */
33
+ readonly normal: V3;
34
+ /** Approach speed along the normal before the response, m/s. */
35
+ readonly speed: number;
36
+ readonly impulse: number;
37
+ }
38
+ export interface ImpactWorldOptions {
39
+ readonly colliders: readonly ImpactCollider[];
40
+ readonly restitution?: number;
41
+ readonly friction?: number;
42
+ /** Contacts slower than this resolve but do not emit an event (resting contact). Default 0.5 m/s. */
43
+ readonly eventMinSpeed?: number;
44
+ readonly onImpact?: (impact: Impact) => void;
45
+ }
46
+ export interface ImpactWorld {
47
+ step(body: ImpactBody, dt: number): Impact[];
48
+ add(collider: ImpactCollider): void;
49
+ remove(id: string): void;
50
+ reset(): void;
51
+ }
52
+ /**
53
+ * Swept-sphere collision against static boxes (optionally yawed) and spheres. A body moving fast cannot
54
+ * tunnel through a wall or gate; each new contact emits one `Impact` (continuous sliding does not repeat).
55
+ * Box corners are treated as sharp expanded boxes (slightly conservative at corners).
56
+ */
57
+ export declare function createImpactWorld(options: ImpactWorldOptions): ImpactWorld;
58
+ export interface HitStop {
59
+ trigger(ms: number): void;
60
+ update(realDtSeconds: number): void;
61
+ /** Multiply the simulation time step by this; 1 normally, near 0 during a hit-stop. */
62
+ timeScale(): number;
63
+ readonly active: boolean;
64
+ }
65
+ export declare function createHitStop(frozenScale?: number): HitStop;
66
+ export interface CameraShake {
67
+ add(trauma: number): void;
68
+ update(dt: number): {
69
+ readonly x: number;
70
+ readonly y: number;
71
+ readonly roll: number;
72
+ };
73
+ readonly trauma: number;
74
+ }
75
+ /** Trauma-based shake: offset scales with trauma squared, decays linearly, deterministic (no Math.random). */
76
+ export declare function createCameraShake(options?: {
77
+ readonly decayPerSecond?: number;
78
+ readonly maxOffset?: number;
79
+ readonly maxRoll?: number;
80
+ }): CameraShake;
81
+ export interface ParticleBurst {
82
+ readonly point: V3;
83
+ readonly normal: V3;
84
+ readonly count: number;
85
+ readonly speed: number;
86
+ }
87
+ export interface ImpactFeedbackOptions {
88
+ readonly hitStop?: HitStop;
89
+ readonly shake?: CameraShake;
90
+ /** Play a cue by name at a gain 0..1 (wire to a cue bank). */
91
+ readonly cue?: (name: string, gain: number) => void;
92
+ readonly cueName?: string;
93
+ readonly particles?: (burst: ParticleBurst) => void;
94
+ readonly onDamage?: (amount: number, impact: Impact) => void;
95
+ /** Impact speed (m/s) that maps to full strength. Default 12. */
96
+ readonly fullSpeed?: number;
97
+ /** Hit-stop duration range in ms. Defaults 30 to 80. */
98
+ readonly hitStopMs?: readonly [number, number];
99
+ readonly damagePerSpeed?: number;
100
+ readonly minSpeed?: number;
101
+ }
102
+ export interface ImpactFeedbackResult {
103
+ readonly strength: number;
104
+ readonly hitStopMs: number;
105
+ readonly trauma: number;
106
+ readonly damage: number;
107
+ readonly particleCount: number;
108
+ }
109
+ /** The standard feedback bundle for a solid hit: hit-stop, camera shake, sound, particles and damage, scaled by speed. */
110
+ export declare function createImpactFeedback(options: ImpactFeedbackOptions): {
111
+ handle(impact: Impact): ImpactFeedbackResult;
112
+ };
113
+ //# sourceMappingURL=impact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact.d.ts","sourceRoot":"","sources":["../../../../../packages/game/src/motion/impact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,233 @@
1
+ const EPS = 1e-9;
2
+ function rotY(v, yaw) {
3
+ const c = Math.cos(yaw);
4
+ const s = Math.sin(yaw);
5
+ return [c * v[0] + s * v[2], v[1], -s * v[0] + c * v[2]];
6
+ }
7
+ function sweepBox(p, d, radius, box) {
8
+ const yaw = box.yaw ?? 0;
9
+ const rel = [p[0] - box.center[0], p[1] - box.center[1], p[2] - box.center[2]];
10
+ const lp = rotY(rel, -yaw);
11
+ const ld = rotY(d, -yaw);
12
+ const h = [box.half[0] + radius, box.half[1] + radius, box.half[2] + radius];
13
+ const inside = Math.abs(lp[0]) < h[0] && Math.abs(lp[1]) < h[1] && Math.abs(lp[2]) < h[2];
14
+ if (inside) {
15
+ let axis = 0;
16
+ let best = Number.POSITIVE_INFINITY;
17
+ for (let i = 0; i < 3; i += 1) {
18
+ const pen = h[i] - Math.abs(lp[i]);
19
+ if (pen < best) {
20
+ best = pen;
21
+ axis = i;
22
+ }
23
+ }
24
+ const n = [0, 0, 0];
25
+ n[axis] = lp[axis] >= 0 ? 1 : -1;
26
+ return { t: 0, normal: rotY(n, yaw), collider: box };
27
+ }
28
+ let tmin = 0;
29
+ let tmax = 1;
30
+ let axisHit = -1;
31
+ let sign = 1;
32
+ for (let i = 0; i < 3; i += 1) {
33
+ const o = lp[i];
34
+ const dir = ld[i];
35
+ if (Math.abs(dir) < EPS) {
36
+ if (Math.abs(o) >= h[i])
37
+ return undefined;
38
+ continue;
39
+ }
40
+ let t1 = (-h[i] - o) / dir;
41
+ let t2 = (h[i] - o) / dir;
42
+ let s = -1;
43
+ if (t1 > t2) {
44
+ [t1, t2] = [t2, t1];
45
+ s = 1;
46
+ }
47
+ if (t1 > tmin) {
48
+ tmin = t1;
49
+ axisHit = i;
50
+ sign = s;
51
+ }
52
+ tmax = Math.min(tmax, t2);
53
+ if (tmin > tmax)
54
+ return undefined;
55
+ }
56
+ if (axisHit < 0)
57
+ return undefined;
58
+ const n = [0, 0, 0];
59
+ n[axisHit] = sign;
60
+ return { t: tmin, normal: rotY(n, yaw), collider: box };
61
+ }
62
+ function sweepSphere(p, d, radius, s) {
63
+ const R = radius + s.radius;
64
+ const m = [p[0] - s.center[0], p[1] - s.center[1], p[2] - s.center[2]];
65
+ const a = d[0] * d[0] + d[1] * d[1] + d[2] * d[2];
66
+ const c = m[0] * m[0] + m[1] * m[1] + m[2] * m[2] - R * R;
67
+ if (c < 0) {
68
+ const len = Math.hypot(m[0], m[1], m[2]) || 1;
69
+ return { t: 0, normal: [m[0] / len, m[1] / len, m[2] / len], collider: s };
70
+ }
71
+ if (a < EPS)
72
+ return undefined;
73
+ const b = m[0] * d[0] + m[1] * d[1] + m[2] * d[2];
74
+ if (b >= 0)
75
+ return undefined;
76
+ const disc = b * b - a * c;
77
+ if (disc < 0)
78
+ return undefined;
79
+ const t = (-b - Math.sqrt(disc)) / a;
80
+ if (t < 0 || t > 1)
81
+ return undefined;
82
+ const hit = [m[0] + d[0] * t, m[1] + d[1] * t, m[2] + d[2] * t];
83
+ const len = Math.hypot(hit[0], hit[1], hit[2]) || 1;
84
+ return { t, normal: [hit[0] / len, hit[1] / len, hit[2] / len], collider: s };
85
+ }
86
+ /**
87
+ * Swept-sphere collision against static boxes (optionally yawed) and spheres. A body moving fast cannot
88
+ * tunnel through a wall or gate; each new contact emits one `Impact` (continuous sliding does not repeat).
89
+ * Box corners are treated as sharp expanded boxes (slightly conservative at corners).
90
+ */
91
+ export function createImpactWorld(options) {
92
+ const colliders = new Map();
93
+ for (const c of options.colliders)
94
+ colliders.set(c.id, c);
95
+ const baseRestitution = options.restitution ?? 0.2;
96
+ const baseFriction = options.friction ?? 0.1;
97
+ const eventMin = options.eventMinSpeed ?? 0.5;
98
+ let touching = new Set();
99
+ return {
100
+ add(c) {
101
+ colliders.set(c.id, c);
102
+ },
103
+ remove(id) {
104
+ colliders.delete(id);
105
+ touching.delete(id);
106
+ },
107
+ reset() {
108
+ touching = new Set();
109
+ },
110
+ step(body, dt) {
111
+ const impacts = [];
112
+ const now = new Set();
113
+ let remaining = dt;
114
+ for (let iter = 0; iter < 4 && remaining > 0; iter += 1) {
115
+ const d = [body.velocity[0] * remaining, body.velocity[1] * remaining, body.velocity[2] * remaining];
116
+ let best;
117
+ for (const c of colliders.values()) {
118
+ const hit = c.kind === "box" ? sweepBox(body.position, d, body.radius, c) : sweepSphere(body.position, d, body.radius, c);
119
+ if (hit !== undefined && (best === undefined || hit.t < best.t))
120
+ best = hit;
121
+ }
122
+ if (best === undefined) {
123
+ body.position[0] += d[0];
124
+ body.position[1] += d[1];
125
+ body.position[2] += d[2];
126
+ remaining = 0;
127
+ break;
128
+ }
129
+ const skin = 1e-4;
130
+ const tt = Math.max(0, best.t);
131
+ body.position[0] += d[0] * tt + best.normal[0] * skin;
132
+ body.position[1] += d[1] * tt + best.normal[1] * skin;
133
+ body.position[2] += d[2] * tt + best.normal[2] * skin;
134
+ const n = best.normal;
135
+ const vn = body.velocity[0] * n[0] + body.velocity[1] * n[1] + body.velocity[2] * n[2];
136
+ const approach = Math.max(0, -vn);
137
+ const e = best.collider.restitution ?? baseRestitution;
138
+ const mu = best.collider.friction ?? baseFriction;
139
+ if (vn < 0) {
140
+ const tx = body.velocity[0] - vn * n[0];
141
+ const ty = body.velocity[1] - vn * n[1];
142
+ const tz = body.velocity[2] - vn * n[2];
143
+ const keep = Math.max(0, 1 - mu);
144
+ body.velocity[0] = tx * keep - e * vn * n[0];
145
+ body.velocity[1] = ty * keep - e * vn * n[1];
146
+ body.velocity[2] = tz * keep - e * vn * n[2];
147
+ }
148
+ const id = best.collider.id;
149
+ now.add(id);
150
+ if (!touching.has(id) && approach >= eventMin) {
151
+ const point = [body.position[0] - n[0] * body.radius, body.position[1] - n[1] * body.radius, body.position[2] - n[2] * body.radius];
152
+ const impact = { colliderId: id, tag: best.collider.tag, point, normal: [n[0], n[1], n[2]], speed: approach, impulse: approach * (1 + e) };
153
+ impacts.push(impact);
154
+ options.onImpact?.(impact);
155
+ }
156
+ remaining *= 1 - tt;
157
+ if (tt >= 1)
158
+ break;
159
+ }
160
+ touching = now;
161
+ return impacts;
162
+ }
163
+ };
164
+ }
165
+ export function createHitStop(frozenScale = 0.02) {
166
+ let remaining = 0;
167
+ return {
168
+ trigger(ms) {
169
+ remaining = Math.max(remaining, Math.max(0, ms) / 1000);
170
+ },
171
+ update(dt) {
172
+ remaining = Math.max(0, remaining - Math.max(0, dt));
173
+ },
174
+ timeScale() {
175
+ return remaining > 0 ? frozenScale : 1;
176
+ },
177
+ get active() {
178
+ return remaining > 0;
179
+ }
180
+ };
181
+ }
182
+ /** Trauma-based shake: offset scales with trauma squared, decays linearly, deterministic (no Math.random). */
183
+ export function createCameraShake(options = {}) {
184
+ const decay = options.decayPerSecond ?? 1.6;
185
+ const maxOffset = options.maxOffset ?? 0.12;
186
+ const maxRoll = options.maxRoll ?? 0.04;
187
+ let trauma = 0;
188
+ let t = 0;
189
+ return {
190
+ add(amount) {
191
+ trauma = Math.min(1, trauma + Math.max(0, amount));
192
+ },
193
+ update(dt) {
194
+ t += Math.max(0, dt);
195
+ trauma = Math.max(0, trauma - decay * Math.max(0, dt));
196
+ const s = trauma * trauma;
197
+ return {
198
+ x: s * maxOffset * Math.sin(t * 61.3 + 1.7),
199
+ y: s * maxOffset * Math.sin(t * 47.9 + 4.1),
200
+ roll: s * maxRoll * Math.sin(t * 39.1 + 2.9)
201
+ };
202
+ },
203
+ get trauma() {
204
+ return trauma;
205
+ }
206
+ };
207
+ }
208
+ /** The standard feedback bundle for a solid hit: hit-stop, camera shake, sound, particles and damage, scaled by speed. */
209
+ export function createImpactFeedback(options) {
210
+ const full = options.fullSpeed ?? 12;
211
+ const [msLo, msHi] = options.hitStopMs ?? [30, 80];
212
+ const minSpeed = options.minSpeed ?? 0.5;
213
+ return {
214
+ handle(impact) {
215
+ const strength = Math.max(0, Math.min(1, impact.speed / full));
216
+ if (impact.speed < minSpeed)
217
+ return { strength, hitStopMs: 0, trauma: 0, damage: 0, particleCount: 0 };
218
+ const hitStopMs = msLo + (msHi - msLo) * strength;
219
+ const trauma = 0.2 + 0.8 * strength;
220
+ const damage = (options.damagePerSpeed ?? 0) * impact.speed;
221
+ const particleCount = Math.round(4 + 28 * strength);
222
+ options.hitStop?.trigger(hitStopMs);
223
+ options.shake?.add(trauma);
224
+ if (options.cue !== undefined)
225
+ options.cue(options.cueName ?? "impact", 0.25 + 0.75 * strength);
226
+ options.particles?.({ point: impact.point, normal: impact.normal, count: particleCount, speed: 1 + 5 * strength });
227
+ if (damage > 0)
228
+ options.onDamage?.(damage, impact);
229
+ return { strength, hitStopMs, trauma, damage, particleCount };
230
+ }
231
+ };
232
+ }
233
+ //# sourceMappingURL=impact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact.js","sourceRoot":"","sources":["../../../../../packages/game/src/motion/impact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export { smoothDamp, createSmoothFollow3, lerpAngle, createRenderInterpolator, secondDifferenceRms, jitterReport } from "./smoothing.js";
2
+ export type { DampResult, SmoothFollow3, RenderInterpolator, JitterReport } from "./smoothing.js";
3
+ export { createLocomotion, proceduralLegSwing } from "./locomotion.js";
4
+ export type { LocomotionGait, LocomotionOptions, LocomotionFrame, Locomotion, LegPose, ProceduralGait } from "./locomotion.js";
5
+ export { createFootSlideMeter } from "./footSlide.js";
6
+ export type { FootSlideOptions, FootSlideReport, FootSlideMeter } from "./footSlide.js";
7
+ export { createImpactWorld, createHitStop, createCameraShake, createImpactFeedback } from "./impact.js";
8
+ export type { ImpactBoxCollider, ImpactSphereCollider, ImpactCollider, ImpactBody, Impact, ImpactWorldOptions, ImpactWorld, HitStop, CameraShake, ParticleBurst, ImpactFeedbackOptions, ImpactFeedbackResult } from "./impact.js";
9
+ export { attachToBone, resolveBone, boneAliases, boneWorldPosition, attachmentDistance } from "./boneAttach.js";
10
+ export type { BoneRole, SocketLike, AttachableActor, AttachToBoneOptions, BoneAttachment } from "./boneAttach.js";
11
+ export { checkDoubleFrame, detectSharedSkeleton, detectCoincidentModels, detectDoubleBlend } from "./doubleFrame.js";
12
+ export type { DrawEntry, ModelInstance, AnimLayer, DoubleFrameFinding, DoubleFrameReport } from "./doubleFrame.js";
13
+ export { createFixedStepPresenter, createRecordBlend } from "./presenter.js";
14
+ export type { AlphaSource, FixedStepPresenterOptions, FixedStepPresenter, RecordBlendOptions } from "./presenter.js";
15
+ export { runMotionGate } from "./motionGate.js";
16
+ export type { MotionGateOptions, MotionGateReport } from "./motionGate.js";
17
+ export { clearCameraEye, createCameraClearance } from "./cameraClear.js";
18
+ export type { CameraVec3, ClearEyeOptions, ClearEye, CameraClearanceOptions, CameraClearance } from "./cameraClear.js";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/game/src/motion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,SAAS,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtI,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5H,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrG,YAAY,EACV,iBAAiB,EAAE,oBAAoB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE,WAAW,EAC5G,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,qBAAqB,EAAE,oBAAoB,EACjF,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC7G,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClH,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAChH,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC1E,YAAY,EAAE,WAAW,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAClH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { smoothDamp, createSmoothFollow3, lerpAngle, createRenderInterpolator, secondDifferenceRms, jitterReport } from "./smoothing.js";
2
+ export { createLocomotion, proceduralLegSwing } from "./locomotion.js";
3
+ export { createFootSlideMeter } from "./footSlide.js";
4
+ export { createImpactWorld, createHitStop, createCameraShake, createImpactFeedback } from "./impact.js";
5
+ export { attachToBone, resolveBone, boneAliases, boneWorldPosition, attachmentDistance } from "./boneAttach.js";
6
+ export { checkDoubleFrame, detectSharedSkeleton, detectCoincidentModels, detectDoubleBlend } from "./doubleFrame.js";
7
+ export { createFixedStepPresenter, createRecordBlend } from "./presenter.js";
8
+ export { runMotionGate } from "./motionGate.js";
9
+ export { clearCameraEye, createCameraClearance } from "./cameraClear.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/game/src/motion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,SAAS,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEtI,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAKrG,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE7G,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElH,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,55 @@
1
+ export interface LocomotionGait {
2
+ readonly name: string;
3
+ /** Ground speed in m/s that the clip's root travels at playback rate 1. 0 for idle. */
4
+ readonly speed: number;
5
+ /** Seconds for one full stride cycle at playback rate 1. */
6
+ readonly cycle: number;
7
+ }
8
+ export interface LocomotionOptions {
9
+ readonly gaits: readonly LocomotionGait[];
10
+ /** Weight change per second when blending between gaits (default 6). */
11
+ readonly blendRate?: number;
12
+ readonly minRate?: number;
13
+ readonly maxRate?: number;
14
+ }
15
+ export interface LocomotionFrame {
16
+ readonly weights: Readonly<Record<string, number>>;
17
+ readonly rates: Readonly<Record<string, number>>;
18
+ /** Stride phase of the dominant gait, 0 to 1. */
19
+ readonly phase: number;
20
+ readonly dominant: string;
21
+ /** True when ground speed exceeds the fastest gait by more than the rate clamp can hide. */
22
+ readonly overspeed: boolean;
23
+ }
24
+ export interface Locomotion {
25
+ update(groundSpeed: number, dt: number): LocomotionFrame;
26
+ reset(): void;
27
+ }
28
+ /**
29
+ * Drives idle/walk/run/sprint clips from real ground speed so feet match the ground: clip weights
30
+ * follow speed brackets and playback rate = speed / clip speed (clamped), so planted feet do not slide.
31
+ */
32
+ export declare function createLocomotion(options: LocomotionOptions): Locomotion;
33
+ export interface LegPose {
34
+ /** Hip flexion, radians (positive swings the leg forward). */
35
+ readonly hip: number;
36
+ /** Knee flexion, radians (0 straight, positive bends). */
37
+ readonly knee: number;
38
+ readonly ankle: number;
39
+ }
40
+ export interface ProceduralGait {
41
+ readonly left: LegPose;
42
+ readonly right: LegPose;
43
+ /** Arm swing, radians, opposite to the same-side leg. */
44
+ readonly armLeft: number;
45
+ readonly armRight: number;
46
+ /** Vertical bob of the pelvis in metres. */
47
+ readonly bob: number;
48
+ }
49
+ /** Procedural leg-swing fallback for rigs with no usable walk/run clip. `phase` is a 0..1 stride phase. */
50
+ export declare function proceduralLegSwing(phase: number, groundSpeed: number, options?: {
51
+ readonly maxHip?: number;
52
+ readonly maxKnee?: number;
53
+ readonly speedForMax?: number;
54
+ }): ProceduralGait;
55
+ //# sourceMappingURL=locomotion.d.ts.map