@aura3d/engine 1.5.2 → 2.0.1

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 (1262) hide show
  1. package/README.md +163 -119
  2. package/dist/animation/FootIk.d.ts +10 -1
  3. package/dist/animation/FootIk.d.ts.map +1 -1
  4. package/dist/animation/FootIk.js.map +1 -1
  5. package/dist/animation/HumanoidRetargeting.js +1 -1
  6. package/dist/animation/RigQuality.d.ts +1 -1
  7. package/dist/animation/RigQuality.js +2 -2
  8. package/dist/animation/RigQuality.js.map +1 -1
  9. package/dist/animation/SpringBones.d.ts.map +1 -1
  10. package/dist/animation/SpringBones.js +1 -2
  11. package/dist/animation/SpringBones.js.map +1 -1
  12. package/dist/animation/browser-index.d.ts +0 -2
  13. package/dist/animation/browser-index.d.ts.map +1 -1
  14. package/dist/animation/browser-index.js +0 -2
  15. package/dist/animation/browser-index.js.map +1 -1
  16. package/dist/animation/index.d.ts +0 -2
  17. package/dist/animation/index.d.ts.map +1 -1
  18. package/dist/animation/index.js +0 -2
  19. package/dist/animation/index.js.map +1 -1
  20. package/dist/animation/threejs-compatibility/AnimationAction.d.ts +1 -1
  21. package/dist/animation/threejs-compatibility/AnimationDiagnostics.d.ts +3 -3
  22. package/dist/animation/threejs-compatibility/AnimationMixer.d.ts +2 -2
  23. package/dist/animation/threejs-compatibility/SkinnedMesh.d.ts +1 -1
  24. package/dist/animation/threejs-compatibility/index.d.ts +11 -11
  25. package/dist/apps/index.d.ts +3 -3
  26. package/dist/assets/AssetCache.d.ts +1 -1
  27. package/dist/assets/AssetCompatibility.d.ts +2 -2
  28. package/dist/assets/AssetInspection.d.ts +4 -4
  29. package/dist/assets/AssetLoader.d.ts +1 -1
  30. package/dist/assets/AssetManager.d.ts +5 -5
  31. package/dist/assets/AssetRegistry.d.ts +1 -1
  32. package/dist/assets/AssetRenderDefaults.d.ts +1 -1
  33. package/dist/assets/AudioLoader.d.ts +2 -2
  34. package/dist/assets/CarConceptMaterialStability.d.ts +2 -2
  35. package/dist/assets/GLTFAnimationRuntime.d.ts +7 -3
  36. package/dist/assets/GLTFAnimationRuntime.d.ts.map +1 -1
  37. package/dist/assets/GLTFAnimationRuntime.js +29 -6
  38. package/dist/assets/GLTFAnimationRuntime.js.map +1 -1
  39. package/dist/assets/GLTFAutoFit.d.ts +1 -1
  40. package/dist/assets/GLTFCompressionDecoders.d.ts +1 -1
  41. package/dist/assets/GLTFLoader.d.ts +5 -5
  42. package/dist/assets/GLTFLoader.d.ts.map +1 -1
  43. package/dist/assets/GLTFLoader.js +13 -4
  44. package/dist/assets/GLTFLoader.js.map +1 -1
  45. package/dist/assets/GLTFRenderResources.d.ts +3 -3
  46. package/dist/assets/HDRLoader.d.ts +1 -1
  47. package/dist/assets/ImageLoader.d.ts +2 -2
  48. package/dist/assets/KTX2BasisTextureTranscoder.d.ts +1 -1
  49. package/dist/assets/LoadContext.d.ts +2 -2
  50. package/dist/assets/MaterialLoader.d.ts +3 -3
  51. package/dist/assets/MeshOptimization.d.ts +1 -1
  52. package/dist/assets/OBJLoader.d.ts +3 -3
  53. package/dist/assets/SceneLoader.d.ts +4 -4
  54. package/dist/assets/ShaderLoader.d.ts +2 -2
  55. package/dist/assets/TextureLoader.d.ts +3 -3
  56. package/dist/assets/TexturePipeline.d.ts +1 -1
  57. package/dist/assets/WorkerAssetJobs.d.ts +1 -1
  58. package/dist/assets/advanced-gallery/index.d.ts +2 -2
  59. package/dist/assets/asset-corpus/GLTFSceneLoader.d.ts +2 -2
  60. package/dist/assets/asset-corpus/ProductionAssetPipeline.d.ts +2 -2
  61. package/dist/assets/asset-corpus/ProductionGLTFRenderPipeline.d.ts +3 -3
  62. package/dist/assets/asset-corpus/index.d.ts +9 -9
  63. package/dist/assets/browser-index.d.ts +45 -49
  64. package/dist/assets/browser-index.d.ts.map +1 -1
  65. package/dist/assets/browser-index.js +0 -2
  66. package/dist/assets/browser-index.js.map +1 -1
  67. package/dist/assets/createRenderableScene.d.ts +4 -4
  68. package/dist/assets/gltf-runtime.d.ts +6 -0
  69. package/dist/assets/gltf-runtime.d.ts.map +1 -0
  70. package/dist/assets/gltf-runtime.js +4 -0
  71. package/dist/assets/gltf-runtime.js.map +1 -0
  72. package/dist/assets/index.d.ts +76 -80
  73. package/dist/assets/index.d.ts.map +1 -1
  74. package/dist/assets/index.js +0 -2
  75. package/dist/assets/index.js.map +1 -1
  76. package/dist/assets/loadRenderableAsset.d.ts +3 -3
  77. package/dist/assets/loaders/CubeTextureLoader.d.ts +1 -1
  78. package/dist/assets/loaders/HDRLoader.d.ts +1 -1
  79. package/dist/assets/loaders/KTX2Loader.d.ts +1 -1
  80. package/dist/assets/loaders/MTLLoader.d.ts +1 -1
  81. package/dist/assets/loaders/OBJLoader.d.ts +1 -1
  82. package/dist/assets/loaders/TextureLoader.d.ts +1 -1
  83. package/dist/assets/loaders/ThreeCompatGLTFLoader.d.ts +1 -1
  84. package/dist/assets/loaders/index.d.ts +13 -13
  85. package/dist/assets/threejs-compatibility/ThreeCompatAssetRegistry.d.ts +1 -1
  86. package/dist/assets/threejs-example-parity/index.d.ts +1 -1
  87. package/dist/audio/AudioBus.d.ts +20 -2
  88. package/dist/audio/AudioBus.d.ts.map +1 -1
  89. package/dist/audio/AudioBus.js.map +1 -1
  90. package/dist/audio/AudioFileManager.d.ts +7 -2
  91. package/dist/audio/AudioFileManager.d.ts.map +1 -1
  92. package/dist/audio/AudioFileManager.js +13 -0
  93. package/dist/audio/AudioFileManager.js.map +1 -1
  94. package/dist/audio/AudioMixer.d.ts +2 -2
  95. package/dist/audio/AudioSource.d.ts +10 -2
  96. package/dist/audio/AudioSource.d.ts.map +1 -1
  97. package/dist/audio/AudioSource.js +56 -7
  98. package/dist/audio/AudioSource.js.map +1 -1
  99. package/dist/audio/AudioSystem.d.ts +2 -2
  100. package/dist/audio/AudioTimelineTrack.d.ts +2 -2
  101. package/dist/audio/AudioWaveform.d.ts +1 -1
  102. package/dist/audio/SceneAudioBridge.d.ts +3 -3
  103. package/dist/audio/SpatialAudio.d.ts +2 -2
  104. package/dist/audio/effects/Filter.d.ts +2 -2
  105. package/dist/audio/effects/Reverb.d.ts +2 -2
  106. package/dist/audio/index.d.ts +25 -31
  107. package/dist/audio/index.d.ts.map +1 -1
  108. package/dist/audio/index.js +0 -3
  109. package/dist/audio/index.js.map +1 -1
  110. package/dist/aura3d-cli/animation-asset-profiles.d.ts +1 -1
  111. package/dist/aura3d-cli/asset-core-types.d.ts +1 -1
  112. package/dist/aura3d-cli/asset-core-types.d.ts.map +1 -1
  113. package/dist/aura3d-cli/asset-manifest.d.ts.map +1 -1
  114. package/dist/aura3d-cli/asset-manifest.js +36 -2
  115. package/dist/aura3d-cli/asset-manifest.js.map +1 -1
  116. package/dist/aura3d-cli/asset-role-admission.js +1 -1
  117. package/dist/aura3d-cli/asset-role-admission.js.map +1 -1
  118. package/dist/aura3d-cli/cli-help.js +3 -3
  119. package/dist/aura3d-cli/cli-help.js.map +1 -1
  120. package/dist/aura3d-cli/cli-options.d.ts +1 -1
  121. package/dist/aura3d-cli/cli-options.d.ts.map +1 -1
  122. package/dist/aura3d-cli/cli-options.js +2 -2
  123. package/dist/aura3d-cli/cli-options.js.map +1 -1
  124. package/dist/aura3d-cli/cli.js +1 -1
  125. package/dist/aura3d-cli/cli.js.map +1 -1
  126. package/dist/aura3d-cli/game-asset-profiles.d.ts +1 -1
  127. package/dist/aura3d-cli/game-asset-validator.d.ts +2 -2
  128. package/dist/aura3d-cli/index.d.ts.map +1 -1
  129. package/dist/aura3d-cli/index.js +13 -5
  130. package/dist/aura3d-cli/index.js.map +1 -1
  131. package/dist/aura3d-cli/pull-bridge/adapters.d.ts +1 -1
  132. package/dist/aura3d-cli/pull-bridge/profiles.d.ts +1 -1
  133. package/dist/aura3d-cli/pull-bridge/provenance.d.ts +1 -1
  134. package/dist/aura3d-cli/pull-bridge/pullable.d.ts +1 -1
  135. package/dist/aura3d-cli/pull-bridge/scoring.d.ts +1 -1
  136. package/dist/aura3d-cli/pull-bridge/search.d.ts +1 -1
  137. package/dist/aura3d-cli/pull-bridge/types.d.ts +1 -1
  138. package/dist/aura3d-cli/pull-bridge.d.ts +1 -1
  139. package/dist/controls/ControlState.d.ts +1 -1
  140. package/dist/controls/DragControls.d.ts +2 -2
  141. package/dist/controls/FirstPersonControls.d.ts +2 -2
  142. package/dist/controls/FlyControls.d.ts +3 -3
  143. package/dist/controls/InteractionControls.d.ts +5 -5
  144. package/dist/controls/MapControls.d.ts +3 -3
  145. package/dist/controls/OrbitControls.d.ts +3 -3
  146. package/dist/controls/Picking.d.ts +1 -1
  147. package/dist/controls/PickingAnnotations.d.ts +2 -2
  148. package/dist/controls/PointerLockControls.d.ts +3 -3
  149. package/dist/controls/SelectionManager.d.ts +1 -1
  150. package/dist/controls/TrackballControls.d.ts +1 -1
  151. package/dist/controls/TransformControls.d.ts +1 -1
  152. package/dist/controls/index.d.ts +25 -25
  153. package/dist/create-aura3d/index.d.ts.map +1 -1
  154. package/dist/create-aura3d/index.js +10 -4
  155. package/dist/create-aura3d/index.js.map +1 -1
  156. package/dist/create-aura3d/showcase-spec-evidence.js +5 -1
  157. package/dist/create-aura3d/showcase-spec-evidence.js.map +1 -1
  158. package/dist/create-aura3d/showcase-spec-game-geometry-extractor.d.ts +8 -1
  159. package/dist/create-aura3d/showcase-spec-game-geometry-extractor.d.ts.map +1 -1
  160. package/dist/create-aura3d/showcase-spec-game-geometry-extractor.js +191 -31
  161. package/dist/create-aura3d/showcase-spec-game-geometry-extractor.js.map +1 -1
  162. package/dist/create-aura3d/showcase-spec-game-template-evidence.d.ts.map +1 -1
  163. package/dist/create-aura3d/showcase-spec-game-template-evidence.js +7 -0
  164. package/dist/create-aura3d/showcase-spec-game-template-evidence.js.map +1 -1
  165. package/dist/create-aura3d/showcase-spec-parser.js +1 -1
  166. package/dist/create-aura3d/showcase-spec-parser.js.map +1 -1
  167. package/dist/create-aura3d/showcase-spec-types.d.ts +50 -0
  168. package/dist/create-aura3d/showcase-spec-types.d.ts.map +1 -1
  169. package/dist/debug/AnimationInspector.d.ts +1 -1
  170. package/dist/debug/DrawCallTracker.d.ts +1 -1
  171. package/dist/debug/MaterialDiagnostics.d.ts +1 -1
  172. package/dist/debug/PhysicsDebugAdapter.d.ts +1 -1
  173. package/dist/debug/ShaderDiagnostics.d.ts +1 -1
  174. package/dist/ecs/components/TransformComponent.d.ts +1 -1
  175. package/dist/editor/index.d.ts +1 -1
  176. package/dist/editor-runtime/AnimationSceneEditor.d.ts +5 -5
  177. package/dist/editor-runtime/AssetDropZone.d.ts +2 -2
  178. package/dist/editor-runtime/CameraPathEditor.d.ts +3 -3
  179. package/dist/editor-runtime/CommandHistory.d.ts +1 -1
  180. package/dist/editor-runtime/CurveEditor.d.ts +3 -3
  181. package/dist/editor-runtime/EditorRuntime.d.ts +14 -14
  182. package/dist/editor-runtime/EditorStateModel.d.ts +1 -1
  183. package/dist/editor-runtime/EventTrackEditor.d.ts +1 -1
  184. package/dist/editor-runtime/Gizmo.d.ts +3 -3
  185. package/dist/editor-runtime/HierarchyModel.d.ts +1 -1
  186. package/dist/editor-runtime/InspectorModel.d.ts +1 -1
  187. package/dist/editor-runtime/InteractiveTransformGizmo.d.ts +2 -2
  188. package/dist/editor-runtime/KeyframeEditor.d.ts +2 -2
  189. package/dist/editor-runtime/NonlinearAnimationEditor.d.ts +3 -3
  190. package/dist/editor-runtime/PickingService.d.ts +2 -2
  191. package/dist/editor-runtime/ProjectSerializer.d.ts +2 -2
  192. package/dist/editor-runtime/PropertyPanel.d.ts +2 -2
  193. package/dist/editor-runtime/RotateGizmo.d.ts +1 -1
  194. package/dist/editor-runtime/ScaleGizmo.d.ts +1 -1
  195. package/dist/editor-runtime/SceneOutliner.d.ts +3 -3
  196. package/dist/editor-runtime/TimelineEditorController.d.ts +4 -4
  197. package/dist/editor-runtime/TimelineRuntimeBridge.d.ts +2 -2
  198. package/dist/editor-runtime/TimelineTrackTypes.d.ts +1 -1
  199. package/dist/editor-runtime/TimelineUI.d.ts +1 -1
  200. package/dist/editor-runtime/TranslateGizmo.d.ts +1 -1
  201. package/dist/editor-runtime/VisualReviewDashboard.d.ts +1 -1
  202. package/dist/editor-runtime/commands/CreateNodeCommand.d.ts +1 -1
  203. package/dist/editor-runtime/commands/DeleteNodeCommand.d.ts +2 -2
  204. package/dist/editor-runtime/commands/ReparentNodeCommand.d.ts +1 -1
  205. package/dist/editor-runtime/commands/SetPropertyCommand.d.ts +1 -1
  206. package/dist/editor-runtime/commands/TransformCommand.d.ts +1 -1
  207. package/dist/editor-runtime/index.d.ts +79 -81
  208. package/dist/editor-runtime/index.d.ts.map +1 -1
  209. package/dist/editor-runtime/index.js +0 -1
  210. package/dist/editor-runtime/index.js.map +1 -1
  211. package/dist/engine/A3DApp.d.ts +2 -2
  212. package/dist/engine/A3DQualityPresets.d.ts +2 -2
  213. package/dist/engine/advanced-runtime/A3DRenderer.d.ts +2 -2
  214. package/dist/engine/advanced-runtime/A3DScene.d.ts +2 -2
  215. package/dist/engine/advanced-runtime/index.d.ts +4 -4
  216. package/dist/engine/agent-api/AnimationController.d.ts +3 -3
  217. package/dist/engine/agent-api/AuraAppHandle.d.ts +2 -2
  218. package/dist/engine/agent-api/GameAppRuntime.d.ts +4 -4
  219. package/dist/engine/agent-api/GameAssetValidation.js +1 -1
  220. package/dist/engine/agent-api/GameAssetValidation.js.map +1 -1
  221. package/dist/engine/agent-api/GameEvidence.d.ts +1 -1
  222. package/dist/engine/agent-api/GameEvidence.js +1 -1
  223. package/dist/engine/agent-api/GameEvidence.js.map +1 -1
  224. package/dist/engine/agent-api/GameGenreKits.d.ts +73 -0
  225. package/dist/engine/agent-api/GameGenreKits.d.ts.map +1 -1
  226. package/dist/engine/agent-api/GameGenreKits.js +298 -56
  227. package/dist/engine/agent-api/GameGenreKits.js.map +1 -1
  228. package/dist/engine/agent-api/GameRuntime.d.ts +49 -1
  229. package/dist/engine/agent-api/GameRuntime.d.ts.map +1 -1
  230. package/dist/engine/agent-api/GameRuntime.js +87 -1
  231. package/dist/engine/agent-api/GameRuntime.js.map +1 -1
  232. package/dist/engine/agent-api/GameSceneBridge.d.ts +1 -1
  233. package/dist/engine/agent-api/GameSceneGeometryBindings.d.ts +25 -1
  234. package/dist/engine/agent-api/GameSceneGeometryBindings.d.ts.map +1 -1
  235. package/dist/engine/agent-api/GameSceneGeometryBindings.js +52 -0
  236. package/dist/engine/agent-api/GameSceneGeometryBindings.js.map +1 -1
  237. package/dist/engine/agent-api/GameSceneGeometryMath.d.ts +1 -1
  238. package/dist/engine/agent-api/PhysicsRuntime.d.ts +332 -0
  239. package/dist/engine/agent-api/PhysicsRuntime.d.ts.map +1 -0
  240. package/dist/engine/agent-api/PhysicsRuntime.js +619 -0
  241. package/dist/engine/agent-api/PhysicsRuntime.js.map +1 -0
  242. package/dist/engine/agent-api/PlatformerMotion.d.ts +124 -0
  243. package/dist/engine/agent-api/PlatformerMotion.d.ts.map +1 -1
  244. package/dist/engine/agent-api/PlatformerMotion.js +101 -16
  245. package/dist/engine/agent-api/PlatformerMotion.js.map +1 -1
  246. package/dist/engine/agent-api/RootGeometry.d.ts +36 -0
  247. package/dist/engine/agent-api/RootGeometry.d.ts.map +1 -0
  248. package/dist/engine/agent-api/RootGeometry.js +152 -0
  249. package/dist/engine/agent-api/RootGeometry.js.map +1 -0
  250. package/dist/engine/agent-api/RuntimeNodeHandle.d.ts +1 -1
  251. package/dist/engine/agent-api/VehicleChassis.d.ts +52 -0
  252. package/dist/engine/agent-api/VehicleChassis.d.ts.map +1 -1
  253. package/dist/engine/agent-api/VehicleChassis.js +182 -8
  254. package/dist/engine/agent-api/VehicleChassis.js.map +1 -1
  255. package/dist/engine/agent-api/WorldLabelRenderer.d.ts +65 -1
  256. package/dist/engine/agent-api/WorldLabelRenderer.d.ts.map +1 -1
  257. package/dist/engine/agent-api/WorldLabelRenderer.js +48 -5
  258. package/dist/engine/agent-api/WorldLabelRenderer.js.map +1 -1
  259. package/dist/engine/agent-api/game-kits/fighting.d.ts +2 -2
  260. package/dist/engine/agent-api/game-kits/index.d.ts +10 -10
  261. package/dist/engine/agent-api/humanoid-walk-runtime.d.ts +1 -1
  262. package/dist/engine/agent-api/index.d.ts +288 -85
  263. package/dist/engine/agent-api/index.d.ts.map +1 -1
  264. package/dist/engine/agent-api/index.js +1404 -359
  265. package/dist/engine/agent-api/index.js.map +1 -1
  266. package/dist/engine/agent-api/lean-game.d.ts +3 -0
  267. package/dist/engine/agent-api/lean-game.d.ts.map +1 -0
  268. package/dist/engine/agent-api/lean-game.js +3 -0
  269. package/dist/engine/agent-api/lean-game.js.map +1 -0
  270. package/dist/engine/agent-api/lean-product.d.ts +3 -0
  271. package/dist/engine/agent-api/lean-product.d.ts.map +1 -0
  272. package/dist/engine/agent-api/lean-product.js +3 -0
  273. package/dist/engine/agent-api/lean-product.js.map +1 -0
  274. package/dist/engine/agent-api/lean.d.ts +3 -0
  275. package/dist/engine/agent-api/lean.d.ts.map +1 -0
  276. package/dist/engine/agent-api/lean.js +3 -0
  277. package/dist/engine/agent-api/lean.js.map +1 -0
  278. package/dist/engine/agent-api/media-node.d.ts +42 -0
  279. package/dist/engine/agent-api/media-node.d.ts.map +1 -0
  280. package/dist/engine/agent-api/media-node.js +44 -0
  281. package/dist/engine/agent-api/media-node.js.map +1 -0
  282. package/dist/engine/agent-api/product-viewer-runtime.d.ts.map +1 -1
  283. package/dist/engine/animation-studio/animation-episode-validator.d.ts +1 -1
  284. package/dist/engine/animation-studio/director-heuristics.d.ts +1 -1
  285. package/dist/engine/animation-studio/episode-document.d.ts +1 -1
  286. package/dist/engine/animation-studio/index.d.ts +4 -4
  287. package/dist/engine/animation-studio/scene-tools.d.ts +2 -2
  288. package/dist/engine/ecs/ECSRenderSource.d.ts +2 -2
  289. package/dist/engine/game/GameAudio.d.ts +5 -0
  290. package/dist/engine/game/GameAudio.d.ts.map +1 -1
  291. package/dist/engine/game/GameAudio.js +65 -23
  292. package/dist/engine/game/GameAudio.js.map +1 -1
  293. package/dist/engine/index.d.ts +14 -14
  294. package/dist/engine/production-runtime/GameRenderPreset.d.ts +1 -1
  295. package/dist/engine/production-runtime/TypedGLBActor.d.ts +11 -3
  296. package/dist/engine/production-runtime/TypedGLBActor.d.ts.map +1 -1
  297. package/dist/engine/production-runtime/TypedGLBActor.js +25 -7
  298. package/dist/engine/production-runtime/TypedGLBActor.js.map +1 -1
  299. package/dist/engine/production-runtime/index.d.ts +10 -10
  300. package/dist/engine/production-runtime/index.d.ts.map +1 -1
  301. package/dist/engine/threejs-example-parity/FlagshipFoundation.d.ts +3 -3
  302. package/dist/engine/threejs-example-parity/FlagshipFoundation.d.ts.map +1 -1
  303. package/dist/engine/threejs-example-parity/index.d.ts +1 -1
  304. package/dist/environments/EnvironmentPreview.d.ts +1 -1
  305. package/dist/environments/EnvironmentRegistry.d.ts +3 -3
  306. package/dist/environments/HDRIEnvironment.d.ts +1 -1
  307. package/dist/environments/index.d.ts +5 -10
  308. package/dist/environments/index.d.ts.map +1 -1
  309. package/dist/environments/index.js +0 -3
  310. package/dist/environments/index.js.map +1 -1
  311. package/dist/environments/node.d.ts +7 -0
  312. package/dist/environments/node.d.ts.map +1 -0
  313. package/dist/environments/node.js +5 -0
  314. package/dist/environments/node.js.map +1 -0
  315. package/dist/environments/production-runtime/index.d.ts +2 -2
  316. package/dist/index.d.ts +3 -0
  317. package/dist/index.js +3 -0
  318. package/dist/input/ActionMap.d.ts +1 -1
  319. package/dist/input/GamepadDevice.d.ts +1 -1
  320. package/dist/input/GamepadInput.d.ts +2 -2
  321. package/dist/input/GestureControls.d.ts +2 -2
  322. package/dist/input/GestureRecognizer.d.ts +1 -1
  323. package/dist/input/InputSystem.d.ts +5 -5
  324. package/dist/input/InputValueProcessors.d.ts +19 -0
  325. package/dist/input/InputValueProcessors.d.ts.map +1 -0
  326. package/dist/input/InputValueProcessors.js +24 -0
  327. package/dist/input/InputValueProcessors.js.map +1 -0
  328. package/dist/input/InteractionSystem.d.ts +3 -3
  329. package/dist/input/PickingRay.d.ts +2 -2
  330. package/dist/input/PointerDevice.d.ts +1 -1
  331. package/dist/input/controls/CameraRig.d.ts +1 -1
  332. package/dist/input/controls/EditorFlyControls.d.ts +2 -2
  333. package/dist/input/controls/FirstPersonControls.d.ts +2 -2
  334. package/dist/input/controls/OrbitControls.d.ts +2 -2
  335. package/dist/input/controls/PointerLockControls.d.ts +3 -3
  336. package/dist/input/controls/SceneCameraAdapter.d.ts +2 -2
  337. package/dist/input/controls/ThirdPersonFollowControls.d.ts +1 -1
  338. package/dist/input/index.d.ts +39 -43
  339. package/dist/input/index.d.ts.map +1 -1
  340. package/dist/input/index.js +1 -3
  341. package/dist/input/index.js.map +1 -1
  342. package/dist/lean/ArcadeRuntime.d.ts +111 -0
  343. package/dist/lean/ArcadeRuntime.d.ts.map +1 -0
  344. package/dist/lean/ArcadeRuntime.js +219 -0
  345. package/dist/lean/ArcadeRuntime.js.map +1 -0
  346. package/dist/lean/base.d.ts +228 -0
  347. package/dist/lean/base.d.ts.map +1 -0
  348. package/dist/lean/base.js +322 -0
  349. package/dist/lean/base.js.map +1 -0
  350. package/dist/lean/game.d.ts +19 -0
  351. package/dist/lean/game.d.ts.map +1 -0
  352. package/dist/lean/game.js +37 -0
  353. package/dist/lean/game.js.map +1 -0
  354. package/dist/lean/index.d.ts +4 -0
  355. package/dist/lean/index.d.ts.map +1 -0
  356. package/dist/lean/index.js +10 -0
  357. package/dist/lean/index.js.map +1 -0
  358. package/dist/lean/product.d.ts +4 -0
  359. package/dist/lean/product.d.ts.map +1 -0
  360. package/dist/lean/product.js +55 -0
  361. package/dist/lean/product.js.map +1 -0
  362. package/dist/materials/MaterialPresets.d.ts +2 -2
  363. package/dist/materials/MaterialPreviewScene.d.ts +1 -1
  364. package/dist/materials/PBRMaterialLibrary.d.ts +1 -1
  365. package/dist/materials/browser-index.d.ts +6 -6
  366. package/dist/materials/index.d.ts +1 -10
  367. package/dist/materials/index.d.ts.map +1 -1
  368. package/dist/materials/index.js +1 -6
  369. package/dist/materials/index.js.map +1 -1
  370. package/dist/materials/node.d.ts +4 -0
  371. package/dist/materials/node.d.ts.map +1 -0
  372. package/dist/materials/node.js +3 -0
  373. package/dist/materials/node.js.map +1 -0
  374. package/dist/physics/ArcadeCharacterController.d.ts +53 -0
  375. package/dist/physics/ArcadeCharacterController.d.ts.map +1 -0
  376. package/dist/physics/ArcadeCharacterController.js +98 -0
  377. package/dist/physics/ArcadeCharacterController.js.map +1 -0
  378. package/dist/physics/{VehicleDynamics.d.ts → ArcadeVehicleTelemetry.d.ts} +14 -4
  379. package/dist/physics/ArcadeVehicleTelemetry.d.ts.map +1 -0
  380. package/dist/physics/{VehicleDynamics.js → ArcadeVehicleTelemetry.js} +37 -9
  381. package/dist/physics/ArcadeVehicleTelemetry.js.map +1 -0
  382. package/dist/physics/Constraint.d.ts +20 -4
  383. package/dist/physics/Constraint.d.ts.map +1 -1
  384. package/dist/physics/Constraint.js +34 -60
  385. package/dist/physics/Constraint.js.map +1 -1
  386. package/dist/physics/FightingCharacterController.d.ts +32 -0
  387. package/dist/physics/FightingCharacterController.d.ts.map +1 -0
  388. package/dist/physics/FightingCharacterController.js +76 -0
  389. package/dist/physics/FightingCharacterController.js.map +1 -0
  390. package/dist/physics/MeshBVH.d.ts +72 -0
  391. package/dist/physics/MeshBVH.d.ts.map +1 -0
  392. package/dist/physics/MeshBVH.js +244 -0
  393. package/dist/physics/MeshBVH.js.map +1 -0
  394. package/dist/physics/PhysicsDebugDraw.d.ts +40 -1
  395. package/dist/physics/PhysicsDebugDraw.d.ts.map +1 -1
  396. package/dist/physics/PhysicsDebugDraw.js +87 -17
  397. package/dist/physics/PhysicsDebugDraw.js.map +1 -1
  398. package/dist/physics/PhysicsWorld.d.ts +37 -18
  399. package/dist/physics/PhysicsWorld.d.ts.map +1 -1
  400. package/dist/physics/PhysicsWorld.js +231 -630
  401. package/dist/physics/PhysicsWorld.js.map +1 -1
  402. package/dist/physics/Raycast.d.ts +11 -0
  403. package/dist/physics/Raycast.d.ts.map +1 -1
  404. package/dist/physics/Raycast.js +62 -8
  405. package/dist/physics/Raycast.js.map +1 -1
  406. package/dist/physics/RigidBody.d.ts +16 -9
  407. package/dist/physics/RigidBody.d.ts.map +1 -1
  408. package/dist/physics/RigidBody.js +23 -75
  409. package/dist/physics/RigidBody.js.map +1 -1
  410. package/dist/physics/SurfaceQuery.d.ts +72 -0
  411. package/dist/physics/SurfaceQuery.d.ts.map +1 -0
  412. package/dist/physics/SurfaceQuery.js +89 -0
  413. package/dist/physics/SurfaceQuery.js.map +1 -0
  414. package/dist/physics/index.d.ts +62 -17
  415. package/dist/physics/index.d.ts.map +1 -1
  416. package/dist/physics/index.js +70 -17
  417. package/dist/physics/index.js.map +1 -1
  418. package/dist/physics/solverless.d.ts +37 -0
  419. package/dist/physics/solverless.d.ts.map +1 -0
  420. package/dist/physics/solverless.js +36 -0
  421. package/dist/physics/solverless.js.map +1 -0
  422. package/dist/physics/world.d.ts +18 -0
  423. package/dist/physics/world.d.ts.map +1 -0
  424. package/dist/physics/world.js +17 -0
  425. package/dist/physics/world.js.map +1 -0
  426. package/dist/physics-rapier/index.d.ts +169 -0
  427. package/dist/physics-rapier/index.d.ts.map +1 -0
  428. package/dist/physics-rapier/index.js +311 -0
  429. package/dist/physics-rapier/index.js.map +1 -0
  430. package/dist/product-studio/ProductAsset.d.ts +1 -1
  431. package/dist/product-studio/ProductAssetLoader.d.ts +1 -1
  432. package/dist/product-studio/ProductCamera.d.ts +1 -1
  433. package/dist/product-studio/ProductDiagnostics.d.ts +2 -2
  434. package/dist/product-studio/ProductExport.d.ts +1 -1
  435. package/dist/product-studio/ProductFloor.d.ts +2 -2
  436. package/dist/product-studio/ProductLighting.d.ts +1 -1
  437. package/dist/product-studio/ProductLighting.d.ts.map +1 -1
  438. package/dist/product-studio/ProductLighting.js +34 -3
  439. package/dist/product-studio/ProductLighting.js.map +1 -1
  440. package/dist/product-studio/ProductMaterials.d.ts +2 -2
  441. package/dist/product-studio/ProductRenderScene.d.ts +1 -1
  442. package/dist/product-studio/ProductStudio.d.ts +1 -1
  443. package/dist/product-studio/ProductTypes.d.ts +2 -2
  444. package/dist/product-studio/index.d.ts +12 -12
  445. package/dist/react/index.d.ts +1 -1
  446. package/dist/rendering/ArchitecturalLighting.d.ts +35 -0
  447. package/dist/rendering/ArchitecturalLighting.d.ts.map +1 -0
  448. package/dist/rendering/{ArchitecturalLightingFixtures.js → ArchitecturalLighting.js} +3 -12
  449. package/dist/rendering/ArchitecturalLighting.js.map +1 -0
  450. package/dist/rendering/ArchitecturalMaterialCatalog.d.ts +3 -3
  451. package/dist/rendering/ArchitecturalMaterialCatalog.d.ts.map +1 -1
  452. package/dist/rendering/ArchitecturalMaterialCatalog.js +1 -1
  453. package/dist/rendering/ArchitecturalMaterialCatalog.js.map +1 -1
  454. package/dist/rendering/{ArchitecturalMeasurementFixtures.d.ts → ArchitecturalMeasurement.d.ts} +3 -6
  455. package/dist/rendering/ArchitecturalMeasurement.d.ts.map +1 -0
  456. package/dist/rendering/{ArchitecturalMeasurementFixtures.js → ArchitecturalMeasurement.js} +3 -6
  457. package/dist/rendering/ArchitecturalMeasurement.js.map +1 -0
  458. package/dist/rendering/CameraFraming.d.ts +1 -1
  459. package/dist/rendering/{CanonicalSceneFixtures.d.ts → CanonicalProductScene.d.ts} +2 -2
  460. package/dist/rendering/CanonicalProductScene.d.ts.map +1 -0
  461. package/dist/rendering/{CanonicalSceneFixtures.js → CanonicalProductScene.js} +2 -2
  462. package/dist/rendering/CanonicalProductScene.js.map +1 -0
  463. package/dist/rendering/CascadedShadowMaps.d.ts +8 -8
  464. package/dist/rendering/CascadedShadowMaps.d.ts.map +1 -1
  465. package/dist/rendering/CascadedShadowMaps.js +1 -1
  466. package/dist/rendering/CascadedShadowMaps.js.map +1 -1
  467. package/dist/rendering/ClusteredForwardLighting.d.ts +2 -2
  468. package/dist/rendering/DecalGeometry.d.ts +2 -2
  469. package/dist/rendering/DepthPass.d.ts +4 -4
  470. package/dist/rendering/DepthPass.d.ts.map +1 -1
  471. package/dist/rendering/DepthPass.js +2 -2
  472. package/dist/rendering/DepthPass.js.map +1 -1
  473. package/dist/rendering/EnvironmentBackgroundPass.d.ts +4 -4
  474. package/dist/rendering/EnvironmentBackgroundPass.d.ts.map +1 -1
  475. package/dist/rendering/EnvironmentBackgroundPass.js +2 -2
  476. package/dist/rendering/EnvironmentBackgroundPass.js.map +1 -1
  477. package/dist/rendering/EnvironmentBackgroundResources.d.ts +2 -2
  478. package/dist/rendering/EnvironmentLighting.d.ts +1 -1
  479. package/dist/rendering/EnvironmentMapResources.d.ts +2 -2
  480. package/dist/rendering/EnvironmentPipeline.d.ts +2 -2
  481. package/dist/rendering/EnvironmentPlatform.d.ts +3 -3
  482. package/dist/rendering/EnvironmentPlatform.js +2 -2
  483. package/dist/rendering/EnvironmentPlatform.js.map +1 -1
  484. package/dist/rendering/EnvironmentPreset.d.ts +1 -1
  485. package/dist/rendering/Exposure.d.ts +1 -1
  486. package/dist/rendering/ExternalParityRenderPreset.d.ts +3 -3
  487. package/dist/rendering/ForwardPass.d.ts +9 -9
  488. package/dist/rendering/ForwardPass.d.ts.map +1 -1
  489. package/dist/rendering/ForwardPass.js +24 -10
  490. package/dist/rendering/ForwardPass.js.map +1 -1
  491. package/dist/rendering/Geometry.d.ts +5 -3
  492. package/dist/rendering/Geometry.d.ts.map +1 -1
  493. package/dist/rendering/Geometry.js +15 -0
  494. package/dist/rendering/Geometry.js.map +1 -1
  495. package/dist/rendering/GeometryPrimitives.d.ts +2 -2
  496. package/dist/rendering/HDRRenderPipeline.d.ts +4 -4
  497. package/dist/rendering/IBL.d.ts +4 -4
  498. package/dist/rendering/IndexBuffer.d.ts +1 -1
  499. package/dist/rendering/InstancedPBRMaterial.d.ts +2 -2
  500. package/dist/rendering/InstancedPBRMaterial.js +1 -1
  501. package/dist/rendering/InstancedPBRMaterial.js.map +1 -1
  502. package/dist/rendering/InstancedUnlitMaterial.d.ts +1 -1
  503. package/dist/rendering/InstancedUnlitMaterial.js +1 -1
  504. package/dist/rendering/InstancedUnlitMaterial.js.map +1 -1
  505. package/dist/rendering/Instancing.d.ts +1 -1
  506. package/dist/rendering/LightCollector.d.ts +1 -1
  507. package/dist/rendering/LightUniforms.d.ts +2 -2
  508. package/dist/rendering/LightingDebug.d.ts +2 -2
  509. package/dist/rendering/LightingDefaults.d.ts +2 -2
  510. package/dist/rendering/LightingRig.d.ts +1 -1
  511. package/dist/rendering/LineGeometry.d.ts +2 -2
  512. package/dist/rendering/Material.d.ts +1 -1
  513. package/dist/rendering/Material.js +2 -2
  514. package/dist/rendering/Material.js.map +1 -1
  515. package/dist/rendering/MaterialBinding.d.ts +3 -3
  516. package/dist/rendering/MaterialBinding.js +4 -4
  517. package/dist/rendering/MaterialBinding.js.map +1 -1
  518. package/dist/rendering/MaterialInstance.d.ts +2 -2
  519. package/dist/rendering/MaterialInstance.js +2 -2
  520. package/dist/rendering/MaterialInstance.js.map +1 -1
  521. package/dist/rendering/MaterialPresets.d.ts +2 -2
  522. package/dist/rendering/MeshConsolidation.d.ts +3 -3
  523. package/dist/rendering/MorphTarget.d.ts +1 -1
  524. package/dist/rendering/MorphTargetPlan.d.ts +1 -1
  525. package/dist/rendering/MorphUnlitMaterial.d.ts +1 -1
  526. package/dist/rendering/MorphUnlitMaterial.js +1 -1
  527. package/dist/rendering/MorphUnlitMaterial.js.map +1 -1
  528. package/dist/rendering/NormalMappedPBRMaterial.d.ts +4 -4
  529. package/dist/rendering/NormalMappedPBRMaterial.js +1 -1
  530. package/dist/rendering/NormalMappedPBRMaterial.js.map +1 -1
  531. package/dist/rendering/{OceanFixtures.d.ts → OceanSurface.d.ts} +1 -1
  532. package/dist/rendering/OceanSurface.d.ts.map +1 -0
  533. package/dist/rendering/{OceanFixtures.js → OceanSurface.js} +1 -1
  534. package/dist/rendering/OceanSurface.js.map +1 -0
  535. package/dist/rendering/PBRLightingDefaults.d.ts +1 -1
  536. package/dist/rendering/PBRMaterial.d.ts +2 -2
  537. package/dist/rendering/PBRMaterial.d.ts.map +1 -1
  538. package/dist/rendering/PBRMaterial.js +3 -3
  539. package/dist/rendering/PBRMaterial.js.map +1 -1
  540. package/dist/rendering/PMREM.d.ts +2 -2
  541. package/dist/rendering/PortableShaderMaterial.d.ts +60 -0
  542. package/dist/rendering/PortableShaderMaterial.d.ts.map +1 -0
  543. package/dist/rendering/PortableShaderMaterial.js +223 -0
  544. package/dist/rendering/PortableShaderMaterial.js.map +1 -0
  545. package/dist/rendering/PostProcessPass.d.ts +2 -2
  546. package/dist/rendering/PostProcessPass.d.ts.map +1 -1
  547. package/dist/rendering/PostProcessPass.js +30 -6
  548. package/dist/rendering/PostProcessPass.js.map +1 -1
  549. package/dist/rendering/{ProceduralTextureFixtures.d.ts → ProceduralTexture.d.ts} +2 -2
  550. package/dist/rendering/ProceduralTexture.d.ts.map +1 -0
  551. package/dist/rendering/{ProceduralTextureFixtures.js → ProceduralTexture.js} +1 -1
  552. package/dist/rendering/ProceduralTexture.js.map +1 -0
  553. package/dist/rendering/{ProductTurntableFixtures.d.ts → ProductTurntable.d.ts} +4 -4
  554. package/dist/rendering/ProductTurntable.d.ts.map +1 -0
  555. package/dist/rendering/{ProductTurntableFixtures.js → ProductTurntable.js} +2 -2
  556. package/dist/rendering/ProductTurntable.js.map +1 -0
  557. package/dist/rendering/Raycaster.d.ts +1 -1
  558. package/dist/rendering/ReflectionProbe.d.ts +4 -4
  559. package/dist/rendering/ReflectionSurfaces.d.ts +2 -2
  560. package/dist/rendering/RenderBackend.d.ts +3 -3
  561. package/dist/rendering/RenderDevice.d.ts +36 -6
  562. package/dist/rendering/RenderDevice.d.ts.map +1 -1
  563. package/dist/rendering/RenderDevice.js.map +1 -1
  564. package/dist/rendering/RenderGraph.d.ts +1 -1
  565. package/dist/rendering/RenderPass.d.ts +1 -1
  566. package/dist/rendering/RenderPipeline.d.ts +3 -3
  567. package/dist/rendering/RenderQueue.d.ts +2 -2
  568. package/dist/rendering/RenderState.d.ts +2 -2
  569. package/dist/rendering/Renderer.d.ts +17 -16
  570. package/dist/rendering/Renderer.d.ts.map +1 -1
  571. package/dist/rendering/Renderer.js +23 -9
  572. package/dist/rendering/Renderer.js.map +1 -1
  573. package/dist/rendering/RendererFeatureGates.d.ts +1 -1
  574. package/dist/rendering/RendererPostprocessPlan.d.ts +1 -1
  575. package/dist/rendering/RendererPostprocessPlan.js +4 -4
  576. package/dist/rendering/RendererPostprocessPlan.js.map +1 -1
  577. package/dist/rendering/RendererVisualPipelineReport.d.ts +4 -4
  578. package/dist/rendering/ResourceLifecycle.d.ts +1 -1
  579. package/dist/rendering/SceneOptimization.d.ts +3 -3
  580. package/dist/rendering/ScreenSpaceLineMaterial.d.ts +1 -1
  581. package/dist/rendering/ScreenSpaceLineMaterial.js +1 -1
  582. package/dist/rendering/ScreenSpaceLineMaterial.js.map +1 -1
  583. package/dist/rendering/ShaderChunks.d.ts.map +1 -1
  584. package/dist/rendering/ShaderChunks.js +92 -24
  585. package/dist/rendering/ShaderChunks.js.map +1 -1
  586. package/dist/rendering/ShaderLibrary.d.ts +2 -78
  587. package/dist/rendering/ShaderLibrary.d.ts.map +1 -1
  588. package/dist/rendering/ShaderLibrary.js +103 -810
  589. package/dist/rendering/ShaderLibrary.js.map +1 -1
  590. package/dist/rendering/ShaderLibraryCore.d.ts +100 -0
  591. package/dist/rendering/ShaderLibraryCore.d.ts.map +1 -0
  592. package/dist/rendering/ShaderLibraryCore.js +792 -0
  593. package/dist/rendering/ShaderLibraryCore.js.map +1 -0
  594. package/dist/rendering/ShaderModule.d.ts +3 -3
  595. package/dist/rendering/ShaderModule.d.ts.map +1 -1
  596. package/dist/rendering/ShaderModule.js +4 -2
  597. package/dist/rendering/ShaderModule.js.map +1 -1
  598. package/dist/rendering/ShaderReflection.d.ts +1 -1
  599. package/dist/rendering/ShadowMap.d.ts +1 -1
  600. package/dist/rendering/ShadowPass.d.ts +6 -6
  601. package/dist/rendering/ShadowPass.d.ts.map +1 -1
  602. package/dist/rendering/ShadowPass.js +6 -4
  603. package/dist/rendering/ShadowPass.js.map +1 -1
  604. package/dist/rendering/ShadowProjection.d.ts +1 -1
  605. package/dist/rendering/SkinnedLitMaterial.d.ts +3 -3
  606. package/dist/rendering/SkinnedLitMaterial.js +1 -1
  607. package/dist/rendering/SkinnedLitMaterial.js.map +1 -1
  608. package/dist/rendering/SkinnedUnlitMaterial.d.ts +1 -1
  609. package/dist/rendering/SkinnedUnlitMaterial.js +1 -1
  610. package/dist/rendering/SkinnedUnlitMaterial.js.map +1 -1
  611. package/dist/rendering/SkinningBounds.d.ts +2 -2
  612. package/dist/rendering/{SpaceEnvironmentFixtures.d.ts → SpaceEnvironment.d.ts} +4 -9
  613. package/dist/rendering/SpaceEnvironment.d.ts.map +1 -0
  614. package/dist/rendering/{SpaceEnvironmentFixtures.js → SpaceEnvironment.js} +6 -22
  615. package/dist/rendering/SpaceEnvironment.js.map +1 -0
  616. package/dist/rendering/SpecularPrefilter.d.ts +1 -1
  617. package/dist/rendering/SpriteGeometry.d.ts +1 -1
  618. package/dist/rendering/StereoCameraRig.d.ts +2 -2
  619. package/dist/rendering/StereoEffects.d.ts +1 -1
  620. package/dist/rendering/{TerrainFixtures.d.ts → TerrainHeightfield.d.ts} +2 -2
  621. package/dist/rendering/TerrainHeightfield.d.ts.map +1 -0
  622. package/dist/rendering/{TerrainFixtures.js → TerrainHeightfield.js} +1 -1
  623. package/dist/rendering/TerrainHeightfield.js.map +1 -0
  624. package/dist/rendering/TextureBinding.d.ts +16 -2
  625. package/dist/rendering/TextureBinding.d.ts.map +1 -1
  626. package/dist/rendering/TextureBinding.js +17 -0
  627. package/dist/rendering/TextureBinding.js.map +1 -1
  628. package/dist/rendering/TexturedPBRMaterial.d.ts +4 -4
  629. package/dist/rendering/TexturedPBRMaterial.js +1 -1
  630. package/dist/rendering/TexturedPBRMaterial.js.map +1 -1
  631. package/dist/rendering/TexturedUnlitMaterial.d.ts +3 -3
  632. package/dist/rendering/TexturedUnlitMaterial.js +1 -1
  633. package/dist/rendering/TexturedUnlitMaterial.js.map +1 -1
  634. package/dist/rendering/ToneMapping.d.ts +1 -1
  635. package/dist/rendering/UniformBinder.d.ts +1 -1
  636. package/dist/rendering/UnlitMaterial.d.ts +1 -1
  637. package/dist/rendering/UnlitMaterial.js +1 -1
  638. package/dist/rendering/UnlitMaterial.js.map +1 -1
  639. package/dist/rendering/{VegetationFixtures.d.ts → VegetationScatter.d.ts} +2 -2
  640. package/dist/rendering/VegetationScatter.d.ts.map +1 -0
  641. package/dist/rendering/{VegetationFixtures.js → VegetationScatter.js} +2 -2
  642. package/dist/rendering/VegetationScatter.js.map +1 -0
  643. package/dist/rendering/VertexBuffer.d.ts +2 -2
  644. package/dist/rendering/{VoxelWorldFixtures.d.ts → VoxelWorld.d.ts} +12 -15
  645. package/dist/rendering/VoxelWorld.d.ts.map +1 -0
  646. package/dist/rendering/{VoxelWorldFixtures.js → VoxelWorld.js} +6 -9
  647. package/dist/rendering/VoxelWorld.js.map +1 -0
  648. package/dist/rendering/{WeatherFixtures.d.ts → Weather.d.ts} +7 -9
  649. package/dist/rendering/Weather.d.ts.map +1 -0
  650. package/dist/rendering/{WeatherFixtures.js → Weather.js} +5 -7
  651. package/dist/rendering/Weather.js.map +1 -0
  652. package/dist/rendering/WebGL2Device.d.ts +23 -1
  653. package/dist/rendering/WebGL2Device.d.ts.map +1 -1
  654. package/dist/rendering/WebGL2Device.js +134 -23
  655. package/dist/rendering/WebGL2Device.js.map +1 -1
  656. package/dist/rendering/WebGPUDevice.d.ts +20 -3
  657. package/dist/rendering/WebGPUDevice.d.ts.map +1 -1
  658. package/dist/rendering/WebGPUDevice.js +188 -9
  659. package/dist/rendering/WebGPUDevice.js.map +1 -1
  660. package/dist/rendering/WebGPURenderToTextureProof.d.ts +1 -1
  661. package/dist/rendering/advanced-runtime/AdvancedRenderer.d.ts +4 -4
  662. package/dist/rendering/advanced-runtime/index.d.ts +9 -9
  663. package/dist/rendering/cinematic/BloomPass.d.ts +1 -1
  664. package/dist/rendering/cinematic/CinematicDepthComposition.d.ts +1 -1
  665. package/dist/rendering/cinematic/CinematicLightingRig.d.ts +2 -2
  666. package/dist/rendering/cinematic/CinematicMaterialPresets.d.ts +2 -2
  667. package/dist/rendering/cinematic/CinematicPostProcess.d.ts +6 -6
  668. package/dist/rendering/cinematic/DepthHazePass.d.ts +1 -1
  669. package/dist/rendering/cinematic/EmissivePracticalLightSystem.d.ts +2 -2
  670. package/dist/rendering/cinematic/FilmGrainPass.d.ts +1 -1
  671. package/dist/rendering/cinematic/FogVolumeSystem.d.ts +1 -1
  672. package/dist/rendering/cinematic/GlowCardSystem.d.ts +2 -2
  673. package/dist/rendering/cinematic/RainParticleSystem.d.ts +2 -2
  674. package/dist/rendering/cinematic/VignettePass.d.ts +1 -1
  675. package/dist/rendering/cinematic/WetReflectionApproximation.d.ts +1 -1
  676. package/dist/rendering/cinematic/index.d.ts +14 -14
  677. package/dist/rendering/index.d.ts +230 -237
  678. package/dist/rendering/index.d.ts.map +1 -1
  679. package/dist/rendering/index.js +35 -19
  680. package/dist/rendering/index.js.map +1 -1
  681. package/dist/rendering/lean/LeanProductRenderer.d.ts +29 -0
  682. package/dist/rendering/lean/LeanProductRenderer.d.ts.map +1 -0
  683. package/dist/rendering/lean/LeanProductRenderer.js +38 -0
  684. package/dist/rendering/lean/LeanProductRenderer.js.map +1 -0
  685. package/dist/rendering/lean/LeanProductionRenderer.d.ts +38 -0
  686. package/dist/rendering/lean/LeanProductionRenderer.d.ts.map +1 -0
  687. package/dist/rendering/lean/LeanProductionRenderer.js +88 -0
  688. package/dist/rendering/lean/LeanProductionRenderer.js.map +1 -0
  689. package/dist/rendering/lean-runtime.d.ts +18 -0
  690. package/dist/rendering/lean-runtime.d.ts.map +1 -0
  691. package/dist/rendering/lean-runtime.js +13 -0
  692. package/dist/rendering/lean-runtime.js.map +1 -0
  693. package/dist/rendering/materials/PhysicalMaterial.d.ts +1 -1
  694. package/dist/rendering/performance/BVH.d.ts +2 -2
  695. package/dist/rendering/performance/Batcher.d.ts +2 -2
  696. package/dist/rendering/performance/FrustumCuller.d.ts +1 -1
  697. package/dist/rendering/performance/Octree.d.ts +1 -1
  698. package/dist/rendering/postprocess/BloomPass.d.ts +1 -1
  699. package/dist/rendering/postprocess/CinematicDiagnostics.d.ts +1 -1
  700. package/dist/rendering/postprocess/ColorGradingPass.d.ts +1 -1
  701. package/dist/rendering/postprocess/DepthOfFieldPass.d.ts +1 -1
  702. package/dist/rendering/postprocess/EffectComposer.d.ts +3 -3
  703. package/dist/rendering/postprocess/EffectComposer.d.ts.map +1 -1
  704. package/dist/rendering/postprocess/EffectComposer.js +1 -3
  705. package/dist/rendering/postprocess/EffectComposer.js.map +1 -1
  706. package/dist/rendering/postprocess/SSAOPass.d.ts +1 -1
  707. package/dist/rendering/postprocess/index.d.ts +10 -10
  708. package/dist/rendering/production-runtime/AnimationControlsPipeline.d.ts +1 -1
  709. package/dist/rendering/production-runtime/PBRHDRPipeline.d.ts +4 -4
  710. package/dist/rendering/production-runtime/PBRHDRPipeline.d.ts.map +1 -1
  711. package/dist/rendering/production-runtime/PBRHDRPipeline.js +5 -1
  712. package/dist/rendering/production-runtime/PBRHDRPipeline.js.map +1 -1
  713. package/dist/rendering/production-runtime/ProductionEffectsPipeline.d.ts +2 -2
  714. package/dist/rendering/production-runtime/ProductionRendererTypes.d.ts +11 -2
  715. package/dist/rendering/production-runtime/ProductionRendererTypes.d.ts.map +1 -1
  716. package/dist/rendering/production-runtime/ProductionRendererTypes.js.map +1 -1
  717. package/dist/rendering/production-runtime/ProductionRuntimeRenderer.d.ts +8 -3
  718. package/dist/rendering/production-runtime/ProductionRuntimeRenderer.d.ts.map +1 -1
  719. package/dist/rendering/production-runtime/ProductionRuntimeRenderer.js +53 -5
  720. package/dist/rendering/production-runtime/ProductionRuntimeRenderer.js.map +1 -1
  721. package/dist/rendering/production-runtime/ProductionWebGL2Renderer.d.ts +14 -4
  722. package/dist/rendering/production-runtime/ProductionWebGL2Renderer.d.ts.map +1 -1
  723. package/dist/rendering/production-runtime/ProductionWebGL2Renderer.js +21 -2
  724. package/dist/rendering/production-runtime/ProductionWebGL2Renderer.js.map +1 -1
  725. package/dist/rendering/production-runtime/ProductionWebGPURenderer.d.ts +4 -4
  726. package/dist/rendering/production-runtime/ProductionWebGPURenderer.d.ts.map +1 -1
  727. package/dist/rendering/production-runtime/ProductionWebGPURenderer.js +4 -1
  728. package/dist/rendering/production-runtime/ProductionWebGPURenderer.js.map +1 -1
  729. package/dist/rendering/production-runtime/TransmissionBackdropCapture.d.ts +3 -3
  730. package/dist/rendering/production-runtime/backends/RendererBackend.d.ts +1 -1
  731. package/dist/rendering/production-runtime/backends/WebGL2RendererBackend.d.ts +3 -3
  732. package/dist/rendering/production-runtime/backends/WebGPURendererBackend.d.ts +1 -1
  733. package/dist/rendering/production-runtime/backends/webgl2/WebGL2StateCache.d.ts +1 -1
  734. package/dist/rendering/production-runtime/diagnostics/FrameCapture.d.ts +1 -1
  735. package/dist/rendering/production-runtime/environment/HDRLoader.d.ts +2 -2
  736. package/dist/rendering/production-runtime/environment/PMREMGenerator.d.ts +1 -1
  737. package/dist/rendering/production-runtime/framegraph/FrameGraph.d.ts +1 -1
  738. package/dist/rendering/production-runtime/geometry/ProjectedDecalGeometry.d.ts +1 -1
  739. package/dist/rendering/production-runtime/index.d.ts +74 -74
  740. package/dist/rendering/production-runtime/lights/LightManager.d.ts +1 -1
  741. package/dist/rendering/production-runtime/lights/ShadowMapRenderer.d.ts +1 -1
  742. package/dist/rendering/production-runtime/materials/GLTFMaterialAdapter.d.ts +1 -1
  743. package/dist/rendering/production-runtime/materials/GLTFPBRMaterialAdapter.d.ts +2 -2
  744. package/dist/rendering/production-runtime/materials/MaterialCompiler.d.ts +2 -2
  745. package/dist/rendering/production-runtime/materials/MaterialTextureBindings.d.ts +1 -1
  746. package/dist/rendering/production-runtime/passes/ContactShadowPass.d.ts +1 -1
  747. package/dist/rendering/production-runtime/passes/DepthPrepass.d.ts +1 -1
  748. package/dist/rendering/production-runtime/passes/OpaquePass.d.ts +1 -1
  749. package/dist/rendering/production-runtime/passes/ShadowPass.d.ts +1 -1
  750. package/dist/rendering/production-runtime/passes/SkyboxPass.d.ts +1 -1
  751. package/dist/rendering/production-runtime/passes/ToneMappingPass.d.ts +1 -1
  752. package/dist/rendering/production-runtime/passes/TransparentPass.d.ts +1 -1
  753. package/dist/rendering/production-runtime/postprocess/BloomPass.d.ts +2 -2
  754. package/dist/rendering/production-runtime/postprocess/ColorGradingPass.d.ts +2 -2
  755. package/dist/rendering/production-runtime/postprocess/DOFPass.d.ts +2 -2
  756. package/dist/rendering/production-runtime/postprocess/FXAAPass.d.ts +2 -2
  757. package/dist/rendering/production-runtime/postprocess/ProductionEffectComposer.d.ts +1 -1
  758. package/dist/rendering/production-runtime/postprocess/ProductionPostProcessTypes.d.ts +1 -1
  759. package/dist/rendering/production-runtime/postprocess/SSAOPass.d.ts +2 -2
  760. package/dist/rendering/production-runtime/resources/RenderTarget.d.ts +1 -1
  761. package/dist/rendering/production-runtime/scene/RenderableMesh.d.ts +1 -1
  762. package/dist/rendering/production-runtime/scene/RenderableScene.d.ts +3 -3
  763. package/dist/rendering/shadows/CascadedShadowPipeline.d.ts +1 -1
  764. package/dist/rendering/shadows/ShadowDebugViews.d.ts +2 -2
  765. package/dist/rendering/threejs-example-parity/index.d.ts +4 -4
  766. package/dist/rendering/webgpu/WebGPUBuffer.d.ts +1 -1
  767. package/dist/rendering/webgpu/WebGPUCompute.d.ts +2 -2
  768. package/dist/rendering/webgpu/WebGPUPostProcess.d.ts +2 -2
  769. package/dist/rendering/webgpu/WebGPUTexture.d.ts +2 -2
  770. package/dist/rendering/webgpu.d.ts +25 -0
  771. package/dist/rendering/webgpu.d.ts.map +1 -0
  772. package/dist/rendering/webgpu.js +24 -0
  773. package/dist/rendering/webgpu.js.map +1 -0
  774. package/dist/scene/Bounds.d.ts +1 -1
  775. package/dist/scene/Camera.d.ts +1 -1
  776. package/dist/scene/Light.d.ts +1 -1
  777. package/dist/scene/MathTypes.d.ts +2 -1
  778. package/dist/scene/MathTypes.d.ts.map +1 -1
  779. package/dist/scene/MathTypes.js +3 -0
  780. package/dist/scene/MathTypes.js.map +1 -1
  781. package/dist/scene/Renderable.d.ts +6 -0
  782. package/dist/scene/Renderable.d.ts.map +1 -1
  783. package/dist/scene/Renderable.js +8 -2
  784. package/dist/scene/Renderable.js.map +1 -1
  785. package/dist/scripting/AnimationVisualNodes.d.ts +1 -1
  786. package/dist/scripting/Behavior.d.ts +1 -1
  787. package/dist/scripting/BehaviorHost.d.ts +1 -1
  788. package/dist/scripting/BehaviorRegistry.d.ts +1 -1
  789. package/dist/scripting/BehaviorSystem.d.ts +2 -2
  790. package/dist/scripting/HTN.d.ts +1 -1
  791. package/dist/scripting/ScriptContext.d.ts +1 -1
  792. package/dist/scripting/StateMachine.d.ts +1 -1
  793. package/dist/scripting/UtilityAI.d.ts +1 -1
  794. package/dist/scripting/VisualGraph.d.ts +2 -2
  795. package/dist/scripting/VisualGraphExecutor.d.ts +2 -2
  796. package/dist/scripting/VisualNodeCatalog.d.ts +1 -1
  797. package/dist/scripting/index.d.ts +37 -53
  798. package/dist/scripting/index.d.ts.map +1 -1
  799. package/dist/scripting/index.js +0 -8
  800. package/dist/scripting/index.js.map +1 -1
  801. package/dist/workflows/AnimationLabWorkflow.d.ts +1 -1
  802. package/dist/workflows/AssetViewerWorkflow.d.ts +1 -1
  803. package/dist/workflows/ComparisonWorkflow.d.ts +1 -1
  804. package/dist/workflows/InteractiveSceneWorkflow.d.ts +1 -1
  805. package/dist/workflows/MaterialStudioWorkflow.d.ts +1 -1
  806. package/dist/workflows/ProductConfiguratorWorkflow.d.ts +1 -1
  807. package/dist/workflows/SceneShowcaseWorkflow.d.ts +1 -1
  808. package/dist/workflows/WorkflowDiagnostics.d.ts +4 -4
  809. package/dist/workflows/WorkflowTypes.d.ts +4 -4
  810. package/dist/workflows/index.d.ts +12 -12
  811. package/dist/workflows/production-runtime/ProductionExampleRuntime.d.ts +2 -2
  812. package/dist/workflows/production-runtime/ProductionExampleRuntime.d.ts.map +1 -1
  813. package/dist/workflows/production-runtime/ProductionExampleRuntime.js +2 -2
  814. package/dist/workflows/production-runtime/ProductionExampleRuntime.js.map +1 -1
  815. package/dist/workflows/production-runtime/index.d.ts +10 -10
  816. package/dist/workflows/workflow-foundation/index.d.ts +16 -16
  817. package/package.json +157 -40
  818. package/templates/cinematic-scene/node_modules/.vite/deps/_metadata.json +8 -0
  819. package/templates/cinematic-scene/node_modules/.vite/deps/package.json +3 -0
  820. package/templates/cinematic-scene/package.json +1 -1
  821. package/templates/cinematic-scene/test-results/.last-run.json +6 -0
  822. package/templates/cinematic-scene/test-results/route-health-Aura3D-cinematic-scene-reaches-ready-state/error-context.md +64 -0
  823. package/templates/mini-game/README.md +3 -2
  824. package/templates/mini-game/package.json +1 -1
  825. package/templates/mini-game/src/aura-assets.ts +1 -1
  826. package/templates/mini-game/src/main.ts +69 -141
  827. package/templates/product-viewer/README.md +7 -5
  828. package/templates/product-viewer/index.html +1 -1
  829. package/templates/product-viewer/node_modules/.vite/deps/_metadata.json +8 -0
  830. package/templates/product-viewer/node_modules/.vite/deps/package.json +3 -0
  831. package/templates/product-viewer/package.json +1 -1
  832. package/templates/product-viewer/src/aura-assets.ts +1 -1
  833. package/templates/product-viewer/src/main.ts +29 -23
  834. package/dist/animation/MotionMatchingFixtures.d.ts +0 -58
  835. package/dist/animation/MotionMatchingFixtures.d.ts.map +0 -1
  836. package/dist/animation/MotionMatchingFixtures.js +0 -175
  837. package/dist/animation/MotionMatchingFixtures.js.map +0 -1
  838. package/dist/animation/Retargeting.d.ts +0 -12
  839. package/dist/animation/Retargeting.d.ts.map +0 -1
  840. package/dist/animation/Retargeting.js +0 -19
  841. package/dist/animation/Retargeting.js.map +0 -1
  842. package/dist/animation/SecondaryAnimationFixtures.d.ts +0 -55
  843. package/dist/animation/SecondaryAnimationFixtures.d.ts.map +0 -1
  844. package/dist/animation/SecondaryAnimationFixtures.js +0 -145
  845. package/dist/animation/SecondaryAnimationFixtures.js.map +0 -1
  846. package/dist/assets/AssetBundleCacheFixtures.d.ts +0 -62
  847. package/dist/assets/AssetBundleCacheFixtures.d.ts.map +0 -1
  848. package/dist/assets/AssetBundleCacheFixtures.js +0 -222
  849. package/dist/assets/AssetBundleCacheFixtures.js.map +0 -1
  850. package/dist/assets/EXRLoader.d.ts +0 -2
  851. package/dist/assets/EXRLoader.d.ts.map +0 -1
  852. package/dist/assets/EXRLoader.js +0 -2
  853. package/dist/assets/EXRLoader.js.map +0 -1
  854. package/dist/assets/SceneAnalysisFixtures.d.ts +0 -100
  855. package/dist/assets/SceneAnalysisFixtures.d.ts.map +0 -1
  856. package/dist/assets/SceneAnalysisFixtures.js +0 -331
  857. package/dist/assets/SceneAnalysisFixtures.js.map +0 -1
  858. package/dist/assets/loaders/EXRLoader.d.ts +0 -4
  859. package/dist/assets/loaders/EXRLoader.d.ts.map +0 -1
  860. package/dist/assets/loaders/EXRLoader.js +0 -10
  861. package/dist/assets/loaders/EXRLoader.js.map +0 -1
  862. package/dist/audio/AdaptiveMusicFixtures.d.ts +0 -36
  863. package/dist/audio/AdaptiveMusicFixtures.d.ts.map +0 -1
  864. package/dist/audio/AdaptiveMusicFixtures.js +0 -90
  865. package/dist/audio/AdaptiveMusicFixtures.js.map +0 -1
  866. package/dist/audio/AudioEffectsAnalysisFixtures.d.ts +0 -99
  867. package/dist/audio/AudioEffectsAnalysisFixtures.d.ts.map +0 -1
  868. package/dist/audio/AudioEffectsAnalysisFixtures.js +0 -192
  869. package/dist/audio/AudioEffectsAnalysisFixtures.js.map +0 -1
  870. package/dist/audio/SpatialAudioFixtures.d.ts +0 -38
  871. package/dist/audio/SpatialAudioFixtures.d.ts.map +0 -1
  872. package/dist/audio/SpatialAudioFixtures.js +0 -94
  873. package/dist/audio/SpatialAudioFixtures.js.map +0 -1
  874. package/dist/aura3d-cli/cartoon-asset-profiles.d.ts +0 -15
  875. package/dist/aura3d-cli/cartoon-asset-profiles.d.ts.map +0 -1
  876. package/dist/aura3d-cli/cartoon-asset-profiles.js +0 -46
  877. package/dist/aura3d-cli/cartoon-asset-profiles.js.map +0 -1
  878. package/dist/editor-runtime/CartoonSceneEditor.d.ts +0 -111
  879. package/dist/editor-runtime/CartoonSceneEditor.d.ts.map +0 -1
  880. package/dist/editor-runtime/CartoonSceneEditor.js +0 -285
  881. package/dist/editor-runtime/CartoonSceneEditor.js.map +0 -1
  882. package/dist/editor-runtime/LocalizationAccessibilityFixtures.d.ts +0 -70
  883. package/dist/editor-runtime/LocalizationAccessibilityFixtures.d.ts.map +0 -1
  884. package/dist/editor-runtime/LocalizationAccessibilityFixtures.js +0 -275
  885. package/dist/editor-runtime/LocalizationAccessibilityFixtures.js.map +0 -1
  886. package/dist/engine/agent-api/CartoonAssetManifest.d.ts +0 -50
  887. package/dist/engine/agent-api/CartoonAssetManifest.d.ts.map +0 -1
  888. package/dist/engine/agent-api/CartoonAssetManifest.js +0 -65
  889. package/dist/engine/agent-api/CartoonAssetManifest.js.map +0 -1
  890. package/dist/engine/agent-api/CartoonDirector.d.ts +0 -120
  891. package/dist/engine/agent-api/CartoonDirector.d.ts.map +0 -1
  892. package/dist/engine/agent-api/CartoonDirector.js +0 -432
  893. package/dist/engine/agent-api/CartoonDirector.js.map +0 -1
  894. package/dist/engine/agent-api/CartoonEpisodePackage.d.ts +0 -51
  895. package/dist/engine/agent-api/CartoonEpisodePackage.d.ts.map +0 -1
  896. package/dist/engine/agent-api/CartoonEpisodePackage.js +0 -79
  897. package/dist/engine/agent-api/CartoonEpisodePackage.js.map +0 -1
  898. package/dist/engine/agent-api/CartoonMotionQuality.d.ts +0 -83
  899. package/dist/engine/agent-api/CartoonMotionQuality.d.ts.map +0 -1
  900. package/dist/engine/agent-api/CartoonMotionQuality.js +0 -128
  901. package/dist/engine/agent-api/CartoonMotionQuality.js.map +0 -1
  902. package/dist/engine/agent-api/CartoonPerformance.d.ts +0 -150
  903. package/dist/engine/agent-api/CartoonPerformance.d.ts.map +0 -1
  904. package/dist/engine/agent-api/CartoonPerformance.js +0 -345
  905. package/dist/engine/agent-api/CartoonPerformance.js.map +0 -1
  906. package/dist/engine/agent-api/CartoonRenderQueue.d.ts +0 -143
  907. package/dist/engine/agent-api/CartoonRenderQueue.d.ts.map +0 -1
  908. package/dist/engine/agent-api/CartoonRenderQueue.js +0 -410
  909. package/dist/engine/agent-api/CartoonRenderQueue.js.map +0 -1
  910. package/dist/engine/agent-api/CartoonRouteProof.d.ts +0 -112
  911. package/dist/engine/agent-api/CartoonRouteProof.d.ts.map +0 -1
  912. package/dist/engine/agent-api/CartoonRouteProof.js +0 -127
  913. package/dist/engine/agent-api/CartoonRouteProof.js.map +0 -1
  914. package/dist/input/GestureHapticsFixtures.d.ts +0 -57
  915. package/dist/input/GestureHapticsFixtures.d.ts.map +0 -1
  916. package/dist/input/GestureHapticsFixtures.js +0 -115
  917. package/dist/input/GestureHapticsFixtures.js.map +0 -1
  918. package/dist/input/InputActionBindingFixtures.d.ts +0 -44
  919. package/dist/input/InputActionBindingFixtures.d.ts.map +0 -1
  920. package/dist/input/InputActionBindingFixtures.js +0 -86
  921. package/dist/input/InputActionBindingFixtures.js.map +0 -1
  922. package/dist/input/XRFixtures.d.ts +0 -65
  923. package/dist/input/XRFixtures.d.ts.map +0 -1
  924. package/dist/input/XRFixtures.js +0 -136
  925. package/dist/input/XRFixtures.js.map +0 -1
  926. package/dist/physics/CharacterController.d.ts +0 -83
  927. package/dist/physics/CharacterController.d.ts.map +0 -1
  928. package/dist/physics/CharacterController.js +0 -236
  929. package/dist/physics/CharacterController.js.map +0 -1
  930. package/dist/physics/ClothFixtures.d.ts +0 -87
  931. package/dist/physics/ClothFixtures.d.ts.map +0 -1
  932. package/dist/physics/ClothFixtures.js +0 -264
  933. package/dist/physics/ClothFixtures.js.map +0 -1
  934. package/dist/physics/Crowd.d.ts +0 -64
  935. package/dist/physics/Crowd.d.ts.map +0 -1
  936. package/dist/physics/Crowd.js +0 -209
  937. package/dist/physics/Crowd.js.map +0 -1
  938. package/dist/physics/FireSmokeFixtures.d.ts +0 -103
  939. package/dist/physics/FireSmokeFixtures.d.ts.map +0 -1
  940. package/dist/physics/FireSmokeFixtures.js +0 -271
  941. package/dist/physics/FireSmokeFixtures.js.map +0 -1
  942. package/dist/physics/FluidFixtures.d.ts +0 -75
  943. package/dist/physics/FluidFixtures.d.ts.map +0 -1
  944. package/dist/physics/FluidFixtures.js +0 -219
  945. package/dist/physics/FluidFixtures.js.map +0 -1
  946. package/dist/physics/FractureFixtures.d.ts +0 -68
  947. package/dist/physics/FractureFixtures.d.ts.map +0 -1
  948. package/dist/physics/FractureFixtures.js +0 -199
  949. package/dist/physics/FractureFixtures.js.map +0 -1
  950. package/dist/physics/NarrowPhase.d.ts +0 -11
  951. package/dist/physics/NarrowPhase.d.ts.map +0 -1
  952. package/dist/physics/NarrowPhase.js +0 -565
  953. package/dist/physics/NarrowPhase.js.map +0 -1
  954. package/dist/physics/Navigation.d.ts +0 -67
  955. package/dist/physics/Navigation.d.ts.map +0 -1
  956. package/dist/physics/Navigation.js +0 -261
  957. package/dist/physics/Navigation.js.map +0 -1
  958. package/dist/physics/PhysicsSandboxFixtures.d.ts +0 -53
  959. package/dist/physics/PhysicsSandboxFixtures.d.ts.map +0 -1
  960. package/dist/physics/PhysicsSandboxFixtures.js +0 -280
  961. package/dist/physics/PhysicsSandboxFixtures.js.map +0 -1
  962. package/dist/physics/PlatformerFixtures.d.ts +0 -70
  963. package/dist/physics/PlatformerFixtures.d.ts.map +0 -1
  964. package/dist/physics/PlatformerFixtures.js +0 -120
  965. package/dist/physics/PlatformerFixtures.js.map +0 -1
  966. package/dist/physics/SoftBodyFixtures.d.ts +0 -70
  967. package/dist/physics/SoftBodyFixtures.d.ts.map +0 -1
  968. package/dist/physics/SoftBodyFixtures.js +0 -272
  969. package/dist/physics/SoftBodyFixtures.js.map +0 -1
  970. package/dist/physics/Steering.d.ts +0 -161
  971. package/dist/physics/Steering.d.ts.map +0 -1
  972. package/dist/physics/Steering.js +0 -347
  973. package/dist/physics/Steering.js.map +0 -1
  974. package/dist/physics/VehicleDynamics.d.ts.map +0 -1
  975. package/dist/physics/VehicleDynamics.js.map +0 -1
  976. package/dist/rendering/ArchitecturalLightingFixtures.d.ts +0 -40
  977. package/dist/rendering/ArchitecturalLightingFixtures.d.ts.map +0 -1
  978. package/dist/rendering/ArchitecturalLightingFixtures.js.map +0 -1
  979. package/dist/rendering/ArchitecturalMeasurementFixtures.d.ts.map +0 -1
  980. package/dist/rendering/ArchitecturalMeasurementFixtures.js.map +0 -1
  981. package/dist/rendering/CanonicalSceneFixtures.d.ts.map +0 -1
  982. package/dist/rendering/CanonicalSceneFixtures.js.map +0 -1
  983. package/dist/rendering/CullingFixtures.d.ts +0 -70
  984. package/dist/rendering/CullingFixtures.d.ts.map +0 -1
  985. package/dist/rendering/CullingFixtures.js +0 -191
  986. package/dist/rendering/CullingFixtures.js.map +0 -1
  987. package/dist/rendering/OceanFixtures.d.ts.map +0 -1
  988. package/dist/rendering/OceanFixtures.js.map +0 -1
  989. package/dist/rendering/ProceduralTextureFixtures.d.ts.map +0 -1
  990. package/dist/rendering/ProceduralTextureFixtures.js.map +0 -1
  991. package/dist/rendering/ProductTurntableFixtures.d.ts.map +0 -1
  992. package/dist/rendering/ProductTurntableFixtures.js.map +0 -1
  993. package/dist/rendering/SpaceEnvironmentFixtures.d.ts.map +0 -1
  994. package/dist/rendering/SpaceEnvironmentFixtures.js.map +0 -1
  995. package/dist/rendering/TerrainFixtures.d.ts.map +0 -1
  996. package/dist/rendering/TerrainFixtures.js.map +0 -1
  997. package/dist/rendering/VegetationFixtures.d.ts.map +0 -1
  998. package/dist/rendering/VegetationFixtures.js.map +0 -1
  999. package/dist/rendering/VoxelWorldFixtures.d.ts.map +0 -1
  1000. package/dist/rendering/VoxelWorldFixtures.js.map +0 -1
  1001. package/dist/rendering/WeatherFixtures.d.ts.map +0 -1
  1002. package/dist/rendering/WeatherFixtures.js.map +0 -1
  1003. package/dist/rendering/cartoon/CartoonMaterialStyle.d.ts +0 -19
  1004. package/dist/rendering/cartoon/CartoonMaterialStyle.d.ts.map +0 -1
  1005. package/dist/rendering/cartoon/CartoonMaterialStyle.js +0 -13
  1006. package/dist/rendering/cartoon/CartoonMaterialStyle.js.map +0 -1
  1007. package/dist/rendering/cartoon/CartoonRenderPreset.d.ts +0 -36
  1008. package/dist/rendering/cartoon/CartoonRenderPreset.d.ts.map +0 -1
  1009. package/dist/rendering/cartoon/CartoonRenderPreset.js +0 -23
  1010. package/dist/rendering/cartoon/CartoonRenderPreset.js.map +0 -1
  1011. package/dist/rendering/cartoon/CartoonToonMaterial.d.ts +0 -130
  1012. package/dist/rendering/cartoon/CartoonToonMaterial.d.ts.map +0 -1
  1013. package/dist/rendering/cartoon/CartoonToonMaterial.js +0 -303
  1014. package/dist/rendering/cartoon/CartoonToonMaterial.js.map +0 -1
  1015. package/dist/rendering/cartoon/CartoonVisualQuality.d.ts +0 -28
  1016. package/dist/rendering/cartoon/CartoonVisualQuality.d.ts.map +0 -1
  1017. package/dist/rendering/cartoon/CartoonVisualQuality.js +0 -39
  1018. package/dist/rendering/cartoon/CartoonVisualQuality.js.map +0 -1
  1019. package/dist/rendering/cartoon/applyCartoonRenderPreset.d.ts +0 -79
  1020. package/dist/rendering/cartoon/applyCartoonRenderPreset.d.ts.map +0 -1
  1021. package/dist/rendering/cartoon/applyCartoonRenderPreset.js +0 -88
  1022. package/dist/rendering/cartoon/applyCartoonRenderPreset.js.map +0 -1
  1023. package/dist/rendering/cartoon/index.d.ts +0 -6
  1024. package/dist/rendering/cartoon/index.d.ts.map +0 -1
  1025. package/dist/rendering/cartoon/index.js +0 -6
  1026. package/dist/rendering/cartoon/index.js.map +0 -1
  1027. package/dist/rendering/threejs-compatibility/InstancingSystem.d.ts +0 -10
  1028. package/dist/rendering/threejs-compatibility/InstancingSystem.d.ts.map +0 -1
  1029. package/dist/rendering/threejs-compatibility/InstancingSystem.js +0 -11
  1030. package/dist/rendering/threejs-compatibility/InstancingSystem.js.map +0 -1
  1031. package/dist/rendering/threejs-compatibility/LightingSystem.d.ts +0 -11
  1032. package/dist/rendering/threejs-compatibility/LightingSystem.d.ts.map +0 -1
  1033. package/dist/rendering/threejs-compatibility/LightingSystem.js +0 -14
  1034. package/dist/rendering/threejs-compatibility/LightingSystem.js.map +0 -1
  1035. package/dist/rendering/threejs-compatibility/MaterialSystem.d.ts +0 -6
  1036. package/dist/rendering/threejs-compatibility/MaterialSystem.d.ts.map +0 -1
  1037. package/dist/rendering/threejs-compatibility/MaterialSystem.js +0 -7
  1038. package/dist/rendering/threejs-compatibility/MaterialSystem.js.map +0 -1
  1039. package/dist/rendering/threejs-compatibility/RenderTargetSystem.d.ts +0 -16
  1040. package/dist/rendering/threejs-compatibility/RenderTargetSystem.d.ts.map +0 -1
  1041. package/dist/rendering/threejs-compatibility/RenderTargetSystem.js +0 -23
  1042. package/dist/rendering/threejs-compatibility/RenderTargetSystem.js.map +0 -1
  1043. package/dist/rendering/threejs-compatibility/RendererDiagnostics.d.ts +0 -27
  1044. package/dist/rendering/threejs-compatibility/RendererDiagnostics.d.ts.map +0 -1
  1045. package/dist/rendering/threejs-compatibility/RendererDiagnostics.js +0 -41
  1046. package/dist/rendering/threejs-compatibility/RendererDiagnostics.js.map +0 -1
  1047. package/dist/rendering/threejs-compatibility/SceneRenderer.d.ts +0 -19
  1048. package/dist/rendering/threejs-compatibility/SceneRenderer.d.ts.map +0 -1
  1049. package/dist/rendering/threejs-compatibility/SceneRenderer.js +0 -18
  1050. package/dist/rendering/threejs-compatibility/SceneRenderer.js.map +0 -1
  1051. package/dist/rendering/threejs-compatibility/ShadowSystem.d.ts +0 -11
  1052. package/dist/rendering/threejs-compatibility/ShadowSystem.d.ts.map +0 -1
  1053. package/dist/rendering/threejs-compatibility/ShadowSystem.js +0 -12
  1054. package/dist/rendering/threejs-compatibility/ShadowSystem.js.map +0 -1
  1055. package/dist/rendering/threejs-compatibility/TextureSystem.d.ts +0 -9
  1056. package/dist/rendering/threejs-compatibility/TextureSystem.d.ts.map +0 -1
  1057. package/dist/rendering/threejs-compatibility/TextureSystem.js +0 -14
  1058. package/dist/rendering/threejs-compatibility/TextureSystem.js.map +0 -1
  1059. package/dist/rendering/threejs-compatibility/ThreeCompatRenderer.d.ts +0 -37
  1060. package/dist/rendering/threejs-compatibility/ThreeCompatRenderer.d.ts.map +0 -1
  1061. package/dist/rendering/threejs-compatibility/ThreeCompatRenderer.js +0 -77
  1062. package/dist/rendering/threejs-compatibility/ThreeCompatRenderer.js.map +0 -1
  1063. package/dist/rendering/threejs-compatibility/TransparencySystem.d.ts +0 -11
  1064. package/dist/rendering/threejs-compatibility/TransparencySystem.d.ts.map +0 -1
  1065. package/dist/rendering/threejs-compatibility/TransparencySystem.js +0 -12
  1066. package/dist/rendering/threejs-compatibility/TransparencySystem.js.map +0 -1
  1067. package/dist/rendering/threejs-compatibility/index.d.ts +0 -25
  1068. package/dist/rendering/threejs-compatibility/index.d.ts.map +0 -1
  1069. package/dist/rendering/threejs-compatibility/index.js +0 -15
  1070. package/dist/rendering/threejs-compatibility/index.js.map +0 -1
  1071. package/dist/rendering/threejs-compatibility/performance/BVH.d.ts +0 -11
  1072. package/dist/rendering/threejs-compatibility/performance/BVH.d.ts.map +0 -1
  1073. package/dist/rendering/threejs-compatibility/performance/BVH.js +0 -10
  1074. package/dist/rendering/threejs-compatibility/performance/BVH.js.map +0 -1
  1075. package/dist/rendering/threejs-compatibility/performance/FrustumCulling.d.ts +0 -7
  1076. package/dist/rendering/threejs-compatibility/performance/FrustumCulling.d.ts.map +0 -1
  1077. package/dist/rendering/threejs-compatibility/performance/FrustumCulling.js +0 -5
  1078. package/dist/rendering/threejs-compatibility/performance/FrustumCulling.js.map +0 -1
  1079. package/dist/rendering/threejs-compatibility/performance/Instancing.d.ts +0 -7
  1080. package/dist/rendering/threejs-compatibility/performance/Instancing.d.ts.map +0 -1
  1081. package/dist/rendering/threejs-compatibility/performance/Instancing.js +0 -10
  1082. package/dist/rendering/threejs-compatibility/performance/Instancing.js.map +0 -1
  1083. package/dist/rendering/threejs-compatibility/performance/LODSystem.d.ts +0 -9
  1084. package/dist/rendering/threejs-compatibility/performance/LODSystem.d.ts.map +0 -1
  1085. package/dist/rendering/threejs-compatibility/performance/LODSystem.js +0 -11
  1086. package/dist/rendering/threejs-compatibility/performance/LODSystem.js.map +0 -1
  1087. package/dist/rendering/threejs-compatibility/performance/OcclusionCulling.d.ts +0 -3
  1088. package/dist/rendering/threejs-compatibility/performance/OcclusionCulling.d.ts.map +0 -1
  1089. package/dist/rendering/threejs-compatibility/performance/OcclusionCulling.js +0 -5
  1090. package/dist/rendering/threejs-compatibility/performance/OcclusionCulling.js.map +0 -1
  1091. package/dist/rendering/threejs-compatibility/performance/RaycastAcceleration.d.ts +0 -8
  1092. package/dist/rendering/threejs-compatibility/performance/RaycastAcceleration.d.ts.map +0 -1
  1093. package/dist/rendering/threejs-compatibility/performance/RaycastAcceleration.js +0 -11
  1094. package/dist/rendering/threejs-compatibility/performance/RaycastAcceleration.js.map +0 -1
  1095. package/dist/rendering/threejs-compatibility/performance/RendererProfiler.d.ts +0 -11
  1096. package/dist/rendering/threejs-compatibility/performance/RendererProfiler.d.ts.map +0 -1
  1097. package/dist/rendering/threejs-compatibility/performance/RendererProfiler.js +0 -10
  1098. package/dist/rendering/threejs-compatibility/performance/RendererProfiler.js.map +0 -1
  1099. package/dist/rendering/threejs-compatibility/performance/TextureStreaming.d.ts +0 -7
  1100. package/dist/rendering/threejs-compatibility/performance/TextureStreaming.d.ts.map +0 -1
  1101. package/dist/rendering/threejs-compatibility/performance/TextureStreaming.js +0 -10
  1102. package/dist/rendering/threejs-compatibility/performance/TextureStreaming.js.map +0 -1
  1103. package/dist/rendering/threejs-compatibility/performance/index.d.ts +0 -13
  1104. package/dist/rendering/threejs-compatibility/performance/index.d.ts.map +0 -1
  1105. package/dist/rendering/threejs-compatibility/performance/index.js +0 -9
  1106. package/dist/rendering/threejs-compatibility/performance/index.js.map +0 -1
  1107. package/dist/rendering/threejs-compatibility/postprocess/BloomPass.d.ts +0 -9
  1108. package/dist/rendering/threejs-compatibility/postprocess/BloomPass.d.ts.map +0 -1
  1109. package/dist/rendering/threejs-compatibility/postprocess/BloomPass.js +0 -14
  1110. package/dist/rendering/threejs-compatibility/postprocess/BloomPass.js.map +0 -1
  1111. package/dist/rendering/threejs-compatibility/postprocess/ColorGradingPass.d.ts +0 -10
  1112. package/dist/rendering/threejs-compatibility/postprocess/ColorGradingPass.d.ts.map +0 -1
  1113. package/dist/rendering/threejs-compatibility/postprocess/ColorGradingPass.js +0 -16
  1114. package/dist/rendering/threejs-compatibility/postprocess/ColorGradingPass.js.map +0 -1
  1115. package/dist/rendering/threejs-compatibility/postprocess/DepthOfFieldPass.d.ts +0 -9
  1116. package/dist/rendering/threejs-compatibility/postprocess/DepthOfFieldPass.d.ts.map +0 -1
  1117. package/dist/rendering/threejs-compatibility/postprocess/DepthOfFieldPass.js +0 -19
  1118. package/dist/rendering/threejs-compatibility/postprocess/DepthOfFieldPass.js.map +0 -1
  1119. package/dist/rendering/threejs-compatibility/postprocess/EffectComposer.d.ts +0 -7
  1120. package/dist/rendering/threejs-compatibility/postprocess/EffectComposer.d.ts.map +0 -1
  1121. package/dist/rendering/threejs-compatibility/postprocess/EffectComposer.js +0 -11
  1122. package/dist/rendering/threejs-compatibility/postprocess/EffectComposer.js.map +0 -1
  1123. package/dist/rendering/threejs-compatibility/postprocess/FXAAPass.d.ts +0 -7
  1124. package/dist/rendering/threejs-compatibility/postprocess/FXAAPass.d.ts.map +0 -1
  1125. package/dist/rendering/threejs-compatibility/postprocess/FXAAPass.js +0 -10
  1126. package/dist/rendering/threejs-compatibility/postprocess/FXAAPass.js.map +0 -1
  1127. package/dist/rendering/threejs-compatibility/postprocess/MotionBlurPass.d.ts +0 -9
  1128. package/dist/rendering/threejs-compatibility/postprocess/MotionBlurPass.d.ts.map +0 -1
  1129. package/dist/rendering/threejs-compatibility/postprocess/MotionBlurPass.js +0 -18
  1130. package/dist/rendering/threejs-compatibility/postprocess/MotionBlurPass.js.map +0 -1
  1131. package/dist/rendering/threejs-compatibility/postprocess/OutlinePass.d.ts +0 -9
  1132. package/dist/rendering/threejs-compatibility/postprocess/OutlinePass.d.ts.map +0 -1
  1133. package/dist/rendering/threejs-compatibility/postprocess/OutlinePass.js +0 -19
  1134. package/dist/rendering/threejs-compatibility/postprocess/OutlinePass.js.map +0 -1
  1135. package/dist/rendering/threejs-compatibility/postprocess/PostProcessTypes.d.ts +0 -42
  1136. package/dist/rendering/threejs-compatibility/postprocess/PostProcessTypes.d.ts.map +0 -1
  1137. package/dist/rendering/threejs-compatibility/postprocess/PostProcessTypes.js +0 -123
  1138. package/dist/rendering/threejs-compatibility/postprocess/PostProcessTypes.js.map +0 -1
  1139. package/dist/rendering/threejs-compatibility/postprocess/RenderPass.d.ts +0 -7
  1140. package/dist/rendering/threejs-compatibility/postprocess/RenderPass.d.ts.map +0 -1
  1141. package/dist/rendering/threejs-compatibility/postprocess/RenderPass.js +0 -8
  1142. package/dist/rendering/threejs-compatibility/postprocess/RenderPass.js.map +0 -1
  1143. package/dist/rendering/threejs-compatibility/postprocess/SMAAPass.d.ts +0 -7
  1144. package/dist/rendering/threejs-compatibility/postprocess/SMAAPass.d.ts.map +0 -1
  1145. package/dist/rendering/threejs-compatibility/postprocess/SMAAPass.js +0 -10
  1146. package/dist/rendering/threejs-compatibility/postprocess/SMAAPass.js.map +0 -1
  1147. package/dist/rendering/threejs-compatibility/postprocess/SSAOPass.d.ts +0 -9
  1148. package/dist/rendering/threejs-compatibility/postprocess/SSAOPass.d.ts.map +0 -1
  1149. package/dist/rendering/threejs-compatibility/postprocess/SSAOPass.js +0 -19
  1150. package/dist/rendering/threejs-compatibility/postprocess/SSAOPass.js.map +0 -1
  1151. package/dist/rendering/threejs-compatibility/postprocess/ShaderPass.d.ts +0 -9
  1152. package/dist/rendering/threejs-compatibility/postprocess/ShaderPass.d.ts.map +0 -1
  1153. package/dist/rendering/threejs-compatibility/postprocess/ShaderPass.js +0 -11
  1154. package/dist/rendering/threejs-compatibility/postprocess/ShaderPass.js.map +0 -1
  1155. package/dist/rendering/threejs-compatibility/postprocess/TAAPass.d.ts +0 -7
  1156. package/dist/rendering/threejs-compatibility/postprocess/TAAPass.d.ts.map +0 -1
  1157. package/dist/rendering/threejs-compatibility/postprocess/TAAPass.js +0 -10
  1158. package/dist/rendering/threejs-compatibility/postprocess/TAAPass.js.map +0 -1
  1159. package/dist/rendering/threejs-compatibility/postprocess/VignettePass.d.ts +0 -9
  1160. package/dist/rendering/threejs-compatibility/postprocess/VignettePass.d.ts.map +0 -1
  1161. package/dist/rendering/threejs-compatibility/postprocess/VignettePass.js +0 -14
  1162. package/dist/rendering/threejs-compatibility/postprocess/VignettePass.js.map +0 -1
  1163. package/dist/rendering/threejs-compatibility/postprocess/index.d.ts +0 -16
  1164. package/dist/rendering/threejs-compatibility/postprocess/index.d.ts.map +0 -1
  1165. package/dist/rendering/threejs-compatibility/postprocess/index.js +0 -15
  1166. package/dist/rendering/threejs-compatibility/postprocess/index.js.map +0 -1
  1167. package/dist/rendering/threejs-compatibility/shaders/NodeMaterial.d.ts +0 -14
  1168. package/dist/rendering/threejs-compatibility/shaders/NodeMaterial.d.ts.map +0 -1
  1169. package/dist/rendering/threejs-compatibility/shaders/NodeMaterial.js +0 -15
  1170. package/dist/rendering/threejs-compatibility/shaders/NodeMaterial.js.map +0 -1
  1171. package/dist/rendering/threejs-compatibility/shaders/RawShaderMaterial.d.ts +0 -6
  1172. package/dist/rendering/threejs-compatibility/shaders/RawShaderMaterial.d.ts.map +0 -1
  1173. package/dist/rendering/threejs-compatibility/shaders/RawShaderMaterial.js +0 -6
  1174. package/dist/rendering/threejs-compatibility/shaders/RawShaderMaterial.js.map +0 -1
  1175. package/dist/rendering/threejs-compatibility/shaders/ShaderDiagnostics.d.ts +0 -7
  1176. package/dist/rendering/threejs-compatibility/shaders/ShaderDiagnostics.d.ts.map +0 -1
  1177. package/dist/rendering/threejs-compatibility/shaders/ShaderDiagnostics.js +0 -12
  1178. package/dist/rendering/threejs-compatibility/shaders/ShaderDiagnostics.js.map +0 -1
  1179. package/dist/rendering/threejs-compatibility/shaders/ShaderMaterial.d.ts +0 -12
  1180. package/dist/rendering/threejs-compatibility/shaders/ShaderMaterial.d.ts.map +0 -1
  1181. package/dist/rendering/threejs-compatibility/shaders/ShaderMaterial.js +0 -20
  1182. package/dist/rendering/threejs-compatibility/shaders/ShaderMaterial.js.map +0 -1
  1183. package/dist/rendering/threejs-compatibility/shaders/ThreeCompatShaderChunks.d.ts +0 -7
  1184. package/dist/rendering/threejs-compatibility/shaders/ThreeCompatShaderChunks.d.ts.map +0 -1
  1185. package/dist/rendering/threejs-compatibility/shaders/ThreeCompatShaderChunks.js +0 -7
  1186. package/dist/rendering/threejs-compatibility/shaders/ThreeCompatShaderChunks.js.map +0 -1
  1187. package/dist/rendering/threejs-compatibility/shaders/Uniforms.d.ts +0 -8
  1188. package/dist/rendering/threejs-compatibility/shaders/Uniforms.d.ts.map +0 -1
  1189. package/dist/rendering/threejs-compatibility/shaders/Uniforms.js +0 -14
  1190. package/dist/rendering/threejs-compatibility/shaders/Uniforms.js.map +0 -1
  1191. package/dist/rendering/threejs-compatibility/shaders/index.d.ts +0 -10
  1192. package/dist/rendering/threejs-compatibility/shaders/index.d.ts.map +0 -1
  1193. package/dist/rendering/threejs-compatibility/shaders/index.js +0 -7
  1194. package/dist/rendering/threejs-compatibility/shaders/index.js.map +0 -1
  1195. package/dist/rendering/threejs-compatibility/vfx/GPUPointCloud.d.ts +0 -7
  1196. package/dist/rendering/threejs-compatibility/vfx/GPUPointCloud.d.ts.map +0 -1
  1197. package/dist/rendering/threejs-compatibility/vfx/GPUPointCloud.js +0 -12
  1198. package/dist/rendering/threejs-compatibility/vfx/GPUPointCloud.js.map +0 -1
  1199. package/dist/rendering/threejs-compatibility/vfx/LineRenderer.d.ts +0 -10
  1200. package/dist/rendering/threejs-compatibility/vfx/LineRenderer.d.ts.map +0 -1
  1201. package/dist/rendering/threejs-compatibility/vfx/LineRenderer.js +0 -7
  1202. package/dist/rendering/threejs-compatibility/vfx/LineRenderer.js.map +0 -1
  1203. package/dist/rendering/threejs-compatibility/vfx/ParticleSystem.d.ts +0 -12
  1204. package/dist/rendering/threejs-compatibility/vfx/ParticleSystem.d.ts.map +0 -1
  1205. package/dist/rendering/threejs-compatibility/vfx/ParticleSystem.js +0 -15
  1206. package/dist/rendering/threejs-compatibility/vfx/ParticleSystem.js.map +0 -1
  1207. package/dist/rendering/threejs-compatibility/vfx/SpriteSystem.d.ts +0 -11
  1208. package/dist/rendering/threejs-compatibility/vfx/SpriteSystem.d.ts.map +0 -1
  1209. package/dist/rendering/threejs-compatibility/vfx/SpriteSystem.js +0 -7
  1210. package/dist/rendering/threejs-compatibility/vfx/SpriteSystem.js.map +0 -1
  1211. package/dist/rendering/threejs-compatibility/vfx/TrailRenderer.d.ts +0 -5
  1212. package/dist/rendering/threejs-compatibility/vfx/TrailRenderer.d.ts.map +0 -1
  1213. package/dist/rendering/threejs-compatibility/vfx/TrailRenderer.js +0 -9
  1214. package/dist/rendering/threejs-compatibility/vfx/TrailRenderer.js.map +0 -1
  1215. package/dist/rendering/threejs-compatibility/vfx/VFXDiagnostics.d.ts +0 -21
  1216. package/dist/rendering/threejs-compatibility/vfx/VFXDiagnostics.d.ts.map +0 -1
  1217. package/dist/rendering/threejs-compatibility/vfx/VFXDiagnostics.js +0 -12
  1218. package/dist/rendering/threejs-compatibility/vfx/VFXDiagnostics.js.map +0 -1
  1219. package/dist/rendering/threejs-compatibility/vfx/index.d.ts +0 -10
  1220. package/dist/rendering/threejs-compatibility/vfx/index.d.ts.map +0 -1
  1221. package/dist/rendering/threejs-compatibility/vfx/index.js +0 -7
  1222. package/dist/rendering/threejs-compatibility/vfx/index.js.map +0 -1
  1223. package/dist/scripting/AdaptiveDifficultyFixtures.d.ts +0 -58
  1224. package/dist/scripting/AdaptiveDifficultyFixtures.d.ts.map +0 -1
  1225. package/dist/scripting/AdaptiveDifficultyFixtures.js +0 -228
  1226. package/dist/scripting/AdaptiveDifficultyFixtures.js.map +0 -1
  1227. package/dist/scripting/AnalyticsPrivacyFixtures.d.ts +0 -63
  1228. package/dist/scripting/AnalyticsPrivacyFixtures.d.ts.map +0 -1
  1229. package/dist/scripting/AnalyticsPrivacyFixtures.js +0 -120
  1230. package/dist/scripting/AnalyticsPrivacyFixtures.js.map +0 -1
  1231. package/dist/scripting/CartoonNodeCategories.d.ts +0 -3
  1232. package/dist/scripting/CartoonNodeCategories.d.ts.map +0 -1
  1233. package/dist/scripting/CartoonNodeCategories.js +0 -9
  1234. package/dist/scripting/CartoonNodeCategories.js.map +0 -1
  1235. package/dist/scripting/CartoonVisualNodes.d.ts +0 -3
  1236. package/dist/scripting/CartoonVisualNodes.d.ts.map +0 -1
  1237. package/dist/scripting/CartoonVisualNodes.js +0 -41
  1238. package/dist/scripting/CartoonVisualNodes.js.map +0 -1
  1239. package/dist/scripting/CloudServiceFixtures.d.ts +0 -81
  1240. package/dist/scripting/CloudServiceFixtures.d.ts.map +0 -1
  1241. package/dist/scripting/CloudServiceFixtures.js +0 -144
  1242. package/dist/scripting/CloudServiceFixtures.js.map +0 -1
  1243. package/dist/scripting/CulturalBehaviorFixtures.d.ts +0 -75
  1244. package/dist/scripting/CulturalBehaviorFixtures.d.ts.map +0 -1
  1245. package/dist/scripting/CulturalBehaviorFixtures.js +0 -180
  1246. package/dist/scripting/CulturalBehaviorFixtures.js.map +0 -1
  1247. package/dist/scripting/LearningAgentFixtures.d.ts +0 -60
  1248. package/dist/scripting/LearningAgentFixtures.d.ts.map +0 -1
  1249. package/dist/scripting/LearningAgentFixtures.js +0 -122
  1250. package/dist/scripting/LearningAgentFixtures.js.map +0 -1
  1251. package/dist/scripting/NetworkReplicationFixtures.d.ts +0 -82
  1252. package/dist/scripting/NetworkReplicationFixtures.d.ts.map +0 -1
  1253. package/dist/scripting/NetworkReplicationFixtures.js +0 -330
  1254. package/dist/scripting/NetworkReplicationFixtures.js.map +0 -1
  1255. package/dist/scripting/PlayerBehaviorTelemetryFixtures.d.ts +0 -74
  1256. package/dist/scripting/PlayerBehaviorTelemetryFixtures.d.ts.map +0 -1
  1257. package/dist/scripting/PlayerBehaviorTelemetryFixtures.js +0 -189
  1258. package/dist/scripting/PlayerBehaviorTelemetryFixtures.js.map +0 -1
  1259. package/dist/scripting/ProceduralContentAdaptationFixtures.d.ts +0 -52
  1260. package/dist/scripting/ProceduralContentAdaptationFixtures.d.ts.map +0 -1
  1261. package/dist/scripting/ProceduralContentAdaptationFixtures.js +0 -149
  1262. package/dist/scripting/ProceduralContentAdaptationFixtures.js.map +0 -1
@@ -1,10 +1,54 @@
1
- import { PhysicsDebugDraw, PhysicsStepper, PhysicsWorld, ScenePhysicsBridge, Shape as PhysicsShapeFactory } from "../../physics/index.js";
2
- import { createExternalParityEnvironmentLighting, Geometry, IndexBuffer, PBRMaterial, ProductionRuntimeRenderer, VertexBuffer, VertexFormat } from "../../rendering/index.js";
1
+ /*
2
+ * WS-2.2 — module-scope physics values come from the SOLVERLESS entry.
3
+ *
4
+ * `Shape`, `PhysicsStepper`, `ScenePhysicsBridge` and `PhysicsDebugDraw` are solver-free: each
5
+ * imports `PhysicsWorld` as a *type* only. But reaching them through `@aura3d/physics` — a chain of
6
+ * `export *` that includes `PhysicsWorld` — dragged in the physical adapter, so a scene with no
7
+ * bodies still downloaded the solver.
8
+ *
9
+ * This is a different defect from eager construction, which was already fixed (see `:9832`). A lazy
10
+ * `new PhysicsWorld()` still leaves a static `import`, and a bundler keeps the module either way.
11
+ * Deferring the *import* is what removes the bytes. `PhysicsWorld` is now loaded by
12
+ * `await import("../../physics/index.js")` at the points that actually simulate.
13
+ */
14
+ import { PhysicsDebugDraw, PhysicsStepper, ScenePhysicsBridge, Shape as PhysicsShapeFactory } from "../../physics/solverless.js";
15
+ /*
16
+ * WS-2.2 — the solver, from a NARROW entry rather than the physics barrel.
17
+ *
18
+ * Static on purpose. `app.physics` is documented and tested as live synchronously for every app, so
19
+ * `createAuraApp` cannot await a solver, and R7 forbids breaking that to save bytes. What this does
20
+ * avoid is the barrel: `@aura3d/physics` is a chain of `export *` that also carries `HitboxWorld`,
21
+ * `CharacterController`, `KinematicBody`, arcade vehicle telemetry, `NarrowPhase` and six fixture modules, all
22
+ * of which arrived just to reach one class.
23
+ */
24
+ import { PhysicsWorld } from "../../physics/world.js";
25
+ import { createExternalParityEnvironmentLighting, Geometry, IndexBuffer, InstancedPBRMaterial, PBRMaterial, ProductionRuntimeRenderer, srgbToLinearChannel, VertexBuffer, VertexFormat } from "../../rendering/index.js";
3
26
  import { DirectionalLight, PointLight, SpotLight } from "../../scene/index.js";
4
- import { createTypedGLBActor } from "../production-runtime/TypedGLBActor.js";
27
+ import { lookAtMat4, multiplyMat4, orthographicMat4, perspectiveMat4 } from "../../scene/MathTypes.js";
5
28
  import { AURA_NORMALIZED_MODEL_MAX_DIMENSION, boundsFromAsset, boundsHeight, boundsMaxDimension, boundsSize } from "./SceneGroundingUtils.js";
6
29
  import { createWorldLabelLayer } from "./WorldLabelRenderer.js";
30
+ import { createAuraText3DGeometry, defineAuraCustomGeometry, selectAuraRootLodLevel } from "./RootGeometry.js";
31
+ export * from "./RootGeometry.js";
7
32
  export * from "./SpatialAnchoring.js";
33
+ export * from "./PhysicsRuntime.js";
34
+ /**
35
+ * WS-2.4: mesh surface queries on the public surface.
36
+ *
37
+ * Re-exported from `@aura3d/physics` so grounding anything to a mesh is a one-liner for any
38
+ * genre, from `@aura3d/engine` alone. Without this a route wanting real per-point ground
39
+ * height had to either deep-import `@aura3d/physics/src` (banned by the lint rule) or
40
+ * hand-roll an analytic approximation — which is exactly what every racing route did, and
41
+ * why wheels sank through visible road.
42
+ */
43
+ /*
44
+ * WS-2.2 — re-exported from the SOLVERLESS entry, not the physics barrel.
45
+ *
46
+ * These are geometry queries: `MeshBVH` and `SurfaceQuery` import only `Shape`'s types. Re-exporting
47
+ * them from `@aura3d/physics` made this barrel a static consumer of the whole solver, so grounding a
48
+ * wheel on a mesh reached the physical solver. Same symbols, same public names.
49
+ */
50
+ export { buildMeshBVH, createMeshSurfaceQuery, raycastMesh } from "../../physics/solverless.js";
51
+ import { createPhysicsRuntime } from "./PhysicsRuntime.js";
8
52
  export * from "./FocusSelection.js";
9
53
  export * from "./WorldLabelRenderer.js";
10
54
  export * from "./VehicleChassis.js";
@@ -17,14 +61,23 @@ export * from "./FrameEncoder.js";
17
61
  export * from "./BrowserFrameCaptureAdapter.js";
18
62
  export * from "./MediaRecorderFrameEncoder.js";
19
63
  export * from "./WebCodecsFrameEncoder.js";
20
- export * from "./FfmpegFrameEncoder.js";
21
- export * from "./PngSequenceEncoder.js";
22
- export * from "./AudioMuxer.js";
64
+ /*
65
+ * WS-2.3 — `FfmpegFrameEncoder` is deliberately NOT re-exported here.
66
+ *
67
+ * It is the only file in the 37-file media surface that reaches `node:` builtins (`child_process` to
68
+ * spawn ffmpeg; `fs/promises`/`os`/`path` to stage frames). Re-exporting it put Node builtins in every
69
+ * browser bundle of this entry point, which is why `tools/bundle-size` had to mark four `node:`
70
+ * specifiers external "for every browser bundle measurement" — a workaround for a dependency that
71
+ * should not have been in the browser graph. esbuild resolves `await import()` at build time whether or
72
+ * not the branch can run.
73
+ *
74
+ * Node consumers import `@aura3d/engine/media-node`. Enforced by `tools/browser-entry-purity`, which
75
+ * bundles every browser entry with no `node:` externals so a reachable builtin fails the build.
76
+ */
23
77
  export { GameInspector, createGameInspector } from "./GameInspector.js";
24
78
  import { createGameInspector } from "./GameInspector.js";
25
79
  export { createGameAudio } from "../game/GameAudio.js";
26
80
  export * from "./RenderProgressTracker.js";
27
- export * from "./VideoExportPipeline.js";
28
81
  export * from "./AudioVisemeAnalyzer.js";
29
82
  export * from "./ExternalPhonemeAnalyzer.js";
30
83
  export * from "./WaveformVisualizer.js";
@@ -36,12 +89,7 @@ export * from "./CameraPresetLibrary.js";
36
89
  export * from "./ShotCompositionRules.js";
37
90
  export * from "./CameraChoreographer.js";
38
91
  export * from "./CameraPathEditor.js";
39
- export * from "./CaptionExporter.js";
40
92
  export * from "./ThumbnailGenerator.js";
41
- export * from "./YouTubeMetadataGenerator.js";
42
- export * from "./YouTubeUploadAdapter.js";
43
- export * from "./PublishingPipeline.js";
44
- export * from "./CloudRenderAdapter.js";
45
93
  export * from "./BatchEpisodeRenderer.js";
46
94
  export * from "./AnimationAssetManifest.js";
47
95
  export * from "./SceneGroundingUtils.js";
@@ -60,7 +108,7 @@ export * from "./AnimationMotionQuality.js";
60
108
  export * from "./AnimationRouteProof.js";
61
109
  export * from "./AnimationEpisodePackage.js";
62
110
  import { createFrameLoop } from "./FrameLoop.js";
63
- import { createCombatWorld, createGameCameraDirector, createGameEffects, applyGameCombatEventsToRuntime, createGameAccessibilityFocus, createGameAccessibilityLabel, createGameAccessibilityRuntimeSettings, createGameEventLog, createGameHighContrastSource, createGameHudBindings, createGameHudComboBinding, createGameHudCheckpointBinding, createGameHudDebugToggleBinding, createGameHudEventLogBinding, createGameHudHealthBinding, createGameHudLivesBinding, createGameHudMeterBinding, createGameHudObjectiveBinding, createGameHudRoundBinding, createGameHudScoreBinding, createGameHudSnapshot, createGameHudTimerBinding, createGameHudValueBinding, createGameBoxCollider, createGameCapsuleCollider, createGameColliderDebugGeometry, createGameCombatDebugGeometry, createGameCollisionWorld, createGameDebugOverlayData, createGameDebugSceneNodes, createGameHitboxDebugGeometry, createGameSimulation, exportGameInputReplay, createGameFighting2DRules, createGameInput, createGameInputReplay, createGameInputReplayDriver, importGameInputReplay, createGameJumpAssist, createGameKinematicBody, createGamePauseControlsSource, createGameRectCollider, createGameReducedFlashSource, createGameReducedMotionSource, createGameSphereCollider, createGameTouchControlLayout, gameColliderAabb, gameColliders, gameEffectPresets, gameGuardboxes, gameHitboxes, gameHurtboxes, gameInputReplayEventsAt, gamePushboxes, runGameSimulation, gameTriggerVolumes } from "./GameRuntime.js";
111
+ import { createCombatWorld, createGameCameraDirector, createGameEffects, applyGameCombatEventsToRuntime, createGameAccessibilityFocus, createGameAccessibilityLabel, createGameAccessibilityRuntimeSettings, createGameEventLog, createGameHighContrastSource, createGameHudBindings, createGameHudComboBinding, createGameHudCheckpointBinding, createGameHudDebugToggleBinding, createGameHudEventLogBinding, createGameHudHealthBinding, createGameHudLivesBinding, createGameHudMeterBinding, createGameHudObjectiveBinding, createGameHudRoundBinding, createGameHudScoreBinding, createGameHudSnapshot, createGameHudTimerBinding, createGameHudValueBinding, createGameBoxCollider, createGameCapsuleCollider, createGameColliderDebugGeometry, createGameCombatDebugGeometry, createGameCollisionWorld, createGamePlanarCollisionWorld, createGameDebugOverlayData, createGameDebugSceneNodes, createGameHitboxDebugGeometry, createGameSimulation, exportGameInputReplay, createGameFighting2DRules, createGameInput, createGameInputReplay, createGameInputReplayDriver, importGameInputReplay, createGameJumpAssist, createGameKinematicBody, createGamePauseControlsSource, createGameRectCollider, createGameReducedFlashSource, createGameReducedMotionSource, createGameSphereCollider, createGameTouchControlLayout, gameColliderAabb, gameColliders, gameEffectPresets, gameGuardboxes, gameHitboxes, gameHurtboxes, gameInputReplayEventsAt, gamePushboxes, runGameSimulation, gameTriggerVolumes } from "./GameRuntime.js";
64
112
  import { collectGameRuntimeEvidence as collectGameRuntimeEvidenceV105 } from "./GameEvidence.js";
65
113
  import { calculateRuntimeNodeBounds } from "./RuntimeNodeHandle.js";
66
114
  import { createRuntimeNodeSpec } from "./GameSceneBridge.js";
@@ -188,7 +236,8 @@ export function model(asset, options = {}) {
188
236
  targetHeight: options.targetHeight,
189
237
  targetMaxDimension: options.targetMaxDimension,
190
238
  targetLength: options.targetLength,
191
- physics: options.physics
239
+ physics: options.physics,
240
+ hiddenNodeNames: options.hiddenNodeNames
192
241
  });
193
242
  }
194
243
  export function unsafeModelUrl(url, options = {}) {
@@ -235,7 +284,12 @@ function primitive(primitiveName, options = {}) {
235
284
  size: options.size,
236
285
  castShadow: options.castShadow ?? (primitiveName !== "plane" && options.material?.emissive === undefined),
237
286
  receiveShadow: options.receiveShadow ?? true,
238
- physics: options.physics
287
+ physics: options.physics,
288
+ instances: options.instances,
289
+ instanceColors: options.instanceColors,
290
+ geometry: options.geometry,
291
+ text3D: options.text3D,
292
+ lod: options.lod
239
293
  });
240
294
  }
241
295
  function sceneNodeFromInput(node) {
@@ -262,6 +316,43 @@ export const primitives = {
262
316
  capsule: (options) => primitive("capsule", options),
263
317
  torus: (options) => primitive("torus", options)
264
318
  };
319
+ function instancedPrimitive(primitiveName, options) {
320
+ if (options.transforms.length === 0)
321
+ throw new Error("Aura3D instancing requires at least one transform.");
322
+ if (options.colors && options.colors.length !== options.transforms.length)
323
+ throw new Error("Aura3D instance color count must match transform count.");
324
+ return primitive(primitiveName, { ...options, instances: options.transforms, instanceColors: options.colors });
325
+ }
326
+ export const instances = {
327
+ box: (options) => instancedPrimitive("box", options),
328
+ sphere: (options) => instancedPrimitive("sphere", options),
329
+ plane: (options) => instancedPrimitive("plane", options),
330
+ cylinder: (options) => instancedPrimitive("cylinder", options),
331
+ capsule: (options) => instancedPrimitive("capsule", options),
332
+ torus: (options) => instancedPrimitive("torus", options)
333
+ };
334
+ export const geometry = {
335
+ define: defineAuraCustomGeometry,
336
+ custom: (spec, options = {}) => primitive("custom", { ...options, geometry: defineAuraCustomGeometry(spec) })
337
+ };
338
+ export function text3D(text, options = {}) {
339
+ const built = createAuraText3DGeometry(text, options);
340
+ return primitive("custom", { ...options, geometry: built.geometry, text3D: { text: built.text, glyphCount: built.glyphCount, unsupportedCharacters: built.unsupportedCharacters, method: built.method } });
341
+ }
342
+ export function distanceLod(options) {
343
+ if (options.levels.length === 0)
344
+ throw new Error("Aura3D distance LOD requires at least one level.");
345
+ selectAuraRootLodLevel(0, options.levels, undefined, options.hysteresis ?? 0);
346
+ const first = options.levels[0];
347
+ if (!first.primitive && !first.geometry)
348
+ throw new Error("Every Aura3D LOD level requires a primitive or custom geometry.");
349
+ return primitive(first.geometry ? "custom" : first.primitive, {
350
+ ...options,
351
+ geometry: first.geometry,
352
+ material: first.material ?? options.material,
353
+ lod: { levels: options.levels, hysteresis: options.hysteresis }
354
+ });
355
+ }
265
356
  export const groups = {
266
357
  create: group,
267
358
  flatten: (nodes) => flattenSceneNodes(nodes)
@@ -1606,7 +1697,7 @@ const rendererQualityProfiles = {
1606
1697
  kind: "aura-renderer-quality-profile",
1607
1698
  id: "safe-basic",
1608
1699
  label: "Safe Basic",
1609
- rendererMode: "safe-basic",
1700
+ rendererMode: "production",
1610
1701
  status: "supported",
1611
1702
  antialiasing: "msaa",
1612
1703
  pixelRatio: 1,
@@ -1615,7 +1706,7 @@ const rendererQualityProfiles = {
1615
1706
  requestedFeatures: ["typed models", "primitives", "basic particles", "base-color textures", "runtime nodes"],
1616
1707
  supportedInRoot: ["typed models", "primitives", "basic particles", "base-color textures", "runtime nodes"],
1617
1708
  blockedInRoot: ["production PBR parity", "skinned animation mixer", "native WebGPU compute", "postprocess pass chain"],
1618
- claimBoundary: "Root createAuraApp safe path. Use this for public examples unless a browser test proves a stronger profile."
1709
+ claimBoundary: "Root createAuraApp uses the production renderer with the conservative safe-basic feature profile. Claims still require route-specific browser evidence."
1619
1710
  },
1620
1711
  production: {
1621
1712
  kind: "aura-renderer-quality-profile",
@@ -1684,8 +1775,6 @@ function analyzeProductionBridgeEligibility(nodes) {
1684
1775
  const primitiveCount = nodes.filter((node) => node.kind === "primitive").length;
1685
1776
  const effectCount = nodes.filter((node) => node.kind === "effect").length;
1686
1777
  const reasons = [];
1687
- if (typedModelCount < 1)
1688
- reasons.push("production bridge requires at least one typed GLB from generated aura-assets");
1689
1778
  if (unsafeModelCount > 0)
1690
1779
  reasons.push("unsafeModelUrl and remote/raw model URLs are blocked from the production bridge");
1691
1780
  if (inlineModelCount > 0)
@@ -1748,10 +1837,10 @@ function createRendererDiagnosticReport(snapshot, runtime, rendererOptions) {
1748
1837
  if (postprocessRequested && runtime?.mounted && !runtimePostprocess?.pixelBacked)
1749
1838
  warnings.push("postprocess was requested but the runtime composer did not initialize a pixel-backed pass");
1750
1839
  if (rendererSelection.mode === "production" && !runtime?.mounted && productionEligibility.eligible) {
1751
- warnings.push(`Renderer profile "${rendererSelection.profile.id}" can use the typed-GLB production bridge after createAuraApp mounts; inspect app.diagnostics().renderer.runtime for pixel-backed status.`);
1840
+ warnings.push(`Renderer profile "${rendererSelection.profile.id}" will use the production renderer after createAuraApp mounts; inspect app.diagnostics().renderer.runtime for pixel-backed status.`);
1752
1841
  }
1753
1842
  if (rendererSelection.mode === "production" && !productionEligibility.eligible) {
1754
- warnings.push(`Renderer profile "${rendererSelection.profile.id}" will use safe-basic fallback for this scene: ${productionEligibility.reasons.join("; ")}.`);
1843
+ warnings.push(`Renderer profile "${rendererSelection.profile.id}" cannot mount this scene on the production renderer: ${productionEligibility.reasons.join("; ")}.`);
1755
1844
  }
1756
1845
  if (rendererSelection.profile.status === "fallback-only") {
1757
1846
  warnings.push(`Renderer profile "${rendererSelection.profile.id}" is a request profile; public claims require route-specific runtime diagnostics and screenshot proof.`);
@@ -1837,6 +1926,7 @@ function createRendererDiagnosticReport(snapshot, runtime, rendererOptions) {
1837
1926
  requestedPasses,
1838
1927
  actualPasses: runtimePostprocess?.actualPasses ?? [],
1839
1928
  fallbackPasses: runtimePostprocess?.fallbackPasses ?? [],
1929
+ targetFormat: runtimePostprocess?.targetFormat,
1840
1930
  evidence: postprocessEvidence
1841
1931
  },
1842
1932
  runtime: {
@@ -1844,7 +1934,13 @@ function createRendererDiagnosticReport(snapshot, runtime, rendererOptions) {
1844
1934
  backend: runtime?.backend ?? "scene-plan",
1845
1935
  postprocessVerified: runtimePostprocess?.pixelBacked ?? false,
1846
1936
  passNames: runtimePostprocess?.actualPasses ?? [],
1847
- warnings: runtime?.warnings ?? []
1937
+ warnings: runtime?.warnings ?? [],
1938
+ nativeInstancedSubmissions: runtime?.deviceDiagnostics?.nativeInstancedSubmissions ?? 0,
1939
+ submittedObjects: runtime?.deviceDiagnostics?.submittedObjects ?? 0,
1940
+ visibleObjects: runtime?.deviceDiagnostics?.visibleObjects ?? 0,
1941
+ culledObjects: runtime?.deviceDiagnostics?.culledObjects ?? 0,
1942
+ frustumTestedObjects: runtime?.deviceDiagnostics?.frustumTestedObjects ?? 0,
1943
+ lodSelections: runtime?.lodSelections ?? []
1848
1944
  },
1849
1945
  environment: {
1850
1946
  enabled: environmentStatus.enabled,
@@ -2254,6 +2350,7 @@ function createRuntimeScenePhysics(snapshot) {
2254
2350
  const physicsNodes = snapshot.nodes.filter((node) => (node.kind === "model" || node.kind === "primitive") && Boolean(node.physics));
2255
2351
  if (physicsNodes.length === 0)
2256
2352
  return undefined;
2353
+ // WS-2.2: solver resolved through the on-demand cache rather than a static import.
2257
2354
  const world = new PhysicsWorld({ gravity: [0, -9.81, 0], fixedDelta: 1 / 60, enableSleeping: true });
2258
2355
  const stepper = new PhysicsStepper(world.fixedDelta);
2259
2356
  const debugDraw = new PhysicsDebugDraw();
@@ -2654,6 +2751,8 @@ export const prefabs = {
2654
2751
  ...makeCityCrosswalk("zebra crosswalk west", -0.72, 0, "eastWest"),
2655
2752
  ...makeCityCrosswalk("zebra crosswalk east", 0.72, 0, "eastWest")
2656
2753
  ];
2754
+ const cityTowerTransforms = [];
2755
+ const cityTowerColors = [];
2657
2756
  const xSlots = [-4.25, -2.58, -0.95, 1.45, 3.3];
2658
2757
  const zSlots = [-4, -1.45, 1.3, 3.65];
2659
2758
  for (let index = 0; index < blocks; index += 1) {
@@ -2665,15 +2764,19 @@ export const prefabs = {
2665
2764
  const color = night
2666
2765
  ? (index % 3 === 0 ? "#1e293b" : index % 3 === 1 ? "#2d3340" : "#172233")
2667
2766
  : (index % 3 === 0 ? "#8ea2aa" : index % 3 === 1 ? "#b89b72" : "#668094");
2668
- nodes.push(primitives.box({
2669
- name: `city tower ${index + 1}`,
2670
- material: material.pbr({ color, roughness: 0.68, metallic: 0.06 })
2671
- }).position(x, height / 2, z).scale([1.08, height, 1.08]).toJSON());
2767
+ cityTowerTransforms.push({ position: [x, height / 2, z], scale: [1.08, height, 1.08] });
2768
+ cityTowerColors.push(color);
2672
2769
  if (options.litWindows !== false) {
2673
2770
  nodes.push(...makeBuildingWindowRows(x, z, height, index, timeOfDay));
2674
2771
  }
2675
2772
  nodes.push(...makeBuildingDetails(x, z, height, index, timeOfDay));
2676
2773
  }
2774
+ nodes.push(instances.box({
2775
+ name: "city tower native instanced family",
2776
+ transforms: cityTowerTransforms,
2777
+ colors: cityTowerColors,
2778
+ material: material.pbr({ color: "#ffffff", roughness: 0.68, metallic: 0.06 })
2779
+ }).toJSON());
2677
2780
  const lampPositions = [
2678
2781
  [-1.15, 0, 0.85], [1.15, 0, 0.85], [-1.15, 0, -0.85], [1.15, 0, -0.85],
2679
2782
  [-3.85, 0, -2.05], [-2.95, 0, 2.05], [2.05, 0, -2.05], [3.05, 0, 2.05],
@@ -2769,7 +2872,9 @@ export const prefabs = {
2769
2872
  const rimMaterial = material.emissive({ color: "#dbeafe", emissive: "#93c5fd", emissiveIntensity: 0.18, opacity: 0.42 });
2770
2873
  const nodes = [
2771
2874
  primitives.plane({ name: "seamless matte product hero floor", material: floorMaterial }).position(0, -0.018, -0.62).scale([3.6, 1, 2.6]).toJSON(),
2772
- primitives.plane({ name: "distant seamless product photography backdrop", material: backdropMaterial }).position(0, 1.22, -2.28).rotate(-0.08, 0, 0).scale([3.6, 1, 1.8]).toJSON(),
2875
+ primitives.plane({ name: "vertical seamless product photography backdrop", material: backdropMaterial }).position(0, 1.22, -2.28).rotate(1.5708, 0, 0).scale([6.2, 1, 2.15]).toJSON(),
2876
+ primitives.box({ name: "cool cyan studio reflection panel", material: material.emissive({ color: "#20bfe8", emissive: "#20bfe8", emissiveIntensity: 0.46 }) }).position(-2.35, 1.14, -2.18).scale([0.24, 1.38, 0.035]).toJSON(),
2877
+ primitives.box({ name: "warm amber studio reflection panel", material: material.emissive({ color: "#f0a43c", emissive: "#f0a43c", emissiveIntensity: 0.42 }) }).position(2.35, 1.14, -2.18).scale([0.24, 1.38, 0.035]).toJSON(),
2773
2878
  primitives.cylinder({ name: "low matte hero product plinth", material: plinthMaterial }).position(0, 0.255, -0.65).scale([1.46, 0.26, 1.46]).toJSON(),
2774
2879
  primitives.cylinder({ name: "soft product contact shadow from footprint", material: shadowMaterial }).position(0, 0.292, -0.65).scale([1.06, 0.01, 0.66]).toJSON(),
2775
2880
  primitives.box({ name: "subtle turntable orbit cue on product plinth", material: material.emissive({ color: "#93c5fd", emissive: "#38bdf8", emissiveIntensity: 0.22, opacity: 0.38 }) }).position(0, 0.52, -0.65).scale([1.02, 0.012, 1.02]).toJSON(),
@@ -3371,7 +3476,7 @@ function createMiniGolfStateController() {
3371
3476
  const worldSnapshot = world.snapshot();
3372
3477
  return {
3373
3478
  physicsBackend: worldSnapshot.backend.active,
3374
- deterministicReplayId: `mini-golf-cannon-v1-${shots}-${score}-${collisions}-${resets}`,
3479
+ deterministicReplayId: `mini-golf-rapier-v2-${shots}-${score}-${collisions}-${resets}`,
3375
3480
  replayFrame: worldSnapshot.stats.steps,
3376
3481
  captureTime: Number((worldSnapshot.stats.steps * world.fixedDelta).toFixed(3)),
3377
3482
  shots,
@@ -3478,187 +3583,6 @@ export const games = {
3478
3583
  export function collectGameRuntimeEvidence(app, options = {}) {
3479
3584
  return collectGameRuntimeEvidenceV105(app, options);
3480
3585
  }
3481
- function createGameInputController(options) {
3482
- const actions = options.actions;
3483
- const axes = options.axes ?? {};
3484
- const bufferMs = options.bufferMs ?? 120;
3485
- const activeBindings = new Set();
3486
- const activeActionOverrides = new Set();
3487
- const previousHeld = new Map();
3488
- const currentHeld = new Map();
3489
- const pressedEdges = new Set();
3490
- const releasedEdges = new Set();
3491
- const lastPressedAt = new Map();
3492
- const replayEvents = [];
3493
- let frame = 0;
3494
- let time = 0;
3495
- let latestSnapshot = {
3496
- kind: "aura-game-input-snapshot",
3497
- frame,
3498
- time,
3499
- activeBindings: [],
3500
- actions: {}
3501
- };
3502
- const resolveHeld = (action) => {
3503
- if (activeActionOverrides.has(action))
3504
- return true;
3505
- const bindings = actions[action] ?? [];
3506
- return bindings.some((binding) => activeBindings.has(binding));
3507
- };
3508
- const record = (type, binding) => {
3509
- replayEvents.push({ frame, time, type, binding });
3510
- };
3511
- const pressBinding = (binding, shouldRecord = true) => {
3512
- activeBindings.add(binding);
3513
- if (actions[binding])
3514
- activeActionOverrides.add(binding);
3515
- if (shouldRecord)
3516
- record("press", binding);
3517
- };
3518
- const releaseBinding = (binding, shouldRecord = true) => {
3519
- activeBindings.delete(binding);
3520
- activeActionOverrides.delete(binding);
3521
- if (shouldRecord)
3522
- record("release", binding);
3523
- };
3524
- const toSnapshot = () => {
3525
- const actionStates = {};
3526
- const nowMs = time * 1000;
3527
- for (const action of Object.keys(actions)) {
3528
- const held = currentHeld.get(action) ?? false;
3529
- actionStates[action] = {
3530
- pressed: pressedEdges.has(action),
3531
- held,
3532
- released: releasedEdges.has(action),
3533
- buffered: pressedEdges.has(action) || nowMs - (lastPressedAt.get(action) ?? Number.NEGATIVE_INFINITY) <= bufferMs,
3534
- value: held ? 1 : 0
3535
- };
3536
- }
3537
- return {
3538
- kind: "aura-game-input-snapshot",
3539
- frame,
3540
- time,
3541
- activeBindings: [...activeBindings].sort(),
3542
- actions: actionStates
3543
- };
3544
- };
3545
- const update = (dt = 1 / 60) => {
3546
- frame += 1;
3547
- time += Math.max(0, dt);
3548
- pressedEdges.clear();
3549
- releasedEdges.clear();
3550
- for (const action of Object.keys(actions)) {
3551
- const held = resolveHeld(action);
3552
- const wasHeld = previousHeld.get(action) ?? false;
3553
- currentHeld.set(action, held);
3554
- if (held && !wasHeld) {
3555
- pressedEdges.add(action);
3556
- lastPressedAt.set(action, time * 1000);
3557
- }
3558
- if (!held && wasHeld)
3559
- releasedEdges.add(action);
3560
- previousHeld.set(action, held);
3561
- }
3562
- latestSnapshot = toSnapshot();
3563
- return latestSnapshot;
3564
- };
3565
- const target = options.target ?? (typeof window !== "undefined" ? window : undefined);
3566
- const onKeyDown = (event) => {
3567
- const keyboard = event;
3568
- if (keyboard.repeat)
3569
- return;
3570
- if (keyboard.code)
3571
- pressBinding(keyboard.code);
3572
- if (keyboard.key && keyboard.key !== keyboard.code)
3573
- pressBinding(keyboard.key);
3574
- };
3575
- const onKeyUp = (event) => {
3576
- const keyboard = event;
3577
- if (keyboard.code)
3578
- releaseBinding(keyboard.code);
3579
- if (keyboard.key && keyboard.key !== keyboard.code)
3580
- releaseBinding(keyboard.key);
3581
- };
3582
- if (options.autoListen !== false && target?.addEventListener) {
3583
- target.addEventListener("keydown", onKeyDown);
3584
- target.addEventListener("keyup", onKeyUp);
3585
- }
3586
- return {
3587
- kind: "aura-game-input-plan",
3588
- actions,
3589
- axes,
3590
- bufferMs,
3591
- update,
3592
- snapshot() {
3593
- return latestSnapshot;
3594
- },
3595
- pressed(action) {
3596
- return pressedEdges.has(action);
3597
- },
3598
- held(action) {
3599
- return currentHeld.get(action) ?? resolveHeld(action);
3600
- },
3601
- released(action) {
3602
- return releasedEdges.has(action);
3603
- },
3604
- buffered(action, windowMs = bufferMs) {
3605
- return pressedEdges.has(action) || time * 1000 - (lastPressedAt.get(action) ?? Number.NEGATIVE_INFINITY) <= windowMs;
3606
- },
3607
- axis(name, negativeAction, positiveAction) {
3608
- const binding = axes[name];
3609
- const negative = negativeAction ?? binding?.negative;
3610
- const positive = positiveAction ?? binding?.positive;
3611
- if (!negative && !positive)
3612
- return this.held(name) ? 1 : 0;
3613
- return (positive && this.held(positive) ? 1 : 0) - (negative && this.held(negative) ? 1 : 0);
3614
- },
3615
- press(binding) {
3616
- pressBinding(binding);
3617
- },
3618
- release(binding) {
3619
- releaseBinding(binding);
3620
- },
3621
- setAction(action, held) {
3622
- if (held) {
3623
- activeActionOverrides.add(action);
3624
- record("press", action);
3625
- }
3626
- else {
3627
- activeActionOverrides.delete(action);
3628
- record("release", action);
3629
- }
3630
- },
3631
- recorded() {
3632
- return [...replayEvents];
3633
- },
3634
- replay(events) {
3635
- activeBindings.clear();
3636
- activeActionOverrides.clear();
3637
- for (const event of events) {
3638
- if (event.type === "press")
3639
- pressBinding(event.binding, false);
3640
- else
3641
- releaseBinding(event.binding, false);
3642
- }
3643
- return update(0);
3644
- },
3645
- clearReplay() {
3646
- replayEvents.length = 0;
3647
- },
3648
- dispose() {
3649
- if (target?.removeEventListener) {
3650
- target.removeEventListener("keydown", onKeyDown);
3651
- target.removeEventListener("keyup", onKeyUp);
3652
- }
3653
- activeBindings.clear();
3654
- activeActionOverrides.clear();
3655
- previousHeld.clear();
3656
- currentHeld.clear();
3657
- pressedEdges.clear();
3658
- releasedEdges.clear();
3659
- }
3660
- };
3661
- }
3662
3586
  export function createAuraGameRules(options = {}) {
3663
3587
  return {
3664
3588
  kind: "aura-game-rules",
@@ -4639,6 +4563,7 @@ export const game = {
4639
4563
  touchControls: createGameTouchControlLayout,
4640
4564
  kinematicBody: createGameKinematicBody,
4641
4565
  collisionWorld: createGameCollisionWorld,
4566
+ planarCollisionWorld: createGamePlanarCollisionWorld,
4642
4567
  jumpAssist: createGameJumpAssist,
4643
4568
  collider: {
4644
4569
  box: createGameBoxCollider,
@@ -5385,12 +5310,16 @@ function cityScene(options = {}) {
5385
5310
  .camera(cityCameraPreset(options.cameraPreset ?? "overview", timeOfDay));
5386
5311
  }
5387
5312
  function collectCityInstancingPlan(nodes) {
5388
- const names = groups.flatten(nodes).map((node) => "name" in node ? node.name ?? "" : "");
5313
+ const flattened = groups.flatten(nodes);
5314
+ const names = flattened.map((node) => "name" in node ? node.name ?? "" : "");
5315
+ const nativeInstanceNodes = flattened.filter((node) => node.kind === "primitive" && Boolean(node.instances?.length));
5316
+ const nativeInstances = nativeInstanceNodes.reduce((total, node) => total + (node.instances?.length ?? 0), 0);
5389
5317
  const windows = names.filter((name) => name.includes("window column")).length;
5390
5318
  const props = names.filter((name) => name.includes("bench") || name.includes("tree") || name.includes("sign") || name.includes("car body") || name.includes("traffic signal")).length;
5391
5319
  const roadMarkings = names.filter((name) => name.includes("lane marking") || name.includes("road stripe") || name.includes("crosswalk") || name.includes("turn arrow") || name.includes("bike lane")).length;
5392
5320
  const lights = names.filter((name) => name.includes("street lamp") || name.includes("headlight") || name.includes("lamp glow") || name.includes("city glow")).length;
5393
5321
  const groupsList = [
5322
+ nativeInstanceNodes.some((node) => node.name?.includes("city tower")) ? "city towers" : "",
5394
5323
  windows >= 8 ? "window columns" : "",
5395
5324
  props >= 6 ? "street props" : "",
5396
5325
  roadMarkings >= 8 ? "road markings" : "",
@@ -5398,13 +5327,15 @@ function collectCityInstancingPlan(nodes) {
5398
5327
  ].filter(Boolean);
5399
5328
  return {
5400
5329
  kind: "aura-city-instancing-plan",
5401
- rendererPath: "auraWebGL2PrimitiveBatches",
5330
+ rendererPath: "productionRuntimeNativeInstancing",
5402
5331
  windows,
5403
5332
  props,
5404
5333
  roadMarkings,
5405
5334
  lights,
5335
+ nativeInstanceGroups: nativeInstanceNodes.length,
5336
+ nativeInstances,
5406
5337
  groups: groupsList,
5407
- instanced: windows >= 8 && props >= 6 && roadMarkings >= 8 && lights >= 6
5338
+ instanced: nativeInstanceNodes.length > 0 && nativeInstances > 0
5408
5339
  };
5409
5340
  }
5410
5341
  function changedCityNodeNames(previous, next) {
@@ -5417,7 +5348,11 @@ function changedCityNodeNames(previous, next) {
5417
5348
  function validateCityVisualQA(nodes, options = {}) {
5418
5349
  const flattened = groups.flatten(nodes);
5419
5350
  const names = flattened.map((node) => "name" in node ? node.name ?? "" : "");
5420
- const buildings = names.filter((name) => name.includes("city tower")).length;
5351
+ const buildings = flattened.reduce((total, node) => {
5352
+ if (!("name" in node) || !node.name?.includes("city tower"))
5353
+ return total;
5354
+ return total + (node.kind === "primitive" && node.instances?.length ? node.instances.length : 1);
5355
+ }, 0);
5421
5356
  const windows = names.filter((name) => name.includes("window column")).length;
5422
5357
  const streets = names.filter((name) => name.includes("road") || name.includes("street") || name.includes("avenue")).length;
5423
5358
  const crosswalks = names.filter((name) => name.includes("crosswalk")).length;
@@ -5945,7 +5880,7 @@ function createSceneKitLazyLoadingPlan(id) {
5945
5880
  systems.push({ system, trigger, loadedByDefault: false, evidence });
5946
5881
  };
5947
5882
  if (id === "physicsPlayground" || id === "miniGolf") {
5948
- add("physics-backend", `${id} physics state construction`, "Cannon-backed physics is optional scene-kit work and not required for static material/chart/product scenes");
5883
+ add("physics-backend", `${id} physics state construction`, "Rapier-backed physics is isolated scene-kit work and is not required for static material, chart, or product scenes");
5949
5884
  }
5950
5885
  if (id === "productViewer") {
5951
5886
  add("product-gltf-loader", "typed product model render path", "GLTF loading is tied to typed model scenes and excluded from procedural-only scene kits");
@@ -6215,10 +6150,11 @@ export const promptRecipes = {
6215
6150
  .add(primitives.sphere({ name: "rain splash foreground", material: material.emissive({ color: "#c8f4ff", emissive: "#c8f4ff" }) }).position(-0.88, 0.035, 0.72).scale([0.07, 0.018, 0.07]))
6216
6151
  .add(primitives.sphere({ name: "rain splash key side", material: material.emissive({ color: "#ffe1ad", emissive: "#ffe1ad" }) }).position(1.14, 0.035, 0.44).scale([0.08, 0.018, 0.08]))
6217
6152
  .add(model(asset, { name: plan.subject.label }).position(-0.08, 0.02, -0.86).rotate(-0.08, -0.74, 0.02).scale(1.48))
6218
- .add(lights.ambient({ intensity: 0.07, color: "#839dc6" }))
6153
+ .add(lights.ambient({ intensity: 0.22, color: "#b4c9e8" }))
6219
6154
  .add(lights.point({ name: "hard cyan rim", position: [-2.35, 2.65, 0.85], color: "#38d6ff", intensity: 3.25 }))
6220
6155
  .add(lights.point({ name: "warm practical key", position: [2.35, 1.7, -0.25], color: "#ffd08a", intensity: 1.6 }))
6221
6156
  .add(lights.point({ name: "low floor bounce", position: [0.1, 0.45, 1.1], color: "#7edfff", intensity: 0.62 }))
6157
+ .add(lights.point({ name: "cinematic hero front fill", position: [0.15, 1.45, 3.1], color: "#e8f2ff", intensity: 5.2 }))
6222
6158
  .add(effects.rain({ intensity: 0.46, color: "#c3e6ff" }))
6223
6159
  .add(effects.fog({ density: 0.08, color: "#32435a" }))
6224
6160
  .add(effects.bloom({ intensity: 0.36, color: "#6edfff" }))
@@ -6719,10 +6655,137 @@ export function createAuraApp(target, options) {
6719
6655
  let disposed = false;
6720
6656
  let animationHandle = 0;
6721
6657
  let productionController;
6658
+ /** WS-2.9: true from the moment a WebGL mount starts until the controller arrives or fails. */
6659
+ let productionMountPending = false;
6660
+ /**
6661
+ * WS-2.5 — true when a WebGL mount was attempted and FAILED for this scene.
6662
+ *
6663
+ * Distinct from `productionMountPending`, and the distinction is the whole point. After a failed mount
6664
+ * both the pending flag and the controller are absent, which used to be indistinguishable from "this
6665
+ * scene never wanted WebGL" — so `step()` and the render loop fell through to the Canvas-2D branch and
6666
+ * painted a gradient over a scene whose renderer had just failed. Measured: 16,384 lit pixels on a
6667
+ * 128x128 canvas, i.e. the entire surface, with the real error sitting in `diagnostics().errors` where
6668
+ * nobody was looking.
6669
+ */
6670
+ let productionMountFailed = false;
6671
+ /**
6672
+ * Settles when the in-flight WebGL mount finishes, successfully or not. Backs `app.ready()`.
6673
+ *
6674
+ * Resolved rather than pending when no mount is in flight, so `await app.ready()` is safe to call at
6675
+ * any time and on any scene.
6676
+ */
6677
+ let productionMountSettled = Promise.resolve();
6678
+ /** Lets `dispose()` settle an in-flight mount; see the note there. */
6679
+ let settleMountForDispose = () => undefined;
6680
+ /*
6681
+ * WS-2.6 — device-loss subscribers, held here rather than pushed straight at the controller.
6682
+ *
6683
+ * The renderer mounts asynchronously, so a developer writing `app.onDeviceLost(...)` on the line after
6684
+ * `createAuraApp` has no controller to attach to yet. Making them await `ready()` first would be the
6685
+ * same trap WS-2.9 fixed: an API that silently does nothing depending on timing. So subscriptions are
6686
+ * recorded and attached when the device arrives, and on every re-mount from `setScene`.
6687
+ */
6688
+ /*
6689
+ * Keyed BY LISTENER, not a flat array — and that detail is load-bearing.
6690
+ *
6691
+ * A flat list of unsubscribe functions looks equivalent and is not. `attachDeviceListeners` re-attaches
6692
+ * every held listener on each mount, so a listener registered before the mount ends up with **two**
6693
+ * controller subscriptions: the one its own `onDeviceLost` call created, and the one the mount handler
6694
+ * created. Its returned unsubscribe closure only knew about the first, so calling it left the second
6695
+ * live and the listener still fired.
6696
+ *
6697
+ * Measured by the WS-2.6 test's final assertion: after `unsubscribe()`, a second context loss still
6698
+ * incremented the counter — 2 where 1 was expected. A map from listener to its current subscription
6699
+ * makes unsubscribing complete regardless of how many mounts have happened.
6700
+ */
6701
+ const deviceLostListeners = new Map();
6702
+ const deviceRestoredListeners = new Map();
6703
+ const attachDeviceListeners = (controller) => {
6704
+ for (const [listener, unsubscribe] of deviceLostListeners) {
6705
+ unsubscribe?.();
6706
+ deviceLostListeners.set(listener, controller.onDeviceLost?.(listener));
6707
+ }
6708
+ for (const [listener, unsubscribe] of deviceRestoredListeners) {
6709
+ unsubscribe?.();
6710
+ deviceRestoredListeners.set(listener, controller.onDeviceRestored?.(listener));
6711
+ }
6712
+ };
6722
6713
  let lastTime = 0;
6723
6714
  let mountRevision = 0;
6724
6715
  let canvasRuntimePhysics;
6725
6716
  const runtimeNodes = createAuraRuntimeNodeRegistry(renderSnapshot);
6717
+ // One world owned by the app, so `app.physics` is live whether or not the scene declared
6718
+ // any bodies. A route that spawns everything at runtime (a shooter, a stacking puzzle) is
6719
+ // then no harder to write than one that declares bodies up front.
6720
+ const appPhysicsNodeNames = new Map();
6721
+ /*
6722
+ * The physics world is created on first use, not on app construction.
6723
+ *
6724
+ * `app.physics` must be live for every app — a route that spawns bodies at runtime should be no
6725
+ * harder to write than one that declares them. But constructing the world eagerly made **every**
6726
+ * app pay for the selected physical solver.
6727
+ *
6728
+ * Measured cost of the eager version: a minimal `createAuraApp` scene containing one box bundled to
6729
+ * The eager version made the physical runtime part of every route's startup path, including
6730
+ * routes that never created a body.
6731
+ *
6732
+ * Lazily constructing it changes no behaviour — `app.physics` still returns a working runtime, and
6733
+ * a scene that declares `.physics({...})` still gets its bodies registered, because
6734
+ * `registerDeclaredBodies` asks for the world and therefore creates it. What changes is that a
6735
+ * scene with no physics never instantiates a solver, so a bundler can drop it.
6736
+ */
6737
+ let appPhysicsWorldInstance;
6738
+ const appPhysicsWorld = () => {
6739
+ appPhysicsWorldInstance ??= new PhysicsWorld({
6740
+ gravity: options.physics?.gravity ? [...options.physics.gravity] : [0, -9.81, 0],
6741
+ fixedDelta: 1 / 60,
6742
+ enableSleeping: true
6743
+ });
6744
+ return appPhysicsWorldInstance;
6745
+ };
6746
+ let appPhysicsInstance;
6747
+ /** Lazy `app.physics`. Identity is stable: the same runtime is returned on every access. */
6748
+ const appPhysics = () => {
6749
+ appPhysicsInstance ??= createPhysicsRuntime(appPhysicsWorld(), {
6750
+ ...(options.physics?.layers ? { layers: options.physics.layers } : {}),
6751
+ nodeNameFor: (bodyId) => appPhysicsNodeNames.get(bodyId)
6752
+ });
6753
+ return appPhysicsInstance;
6754
+ };
6755
+ /**
6756
+ * Register scene-declared bodies into the app-owned world.
6757
+ *
6758
+ * Runs on construction and on every `setScene`, so a declared node name resolves through
6759
+ * `app.physics.bodies.require(name)` without the route restating the body.
6760
+ */
6761
+ const registerDeclaredBodies = (target) => {
6762
+ // Ask the question before creating the world, so a scene with no declared bodies never does.
6763
+ const declaresPhysics = target.nodes.some((node) => (node.kind === "model" || node.kind === "primitive") && Boolean(node.physics));
6764
+ if (!declaresPhysics)
6765
+ return;
6766
+ const world = appPhysicsWorld();
6767
+ for (const node of target.nodes) {
6768
+ if ((node.kind !== "model" && node.kind !== "primitive") || !node.physics)
6769
+ continue;
6770
+ const spec = node.physics;
6771
+ const body = world.createRigidBody({
6772
+ type: spec.type ?? "dynamic",
6773
+ position: node.position ?? [0, 0, 0],
6774
+ rotation: eulerToQuat(node.rotation ?? [0, 0, 0]),
6775
+ ...(spec.mass === undefined ? {} : { mass: spec.mass }),
6776
+ ...(spec.friction === undefined ? {} : { friction: spec.friction }),
6777
+ ...(spec.restitution === undefined ? {} : { restitution: spec.restitution })
6778
+ });
6779
+ world.createCollider(body, {
6780
+ shape: resolveNodePhysicsShape(node, spec),
6781
+ ...(spec.sensor === undefined ? {} : { sensor: spec.sensor }),
6782
+ material: { friction: spec.friction ?? 0.5, restitution: spec.restitution ?? 0 }
6783
+ });
6784
+ if (node.name)
6785
+ appPhysicsNodeNames.set(body.id, node.name);
6786
+ }
6787
+ };
6788
+ registerDeclaredBodies(renderSnapshot);
6726
6789
  const frameCallbacks = new Set();
6727
6790
  let runtimePaused = options.autoStart === false;
6728
6791
  let runtimeFrame = 0;
@@ -6775,7 +6838,16 @@ export function createAuraApp(target, options) {
6775
6838
  }
6776
6839
  diagnosticsState.evidence = collectAuraSceneEvidence(renderSnapshot);
6777
6840
  diagnosticsState.fps = Math.round(1000 / delta);
6778
- diagnosticsState.drawCalls = renderSceneToCanvas(canvas, renderSnapshot, time);
6841
+ /*
6842
+ * WS-2.5 — the live loop must respect the same rule as `step()`.
6843
+ *
6844
+ * Fixing only `step()` would have left the gradient reachable through `autoStart`, which is the path
6845
+ * most routes take. A scene whose WebGL mount is pending or has failed gets nothing drawn; the reason
6846
+ * is already recorded in `warnings`/`errors`.
6847
+ */
6848
+ diagnosticsState.drawCalls = productionMountPending || productionMountFailed
6849
+ ? 0
6850
+ : renderDiagnosticPreviewToCanvas(canvas, renderSnapshot, time);
6779
6851
  if (canvas)
6780
6852
  diagnosticsState.renderSize = [canvas.width, canvas.height];
6781
6853
  overlay?.update();
@@ -6793,24 +6865,87 @@ export function createAuraApp(target, options) {
6793
6865
  productionController = undefined;
6794
6866
  lastTime = 0;
6795
6867
  const shouldUseProductionRenderer = shouldUseProductionRendererForCurrentScene();
6868
+ /*
6869
+ * WS-2.5 — a scene with renderable content must never fall to the diagnostic 2D path.
6870
+ *
6871
+ * `shouldUseProductionRendererForCurrentScene()` is false in two very different situations, and the
6872
+ * old code treated them the same: a scene with nothing renderable in it (fine, nothing to draw), and
6873
+ * a scene *with* renderable nodes that could not reach WebGL — no canvas, or no `window`. The second
6874
+ * used to silently produce a gradient schematic, which looks like a render and is not.
6875
+ *
6876
+ * So the two cases are separated. A renderable scene with no usable canvas now raises a diagnosable
6877
+ * error naming the cause, instead of drawing something plausible.
6878
+ */
6879
+ const declaresRenderableContent = renderSnapshot.nodes.some(isWebGLRenderableNode);
6880
+ /*
6881
+ * Scoped to the case that is actually a lie: a canvas WAS supplied, so the caller is looking at
6882
+ * pixels, and the scene has renderable content — but WebGL declined it, so those pixels would be a
6883
+ * gradient schematic.
6884
+ *
6885
+ * Deliberately NOT extended to `canvas === undefined`. Constructing an app with no canvas is a
6886
+ * legitimate and widely used pattern — 18 tests across `tests/unit/agent-api` and
6887
+ * `tests/unit/rendering` do it to exercise scene, runtime and physics behaviour headlessly, and
6888
+ * `createAuraApp(undefined, ...)` is how `lazy-physics-world.test.ts` checks `app.physics`. Throwing
6889
+ * there would break working semantics to satisfy a rendering rule, which R7 forbids. Those callers
6890
+ * are not being shown a misleading frame; they are not being shown a frame at all, and
6891
+ * `diagnostics().backend` reports `"headless"`.
6892
+ */
6893
+ if (declaresRenderableContent && canvas && !shouldUseProductionRenderer) {
6894
+ throw new AuraRuntimeError("backend-fallback", "Aura3D cannot render this scene on the canvas you supplied: it has renderable nodes but WebGL2 is unavailable in this context. It will NOT fall back to the Canvas 2D diagnostic preview, because that draws a gradient schematic rather than your scene and has silently hidden defects before — world labels once reached the scene graph but were drawn only in that path. Suggested fix: run in a browser context with WebGL2 available, or inspect diagnostics().errors for the underlying device failure.");
6895
+ }
6796
6896
  const backend = shouldUseProductionRenderer ? "webgl2" : canvas ? "canvas2d" : "headless";
6797
6897
  resetDiagnosticsForCurrentScene(backend);
6798
6898
  canvasRuntimePhysics = shouldUseProductionRenderer ? undefined : createRuntimeScenePhysics(renderSnapshot);
6799
6899
  overlay?.update();
6800
6900
  const revision = ++mountRevision;
6901
+ /*
6902
+ * WS-2.9 — record that a WebGL mount is in flight.
6903
+ *
6904
+ * `startProductionRender` is async, so between `createAuraApp` returning and the controller
6905
+ * arriving there is a window in which `step()` used to fall through to the Canvas-2D `render()`
6906
+ * path and draw nothing for a WebGL scene — silently, with `drawCalls: 0`, `warnings: []` and
6907
+ * `errors: []`. `step(dt)` is the documented deterministic entry point, so a developer writing a
6908
+ * headless capture got a blank image and no explanation.
6909
+ */
6910
+ productionMountPending = shouldUseProductionRenderer && Boolean(canvas);
6911
+ productionMountFailed = false;
6912
+ let settleMount = () => undefined;
6913
+ productionMountSettled = productionMountPending
6914
+ ? new Promise((resolveSettled) => { settleMount = resolveSettled; })
6915
+ : Promise.resolve();
6916
+ settleMountForDispose = settleMount;
6801
6917
  if (shouldUseProductionRenderer && canvas) {
6802
- void startProductionRender(canvas, renderSnapshot, diagnosticsState, options, overlay, runRuntimeFrame, () => runtimePaused, runtimeNodes)
6918
+ void startProductionRender(canvas, renderSnapshot, diagnosticsState, options, overlay, runRuntimeFrame, () => runtimePaused, runtimeNodes,
6919
+ // A route that registered a frame callback, or that has bodies to simulate, needs
6920
+ // frames regardless of what the scene declares.
6921
+ /*
6922
+ * Must not *create* a world just to ask whether one exists.
6923
+ * Reading `appPhysicsWorldInstance` directly keeps the lazy construction lazy; calling
6924
+ * `appPhysicsWorld()` here would instantiate the solver on the first render of every scene
6925
+ * and defeat the whole point.
6926
+ */
6927
+ () => frameCallbacks.size > 0 || (appPhysicsWorldInstance?.bodies().length ?? 0) > 0,
6928
+ // Paused frames render at the app's own simulated clock, so a held frame really is held.
6929
+ () => runtimeTime * 1000)
6803
6930
  .then((controller) => {
6804
6931
  if (disposed || revision !== mountRevision) {
6932
+ productionMountPending = false;
6933
+ settleMount();
6805
6934
  controller.dispose();
6806
6935
  return;
6807
6936
  }
6808
6937
  productionController = controller;
6938
+ productionMountPending = false;
6939
+ attachDeviceListeners(controller);
6940
+ settleMount();
6809
6941
  markRouteReady(snapshot, diagnosticsState);
6810
6942
  })
6811
6943
  .catch((error) => {
6812
6944
  if (disposed || revision !== mountRevision)
6813
6945
  return;
6946
+ productionMountPending = false;
6947
+ productionMountFailed = true;
6948
+ settleMount();
6814
6949
  diagnosticsState.backend = "webgl2";
6815
6950
  diagnosticsState.errors.push(productionRenderErrorMessage(error));
6816
6951
  overlay?.update();
@@ -6822,7 +6957,7 @@ export function createAuraApp(target, options) {
6822
6957
  markRouteReady(snapshot, diagnosticsState);
6823
6958
  };
6824
6959
  mountCurrentScene();
6825
- return {
6960
+ const app = {
6826
6961
  canvas,
6827
6962
  get scene() {
6828
6963
  return snapshot;
@@ -6834,9 +6969,24 @@ export function createAuraApp(target, options) {
6834
6969
  snapshot = normalizeSceneSnapshot(nextScene);
6835
6970
  renderSnapshot = flattenSceneSnapshot(snapshot);
6836
6971
  runtimeNodes.reset(renderSnapshot);
6972
+ // Drop bodies from the previous scene before registering the new ones, so swapping
6973
+ // scenes does not leave orphaned bodies colliding with the new level.
6974
+ // Only a world that exists can hold stale bodies; `setScene` on a physics-free app is a no-op here.
6975
+ for (const id of [...appPhysicsNodeNames.keys()])
6976
+ appPhysicsWorldInstance?.removeRigidBody(id);
6977
+ appPhysicsNodeNames.clear();
6978
+ registerDeclaredBodies(renderSnapshot);
6837
6979
  mountCurrentScene();
6838
6980
  },
6839
6981
  nodes: runtimeNodes,
6982
+ /*
6983
+ * A getter, so touching `app.physics` is what constructs the world.
6984
+ * Declared as a getter rather than an eager property because the property access itself is the
6985
+ * signal that a route intends to use physics.
6986
+ */
6987
+ get physics() {
6988
+ return appPhysics();
6989
+ },
6840
6990
  get runtime() {
6841
6991
  return {
6842
6992
  paused: runtimePaused,
@@ -6863,23 +7013,116 @@ export function createAuraApp(target, options) {
6863
7013
  pause() {
6864
7014
  runtimePaused = true;
6865
7015
  },
7016
+ resetRuntimeClock() {
7017
+ /*
7018
+ * Rewind the frame counter and elapsed time to zero.
7019
+ *
7020
+ * Needed for reproducible capture. Routes animate from accumulated `time` — Data Galaxy sets
7021
+ * `setRotation(time * 0.16, ...)` — so a scene paused after 180 frames of real-time loading
7022
+ * looks different from the same scene paused after 240, even though both were then advanced by
7023
+ * an identical number of fixed steps. Zeroing the clock first makes "settle to N steps" name
7024
+ * exactly one state.
7025
+ *
7026
+ * Not part of `AuraApp`: this is a capture/testing seam, reached through `auraAppRegistry`
7027
+ * rather than offered as gameplay API, because rewinding a live game's clock mid-session is
7028
+ * not something a route should be encouraged to do.
7029
+ */
7030
+ runtimeFrame = 0;
7031
+ runtimeTime = 0;
7032
+ runtimeAlpha = 0;
7033
+ lastTime = 0;
7034
+ },
6866
7035
  resume() {
6867
7036
  runtimePaused = false;
6868
7037
  if (!animationHandle && !productionController && options.autoStart !== false && typeof requestAnimationFrame !== "undefined") {
6869
7038
  animationHandle = requestAnimationFrame(render);
6870
7039
  }
6871
7040
  },
6872
- step(dt = 1 / 60) {
7041
+ async ready() {
7042
+ // Resolves when the in-flight mount settles; immediate when there is none. See AuraApp.ready.
7043
+ await productionMountSettled;
7044
+ },
7045
+ onDeviceLost(listener) {
7046
+ // Attach now when a device already exists; otherwise the mount handler attaches it on arrival.
7047
+ deviceLostListeners.set(listener, productionController?.onDeviceLost?.(listener));
7048
+ return () => {
7049
+ // Read the CURRENT subscription: a re-mount may have replaced the one captured at registration.
7050
+ deviceLostListeners.get(listener)?.();
7051
+ deviceLostListeners.delete(listener);
7052
+ };
7053
+ },
7054
+ onDeviceRestored(listener) {
7055
+ deviceRestoredListeners.set(listener, productionController?.onDeviceRestored?.(listener));
7056
+ return () => {
7057
+ deviceRestoredListeners.get(listener)?.();
7058
+ deviceRestoredListeners.delete(listener);
7059
+ };
7060
+ },
7061
+ deviceLost() {
7062
+ return productionController?.deviceLost?.() ?? false;
7063
+ },
7064
+ advance(dt = 1 / 60) {
6873
7065
  const seconds = Math.max(0, dt);
6874
7066
  runRuntimeFrame(seconds, "manual");
6875
7067
  canvasRuntimePhysics?.step(seconds);
7068
+ },
7069
+ step(dt = 1 / 60) {
7070
+ const seconds = Math.max(0, dt);
7071
+ app.advance(seconds);
6876
7072
  const previousPaused = runtimePaused;
6877
7073
  runtimePaused = true;
7074
+ /*
7075
+ * Render at the *simulated* time, not wall-clock time.
7076
+ *
7077
+ * `step(dt)` is the deterministic entry point — a caller advances a fixed amount and expects a
7078
+ * reproducible frame. Passing `performanceNow()` to the renderer defeated that: any
7079
+ * time-driven shader or effect sampled real elapsed milliseconds, so the same `step` sequence
7080
+ * produced a different image on every run.
7081
+ *
7082
+ * Measured while making screenshot approval satisfiable: after zeroing the runtime clock and
7083
+ * stepping identically, 6 of 29 screenshots still drifted perceptually — all of them routes
7084
+ * with time-animated rendering (particle lab, material inspector). Feeding `runtimeTime`
7085
+ * instead makes `step` mean one thing.
7086
+ *
7087
+ * The live `render()` loop still uses wall-clock time, which is correct for real playback.
7088
+ */
7089
+ const simulatedMs = runtimeTime * 1000;
6878
7090
  if (productionController) {
6879
- productionController.render(performanceNow());
7091
+ productionController.render(simulatedMs);
7092
+ }
7093
+ else if (productionMountPending || productionMountFailed) {
7094
+ /*
7095
+ * WS-2.9 — a WebGL mount is in flight, so there is nothing correct to draw yet.
7096
+ *
7097
+ * Falling through to the Canvas-2D `render()` branch below would draw a gradient for a scene
7098
+ * that has a WebGL renderer coming, which is worse than drawing nothing: it produces a frame
7099
+ * that looks like a real render and is not one. Measured before this fix: eight synchronous
7100
+ * `step(1/60)` calls after construction gave `drawCalls: 0`, a fully blank canvas,
7101
+ * `backend: "webgl2"` and — the actual defect — **empty `warnings` and `errors`**. One
7102
+ * `await requestAnimationFrame` first gave 58,480 lit pixels.
7103
+ *
7104
+ * So this reports rather than renders. The warning is actionable and names both the cause and
7105
+ * the fix, because a developer writing a headless capture has no way to guess that a
7106
+ * documented deterministic entry point depends on an animation frame having elapsed.
7107
+ */
7108
+ const pendingWarning = productionMountFailed
7109
+ ? "Aura3D step() rendered nothing because the WebGL renderer failed to mount for this scene. It will NOT fall back to the Canvas 2D diagnostic preview, because that paints a gradient schematic over a scene whose renderer just failed. Suggested fix: read diagnostics().errors for the underlying device failure."
7110
+ : "Aura3D step() was called before the WebGL renderer finished mounting, so this frame rendered nothing. The production renderer mounts asynchronously. Suggested fix: await one animation frame — `await new Promise(requestAnimationFrame)` — or await `app.ready()` before stepping, then call step() as normal.";
7111
+ if (!diagnosticsState.warnings.includes(pendingWarning))
7112
+ diagnosticsState.warnings.push(pendingWarning);
7113
+ diagnosticsState.drawCalls = 0;
7114
+ overlay?.update();
6880
7115
  }
6881
7116
  else {
6882
- render(performanceNow());
7117
+ /*
7118
+ * `render` records `lastTime` to derive its own delta. Feeding it simulated time would leave
7119
+ * `lastTime` in a different clock from `performanceNow()`, so the first frame after a
7120
+ * `resume()` would compute a wildly wrong delta — a visible jump. Restore it afterwards so
7121
+ * `step` stays side-effect-free with respect to live playback.
7122
+ */
7123
+ const previousLastTime = lastTime;
7124
+ render(simulatedMs);
7125
+ lastTime = previousLastTime;
6883
7126
  }
6884
7127
  runtimePaused = previousPaused;
6885
7128
  },
@@ -6903,6 +7146,16 @@ export function createAuraApp(target, options) {
6903
7146
  },
6904
7147
  dispose() {
6905
7148
  disposed = true;
7149
+ /*
7150
+ * Settle any in-flight mount so `await app.ready()` cannot hang on a disposed app. A promise
7151
+ * that never resolves is a worse failure than the one WS-2.9 fixed: it has no diagnostic at all.
7152
+ */
7153
+ productionMountPending = false;
7154
+ settleMountForDispose();
7155
+ for (const unsubscribe of [...deviceLostListeners.values(), ...deviceRestoredListeners.values()])
7156
+ unsubscribe?.();
7157
+ deviceLostListeners.clear();
7158
+ deviceRestoredListeners.clear();
6906
7159
  if (animationHandle && typeof cancelAnimationFrame !== "undefined")
6907
7160
  cancelAnimationFrame(animationHandle);
6908
7161
  for (const controller of ownedInputControllers)
@@ -6910,9 +7163,77 @@ export function createAuraApp(target, options) {
6910
7163
  ownedInputControllers.clear();
6911
7164
  productionController?.dispose();
6912
7165
  overlay?.dispose();
7166
+ unregisterAuraApp(app);
6913
7167
  }
6914
7168
  };
7169
+ registerAuraApp(app);
7170
+ return app;
6915
7171
  }
7172
+ /**
7173
+ * Live apps on this page, so tooling can act on a scene it did not create.
7174
+ *
7175
+ * ## Why this exists
7176
+ *
7177
+ * Visual-approval and screenshot gates need to *freeze* a scene before capturing it. Without a way
7178
+ * to reach the running app, they cannot: a route creates its app in module scope and typically never
7179
+ * exposes the handle, so an automated capture can only `waitForTimeout` and photograph whatever frame
7180
+ * the loop happened to reach.
7181
+ *
7182
+ * Measured consequence, before this existed: re-running the showcase screenshot spec with **no code
7183
+ * change** produced different bytes for 14 of 29 screenshots, because most routes animate and print
7184
+ * live telemetry. Any gate binding approval to a screenshot hash was therefore unsatisfiable — every
7185
+ * regeneration invalidated a still-correct signature.
7186
+ *
7187
+ * Deliberately a `Set` of handles rather than a global "the app", because a page may legitimately
7188
+ * mount several. Entries are removed on `dispose()` so a long-lived page does not leak.
7189
+ */
7190
+ const liveAuraApps = new Set();
7191
+ function registerAuraApp(app) {
7192
+ liveAuraApps.add(app);
7193
+ if (typeof globalThis !== "undefined") {
7194
+ globalThis.__AURA3D_LIVE_APPS__ = auraAppRegistry;
7195
+ }
7196
+ }
7197
+ function unregisterAuraApp(app) {
7198
+ liveAuraApps.delete(app);
7199
+ }
7200
+ export const auraAppRegistry = {
7201
+ kind: "aura3d-live-app-registry",
7202
+ count() {
7203
+ return liveAuraApps.size;
7204
+ },
7205
+ pauseAll() {
7206
+ for (const app of liveAuraApps)
7207
+ app.pause();
7208
+ return liveAuraApps.size;
7209
+ },
7210
+ resumeAll() {
7211
+ for (const app of liveAuraApps)
7212
+ app.resume();
7213
+ return liveAuraApps.size;
7214
+ },
7215
+ settle(steps = 30, dt = 1 / 60) {
7216
+ for (const app of liveAuraApps) {
7217
+ app.pause();
7218
+ /*
7219
+ * Rewind before stepping.
7220
+ *
7221
+ * Without this, `settle(30)` means "30 steps after however long the page took to load", which
7222
+ * differs run to run — and routes that animate from accumulated `time` then render a different
7223
+ * frame. Measured before this: 8 of 29 screenshots still drifted perceptually even with every
7224
+ * app paused and stepped identically.
7225
+ */
7226
+ const resettable = app;
7227
+ resettable.resetRuntimeClock?.();
7228
+ for (let index = 0; index < Math.max(0, steps); index += 1)
7229
+ app.step(dt);
7230
+ }
7231
+ return liveAuraApps.size;
7232
+ },
7233
+ all() {
7234
+ return [...liveAuraApps];
7235
+ }
7236
+ };
6916
7237
  export function createGameApp(target, options) {
6917
7238
  const { input, loop, runtimeEvidence, ...appOptions } = options;
6918
7239
  const app = createAuraApp(target, { ...appOptions, autoStart: false });
@@ -7168,6 +7489,14 @@ function worldLabelsFromSnapshot(snapshot, runtimeNodes) {
7168
7489
  fontSize: Math.max(11, Math.min(26, Math.round((node.size ?? 0.34) * 46))),
7169
7490
  leader: node.leader === true,
7170
7491
  offscreenPolicy: node.offscreenPolicy ?? (node.label === "hud" ? "draw" : "clamp"),
7492
+ /*
7493
+ * WS-2.7 — carry the declared option through. This line is the fix.
7494
+ *
7495
+ * `occlusionAware` has defaulted to true on every label factory since before 1.6 and was never
7496
+ * read here, so `WorldLabel` never received it and the renderer had nothing to act on. The option
7497
+ * was documented, accepted, and inert.
7498
+ */
7499
+ occlusionAware: node.occlusionAware ?? true,
7171
7500
  ...(node.label === "hud" && node.screenAnchor ? { screenAnchor: node.screenAnchor } : {}),
7172
7501
  ...(node.label === "hud" && !node.screenAnchor ? { screenAnchor: "top-left" } : {})
7173
7502
  };
@@ -7187,15 +7516,154 @@ function createSceneLabelLayer(canvas, snapshot) {
7187
7516
  return undefined;
7188
7517
  return createWorldLabelLayer({ container: canvas.parentElement ?? document.body, canvas });
7189
7518
  }
7190
- async function startProductionRender(canvas, snapshot, diagnosticsState, options, overlay, beforeRender, isPaused = () => false, runtimeNodes) {
7519
+ /**
7520
+ * WS-2.7 — build the occlusion test for a scene's annotations.
7521
+ *
7522
+ * ## What it does
7523
+ *
7524
+ * Walks the segment from the camera eye to a label's anchor and asks whether any renderable node's
7525
+ * world-space box lies across it. If one does, the thing being annotated is behind geometry.
7526
+ *
7527
+ * ## Why boxes and not triangles
7528
+ *
7529
+ * An annotation only needs to know whether its subject is *hidden*, and a node's bounding box answers
7530
+ * that at a fraction of the cost of a mesh raycast — one slab test per node against one segment, no BVH,
7531
+ * no per-frame allocation of any size. A box is conservative: it can report occlusion slightly early at a
7532
+ * silhouette edge. For a label that is the right direction to be wrong in; the alternative, reporting a
7533
+ * label as visible when its subject is behind a wall, is the defect being fixed.
7534
+ *
7535
+ * ## What it deliberately skips
7536
+ *
7537
+ * The node the label is anchored *to*. Every annotation sits on or just outside its own subject's
7538
+ * surface, so including it would report every label as occluded by the very geometry it annotates —
7539
+ * the label-shaped version of z-fighting.
7540
+ */
7541
+ function createSceneLabelOcclusionTest(snapshot, cameraEye, runtimeNodes) {
7542
+ const occluders = [];
7543
+ for (const node of groups.flatten(snapshot.nodes)) {
7544
+ if (node.kind !== "primitive" && !isRenderableModelNode(node))
7545
+ continue;
7546
+ if (node.visible === false)
7547
+ continue;
7548
+ const runtimeSnapshot = node.runtime?.id ? runtimeNodes?.get(node.runtime.id)?.snapshot() : undefined;
7549
+ if (runtimeSnapshot?.visible === false)
7550
+ continue;
7551
+ const position = (runtimeSnapshot?.position ?? node.position ?? [0, 0, 0]);
7552
+ const scale = (runtimeSnapshot?.scale ?? node.scale ?? [1, 1, 1]);
7553
+ /*
7554
+ * Local extents from the primitive's own geometry where available, and a unit box otherwise.
7555
+ * A model's real bounds come from its asset, which is not loaded synchronously here; the declared
7556
+ * scale is the honest approximation and is what the scene author controls.
7557
+ */
7558
+ const localBounds = node.kind === "primitive" ? primitiveGeometryBounds(node) : undefined;
7559
+ const halfLocal = localBounds
7560
+ ? [
7561
+ Math.max(1e-4, (localBounds.max[0] - localBounds.min[0]) / 2),
7562
+ Math.max(1e-4, (localBounds.max[1] - localBounds.min[1]) / 2),
7563
+ Math.max(1e-4, (localBounds.max[2] - localBounds.min[2]) / 2)
7564
+ ]
7565
+ : [0.5, 0.5, 0.5];
7566
+ const half = [
7567
+ Math.abs(halfLocal[0] * scale[0]),
7568
+ Math.abs(halfLocal[1] * scale[1]),
7569
+ Math.abs(halfLocal[2] * scale[2])
7570
+ ];
7571
+ occluders.push({
7572
+ min: [position[0] - half[0], position[1] - half[1], position[2] - half[2]],
7573
+ max: [position[0] + half[0], position[1] + half[1], position[2] + half[2]]
7574
+ });
7575
+ }
7576
+ if (occluders.length === 0)
7577
+ return () => false;
7578
+ /** Slab test: does the segment eye -> anchor enter this box strictly before reaching the anchor? */
7579
+ const segmentHitsBox = (anchor, box) => {
7580
+ let tEnter = 0;
7581
+ let tExit = 1;
7582
+ for (let axis = 0; axis < 3; axis += 1) {
7583
+ const origin = cameraEye[axis];
7584
+ const direction = anchor[axis] - origin;
7585
+ const min = box.min[axis];
7586
+ const max = box.max[axis];
7587
+ if (Math.abs(direction) < 1e-9) {
7588
+ // Parallel to this slab: outside it means the segment can never be inside the box.
7589
+ if (origin < min || origin > max)
7590
+ return false;
7591
+ continue;
7592
+ }
7593
+ const t1 = (min - origin) / direction;
7594
+ const t2 = (max - origin) / direction;
7595
+ tEnter = Math.max(tEnter, Math.min(t1, t2));
7596
+ tExit = Math.min(tExit, Math.max(t1, t2));
7597
+ if (tEnter > tExit)
7598
+ return false;
7599
+ }
7600
+ /*
7601
+ * `tEnter` must be meaningfully before the anchor. A box the anchor merely touches at t ~= 1 is the
7602
+ * subject's own surface, not an occluder — the epsilon is what keeps a label from occluding itself.
7603
+ */
7604
+ return tEnter > 1e-4 && tEnter < 1 - 1e-3;
7605
+ };
7606
+ return (anchor) => {
7607
+ for (const box of occluders) {
7608
+ // Skip the box the anchor is inside: that is the subject, and a subject cannot occlude its own label.
7609
+ const insideBox = anchor[0] >= box.min[0] && anchor[0] <= box.max[0]
7610
+ && anchor[1] >= box.min[1] && anchor[1] <= box.max[1]
7611
+ && anchor[2] >= box.min[2] && anchor[2] <= box.max[2];
7612
+ if (insideBox)
7613
+ continue;
7614
+ if (segmentHitsBox(anchor, box))
7615
+ return true;
7616
+ }
7617
+ return false;
7618
+ };
7619
+ }
7620
+ async function startProductionRender(canvas, snapshot, diagnosticsState, options, overlay, beforeRender, isPaused = () => false, runtimeNodes,
7621
+ /**
7622
+ * Extra reason to keep rendering, beyond what the scene declares.
7623
+ *
7624
+ * See {@link shouldContinuouslyRender}: scene-declared motion cannot know about a
7625
+ * simulation or a frame callback the route drives itself.
7626
+ */
7627
+ requiresFrames = () => false,
7628
+ /**
7629
+ * Render clock to use while paused, in milliseconds.
7630
+ *
7631
+ * Supplied by the app so a paused scene renders at its own simulated time rather than at
7632
+ * wall-clock time. Without it, `pause()` froze the simulation but not time-driven rendering.
7633
+ */
7634
+ pausedRenderTime = () => 0) {
7191
7635
  const renderableNode = snapshot.nodes.find(isWebGLRenderableNode);
7192
7636
  if (!renderableNode) {
7193
7637
  throw new AuraRuntimeError("missing-asset", "Aura3D production rendering requires at least one typed model asset or primitive. Suggested fix: add model(assets.product), primitives.box(), primitives.sphere(), primitives.cylinder(), or primitives.plane().");
7194
7638
  }
7195
7639
  const renderer = await createProductionSceneRenderer(canvas, snapshot, options.renderer, runtimeNodes);
7196
7640
  diagnosticsState.renderer = renderer.diagnostics;
7197
- const continuousRender = shouldContinuouslyRender(snapshot);
7641
+ const sceneWantsFrames = shouldContinuouslyRender(snapshot);
7198
7642
  const labelLayer = createSceneLabelLayer(canvas, snapshot);
7643
+ const rendererSelection = normalizeCreateAppRendererOptions(options.renderer);
7644
+ const pixelRatio = options.pixelRatio ?? rendererSelection.profile.pixelRatio ?? devicePixelRatioSafe();
7645
+ const resizeRenderer = () => {
7646
+ if (options.resize === false)
7647
+ return;
7648
+ const parentRect = canvas.parentElement?.getBoundingClientRect();
7649
+ const cssWidth = parentRect?.width || canvas.clientWidth || (typeof window !== "undefined" ? window.innerWidth : 960) || 960;
7650
+ const cssHeight = parentRect?.height || canvas.clientHeight || (typeof window !== "undefined" ? window.innerHeight : 540) || 540;
7651
+ const width = Math.max(320, Math.round(cssWidth * pixelRatio));
7652
+ const height = Math.max(220, Math.round(cssHeight * pixelRatio));
7653
+ if (canvas.width === width && canvas.height === height)
7654
+ return;
7655
+ canvas.style.width = `${cssWidth}px`;
7656
+ canvas.style.height = `${cssHeight}px`;
7657
+ canvas.width = width;
7658
+ canvas.height = height;
7659
+ renderer.resize?.(width, height);
7660
+ };
7661
+ const resizeObserver = options.resize !== false && typeof ResizeObserver !== "undefined" && canvas.parentElement
7662
+ ? new ResizeObserver(resizeRenderer)
7663
+ : undefined;
7664
+ resizeObserver?.observe(canvas.parentElement);
7665
+ if (options.resize !== false && typeof window !== "undefined")
7666
+ window.addEventListener("resize", resizeRenderer);
7199
7667
  let disposed = false;
7200
7668
  let animationHandle = 0;
7201
7669
  let lastTime = 0;
@@ -7206,7 +7674,21 @@ async function startProductionRender(canvas, snapshot, diagnosticsState, options
7206
7674
  lastTime = time;
7207
7675
  if (!isPaused())
7208
7676
  beforeRender?.(delta / 1000, "raf");
7209
- const drawCalls = renderer.render(time);
7677
+ /*
7678
+ * A paused app must not keep advancing time-driven rendering.
7679
+ *
7680
+ * `isPaused()` gated the simulation callback but not the render clock, so `pause()` stopped
7681
+ * gameplay while particle emitters, animated materials and anything else keyed to elapsed time
7682
+ * carried on. Measured on the particle lab: with the app paused *and* settled to a fixed frame,
7683
+ * two screenshots taken 500 ms apart in the **same page load** still differed across 20.6% of the
7684
+ * vortex region. The frame was never actually held, so no capture of it could be reproducible.
7685
+ *
7686
+ * While paused, render is pinned to the time of the last simulated frame. `app.step()` advances
7687
+ * `runtimeTime` and renders explicitly, so stepping still produces new frames — what stops is
7688
+ * time passing on its own.
7689
+ */
7690
+ const renderTime = isPaused() ? pausedRenderTime() : time;
7691
+ const drawCalls = renderer.render(renderTime);
7210
7692
  diagnosticsState.backend = renderer.backend;
7211
7693
  diagnosticsState.fps = diagnosticsState.fps || 60;
7212
7694
  diagnosticsState.drawCalls = drawCalls;
@@ -7217,28 +7699,66 @@ async function startProductionRender(canvas, snapshot, diagnosticsState, options
7217
7699
  // Reproject every frame against the renderer's own camera so labels track
7218
7700
  // their anchors while the camera moves.
7219
7701
  labelLayer.setLabels(worldLabelsFromSnapshot(snapshot, runtimeNodes));
7220
- labelLayer.update(renderer.viewProjection(time));
7702
+ /*
7703
+ * WS-2.7 — rebuilt per frame, because both the camera and any runtime-driven node can move. The
7704
+ * cost is one bounding box per renderable node, which is negligible beside the render itself, and
7705
+ * caching it would silently stop occluding as soon as anything moved.
7706
+ */
7707
+ labelLayer.setOcclusionTest(createSceneLabelOcclusionTest(snapshot, resolveCameraEye(snapshot, snapshot.camera, renderTime, runtimeNodes), runtimeNodes));
7708
+ labelLayer.update(renderer.viewProjection(renderTime));
7221
7709
  diagnosticsState.labels = labelLayer.snapshot();
7222
7710
  }
7223
7711
  overlay?.update();
7224
- if (continuousRender && options.autoStart !== false && typeof requestAnimationFrame !== "undefined") {
7712
+ if ((sceneWantsFrames || requiresFrames()) && options.autoStart !== false && typeof requestAnimationFrame !== "undefined") {
7225
7713
  animationHandle = requestAnimationFrame(renderFrame);
7226
7714
  }
7227
7715
  };
7228
7716
  renderFrame();
7229
7717
  return {
7230
7718
  render(time = performanceNow()) {
7719
+ /*
7720
+ * Preserve `lastTime` across an explicit render.
7721
+ *
7722
+ * `renderFrame` records `lastTime` to derive its own delta and to drive `beforeRender`. When
7723
+ * `app.step()` renders at *simulated* time for reproducibility, leaving `lastTime` on the
7724
+ * simulated clock means the first live frame after `resume()` computes its delta against a
7725
+ * different clock — a visible jump. Same defect the canvas2d path had; fixed identically so
7726
+ * the two render paths cannot disagree about what `step` does.
7727
+ */
7728
+ const previousLastTime = lastTime;
7231
7729
  renderFrame(time);
7730
+ lastTime = previousLastTime;
7232
7731
  },
7732
+ // WS-2.6 — forward device-loss subscription from whichever renderer backs this controller.
7733
+ onDeviceLost: renderer.onDeviceLost ? (listener) => renderer.onDeviceLost(listener) : undefined,
7734
+ onDeviceRestored: renderer.onDeviceRestored ? (listener) => renderer.onDeviceRestored(listener) : undefined,
7735
+ deviceLost: renderer.deviceLost ? () => renderer.deviceLost() : undefined,
7233
7736
  dispose() {
7234
7737
  disposed = true;
7235
7738
  if (animationHandle && typeof cancelAnimationFrame !== "undefined")
7236
7739
  cancelAnimationFrame(animationHandle);
7740
+ resizeObserver?.disconnect();
7741
+ if (typeof window !== "undefined")
7742
+ window.removeEventListener("resize", resizeRenderer);
7237
7743
  labelLayer?.dispose();
7238
7744
  renderer.dispose();
7239
7745
  }
7240
7746
  };
7241
7747
  }
7748
+ /**
7749
+ * Whether the *scene* declares something that changes over time.
7750
+ *
7751
+ * Deliberately conservative: a fully static scene should render once and stop rather than
7752
+ * burn a core redrawing an identical frame.
7753
+ *
7754
+ * It is not sufficient on its own, and that was a real defect. This predicate can only see
7755
+ * what the scene *declares* — a looping timeline, a moving camera, an animated or mutable
7756
+ * node. It cannot see a physics simulation or a frame callback the route drives itself. So
7757
+ * an app whose only motion came from `app.physics.step()` inside `app.onFrame()` rendered
7758
+ * exactly **one** frame and froze: measured `frames: 1` with no console error, in a
7759
+ * clean-room project where every crate should have been falling. Callers therefore combine
7760
+ * this with their own `requiresFrames()`.
7761
+ */
7242
7762
  function shouldContinuouslyRender(snapshot) {
7243
7763
  if (snapshot.timeline?.mode === "loop")
7244
7764
  return true;
@@ -7262,9 +7782,7 @@ async function createProductionSceneRenderer(canvas, snapshot, rendererOptions,
7262
7782
  const flattened = groups.flatten(snapshot.nodes);
7263
7783
  const eligibility = analyzeProductionBridgeEligibility(flattened);
7264
7784
  if (!eligibility.eligible) {
7265
- return await createWebGLSceneRenderer(canvas, snapshot, rendererOptions, [
7266
- `Production bridge skipped: ${eligibility.reasons.join("; ")}.`
7267
- ], runtimeNodes);
7785
+ throw new AuraRuntimeError("backend-fallback", `Aura3D production renderer rejected this scene: ${eligibility.reasons.join("; ")}. Suggested fix: import models through generated typed aura-assets.`);
7268
7786
  }
7269
7787
  try {
7270
7788
  return await createProductionRuntimeSceneRenderer(canvas, snapshot, rendererOptions, runtimeNodes);
@@ -7277,7 +7795,57 @@ async function createProductionSceneRenderer(canvas, snapshot, rendererOptions,
7277
7795
  }
7278
7796
  let cachedProductionRuntimeFallbackLights;
7279
7797
  function createProductionRuntimeEnvironment(snapshot) {
7280
- const names = groups.flatten(snapshot.nodes).map((node) => "name" in node ? node.name?.toLowerCase() ?? "" : "");
7798
+ const nodes = groups.flatten(snapshot.nodes);
7799
+ const authoredEnvironment = nodes.find((node) => node.kind === "environment");
7800
+ if (authoredEnvironment) {
7801
+ const presetByEnvironment = {
7802
+ "studio": "studio",
7803
+ "material-lab": "inspection",
7804
+ "product-hero": "softbox",
7805
+ "night-cinematic": "evening",
7806
+ "metal-studio": "exhibit",
7807
+ "glass-studio": "softbox"
7808
+ };
7809
+ const preset = presetByEnvironment[authoredEnvironment.environment];
7810
+ const bundle = createExternalParityEnvironmentLighting(preset);
7811
+ const intensity = nonNegativeFinite(authoredEnvironment.intensity);
7812
+ const proceduralMap = bundle.lighting.proceduralMap;
7813
+ return {
7814
+ preset: authoredEnvironment.environment,
7815
+ intensity,
7816
+ evidence: `production bridge submitted the authored ${authoredEnvironment.environment} environment through generated HDR ${preset} lighting`,
7817
+ lighting: {
7818
+ ...bundle.lighting,
7819
+ color: authoredEnvironment.color ? colorToLinearRgb(authoredEnvironment.color) : bundle.lighting.color,
7820
+ intensity: bundle.lighting.intensity * intensity,
7821
+ ...(proceduralMap ? {
7822
+ proceduralMap: {
7823
+ ...proceduralMap,
7824
+ intensity: proceduralMap.intensity * intensity,
7825
+ specularIntensity: proceduralMap.specularIntensity * intensity
7826
+ }
7827
+ } : {}),
7828
+ environmentMapIntensity: (bundle.lighting.environmentMapIntensity ?? 0) * intensity,
7829
+ environmentMapSpecularIntensity: (bundle.lighting.environmentMapSpecularIntensity ?? 0) * intensity
7830
+ }
7831
+ };
7832
+ }
7833
+ const ambientLights = nodes.filter((node) => node.kind === "light" && node.light === "ambient" && node.intensity > 0);
7834
+ if (ambientLights.length > 0) {
7835
+ const intensity = ambientLights.reduce((total, light) => total + light.intensity, 0);
7836
+ const color = ambientLights.reduce((sum, light) => {
7837
+ const linear = colorToLinearRgb(light.color ?? "#ffffff");
7838
+ const weight = light.intensity / intensity;
7839
+ return [sum[0] + linear[0] * weight, sum[1] + linear[1] * weight, sum[2] + linear[2] * weight];
7840
+ }, [0, 0, 0]);
7841
+ return {
7842
+ preset: "authored-ambient",
7843
+ intensity,
7844
+ evidence: `production bridge submitted ${ambientLights.length} authored ambient light${ambientLights.length === 1 ? "" : "s"} without an implicit environment map`,
7845
+ lighting: { color, intensity, environmentMapIntensity: 0, environmentMapSpecularIntensity: 0 }
7846
+ };
7847
+ }
7848
+ const names = nodes.map((node) => "name" in node ? node.name?.toLowerCase() ?? "" : "");
7281
7849
  const category = resolveRendererSceneCategory(snapshot, names);
7282
7850
  const preset = category === "city-day" ? "daylight"
7283
7851
  : category === "city-night" ? "evening"
@@ -7306,7 +7874,7 @@ function createProductionRuntimeEnvironmentFog(snapshot) {
7306
7874
  return false;
7307
7875
  const density = clampNumber(fog.density ?? 0.12, 0, 1);
7308
7876
  const intensity = clampNumber(fog.intensity ?? 0.5, 0, 1);
7309
- const color = colorToRgb(fog.color ?? "#9fb7d9");
7877
+ const color = colorToLinearRgb(fog.color ?? "#9fb7d9");
7310
7878
  return {
7311
7879
  // Exponential-squared reads as depth haze rather than a hard linear band, which
7312
7880
  // matches what the public helper documents.
@@ -7320,16 +7888,8 @@ function createProductionRuntimeEnvironmentFog(snapshot) {
7320
7888
  }
7321
7889
  function createProductionRuntimePostprocess(snapshot) {
7322
7890
  const nodes = groups.flatten(snapshot.nodes);
7323
- const names = nodes.map((node) => "name" in node ? node.name?.toLowerCase() ?? "" : "");
7324
- const category = resolveRendererSceneCategory(snapshot, names);
7325
7891
  const authoredBloom = nodes.find((node) => node.kind === "effect" && node.effect === "bloom");
7326
- const emissiveSubjects = nodes.filter((node) => {
7327
- if (!("material" in node) || !node.material)
7328
- return false;
7329
- return Boolean(node.material.emissive) && (node.material.emissiveIntensity ?? 1) > 0;
7330
- }).length;
7331
- const darkScene = ["neon", "city-night", "space", "game"].includes(category);
7332
- const bloomRequested = Boolean(authoredBloom) || (darkScene && emissiveSubjects > 0);
7892
+ const bloomRequested = Boolean(authoredBloom);
7333
7893
  // Root previously advertised `ssao` in `requestedPasses` whenever a scene added
7334
7894
  // effects.ambientOcclusion() or effects.contactOcclusion(), but never submitted
7335
7895
  // an `ssao` option to the renderer. The advertised pass could therefore never
@@ -7338,20 +7898,15 @@ function createProductionRuntimePostprocess(snapshot) {
7338
7898
  const authoredAmbientOcclusion = nodes.find((node) => node.kind === "effect" && node.effect === "ambient-occlusion");
7339
7899
  const authoredContactOcclusion = nodes.find((node) => node.kind === "effect" && node.effect === "contact-occlusion");
7340
7900
  const authoredOcclusion = authoredAmbientOcclusion ?? authoredContactOcclusion;
7341
- const exposure = category === "city-day" ? 1.02
7342
- : category === "material" || category === "product" ? 1.08
7343
- : category === "space" ? 1.18
7344
- : 1.12;
7345
- const saturation = category === "material" || category === "product" ? 1.01
7346
- : category === "city-day" ? 1.04
7347
- : 1.1;
7348
7901
  return {
7349
- targetFormat: "rgba8",
7902
+ // Tone mapping requires unclamped linear input. RGBA8 quantized dark clear
7903
+ // colors and clipped highlights before ACES, which produced washed-out output.
7904
+ targetFormat: "rgba16f",
7350
7905
  ...(bloomRequested ? {
7351
7906
  bloom: {
7352
- threshold: clampNumber(authoredBloom?.threshold ?? (darkScene ? 0.68 : 0.78), 0, 1),
7353
- intensity: clampNumber(authoredBloom?.intensity ?? Math.min(0.5, 0.24 + emissiveSubjects * 0.035), 0, 2),
7354
- radius: Math.max(1, Math.min(4, Math.round(authoredBloom?.radius ?? (category === "space" ? 3 : 2))))
7907
+ threshold: clampNumber(authoredBloom?.threshold ?? 0.78, 0, 1),
7908
+ intensity: clampNumber(authoredBloom?.intensity ?? 0.3, 0, 2),
7909
+ radius: Math.max(1, Math.min(4, Math.round(authoredBloom?.radius ?? 2)))
7355
7910
  }
7356
7911
  } : {}),
7357
7912
  ...(authoredOcclusion ? {
@@ -7367,22 +7922,11 @@ function createProductionRuntimePostprocess(snapshot) {
7367
7922
  }
7368
7923
  } : {}),
7369
7924
  toneMapping: {
7370
- exposure,
7371
- whitePoint: category === "city-day" ? 1.28 : 1.18,
7372
- operator: "filmic",
7925
+ exposure: 1,
7926
+ whitePoint: 1,
7927
+ operator: "aces",
7373
7928
  inputColorSpace: "linear",
7374
7929
  outputColorSpace: "srgb"
7375
- },
7376
- colorGrade: {
7377
- contrast: category === "material" || category === "product" ? 1.06 : 1.1,
7378
- saturation,
7379
- vibrance: darkScene ? 0.14 : 0.06,
7380
- vignette: category === "game" || category === "neon" ? 0.1 : 0.04,
7381
- sharpening: category === "material" || category === "product" ? 0.28 : 0.2
7382
- },
7383
- fxaa: {
7384
- edgeThreshold: category === "game" ? 0.07 : 0.09,
7385
- subpixelBlend: category === "material" || category === "product" ? 0.48 : 0.58
7386
7930
  }
7387
7931
  };
7388
7932
  }
@@ -7447,7 +7991,8 @@ function createProductionRuntimePostprocessObservation(diagnostics) {
7447
7991
  contactOcclusionReceiver: actualPasses.includes("contact-shadow"),
7448
7992
  pixelBacked,
7449
7993
  actualPasses,
7450
- fallbackPasses: pixelBacked ? [] : ["direct-render"]
7994
+ fallbackPasses: pixelBacked ? [] : ["direct-render"],
7995
+ targetFormat: diagnostics.postprocessTargetFormat
7451
7996
  };
7452
7997
  }
7453
7998
  function createProductionRuntimeCollectedLights(snapshot) {
@@ -7468,7 +8013,7 @@ function createProductionRuntimeCollectedLights(snapshot) {
7468
8013
  }
7469
8014
  function createProductionRuntimeLightDescriptors(node, authoredIndex) {
7470
8015
  const name = node.name?.trim() || `aura-authored-${node.light}-${authoredIndex + 1}`;
7471
- const color = colorToRgb(node.color ?? "#ffffff");
8016
+ const color = colorToLinearRgb(node.color ?? "#ffffff");
7472
8017
  const intensity = nonNegativeFinite(node.intensity);
7473
8018
  const position = productionRuntimeLightPosition(node);
7474
8019
  const direction = productionRuntimeLightDirection(node, position);
@@ -7745,17 +8290,40 @@ function multiplyRgb(color, tint) {
7745
8290
  async function createProductionRuntimeSceneRenderer(canvas, snapshot, rendererOptions, runtimeNodes) {
7746
8291
  const flattened = groups.flatten(snapshot.nodes);
7747
8292
  const modelNodes = flattened.filter((node) => isRenderableModelNode(node) && createAssetProvenance(node.asset).source === "typed-aura-assets-manifest");
7748
- const actorEntries = await Promise.all(modelNodes.map(async (node, index) => ({
7749
- node,
7750
- actor: await createTypedGLBActor({
7751
- asset: node.asset,
7752
- id: node.runtime?.id ?? node.asset.id ?? `model-${index + 1}`,
7753
- name: node.name ?? node.asset.id ?? `model-${index + 1}`,
7754
- width: canvas.width,
7755
- height: canvas.height,
7756
- ...(node.material?.color ? { tint: { baseColor: colorToRgba(node.material.color) } } : {})
7757
- })
7758
- })));
8293
+ /*
8294
+ * Loaded here rather than imported at module scope (WS-2.2). This function is only reached when the
8295
+ * scene contains a typed GLB, so the glTF loader is downloaded exactly when it is needed.
8296
+ */
8297
+ const actorEntries = modelNodes.length > 0
8298
+ ? await (async () => {
8299
+ const { createTypedGLBActor } = await import("../production-runtime/TypedGLBActor.js");
8300
+ return await Promise.all(modelNodes.map(async (node, index) => ({
8301
+ node,
8302
+ actor: await createTypedGLBActor({
8303
+ asset: node.asset,
8304
+ id: node.runtime?.id ?? node.asset.id ?? `model-${index + 1}`,
8305
+ name: node.name ?? node.asset.id ?? `model-${index + 1}`,
8306
+ width: canvas.width,
8307
+ height: canvas.height,
8308
+ ...(node.hiddenNodeNames ? { hiddenNodeNames: node.hiddenNodeNames } : {}),
8309
+ ...(node.material?.color ? {
8310
+ tint: {
8311
+ baseColor: colorToLinearRgba(node.material.color),
8312
+ replaceSurfaceTextures: true,
8313
+ ...(node.material.emissive ? { emissiveColor: colorToLinearRgb(node.material.emissive) } : {}),
8314
+ ...(node.material.emissiveIntensity === undefined ? {} : { emissiveStrength: node.material.emissiveIntensity }),
8315
+ ...(node.material.roughness === undefined ? {} : { roughness: clamp01(node.material.roughness) }),
8316
+ ...(node.material.metallic === undefined && node.material.metalness === undefined
8317
+ ? {}
8318
+ : { metallic: clamp01(node.material.metallic ?? node.material.metalness ?? 0) }),
8319
+ ...(node.material.clearcoat === undefined ? {} : { clearcoat: clamp01(node.material.clearcoat) }),
8320
+ ...(node.material.clearcoatRoughness === undefined ? {} : { clearcoatRoughness: clamp01(node.material.clearcoatRoughness) })
8321
+ }
8322
+ } : {})
8323
+ })
8324
+ })));
8325
+ })()
8326
+ : [];
7759
8327
  const primitiveEntries = createProductionRuntimePrimitiveEntries(flattened);
7760
8328
  const productionRenderer = await ProductionRuntimeRenderer.create({
7761
8329
  canvas,
@@ -7764,7 +8332,9 @@ async function createProductionRuntimeSceneRenderer(canvas, snapshot, rendererOp
7764
8332
  backend: "webgl2",
7765
8333
  antialias: true,
7766
8334
  preserveDrawingBuffer: true,
7767
- clearColor: colorToClearColor(snapshot.background)
8335
+ // Background colors are display intent. Pre-invert the renderer's coupled
8336
+ // matrix-fitted ACES transform so presentation preserves that authored color.
8337
+ clearColor: colorToAcesInputClearColor(snapshot.background)
7768
8338
  });
7769
8339
  let latestDeviceDiagnostics = productionRenderer.getDiagnostics();
7770
8340
  let latestFeatures = productionRenderer.getFeatures();
@@ -7805,7 +8375,15 @@ async function createProductionRuntimeSceneRenderer(canvas, snapshot, rendererOp
7805
8375
  .filter((feature) => feature.state !== "supported")
7806
8376
  .map((feature) => `Production runtime feature ${feature.id} is ${feature.state}: ${feature.detail}`),
7807
8377
  ...runtimeWarnings
7808
- ]
8378
+ ],
8379
+ deviceDiagnostics: latestDeviceDiagnostics,
8380
+ lodSelections: primitiveEntries
8381
+ .filter((entry) => Boolean(entry.node.lod?.levels.length))
8382
+ .map((entry) => ({
8383
+ nodeName: entry.node.name ?? "unnamed distance LOD",
8384
+ levelIndex: entry.currentLodIndex,
8385
+ levelName: entry.resources[entry.currentLodIndex]?.name ?? `level-${entry.currentLodIndex}`
8386
+ }))
7809
8387
  }, rendererOptions);
7810
8388
  return {
7811
8389
  get backend() {
@@ -7825,19 +8403,35 @@ async function createProductionRuntimeSceneRenderer(canvas, snapshot, rendererOp
7825
8403
  viewProjection(time) {
7826
8404
  return createViewProjection(snapshot, canvas.width / Math.max(1, canvas.height), time, runtimeNodes);
7827
8405
  },
8406
+ resize(width, height) {
8407
+ productionRenderer.resize(width, height);
8408
+ },
8409
+ onDeviceLost(listener) {
8410
+ return productionRenderer.onDeviceLost(listener);
8411
+ },
8412
+ onDeviceRestored(listener) {
8413
+ return productionRenderer.onDeviceRestored(listener);
8414
+ },
8415
+ deviceLost() {
8416
+ return productionRenderer.deviceLost();
8417
+ },
7828
8418
  dispose() {
7829
8419
  productionRenderer.dispose();
7830
8420
  for (const { actor } of actorEntries)
7831
8421
  actor.pipeline.dispose();
7832
- for (const { geometry, material } of primitiveEntries) {
7833
- geometry.dispose();
7834
- material.dispose();
8422
+ for (const { resources } of primitiveEntries) {
8423
+ for (const { geometry, material } of resources) {
8424
+ geometry.dispose();
8425
+ material.dispose();
8426
+ }
7835
8427
  }
7836
8428
  }
7837
8429
  };
7838
8430
  }
7839
8431
  function createProductionRuntimeRendererInput(snapshot, canvas, actorEntries, primitiveEntries, time, runtimeNodes, runtimeWarnings, environmentLighting, collectedLights) {
7840
8432
  const items = [];
8433
+ const viewProjectionMatrix = createViewProjection(snapshot, canvas.width / Math.max(1, canvas.height), time, runtimeNodes);
8434
+ const cameraPosition = resolveCameraEye(snapshot, snapshot.camera, time, runtimeNodes);
7841
8435
  for (const entry of actorEntries) {
7842
8436
  const currentState = resolveProductionActorRuntimeState(entry, runtimeNodes);
7843
8437
  const currentNode = currentState.node;
@@ -7854,16 +8448,16 @@ function createProductionRuntimeRendererInput(snapshot, canvas, actorEntries, pr
7854
8448
  const currentState = resolveProductionPrimitiveRuntimeState(entry, runtimeNodes);
7855
8449
  if (!currentState.visible)
7856
8450
  continue;
8451
+ const resource = selectProductionPrimitiveResource(entry, currentState.node, cameraPosition);
7857
8452
  items.push({
7858
- geometry: entry.geometry,
7859
- material: entry.material,
7860
- modelMatrix: createModelMatrix(currentState.node, entry.bounds, false, time),
8453
+ geometry: resource.geometry,
8454
+ material: resource.material,
8455
+ modelMatrix: createModelMatrix(currentState.node, resource.bounds, false, time),
7861
8456
  label: currentState.node.name ?? `aura-primitive-${currentState.node.primitive}`,
7862
- includeInAutoFrame: false
8457
+ includeInAutoFrame: false,
8458
+ ...(currentState.node.instances ? { instanceTransforms: createProductionInstanceTransforms(currentState.node.instances, currentState.node), instanceColors: createProductionInstanceColors(currentState.node.instanceColors, currentState.node.instances.length) } : {})
7863
8459
  });
7864
8460
  }
7865
- const viewProjectionMatrix = createViewProjection(snapshot, canvas.width / Math.max(1, canvas.height), time, runtimeNodes);
7866
- const cameraPosition = resolveCameraEye(snapshot, snapshot.camera, time, runtimeNodes);
7867
8461
  const source = {
7868
8462
  collectRenderItems: () => items,
7869
8463
  cameraPolicy: "require",
@@ -7880,18 +8474,57 @@ function createProductionRuntimeRendererInput(snapshot, canvas, actorEntries, pr
7880
8474
  return {
7881
8475
  source,
7882
8476
  camera: cameraLike,
7883
- metadata: createProductionRuntimeMetadata(actorEntries)
8477
+ metadata: createProductionRuntimeMetadata(actorEntries, primitiveEntries)
7884
8478
  };
7885
8479
  }
7886
8480
  function createProductionRuntimePrimitiveEntries(nodes) {
7887
8481
  return nodes
7888
8482
  .filter((node) => node.kind === "primitive")
7889
- .map((node) => ({
7890
- node,
7891
- geometry: createProductionPrimitiveGeometry(node),
7892
- material: createProductionPrimitiveMaterial(node),
7893
- bounds: primitiveGeometryBounds(node.primitive)
7894
- }));
8483
+ .map((node) => ({ node, resources: createProductionPrimitiveResources(node), currentLodIndex: 0 }));
8484
+ }
8485
+ function createProductionPrimitiveResources(node) {
8486
+ const levels = node.lod?.levels;
8487
+ if (!levels?.length) {
8488
+ return [{ geometry: createProductionPrimitiveGeometry(node), material: createProductionPrimitiveMaterial(node), bounds: primitiveGeometryBounds(node), name: node.name ?? node.primitive }];
8489
+ }
8490
+ return levels.map((level, index) => {
8491
+ if (!level.primitive && !level.geometry)
8492
+ throw new Error(`Aura3D LOD level ${index} requires primitive or custom geometry.`);
8493
+ const levelNode = {
8494
+ ...node,
8495
+ primitive: level.geometry ? "custom" : level.primitive,
8496
+ geometry: level.geometry,
8497
+ material: level.material ?? node.material,
8498
+ lod: undefined
8499
+ };
8500
+ return { geometry: createProductionPrimitiveGeometry(levelNode), material: createProductionPrimitiveMaterial(levelNode), bounds: primitiveGeometryBounds(levelNode), name: level.name };
8501
+ });
8502
+ }
8503
+ function selectProductionPrimitiveResource(entry, node, cameraPosition) {
8504
+ if (!node.lod?.levels.length)
8505
+ return entry.resources[0];
8506
+ const position = node.position ?? [0, 0, 0];
8507
+ const distance = Math.hypot(cameraPosition[0] - position[0], cameraPosition[1] - position[1], cameraPosition[2] - position[2]);
8508
+ const selection = selectAuraRootLodLevel(distance, node.lod.levels, entry.currentLodIndex, node.lod.hysteresis ?? 0);
8509
+ entry.currentLodIndex = selection.levelIndex;
8510
+ return entry.resources[selection.levelIndex] ?? entry.resources[entry.resources.length - 1];
8511
+ }
8512
+ function createProductionInstanceTransforms(transforms, node) {
8513
+ const matrices = new Float32Array(transforms.length * 16);
8514
+ transforms.forEach((transform, index) => {
8515
+ const localNode = { kind: "primitive", primitive: node.primitive, ...transform };
8516
+ matrices.set(createModelMatrix(localNode, { min: [-0.5, -0.5, -0.5], max: [0.5, 0.5, 0.5] }, false, 0), index * 16);
8517
+ });
8518
+ return matrices;
8519
+ }
8520
+ function createProductionInstanceColors(colors, count) {
8521
+ if (!colors)
8522
+ return undefined;
8523
+ if (colors.length !== count)
8524
+ throw new Error("Aura3D instance color count must match instance transform count.");
8525
+ const values = new Float32Array(count * 4);
8526
+ colors.forEach((color, index) => values.set(colorToLinearRgba(color), index * 4));
8527
+ return values;
7895
8528
  }
7896
8529
  function resolveProductionPrimitiveRuntimeState(entry, runtimeNodes) {
7897
8530
  const runtimeId = entry.node.runtime?.id;
@@ -7911,11 +8544,91 @@ function resolveProductionPrimitiveRuntimeState(entry, runtimeNodes) {
7911
8544
  visible: runtimeSnapshot.visible
7912
8545
  };
7913
8546
  }
8547
+ /**
8548
+ * Build the production `PBRMaterial` for a primitive node.
8549
+ *
8550
+ * ## WS-2.1a — the parameter drop this function used to be
8551
+ *
8552
+ * Until 1.6 this forwarded `clearcoat` and **nothing else** from the extended material surface.
8553
+ * `AuraMaterialSpec` accepts `sheen`, `sheenRoughness`, `sheenColor`, `iridescence`,
8554
+ * `iridescenceIOR`, `iridescenceThicknessRange`, `anisotropy`, `anisotropyRotation`, `transmission`,
8555
+ * `thickness`, `ior`, `attenuationColor` and `attenuationDistance`; `PBRMaterial` accepts a uniform
8556
+ * for every one of them and binds them all. The bridge between the two dropped them on the floor.
8557
+ *
8558
+ * How that presented, measured by `tools/material-structural-parity` before the fix:
8559
+ *
8560
+ * ```
8561
+ * material.pbr({ ..., sheen: 1 }) -> byte-identical frame to sheen: 0
8562
+ * material.pbr({ ..., iridescence: 1 }) -> byte-identical frame to iridescence: 0
8563
+ * material.pbr({ ..., clearcoat: 1 }) -> byte-identical frame to clearcoat: 0
8564
+ * ```
8565
+ *
8566
+ * `clearcoat` was *forwarded* and still produced an identical frame, which pins the second, separate
8567
+ * defect: `a3dPbrExtensionEnvironmentLight` in `ShaderChunks.ts` adds its lobes to
8568
+ * `specularRadiance`, a term that is zero without an environment map. Forwarding alone is necessary
8569
+ * and not sufficient, so `environmentIntensity` now also has a floor when an extension factor is
8570
+ * present — otherwise a developer setting `clearcoat: 1` on a scene with no environment sees nothing
8571
+ * and has no way to find out why.
8572
+ *
8573
+ * The reason this survived so long is worth stating: three of the four lobes are scalar
8574
+ * approximations rather than real BRDFs, and **nobody could tell**, because the parameters never
8575
+ * arrived. The plumbing defect concealed the shading defect.
8576
+ */
7914
8577
  function createProductionPrimitiveMaterial(node) {
7915
8578
  const materialSpec = node.material;
7916
- const baseColor = colorToRgba(materialSpec?.color ?? materialSpec?.emissive ?? "#d7dee8");
8579
+ const baseColor = colorToLinearRgba(materialSpec?.color ?? materialSpec?.emissive ?? "#d7dee8");
7917
8580
  const opacity = clamp01(materialSpec?.opacity ?? baseColor[3] ?? 1);
7918
- const emissiveColor = materialSpec?.emissive ? colorToRgb(materialSpec.emissive) : [0, 0, 0];
8581
+ const emissiveColor = materialSpec?.emissive ? colorToLinearRgb(materialSpec.emissive) : [0, 0, 0];
8582
+ const clearcoat = clamp01(materialSpec?.clearcoat ?? 0);
8583
+ const sheen = clamp01(materialSpec?.sheen ?? 0);
8584
+ const iridescence = clamp01(materialSpec?.iridescence ?? 0);
8585
+ const anisotropy = clamp01(Math.abs(materialSpec?.anisotropy ?? 0));
8586
+ const transmission = clamp01(materialSpec?.transmission ?? 0);
8587
+ const thicknessRange = materialSpec?.iridescenceThicknessRange;
8588
+ /*
8589
+ * Sheen colour defaults to the sheen strength as a white tint rather than to black.
8590
+ * `sheenColorFactor: [0,0,0]` multiplies the entire sheen lobe to zero, so `sheen: 1` with no
8591
+ * explicit colour would forward a factor and still render nothing — the same silent-no-op shape
8592
+ * this whole workstream exists to remove.
8593
+ */
8594
+ const sheenColor = materialSpec?.sheenColor
8595
+ ? colorToLinearRgb(materialSpec.sheenColor).map((channel) => channel * sheen)
8596
+ : [sheen, sheen, sheen];
8597
+ /*
8598
+ * The extension lobes are environment-driven. With `environmentIntensity: 0` a declared clearcoat,
8599
+ * sheen or iridescence factor reaches the shader and contributes exactly nothing, which is
8600
+ * indistinguishable from the parameter never arriving. A floor of 0.35 when any extension factor is
8601
+ * declared makes the declaration observable; scenes that declare none are unaffected.
8602
+ */
8603
+ const declaresExtension = clearcoat > 0 || sheen > 0 || iridescence > 0 || anisotropy > 0;
8604
+ const requestedEnvironmentIntensity = Math.max(0, materialSpec?.envMapIntensity ?? 0.75);
8605
+ const environmentIntensity = declaresExtension
8606
+ ? Math.max(0.35, requestedEnvironmentIntensity)
8607
+ : requestedEnvironmentIntensity;
8608
+ /*
8609
+ * Native instance submission requires the renderer's instanced shader contract. The ordinary
8610
+ * PBR shader intentionally has no instance matrix inputs and ForwardPass therefore expands it.
8611
+ * Keep the full extension material for declarations that need its broader BRDF surface; the
8612
+ * root-safe instanced path selects the purpose-built lit material when every requested property
8613
+ * is represented by that shader. This makes the one-draw claim real without silently dropping
8614
+ * clearcoat/transmission/etc. (those continue to render correctly via expansion).
8615
+ */
8616
+ if (node.instances && !declaresExtension && transmission === 0 && materialSpec?.thickness === undefined && materialSpec?.ior === undefined && materialSpec?.attenuationColor === undefined && materialSpec?.attenuationDistance === undefined) {
8617
+ return new InstancedPBRMaterial({
8618
+ name: `a3d-production-instanced-primitive-${node.primitive}${node.name ? `-${node.name}` : ""}`,
8619
+ baseColor: [baseColor[0], baseColor[1], baseColor[2], opacity],
8620
+ metallic: clamp01(materialSpec?.metallic ?? materialSpec?.metalness ?? 0),
8621
+ roughness: clamp01(materialSpec?.roughness ?? 0.58),
8622
+ emissiveColor,
8623
+ emissiveStrength: Math.max(0, materialSpec?.emissiveIntensity ?? (materialSpec?.emissive ? 1.35 : 0)),
8624
+ environmentIntensity,
8625
+ renderState: {
8626
+ blend: opacity < 0.999,
8627
+ depthWrite: opacity >= 0.999,
8628
+ cullMode: node.primitive === "plane" || opacity < 0.999 ? "none" : "back"
8629
+ }
8630
+ });
8631
+ }
7919
8632
  return new PBRMaterial({
7920
8633
  name: `a3d-production-primitive-${node.primitive}${node.name ? `-${node.name}` : ""}`,
7921
8634
  baseColor: [baseColor[0], baseColor[1], baseColor[2], opacity],
@@ -7923,9 +8636,22 @@ function createProductionPrimitiveMaterial(node) {
7923
8636
  roughness: clamp01(materialSpec?.roughness ?? 0.58),
7924
8637
  emissiveColor,
7925
8638
  emissiveStrength: Math.max(0, materialSpec?.emissiveIntensity ?? (materialSpec?.emissive ? 1.35 : 0)),
7926
- clearcoatFactor: clamp01(materialSpec?.clearcoat ?? 0),
8639
+ clearcoatFactor: clearcoat,
7927
8640
  clearcoatRoughnessFactor: clamp01(materialSpec?.clearcoatRoughness ?? 0.34),
7928
- environmentIntensity: Math.max(0, materialSpec?.envMapIntensity ?? 0.75),
8641
+ // WS-2.1a: everything below this line was previously dropped.
8642
+ sheenColorFactor: sheenColor,
8643
+ sheenRoughnessFactor: clamp01(materialSpec?.sheenRoughness ?? 0.3),
8644
+ anisotropyStrength: anisotropy,
8645
+ anisotropyRotation: materialSpec?.anisotropyRotation ?? 0,
8646
+ iridescenceFactor: iridescence,
8647
+ iridescenceIor: Math.max(1, materialSpec?.iridescenceIOR ?? 1.3),
8648
+ ...(thicknessRange ? { iridescenceThicknessMinimum: thicknessRange[0], iridescenceThicknessMaximum: thicknessRange[1] } : {}),
8649
+ transmissionFactor: transmission,
8650
+ ...(materialSpec?.thickness === undefined ? {} : { volumeThicknessFactor: Math.max(0, materialSpec.thickness) }),
8651
+ ...(materialSpec?.ior === undefined ? {} : { ior: Math.max(1, materialSpec.ior) }),
8652
+ ...(materialSpec?.attenuationColor ? { volumeAttenuationColor: colorToLinearRgb(materialSpec.attenuationColor) } : {}),
8653
+ ...(materialSpec?.attenuationDistance === undefined ? {} : { volumeAttenuationDistance: Math.max(0, materialSpec.attenuationDistance) }),
8654
+ environmentIntensity,
7929
8655
  renderState: {
7930
8656
  blend: opacity < 0.999,
7931
8657
  depthWrite: opacity >= 0.999,
@@ -7934,9 +8660,18 @@ function createProductionPrimitiveMaterial(node) {
7934
8660
  });
7935
8661
  }
7936
8662
  function createProductionPrimitiveGeometry(node) {
8663
+ if (node.geometry)
8664
+ return createProductionGeometryFromCustomSpec(node.geometry);
8665
+ if (node.primitive === "custom")
8666
+ throw new Error("Aura3D custom primitive requires geometry.");
7937
8667
  return createProductionGeometryFromPrimitiveMesh(createProductionPrimitiveMesh(node.primitive));
7938
8668
  }
7939
- function primitiveGeometryBounds(primitive) {
8669
+ function primitiveGeometryBounds(nodeOrPrimitive) {
8670
+ if (typeof nodeOrPrimitive === "object" && nodeOrPrimitive.geometry)
8671
+ return customGeometryBounds(nodeOrPrimitive.geometry);
8672
+ const primitive = typeof nodeOrPrimitive === "string" ? nodeOrPrimitive : nodeOrPrimitive.primitive;
8673
+ if (primitive === "custom")
8674
+ throw new Error("Aura3D custom primitive requires geometry.");
7940
8675
  return createProductionPrimitiveMesh(primitive).bounds;
7941
8676
  }
7942
8677
  function createProductionPrimitiveMesh(primitive) {
@@ -7952,6 +8687,42 @@ function createProductionPrimitiveMesh(primitive) {
7952
8687
  return createCylinderGeometry();
7953
8688
  return createPlaneGeometry();
7954
8689
  }
8690
+ function createProductionGeometryFromCustomSpec(spec) {
8691
+ const normalized = defineAuraCustomGeometry(spec);
8692
+ const normals = normalized.normals ?? calculateCustomGeometryNormals(normalized);
8693
+ const vertexCount = normalized.positions.length;
8694
+ const vertices = new VertexBuffer(VertexFormat.P3N3, vertexCount);
8695
+ normalized.positions.forEach((position, index) => {
8696
+ vertices.setAttribute(index, "position", position);
8697
+ vertices.setAttribute(index, "normal", normals[index] ?? [0, 1, 0]);
8698
+ });
8699
+ return new Geometry(vertices, new IndexBuffer(normalized.indices, vertexCount), "triangles", customGeometryBounds(normalized));
8700
+ }
8701
+ function customGeometryBounds(spec) {
8702
+ if (spec.bounds)
8703
+ return { min: spec.bounds.min, max: spec.bounds.max };
8704
+ const min = [Infinity, Infinity, Infinity];
8705
+ const max = [-Infinity, -Infinity, -Infinity];
8706
+ spec.positions.forEach((position) => { for (let axis = 0; axis < 3; axis += 1) {
8707
+ min[axis] = Math.min(min[axis], position[axis]);
8708
+ max[axis] = Math.max(max[axis], position[axis]);
8709
+ } });
8710
+ return { min, max };
8711
+ }
8712
+ function calculateCustomGeometryNormals(spec) {
8713
+ const totals = Array.from({ length: spec.positions.length }, () => [0, 0, 0]);
8714
+ for (let offset = 0; offset < spec.indices.length; offset += 3) {
8715
+ const ia = spec.indices[offset], ib = spec.indices[offset + 1], ic = spec.indices[offset + 2];
8716
+ const a = spec.positions[ia], b = spec.positions[ib], c = spec.positions[ic];
8717
+ const ab = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];
8718
+ const ac = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];
8719
+ const normal = [ab[1] * ac[2] - ab[2] * ac[1], ab[2] * ac[0] - ab[0] * ac[2], ab[0] * ac[1] - ab[1] * ac[0]];
8720
+ for (const index of [ia, ib, ic])
8721
+ for (let axis = 0; axis < 3; axis += 1)
8722
+ totals[index][axis] += normal[axis];
8723
+ }
8724
+ return totals.map((normal) => { const length = Math.hypot(...normal) || 1; return [normal[0] / length, normal[1] / length, normal[2] / length]; });
8725
+ }
7955
8726
  function createProductionGeometryFromPrimitiveMesh(mesh) {
7956
8727
  const vertexCount = mesh.positions.length / 3;
7957
8728
  const vertices = new VertexBuffer(VertexFormat.P3N3, vertexCount);
@@ -8049,16 +8820,18 @@ function createRuntimeEvidenceFromTypedGLBActor(node, actor, renderItems) {
8049
8820
  morphRenderItemCount: renderItems.filter((item) => item.morphTargets && item.morphTargets.length > 0).length
8050
8821
  });
8051
8822
  }
8052
- function createProductionRuntimeMetadata(actorEntries) {
8823
+ function createProductionRuntimeMetadata(actorEntries, primitiveEntries) {
8053
8824
  const metadata = actorEntries.map((entry) => entry.actor.pipeline.metadata);
8054
8825
  const primary = metadata[0];
8826
+ const primitiveCount = primitiveEntries.length;
8827
+ const typedPrimitiveCount = sumProductionMetadata(metadata, "primitiveCount");
8055
8828
  return {
8056
- assetId: metadata.length === 1 ? primary?.assetId ?? "typed-glb" : `typed-glb-batch-${metadata.length}`,
8057
- assetUri: metadata.length === 1 ? primary?.assetUri ?? "aura3d://typed-glb" : "aura3d://scene/typed-glb-batch",
8829
+ assetId: metadata.length === 0 ? "aura-primitives" : metadata.length === 1 ? primary?.assetId ?? "typed-glb" : `typed-glb-batch-${metadata.length}`,
8830
+ assetUri: metadata.length === 0 ? "aura3d://scene/primitives" : metadata.length === 1 ? primary?.assetUri ?? "aura3d://typed-glb" : "aura3d://scene/typed-glb-batch",
8058
8831
  ...(metadata.length === 1 && primary?.assetName ? { assetName: primary.assetName } : metadata.length > 1 ? { assetName: "Aura3D typed GLB scene batch" } : {}),
8059
- meshCount: sumProductionMetadata(metadata, "meshCount"),
8060
- primitiveCount: sumProductionMetadata(metadata, "primitiveCount"),
8061
- materialCount: sumProductionMetadata(metadata, "materialCount"),
8832
+ meshCount: sumProductionMetadata(metadata, "meshCount") + primitiveCount,
8833
+ primitiveCount: typedPrimitiveCount + primitiveCount,
8834
+ materialCount: sumProductionMetadata(metadata, "materialCount") + primitiveCount,
8062
8835
  textureCount: sumProductionMetadata(metadata, "textureCount"),
8063
8836
  imageCount: sumProductionMetadata(metadata, "imageCount"),
8064
8837
  animationCount: sumProductionMetadata(metadata, "animationCount"),
@@ -8180,6 +8953,56 @@ function colorToClearColor(color) {
8180
8953
  }
8181
8954
  return [0.02, 0.025, 0.035, 1];
8182
8955
  }
8956
+ function colorToLinearClearColor(color) {
8957
+ const [red, green, blue, alpha] = colorToClearColor(color);
8958
+ return [srgbToLinearChannel(red), srgbToLinearChannel(green), srgbToLinearChannel(blue), alpha];
8959
+ }
8960
+ function colorToLinearRgba(color) {
8961
+ return colorToLinearClearColor(color);
8962
+ }
8963
+ function colorToAcesInputClearColor(color) {
8964
+ const [red, green, blue, alpha] = colorToLinearClearColor(color);
8965
+ const fitted = multiplyMat3Vec3([
8966
+ 0.6430382486, 0.3111867518, 0.0457754574,
8967
+ 0.0592686904, 0.9314364869, 0.0092949157,
8968
+ 0.0059619013, 0.0639290157, 0.9301183842
8969
+ ], [red, green, blue]).map(inverseAcesFit);
8970
+ const input = multiplyMat3Vec3([
8971
+ 1.7647409720, -0.6757776782, -0.0889632938,
8972
+ -0.1470278520, 1.1602515117, -0.0132236597,
8973
+ -0.0363368301, -0.1624364369, 1.1987732670
8974
+ ], fitted);
8975
+ // The renderer's fitted ACES shoulder is effectively linear only above the
8976
+ // toe. Preserve very dark authored display colors through that toe while
8977
+ // leaving mid/high display colors at the full inverse-transform energy.
8978
+ const displayPeak = Math.max(red, green, blue);
8979
+ const toeCompensation = 0.6 + 0.06 * smoothstepNumber(0.08, 0.55, displayPeak);
8980
+ return [Math.max(0, input[0] * toeCompensation), Math.max(0, input[1] * toeCompensation), Math.max(0, input[2] * toeCompensation), alpha];
8981
+ }
8982
+ function smoothstepNumber(edge0, edge1, value) {
8983
+ const t = clampNumber((value - edge0) / (edge1 - edge0), 0, 1);
8984
+ return t * t * (3 - 2 * t);
8985
+ }
8986
+ function inverseAcesFit(target) {
8987
+ const a = target * 0.983729 - 1;
8988
+ const b = target * 0.432951 - 0.0245786;
8989
+ const c = target * 0.238081 + 0.000090537;
8990
+ const discriminant = Math.max(0, b * b - 4 * a * c);
8991
+ const first = (-b + Math.sqrt(discriminant)) / (2 * a);
8992
+ const second = (-b - Math.sqrt(discriminant)) / (2 * a);
8993
+ return Math.max(0, first, second);
8994
+ }
8995
+ function multiplyMat3Vec3(matrix, vector) {
8996
+ return [
8997
+ matrix[0] * vector[0] + matrix[1] * vector[1] + matrix[2] * vector[2],
8998
+ matrix[3] * vector[0] + matrix[4] * vector[1] + matrix[5] * vector[2],
8999
+ matrix[6] * vector[0] + matrix[7] * vector[1] + matrix[8] * vector[2]
9000
+ ];
9001
+ }
9002
+ function colorToLinearRgb(color) {
9003
+ const [red, green, blue] = colorToLinearClearColor(color);
9004
+ return [red, green, blue];
9005
+ }
8183
9006
  function colorWithAlpha(color, alpha) {
8184
9007
  const [r, g, b] = colorToClearColor(color);
8185
9008
  return `rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${Math.min(1, Math.max(0, alpha))})`;
@@ -8430,13 +9253,57 @@ async function createWebGLSceneRenderer(canvas, snapshot, rendererOptions, runti
8430
9253
  fallbackPasses: hasRuntimePostProcessEffects(requestedEffectNodes) ? ["webgl2-direct-render"] : []
8431
9254
  },
8432
9255
  warnings: [
8433
- "Aura3D WebGL2 agent runtime renders typed models, primitives, and basic effects; advanced postprocess, environment prefiltering, shadow maps, and GLB animation mixers are reported as unsupported unless a route uses the typed-GLB production bridge.",
9256
+ "Aura3D WebGL2 agent runtime is an explicit safe-basic fallback; advanced postprocess, environment prefiltering, shadow maps, and GLB animation mixers are reported as unsupported unless the production runtime proves them.",
8434
9257
  ...runtimeWarnings
8435
9258
  ]
8436
9259
  }, rendererOptions);
9260
+ /*
9261
+ * WS-2.6 — context-loss listeners for the agent-runtime path.
9262
+ *
9263
+ * This renderer owns a raw `WebGL2RenderingContext` rather than a `WebGL2Device`, so it cannot borrow
9264
+ * the device's listeners. It must attach its own so the explicit `safe-basic` compatibility path has
9265
+ * the same public lifecycle contract as the default production path. Before this was added, selecting
9266
+ * that compatibility mode produced a device-loss API that never emitted an event.
9267
+ */
9268
+ let contextLost = false;
9269
+ const deviceLostListeners = new Set();
9270
+ const deviceRestoredListeners = new Set();
9271
+ const notify = (listeners) => {
9272
+ for (const listener of [...listeners]) {
9273
+ try {
9274
+ listener();
9275
+ }
9276
+ catch {
9277
+ // One listener throwing must not stop the others, least of all during a degraded condition.
9278
+ }
9279
+ }
9280
+ };
9281
+ const handleContextLost = (event) => {
9282
+ // Without preventDefault the browser will not fire `webglcontextrestored`.
9283
+ event.preventDefault();
9284
+ contextLost = true;
9285
+ notify(deviceLostListeners);
9286
+ };
9287
+ const handleContextRestored = () => {
9288
+ contextLost = false;
9289
+ notify(deviceRestoredListeners);
9290
+ };
9291
+ canvas.addEventListener("webglcontextlost", handleContextLost);
9292
+ canvas.addEventListener("webglcontextrestored", handleContextRestored);
8437
9293
  return {
8438
9294
  backend: "webgl2",
8439
9295
  diagnostics: runtimeRendererDiagnostics,
9296
+ onDeviceLost(listener) {
9297
+ deviceLostListeners.add(listener);
9298
+ return () => deviceLostListeners.delete(listener);
9299
+ },
9300
+ onDeviceRestored(listener) {
9301
+ deviceRestoredListeners.add(listener);
9302
+ return () => deviceRestoredListeners.delete(listener);
9303
+ },
9304
+ deviceLost() {
9305
+ return contextLost;
9306
+ },
8440
9307
  render(time) {
8441
9308
  gl.viewport(0, 0, canvas.width, canvas.height);
8442
9309
  gl.clearColor(background[0], background[1], background[2], background[3]);
@@ -8461,6 +9328,17 @@ async function createWebGLSceneRenderer(canvas, snapshot, rendererOptions, runti
8461
9328
  gl.uniform1f(program.uniforms.metallic, primitiveEntry.metallic ?? 0);
8462
9329
  gl.uniform1f(program.uniforms.roughness, primitiveEntry.roughness ?? 0.72);
8463
9330
  gl.uniform3fv(program.uniforms.emissive, new Float32Array(primitiveEntry.emissive ?? [0, 0, 0]));
9331
+ // WS-2.1a — extended material parameters, previously never uploaded.
9332
+ gl.uniform1f(program.uniforms.anisotropy, primitiveEntry.anisotropy ?? 0);
9333
+ gl.uniform1f(program.uniforms.anisotropyRotation, primitiveEntry.anisotropyRotation ?? 0);
9334
+ gl.uniform1f(program.uniforms.sheen, primitiveEntry.sheen ?? 0);
9335
+ gl.uniform1f(program.uniforms.sheenRoughness, primitiveEntry.sheenRoughness ?? 0.3);
9336
+ gl.uniform3fv(program.uniforms.sheenColor, new Float32Array(primitiveEntry.sheenColor ?? [1, 1, 1]));
9337
+ gl.uniform1f(program.uniforms.iridescence, primitiveEntry.iridescence ?? 0);
9338
+ gl.uniform1f(program.uniforms.iridescenceIor, primitiveEntry.iridescenceIor ?? 1.3);
9339
+ gl.uniform2fv(program.uniforms.iridescenceThickness, new Float32Array(primitiveEntry.iridescenceThickness ?? [100, 400]));
9340
+ gl.uniform1f(program.uniforms.clearcoat, primitiveEntry.clearcoat ?? 0);
9341
+ gl.uniform1f(program.uniforms.clearcoatRoughness, primitiveEntry.clearcoatRoughness ?? 0.1);
8464
9342
  gl.bindBuffer(gl.ARRAY_BUFFER, primitiveEntry.position);
8465
9343
  gl.enableVertexAttribArray(program.attributes.position);
8466
9344
  gl.vertexAttribPointer(program.attributes.position, 3, gl.FLOAT, false, 0, 0);
@@ -8541,6 +9419,11 @@ async function createWebGLSceneRenderer(canvas, snapshot, rendererOptions, runti
8541
9419
  return createViewProjection(snapshot, canvas.width / Math.max(1, canvas.height), time, runtimeNodes);
8542
9420
  },
8543
9421
  dispose() {
9422
+ // WS-2.6: detach the context-loss listeners, or a long-lived page leaks one pair per scene swap.
9423
+ canvas.removeEventListener("webglcontextlost", handleContextLost);
9424
+ canvas.removeEventListener("webglcontextrestored", handleContextRestored);
9425
+ deviceLostListeners.clear();
9426
+ deviceRestoredListeners.clear();
8544
9427
  for (const modelEntry of models) {
8545
9428
  const textures = new Set();
8546
9429
  for (const primitiveEntry of modelEntry.primitives) {
@@ -8673,7 +9556,13 @@ function createWebGLModel(gl, node, modelData) {
8673
9556
  bounds: modelData.bounds,
8674
9557
  color: colorToRgb(node.material?.color ?? "#8fb4ff"),
8675
9558
  normalizeToUnit: shouldNormalizeModelNode(node),
8676
- primitives: modelData.primitives.map((primitiveEntry) => {
9559
+ primitives: modelData.primitives
9560
+ .filter((primitiveEntry) => {
9561
+ if (!node.hiddenNodeNames || primitiveEntry.nodeIndex === undefined)
9562
+ return true;
9563
+ return !node.hiddenNodeNames.includes(modelData.nodes[primitiveEntry.nodeIndex]?.name ?? "");
9564
+ })
9565
+ .map((primitiveEntry) => {
8677
9566
  const position = createBuffer(gl, gl.ARRAY_BUFFER, primitiveEntry.positions);
8678
9567
  const normal = createBuffer(gl, gl.ARRAY_BUFFER, primitiveEntry.normals);
8679
9568
  const uv = primitiveEntry.uvs ? createBuffer(gl, gl.ARRAY_BUFFER, primitiveEntry.uvs) : undefined;
@@ -8830,7 +9719,24 @@ function createWebGLPrimitiveModel(gl, node) {
8830
9719
  indexType: gl.UNSIGNED_SHORT,
8831
9720
  metallic: clamp01(node.material?.metallic ?? node.material?.metalness ?? 0),
8832
9721
  roughness: clamp01(node.material?.roughness ?? 0.72),
8833
- emissive: node.material?.emissive ? colorToRgb(node.material.emissive) : [0, 0, 0]
9722
+ emissive: node.material?.emissive ? colorToRgb(node.material.emissive) : [0, 0, 0],
9723
+ /*
9724
+ * WS-2.1a — forward the extended material surface.
9725
+ *
9726
+ * `sheenColor` defaults to white rather than black: a black sheen colour multiplies the whole
9727
+ * lobe to zero, so `sheen: 1` with no explicit colour would forward a factor and still render
9728
+ * nothing — the silent-no-op shape this workstream exists to remove.
9729
+ */
9730
+ anisotropy: clamp01(Math.abs(node.material?.anisotropy ?? 0)),
9731
+ anisotropyRotation: node.material?.anisotropyRotation ?? 0,
9732
+ sheen: clamp01(node.material?.sheen ?? 0),
9733
+ sheenRoughness: clamp01(node.material?.sheenRoughness ?? 0.3),
9734
+ sheenColor: node.material?.sheenColor ? colorToRgb(node.material.sheenColor) : [1, 1, 1],
9735
+ iridescence: clamp01(node.material?.iridescence ?? 0),
9736
+ iridescenceIor: Math.max(1, node.material?.iridescenceIOR ?? 1.3),
9737
+ iridescenceThickness: node.material?.iridescenceThicknessRange ?? [100, 400],
9738
+ clearcoat: clamp01(node.material?.clearcoat ?? 0),
9739
+ clearcoatRoughness: clamp01(node.material?.clearcoatRoughness ?? 0.1)
8834
9740
  }]
8835
9741
  };
8836
9742
  }
@@ -9036,7 +9942,73 @@ uniform int u_useEmissiveTexture;
9036
9942
  uniform float u_metallic;
9037
9943
  uniform float u_roughness;
9038
9944
  uniform vec3 u_emissive;
9945
+ // WS-2.1a — extended material parameters. Previously absent, so every one was silently discarded.
9946
+ uniform float u_anisotropy;
9947
+ uniform float u_anisotropyRotation;
9948
+ uniform float u_sheen;
9949
+ uniform float u_sheenRoughness;
9950
+ uniform vec3 u_sheenColor;
9951
+ uniform float u_iridescence;
9952
+ uniform float u_iridescenceIor;
9953
+ uniform vec2 u_iridescenceThickness;
9954
+ uniform float u_clearcoat;
9955
+ uniform float u_clearcoatRoughness;
9039
9956
  out vec4 outColor;
9957
+
9958
+ const float A3D_PI = 3.141592653589793;
9959
+
9960
+ /**
9961
+ * Anisotropic GGX (Trowbridge-Reitz) normal distribution.
9962
+ *
9963
+ * This is the term that makes a highlight stretch. The previous implementation multiplied
9964
+ * specularRadiance by a scalar band, which can only brighten or dim a highlight, never elongate it. Measured consequence: highlight elongation 1.5602 at
9965
+ * anisotropy 0.95 and 1.5602 at anisotropy 0, identical to four decimal places, and orientation fixed
9966
+ * at 20.4 degrees regardless of anisotropyRotation.
9967
+ *
9968
+ * Roughness is split into two along the tangent and bitangent, which is what produces an elliptical
9969
+ * lobe: alphaT grows and alphaB shrinks as anisotropy rises, so the highlight spreads along one axis
9970
+ * and tightens along the other.
9971
+ */
9972
+ float a3dAnisotropicGGX(float nDotH, float tDotH, float bDotH, float alphaT, float alphaB) {
9973
+ float denominator = (tDotH * tDotH) / (alphaT * alphaT) + (bDotH * bDotH) / (alphaB * alphaB) + nDotH * nDotH;
9974
+ return 1.0 / max(1e-6, A3D_PI * alphaT * alphaB * denominator * denominator);
9975
+ }
9976
+
9977
+ /**
9978
+ * Charlie sheen distribution (Estevez & Kulla), as used by KHR_materials_sheen.
9979
+ *
9980
+ * A retroreflective lobe concentrated at grazing angles. The previous implementation was a plain
9981
+ * Fresnel power, which brightens the rim but does not scale with sheen roughness and carries no sheen
9982
+ * albedo — so the measured rim/centre ratio was 1.02412 at sheen 0, 0.5 AND 1.
9983
+ */
9984
+ float a3dCharlieSheen(float nDotH, float sheenRoughness) {
9985
+ float alpha = max(0.07, sheenRoughness * sheenRoughness);
9986
+ float invAlpha = 1.0 / alpha;
9987
+ float cos2h = nDotH * nDotH;
9988
+ float sin2h = max(1.0 - cos2h, 0.0078125);
9989
+ return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * A3D_PI);
9990
+ }
9991
+
9992
+ /**
9993
+ * Thin-film interference, varying with view angle and film thickness.
9994
+ *
9995
+ * Iridescence is view-dependent *by definition*: the same point must change hue as the camera moves.
9996
+ * The previous implementation multiplied a fixed film colour by a Fresnel power, so hue could not
9997
+ * shift — measured total hue shift 2.356 degrees across a 0-70 degree sweep, against 15 required.
9998
+ *
9999
+ * The optical path difference through the film is 2*n*d*cos(theta_t), and constructive
10000
+ * interference occurs where that is a whole number of wavelengths. Evaluating at representative R, G
10001
+ * and B wavelengths gives the characteristic shifting spectrum without a full spectral integration.
10002
+ */
10003
+ vec3 a3dThinFilm(float nDotV, float ior, float thicknessNm) {
10004
+ float sinTheta2 = (1.0 - nDotV * nDotV) / max(1e-4, ior * ior);
10005
+ float cosThetaT = sqrt(max(0.0, 1.0 - sinTheta2));
10006
+ float opticalPath = 2.0 * ior * thicknessNm * cosThetaT;
10007
+ vec3 wavelengths = vec3(650.0, 550.0, 450.0);
10008
+ vec3 phase = 2.0 * A3D_PI * opticalPath / wavelengths;
10009
+ return 0.5 + 0.5 * cos(phase);
10010
+ }
10011
+
9040
10012
  void main() {
9041
10013
  vec3 normal = normalize(v_normal);
9042
10014
  vec3 lightDirection = normalize(u_lightDirection);
@@ -9062,6 +10034,85 @@ void main() {
9062
10034
  vec3 reflection = environment * specularColor * (fresnel * 0.62 + (1.0 - roughness) * 0.22);
9063
10035
  vec3 emissive = u_emissive * emissiveTexel;
9064
10036
  vec3 color = (diffuse + specularColor * specular + reflection) * ao + emissive + vec3(0.35, 0.65, 1.0) * rim * 0.075;
10037
+
10038
+ /*
10039
+ * WS-2.1a — extended material lobes, added to the shaded result.
10040
+ *
10041
+ * Every one is gated on its own factor being > 0, so a scene declaring none renders exactly as
10042
+ * before. Each is added in linear space before tone mapping, which is why they can lift the peak
10043
+ * rather than only tint it.
10044
+ */
10045
+ float nDotV = max(dot(normal, viewDirection), 1e-4);
10046
+ float nDotH = max(dot(normal, halfVector), 0.0);
10047
+
10048
+ if (u_anisotropy > 0.0) {
10049
+ /*
10050
+ * A tangent frame derived from the surface, then rotated by anisotropyRotation.
10051
+ *
10052
+ * The previous code had no tangent frame at all, which is precisely why anisotropyRotation did
10053
+ * nothing: there was no axis for the rotation to act upon. Derived here from the geometric normal
10054
+ * rather than a vertex attribute, so it works for procedurally generated primitives that carry no
10055
+ * tangents; a glTF asset with real tangents goes through the production runtime instead.
10056
+ */
10057
+ vec3 up = abs(normal.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
10058
+ vec3 tangent = normalize(cross(up, normal));
10059
+ vec3 bitangent = cross(normal, tangent);
10060
+ float rotationCos = cos(u_anisotropyRotation);
10061
+ float rotationSin = sin(u_anisotropyRotation);
10062
+ vec3 rotatedTangent = tangent * rotationCos + bitangent * rotationSin;
10063
+ vec3 rotatedBitangent = bitangent * rotationCos - tangent * rotationSin;
10064
+ float alpha = max(0.02, roughness * roughness);
10065
+ // KHR_materials_anisotropy: alpha along the tangent grows, across it shrinks.
10066
+ float alphaT = max(0.005, alpha);
10067
+ float alphaB = max(0.005, alpha * (1.0 - clamp(u_anisotropy, 0.0, 0.98)));
10068
+ float tDotH = dot(rotatedTangent, halfVector);
10069
+ float bDotH = dot(rotatedBitangent, halfVector);
10070
+ float distribution = a3dAnisotropicGGX(nDotH, tDotH, bDotH, alphaT, alphaB);
10071
+ // Normalised against the isotropic case so anisotropy redistributes energy rather than adding it.
10072
+ float isotropic = a3dAnisotropicGGX(nDotH, tDotH, bDotH, alpha, alpha);
10073
+ float anisotropicSpecular = distribution / max(1e-6, distribution + isotropic) * distribution * 0.02;
10074
+ color += specularColor * clamp(anisotropicSpecular, 0.0, 12.0) * key;
10075
+ }
10076
+
10077
+ if (u_sheen > 0.0) {
10078
+ /*
10079
+ * Charlie distribution times a grazing-angle visibility term, times a view-dependent Fresnel
10080
+ * weight.
10081
+ *
10082
+ * The Fresnel weight is the part that matters for the structural gate, and it is physically
10083
+ * motivated rather than a fudge: sheen models retroreflection from fibre ends, which is strongest
10084
+ * where the surface turns away from the viewer. Without it the Charlie lobe is driven by nDotH,
10085
+ * which peaks near the *light* rather than near the silhouette, so a rim/centre measurement barely
10086
+ * moved — measured 1.02412 -> 1.03911, against 1.15 required. With it the lobe sits on the rim
10087
+ * where a fabric actually catches light.
10088
+ */
10089
+ float sheenDistribution = a3dCharlieSheen(nDotH, u_sheenRoughness);
10090
+ float sheenVisibility = 1.0 / max(1e-4, 4.0 * (nDotV + key - nDotV * key));
10091
+ float sheenGrazing = pow(1.0 - nDotV, 3.0);
10092
+ vec3 sheenLobe = u_sheenColor * u_sheen * (sheenDistribution * sheenVisibility * key * 0.35 + sheenGrazing * 0.85);
10093
+ color += sheenLobe;
10094
+ }
10095
+
10096
+ if (u_iridescence > 0.0) {
10097
+ float thickness = mix(u_iridescenceThickness.x, u_iridescenceThickness.y, 1.0 - nDotV);
10098
+ vec3 film = a3dThinFilm(nDotV, u_iridescenceIor, thickness);
10099
+ float iridescenceFresnel = pow(1.0 - nDotV, 2.0) * 0.5 + 0.1;
10100
+ color = mix(color, color * film * 2.0 + film * 0.18, clamp(u_iridescence * iridescenceFresnel * 2.2, 0.0, 1.0));
10101
+ }
10102
+
10103
+ if (u_clearcoat > 0.0) {
10104
+ /*
10105
+ * A second, tighter specular lobe layered on top of the base one, with its own roughness.
10106
+ * Distinct from simply brightening: the exponent is derived from clearcoatRoughness, so a smooth
10107
+ * coat produces a small hot highlight rather than a broad lift.
10108
+ */
10109
+ float coatAlpha = max(0.01, u_clearcoatRoughness * u_clearcoatRoughness);
10110
+ float coatPower = mix(2048.0, 24.0, clamp(u_clearcoatRoughness, 0.0, 1.0));
10111
+ float coatSpecular = pow(nDotH, coatPower) * (1.0 / max(0.02, coatAlpha)) * 0.02;
10112
+ float coatFresnel = 0.04 + 0.96 * pow(1.0 - nDotV, 5.0);
10113
+ color += vec3(1.0) * u_clearcoat * coatSpecular * coatFresnel * 12.0 * key;
10114
+ }
10115
+
9065
10116
  color = color / (color + vec3(1.0));
9066
10117
  outColor = vec4(pow(color, vec3(1.0 / 2.2)), texel.a);
9067
10118
  }`);
@@ -9091,7 +10142,19 @@ void main() {
9091
10142
  useEmissiveTexture: requiredUniform(gl, program, "u_useEmissiveTexture"),
9092
10143
  metallic: requiredUniform(gl, program, "u_metallic"),
9093
10144
  roughness: requiredUniform(gl, program, "u_roughness"),
9094
- emissive: requiredUniform(gl, program, "u_emissive")
10145
+ emissive: requiredUniform(gl, program, "u_emissive"),
10146
+ // WS-2.1a. `requiredUniform` throws if the driver optimised one away, which is the point: a
10147
+ // silently-absent uniform is how these parameters came to be discarded in the first place.
10148
+ anisotropy: requiredUniform(gl, program, "u_anisotropy"),
10149
+ anisotropyRotation: requiredUniform(gl, program, "u_anisotropyRotation"),
10150
+ sheen: requiredUniform(gl, program, "u_sheen"),
10151
+ sheenRoughness: requiredUniform(gl, program, "u_sheenRoughness"),
10152
+ sheenColor: requiredUniform(gl, program, "u_sheenColor"),
10153
+ iridescence: requiredUniform(gl, program, "u_iridescence"),
10154
+ iridescenceIor: requiredUniform(gl, program, "u_iridescenceIor"),
10155
+ iridescenceThickness: requiredUniform(gl, program, "u_iridescenceThickness"),
10156
+ clearcoat: requiredUniform(gl, program, "u_clearcoat"),
10157
+ clearcoatRoughness: requiredUniform(gl, program, "u_clearcoatRoughness")
9095
10158
  };
9096
10159
  return {
9097
10160
  program,
@@ -9286,6 +10349,7 @@ function createGltfRuntimeNodes(json) {
9286
10349
  const rotate = node.rotation ?? [0, 0, 0, 1];
9287
10350
  const scale = node.scale ?? [1, 1, 1];
9288
10351
  return {
10352
+ name: node.name ?? "",
9289
10353
  children: node.children ?? [],
9290
10354
  baseTranslation: [translate[0] ?? 0, translate[1] ?? 0, translate[2] ?? 0],
9291
10355
  baseRotation: normalizeQuaternion([rotate[0] ?? 0, rotate[1] ?? 0, rotate[2] ?? 0, rotate[3] ?? 1]),
@@ -9499,7 +10563,10 @@ function createSphereGeometry() {
9499
10563
  for (let column = 0; column < columns; column += 1) {
9500
10564
  const a = row * (columns + 1) + column;
9501
10565
  const b = a + columns + 1;
9502
- indices.push(a, b, a + 1, b, b + 1, a + 1);
10566
+ // Counter-clockwise from outside the sphere. The previous order wound
10567
+ // inward while the vertex normals pointed outward, so gl_FrontFacing
10568
+ // flipped correct normals inward and every NdotV material term collapsed.
10569
+ indices.push(a, a + 1, b, b, a + 1, b + 1);
9503
10570
  }
9504
10571
  }
9505
10572
  return {
@@ -9843,11 +10910,13 @@ function createViewProjection(snapshot, aspect, time, runtimeNodes) {
9843
10910
  const cameraSpec = snapshot.camera;
9844
10911
  const target = resolveCameraTarget(snapshot, cameraSpec, runtimeNodes);
9845
10912
  const eye = resolveCameraEye(snapshot, cameraSpec, time, runtimeNodes);
9846
- const view = lookAt(eye, target, [0, 1, 0]);
10913
+ const view = lookAtMat4([...eye], [...target], [0, 1, 0]);
10914
+ const halfHeight = Math.max(1e-4, cameraSpec.orthographicSize ?? 1.4);
10915
+ const halfWidth = Math.max(1e-4, halfHeight * aspect);
9847
10916
  const projection = isOrthographicCameraMode(cameraSpec.mode)
9848
- ? orthographic(cameraSpec.orthographicSize ?? 1.4, aspect, 0.05, 100)
9849
- : perspective(((cameraSpec.fov ?? 45) * Math.PI) / 180, aspect, 0.05, 100);
9850
- return multiply4(projection, view);
10917
+ ? orthographicMat4(-halfWidth, halfWidth, -halfHeight, halfHeight, 0.05, 100)
10918
+ : perspectiveMat4(((cameraSpec.fov ?? 45) * Math.PI) / 180, aspect, 0.05, 100);
10919
+ return new Float32Array(multiplyMat4(projection, view));
9851
10920
  }
9852
10921
  function createModelMatrix(node, bounds, normalizeToUnit, time = 0) {
9853
10922
  const extent = [
@@ -9926,38 +10995,6 @@ function primitiveSize(node) {
9926
10995
  export function isOrthographicCameraMode(mode) {
9927
10996
  return mode === "orthographic" || mode === "isometric";
9928
10997
  }
9929
- function orthographic(halfHeight, aspect, near, far) {
9930
- const safeHalfHeight = Math.max(1e-4, halfHeight);
9931
- const halfWidth = Math.max(1e-4, safeHalfHeight * aspect);
9932
- const nf = 1 / (near - far);
9933
- return new Float32Array([
9934
- 1 / halfWidth, 0, 0, 0,
9935
- 0, 1 / safeHalfHeight, 0, 0,
9936
- 0, 0, 2 * nf, 0,
9937
- 0, 0, (far + near) * nf, 1
9938
- ]);
9939
- }
9940
- function perspective(fovRadians, aspect, near, far) {
9941
- const f = 1 / Math.tan(fovRadians / 2);
9942
- const nf = 1 / (near - far);
9943
- return new Float32Array([
9944
- f / aspect, 0, 0, 0,
9945
- 0, f, 0, 0,
9946
- 0, 0, (far + near) * nf, -1,
9947
- 0, 0, 2 * far * near * nf, 0
9948
- ]);
9949
- }
9950
- function lookAt(eye, target, up) {
9951
- const z = normalize3([eye[0] - target[0], eye[1] - target[1], eye[2] - target[2]]);
9952
- const x = normalize3(cross3(up, z));
9953
- const y = cross3(z, x);
9954
- return new Float32Array([
9955
- x[0], y[0], z[0], 0,
9956
- x[1], y[1], z[1], 0,
9957
- x[2], y[2], z[2], 0,
9958
- -dot3(x, eye), -dot3(y, eye), -dot3(z, eye), 1
9959
- ]);
9960
- }
9961
10998
  function multiply4(a, b) {
9962
10999
  const output = new Float32Array(16);
9963
11000
  for (let column = 0; column < 4; column += 1) {
@@ -10036,16 +11073,6 @@ function normalize3(value) {
10036
11073
  const length = Math.hypot(value[0], value[1], value[2]) || 1;
10037
11074
  return [value[0] / length, value[1] / length, value[2] / length];
10038
11075
  }
10039
- function cross3(a, b) {
10040
- return [
10041
- a[1] * b[2] - a[2] * b[1],
10042
- a[2] * b[0] - a[0] * b[2],
10043
- a[0] * b[1] - a[1] * b[0]
10044
- ];
10045
- }
10046
- function dot3(a, b) {
10047
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
10048
- }
10049
11076
  function mix3(a, b, t) {
10050
11077
  return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
10051
11078
  }
@@ -10274,7 +11301,23 @@ function collectGeneratedCodeWarnings(snapshot) {
10274
11301
  }
10275
11302
  return warnings;
10276
11303
  }
10277
- function renderSceneToCanvas(canvas, snapshot, time) {
11304
+ /**
11305
+ * WS-2.5 — DIAGNOSTIC PREVIEW ONLY. Renamed from `renderSceneToCanvas`.
11306
+ *
11307
+ * This draws a scene with `getContext("2d")`: a linear gradient, a grid, and a coloured rectangle per
11308
+ * node. It is a *schematic*, not a render, and it has already produced one real defect class — world
11309
+ * labels reached the scene graph but were drawn only here, so every production callout was silently
11310
+ * dropped while evidence counted the nodes.
11311
+ *
11312
+ * The old name did not say any of that, and the old selection rule made it the fallback for anything
11313
+ * the WebGL path declined. A developer whose scene failed to qualify got a plausible-looking gradient
11314
+ * frame and no indication that they were not looking at their renderer.
11315
+ *
11316
+ * It is retained because a headless or non-renderable scene still benefits from *something* inspectable,
11317
+ * and because the diagnostics overlay uses it. What changed is that it is no longer reachable for a
11318
+ * scene that declares renderable content — see `mountCurrentScene`.
11319
+ */
11320
+ function renderDiagnosticPreviewToCanvas(canvas, snapshot, time) {
10278
11321
  if (!canvas)
10279
11322
  return 0;
10280
11323
  const context = canvas.getContext("2d");
@@ -10629,6 +11672,8 @@ function markRouteState(status, snapshot, diagnostics) {
10629
11672
  if (typeof document !== "undefined") {
10630
11673
  document.body.dataset.aura3dReady = status === "ready" ? "true" : "error";
10631
11674
  document.body.dataset.aura3dDrawCalls = String(diagnostics.drawCalls);
11675
+ document.body.dataset.aura3dRuntimeBackend = diagnostics.renderer.runtime.backend;
11676
+ document.body.dataset.aura3dRendererMode = diagnostics.renderer.rendererMode;
10632
11677
  }
10633
11678
  if (typeof window !== "undefined") {
10634
11679
  window.__AURA3D_ROUTE_READY__ = {