@babylonjs/lite 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/index.js +512 -512
  2. package/dist/index.js.map +1 -1
  3. package/index.d.ts +829 -28
  4. package/lib/audio/analyzer.js +65 -0
  5. package/lib/audio/analyzer.js.map +1 -0
  6. package/lib/audio/audio-bus.js +38 -0
  7. package/lib/audio/audio-bus.js.map +1 -0
  8. package/lib/audio/audio-engine.js +188 -0
  9. package/lib/audio/audio-engine.js.map +1 -0
  10. package/lib/audio/audio-fetch.js +18 -0
  11. package/lib/audio/audio-fetch.js.map +1 -0
  12. package/lib/audio/audio-param.js +96 -0
  13. package/lib/audio/audio-param.js.map +1 -0
  14. package/lib/audio/audio-signal.js +46 -0
  15. package/lib/audio/audio-signal.js.map +1 -0
  16. package/lib/audio/bus.js +33 -0
  17. package/lib/audio/bus.js.map +1 -0
  18. package/lib/audio/host-types.js +2 -0
  19. package/lib/audio/host-types.js.map +1 -0
  20. package/lib/audio/index.js +12 -0
  21. package/lib/audio/index.js.map +1 -0
  22. package/lib/audio/sound-buffer.js +59 -0
  23. package/lib/audio/sound-buffer.js.map +1 -0
  24. package/lib/audio/sound-source.js +57 -0
  25. package/lib/audio/sound-source.js.map +1 -0
  26. package/lib/audio/sound-sub-graph.js +72 -0
  27. package/lib/audio/sound-sub-graph.js.map +1 -0
  28. package/lib/audio/spatial.js +466 -0
  29. package/lib/audio/spatial.js.map +1 -0
  30. package/lib/audio/static-sound.js +313 -0
  31. package/lib/audio/static-sound.js.map +1 -0
  32. package/lib/audio/stereo.js +40 -0
  33. package/lib/audio/stereo.js.map +1 -0
  34. package/lib/audio/streaming-sound.js +377 -0
  35. package/lib/audio/streaming-sound.js.map +1 -0
  36. package/lib/audio/unmute-ui.js +72 -0
  37. package/lib/audio/unmute-ui.js.map +1 -0
  38. package/lib/audio/visualizer.js +101 -0
  39. package/lib/audio/visualizer.js.map +1 -0
  40. package/lib/camera/geospatial-camera-controls.js +22 -0
  41. package/lib/camera/geospatial-camera-controls.js.map +1 -1
  42. package/lib/camera/geospatial-camera-fly.js +2 -1
  43. package/lib/camera/geospatial-camera-fly.js.map +1 -1
  44. package/lib/effect/effect-renderer.js +1 -1
  45. package/lib/effect/effect-renderer.js.map +1 -1
  46. package/lib/engine/engine.js +1 -1
  47. package/lib/index.js +15 -1
  48. package/lib/index.js.map +1 -1
  49. package/lib/light/types.js.map +1 -1
  50. package/lib/loader-gltf/animation-pointer-basecolor.js +25 -0
  51. package/lib/loader-gltf/animation-pointer-basecolor.js.map +1 -0
  52. package/lib/loader-gltf/animation-pointer-ext.js +244 -0
  53. package/lib/loader-gltf/animation-pointer-ext.js.map +1 -0
  54. package/lib/loader-gltf/animation-pointer-lights.js +46 -0
  55. package/lib/loader-gltf/animation-pointer-lights.js.map +1 -0
  56. package/lib/loader-gltf/animation-pointer.js +4 -1
  57. package/lib/loader-gltf/animation-pointer.js.map +1 -1
  58. package/lib/loader-gltf/gltf-animation.js +5 -3
  59. package/lib/loader-gltf/gltf-animation.js.map +1 -1
  60. package/lib/loader-gltf/gltf-color-normalize.js +10 -1
  61. package/lib/loader-gltf/gltf-color-normalize.js.map +1 -1
  62. package/lib/loader-gltf/gltf-feature-animation-pointer.js +67 -47
  63. package/lib/loader-gltf/gltf-feature-animation-pointer.js.map +1 -1
  64. package/lib/loader-gltf/gltf-feature-lights-punctual.js +51 -9
  65. package/lib/loader-gltf/gltf-feature-lights-punctual.js.map +1 -1
  66. package/lib/loader-gltf/gltf-feature-primitive.js +20 -0
  67. package/lib/loader-gltf/gltf-feature-primitive.js.map +1 -0
  68. package/lib/loader-gltf/gltf-feature-registry.js +25 -0
  69. package/lib/loader-gltf/gltf-feature-registry.js.map +1 -1
  70. package/lib/loader-gltf/gltf-feature-skeleton.js +18 -3
  71. package/lib/loader-gltf/gltf-feature-skeleton.js.map +1 -1
  72. package/lib/loader-gltf/gltf-interleave.js +3 -2
  73. package/lib/loader-gltf/gltf-interleave.js.map +1 -1
  74. package/lib/loader-gltf/gltf-light-pointer-state.js +18 -0
  75. package/lib/loader-gltf/gltf-light-pointer-state.js.map +1 -0
  76. package/lib/loader-gltf/gltf-parser.js +7 -1
  77. package/lib/loader-gltf/gltf-parser.js.map +1 -1
  78. package/lib/loader-gltf/gltf-pbr-builder-ext.js +1 -1
  79. package/lib/loader-gltf/gltf-pbr-builder-ext.js.map +1 -1
  80. package/lib/loader-gltf/gltf-pbr-builder.js +1 -1
  81. package/lib/loader-gltf/gltf-pbr-builder.js.map +1 -1
  82. package/lib/loader-gltf/gltf-sampler-denorm.js +20 -0
  83. package/lib/loader-gltf/gltf-sampler-denorm.js.map +1 -0
  84. package/lib/loader-gltf/gltf-sampler-desc.js +11 -2
  85. package/lib/loader-gltf/gltf-sampler-desc.js.map +1 -1
  86. package/lib/loader-gltf/gltf-uv-denorm.js +28 -0
  87. package/lib/loader-gltf/gltf-uv-denorm.js.map +1 -0
  88. package/lib/loader-gltf/load-gltf.js +15 -6
  89. package/lib/loader-gltf/load-gltf.js.map +1 -1
  90. package/lib/material/material-rebuild.js +4 -0
  91. package/lib/material/material-rebuild.js.map +1 -1
  92. package/lib/material/mesh-features.js +8 -1
  93. package/lib/material/mesh-features.js.map +1 -1
  94. package/lib/material/pbr/fragments/reflectance-fragment.js +1 -1
  95. package/lib/material/pbr/fragments/reflectance-fragment.js.map +1 -1
  96. package/lib/material/pbr/fragments/refraction-rtt-fragment.js +1 -1
  97. package/lib/material/pbr/fragments/refraction-rtt-fragment.js.map +1 -1
  98. package/lib/material/pbr/pbr-pipeline.js +7 -3
  99. package/lib/material/pbr/pbr-pipeline.js.map +1 -1
  100. package/lib/material/pbr/pbr-primitive-resolver.js +34 -0
  101. package/lib/material/pbr/pbr-primitive-resolver.js.map +1 -0
  102. package/lib/material/pbr/pbr-renderable.js +1 -1
  103. package/lib/material/pbr/pbr-renderable.js.map +1 -1
  104. package/lib/material/shader/shader-material.js +9 -5
  105. package/lib/material/shader/shader-material.js.map +1 -1
  106. package/lib/material/shader/shader-thin-instance.js +1 -1
  107. package/lib/material/shader/shader-thin-instance.js.map +1 -1
  108. package/lib/material/standard/standard-renderable.js +1 -1
  109. package/lib/material/standard/standard-renderable.js.map +1 -1
  110. package/lib/mesh/mesh-dispose.js +1 -0
  111. package/lib/mesh/mesh-dispose.js.map +1 -1
  112. package/lib/mesh/thin-instance-cull-binding.js +15 -6
  113. package/lib/mesh/thin-instance-cull-binding.js.map +1 -1
  114. package/lib/post-process/taa.js +193 -0
  115. package/lib/post-process/taa.js.map +1 -0
  116. package/lib/scene/scene-core.js +1 -0
  117. package/lib/scene/scene-core.js.map +1 -1
  118. package/lib/scene/scene-material-swap.js +2 -0
  119. package/lib/scene/scene-material-swap.js.map +1 -1
  120. package/lib/shadow/csm-shadow-task-hooks.js +67 -9
  121. package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
  122. package/lib/sprite/billboard-custom-shader.js +32 -32
  123. package/lib/sprite/billboard-custom-shader.js.map +1 -1
  124. package/lib/sprite/billboard-pipeline.js +54 -56
  125. package/lib/sprite/billboard-pipeline.js.map +1 -1
  126. package/lib/sprite/custom-shader-core.js +1 -1
  127. package/lib/sprite/custom-shader-core.js.map +1 -1
  128. package/lib/sprite/shared/sprite-atlas.js +2 -2
  129. package/lib/sprite/shared/sprite-atlas.js.map +1 -1
  130. package/lib/sprite/sprite-2d-coverage-gamma.js +58 -0
  131. package/lib/sprite/sprite-2d-coverage-gamma.js.map +1 -0
  132. package/lib/sprite/sprite-2d-uvscroll.js +39 -0
  133. package/lib/sprite/sprite-2d-uvscroll.js.map +1 -0
  134. package/lib/sprite/sprite-2d.js +6 -36
  135. package/lib/sprite/sprite-2d.js.map +1 -1
  136. package/lib/sprite/sprite-coverage-gamma-hook.js +10 -0
  137. package/lib/sprite/sprite-coverage-gamma-hook.js.map +1 -0
  138. package/lib/sprite/sprite-custom-shader.js +2 -2
  139. package/lib/sprite/sprite-custom-shader.js.map +1 -1
  140. package/lib/sprite/sprite-pipeline.js +61 -73
  141. package/lib/sprite/sprite-pipeline.js.map +1 -1
  142. package/lib/sprite/sprite-renderable.js +5 -5
  143. package/lib/sprite/sprite-renderable.js.map +1 -1
  144. package/lib/sprite/sprite-renderer.js +4 -4
  145. package/lib/sprite/sprite-renderer.js.map +1 -1
  146. package/lib/sprite/sprite-scene.js +1 -1
  147. package/lib/sprite/sprite-scene.js.map +1 -1
  148. package/lib/text/_gpu/text-pipeline.js +1 -1
  149. package/lib/text/_gpu/text-pipeline.js.map +1 -1
  150. package/lib/text/text-renderer.js +3 -1
  151. package/lib/text/text-renderer.js.map +1 -1
  152. package/package.json +3 -3
@@ -0,0 +1,466 @@
1
+ import { createRampParam, isRamping, setRampTarget } from './audio-param.js';
2
+ import { rebuildSoundSubGraphHead } from './sound-sub-graph.js';
3
+ import { mat4Decompose } from '../math/mat4-decompose.js';
4
+
5
+ const SpatialDefaults = {
6
+ coneInnerAngle: 6.28318530718,
7
+ coneOuterAngle: 6.28318530718,
8
+ coneOuterVolume: 0,
9
+ distanceModel: "linear",
10
+ maxDistance: 1e4,
11
+ minDistance: 1,
12
+ panningEnabled: true,
13
+ panningModel: "equalpower",
14
+ rolloffFactor: 1
15
+ };
16
+ const ATTACH_POSITION = 1;
17
+ const ATTACH_ROTATION = 2;
18
+ const ATTACH_BOTH = 3;
19
+ const EPSILON = 1e-3;
20
+ function r2d(radians) {
21
+ return radians * 180 / Math.PI;
22
+ }
23
+ function rotateByQuat(q, vx, vy, vz) {
24
+ const tx = 2 * (q.y * vz - q.z * vy);
25
+ const ty = 2 * (q.z * vx - q.x * vz);
26
+ const tz = 2 * (q.x * vy - q.y * vx);
27
+ return {
28
+ x: vx + q.w * tx + (q.y * tz - q.z * ty),
29
+ y: vy + q.w * ty + (q.z * tx - q.x * tz),
30
+ z: vz + q.w * tz + (q.x * ty - q.y * tx)
31
+ };
32
+ }
33
+ function vecEquals(a, b) {
34
+ return Math.abs(a.x - b.x) < EPSILON && Math.abs(a.y - b.y) < EPSILON && Math.abs(a.z - b.z) < EPSILON;
35
+ }
36
+ function quatEquals(a, b) {
37
+ return Math.abs(a.x - b.x) < EPSILON && Math.abs(a.y - b.y) < EPSILON && Math.abs(a.z - b.z) < EPSILON && Math.abs(a.w - b.w) < EPSILON;
38
+ }
39
+ function toAttachmentFlags(type) {
40
+ switch (type) {
41
+ case "position":
42
+ return ATTACH_POSITION;
43
+ case "rotation":
44
+ return ATTACH_ROTATION;
45
+ default:
46
+ return ATTACH_BOTH;
47
+ }
48
+ }
49
+ function createSpatialSubNode(engine) {
50
+ const ctx = engine._ctx;
51
+ const inputNode = new GainNode(ctx);
52
+ const attenuationNode = new GainNode(ctx);
53
+ const panner = new PannerNode(ctx);
54
+ const node = {
55
+ _engine: engine,
56
+ _inputNode: inputNode,
57
+ _panner: panner,
58
+ _attenuationNode: attenuationNode,
59
+ _attenuationRamp: createRampParam(attenuationNode.gain, engine),
60
+ _panningEnabled: SpatialDefaults.panningEnabled,
61
+ _positionX: createRampParam(panner.positionX, engine),
62
+ _positionY: createRampParam(panner.positionY, engine),
63
+ _positionZ: createRampParam(panner.positionZ, engine),
64
+ _orientationX: createRampParam(panner.orientationX, engine),
65
+ _orientationY: createRampParam(panner.orientationY, engine),
66
+ _orientationZ: createRampParam(panner.orientationZ, engine),
67
+ _position: { x: 0, y: 0, z: 0 },
68
+ _orientation: { x: 1, y: 0, z: 0 },
69
+ _rotationQuaternion: { x: 0, y: 0, z: 0, w: 1 },
70
+ _lastPosition: { x: NaN, y: NaN, z: NaN },
71
+ _lastOrientation: { x: NaN, y: NaN, z: NaN },
72
+ _lastQuat: { x: NaN, y: NaN, z: NaN, w: NaN },
73
+ _attached: null,
74
+ _attachmentType: ATTACH_BOTH,
75
+ _attachUnsub: null,
76
+ _update: () => updateAttachedSubNode(node),
77
+ _dispose: () => disposeSpatialSubNode(node)
78
+ };
79
+ panner.coneInnerAngle = r2d(SpatialDefaults.coneInnerAngle);
80
+ panner.coneOuterAngle = r2d(SpatialDefaults.coneOuterAngle);
81
+ panner.coneOuterGain = SpatialDefaults.coneOuterVolume;
82
+ panner.distanceModel = SpatialDefaults.distanceModel;
83
+ panner.maxDistance = SpatialDefaults.maxDistance;
84
+ panner.refDistance = SpatialDefaults.minDistance;
85
+ panner.rolloffFactor = SpatialDefaults.rolloffFactor;
86
+ panner.panningModel = SpatialDefaults.panningModel;
87
+ connectActiveInput(node);
88
+ return node;
89
+ }
90
+ function connectActiveInput(node) {
91
+ node._inputNode.disconnect();
92
+ node._inputNode.connect(node._panningEnabled ? node._panner : node._attenuationNode);
93
+ }
94
+ function connectSpatialOutput(node, downstream) {
95
+ node._panner.connect(downstream);
96
+ node._attenuationNode.connect(downstream);
97
+ }
98
+ function disposeSpatialSubNode(node) {
99
+ detachSubNode(node);
100
+ node._inputNode.disconnect();
101
+ node._attenuationNode.disconnect();
102
+ node._panner.disconnect();
103
+ }
104
+ function updateSubNodePosition(node) {
105
+ if (vecEquals(node._lastPosition, node._position)) {
106
+ updateAttenuation(node);
107
+ return;
108
+ }
109
+ setRampTarget(node._positionX, node._position.x);
110
+ setRampTarget(node._positionY, node._position.y);
111
+ setRampTarget(node._positionZ, node._position.z);
112
+ node._lastPosition = { x: node._position.x, y: node._position.y, z: node._position.z };
113
+ updateAttenuation(node);
114
+ }
115
+ function updateSubNodeRotation(node) {
116
+ let changed = false;
117
+ if (!quatEquals(node._lastQuat, node._rotationQuaternion)) {
118
+ node._orientation = rotateByQuat(node._rotationQuaternion, 1, 0, 0);
119
+ node._lastQuat = { x: node._rotationQuaternion.x, y: node._rotationQuaternion.y, z: node._rotationQuaternion.z, w: node._rotationQuaternion.w };
120
+ changed = true;
121
+ } else if (!vecEquals(node._lastOrientation, node._orientation)) {
122
+ changed = true;
123
+ }
124
+ if (!changed) {
125
+ return;
126
+ }
127
+ setRampTarget(node._orientationX, node._orientation.x);
128
+ setRampTarget(node._orientationY, node._orientation.y);
129
+ setRampTarget(node._orientationZ, node._orientation.z);
130
+ node._lastOrientation = { x: node._orientation.x, y: node._orientation.y, z: node._orientation.z };
131
+ }
132
+ function updateAttenuation(node) {
133
+ if (node._panningEnabled) {
134
+ setRampTarget(node._attenuationRamp, 1);
135
+ return;
136
+ }
137
+ const listenerPosition = node._engine._listener?._position ?? { x: 0, y: 0, z: 0 };
138
+ const deltaX = node._position.x - listenerPosition.x;
139
+ const deltaY = node._position.y - listenerPosition.y;
140
+ const deltaZ = node._position.z - listenerPosition.z;
141
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);
142
+ const minDistance = Math.max(node._panner.refDistance, 0);
143
+ const rolloffFactor = node._panner.rolloffFactor;
144
+ let attenuation = 1;
145
+ switch (node._panner.distanceModel) {
146
+ case "linear": {
147
+ const maxDistance = Math.max(node._panner.maxDistance, minDistance);
148
+ const clampedDistance = Math.min(Math.max(distance, minDistance), maxDistance);
149
+ attenuation = maxDistance === minDistance ? distance <= minDistance ? 1 : 0 : 1 - rolloffFactor * (clampedDistance - minDistance) / (maxDistance - minDistance);
150
+ break;
151
+ }
152
+ case "inverse":
153
+ attenuation = minDistance === 0 ? 0 : minDistance / (minDistance + rolloffFactor * (Math.max(distance, minDistance) - minDistance));
154
+ break;
155
+ case "exponential":
156
+ attenuation = minDistance === 0 ? 0 : Math.pow(Math.max(distance, minDistance) / minDistance, -rolloffFactor);
157
+ break;
158
+ }
159
+ setRampTarget(node._attenuationRamp, Math.min(Math.max(attenuation, 0), 1));
160
+ }
161
+ function setSubNodePanningEnabled(node, value) {
162
+ if (node._panningEnabled === value) {
163
+ return;
164
+ }
165
+ node._panningEnabled = value;
166
+ connectActiveInput(node);
167
+ updateAttenuation(node);
168
+ }
169
+ function configureSubNode(node, opts) {
170
+ const panner = node._panner;
171
+ if (opts.coneInnerAngle !== void 0) {
172
+ panner.coneInnerAngle = r2d(opts.coneInnerAngle);
173
+ }
174
+ if (opts.coneOuterAngle !== void 0) {
175
+ panner.coneOuterAngle = r2d(opts.coneOuterAngle);
176
+ }
177
+ if (opts.coneOuterVolume !== void 0) {
178
+ panner.coneOuterGain = opts.coneOuterVolume;
179
+ }
180
+ if (opts.distanceModel !== void 0) {
181
+ panner.distanceModel = opts.distanceModel;
182
+ }
183
+ if (opts.maxDistance !== void 0) {
184
+ panner.maxDistance = opts.maxDistance;
185
+ }
186
+ if (opts.minDistance !== void 0) {
187
+ panner.refDistance = opts.minDistance;
188
+ }
189
+ if (opts.rolloffFactor !== void 0) {
190
+ panner.rolloffFactor = opts.rolloffFactor;
191
+ }
192
+ if (opts.panningModel !== void 0) {
193
+ panner.panningModel = opts.panningModel;
194
+ }
195
+ if (opts.panningEnabled !== void 0) {
196
+ setSubNodePanningEnabled(node, opts.panningEnabled);
197
+ }
198
+ if (opts.position) {
199
+ node._position = { x: opts.position.x, y: opts.position.y, z: opts.position.z };
200
+ }
201
+ if (opts.rotationQuaternion) {
202
+ node._rotationQuaternion = { x: opts.rotationQuaternion.x, y: opts.rotationQuaternion.y, z: opts.rotationQuaternion.z, w: opts.rotationQuaternion.w };
203
+ } else if (opts.orientation) {
204
+ node._orientation = { x: opts.orientation.x, y: opts.orientation.y, z: opts.orientation.z };
205
+ node._lastQuat = { x: node._rotationQuaternion.x, y: node._rotationQuaternion.y, z: node._rotationQuaternion.z, w: node._rotationQuaternion.w };
206
+ }
207
+ updateSubNodePosition(node);
208
+ updateSubNodeRotation(node);
209
+ }
210
+ function attachSubNode(node, target, type) {
211
+ detachSubNode(node);
212
+ node._attached = target;
213
+ node._attachmentType = toAttachmentFlags(type);
214
+ if (target.onDispose) {
215
+ node._attachUnsub = target.onDispose.add(() => detachSubNode(node));
216
+ }
217
+ node._engine._spatialUpdaters.add(node._update);
218
+ updateAttachedSubNode(node);
219
+ }
220
+ function detachSubNode(node) {
221
+ node._attachUnsub?.();
222
+ node._attachUnsub = null;
223
+ node._attached = null;
224
+ node._engine._spatialUpdaters.delete(node._update);
225
+ }
226
+ function updateAttachedSubNode(node) {
227
+ const target = node._attached;
228
+ if (!target) {
229
+ return;
230
+ }
231
+ const { translation, rotation } = mat4Decompose(target.worldMatrix);
232
+ const updatesPosition = (node._attachmentType & ATTACH_POSITION) !== 0;
233
+ if (updatesPosition) {
234
+ node._position = translation;
235
+ updateSubNodePosition(node);
236
+ }
237
+ if (node._attachmentType & ATTACH_ROTATION) {
238
+ node._rotationQuaternion = rotation;
239
+ updateSubNodeRotation(node);
240
+ }
241
+ if (!updatesPosition && !node._panningEnabled) {
242
+ updateSubNodePosition(node);
243
+ }
244
+ }
245
+ function ensureSpatialSubNode(host) {
246
+ const graph = host._graph;
247
+ if (graph._spatial) {
248
+ return graph._spatial;
249
+ }
250
+ ensureSpatialListener(host._engine);
251
+ const node = createSpatialSubNode(host._engine);
252
+ connectSpatialOutput(node, graph._volume);
253
+ graph._spatial = node;
254
+ rebuildSoundSubGraphHead(graph, host._instances);
255
+ return node;
256
+ }
257
+ function enableSpatial(host, options = {}) {
258
+ const node = ensureSpatialSubNode(host);
259
+ configureSubNode(node, options);
260
+ if (options.attachedTo) {
261
+ attachSubNode(node, options.attachedTo, options.attachmentType);
262
+ }
263
+ }
264
+ function setSpatialPosition(host, position) {
265
+ const node = ensureSpatialSubNode(host);
266
+ node._position = { x: position.x, y: position.y, z: position.z };
267
+ updateSubNodePosition(node);
268
+ }
269
+ function setSpatialOrientation(host, orientation) {
270
+ const node = ensureSpatialSubNode(host);
271
+ node._orientation = { x: orientation.x, y: orientation.y, z: orientation.z };
272
+ node._lastQuat = { x: node._rotationQuaternion.x, y: node._rotationQuaternion.y, z: node._rotationQuaternion.z, w: node._rotationQuaternion.w };
273
+ updateSubNodeRotation(node);
274
+ }
275
+ function attachSpatialTarget(target, worldTarget, type) {
276
+ if (isEngine(target)) {
277
+ const listener = ensureSpatialListener(target);
278
+ attachListener(listener, worldTarget, type);
279
+ return;
280
+ }
281
+ const node = ensureSpatialSubNode(target);
282
+ attachSubNode(node, worldTarget, type);
283
+ }
284
+ function detachSpatialTarget(target) {
285
+ if (isEngine(target)) {
286
+ if (target._listener) {
287
+ detachListener(target._listener);
288
+ }
289
+ return;
290
+ }
291
+ if (target._graph._spatial) {
292
+ detachSubNode(target._graph._spatial);
293
+ }
294
+ }
295
+ function setSpatialListener(engine, options = {}) {
296
+ const listener = ensureSpatialListener(engine);
297
+ if (options.position) {
298
+ listener._position = { x: options.position.x, y: options.position.y, z: options.position.z };
299
+ updateListenerPosition(listener);
300
+ }
301
+ if (options.rotationQuaternion) {
302
+ listener._rotationQuaternion = { x: options.rotationQuaternion.x, y: options.rotationQuaternion.y, z: options.rotationQuaternion.z, w: options.rotationQuaternion.w };
303
+ updateListenerRotation(listener);
304
+ }
305
+ if (options.attachedTo) {
306
+ attachListener(listener, options.attachedTo, options.attachmentType);
307
+ }
308
+ }
309
+ function setSpatialListenerPosition(engine, position) {
310
+ const listener = ensureSpatialListener(engine);
311
+ listener._position = { x: position.x, y: position.y, z: position.z };
312
+ updateListenerPosition(listener);
313
+ }
314
+ function updateSpatialAudio(engine) {
315
+ for (const update of engine._spatialUpdaters) {
316
+ update();
317
+ }
318
+ }
319
+ function setSpatialAutoUpdate(engine, enabled, minUpdateMs = 0) {
320
+ engine._spatialAutoStop?.();
321
+ engine._spatialAutoStop = null;
322
+ if (!enabled || typeof requestAnimationFrame !== "function") {
323
+ return;
324
+ }
325
+ let active = true;
326
+ let rafId = 0;
327
+ let lastTime = 0;
328
+ const tick = () => {
329
+ if (!active) {
330
+ return;
331
+ }
332
+ let skip = false;
333
+ if (minUpdateMs > 0) {
334
+ const now = typeof performance !== "undefined" ? performance.now() : Date.now();
335
+ if (lastTime && now - lastTime < minUpdateMs) {
336
+ skip = true;
337
+ } else {
338
+ lastTime = now;
339
+ }
340
+ }
341
+ if (!skip) {
342
+ updateSpatialAudio(engine);
343
+ }
344
+ rafId = requestAnimationFrame(tick);
345
+ };
346
+ rafId = requestAnimationFrame(tick);
347
+ const stop = () => {
348
+ active = false;
349
+ if (typeof cancelAnimationFrame === "function") {
350
+ cancelAnimationFrame(rafId);
351
+ }
352
+ };
353
+ engine._spatialAutoStop = stop;
354
+ engine._disposers.push(stop);
355
+ }
356
+ function isEngine(target) {
357
+ return "_spatialUpdaters" in target;
358
+ }
359
+ function ensureSpatialListener(engine) {
360
+ if (engine._listener) {
361
+ return engine._listener;
362
+ }
363
+ const al = engine._ctx.listener;
364
+ const hasParams = !!(al.positionX && al.forwardX && al.upX);
365
+ const listener = {
366
+ _engine: engine,
367
+ _listener: al,
368
+ _hasParams: hasParams,
369
+ _position: { x: 0, y: 0, z: 0 },
370
+ _rotationQuaternion: { x: 0, y: 0, z: 0, w: 1 },
371
+ _lastPosition: { x: NaN, y: NaN, z: NaN },
372
+ _lastQuat: { x: NaN, y: NaN, z: NaN, w: NaN },
373
+ _positionX: hasParams ? createRampParam(al.positionX, engine) : null,
374
+ _positionY: hasParams ? createRampParam(al.positionY, engine) : null,
375
+ _positionZ: hasParams ? createRampParam(al.positionZ, engine) : null,
376
+ _forwardX: hasParams ? createRampParam(al.forwardX, engine) : null,
377
+ _forwardY: hasParams ? createRampParam(al.forwardY, engine) : null,
378
+ _forwardZ: hasParams ? createRampParam(al.forwardZ, engine) : null,
379
+ _upX: hasParams ? createRampParam(al.upX, engine) : null,
380
+ _upY: hasParams ? createRampParam(al.upY, engine) : null,
381
+ _upZ: hasParams ? createRampParam(al.upZ, engine) : null,
382
+ _attached: null,
383
+ _attachmentType: ATTACH_BOTH,
384
+ _attachUnsub: null,
385
+ _update: () => updateAttachedListener(listener),
386
+ _dispose: () => disposeSpatialListener(listener)
387
+ };
388
+ engine._listener = listener;
389
+ return listener;
390
+ }
391
+ function updateListenerPosition(listener) {
392
+ if (vecEquals(listener._lastPosition, listener._position)) {
393
+ return;
394
+ }
395
+ const p = listener._position;
396
+ if (listener._hasParams) {
397
+ if (listener._attached && (isRamping(listener._positionX) || isRamping(listener._positionY) || isRamping(listener._positionZ))) {
398
+ return;
399
+ }
400
+ setRampTarget(listener._positionX, p.x);
401
+ setRampTarget(listener._positionY, p.y);
402
+ setRampTarget(listener._positionZ, p.z);
403
+ } else {
404
+ listener._listener.setPosition(p.x, p.y, p.z);
405
+ }
406
+ listener._lastPosition = { x: p.x, y: p.y, z: p.z };
407
+ }
408
+ function updateListenerRotation(listener) {
409
+ if (quatEquals(listener._lastQuat, listener._rotationQuaternion)) {
410
+ return;
411
+ }
412
+ const forward = rotateByQuat(listener._rotationQuaternion, 0, 0, -1);
413
+ const up = rotateByQuat(listener._rotationQuaternion, 0, 1, 0);
414
+ if (listener._hasParams) {
415
+ if (listener._attached && (isRamping(listener._forwardX) || isRamping(listener._forwardY) || isRamping(listener._forwardZ) || isRamping(listener._upX) || isRamping(listener._upY) || isRamping(listener._upZ))) {
416
+ return;
417
+ }
418
+ setRampTarget(listener._forwardX, forward.x);
419
+ setRampTarget(listener._forwardY, forward.y);
420
+ setRampTarget(listener._forwardZ, forward.z);
421
+ setRampTarget(listener._upX, up.x);
422
+ setRampTarget(listener._upY, up.y);
423
+ setRampTarget(listener._upZ, up.z);
424
+ } else {
425
+ listener._listener.setOrientation(forward.x, forward.y, forward.z, up.x, up.y, up.z);
426
+ }
427
+ listener._lastQuat = { x: listener._rotationQuaternion.x, y: listener._rotationQuaternion.y, z: listener._rotationQuaternion.z, w: listener._rotationQuaternion.w };
428
+ }
429
+ function attachListener(listener, target, type) {
430
+ detachListener(listener);
431
+ listener._attached = target;
432
+ listener._attachmentType = toAttachmentFlags(type);
433
+ if (target.onDispose) {
434
+ listener._attachUnsub = target.onDispose.add(() => detachListener(listener));
435
+ }
436
+ listener._engine._spatialUpdaters.add(listener._update);
437
+ updateAttachedListener(listener);
438
+ }
439
+ function detachListener(listener) {
440
+ listener._attachUnsub?.();
441
+ listener._attachUnsub = null;
442
+ listener._attached = null;
443
+ listener._engine._spatialUpdaters.delete(listener._update);
444
+ }
445
+ function updateAttachedListener(listener) {
446
+ const target = listener._attached;
447
+ if (!target) {
448
+ return;
449
+ }
450
+ const { translation, rotation } = mat4Decompose(target.worldMatrix);
451
+ if (listener._attachmentType & ATTACH_POSITION) {
452
+ listener._position = translation;
453
+ updateListenerPosition(listener);
454
+ }
455
+ if (listener._attachmentType & ATTACH_ROTATION) {
456
+ listener._rotationQuaternion = rotation;
457
+ updateListenerRotation(listener);
458
+ }
459
+ }
460
+ function disposeSpatialListener(listener) {
461
+ detachListener(listener);
462
+ listener._engine._listener = null;
463
+ }
464
+
465
+ export { attachSpatialTarget, detachSpatialTarget, enableSpatial, ensureSpatialListener, setSpatialAutoUpdate, setSpatialListener, setSpatialListenerPosition, setSpatialOrientation, setSpatialPosition, updateSpatialAudio };
466
+ //# sourceMappingURL=spatial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial.js","sources":["../../../src/audio/spatial.ts"],"sourcesContent":["/**\n * 3D spatial audio — panner sub-node + audio-context listener.\n *\n * Faithful port of AudioV2's `_SpatialWebAudioSubNode` (`PannerNode` config,\n * distance-attenuation fallback math), `_SpatialWebAudioListener`/`…Fallback`\n * (the AudioContext listener), `_SpatialAudioAttacherComponent` (attach to a\n * world transform), and `_SpatialWebAudioUpdaterComponent` (per-frame update),\n * collapsed to pure state + standalone functions.\n *\n * Tree-shaking (Pillar 4): core sound/bus creation does **not** statically\n * import this module. Spatialization is opted into by calling one of the\n * exported functions (`enableSpatial`, `setSpatialPosition`,\n * `attachSpatialTarget`, …), which lazily build the panner sub-node and splice\n * it into the sound sub-graph. An app that never calls a spatial function pays\n * zero bytes for any of this code.\n *\n * Signal flow once enabled (mirrors AudioV2's sub-graph diagram):\n *\n * `instance._volumeNode` -\\> `spatial._inputNode`\n * -\\> `PannerNode` (or attenuation `GainNode` when panning is disabled)\n * -\\> `graph._volume` -\\> … -\\> destination\n */\n\nimport { type AudioEngine } from \"./audio-engine.js\";\nimport { type RampParam, createRampParam, isRamping, setRampTarget } from \"./audio-param.js\";\nimport { type AudioSignal } from \"./audio-signal.js\";\nimport { rebuildSoundSubGraphHead } from \"./sound-sub-graph.js\";\nimport { type AudioGraphHost, type AudioGraphHostState } from \"./host-types.js\";\nimport { type Mat4, type Quat, type Vec3 } from \"../math/types.js\";\nimport { mat4Decompose } from \"../math/mat4-decompose.js\";\n\n// ─── Public option/target types ──────────────────────────────────────\n\n/** Which components of a target's world transform drive the spatial node. */\nexport type SpatialAttachmentType = \"position\" | \"rotation\" | \"positionAndRotation\";\n\n/**\n * Anything exposing a world transform — typically a Lite `Mesh` or camera.\n * The spatial node reads `worldMatrix` each update; if `onDispose` is provided,\n * the node auto-detaches when the target is disposed.\n */\nexport interface SpatialTarget {\n /** Column-major world matrix of the target. */\n readonly worldMatrix: Mat4;\n /** Optional dispose signal — firing it auto-detaches the spatial node. */\n readonly onDispose?: AudioSignal<unknown>;\n}\n\n/** Spatial (3D) options for a sound or bus. All fields optional; defaults match Babylon.js. */\nexport interface SpatialSoundOptions {\n /** World position of the source. Defaults to `(0, 0, 0)`. */\n position?: Vec3;\n /** Facing direction of the source. Defaults to `(1, 0, 0)`. */\n orientation?: Vec3;\n /** Source rotation as a quaternion. When set, drives {@link orientation}. */\n rotationQuaternion?: Quat;\n /** Pan between left/right channels. Defaults to `true`. */\n panningEnabled?: boolean;\n /** Panning algorithm. Defaults to `\"equalpower\"`. */\n panningModel?: PanningModelType;\n /** Distance attenuation model. Defaults to `\"linear\"`. */\n distanceModel?: DistanceModelType;\n /** Reference distance for attenuation. Defaults to `1`. */\n minDistance?: number;\n /** Max distance (linear model). Defaults to `10000`. */\n maxDistance?: number;\n /** Attenuation roll-off factor. Defaults to `1`. */\n rolloffFactor?: number;\n /** Cone inner angle, in radians. Defaults to `2π`. */\n coneInnerAngle?: number;\n /** Cone outer angle, in radians. Defaults to `2π`. */\n coneOuterAngle?: number;\n /** Volume outside the cone outer angle. Defaults to `0`. */\n coneOuterVolume?: number;\n /** Follow a world transform's position and/or rotation. */\n attachedTo?: SpatialTarget;\n /** Which transform components to follow. Defaults to `\"positionAndRotation\"`. */\n attachmentType?: SpatialAttachmentType;\n}\n\n/** Spatial listener options. The listener orientation is derived from its rotation quaternion. */\nexport interface SpatialListenerOptions {\n /** Listener world position. Defaults to `(0, 0, 0)`. */\n position?: Vec3;\n /** Listener rotation. Drives the listener forward/up vectors. */\n rotationQuaternion?: Quat;\n /** Follow a world transform. */\n attachedTo?: SpatialTarget;\n /** Which transform components to follow. Defaults to `\"positionAndRotation\"`. */\n attachmentType?: SpatialAttachmentType;\n}\n\n// ─── Defaults (verbatim from AudioV2 `_SpatialAudioDefaults`) ─────────\n\nconst SpatialDefaults = {\n coneInnerAngle: 6.28318530718,\n coneOuterAngle: 6.28318530718,\n coneOuterVolume: 0,\n distanceModel: \"linear\" as DistanceModelType,\n maxDistance: 10000,\n minDistance: 1,\n panningEnabled: true,\n panningModel: \"equalpower\" as PanningModelType,\n rolloffFactor: 1,\n} as const;\n\n// Attachment-type bit flags (mirror AudioV2 `SpatialAudioAttachmentType`).\nconst ATTACH_POSITION = 1;\nconst ATTACH_ROTATION = 2;\nconst ATTACH_BOTH = 3;\n\nconst EPSILON = 0.001;\n\n// ─── Small math helpers (mechanical equivalents of BJS calls) ────────\n\nfunction r2d(radians: number): number {\n return (radians * 180) / Math.PI;\n}\n\n/**\n * Rotate vector `(vx, vy, vz)` by unit quaternion `q`. Mechanically equivalent\n * to AudioV2's `Vector3.TransformNormalToRef(v, Matrix.FromQuaternion(q))`.\n */\nfunction rotateByQuat(q: Quat, vx: number, vy: number, vz: number): Vec3 {\n const tx = 2 * (q.y * vz - q.z * vy);\n const ty = 2 * (q.z * vx - q.x * vz);\n const tz = 2 * (q.x * vy - q.y * vx);\n return {\n x: vx + q.w * tx + (q.y * tz - q.z * ty),\n y: vy + q.w * ty + (q.z * tx - q.x * tz),\n z: vz + q.w * tz + (q.x * ty - q.y * tx),\n };\n}\n\nfunction vecEquals(a: Vec3, b: Vec3): boolean {\n return Math.abs(a.x - b.x) < EPSILON && Math.abs(a.y - b.y) < EPSILON && Math.abs(a.z - b.z) < EPSILON;\n}\n\nfunction quatEquals(a: Quat, b: Quat): boolean {\n return Math.abs(a.x - b.x) < EPSILON && Math.abs(a.y - b.y) < EPSILON && Math.abs(a.z - b.z) < EPSILON && Math.abs(a.w - b.w) < EPSILON;\n}\n\nfunction toAttachmentFlags(type: SpatialAttachmentType | undefined): number {\n switch (type) {\n case \"position\":\n return ATTACH_POSITION;\n case \"rotation\":\n return ATTACH_ROTATION;\n default:\n return ATTACH_BOTH;\n }\n}\n\n// ─── Panner sub-node ─────────────────────────────────────────────────\n\n/** Panner sub-node state. Pure state — driven by the spatial functions. @internal */\nexport interface SpatialSubNode {\n /** @internal */ _engine: AudioEngine;\n /** Head node — playing instances connect here. @internal */ _inputNode: GainNode;\n /** @internal */ _panner: PannerNode;\n /** Attenuation gain used only when panning is disabled. @internal */ _attenuationNode: GainNode;\n /** @internal */ _attenuationRamp: RampParam;\n /** @internal */ _panningEnabled: boolean;\n /** @internal */ _positionX: RampParam;\n /** @internal */ _positionY: RampParam;\n /** @internal */ _positionZ: RampParam;\n /** @internal */ _orientationX: RampParam;\n /** @internal */ _orientationY: RampParam;\n /** @internal */ _orientationZ: RampParam;\n /** @internal */ _position: Vec3;\n /** @internal */ _orientation: Vec3;\n /** @internal */ _rotationQuaternion: Quat;\n /** @internal */ _lastPosition: Vec3;\n /** @internal */ _lastOrientation: Vec3;\n /** @internal */ _lastQuat: Quat;\n /** @internal */ _attached: SpatialTarget | null;\n /** @internal */ _attachmentType: number;\n /** @internal */ _attachUnsub: (() => void) | null;\n /** Registered into `engine._spatialUpdaters` while attached. @internal */ _update: () => void;\n /** @internal */ _dispose: () => void;\n}\n\nfunction createSpatialSubNode(engine: AudioEngine): SpatialSubNode {\n const ctx = engine._ctx;\n const inputNode = new GainNode(ctx);\n const attenuationNode = new GainNode(ctx);\n const panner = new PannerNode(ctx);\n\n const node: SpatialSubNode = {\n _engine: engine,\n _inputNode: inputNode,\n _panner: panner,\n _attenuationNode: attenuationNode,\n _attenuationRamp: createRampParam(attenuationNode.gain, engine),\n _panningEnabled: SpatialDefaults.panningEnabled,\n _positionX: createRampParam(panner.positionX, engine),\n _positionY: createRampParam(panner.positionY, engine),\n _positionZ: createRampParam(panner.positionZ, engine),\n _orientationX: createRampParam(panner.orientationX, engine),\n _orientationY: createRampParam(panner.orientationY, engine),\n _orientationZ: createRampParam(panner.orientationZ, engine),\n _position: { x: 0, y: 0, z: 0 },\n _orientation: { x: 1, y: 0, z: 0 },\n _rotationQuaternion: { x: 0, y: 0, z: 0, w: 1 },\n _lastPosition: { x: NaN, y: NaN, z: NaN },\n _lastOrientation: { x: NaN, y: NaN, z: NaN },\n _lastQuat: { x: NaN, y: NaN, z: NaN, w: NaN },\n _attached: null,\n _attachmentType: ATTACH_BOTH,\n _attachUnsub: null,\n _update: () => updateAttachedSubNode(node),\n _dispose: () => disposeSpatialSubNode(node),\n };\n\n // Apply panner defaults (degrees on the node; radians in our API).\n panner.coneInnerAngle = r2d(SpatialDefaults.coneInnerAngle);\n panner.coneOuterAngle = r2d(SpatialDefaults.coneOuterAngle);\n panner.coneOuterGain = SpatialDefaults.coneOuterVolume;\n panner.distanceModel = SpatialDefaults.distanceModel;\n panner.maxDistance = SpatialDefaults.maxDistance;\n panner.refDistance = SpatialDefaults.minDistance;\n panner.rolloffFactor = SpatialDefaults.rolloffFactor;\n panner.panningModel = SpatialDefaults.panningModel;\n\n connectActiveInput(node);\n return node;\n}\n\nfunction connectActiveInput(node: SpatialSubNode): void {\n node._inputNode.disconnect();\n node._inputNode.connect(node._panningEnabled ? node._panner : node._attenuationNode);\n}\n\n/** Connect both possible output nodes downstream (mirrors AudioV2 `_connect`). */\nfunction connectSpatialOutput(node: SpatialSubNode, downstream: AudioNode): void {\n node._panner.connect(downstream);\n node._attenuationNode.connect(downstream);\n}\n\nfunction disposeSpatialSubNode(node: SpatialSubNode): void {\n detachSubNode(node);\n node._inputNode.disconnect();\n node._attenuationNode.disconnect();\n node._panner.disconnect();\n}\n\nfunction updateSubNodePosition(node: SpatialSubNode): void {\n if (vecEquals(node._lastPosition, node._position)) {\n updateAttenuation(node);\n return;\n }\n setRampTarget(node._positionX, node._position.x);\n setRampTarget(node._positionY, node._position.y);\n setRampTarget(node._positionZ, node._position.z);\n node._lastPosition = { x: node._position.x, y: node._position.y, z: node._position.z };\n updateAttenuation(node);\n}\n\nfunction updateSubNodeRotation(node: SpatialSubNode): void {\n let changed = false;\n if (!quatEquals(node._lastQuat, node._rotationQuaternion)) {\n node._orientation = rotateByQuat(node._rotationQuaternion, 1, 0, 0);\n node._lastQuat = { x: node._rotationQuaternion.x, y: node._rotationQuaternion.y, z: node._rotationQuaternion.z, w: node._rotationQuaternion.w };\n changed = true;\n } else if (!vecEquals(node._lastOrientation, node._orientation)) {\n changed = true;\n }\n if (!changed) {\n return;\n }\n setRampTarget(node._orientationX, node._orientation.x);\n setRampTarget(node._orientationY, node._orientation.y);\n setRampTarget(node._orientationZ, node._orientation.z);\n node._lastOrientation = { x: node._orientation.x, y: node._orientation.y, z: node._orientation.z };\n}\n\n/**\n * Distance-attenuation fallback used while panning is disabled. Verbatim port\n * of AudioV2 `_SpatialWebAudioSubNode._updateAttenuation`.\n */\nfunction updateAttenuation(node: SpatialSubNode): void {\n if (node._panningEnabled) {\n setRampTarget(node._attenuationRamp, 1);\n return;\n }\n\n const listenerPosition = node._engine._listener?._position ?? { x: 0, y: 0, z: 0 };\n const deltaX = node._position.x - listenerPosition.x;\n const deltaY = node._position.y - listenerPosition.y;\n const deltaZ = node._position.z - listenerPosition.z;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);\n const minDistance = Math.max(node._panner.refDistance, 0);\n const rolloffFactor = node._panner.rolloffFactor;\n let attenuation = 1;\n\n switch (node._panner.distanceModel) {\n case \"linear\": {\n const maxDistance = Math.max(node._panner.maxDistance, minDistance);\n const clampedDistance = Math.min(Math.max(distance, minDistance), maxDistance);\n attenuation = maxDistance === minDistance ? (distance <= minDistance ? 1 : 0) : 1 - (rolloffFactor * (clampedDistance - minDistance)) / (maxDistance - minDistance);\n break;\n }\n case \"inverse\":\n attenuation = minDistance === 0 ? 0 : minDistance / (minDistance + rolloffFactor * (Math.max(distance, minDistance) - minDistance));\n break;\n case \"exponential\":\n attenuation = minDistance === 0 ? 0 : Math.pow(Math.max(distance, minDistance) / minDistance, -rolloffFactor);\n break;\n }\n\n setRampTarget(node._attenuationRamp, Math.min(Math.max(attenuation, 0), 1));\n}\n\nfunction setSubNodePanningEnabled(node: SpatialSubNode, value: boolean): void {\n if (node._panningEnabled === value) {\n return;\n }\n node._panningEnabled = value;\n connectActiveInput(node);\n updateAttenuation(node);\n}\n\nfunction configureSubNode(node: SpatialSubNode, opts: SpatialSoundOptions): void {\n const panner = node._panner;\n if (opts.coneInnerAngle !== undefined) {\n panner.coneInnerAngle = r2d(opts.coneInnerAngle);\n }\n if (opts.coneOuterAngle !== undefined) {\n panner.coneOuterAngle = r2d(opts.coneOuterAngle);\n }\n if (opts.coneOuterVolume !== undefined) {\n panner.coneOuterGain = opts.coneOuterVolume;\n }\n if (opts.distanceModel !== undefined) {\n panner.distanceModel = opts.distanceModel;\n }\n if (opts.maxDistance !== undefined) {\n panner.maxDistance = opts.maxDistance;\n }\n if (opts.minDistance !== undefined) {\n panner.refDistance = opts.minDistance;\n }\n if (opts.rolloffFactor !== undefined) {\n panner.rolloffFactor = opts.rolloffFactor;\n }\n if (opts.panningModel !== undefined) {\n panner.panningModel = opts.panningModel;\n }\n if (opts.panningEnabled !== undefined) {\n setSubNodePanningEnabled(node, opts.panningEnabled);\n }\n if (opts.position) {\n node._position = { x: opts.position.x, y: opts.position.y, z: opts.position.z };\n }\n if (opts.rotationQuaternion) {\n node._rotationQuaternion = { x: opts.rotationQuaternion.x, y: opts.rotationQuaternion.y, z: opts.rotationQuaternion.z, w: opts.rotationQuaternion.w };\n } else if (opts.orientation) {\n node._orientation = { x: opts.orientation.x, y: opts.orientation.y, z: opts.orientation.z };\n node._lastQuat = { x: node._rotationQuaternion.x, y: node._rotationQuaternion.y, z: node._rotationQuaternion.z, w: node._rotationQuaternion.w };\n }\n updateSubNodePosition(node);\n updateSubNodeRotation(node);\n}\n\n// ─── Attacher (shared by sub-node and listener) ──────────────────────\n\nfunction attachSubNode(node: SpatialSubNode, target: SpatialTarget, type: SpatialAttachmentType | undefined): void {\n detachSubNode(node);\n node._attached = target;\n node._attachmentType = toAttachmentFlags(type);\n if (target.onDispose) {\n node._attachUnsub = target.onDispose.add(() => detachSubNode(node));\n }\n node._engine._spatialUpdaters.add(node._update);\n updateAttachedSubNode(node);\n}\n\nfunction detachSubNode(node: SpatialSubNode): void {\n node._attachUnsub?.();\n node._attachUnsub = null;\n node._attached = null;\n node._engine._spatialUpdaters.delete(node._update);\n}\n\nfunction updateAttachedSubNode(node: SpatialSubNode): void {\n const target = node._attached;\n if (!target) {\n return;\n }\n const { translation, rotation } = mat4Decompose(target.worldMatrix);\n const updatesPosition = (node._attachmentType & ATTACH_POSITION) !== 0;\n if (updatesPosition) {\n node._position = translation;\n updateSubNodePosition(node);\n }\n if (node._attachmentType & ATTACH_ROTATION) {\n node._rotationQuaternion = rotation;\n updateSubNodeRotation(node);\n }\n // Parity with AudioV2 `_SpatialAudioAttacherComponent.update`: when the\n // source position is not being updated but panning is disabled, refresh the\n // distance attenuation so it tracks a moving listener.\n if (!updatesPosition && !node._panningEnabled) {\n updateSubNodePosition(node);\n }\n}\n\n// ─── Sub-graph splicing ──────────────────────────────────────────────\n\n/**\n * Lazily build the panner sub-node and splice it into the host's sub-graph,\n * reconnecting any live instances. Idempotent.\n */\nfunction ensureSpatialSubNode(host: AudioGraphHostState): SpatialSubNode {\n const graph = host._graph;\n if (graph._spatial) {\n // The graph stores a structural slot; this feature module owns the full node.\n return graph._spatial as SpatialSubNode;\n }\n\n ensureSpatialListener(host._engine);\n\n const node = createSpatialSubNode(host._engine);\n connectSpatialOutput(node, graph._volume);\n graph._spatial = node;\n\n // Recompute the head and reconnect live instances (handles spatial+stereo parallel routing).\n rebuildSoundSubGraphHead(graph, host._instances);\n\n return node;\n}\n\n// ─── Public API ──────────────────────────────────────────────────────\n\n/**\n * Enables (or reconfigures) 3D spatial audio on a sound or bus, building the\n * panner sub-node on first use. Pulls the spatial module only when called.\n * @param host - A `StaticSound` or `AudioBus`.\n * @param options - Spatial options (position, distance model, cone, attach, …).\n */\nexport function enableSpatial(host: AudioGraphHost, options: SpatialSoundOptions = {}): void {\n const node = ensureSpatialSubNode(host);\n configureSubNode(node, options);\n if (options.attachedTo) {\n attachSubNode(node, options.attachedTo, options.attachmentType);\n }\n}\n\n/**\n * Sets the world position of a spatial sound/bus, building the panner sub-node\n * on first use.\n * @param host - A `StaticSound` or `AudioBus`.\n * @param position - World-space position.\n */\nexport function setSpatialPosition(host: AudioGraphHost, position: Vec3): void {\n const node = ensureSpatialSubNode(host);\n node._position = { x: position.x, y: position.y, z: position.z };\n updateSubNodePosition(node);\n}\n\n/**\n * Sets the facing orientation of a spatial sound/bus.\n * @param host - A `StaticSound` or `AudioBus`.\n * @param orientation - Facing direction.\n */\nexport function setSpatialOrientation(host: AudioGraphHost, orientation: Vec3): void {\n const node = ensureSpatialSubNode(host);\n node._orientation = { x: orientation.x, y: orientation.y, z: orientation.z };\n node._lastQuat = { x: node._rotationQuaternion.x, y: node._rotationQuaternion.y, z: node._rotationQuaternion.z, w: node._rotationQuaternion.w };\n updateSubNodeRotation(node);\n}\n\n/**\n * Attaches a spatial sound/bus — or the engine's listener — to a world\n * transform. The position/rotation follow the target on each\n * {@link updateSpatialAudio} (or auto-update) tick.\n * @param target - A `StaticSound`, `AudioBus`, or the `AudioEngine` (listener).\n * @param worldTarget - The transform to follow.\n * @param type - Which transform components to follow. Defaults to `\"positionAndRotation\"`.\n */\nexport function attachSpatialTarget(target: AudioGraphHost | AudioEngine, worldTarget: SpatialTarget, type?: SpatialAttachmentType): void {\n if (isEngine(target)) {\n const listener = ensureSpatialListener(target);\n attachListener(listener, worldTarget, type);\n return;\n }\n const node = ensureSpatialSubNode(target);\n attachSubNode(node, worldTarget, type);\n}\n\n/**\n * Detaches a spatial sound/bus — or the engine's listener — from its world\n * transform.\n * @param target - A `StaticSound`, `AudioBus`, or the `AudioEngine` (listener).\n */\nexport function detachSpatialTarget(target: AudioGraphHost | AudioEngine): void {\n if (isEngine(target)) {\n if (target._listener) {\n detachListener(target._listener as SpatialListener);\n }\n return;\n }\n if (target._graph._spatial) {\n detachSubNode(target._graph._spatial as SpatialSubNode);\n }\n}\n\n/**\n * Configures the spatial listener (the \"ears\"). Builds it on first use.\n * @param engine - The audio engine.\n * @param options - Listener options.\n */\nexport function setSpatialListener(engine: AudioEngine, options: SpatialListenerOptions = {}): void {\n const listener = ensureSpatialListener(engine);\n if (options.position) {\n listener._position = { x: options.position.x, y: options.position.y, z: options.position.z };\n updateListenerPosition(listener);\n }\n if (options.rotationQuaternion) {\n listener._rotationQuaternion = { x: options.rotationQuaternion.x, y: options.rotationQuaternion.y, z: options.rotationQuaternion.z, w: options.rotationQuaternion.w };\n updateListenerRotation(listener);\n }\n if (options.attachedTo) {\n attachListener(listener, options.attachedTo, options.attachmentType);\n }\n}\n\n/** Sets the listener world position, building the listener on first use. */\nexport function setSpatialListenerPosition(engine: AudioEngine, position: Vec3): void {\n const listener = ensureSpatialListener(engine);\n listener._position = { x: position.x, y: position.y, z: position.z };\n updateListenerPosition(listener);\n}\n\n/**\n * Pumps one spatial update for every attached node and the listener. Call this\n * from your render loop, or enable {@link setSpatialAutoUpdate}.\n * @param engine - The audio engine.\n */\nexport function updateSpatialAudio(engine: AudioEngine): void {\n for (const update of engine._spatialUpdaters) {\n update();\n }\n}\n\n/**\n * Toggles a `requestAnimationFrame`-driven loop that calls\n * {@link updateSpatialAudio} automatically.\n * @param engine - The audio engine.\n * @param enabled - Whether to run the auto-update loop.\n * @param minUpdateMs - Minimum time between updates, in milliseconds. Defaults to `0`.\n */\nexport function setSpatialAutoUpdate(engine: AudioEngine, enabled: boolean, minUpdateMs = 0): void {\n engine._spatialAutoStop?.();\n engine._spatialAutoStop = null;\n if (!enabled || typeof requestAnimationFrame !== \"function\") {\n return;\n }\n\n let active = true;\n let rafId = 0;\n let lastTime = 0;\n\n const tick = (): void => {\n if (!active) {\n return;\n }\n let skip = false;\n if (minUpdateMs > 0) {\n const now = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n if (lastTime && now - lastTime < minUpdateMs) {\n skip = true;\n } else {\n lastTime = now;\n }\n }\n if (!skip) {\n updateSpatialAudio(engine);\n }\n rafId = requestAnimationFrame(tick);\n };\n\n rafId = requestAnimationFrame(tick);\n const stop = (): void => {\n active = false;\n if (typeof cancelAnimationFrame === \"function\") {\n cancelAnimationFrame(rafId);\n }\n };\n engine._spatialAutoStop = stop;\n engine._disposers.push(stop);\n}\n\nfunction isEngine(target: AudioGraphHost | AudioEngine): target is AudioEngine {\n return \"_spatialUpdaters\" in target;\n}\n\n// ─── Spatial listener ────────────────────────────────────────────────\n\n/** Spatial listener state (the AudioContext listener). Pure state. @internal */\nexport interface SpatialListener {\n /** @internal */ _engine: AudioEngine;\n /** @internal */ _listener: AudioListener;\n /** Whether the listener exposes AudioParam properties (vs the legacy setters). @internal */ _hasParams: boolean;\n /** @internal */ _position: Vec3;\n /** @internal */ _rotationQuaternion: Quat;\n /** @internal */ _lastPosition: Vec3;\n /** @internal */ _lastQuat: Quat;\n /** @internal */ _positionX: RampParam | null;\n /** @internal */ _positionY: RampParam | null;\n /** @internal */ _positionZ: RampParam | null;\n /** @internal */ _forwardX: RampParam | null;\n /** @internal */ _forwardY: RampParam | null;\n /** @internal */ _forwardZ: RampParam | null;\n /** @internal */ _upX: RampParam | null;\n /** @internal */ _upY: RampParam | null;\n /** @internal */ _upZ: RampParam | null;\n /** @internal */ _attached: SpatialTarget | null;\n /** @internal */ _attachmentType: number;\n /** @internal */ _attachUnsub: (() => void) | null;\n /** @internal */ _update: () => void;\n /** @internal */ _dispose: () => void;\n}\n\n/** Builds the engine's spatial listener on first use (mirrors AudioV2's lazy listener). @internal */\nexport function ensureSpatialListener(engine: AudioEngine): SpatialListener {\n if (engine._listener) {\n // The engine stores a structural slot; this feature module owns the full listener.\n return engine._listener as SpatialListener;\n }\n\n const al = engine._ctx.listener;\n const hasParams = !!(al.positionX && al.forwardX && al.upX);\n\n const listener: SpatialListener = {\n _engine: engine,\n _listener: al,\n _hasParams: hasParams,\n _position: { x: 0, y: 0, z: 0 },\n _rotationQuaternion: { x: 0, y: 0, z: 0, w: 1 },\n _lastPosition: { x: NaN, y: NaN, z: NaN },\n _lastQuat: { x: NaN, y: NaN, z: NaN, w: NaN },\n _positionX: hasParams ? createRampParam(al.positionX, engine) : null,\n _positionY: hasParams ? createRampParam(al.positionY, engine) : null,\n _positionZ: hasParams ? createRampParam(al.positionZ, engine) : null,\n _forwardX: hasParams ? createRampParam(al.forwardX, engine) : null,\n _forwardY: hasParams ? createRampParam(al.forwardY, engine) : null,\n _forwardZ: hasParams ? createRampParam(al.forwardZ, engine) : null,\n _upX: hasParams ? createRampParam(al.upX, engine) : null,\n _upY: hasParams ? createRampParam(al.upY, engine) : null,\n _upZ: hasParams ? createRampParam(al.upZ, engine) : null,\n _attached: null,\n _attachmentType: ATTACH_BOTH,\n _attachUnsub: null,\n _update: () => updateAttachedListener(listener),\n _dispose: () => disposeSpatialListener(listener),\n };\n\n engine._listener = listener;\n return listener;\n}\n\nfunction updateListenerPosition(listener: SpatialListener): void {\n if (vecEquals(listener._lastPosition, listener._position)) {\n return;\n }\n const p = listener._position;\n if (listener._hasParams) {\n // Skip while a ramp is in flight for an attached listener (another update is coming).\n if (listener._attached && (isRamping(listener._positionX!) || isRamping(listener._positionY!) || isRamping(listener._positionZ!))) {\n return;\n }\n setRampTarget(listener._positionX!, p.x);\n setRampTarget(listener._positionY!, p.y);\n setRampTarget(listener._positionZ!, p.z);\n } else {\n listener._listener.setPosition(p.x, p.y, p.z);\n }\n listener._lastPosition = { x: p.x, y: p.y, z: p.z };\n}\n\nfunction updateListenerRotation(listener: SpatialListener): void {\n if (quatEquals(listener._lastQuat, listener._rotationQuaternion)) {\n return;\n }\n // NB: the Web Audio API is right-handed — forward is -Z, matching AudioV2.\n const forward = rotateByQuat(listener._rotationQuaternion, 0, 0, -1);\n const up = rotateByQuat(listener._rotationQuaternion, 0, 1, 0);\n if (listener._hasParams) {\n if (\n listener._attached &&\n (isRamping(listener._forwardX!) ||\n isRamping(listener._forwardY!) ||\n isRamping(listener._forwardZ!) ||\n isRamping(listener._upX!) ||\n isRamping(listener._upY!) ||\n isRamping(listener._upZ!))\n ) {\n return;\n }\n setRampTarget(listener._forwardX!, forward.x);\n setRampTarget(listener._forwardY!, forward.y);\n setRampTarget(listener._forwardZ!, forward.z);\n setRampTarget(listener._upX!, up.x);\n setRampTarget(listener._upY!, up.y);\n setRampTarget(listener._upZ!, up.z);\n } else {\n listener._listener.setOrientation(forward.x, forward.y, forward.z, up.x, up.y, up.z);\n }\n listener._lastQuat = { x: listener._rotationQuaternion.x, y: listener._rotationQuaternion.y, z: listener._rotationQuaternion.z, w: listener._rotationQuaternion.w };\n}\n\nfunction attachListener(listener: SpatialListener, target: SpatialTarget, type: SpatialAttachmentType | undefined): void {\n detachListener(listener);\n listener._attached = target;\n listener._attachmentType = toAttachmentFlags(type);\n if (target.onDispose) {\n listener._attachUnsub = target.onDispose.add(() => detachListener(listener));\n }\n listener._engine._spatialUpdaters.add(listener._update);\n updateAttachedListener(listener);\n}\n\nfunction detachListener(listener: SpatialListener): void {\n listener._attachUnsub?.();\n listener._attachUnsub = null;\n listener._attached = null;\n listener._engine._spatialUpdaters.delete(listener._update);\n}\n\nfunction updateAttachedListener(listener: SpatialListener): void {\n const target = listener._attached;\n if (!target) {\n return;\n }\n const { translation, rotation } = mat4Decompose(target.worldMatrix);\n if (listener._attachmentType & ATTACH_POSITION) {\n listener._position = translation;\n updateListenerPosition(listener);\n }\n if (listener._attachmentType & ATTACH_ROTATION) {\n listener._rotationQuaternion = rotation;\n updateListenerRotation(listener);\n }\n}\n\nfunction disposeSpatialListener(listener: SpatialListener): void {\n detachListener(listener);\n listener._engine._listener = null;\n}\n"],"names":[],"mappings":"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"}