@aura3d/engine 1.3.3 → 1.4.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 (229) hide show
  1. package/README.md +122 -15
  2. package/dist/assets/GLTFLoader.js +1 -0
  3. package/dist/assets/GLTFLoader.js.map +1 -1
  4. package/dist/assets/GLTFRenderResources.d.ts.map +1 -1
  5. package/dist/assets/GLTFRenderResources.js +1 -0
  6. package/dist/assets/GLTFRenderResources.js.map +1 -1
  7. package/dist/aura3d-cli/asset-constants.d.ts +5 -0
  8. package/dist/aura3d-cli/asset-constants.d.ts.map +1 -0
  9. package/dist/aura3d-cli/asset-constants.js +5 -0
  10. package/dist/aura3d-cli/asset-constants.js.map +1 -0
  11. package/dist/aura3d-cli/asset-core-types.d.ts +206 -0
  12. package/dist/aura3d-cli/asset-core-types.d.ts.map +1 -0
  13. package/dist/aura3d-cli/asset-core-types.js +2 -0
  14. package/dist/aura3d-cli/asset-core-types.js.map +1 -0
  15. package/dist/aura3d-cli/asset-inspection-types.d.ts +131 -0
  16. package/dist/aura3d-cli/asset-inspection-types.d.ts.map +1 -0
  17. package/dist/aura3d-cli/asset-inspection-types.js +2 -0
  18. package/dist/aura3d-cli/asset-inspection-types.js.map +1 -0
  19. package/dist/aura3d-cli/asset-manifest.d.ts +8 -0
  20. package/dist/aura3d-cli/asset-manifest.d.ts.map +1 -0
  21. package/dist/aura3d-cli/asset-manifest.js +116 -0
  22. package/dist/aura3d-cli/asset-manifest.js.map +1 -0
  23. package/dist/aura3d-cli/asset-readiness-types.d.ts +164 -0
  24. package/dist/aura3d-cli/asset-readiness-types.d.ts.map +1 -0
  25. package/dist/aura3d-cli/asset-readiness-types.js +2 -0
  26. package/dist/aura3d-cli/asset-readiness-types.js.map +1 -0
  27. package/dist/aura3d-cli/asset-source-ast.d.ts +8 -0
  28. package/dist/aura3d-cli/asset-source-ast.d.ts.map +1 -0
  29. package/dist/aura3d-cli/asset-source-ast.js +241 -0
  30. package/dist/aura3d-cli/asset-source-ast.js.map +1 -0
  31. package/dist/aura3d-cli/asset-source-roles.d.ts +4 -0
  32. package/dist/aura3d-cli/asset-source-roles.d.ts.map +1 -0
  33. package/dist/aura3d-cli/asset-source-roles.js +79 -0
  34. package/dist/aura3d-cli/asset-source-roles.js.map +1 -0
  35. package/dist/aura3d-cli/asset-source-validation.d.ts +4 -0
  36. package/dist/aura3d-cli/asset-source-validation.d.ts.map +1 -0
  37. package/dist/aura3d-cli/asset-source-validation.js +200 -0
  38. package/dist/aura3d-cli/asset-source-validation.js.map +1 -0
  39. package/dist/aura3d-cli/character-assembly-types.d.ts +39 -0
  40. package/dist/aura3d-cli/character-assembly-types.d.ts.map +1 -0
  41. package/dist/aura3d-cli/character-assembly-types.js +2 -0
  42. package/dist/aura3d-cli/character-assembly-types.js.map +1 -0
  43. package/dist/aura3d-cli/cli-help.d.ts +4 -0
  44. package/dist/aura3d-cli/cli-help.d.ts.map +1 -0
  45. package/dist/aura3d-cli/cli-help.js +48 -0
  46. package/dist/aura3d-cli/cli-help.js.map +1 -0
  47. package/dist/aura3d-cli/cli-options.d.ts +66 -0
  48. package/dist/aura3d-cli/cli-options.d.ts.map +1 -0
  49. package/dist/aura3d-cli/cli-options.js +234 -0
  50. package/dist/aura3d-cli/cli-options.js.map +1 -0
  51. package/dist/aura3d-cli/cli.js +20 -177
  52. package/dist/aura3d-cli/cli.js.map +1 -1
  53. package/dist/aura3d-cli/index.d.ts +12 -402
  54. package/dist/aura3d-cli/index.d.ts.map +1 -1
  55. package/dist/aura3d-cli/index.js +948 -90
  56. package/dist/aura3d-cli/index.js.map +1 -1
  57. package/dist/aura3d-cli/pull-bridge/adapters.d.ts +4 -0
  58. package/dist/aura3d-cli/pull-bridge/adapters.d.ts.map +1 -0
  59. package/dist/aura3d-cli/pull-bridge/adapters.js +38 -0
  60. package/dist/aura3d-cli/pull-bridge/adapters.js.map +1 -0
  61. package/dist/aura3d-cli/pull-bridge/download.d.ts +6 -0
  62. package/dist/aura3d-cli/pull-bridge/download.d.ts.map +1 -0
  63. package/dist/aura3d-cli/pull-bridge/download.js +208 -0
  64. package/dist/aura3d-cli/pull-bridge/download.js.map +1 -0
  65. package/dist/aura3d-cli/pull-bridge/profiles.d.ts +14 -0
  66. package/dist/aura3d-cli/pull-bridge/profiles.d.ts.map +1 -0
  67. package/dist/aura3d-cli/pull-bridge/profiles.js +63 -0
  68. package/dist/aura3d-cli/pull-bridge/profiles.js.map +1 -0
  69. package/dist/aura3d-cli/pull-bridge/provenance.d.ts +9 -0
  70. package/dist/aura3d-cli/pull-bridge/provenance.d.ts.map +1 -0
  71. package/dist/aura3d-cli/pull-bridge/provenance.js +99 -0
  72. package/dist/aura3d-cli/pull-bridge/provenance.js.map +1 -0
  73. package/dist/aura3d-cli/pull-bridge/pullable.d.ts +14 -0
  74. package/dist/aura3d-cli/pull-bridge/pullable.d.ts.map +1 -0
  75. package/dist/aura3d-cli/pull-bridge/pullable.js +58 -0
  76. package/dist/aura3d-cli/pull-bridge/pullable.js.map +1 -0
  77. package/dist/aura3d-cli/pull-bridge/scoring.d.ts +21 -0
  78. package/dist/aura3d-cli/pull-bridge/scoring.d.ts.map +1 -0
  79. package/dist/aura3d-cli/pull-bridge/scoring.js +177 -0
  80. package/dist/aura3d-cli/pull-bridge/scoring.js.map +1 -0
  81. package/dist/aura3d-cli/pull-bridge/search.d.ts +39 -0
  82. package/dist/aura3d-cli/pull-bridge/search.d.ts.map +1 -0
  83. package/dist/aura3d-cli/pull-bridge/search.js +114 -0
  84. package/dist/aura3d-cli/pull-bridge/search.js.map +1 -0
  85. package/dist/aura3d-cli/pull-bridge/types.d.ts +9 -0
  86. package/dist/aura3d-cli/pull-bridge/types.d.ts.map +1 -0
  87. package/dist/aura3d-cli/pull-bridge/types.js +2 -0
  88. package/dist/aura3d-cli/pull-bridge/types.js.map +1 -0
  89. package/dist/aura3d-cli/pull-bridge/vector3.d.ts +2 -0
  90. package/dist/aura3d-cli/pull-bridge/vector3.d.ts.map +1 -0
  91. package/dist/aura3d-cli/pull-bridge/vector3.js +4 -0
  92. package/dist/aura3d-cli/pull-bridge/vector3.js.map +1 -0
  93. package/dist/aura3d-cli/pull-bridge.d.ts +18 -100
  94. package/dist/aura3d-cli/pull-bridge.d.ts.map +1 -1
  95. package/dist/aura3d-cli/pull-bridge.js +59 -526
  96. package/dist/aura3d-cli/pull-bridge.js.map +1 -1
  97. package/dist/create-aura3d/cli.js +10 -0
  98. package/dist/create-aura3d/cli.js.map +1 -1
  99. package/dist/create-aura3d/index.d.ts +1 -1
  100. package/dist/create-aura3d/index.d.ts.map +1 -1
  101. package/dist/create-aura3d/index.js +2 -0
  102. package/dist/create-aura3d/index.js.map +1 -1
  103. package/dist/create-aura3d/showcase-spec-artifacts.d.ts +104 -0
  104. package/dist/create-aura3d/showcase-spec-artifacts.d.ts.map +1 -0
  105. package/dist/create-aura3d/showcase-spec-artifacts.js +142 -0
  106. package/dist/create-aura3d/showcase-spec-artifacts.js.map +1 -0
  107. package/dist/create-aura3d/showcase-spec-category-plan.d.ts +15 -0
  108. package/dist/create-aura3d/showcase-spec-category-plan.d.ts.map +1 -0
  109. package/dist/create-aura3d/showcase-spec-category-plan.js +45 -0
  110. package/dist/create-aura3d/showcase-spec-category-plan.js.map +1 -0
  111. package/dist/create-aura3d/showcase-spec-compiler.d.ts +5 -0
  112. package/dist/create-aura3d/showcase-spec-compiler.d.ts.map +1 -0
  113. package/dist/create-aura3d/showcase-spec-compiler.js +240 -0
  114. package/dist/create-aura3d/showcase-spec-compiler.js.map +1 -0
  115. package/dist/create-aura3d/showcase-spec-evidence.d.ts +7 -0
  116. package/dist/create-aura3d/showcase-spec-evidence.d.ts.map +1 -0
  117. package/dist/create-aura3d/showcase-spec-evidence.js +815 -0
  118. package/dist/create-aura3d/showcase-spec-evidence.js.map +1 -0
  119. package/dist/create-aura3d/showcase-spec-game-geometry-extractor.d.ts +21 -0
  120. package/dist/create-aura3d/showcase-spec-game-geometry-extractor.d.ts.map +1 -0
  121. package/dist/create-aura3d/showcase-spec-game-geometry-extractor.js +725 -0
  122. package/dist/create-aura3d/showcase-spec-game-geometry-extractor.js.map +1 -0
  123. package/dist/create-aura3d/showcase-spec-game-replacement-evidence.d.ts +14 -0
  124. package/dist/create-aura3d/showcase-spec-game-replacement-evidence.d.ts.map +1 -0
  125. package/dist/create-aura3d/showcase-spec-game-replacement-evidence.js +219 -0
  126. package/dist/create-aura3d/showcase-spec-game-replacement-evidence.js.map +1 -0
  127. package/dist/create-aura3d/showcase-spec-game-template-evidence.d.ts +72 -0
  128. package/dist/create-aura3d/showcase-spec-game-template-evidence.d.ts.map +1 -0
  129. package/dist/create-aura3d/showcase-spec-game-template-evidence.js +435 -0
  130. package/dist/create-aura3d/showcase-spec-game-template-evidence.js.map +1 -0
  131. package/dist/create-aura3d/showcase-spec-gameplay-evidence.d.ts +3 -0
  132. package/dist/create-aura3d/showcase-spec-gameplay-evidence.d.ts.map +1 -0
  133. package/dist/create-aura3d/showcase-spec-gameplay-evidence.js +108 -0
  134. package/dist/create-aura3d/showcase-spec-gameplay-evidence.js.map +1 -0
  135. package/dist/create-aura3d/showcase-spec-parser.d.ts +3 -0
  136. package/dist/create-aura3d/showcase-spec-parser.d.ts.map +1 -0
  137. package/dist/create-aura3d/showcase-spec-parser.js +662 -0
  138. package/dist/create-aura3d/showcase-spec-parser.js.map +1 -0
  139. package/dist/create-aura3d/showcase-spec-platformer-artifacts.d.ts +3 -0
  140. package/dist/create-aura3d/showcase-spec-platformer-artifacts.d.ts.map +1 -0
  141. package/dist/create-aura3d/showcase-spec-platformer-artifacts.js +276 -0
  142. package/dist/create-aura3d/showcase-spec-platformer-artifacts.js.map +1 -0
  143. package/dist/create-aura3d/showcase-spec-racing-artifacts.d.ts +3 -0
  144. package/dist/create-aura3d/showcase-spec-racing-artifacts.d.ts.map +1 -0
  145. package/dist/create-aura3d/showcase-spec-racing-artifacts.js +273 -0
  146. package/dist/create-aura3d/showcase-spec-racing-artifacts.js.map +1 -0
  147. package/dist/create-aura3d/showcase-spec-replacement-apply.d.ts +10 -0
  148. package/dist/create-aura3d/showcase-spec-replacement-apply.d.ts.map +1 -0
  149. package/dist/create-aura3d/showcase-spec-replacement-apply.js +166 -0
  150. package/dist/create-aura3d/showcase-spec-replacement-apply.js.map +1 -0
  151. package/dist/create-aura3d/showcase-spec-replacement-candidates.d.ts +16 -0
  152. package/dist/create-aura3d/showcase-spec-replacement-candidates.d.ts.map +1 -0
  153. package/dist/create-aura3d/showcase-spec-replacement-candidates.js +244 -0
  154. package/dist/create-aura3d/showcase-spec-replacement-candidates.js.map +1 -0
  155. package/dist/create-aura3d/showcase-spec-replacement-game-geometry.d.ts +4 -0
  156. package/dist/create-aura3d/showcase-spec-replacement-game-geometry.d.ts.map +1 -0
  157. package/dist/create-aura3d/showcase-spec-replacement-game-geometry.js +175 -0
  158. package/dist/create-aura3d/showcase-spec-replacement-game-geometry.js.map +1 -0
  159. package/dist/create-aura3d/showcase-spec-replacement-manifest.d.ts +41 -0
  160. package/dist/create-aura3d/showcase-spec-replacement-manifest.d.ts.map +1 -0
  161. package/dist/create-aura3d/showcase-spec-replacement-manifest.js +62 -0
  162. package/dist/create-aura3d/showcase-spec-replacement-manifest.js.map +1 -0
  163. package/dist/create-aura3d/showcase-spec-replacement-values.d.ts +9 -0
  164. package/dist/create-aura3d/showcase-spec-replacement-values.d.ts.map +1 -0
  165. package/dist/create-aura3d/showcase-spec-replacement-values.js +41 -0
  166. package/dist/create-aura3d/showcase-spec-replacement-values.js.map +1 -0
  167. package/dist/create-aura3d/showcase-spec-replacement.d.ts +13 -0
  168. package/dist/create-aura3d/showcase-spec-replacement.d.ts.map +1 -0
  169. package/dist/create-aura3d/showcase-spec-replacement.js +144 -0
  170. package/dist/create-aura3d/showcase-spec-replacement.js.map +1 -0
  171. package/dist/create-aura3d/showcase-spec-types.d.ts +304 -0
  172. package/dist/create-aura3d/showcase-spec-types.d.ts.map +1 -0
  173. package/dist/create-aura3d/showcase-spec-types.js +2 -0
  174. package/dist/create-aura3d/showcase-spec-types.js.map +1 -0
  175. package/dist/engine/agent-api/GameAssetValidation.d.ts +5 -0
  176. package/dist/engine/agent-api/GameAssetValidation.d.ts.map +1 -1
  177. package/dist/engine/agent-api/GameAssetValidation.js +103 -0
  178. package/dist/engine/agent-api/GameAssetValidation.js.map +1 -1
  179. package/dist/engine/agent-api/GameEvidence.d.ts +14 -1
  180. package/dist/engine/agent-api/GameEvidence.d.ts.map +1 -1
  181. package/dist/engine/agent-api/GameEvidence.js +77 -6
  182. package/dist/engine/agent-api/GameEvidence.js.map +1 -1
  183. package/dist/engine/agent-api/GameGenreKits.d.ts +473 -0
  184. package/dist/engine/agent-api/GameGenreKits.d.ts.map +1 -0
  185. package/dist/engine/agent-api/GameGenreKits.js +1269 -0
  186. package/dist/engine/agent-api/GameGenreKits.js.map +1 -0
  187. package/dist/engine/agent-api/GameRuntime.d.ts +190 -3
  188. package/dist/engine/agent-api/GameRuntime.d.ts.map +1 -1
  189. package/dist/engine/agent-api/GameRuntime.js +431 -2
  190. package/dist/engine/agent-api/GameRuntime.js.map +1 -1
  191. package/dist/engine/agent-api/GameSceneGeometryBindings.d.ts +181 -0
  192. package/dist/engine/agent-api/GameSceneGeometryBindings.d.ts.map +1 -0
  193. package/dist/engine/agent-api/GameSceneGeometryBindings.js +488 -0
  194. package/dist/engine/agent-api/GameSceneGeometryBindings.js.map +1 -0
  195. package/dist/engine/agent-api/GameSceneGeometryMath.d.ts +39 -0
  196. package/dist/engine/agent-api/GameSceneGeometryMath.d.ts.map +1 -0
  197. package/dist/engine/agent-api/GameSceneGeometryMath.js +89 -0
  198. package/dist/engine/agent-api/GameSceneGeometryMath.js.map +1 -0
  199. package/dist/engine/agent-api/RuntimeNodeHandle.d.ts +4 -0
  200. package/dist/engine/agent-api/RuntimeNodeHandle.d.ts.map +1 -1
  201. package/dist/engine/agent-api/RuntimeNodeHandle.js +2 -0
  202. package/dist/engine/agent-api/RuntimeNodeHandle.js.map +1 -1
  203. package/dist/engine/agent-api/SceneGroundingUtils.d.ts +86 -0
  204. package/dist/engine/agent-api/SceneGroundingUtils.d.ts.map +1 -1
  205. package/dist/engine/agent-api/SceneGroundingUtils.js +116 -0
  206. package/dist/engine/agent-api/SceneGroundingUtils.js.map +1 -1
  207. package/dist/engine/agent-api/index.d.ts +149 -5
  208. package/dist/engine/agent-api/index.d.ts.map +1 -1
  209. package/dist/engine/agent-api/index.js +1893 -113
  210. package/dist/engine/agent-api/index.js.map +1 -1
  211. package/dist/engine/agent-api/product-viewer-runtime.d.ts.map +1 -1
  212. package/dist/engine/production-runtime/TypedGLBActor.d.ts +14 -2
  213. package/dist/engine/production-runtime/TypedGLBActor.d.ts.map +1 -1
  214. package/dist/engine/production-runtime/TypedGLBActor.js +95 -4
  215. package/dist/engine/production-runtime/TypedGLBActor.js.map +1 -1
  216. package/dist/rendering/ForwardPass.js +7 -1
  217. package/dist/rendering/ForwardPass.js.map +1 -1
  218. package/dist/rendering/MorphTarget.d.ts +1 -0
  219. package/dist/rendering/MorphTarget.d.ts.map +1 -1
  220. package/dist/rendering/MorphTarget.js.map +1 -1
  221. package/dist/rendering/Renderer.js +7 -1
  222. package/dist/rendering/Renderer.js.map +1 -1
  223. package/package.json +22 -22
  224. package/templates/mini-game/README.md +13 -0
  225. package/templates/mini-game/index.html +1 -1
  226. package/templates/mini-game/package.json +1 -1
  227. package/templates/mini-game/src/main.ts +251 -21
  228. package/templates/mini-game/tests/playable.spec.ts +49 -0
  229. package/templates/mini-game/tests/screenshot.spec.ts +37 -32
@@ -0,0 +1,181 @@
1
+ import type { GameAssetBoundPlatformerLevel, GameAssetBoundRacingRoute, GameKitRect, GameKitVec2, GamePlatformerPlayableSurfaceMap, GamePlatformerPlayerState, GameRacingSnapshot, GameRacingTrackTopology } from "./GameGenreKits";
2
+ type Vec3 = readonly [number, number, number];
3
+ type Euler3 = readonly [number, number, number];
4
+ export interface GameScenePresentationCameraSpec {
5
+ readonly mode: "perspective" | "follow";
6
+ readonly position?: Vec3;
7
+ readonly target: Vec3;
8
+ readonly offset?: Vec3;
9
+ readonly targetOffset?: Vec3;
10
+ readonly offsetMode?: "scene" | "target-yaw";
11
+ readonly fov: number;
12
+ readonly targetNode?: string;
13
+ readonly distance?: number;
14
+ readonly smoothing?: number;
15
+ readonly subjectEmphasis?: number;
16
+ }
17
+ export interface GameSceneModelOffset {
18
+ readonly x?: number;
19
+ readonly y?: number;
20
+ readonly z?: number;
21
+ }
22
+ export interface GameSceneTransform {
23
+ readonly scale: number;
24
+ readonly offsetX: number;
25
+ readonly offsetZ: number;
26
+ readonly elevation: number;
27
+ }
28
+ export interface GameSceneModelAnchorFit {
29
+ readonly mode: "single-anchor" | "multi-anchor-yaw-fit" | "multi-anchor-plane-fit";
30
+ readonly anchorCount: number;
31
+ readonly averageError: number | null;
32
+ readonly maxError: number | null;
33
+ readonly rotation: Euler3;
34
+ }
35
+ export interface GameRacingSceneBindingOptions {
36
+ readonly topology: GameRacingTrackTopology;
37
+ readonly route: GameAssetBoundRacingRoute;
38
+ readonly trackAsset: string;
39
+ readonly targetSceneSize?: number;
40
+ readonly trackModelTargetMaxDimension?: number;
41
+ readonly trackModelSceneOffset?: GameSceneModelOffset;
42
+ readonly trackModelPresentationOffset?: GameSceneModelOffset;
43
+ readonly trackY?: number;
44
+ readonly carY?: number;
45
+ readonly ghostY?: number;
46
+ readonly requireOverlayEvidence?: boolean;
47
+ }
48
+ export interface GameRacingScenePose {
49
+ readonly position: Vec3;
50
+ readonly rotation: Euler3;
51
+ readonly heading: number;
52
+ }
53
+ export interface GameRacingSceneBinding {
54
+ readonly kind: "aura-game-racing-scene-binding";
55
+ readonly sceneContractVersion: "1.0";
56
+ readonly topologyAssetHash: string;
57
+ readonly transform: GameSceneTransform;
58
+ readonly trackModel: {
59
+ readonly position: Vec3;
60
+ readonly rotation: Euler3;
61
+ readonly targetMaxDimension: number;
62
+ readonly anchorFit: GameSceneModelAnchorFit;
63
+ };
64
+ readonly checkpointScenePoints: readonly Vec3[];
65
+ readonly evidence: {
66
+ readonly sourceAsset: string;
67
+ readonly routeOverlay: string;
68
+ readonly geometryBinding: "track-topology-to-scene-transform";
69
+ readonly assetHash: string;
70
+ readonly topologySource: string;
71
+ readonly routePointCount: number;
72
+ readonly checkpointCount: number;
73
+ readonly averageRouteTopologyError: number;
74
+ readonly modelSceneOffset: Required<GameSceneModelOffset>;
75
+ readonly modelPresentationOffset: Required<GameSceneModelOffset>;
76
+ readonly modelAlignment: {
77
+ readonly source: string;
78
+ readonly modelPoint: Vec3;
79
+ readonly gamePoint: {
80
+ readonly x: number;
81
+ readonly z: number;
82
+ };
83
+ readonly anchorCount: number;
84
+ readonly averageAnchorError: number | null;
85
+ readonly maxAnchorError: number | null;
86
+ readonly rotation: Euler3;
87
+ };
88
+ readonly notes: string;
89
+ };
90
+ toScenePoint(point: GameKitVec2, y?: number): Vec3;
91
+ toScenePose(snapshot: Pick<GameRacingSnapshot, "position" | "heading">, y?: number): GameRacingScenePose;
92
+ }
93
+ export interface GameRacingPresentationCameraOptions {
94
+ readonly sceneBinding: GameRacingSceneBinding;
95
+ readonly focus: Pick<GameRacingSnapshot, "position" | "heading">;
96
+ readonly mode?: "follow" | "overview";
97
+ readonly targetNode?: string;
98
+ readonly distance?: number;
99
+ readonly height?: number;
100
+ readonly sideOffset?: number;
101
+ readonly lookAhead?: number;
102
+ readonly fov?: number;
103
+ }
104
+ export interface GamePlatformerSceneBindingOptions {
105
+ readonly surfaceMap: GamePlatformerPlayableSurfaceMap;
106
+ readonly level: GameAssetBoundPlatformerLevel;
107
+ readonly worldAsset: string;
108
+ readonly targetSceneWidth?: number;
109
+ readonly worldModelTargetMaxDimension?: number;
110
+ readonly worldModelSceneOffset?: GameSceneModelOffset;
111
+ readonly worldModelPresentationOffset?: GameSceneModelOffset;
112
+ readonly worldY?: number;
113
+ readonly worldZ?: number;
114
+ readonly playerZ?: number;
115
+ readonly playerTargetHeight?: number;
116
+ readonly playerYOffset?: number;
117
+ readonly requireOverlayEvidence?: boolean;
118
+ }
119
+ export interface GamePlatformerSceneBinding {
120
+ readonly kind: "aura-game-platformer-scene-binding";
121
+ readonly sceneContractVersion: "1.0";
122
+ readonly surfaceAssetHash: string;
123
+ readonly transform: GameSceneTransform;
124
+ readonly worldModel: {
125
+ readonly position: Vec3;
126
+ readonly rotation: Euler3;
127
+ readonly targetMaxDimension: number;
128
+ readonly anchorFit: GameSceneModelAnchorFit;
129
+ };
130
+ readonly evidence: {
131
+ readonly sourceAsset: string;
132
+ readonly surfaceOverlay: string;
133
+ readonly geometryBinding: "playable-surface-to-scene-transform";
134
+ readonly assetHash: string;
135
+ readonly surfaceSource: string;
136
+ readonly surfaceCount: number;
137
+ readonly levelSurfaceCount: number;
138
+ readonly characterScaleRatio: number;
139
+ readonly averageSurfaceBindingError: number;
140
+ readonly modelSceneOffset: Required<GameSceneModelOffset>;
141
+ readonly modelPresentationOffset: Required<GameSceneModelOffset>;
142
+ readonly playerTargetHeight: number;
143
+ readonly modelAlignment: {
144
+ readonly source: string;
145
+ readonly modelPoint: Vec3;
146
+ readonly gamePoint: GameKitVec2;
147
+ readonly anchorCount: number;
148
+ readonly averageAnchorError: number | null;
149
+ readonly maxAnchorError: number | null;
150
+ readonly rotation: Euler3;
151
+ };
152
+ readonly notes: string;
153
+ };
154
+ toScenePoint(point: GameKitVec2, yOffset?: number): Vec3;
155
+ toScenePlayer(player: GamePlatformerPlayerState): {
156
+ readonly position: Vec3;
157
+ readonly facing: 1 | -1;
158
+ readonly grounded: boolean;
159
+ };
160
+ surfaceToSceneRect(surface: GameKitRect): {
161
+ readonly center: Vec3;
162
+ readonly size: Vec3;
163
+ };
164
+ contactPointForPlayer(player: GamePlatformerPlayerState): Vec3;
165
+ }
166
+ export interface GamePlatformerPresentationCameraOptions {
167
+ readonly sceneBinding: GamePlatformerSceneBinding;
168
+ readonly player: GamePlatformerPlayerState;
169
+ readonly mode?: "follow" | "establishing";
170
+ readonly targetNode?: string;
171
+ readonly lookAhead?: number;
172
+ readonly distance?: number;
173
+ readonly height?: number;
174
+ readonly fov?: number;
175
+ }
176
+ export declare function createGameRacingSceneBinding(options: GameRacingSceneBindingOptions): GameRacingSceneBinding;
177
+ export declare function createGameRacingPresentationCamera(options: GameRacingPresentationCameraOptions): GameScenePresentationCameraSpec;
178
+ export declare function createGamePlatformerSceneBinding(options: GamePlatformerSceneBindingOptions): GamePlatformerSceneBinding;
179
+ export declare function createGamePlatformerPresentationCamera(options: GamePlatformerPresentationCameraOptions): GameScenePresentationCameraSpec;
180
+ export {};
181
+ //# sourceMappingURL=GameSceneGeometryBindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GameSceneGeometryBindings.d.ts","sourceRoot":"","sources":["../../../../../packages/engine/src/agent-api/GameSceneGeometryBindings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,488 @@
1
+ import { assertOverlayValidatedSource, averageRouteTopologyError, averageSurfaceBindingError, boundsFromLeftEdgeRects, boundsFromPoints, normalizedModelLocalOffset, positiveOrDefault, roundScene, sampleRoutePoint, transformFromBounds } from "./GameSceneGeometryMath.js";
2
+ export function createGameRacingSceneBinding(options) {
3
+ const targetSceneSize = positiveOrDefault(options.targetSceneSize, 3.25);
4
+ const trackModelTargetMaxDimension = positiveOrDefault(options.trackModelTargetMaxDimension, targetSceneSize);
5
+ const trackModelSceneOffset = normalizeSceneOffset(options.trackModelSceneOffset);
6
+ const trackModelPresentationOffset = normalizeSceneOffset(options.trackModelPresentationOffset);
7
+ const trackY = options.trackY ?? -0.12;
8
+ const carY = options.carY ?? 0.28;
9
+ const topology = options.topology;
10
+ assertOverlayValidatedSource(topology.source, "game.racingSceneBinding topology");
11
+ assertNoPresentationOffset("game.racingSceneBinding trackModelPresentationOffset", trackModelPresentationOffset);
12
+ if (topology.assetId !== options.trackAsset) {
13
+ throw new Error(`game.racingSceneBinding topology asset ${topology.assetId} does not match track asset ${options.trackAsset}.`);
14
+ }
15
+ if (options.route.assetBinding.trackAssetHash !== topology.assetHash) {
16
+ throw new Error("game.racingSceneBinding requires route and topology to share the same track asset hash.");
17
+ }
18
+ const overlay = topology.evidence.routeOverlay;
19
+ const requiresOverlayEvidence = (options.requireOverlayEvidence ?? true) && topology.source !== "asset-mesh-extracted";
20
+ if (requiresOverlayEvidence && !overlay) {
21
+ throw new Error("game.racingSceneBinding requires retained route overlay evidence.");
22
+ }
23
+ if (requiresOverlayEvidence && hasSceneOffset(trackModelSceneOffset)) {
24
+ throw new Error("game.racingSceneBinding does not allow trackModelSceneOffset with retained overlay evidence; bind the track model and racing route through the same topology transform.");
25
+ }
26
+ const bounds = boundsFromPoints(topology.roadCenterline.map((point) => ({ x: point.x, y: point.z })));
27
+ const transform = transformFromBounds(bounds, targetSceneSize, trackY);
28
+ const routeError = averageRouteTopologyError(options.route.points, topology.roadCenterline);
29
+ if (routeError > 0.06) {
30
+ throw new Error(`game.racingSceneBinding route points are not bound to topology centerline (${routeError.toFixed(3)} average error).`);
31
+ }
32
+ const toScenePoint = (point, y = carY) => [
33
+ roundScene(point.x * transform.scale + transform.offsetX + trackModelSceneOffset.x),
34
+ roundScene(y + trackModelSceneOffset.y),
35
+ roundScene(point.y * transform.scale + transform.offsetZ + trackModelSceneOffset.z)
36
+ ];
37
+ const trackModelFit = fitRacingModelToTopology({
38
+ anchors: topology.modelAlignment.anchorPairs,
39
+ fallbackAnchor: {
40
+ id: "model-alignment",
41
+ modelPoint: topology.modelAlignment.modelPoint,
42
+ gamePoint: topology.modelAlignment.gamePoint
43
+ },
44
+ modelBounds: topology.modelAlignment.modelBounds,
45
+ targetMaxDimension: trackModelTargetMaxDimension,
46
+ toScenePoint: (anchor) => toScenePoint({ x: anchor.gamePoint.x, y: anchor.gamePoint.z }, trackY)
47
+ });
48
+ assertModelAnchorFitQuality({
49
+ label: "game.racingSceneBinding track model alignment",
50
+ fit: trackModelFit.anchorFit,
51
+ targetMaxDimension: trackModelTargetMaxDimension,
52
+ maxAverageErrorRatio: 0.12,
53
+ maxErrorRatio: 0.28
54
+ });
55
+ const trackModelPosition = addVec3(trackModelFit.position, offsetToVec3(trackModelPresentationOffset));
56
+ return {
57
+ kind: "aura-game-racing-scene-binding",
58
+ sceneContractVersion: "1.0",
59
+ topologyAssetHash: topology.assetHash,
60
+ transform,
61
+ trackModel: {
62
+ position: trackModelPosition,
63
+ rotation: trackModelFit.anchorFit.rotation,
64
+ targetMaxDimension: trackModelTargetMaxDimension,
65
+ anchorFit: trackModelFit.anchorFit
66
+ },
67
+ checkpointScenePoints: options.route.checkpoints?.map((progress) => toScenePoint(sampleRoutePoint(options.route.points, progress), carY)) ?? [],
68
+ evidence: {
69
+ sourceAsset: topology.evidence.sourceAsset,
70
+ routeOverlay: overlay ?? "",
71
+ geometryBinding: "track-topology-to-scene-transform",
72
+ assetHash: topology.assetHash,
73
+ topologySource: topology.source,
74
+ routePointCount: options.route.points.length,
75
+ checkpointCount: options.route.checkpoints?.length ?? 0,
76
+ averageRouteTopologyError: routeError,
77
+ modelSceneOffset: trackModelSceneOffset,
78
+ modelPresentationOffset: trackModelPresentationOffset,
79
+ modelAlignment: {
80
+ source: topology.modelAlignment.source,
81
+ modelPoint: topology.modelAlignment.modelPoint,
82
+ gamePoint: topology.modelAlignment.gamePoint,
83
+ anchorCount: trackModelFit.anchorFit.anchorCount,
84
+ averageAnchorError: trackModelFit.anchorFit.averageError,
85
+ maxAnchorError: trackModelFit.anchorFit.maxError,
86
+ rotation: trackModelFit.anchorFit.rotation
87
+ },
88
+ notes: topology.evidence.notes
89
+ },
90
+ toScenePoint,
91
+ toScenePose(snapshot, y = carY) {
92
+ return {
93
+ position: toScenePoint(snapshot.position, y),
94
+ rotation: [0, roundScene(-snapshot.heading + Math.PI / 2), 0],
95
+ heading: roundScene(snapshot.heading)
96
+ };
97
+ }
98
+ };
99
+ }
100
+ export function createGameRacingPresentationCamera(options) {
101
+ if (options.mode === "overview") {
102
+ const track = options.sceneBinding.trackModel.position;
103
+ const distance = positiveOrDefault(options.distance, 5.9);
104
+ const height = positiveOrDefault(options.height, 3.75);
105
+ const target = [
106
+ roundScene(track[0] + 0.08),
107
+ roundScene(track[1] + 0.18),
108
+ roundScene(track[2] - 0.04)
109
+ ];
110
+ return {
111
+ mode: "perspective",
112
+ position: [
113
+ roundScene(target[0] + 0.18),
114
+ roundScene(target[1] + height),
115
+ roundScene(target[2] + distance)
116
+ ],
117
+ target,
118
+ fov: options.fov ?? 42,
119
+ smoothing: 0.05,
120
+ subjectEmphasis: 0.68
121
+ };
122
+ }
123
+ const pose = options.sceneBinding.toScenePose(options.focus);
124
+ const distance = positiveOrDefault(options.distance, 3.6);
125
+ const height = positiveOrDefault(options.height, 1.85);
126
+ const sideOffset = options.sideOffset ?? 0.2;
127
+ const lookAhead = positiveOrDefault(options.lookAhead, 0.46);
128
+ const forwardX = Math.cos(pose.heading);
129
+ const forwardZ = Math.sin(pose.heading);
130
+ const sideX = -forwardZ;
131
+ const sideZ = forwardX;
132
+ const target = [
133
+ roundScene(pose.position[0] + forwardX * lookAhead),
134
+ roundScene(pose.position[1] + 0.16),
135
+ roundScene(pose.position[2] + forwardZ * lookAhead)
136
+ ];
137
+ if (options.targetNode) {
138
+ return {
139
+ mode: "follow",
140
+ targetNode: options.targetNode,
141
+ offset: [roundScene(sideOffset), roundScene(height), roundScene(-distance)],
142
+ targetOffset: [0, 0.18, 0],
143
+ offsetMode: "target-yaw",
144
+ target: [0, 0.2, 0],
145
+ distance,
146
+ fov: options.fov ?? 44,
147
+ smoothing: 0.06,
148
+ subjectEmphasis: 0.78
149
+ };
150
+ }
151
+ return {
152
+ mode: "perspective",
153
+ position: [
154
+ roundScene(pose.position[0] - forwardX * distance + sideX * sideOffset),
155
+ roundScene(pose.position[1] + height),
156
+ roundScene(pose.position[2] - forwardZ * distance + sideZ * sideOffset)
157
+ ],
158
+ target,
159
+ fov: options.fov ?? 44,
160
+ smoothing: 0.08,
161
+ subjectEmphasis: 0.72
162
+ };
163
+ }
164
+ export function createGamePlatformerSceneBinding(options) {
165
+ const targetSceneWidth = positiveOrDefault(options.targetSceneWidth, 5.2);
166
+ const worldModelTargetMaxDimension = positiveOrDefault(options.worldModelTargetMaxDimension, targetSceneWidth);
167
+ const worldModelSceneOffset = normalizeSceneOffset(options.worldModelSceneOffset);
168
+ const worldModelPresentationOffset = normalizeSceneOffset(options.worldModelPresentationOffset);
169
+ const worldY = options.worldY ?? -0.86;
170
+ const worldZ = options.worldZ ?? -0.35;
171
+ const playerZ = options.playerZ ?? 0.42;
172
+ const playerTargetHeight = positiveOrDefault(options.playerTargetHeight, 0.62);
173
+ const playerYOffset = options.playerYOffset ?? 0.06;
174
+ const surfaceMap = options.surfaceMap;
175
+ assertOverlayValidatedSource(surfaceMap.source, "game.platformerSceneBinding surface map");
176
+ assertNoPresentationOffset("game.platformerSceneBinding worldModelPresentationOffset", worldModelPresentationOffset);
177
+ if (surfaceMap.assetId !== options.worldAsset) {
178
+ throw new Error(`game.platformerSceneBinding surface asset ${surfaceMap.assetId} does not match world asset ${options.worldAsset}.`);
179
+ }
180
+ if (options.level.assetBinding.worldAssetHashes?.[options.worldAsset] !== surfaceMap.assetHash) {
181
+ throw new Error("game.platformerSceneBinding requires level and surface map to share the same world asset hash.");
182
+ }
183
+ const overlay = surfaceMap.evidence.routeOverlay;
184
+ const requiresOverlayEvidence = (options.requireOverlayEvidence ?? true) && surfaceMap.source !== "asset-mesh-extracted";
185
+ if (requiresOverlayEvidence && !overlay) {
186
+ throw new Error("game.platformerSceneBinding requires retained surface overlay evidence.");
187
+ }
188
+ if (requiresOverlayEvidence && hasSceneOffset(worldModelSceneOffset)) {
189
+ throw new Error("game.platformerSceneBinding does not allow worldModelSceneOffset with retained overlay evidence; bind the world model and playable surfaces through the same surface transform.");
190
+ }
191
+ const gameplaySurfaces = options.level.platforms ??
192
+ surfaceMap.surfaces.map((surface) => ({
193
+ id: surface.id,
194
+ x: surface.x - surface.width / 2,
195
+ y: surface.y,
196
+ width: surface.width,
197
+ height: surface.height
198
+ }));
199
+ const bounds = boundsFromLeftEdgeRects(gameplaySurfaces);
200
+ const transform = transformFromBounds(bounds, targetSceneWidth, worldY);
201
+ const bindingError = averageSurfaceBindingError(options.level.platforms ?? [], surfaceMap);
202
+ if (bindingError > 0.06) {
203
+ throw new Error(`game.platformerSceneBinding level platforms are not bound to playable surfaces (${bindingError.toFixed(3)} average error).`);
204
+ }
205
+ const toScenePoint = (point, yOffset = 0) => [
206
+ roundScene(point.x * transform.scale + transform.offsetX + worldModelSceneOffset.x),
207
+ roundScene((point.y + yOffset) * transform.scale + transform.elevation + worldModelSceneOffset.y),
208
+ roundScene(playerZ + worldModelSceneOffset.z)
209
+ ];
210
+ const toScenePlayerPosition = (player) => {
211
+ const contact = toScenePoint({ x: player.x, y: player.y }, 0);
212
+ return [
213
+ contact[0],
214
+ roundScene(contact[1] + playerTargetHeight / 2 + playerYOffset),
215
+ contact[2]
216
+ ];
217
+ };
218
+ const worldModelFit = fitPlatformerModelToSurfaces({
219
+ anchors: surfaceMap.modelAlignment.anchorPairs,
220
+ fallbackAnchor: {
221
+ id: "model-alignment",
222
+ modelPoint: surfaceMap.modelAlignment.modelPoint,
223
+ gamePoint: surfaceMap.modelAlignment.gamePoint
224
+ },
225
+ modelBounds: surfaceMap.modelAlignment.modelBounds,
226
+ targetMaxDimension: worldModelTargetMaxDimension,
227
+ worldZ: worldZ + worldModelSceneOffset.z,
228
+ toScenePoint
229
+ });
230
+ assertModelAnchorFitQuality({
231
+ label: "game.platformerSceneBinding world model alignment",
232
+ fit: worldModelFit.anchorFit,
233
+ targetMaxDimension: worldModelTargetMaxDimension,
234
+ maxAverageErrorRatio: 0.12,
235
+ maxErrorRatio: 0.28
236
+ });
237
+ const worldModelPosition = addVec3(worldModelFit.position, offsetToVec3(worldModelPresentationOffset));
238
+ return {
239
+ kind: "aura-game-platformer-scene-binding",
240
+ sceneContractVersion: "1.0",
241
+ surfaceAssetHash: surfaceMap.assetHash,
242
+ transform,
243
+ worldModel: {
244
+ position: worldModelPosition,
245
+ rotation: worldModelFit.anchorFit.rotation,
246
+ targetMaxDimension: worldModelTargetMaxDimension,
247
+ anchorFit: worldModelFit.anchorFit
248
+ },
249
+ evidence: {
250
+ sourceAsset: surfaceMap.evidence.sourceAsset,
251
+ surfaceOverlay: overlay ?? "",
252
+ geometryBinding: "playable-surface-to-scene-transform",
253
+ assetHash: surfaceMap.assetHash,
254
+ surfaceSource: surfaceMap.source,
255
+ surfaceCount: surfaceMap.surfaces.length,
256
+ levelSurfaceCount: options.level.platforms?.length ?? 0,
257
+ characterScaleRatio: surfaceMap.characterScaleRatio,
258
+ averageSurfaceBindingError: bindingError,
259
+ modelSceneOffset: worldModelSceneOffset,
260
+ modelPresentationOffset: worldModelPresentationOffset,
261
+ playerTargetHeight,
262
+ modelAlignment: {
263
+ source: surfaceMap.modelAlignment.source,
264
+ modelPoint: surfaceMap.modelAlignment.modelPoint,
265
+ gamePoint: surfaceMap.modelAlignment.gamePoint,
266
+ anchorCount: worldModelFit.anchorFit.anchorCount,
267
+ averageAnchorError: worldModelFit.anchorFit.averageError,
268
+ maxAnchorError: worldModelFit.anchorFit.maxError,
269
+ rotation: worldModelFit.anchorFit.rotation
270
+ },
271
+ notes: surfaceMap.evidence.notes
272
+ },
273
+ toScenePoint,
274
+ toScenePlayer(player) {
275
+ return {
276
+ position: toScenePlayerPosition(player),
277
+ facing: player.facing,
278
+ grounded: player.grounded
279
+ };
280
+ },
281
+ surfaceToSceneRect(surface) {
282
+ return {
283
+ center: toScenePoint({ x: surface.x + surface.width / 2, y: surface.y + surface.height / 2 }),
284
+ size: [roundScene(surface.width * transform.scale), roundScene(surface.height * transform.scale), 0.04]
285
+ };
286
+ },
287
+ contactPointForPlayer(player) {
288
+ return toScenePoint({ x: player.x, y: player.y }, 0);
289
+ }
290
+ };
291
+ }
292
+ export function createGamePlatformerPresentationCamera(options) {
293
+ const player = options.sceneBinding.toScenePlayer(options.player);
294
+ if (options.mode === "establishing") {
295
+ const world = options.sceneBinding.worldModel.position;
296
+ const distance = positiveOrDefault(options.distance, 6.2);
297
+ const height = positiveOrDefault(options.height, 1.12);
298
+ const target = [
299
+ roundScene((player.position[0] * 0.38) + (world[0] * 0.62) + 0.22),
300
+ roundScene(Math.max(player.position[1] * 0.52, world[1] + 0.42)),
301
+ roundScene((player.position[2] * 0.34) + (world[2] * 0.66))
302
+ ];
303
+ return {
304
+ mode: "perspective",
305
+ position: [
306
+ roundScene(target[0] + 0.04),
307
+ roundScene(target[1] + height),
308
+ roundScene(target[2] + distance)
309
+ ],
310
+ target,
311
+ fov: options.fov ?? 42,
312
+ smoothing: 0.05,
313
+ subjectEmphasis: 0.72
314
+ };
315
+ }
316
+ const lookAhead = options.lookAhead ?? (player.facing === -1 ? -0.56 : 0.56);
317
+ const distance = positiveOrDefault(options.distance, 5.1);
318
+ const height = positiveOrDefault(options.height, 0.68);
319
+ const target = [
320
+ roundScene(player.position[0] + lookAhead),
321
+ roundScene(player.position[1] + 0.28),
322
+ roundScene(player.position[2] - 0.04)
323
+ ];
324
+ if (options.targetNode) {
325
+ return {
326
+ mode: "follow",
327
+ targetNode: options.targetNode,
328
+ offset: [roundScene(lookAhead * 0.42), roundScene(height), roundScene(distance)],
329
+ targetOffset: [roundScene(lookAhead), 0.34, 0],
330
+ offsetMode: "scene",
331
+ target: [0, 0.42, 0],
332
+ distance,
333
+ fov: options.fov ?? 42,
334
+ smoothing: 0.045,
335
+ subjectEmphasis: 0.74
336
+ };
337
+ }
338
+ return {
339
+ mode: "perspective",
340
+ position: [
341
+ roundScene(target[0]),
342
+ roundScene(target[1] + height),
343
+ roundScene(player.position[2] + distance)
344
+ ],
345
+ target,
346
+ fov: options.fov ?? 42,
347
+ smoothing: 0.06,
348
+ subjectEmphasis: 0.78
349
+ };
350
+ }
351
+ function normalizeSceneOffset(offset) {
352
+ return {
353
+ x: roundScene(offset?.x ?? 0),
354
+ y: roundScene(offset?.y ?? 0),
355
+ z: roundScene(offset?.z ?? 0)
356
+ };
357
+ }
358
+ function offsetToVec3(offset) {
359
+ return [offset.x, offset.y, offset.z];
360
+ }
361
+ function hasSceneOffset(offset) {
362
+ return offset.x !== 0 || offset.y !== 0 || offset.z !== 0;
363
+ }
364
+ function assertNoPresentationOffset(label, offset) {
365
+ if (!hasSceneOffset(offset))
366
+ return;
367
+ throw new Error(`${label} is not allowed for scene-bound game geometry; presentation offsets decouple the visible model from gameplay topology.`);
368
+ }
369
+ function assertModelAnchorFitQuality(options) {
370
+ if (options.fit.anchorCount < 2)
371
+ return;
372
+ const averageError = options.fit.averageError ?? 0;
373
+ const maxError = options.fit.maxError ?? 0;
374
+ const averageLimit = roundScene(options.targetMaxDimension * options.maxAverageErrorRatio);
375
+ const maxLimit = roundScene(options.targetMaxDimension * options.maxErrorRatio);
376
+ if (averageError <= averageLimit && maxError <= maxLimit)
377
+ return;
378
+ throw new Error(`${options.label} asset geometry is not scene-bound to game geometry (average anchor error ${averageError}, max anchor error ${maxError}, limits ${averageLimit}/${maxLimit}).`);
379
+ }
380
+ function fitRacingModelToTopology(options) {
381
+ const anchors = options.anchors && options.anchors.length >= 2 ? options.anchors : [options.fallbackAnchor];
382
+ const localOffsets = anchors.map((anchor) => normalizedModelLocalOffset(options.modelBounds, anchor.modelPoint, options.targetMaxDimension));
383
+ const sceneTargets = anchors.map((anchor) => options.toScenePoint(anchor));
384
+ const rotationY = anchors.length >= 2 ? solveYawFromAnchorPairs(localOffsets, sceneTargets) : 0;
385
+ const rotatedOffsets = localOffsets.map((offset) => rotateXZOffset(offset, rotationY));
386
+ const position = averagePosition(sceneTargets.map((target, index) => subtractVec3(target, rotatedOffsets[index] ?? [0, 0, 0])));
387
+ const errors = sceneTargets.map((target, index) => distance3(target, addVec3(position, rotatedOffsets[index] ?? [0, 0, 0])));
388
+ const fitError = summarizeFitErrors(errors, anchors.length);
389
+ return {
390
+ position,
391
+ anchorFit: {
392
+ mode: anchors.length >= 2 ? "multi-anchor-yaw-fit" : "single-anchor",
393
+ anchorCount: anchors.length,
394
+ averageError: fitError.average,
395
+ maxError: fitError.max,
396
+ rotation: [0, roundScene(rotationY), 0]
397
+ }
398
+ };
399
+ }
400
+ function fitPlatformerModelToSurfaces(options) {
401
+ const anchors = options.anchors && options.anchors.length >= 2 ? options.anchors : [options.fallbackAnchor];
402
+ const localOffsets = anchors.map((anchor) => normalizedModelLocalOffset(options.modelBounds, anchor.modelPoint, options.targetMaxDimension));
403
+ const sceneTargets = anchors.map((anchor) => options.toScenePoint(anchor.gamePoint, 0));
404
+ const x = average(sceneTargets.map((target, index) => target[0] - (localOffsets[index]?.[0] ?? 0)));
405
+ const y = average(sceneTargets.map((target, index) => target[1] - (localOffsets[index]?.[1] ?? 0)));
406
+ const fallbackOffset = localOffsets[0] ?? [0, 0, 0];
407
+ const position = [
408
+ roundScene(x),
409
+ roundScene(y),
410
+ roundScene(options.worldZ - fallbackOffset[2])
411
+ ];
412
+ const errors = sceneTargets.map((target, index) => {
413
+ const localOffset = localOffsets[index] ?? [0, 0, 0];
414
+ return Math.hypot(target[0] - (position[0] + localOffset[0]), target[1] - (position[1] + localOffset[1]));
415
+ });
416
+ const fitError = summarizeFitErrors(errors, anchors.length);
417
+ return {
418
+ position,
419
+ anchorFit: {
420
+ mode: anchors.length >= 2 ? "multi-anchor-plane-fit" : "single-anchor",
421
+ anchorCount: anchors.length,
422
+ averageError: fitError.average,
423
+ maxError: fitError.max,
424
+ rotation: [0, 0, 0]
425
+ }
426
+ };
427
+ }
428
+ function solveYawFromAnchorPairs(localOffsets, sceneTargets) {
429
+ let bestA = 0;
430
+ let bestB = 1;
431
+ let bestDistance = 0;
432
+ for (let a = 0; a < localOffsets.length; a += 1) {
433
+ for (let b = a + 1; b < localOffsets.length; b += 1) {
434
+ const routeDistance = Math.hypot(sceneTargets[b][0] - sceneTargets[a][0], sceneTargets[b][2] - sceneTargets[a][2]);
435
+ const modelDistance = Math.hypot(localOffsets[b][0] - localOffsets[a][0], localOffsets[b][2] - localOffsets[a][2]);
436
+ const distance = Math.min(routeDistance, modelDistance);
437
+ if (distance > bestDistance) {
438
+ bestA = a;
439
+ bestB = b;
440
+ bestDistance = distance;
441
+ }
442
+ }
443
+ }
444
+ if (bestDistance <= 0.001)
445
+ return 0;
446
+ const routeAngle = Math.atan2(sceneTargets[bestB][2] - sceneTargets[bestA][2], sceneTargets[bestB][0] - sceneTargets[bestA][0]);
447
+ const modelAngle = Math.atan2(localOffsets[bestB][2] - localOffsets[bestA][2], localOffsets[bestB][0] - localOffsets[bestA][0]);
448
+ return routeAngle - modelAngle;
449
+ }
450
+ function rotateXZOffset(offset, yaw) {
451
+ const cos = Math.cos(yaw);
452
+ const sin = Math.sin(yaw);
453
+ return [
454
+ roundScene(offset[0] * cos - offset[2] * sin),
455
+ offset[1],
456
+ roundScene(offset[0] * sin + offset[2] * cos)
457
+ ];
458
+ }
459
+ function addVec3(a, b) {
460
+ return [roundScene(a[0] + b[0]), roundScene(a[1] + b[1]), roundScene(a[2] + b[2])];
461
+ }
462
+ function subtractVec3(a, b) {
463
+ return [roundScene(a[0] - b[0]), roundScene(a[1] - b[1]), roundScene(a[2] - b[2])];
464
+ }
465
+ function averagePosition(points) {
466
+ return [
467
+ roundScene(average(points.map((point) => point[0]))),
468
+ roundScene(average(points.map((point) => point[1]))),
469
+ roundScene(average(points.map((point) => point[2])))
470
+ ];
471
+ }
472
+ function average(values) {
473
+ if (values.length === 0)
474
+ return 0;
475
+ return values.reduce((sum, value) => sum + value, 0) / values.length;
476
+ }
477
+ function distance3(a, b) {
478
+ return Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]);
479
+ }
480
+ function summarizeFitErrors(errors, anchorCount) {
481
+ if (anchorCount < 2 || errors.length < 2)
482
+ return { average: null, max: null };
483
+ return {
484
+ average: roundScene(average(errors)),
485
+ max: roundScene(Math.max(...errors))
486
+ };
487
+ }
488
+ //# sourceMappingURL=GameSceneGeometryBindings.js.map