@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 @@
1
+ {"version":3,"file":"visualizer.js","sources":["../../../src/audio/visualizer.ts"],"sourcesContent":["/**\n * Real-time audio visualizer — opt-in demo helper.\n *\n * Draws a frequency-bar + waveform display from an {@link AnalyzerSubNode} tap\n * to a 2D `<canvas>`. This is a Lite-specific presentation helper — Babylon.js\n * AudioV2 has no canvas visualizer — so it is intentional adaptation glue, not a\n * port. It builds on the faithful analyzer port (Phase 5) and is fully\n * tree-shakable: importing nothing from here costs nothing, and the module is\n * never referenced by the core sound/bus/engine modules.\n *\n * The render loop uses `requestAnimationFrame` when available; a single frame can\n * also be drawn directly via {@link renderAudioVisualizerFrame} (used in tests).\n */\n\nimport { enableAnalyzer, getByteFrequencyData, getByteTimeDomainData } from \"./analyzer.js\";\nimport { type AudioGraphHost } from \"./host-types.js\";\n\n/** What to draw in the visualizer. */\nexport type AudioVisualizerMode = \"bars\" | \"waveform\" | \"both\";\n\n/** Default visualizer settings. */\nconst Defaults = {\n fftSize: 2048,\n smoothing: 0.8,\n mode: \"both\" as AudioVisualizerMode,\n backgroundColor: \"#101014\",\n barColor: \"#4fc3f7\",\n waveformColor: \"#ffffff\",\n} as const;\n\n/** Options for {@link createAudioVisualizer}. */\nexport interface AudioVisualizerOptions {\n /** FFT window size (a power of two). Defaults to `2048`. */\n fftSize?: number;\n /** Analyzer time-averaging constant in `[0, 1]`. Defaults to `0.8`. */\n smoothing?: number;\n /** What to draw. Defaults to `\"both\"`. */\n mode?: AudioVisualizerMode;\n /** Canvas background fill. Defaults to `\"#101014\"`. */\n backgroundColor?: string;\n /** Frequency-bar color. Defaults to `\"#4fc3f7\"`. */\n barColor?: string;\n /** Waveform line color. Defaults to `\"#ffffff\"`. */\n waveformColor?: string;\n}\n\n/** Visualizer state. Pure state — driven by the visualizer functions. */\nexport interface AudioVisualizer {\n /** The canvas being drawn to. */\n readonly canvas: HTMLCanvasElement;\n /** @internal */ _host: AudioGraphHost;\n /** @internal */ _ctx2d: CanvasRenderingContext2D;\n /** @internal */ _mode: AudioVisualizerMode;\n /** @internal */ _bgColor: string;\n /** @internal */ _barColor: string;\n /** @internal */ _waveColor: string;\n /** @internal */ _freq: Uint8Array;\n /** @internal */ _time: Uint8Array;\n /** @internal */ _raf: number | null;\n /** @internal */ _dispose(): void;\n}\n\n/**\n * Creates a real-time visualizer that taps the host's analyzer and draws to the\n * given canvas. Enables the analyzer on the host if it is not already enabled.\n * Call {@link startAudioVisualizer} to begin the animation loop.\n * @param host - A `StaticSound`, `StreamingSound`, `AudioBus`, or input source.\n * @param canvas - The destination 2D canvas.\n * @param options - Visualizer options.\n * @returns The visualizer handle; dispose it with {@link disposeAudioVisualizer}.\n * @throws If a 2D context cannot be obtained from the canvas.\n */\nexport function createAudioVisualizer(host: AudioGraphHost, canvas: HTMLCanvasElement, options: AudioVisualizerOptions = {}): AudioVisualizer {\n const fftSize = options.fftSize ?? Defaults.fftSize;\n enableAnalyzer(host, { fftSize, smoothing: options.smoothing ?? Defaults.smoothing });\n\n const ctx2d = canvas.getContext(\"2d\");\n if (!ctx2d) {\n throw new Error(\"Unable to get a 2D context from the visualizer canvas.\");\n }\n\n const viz: AudioVisualizer = {\n canvas,\n _host: host,\n _ctx2d: ctx2d,\n _mode: options.mode ?? Defaults.mode,\n _bgColor: options.backgroundColor ?? Defaults.backgroundColor,\n _barColor: options.barColor ?? Defaults.barColor,\n _waveColor: options.waveformColor ?? Defaults.waveformColor,\n _freq: new Uint8Array(fftSize / 2),\n _time: new Uint8Array(fftSize),\n _raf: null,\n _dispose: () => disposeAudioVisualizer(viz),\n };\n return viz;\n}\n\nfunction drawBars(viz: AudioVisualizer, width: number, height: number): void {\n const ctx = viz._ctx2d;\n const bins = viz._freq;\n getByteFrequencyData(viz._host, bins);\n const count = bins.length;\n const barWidth = width / count;\n ctx.fillStyle = viz._barColor;\n for (let i = 0; i < count; i++) {\n const magnitude = bins[i]! / 255;\n const barHeight = magnitude * height;\n ctx.fillRect(i * barWidth, height - barHeight, Math.max(barWidth - 1, 1), barHeight);\n }\n}\n\nfunction drawWaveform(viz: AudioVisualizer, width: number, height: number): void {\n const ctx = viz._ctx2d;\n const samples = viz._time;\n getByteTimeDomainData(viz._host, samples);\n const count = samples.length;\n const step = width / count;\n ctx.lineWidth = 2;\n ctx.strokeStyle = viz._waveColor;\n ctx.beginPath();\n for (let i = 0; i < count; i++) {\n // Byte time-domain data is centered on 128; map to [0, height].\n const y = (samples[i]! / 255) * height;\n const x = i * step;\n if (i === 0) {\n ctx.moveTo(x, y);\n } else {\n ctx.lineTo(x, y);\n }\n }\n ctx.stroke();\n}\n\n/**\n * Draws a single visualizer frame from the current analyzer data. Safe to call\n * directly (e.g. from a custom loop or a test) without starting the built-in\n * animation loop.\n * @param viz - The visualizer handle.\n */\nexport function renderAudioVisualizerFrame(viz: AudioVisualizer): void {\n const { width, height } = viz.canvas;\n const ctx = viz._ctx2d;\n ctx.fillStyle = viz._bgColor;\n ctx.fillRect(0, 0, width, height);\n\n if (viz._mode === \"bars\" || viz._mode === \"both\") {\n drawBars(viz, width, height);\n }\n if (viz._mode === \"waveform\" || viz._mode === \"both\") {\n drawWaveform(viz, width, height);\n }\n}\n\n/**\n * Starts the `requestAnimationFrame` render loop. No-op if already running or if\n * `requestAnimationFrame` is unavailable (e.g. a non-browser environment).\n * @param viz - The visualizer handle.\n */\nexport function startAudioVisualizer(viz: AudioVisualizer): void {\n if (viz._raf !== null || typeof requestAnimationFrame !== \"function\") {\n return;\n }\n const loop = () => {\n renderAudioVisualizerFrame(viz);\n viz._raf = requestAnimationFrame(loop);\n };\n viz._raf = requestAnimationFrame(loop);\n}\n\n/**\n * Stops the render loop if it is running.\n * @param viz - The visualizer handle.\n */\nexport function stopAudioVisualizer(viz: AudioVisualizer): void {\n if (viz._raf !== null) {\n if (typeof cancelAnimationFrame === \"function\") {\n cancelAnimationFrame(viz._raf);\n }\n viz._raf = null;\n }\n}\n\n/**\n * Stops the render loop and releases the visualizer. The underlying analyzer tap\n * stays on the host (dispose the host to release it).\n * @param viz - The visualizer handle.\n */\nexport function disposeAudioVisualizer(viz: AudioVisualizer): void {\n stopAudioVisualizer(viz);\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { computeLocalBasis, computeYawPitchFromLookAt } from './geospatial-camera.js';
2
+ import { flyGeospatialCameraToAsync } from './geospatial-camera-fly.js';
2
3
  import { GEO_EPSILON, clampZoomDistance } from './geospatial-limits.js';
3
4
  import { getViewProjectionMatrix } from './camera.js';
4
5
  import { createPickingRay } from '../picking/ray.js';
@@ -8,6 +9,8 @@ import { computePanSpeedMultiplier, integrateInertialVelocity, REFERENCE_FRAME_R
8
9
  function attachGeospatialControls(camera, canvas, scene, options) {
9
10
  const zoomToCursor = options?.zoomToCursor ?? true;
10
11
  const checkCollisions = options?.checkCollisions ?? false;
12
+ const doubleTapAnimationDurationMs = options?.doubleTapAnimationDurationMs ?? 1e3;
13
+ const doubleTapEasingFunction = options?.doubleTapEasingFunction ?? null;
11
14
  const speed = 1;
12
15
  const panSpeed = 1;
13
16
  const rotationXSpeed = Math.PI / 500;
@@ -418,6 +421,9 @@ function attachGeospatialControls(camera, canvas, scene, options) {
418
421
  de -= 1;
419
422
  }
420
423
  if (dn !== 0 || de !== 0) {
424
+ const invLen = 1 / Math.hypot(dn, de);
425
+ dn *= invLen;
426
+ de *= invLen;
421
427
  computeLocalBasis(camera.center, east, north, up);
422
428
  panAccumulated.x += (north.x * dn + east.x * de) * panStep;
423
429
  panAccumulated.y += (north.y * dn + east.y * de) * panStep;
@@ -471,6 +477,21 @@ function attachGeospatialControls(camera, canvas, scene, options) {
471
477
  function onContextMenu(e) {
472
478
  e.preventDefault();
473
479
  }
480
+ function onDoubleClick(e) {
481
+ if (e.button !== 0 || e.buttons !== 0) {
482
+ return;
483
+ }
484
+ e.preventDefault();
485
+ const r = canvas.getBoundingClientRect();
486
+ const pick = pickScreen(e.clientX - r.left, e.clientY - r.top);
487
+ if (pick.hit && pick.point) {
488
+ void flyGeospatialCameraToAsync(camera, scene, {
489
+ center: { x: pick.point.x, y: pick.point.y, z: pick.point.z },
490
+ durationMs: doubleTapAnimationDurationMs,
491
+ ease: doubleTapEasingFunction ?? void 0
492
+ });
493
+ }
494
+ }
474
495
  function onKeyDown(e) {
475
496
  keysDown.add(e.code);
476
497
  }
@@ -564,6 +585,7 @@ function attachGeospatialControls(camera, canvas, scene, options) {
564
585
  [canvas, "pointerup", onPointerUp],
565
586
  [canvas, "wheel", onWheel, { passive: false }],
566
587
  [canvas, "contextmenu", onContextMenu],
588
+ [canvas, "dblclick", onDoubleClick],
567
589
  [canvas, "touchstart", onTouchStart, { passive: false }],
568
590
  [canvas, "touchmove", onTouchMove, { passive: false }],
569
591
  [canvas, "touchend", onTouchEnd],
@@ -1 +1 @@
1
- {"version":3,"file":"geospatial-camera-controls.js","sources":["../../../src/camera/geospatial-camera-controls.ts"],"sourcesContent":["import type { GeospatialCamera } from \"./geospatial-camera.js\";\nimport { computeLocalBasis, computeYawPitchFromLookAt } from \"./geospatial-camera.js\";\nimport { clampZoomDistance, GEO_EPSILON } from \"./geospatial-limits.js\";\nimport { getViewProjectionMatrix } from \"./camera.js\";\nimport { createPickingRay } from \"../picking/ray.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Vec3, Mat4, Mat4Storage } from \"../math/types.js\";\nimport { REFERENCE_FRAME_RATE, integrateInertialVelocity, computePanSpeedMultiplier, computeZoomSpeedMultiplier } from \"./geospatial-movement.js\";\n\n/** Options for {@link attachGeospatialControls}. */\nexport interface GeospatialControlOptions {\n /** When true, zooming moves toward the point under the cursor; otherwise along the look vector. Default true. */\n zoomToCursor?: boolean;\n /** Enable simple sphere collision so the camera cannot dip below the surface. Default false. */\n checkCollisions?: boolean;\n}\n\ninterface PickResult {\n hit: boolean;\n point: Vec3 | null;\n ray: { origin: Vec3; direction: Vec3 } | null;\n}\n\n/**\n * Attach orbit / pan / zoom controls to a {@link GeospatialCamera}, matching\n * Babylon.js `GeospatialCamera` interactions:\n * - Left-drag: pan (the cursor stays anchored to the globe surface).\n * - Middle/right-drag: rotate (yaw + pitch / tilt).\n * - Wheel: zoom (toward the cursor by default).\n * - Touch: single-finger drag = pan; two-finger pinch = zoom toward the centroid,\n * promoting to a pan once the centroid drifts ≥ 20 px.\n * - Keyboard: arrows = pan, Ctrl+arrows = tilt (pitch/yaw), +/- = zoom along the look vector.\n *\n * Movement uses Babylon.js's framerate-independent physics model (velocity +\n * inertial decay). Globe picking is analytic ray-sphere against the planet\n * sphere (origin-centred, radius = `limits.planetRadius`) — no mesh picking\n * subsystem is required. Inertia is integrated once per frame from the scene's\n * render loop (`scene._beforeRender`).\n *\n * Returns a disposer that removes all listeners and the per-frame hook.\n */\nexport function attachGeospatialControls(camera: GeospatialCamera, canvas: HTMLCanvasElement, scene: SceneContext, options?: GeospatialControlOptions): () => void {\n const zoomToCursor = options?.zoomToCursor ?? true;\n const checkCollisions = options?.checkCollisions ?? false;\n\n // ── Speed / inertia (Babylon GeospatialCameraMovement defaults) ──\n const speed = 1;\n const panSpeed = 1;\n const rotationXSpeed = Math.PI / 500;\n const rotationYSpeed = Math.PI / 500;\n const zoomSpeed = 2;\n const panInertia = 0;\n const rotationInertia = 0;\n const zoomInertia = 0.9;\n\n // ── Accumulated input (reset each frame) ──\n const panAccumulated: Vec3 = { x: 0, y: 0, z: 0 };\n const rotationAccumulated = { x: 0, y: 0 }; // x = pitch pixels, y = yaw pixels\n let zoomAccumulated = 0;\n let activeInput = false;\n\n // ── Velocities (for inertia) ──\n const panVelocity: Vec3 = { x: 0, y: 0, z: 0 };\n const rotationVelocity = { x: 0, y: 0 };\n let zoomVelocity = 0;\n let prevFrameTimeMs = 0;\n\n // ── Per-frame multipliers ──\n let panSpeedMultiplier = 1;\n let zoomSpeedMultiplier = 1;\n\n // ── Per-frame computed deltas ──\n const panDelta: Vec3 = { x: 0, y: 0, z: 0 };\n const rotationDelta = { x: 0, y: 0 };\n let zoomDelta = 0;\n let computedZoomPickPoint: Vec3 | null = null;\n\n // ── Drag (pan) state ──\n let hitPointRadius: number | undefined;\n const dragPlaneNormal: Vec3 = { x: 0, y: 0, z: 0 };\n const dragPlaneOriginEcef: Vec3 = { x: 0, y: 0, z: 0 };\n const dragPlaneHitPointLocal: Vec3 = { x: 0, y: 0, z: 0 };\n const previousDragPlaneHitPointLocal: Vec3 = { x: 0, y: 0, z: 0 };\n\n // ── Pointer state ──\n let pointerX = 0;\n let pointerY = 0;\n let mode: \"none\" | \"pan\" | \"rotate\" = \"none\";\n let lastX = 0;\n let lastY = 0;\n const keysDown = new Set<string>();\n\n // ── Touch (pinch) state ──\n const activeTouches = new Map<number, { x: number; y: number }>();\n let pinchPrevDist = 0;\n let pinchStartCentroidX = 0;\n let pinchStartCentroidY = 0;\n let pinchPanning = false;\n const PINCH_PAN_THRESHOLD = 20; // px of centroid translation before a pinch also pans\n const PINCH_ZOOM_SCALE = 0.05; // pixels of finger-spread → zoom-accumulator units\n\n function rectSize(): { width: number; height: number } {\n const r = canvas.getBoundingClientRect();\n return { width: r.width || canvas.width, height: r.height || canvas.height };\n }\n\n function toCanvas(e: PointerEvent | WheelEvent): void {\n const r = canvas.getBoundingClientRect();\n pointerX = e.clientX - r.left;\n pointerY = e.clientY - r.top;\n }\n\n // ── Picking (analytic ray-sphere against the planet) ──\n\n function screenRay(x: number, y: number): { origin: Vec3; direction: Vec3 } | null {\n const { width, height } = rectSize();\n const vp = getViewProjectionMatrix(camera, width / height);\n const ray = createPickingRay(x, y, vp, width, height);\n if (!ray) {\n return null;\n }\n return { origin: { x: ray.origin[0], y: ray.origin[1], z: ray.origin[2] }, direction: { x: ray.direction[0], y: ray.direction[1], z: ray.direction[2] } };\n }\n\n /** Nearest positive intersection of a ray with the planet sphere (centre origin). */\n function intersectPlanet(origin: Vec3, dir: Vec3): Vec3 | null {\n const r = camera.limits.planetRadius;\n const b = 2 * (origin.x * dir.x + origin.y * dir.y + origin.z * dir.z);\n const c = origin.x * origin.x + origin.y * origin.y + origin.z * origin.z - r * r;\n const disc = b * b - 4 * c;\n if (disc < 0) {\n return null;\n }\n const sq = Math.sqrt(disc);\n let t = (-b - sq) / 2;\n if (t < 0) {\n t = (-b + sq) / 2;\n }\n if (t < 0) {\n return null;\n }\n return { x: origin.x + dir.x * t, y: origin.y + dir.y * t, z: origin.z + dir.z * t };\n }\n\n function pickScreen(x: number, y: number): PickResult {\n const ray = screenRay(x, y);\n if (!ray) {\n return { hit: false, point: null, ray: null };\n }\n const point = intersectPlanet(ray.origin, ray.direction);\n return { hit: !!point, point, ray };\n }\n\n function pickAlongVector(dir: Vec3): Vec3 | null {\n return intersectPlanet(camera.position, dir);\n }\n\n // ── Pan (drag-plane) math ──\n\n function recalcDragPlaneHitPoint(radius: number, ray: { origin: Vec3; direction: Vec3 }, localToEcef: Mat4Storage): void {\n const posLen = Math.max(1e-5, Math.hypot(camera.position.x, camera.position.y, camera.position.z));\n const s = radius / posLen;\n dragPlaneOriginEcef.x = camera.position.x * s;\n dragPlaneOriginEcef.y = camera.position.y * s;\n dragPlaneOriginEcef.z = camera.position.z * s;\n\n const east: Vec3 = { x: 0, y: 0, z: 0 };\n const north: Vec3 = { x: 0, y: 0, z: 0 };\n computeLocalBasis(dragPlaneOriginEcef, east, north, dragPlaneNormal);\n\n // localToEcef = columns [east, north, up] + translation origin.\n localToEcef[0] = east.x;\n localToEcef[1] = east.y;\n localToEcef[2] = east.z;\n localToEcef[3] = 0;\n localToEcef[4] = north.x;\n localToEcef[5] = north.y;\n localToEcef[6] = north.z;\n localToEcef[7] = 0;\n localToEcef[8] = dragPlaneNormal.x;\n localToEcef[9] = dragPlaneNormal.y;\n localToEcef[10] = dragPlaneNormal.z;\n localToEcef[11] = 0;\n localToEcef[12] = dragPlaneOriginEcef.x;\n localToEcef[13] = dragPlaneOriginEcef.y;\n localToEcef[14] = dragPlaneOriginEcef.z;\n localToEcef[15] = 1;\n\n const ecefToLocal = mat4Invert(localToEcef as unknown as Mat4);\n if (!ecefToLocal) {\n return;\n }\n\n // Plane: normal·P + d = 0, d = -normal·origin.\n const d = -(dragPlaneNormal.x * dragPlaneOriginEcef.x + dragPlaneNormal.y * dragPlaneOriginEcef.y + dragPlaneNormal.z * dragPlaneOriginEcef.z);\n const denom = dragPlaneNormal.x * ray.direction.x + dragPlaneNormal.y * ray.direction.y + dragPlaneNormal.z * ray.direction.z;\n if (Math.abs(denom) > 1e-9) {\n const t = -(dragPlaneNormal.x * ray.origin.x + dragPlaneNormal.y * ray.origin.y + dragPlaneNormal.z * ray.origin.z + d) / denom;\n if (t >= 0) {\n const hx = ray.origin.x + ray.direction.x * t;\n const hy = ray.origin.y + ray.direction.y * t;\n const hz = ray.origin.z + ray.direction.z * t;\n transformCoordinates(hx, hy, hz, ecefToLocal as unknown as Mat4Storage, dragPlaneHitPointLocal);\n }\n }\n }\n\n function startDrag(x: number, y: number): void {\n const pick = pickScreen(x, y);\n if (pick.point && pick.ray) {\n hitPointRadius = Math.hypot(pick.point.x, pick.point.y, pick.point.z);\n const tmp = scratchMat;\n recalcDragPlaneHitPoint(hitPointRadius, pick.ray, tmp);\n previousDragPlaneHitPointLocal.x = dragPlaneHitPointLocal.x;\n previousDragPlaneHitPointLocal.y = dragPlaneHitPointLocal.y;\n previousDragPlaneHitPointLocal.z = dragPlaneHitPointLocal.z;\n } else {\n hitPointRadius = undefined;\n }\n }\n\n function handleDrag(x: number, y: number): void {\n if (hitPointRadius === undefined) {\n return;\n }\n const ray = screenRay(x, y);\n if (!ray) {\n return;\n }\n const localToEcef = scratchMat;\n recalcDragPlaneHitPoint(hitPointRadius, ray, localToEcef);\n\n let dx = dragPlaneHitPointLocal.x - previousDragPlaneHitPointLocal.x;\n let dy = dragPlaneHitPointLocal.y - previousDragPlaneHitPointLocal.y;\n let dz = dragPlaneHitPointLocal.z - previousDragPlaneHitPointLocal.z;\n\n // Clamp to avoid huge jumps when the camera is nearly parallel to the plane.\n const maxDelta = hitPointRadius * 0.1;\n const len = Math.hypot(dx, dy, dz);\n if (len > maxDelta) {\n const k = maxDelta / len;\n dx *= k;\n dy *= k;\n dz *= k;\n }\n\n previousDragPlaneHitPointLocal.x = dragPlaneHitPointLocal.x;\n previousDragPlaneHitPointLocal.y = dragPlaneHitPointLocal.y;\n previousDragPlaneHitPointLocal.z = dragPlaneHitPointLocal.z;\n\n // delta (local) → ECEF normal transform.\n const ex = dx * localToEcef[0]! + dy * localToEcef[4]! + dz * localToEcef[8]!;\n const ey = dx * localToEcef[1]! + dy * localToEcef[5]! + dz * localToEcef[9]!;\n const ez = dx * localToEcef[2]! + dy * localToEcef[6]! + dz * localToEcef[10]!;\n\n dragPlaneOriginEcef.x += ex;\n dragPlaneOriginEcef.y += ey;\n dragPlaneOriginEcef.z += ez;\n\n panAccumulated.x -= ex;\n panAccumulated.y -= ey;\n panAccumulated.z -= ez;\n }\n\n function stopDrag(): void {\n hitPointRadius = undefined;\n }\n\n const scratchMat = new Float32Array(16) as unknown as Mat4Storage;\n\n // ── Zoom input ──\n\n function handleZoom(delta: number, toCursor: boolean): void {\n if (delta === 0) {\n return;\n }\n zoomAccumulated += delta;\n const pick = pickScreen(pointerX, pointerY);\n if (toCursor && pick.hit && pick.point && zoomToCursor) {\n computedZoomPickPoint = pick.point;\n } else {\n computedZoomPickPoint = pickAlongVector(camera._lookAt);\n }\n }\n\n // ── Apply per-frame deltas to the camera ──\n\n function applyGeocentricTranslation(): void {\n const cx = camera.center.x + panDelta.x;\n const cy = camera.center.y + panDelta.y;\n const cz = camera.center.z + panDelta.z;\n // Re-project onto the sphere of the same magnitude as the current centre.\n const len = Math.hypot(cx, cy, cz) || 1;\n const target = Math.hypot(camera.center.x, camera.center.y, camera.center.z);\n const k = target / len;\n camera._setOrientation(camera.yaw, camera.pitch, camera.radius, { x: cx * k, y: cy * k, z: cz * k });\n }\n\n function applyGeocentricRotation(): void {\n if (rotationDelta.x === 0 && rotationDelta.y === 0) {\n return;\n }\n const pitch = rotationDelta.x !== 0 ? clampNum(camera.pitch + rotationDelta.x, 0, 0.5 * Math.PI - GEO_EPSILON) : camera.pitch;\n const yaw = rotationDelta.y !== 0 ? camera.yaw + rotationDelta.y : camera.yaw;\n camera._setOrientation(yaw, pitch, camera.radius, camera.center);\n }\n\n function centerAndRadiusFromZoomToPoint(target: Vec3, distance: number, out: Vec3): number {\n const limits = camera.limits;\n const dx = target.x - camera.position.x;\n const dy = target.y - camera.position.y;\n const dz = target.z - camera.position.z;\n const distToTarget = Math.hypot(dx, dy, dz);\n if (distToTarget < limits.radiusMin) {\n out.x = camera.center.x;\n out.y = camera.center.y;\n out.z = camera.center.z;\n return clampNum(camera.radius - distance, limits.radiusMin, limits.radiusMax);\n }\n const s = distance / distToTarget;\n const npx = camera.position.x + dx * s;\n const npy = camera.position.y + dy * s;\n const npz = camera.position.z + dz * s;\n const projected = dx * s * camera._lookAt.x + dy * s * camera._lookAt.y + dz * s * camera._lookAt.z;\n const newRadius = clampNum(camera.radius - projected, limits.radiusMin, limits.radiusMax);\n out.x = npx + camera._lookAt.x * newRadius;\n out.y = npy + camera._lookAt.y * newRadius;\n out.z = npz + camera._lookAt.z * newRadius;\n return newRadius;\n }\n\n const zoomCenterScratch: Vec3 = { x: 0, y: 0, z: 0 };\n\n function applyZoom(): void {\n const limits = camera.limits;\n const distToTarget = computedZoomPickPoint ? dist(camera.position, computedZoomPickPoint) : undefined;\n const clamped = clampZoomDistance(limits, zoomDelta, camera.radius, distToTarget);\n if (Math.abs(clamped) < GEO_EPSILON) {\n return;\n }\n if (computedZoomPickPoint) {\n const newRadius = centerAndRadiusFromZoomToPoint(computedZoomPickPoint, clamped, zoomCenterScratch);\n camera._setOrientation(camera.yaw, camera.pitch, newRadius, zoomCenterScratch);\n } else {\n const newRadius = clampNum(camera.radius - clamped, limits.radiusMin, limits.radiusMax);\n camera._setOrientation(camera.yaw, camera.pitch, newRadius, camera.center);\n }\n }\n\n let wasCenterMovingLastFrame = false;\n\n function recalculateCenter(isCenterMoving: boolean): void {\n const shouldRecalc = wasCenterMovingLastFrame && !isCenterMoving;\n wasCenterMovingLastFrame = isCenterMoving;\n if (!shouldRecalc) {\n return;\n }\n const picked = pickAlongVector(camera._lookAt);\n if (!picked) {\n return;\n }\n const invLen = 1 / (Math.hypot(picked.x, picked.y, picked.z) || 1);\n const dot = camera._lookAt.x * -picked.x * invLen + camera._lookAt.y * -picked.y * invLen + camera._lookAt.z * -picked.z * invLen;\n if (dot <= 0) {\n return;\n }\n const newRadius = dist(camera.position, picked);\n if (newRadius <= GEO_EPSILON) {\n return;\n }\n const yp = { x: 0, y: 0 };\n computeYawPitchFromLookAt(camera._lookAt, picked, camera.yaw, yp);\n camera._setOrientation(yp.x, yp.y, newRadius, picked);\n }\n\n function applyCollision(): void {\n if (!checkCollisions) {\n return;\n }\n const minDist = camera.limits.planetRadius + camera.limits.radiusMin;\n const posLen = Math.hypot(camera.position.x, camera.position.y, camera.position.z);\n if (posLen >= minDist || posLen < 1e-6) {\n return;\n }\n const lift = minDist - posLen;\n const inv = 1 / posLen;\n const ox = camera.position.x * inv * lift;\n const oy = camera.position.y * inv * lift;\n const oz = camera.position.z * inv * lift;\n // Lift the whole rig: offset the centre, position follows from setOrientation.\n camera._setOrientation(camera.yaw, camera.pitch, camera.radius, { x: camera.center.x + ox, y: camera.center.y + oy, z: camera.center.z + oz });\n }\n\n // ── Framerate-independent physics ──\n\n function effectiveDeltaMs(dt: number): number {\n if (dt > 0) {\n return dt;\n }\n if (prevFrameTimeMs > 0) {\n return prevFrameTimeMs;\n }\n return 1000 / REFERENCE_FRAME_RATE;\n }\n\n function nextVelocity(vel: number, pixelDelta: number, inertia: number, dt: number): number {\n return integrateInertialVelocity(vel, pixelDelta, inertia, effectiveDeltaMs(dt), activeInput);\n }\n\n function isDragging(): boolean {\n return hitPointRadius !== undefined;\n }\n\n function computeFrameDeltas(dt: number): void {\n // Pan dampening near the poles and with altitude.\n const center = camera.center;\n if (panAccumulated.x !== 0 || panAccumulated.y !== 0 || panAccumulated.z !== 0) {\n panSpeedMultiplier = computePanSpeedMultiplier(center, camera.position);\n } else {\n panSpeedMultiplier = 1;\n }\n\n // Zoom speed scales with distance to target; suppressed while dragging/rotating.\n if (isDragging() || rotationAccumulated.x !== 0 || rotationAccumulated.y !== 0) {\n zoomSpeedMultiplier = 0;\n zoomVelocity = 0;\n } else {\n const target = computedZoomPickPoint ? dist(camera.position, computedZoomPickPoint) : dist(camera.position, center);\n zoomSpeedMultiplier = computeZoomSpeedMultiplier(target);\n }\n\n const eff = effectiveDeltaMs(dt);\n\n panVelocity.x = nextVelocity(panVelocity.x, panAccumulated.x, panInertia, dt);\n panVelocity.y = nextVelocity(panVelocity.y, panAccumulated.y, panInertia, dt);\n panVelocity.z = nextVelocity(panVelocity.z, panAccumulated.z, panInertia, dt);\n const panScale = speed * panSpeed * panSpeedMultiplier * eff;\n panDelta.x = panVelocity.x * panScale;\n panDelta.y = panVelocity.y * panScale;\n panDelta.z = panVelocity.z * panScale;\n\n rotationVelocity.x = nextVelocity(rotationVelocity.x, rotationAccumulated.x, rotationInertia, dt);\n rotationVelocity.y = nextVelocity(rotationVelocity.y, rotationAccumulated.y, rotationInertia, dt);\n rotationDelta.x = rotationVelocity.x * speed * rotationXSpeed * eff;\n rotationDelta.y = rotationVelocity.y * speed * rotationYSpeed * eff;\n\n zoomVelocity = nextVelocity(zoomVelocity, zoomAccumulated, zoomInertia, dt);\n zoomDelta = zoomVelocity * (speed * zoomSpeed * zoomSpeedMultiplier) * eff;\n\n if (dt > 0) {\n prevFrameTimeMs = dt;\n }\n zoomAccumulated = 0;\n panAccumulated.x = panAccumulated.y = panAccumulated.z = 0;\n rotationAccumulated.x = rotationAccumulated.y = 0;\n activeInput = false;\n }\n\n // ── Per-frame loop ──\n\n function onBeforeRenderTick(deltaMs: number): void {\n // Keyboard injects accumulated input before physics.\n pollKeyboard();\n\n const hasInput =\n panAccumulated.x !== 0 || panAccumulated.y !== 0 || panAccumulated.z !== 0 || rotationAccumulated.x !== 0 || rotationAccumulated.y !== 0 || zoomAccumulated !== 0;\n if (hasInput && camera._cancelFly) {\n camera._cancelFly();\n }\n\n computeFrameDeltas(deltaMs);\n\n let isCenterMoving = false;\n if (panDelta.x !== 0 || panDelta.y !== 0 || panDelta.z !== 0) {\n applyGeocentricTranslation();\n isCenterMoving = true;\n }\n if (rotationDelta.x !== 0 || rotationDelta.y !== 0) {\n applyGeocentricRotation();\n }\n if (Math.abs(zoomDelta) > GEO_EPSILON) {\n applyZoom();\n isCenterMoving = true;\n }\n recalculateCenter(isCenterMoving);\n applyCollision();\n }\n\n // ── Keyboard ──\n\n function pollKeyboard(): void {\n if (keysDown.size === 0) {\n return;\n }\n activeInput = true;\n const rotateStep = 6; // pixels-equivalent per frame\n const zoomStep = 4;\n const panStep = camera.radius * 0.0015;\n const ctrl = keysDown.has(\"ControlLeft\") || keysDown.has(\"ControlRight\");\n\n // +/- : zoom along the look vector (no zoom-to-point pick).\n if (keysDown.has(\"Equal\") || keysDown.has(\"NumpadAdd\")) {\n zoomAccumulated += zoomStep;\n computedZoomPickPoint = null;\n }\n if (keysDown.has(\"Minus\") || keysDown.has(\"NumpadSubtract\")) {\n zoomAccumulated -= zoomStep;\n computedZoomPickPoint = null;\n }\n\n if (ctrl) {\n // Ctrl + arrows: tilt (pitch) and yaw, matching Babylon.js.\n if (keysDown.has(\"ArrowLeft\")) {\n rotationAccumulated.y -= rotateStep;\n }\n if (keysDown.has(\"ArrowRight\")) {\n rotationAccumulated.y += rotateStep;\n }\n if (keysDown.has(\"ArrowUp\")) {\n rotationAccumulated.x += rotateStep;\n }\n if (keysDown.has(\"ArrowDown\")) {\n rotationAccumulated.x -= rotateStep;\n }\n return;\n }\n\n // Arrows: pan (a drag from the canvas centre). Move the centre along the\n // local tangent basis; Up = north, Right = east.\n const east: Vec3 = { x: 0, y: 0, z: 0 };\n const north: Vec3 = { x: 0, y: 0, z: 0 };\n const up: Vec3 = { x: 0, y: 0, z: 0 };\n let dn = 0;\n let de = 0;\n if (keysDown.has(\"ArrowUp\")) {\n dn += 1;\n }\n if (keysDown.has(\"ArrowDown\")) {\n dn -= 1;\n }\n if (keysDown.has(\"ArrowRight\")) {\n de += 1;\n }\n if (keysDown.has(\"ArrowLeft\")) {\n de -= 1;\n }\n if (dn !== 0 || de !== 0) {\n computeLocalBasis(camera.center, east, north, up);\n panAccumulated.x += (north.x * dn + east.x * de) * panStep;\n panAccumulated.y += (north.y * dn + east.y * de) * panStep;\n panAccumulated.z += (north.z * dn + east.z * de) * panStep;\n }\n }\n\n // ── DOM listeners ──\n\n function onPointerDown(e: PointerEvent): void {\n canvas.setPointerCapture(e.pointerId);\n toCanvas(e);\n lastX = e.clientX;\n lastY = e.clientY;\n if (e.button === 0) {\n mode = \"pan\";\n startDrag(pointerX, pointerY);\n } else {\n mode = \"rotate\";\n }\n }\n\n function onPointerMove(e: PointerEvent): void {\n toCanvas(e);\n const dx = e.clientX - lastX;\n const dy = e.clientY - lastY;\n lastX = e.clientX;\n lastY = e.clientY;\n // While two fingers are down the gesture is a pinch (handled by the touch\n // listeners); suppress the pointer-driven pan/rotate the first finger would\n // otherwise trigger. lastX/Y above stay current so the remaining finger\n // doesn't jump when one lifts.\n if (activeTouches.size >= 2) {\n return;\n }\n if (mode === \"none\") {\n return;\n }\n activeInput = true;\n if (mode === \"pan\") {\n handleDrag(pointerX, pointerY);\n } else if (mode === \"rotate\") {\n rotationAccumulated.y += dx; // yaw\n rotationAccumulated.x += dy; // pitch\n }\n }\n\n function onPointerUp(e: PointerEvent): void {\n canvas.releasePointerCapture(e.pointerId);\n if (mode === \"pan\") {\n stopDrag();\n }\n mode = \"none\";\n }\n\n function onWheel(e: WheelEvent): void {\n e.preventDefault();\n toCanvas(e);\n handleZoom(-Math.sign(e.deltaY), true);\n }\n\n function onContextMenu(e: Event): void {\n e.preventDefault();\n }\n\n function onKeyDown(e: KeyboardEvent): void {\n keysDown.add(e.code);\n }\n\n function onKeyUp(e: KeyboardEvent): void {\n keysDown.delete(e.code);\n }\n\n // ── Touch (two-finger pinch = zoom toward centroid; ≥20 px centroid drift = pan) ──\n\n function firstTwoTouches(): [{ x: number; y: number }, { x: number; y: number }] {\n const it = activeTouches.values();\n const a = it.next().value as { x: number; y: number };\n const b = it.next().value as { x: number; y: number };\n return [a, b];\n }\n\n function onTouchStart(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n const t = e.changedTouches[i]!;\n activeTouches.set(t.identifier, { x: t.clientX, y: t.clientY });\n }\n if (activeTouches.size >= 2) {\n // A second finger landed: this is a pinch, not a single-finger pan.\n // Cancel any in-progress pointer drag and stop the browser hijacking\n // the gesture as a page zoom (iOS ignores touch-action for pinch).\n e.preventDefault();\n if (mode === \"pan\") {\n stopDrag();\n }\n mode = \"none\";\n const [p0, p1] = firstTwoTouches();\n pinchPrevDist = Math.hypot(p1.x - p0.x, p1.y - p0.y);\n pinchStartCentroidX = (p0.x + p1.x) / 2;\n pinchStartCentroidY = (p0.y + p1.y) / 2;\n pinchPanning = false;\n }\n }\n\n function onTouchMove(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n const t = e.changedTouches[i]!;\n if (activeTouches.has(t.identifier)) {\n activeTouches.set(t.identifier, { x: t.clientX, y: t.clientY });\n }\n }\n if (activeTouches.size < 2) {\n return;\n }\n e.preventDefault();\n activeInput = true;\n const [p0, p1] = firstTwoTouches();\n const dist2 = Math.hypot(p1.x - p0.x, p1.y - p0.y);\n const centroidClientX = (p0.x + p1.x) / 2;\n const centroidClientY = (p0.y + p1.y) / 2;\n const rect = canvas.getBoundingClientRect();\n pointerX = centroidClientX - rect.left;\n pointerY = centroidClientY - rect.top;\n\n const centroidDrift = Math.hypot(centroidClientX - pinchStartCentroidX, centroidClientY - pinchStartCentroidY);\n if (!pinchPanning && centroidDrift > PINCH_PAN_THRESHOLD) {\n pinchPanning = true;\n startDrag(pointerX, pointerY);\n }\n\n if (pinchPanning) {\n // Pan dominates: drag the globe under the centroid (zoom is suppressed\n // while dragging, mirroring the mid-drag zoom lockout).\n handleDrag(pointerX, pointerY);\n } else if (pinchPrevDist > 0) {\n // Zoom toward the centroid: finger-spread Δpx feeds the zoom accumulator.\n const dDist = dist2 - pinchPrevDist;\n if (dDist !== 0) {\n zoomAccumulated += dDist * PINCH_ZOOM_SCALE;\n const pick = pickScreen(pointerX, pointerY);\n computedZoomPickPoint = pick.hit && pick.point && zoomToCursor ? pick.point : pickAlongVector(camera._lookAt);\n }\n }\n pinchPrevDist = dist2;\n }\n\n function onTouchEnd(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n activeTouches.delete(e.changedTouches[i]!.identifier);\n }\n if (activeTouches.size < 2) {\n if (pinchPanning) {\n stopDrag();\n pinchPanning = false;\n }\n pinchPrevDist = 0;\n }\n // One finger remains: re-anchor lastX/Y so its pointer drag doesn't jump.\n if (activeTouches.size === 1) {\n const p = activeTouches.values().next().value as { x: number; y: number };\n lastX = p.x;\n lastY = p.y;\n }\n }\n\n // iOS Safari fires non-standard gesture* events and still page-zooms even with\n // touch-action:none; swallow them so the pinch stays with the camera.\n function onGesture(e: Event): void {\n e.preventDefault();\n }\n\n scene._beforeRender.push(onBeforeRenderTick);\n\n const listeners: [EventTarget, string, EventListener, AddEventListenerOptions?][] = [\n [canvas, \"pointerdown\", onPointerDown as EventListener],\n [canvas, \"pointermove\", onPointerMove as EventListener],\n [canvas, \"pointerup\", onPointerUp as EventListener],\n [canvas, \"wheel\", onWheel as EventListener, { passive: false }],\n [canvas, \"contextmenu\", onContextMenu as EventListener],\n [canvas, \"touchstart\", onTouchStart as EventListener, { passive: false }],\n [canvas, \"touchmove\", onTouchMove as EventListener, { passive: false }],\n [canvas, \"touchend\", onTouchEnd as EventListener],\n [canvas, \"gesturestart\", onGesture as EventListener, { passive: false }],\n [canvas, \"gesturechange\", onGesture as EventListener, { passive: false }],\n [canvas, \"gestureend\", onGesture as EventListener, { passive: false }],\n [window, \"keydown\", onKeyDown as EventListener],\n [window, \"keyup\", onKeyUp as EventListener],\n ];\n for (const [t, ev, h, opts] of listeners) {\n t.addEventListener(ev, h, opts);\n }\n\n return () => {\n const idx = scene._beforeRender.indexOf(onBeforeRenderTick);\n if (idx >= 0) {\n scene._beforeRender.splice(idx, 1);\n }\n for (const [t, ev, h] of listeners) {\n t.removeEventListener(ev, h);\n }\n };\n}\n\n// ── shared helpers ──\n\nfunction clampNum(v: number, min: number, max: number): number {\n return v < min ? min : v > max ? max : v;\n}\n\nfunction dist(a: Vec3, b: Vec3): number {\n return Math.hypot(a.x - b.x, a.y - b.y, a.z - b.z);\n}\n\n/** Transform a point by a Mat4 (row-vector × column-major matrix, with w divide). */\nfunction transformCoordinates(x: number, y: number, z: number, m: Mat4Storage, out: Vec3): void {\n const rx = x * m[0]! + y * m[4]! + z * m[8]! + m[12]!;\n const ry = x * m[1]! + y * m[5]! + z * m[9]! + m[13]!;\n const rz = x * m[2]! + y * m[6]! + z * m[10]! + m[14]!;\n const rw = x * m[3]! + y * m[7]! + z * m[11]! + m[15]!;\n const inv = rw !== 0 ? 1 / rw : 1;\n out.x = rx * inv;\n out.y = ry * inv;\n out.z = rz * inv;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"geospatial-camera-controls.js","sources":["../../../src/camera/geospatial-camera-controls.ts"],"sourcesContent":["import type { GeospatialCamera } from \"./geospatial-camera.js\";\nimport { computeLocalBasis, computeYawPitchFromLookAt } from \"./geospatial-camera.js\";\nimport { flyGeospatialCameraToAsync } from \"./geospatial-camera-fly.js\";\nimport { clampZoomDistance, GEO_EPSILON } from \"./geospatial-limits.js\";\nimport { getViewProjectionMatrix } from \"./camera.js\";\nimport { createPickingRay } from \"../picking/ray.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Vec3, Mat4, Mat4Storage } from \"../math/types.js\";\nimport { REFERENCE_FRAME_RATE, integrateInertialVelocity, computePanSpeedMultiplier, computeZoomSpeedMultiplier } from \"./geospatial-movement.js\";\n\n/** Options for {@link attachGeospatialControls}. */\nexport interface GeospatialControlOptions {\n /** When true, zooming moves toward the point under the cursor; otherwise along the look vector. Default true. */\n zoomToCursor?: boolean;\n /** Enable simple sphere collision so the camera cannot dip below the surface. Default false. */\n checkCollisions?: boolean;\n /** Duration (ms) of the fly-to animation triggered by a primary-pointer double tap. Default 1000. */\n doubleTapAnimationDurationMs?: number;\n /**\n * Optional easing applied to the double-tap fly-to animation (normalized progress `g` ∈ [0,1]).\n * A single function instance can be created once and reused across double taps. Default null\n * (uses the fly module's cubic ease-in-out).\n */\n doubleTapEasingFunction?: ((g: number) => number) | null;\n}\n\ninterface PickResult {\n hit: boolean;\n point: Vec3 | null;\n ray: { origin: Vec3; direction: Vec3 } | null;\n}\n\n/**\n * Attach orbit / pan / zoom controls to a {@link GeospatialCamera}, matching\n * Babylon.js `GeospatialCamera` interactions:\n * - Left-drag: pan (the cursor stays anchored to the globe surface).\n * - Middle/right-drag: rotate (yaw + pitch / tilt).\n * - Wheel: zoom (toward the cursor by default).\n * - Touch: single-finger drag = pan; two-finger pinch = zoom toward the centroid,\n * promoting to a pan once the centroid drifts ≥ 20 px.\n * - Keyboard: arrows = pan, Ctrl+arrows = tilt (pitch/yaw), +/- = zoom along the look vector.\n * - Double-click (primary button): fly the centre to the point under the cursor.\n *\n * Movement uses Babylon.js's framerate-independent physics model (velocity +\n * inertial decay). Globe picking is analytic ray-sphere against the planet\n * sphere (origin-centred, radius = `limits.planetRadius`) — no mesh picking\n * subsystem is required. Inertia is integrated once per frame from the scene's\n * render loop (`scene._beforeRender`).\n *\n * Returns a disposer that removes all listeners and the per-frame hook.\n */\nexport function attachGeospatialControls(camera: GeospatialCamera, canvas: HTMLCanvasElement, scene: SceneContext, options?: GeospatialControlOptions): () => void {\n const zoomToCursor = options?.zoomToCursor ?? true;\n const checkCollisions = options?.checkCollisions ?? false;\n const doubleTapAnimationDurationMs = options?.doubleTapAnimationDurationMs ?? 1000;\n const doubleTapEasingFunction = options?.doubleTapEasingFunction ?? null;\n\n // ── Speed / inertia (Babylon GeospatialCameraMovement defaults) ──\n const speed = 1;\n const panSpeed = 1;\n const rotationXSpeed = Math.PI / 500;\n const rotationYSpeed = Math.PI / 500;\n const zoomSpeed = 2;\n const panInertia = 0;\n const rotationInertia = 0;\n const zoomInertia = 0.9;\n\n // ── Accumulated input (reset each frame) ──\n const panAccumulated: Vec3 = { x: 0, y: 0, z: 0 };\n const rotationAccumulated = { x: 0, y: 0 }; // x = pitch pixels, y = yaw pixels\n let zoomAccumulated = 0;\n let activeInput = false;\n\n // ── Velocities (for inertia) ──\n const panVelocity: Vec3 = { x: 0, y: 0, z: 0 };\n const rotationVelocity = { x: 0, y: 0 };\n let zoomVelocity = 0;\n let prevFrameTimeMs = 0;\n\n // ── Per-frame multipliers ──\n let panSpeedMultiplier = 1;\n let zoomSpeedMultiplier = 1;\n\n // ── Per-frame computed deltas ──\n const panDelta: Vec3 = { x: 0, y: 0, z: 0 };\n const rotationDelta = { x: 0, y: 0 };\n let zoomDelta = 0;\n let computedZoomPickPoint: Vec3 | null = null;\n\n // ── Drag (pan) state ──\n let hitPointRadius: number | undefined;\n const dragPlaneNormal: Vec3 = { x: 0, y: 0, z: 0 };\n const dragPlaneOriginEcef: Vec3 = { x: 0, y: 0, z: 0 };\n const dragPlaneHitPointLocal: Vec3 = { x: 0, y: 0, z: 0 };\n const previousDragPlaneHitPointLocal: Vec3 = { x: 0, y: 0, z: 0 };\n\n // ── Pointer state ──\n let pointerX = 0;\n let pointerY = 0;\n let mode: \"none\" | \"pan\" | \"rotate\" = \"none\";\n let lastX = 0;\n let lastY = 0;\n const keysDown = new Set<string>();\n\n // ── Touch (pinch) state ──\n const activeTouches = new Map<number, { x: number; y: number }>();\n let pinchPrevDist = 0;\n let pinchStartCentroidX = 0;\n let pinchStartCentroidY = 0;\n let pinchPanning = false;\n const PINCH_PAN_THRESHOLD = 20; // px of centroid translation before a pinch also pans\n const PINCH_ZOOM_SCALE = 0.05; // pixels of finger-spread → zoom-accumulator units\n\n function rectSize(): { width: number; height: number } {\n const r = canvas.getBoundingClientRect();\n return { width: r.width || canvas.width, height: r.height || canvas.height };\n }\n\n function toCanvas(e: PointerEvent | WheelEvent): void {\n const r = canvas.getBoundingClientRect();\n pointerX = e.clientX - r.left;\n pointerY = e.clientY - r.top;\n }\n\n // ── Picking (analytic ray-sphere against the planet) ──\n\n function screenRay(x: number, y: number): { origin: Vec3; direction: Vec3 } | null {\n const { width, height } = rectSize();\n const vp = getViewProjectionMatrix(camera, width / height);\n const ray = createPickingRay(x, y, vp, width, height);\n if (!ray) {\n return null;\n }\n return { origin: { x: ray.origin[0], y: ray.origin[1], z: ray.origin[2] }, direction: { x: ray.direction[0], y: ray.direction[1], z: ray.direction[2] } };\n }\n\n /** Nearest positive intersection of a ray with the planet sphere (centre origin). */\n function intersectPlanet(origin: Vec3, dir: Vec3): Vec3 | null {\n const r = camera.limits.planetRadius;\n const b = 2 * (origin.x * dir.x + origin.y * dir.y + origin.z * dir.z);\n const c = origin.x * origin.x + origin.y * origin.y + origin.z * origin.z - r * r;\n const disc = b * b - 4 * c;\n if (disc < 0) {\n return null;\n }\n const sq = Math.sqrt(disc);\n let t = (-b - sq) / 2;\n if (t < 0) {\n t = (-b + sq) / 2;\n }\n if (t < 0) {\n return null;\n }\n return { x: origin.x + dir.x * t, y: origin.y + dir.y * t, z: origin.z + dir.z * t };\n }\n\n function pickScreen(x: number, y: number): PickResult {\n const ray = screenRay(x, y);\n if (!ray) {\n return { hit: false, point: null, ray: null };\n }\n const point = intersectPlanet(ray.origin, ray.direction);\n return { hit: !!point, point, ray };\n }\n\n function pickAlongVector(dir: Vec3): Vec3 | null {\n return intersectPlanet(camera.position, dir);\n }\n\n // ── Pan (drag-plane) math ──\n\n function recalcDragPlaneHitPoint(radius: number, ray: { origin: Vec3; direction: Vec3 }, localToEcef: Mat4Storage): void {\n const posLen = Math.max(1e-5, Math.hypot(camera.position.x, camera.position.y, camera.position.z));\n const s = radius / posLen;\n dragPlaneOriginEcef.x = camera.position.x * s;\n dragPlaneOriginEcef.y = camera.position.y * s;\n dragPlaneOriginEcef.z = camera.position.z * s;\n\n const east: Vec3 = { x: 0, y: 0, z: 0 };\n const north: Vec3 = { x: 0, y: 0, z: 0 };\n computeLocalBasis(dragPlaneOriginEcef, east, north, dragPlaneNormal);\n\n // localToEcef = columns [east, north, up] + translation origin.\n localToEcef[0] = east.x;\n localToEcef[1] = east.y;\n localToEcef[2] = east.z;\n localToEcef[3] = 0;\n localToEcef[4] = north.x;\n localToEcef[5] = north.y;\n localToEcef[6] = north.z;\n localToEcef[7] = 0;\n localToEcef[8] = dragPlaneNormal.x;\n localToEcef[9] = dragPlaneNormal.y;\n localToEcef[10] = dragPlaneNormal.z;\n localToEcef[11] = 0;\n localToEcef[12] = dragPlaneOriginEcef.x;\n localToEcef[13] = dragPlaneOriginEcef.y;\n localToEcef[14] = dragPlaneOriginEcef.z;\n localToEcef[15] = 1;\n\n const ecefToLocal = mat4Invert(localToEcef as unknown as Mat4);\n if (!ecefToLocal) {\n return;\n }\n\n // Plane: normal·P + d = 0, d = -normal·origin.\n const d = -(dragPlaneNormal.x * dragPlaneOriginEcef.x + dragPlaneNormal.y * dragPlaneOriginEcef.y + dragPlaneNormal.z * dragPlaneOriginEcef.z);\n const denom = dragPlaneNormal.x * ray.direction.x + dragPlaneNormal.y * ray.direction.y + dragPlaneNormal.z * ray.direction.z;\n if (Math.abs(denom) > 1e-9) {\n const t = -(dragPlaneNormal.x * ray.origin.x + dragPlaneNormal.y * ray.origin.y + dragPlaneNormal.z * ray.origin.z + d) / denom;\n if (t >= 0) {\n const hx = ray.origin.x + ray.direction.x * t;\n const hy = ray.origin.y + ray.direction.y * t;\n const hz = ray.origin.z + ray.direction.z * t;\n transformCoordinates(hx, hy, hz, ecefToLocal as unknown as Mat4Storage, dragPlaneHitPointLocal);\n }\n }\n }\n\n function startDrag(x: number, y: number): void {\n const pick = pickScreen(x, y);\n if (pick.point && pick.ray) {\n hitPointRadius = Math.hypot(pick.point.x, pick.point.y, pick.point.z);\n const tmp = scratchMat;\n recalcDragPlaneHitPoint(hitPointRadius, pick.ray, tmp);\n previousDragPlaneHitPointLocal.x = dragPlaneHitPointLocal.x;\n previousDragPlaneHitPointLocal.y = dragPlaneHitPointLocal.y;\n previousDragPlaneHitPointLocal.z = dragPlaneHitPointLocal.z;\n } else {\n hitPointRadius = undefined;\n }\n }\n\n function handleDrag(x: number, y: number): void {\n if (hitPointRadius === undefined) {\n return;\n }\n const ray = screenRay(x, y);\n if (!ray) {\n return;\n }\n const localToEcef = scratchMat;\n recalcDragPlaneHitPoint(hitPointRadius, ray, localToEcef);\n\n let dx = dragPlaneHitPointLocal.x - previousDragPlaneHitPointLocal.x;\n let dy = dragPlaneHitPointLocal.y - previousDragPlaneHitPointLocal.y;\n let dz = dragPlaneHitPointLocal.z - previousDragPlaneHitPointLocal.z;\n\n // Clamp to avoid huge jumps when the camera is nearly parallel to the plane.\n const maxDelta = hitPointRadius * 0.1;\n const len = Math.hypot(dx, dy, dz);\n if (len > maxDelta) {\n const k = maxDelta / len;\n dx *= k;\n dy *= k;\n dz *= k;\n }\n\n previousDragPlaneHitPointLocal.x = dragPlaneHitPointLocal.x;\n previousDragPlaneHitPointLocal.y = dragPlaneHitPointLocal.y;\n previousDragPlaneHitPointLocal.z = dragPlaneHitPointLocal.z;\n\n // delta (local) → ECEF normal transform.\n const ex = dx * localToEcef[0]! + dy * localToEcef[4]! + dz * localToEcef[8]!;\n const ey = dx * localToEcef[1]! + dy * localToEcef[5]! + dz * localToEcef[9]!;\n const ez = dx * localToEcef[2]! + dy * localToEcef[6]! + dz * localToEcef[10]!;\n\n dragPlaneOriginEcef.x += ex;\n dragPlaneOriginEcef.y += ey;\n dragPlaneOriginEcef.z += ez;\n\n panAccumulated.x -= ex;\n panAccumulated.y -= ey;\n panAccumulated.z -= ez;\n }\n\n function stopDrag(): void {\n hitPointRadius = undefined;\n }\n\n const scratchMat = new Float32Array(16) as unknown as Mat4Storage;\n\n // ── Zoom input ──\n\n function handleZoom(delta: number, toCursor: boolean): void {\n if (delta === 0) {\n return;\n }\n zoomAccumulated += delta;\n const pick = pickScreen(pointerX, pointerY);\n if (toCursor && pick.hit && pick.point && zoomToCursor) {\n computedZoomPickPoint = pick.point;\n } else {\n computedZoomPickPoint = pickAlongVector(camera._lookAt);\n }\n }\n\n // ── Apply per-frame deltas to the camera ──\n\n function applyGeocentricTranslation(): void {\n const cx = camera.center.x + panDelta.x;\n const cy = camera.center.y + panDelta.y;\n const cz = camera.center.z + panDelta.z;\n // Re-project onto the sphere of the same magnitude as the current centre.\n const len = Math.hypot(cx, cy, cz) || 1;\n const target = Math.hypot(camera.center.x, camera.center.y, camera.center.z);\n const k = target / len;\n camera._setOrientation(camera.yaw, camera.pitch, camera.radius, { x: cx * k, y: cy * k, z: cz * k });\n }\n\n function applyGeocentricRotation(): void {\n if (rotationDelta.x === 0 && rotationDelta.y === 0) {\n return;\n }\n const pitch = rotationDelta.x !== 0 ? clampNum(camera.pitch + rotationDelta.x, 0, 0.5 * Math.PI - GEO_EPSILON) : camera.pitch;\n const yaw = rotationDelta.y !== 0 ? camera.yaw + rotationDelta.y : camera.yaw;\n camera._setOrientation(yaw, pitch, camera.radius, camera.center);\n }\n\n function centerAndRadiusFromZoomToPoint(target: Vec3, distance: number, out: Vec3): number {\n const limits = camera.limits;\n const dx = target.x - camera.position.x;\n const dy = target.y - camera.position.y;\n const dz = target.z - camera.position.z;\n const distToTarget = Math.hypot(dx, dy, dz);\n if (distToTarget < limits.radiusMin) {\n out.x = camera.center.x;\n out.y = camera.center.y;\n out.z = camera.center.z;\n return clampNum(camera.radius - distance, limits.radiusMin, limits.radiusMax);\n }\n const s = distance / distToTarget;\n const npx = camera.position.x + dx * s;\n const npy = camera.position.y + dy * s;\n const npz = camera.position.z + dz * s;\n const projected = dx * s * camera._lookAt.x + dy * s * camera._lookAt.y + dz * s * camera._lookAt.z;\n const newRadius = clampNum(camera.radius - projected, limits.radiusMin, limits.radiusMax);\n out.x = npx + camera._lookAt.x * newRadius;\n out.y = npy + camera._lookAt.y * newRadius;\n out.z = npz + camera._lookAt.z * newRadius;\n return newRadius;\n }\n\n const zoomCenterScratch: Vec3 = { x: 0, y: 0, z: 0 };\n\n function applyZoom(): void {\n const limits = camera.limits;\n const distToTarget = computedZoomPickPoint ? dist(camera.position, computedZoomPickPoint) : undefined;\n const clamped = clampZoomDistance(limits, zoomDelta, camera.radius, distToTarget);\n if (Math.abs(clamped) < GEO_EPSILON) {\n return;\n }\n if (computedZoomPickPoint) {\n const newRadius = centerAndRadiusFromZoomToPoint(computedZoomPickPoint, clamped, zoomCenterScratch);\n camera._setOrientation(camera.yaw, camera.pitch, newRadius, zoomCenterScratch);\n } else {\n const newRadius = clampNum(camera.radius - clamped, limits.radiusMin, limits.radiusMax);\n camera._setOrientation(camera.yaw, camera.pitch, newRadius, camera.center);\n }\n }\n\n let wasCenterMovingLastFrame = false;\n\n function recalculateCenter(isCenterMoving: boolean): void {\n const shouldRecalc = wasCenterMovingLastFrame && !isCenterMoving;\n wasCenterMovingLastFrame = isCenterMoving;\n if (!shouldRecalc) {\n return;\n }\n const picked = pickAlongVector(camera._lookAt);\n if (!picked) {\n return;\n }\n const invLen = 1 / (Math.hypot(picked.x, picked.y, picked.z) || 1);\n const dot = camera._lookAt.x * -picked.x * invLen + camera._lookAt.y * -picked.y * invLen + camera._lookAt.z * -picked.z * invLen;\n if (dot <= 0) {\n return;\n }\n const newRadius = dist(camera.position, picked);\n if (newRadius <= GEO_EPSILON) {\n return;\n }\n const yp = { x: 0, y: 0 };\n computeYawPitchFromLookAt(camera._lookAt, picked, camera.yaw, yp);\n camera._setOrientation(yp.x, yp.y, newRadius, picked);\n }\n\n function applyCollision(): void {\n if (!checkCollisions) {\n return;\n }\n const minDist = camera.limits.planetRadius + camera.limits.radiusMin;\n const posLen = Math.hypot(camera.position.x, camera.position.y, camera.position.z);\n if (posLen >= minDist || posLen < 1e-6) {\n return;\n }\n const lift = minDist - posLen;\n const inv = 1 / posLen;\n const ox = camera.position.x * inv * lift;\n const oy = camera.position.y * inv * lift;\n const oz = camera.position.z * inv * lift;\n // Lift the whole rig: offset the centre, position follows from setOrientation.\n camera._setOrientation(camera.yaw, camera.pitch, camera.radius, { x: camera.center.x + ox, y: camera.center.y + oy, z: camera.center.z + oz });\n }\n\n // ── Framerate-independent physics ──\n\n function effectiveDeltaMs(dt: number): number {\n if (dt > 0) {\n return dt;\n }\n if (prevFrameTimeMs > 0) {\n return prevFrameTimeMs;\n }\n return 1000 / REFERENCE_FRAME_RATE;\n }\n\n function nextVelocity(vel: number, pixelDelta: number, inertia: number, dt: number): number {\n return integrateInertialVelocity(vel, pixelDelta, inertia, effectiveDeltaMs(dt), activeInput);\n }\n\n function isDragging(): boolean {\n return hitPointRadius !== undefined;\n }\n\n function computeFrameDeltas(dt: number): void {\n // Pan dampening near the poles and with altitude.\n const center = camera.center;\n if (panAccumulated.x !== 0 || panAccumulated.y !== 0 || panAccumulated.z !== 0) {\n panSpeedMultiplier = computePanSpeedMultiplier(center, camera.position);\n } else {\n panSpeedMultiplier = 1;\n }\n\n // Zoom speed scales with distance to target; suppressed while dragging/rotating.\n if (isDragging() || rotationAccumulated.x !== 0 || rotationAccumulated.y !== 0) {\n zoomSpeedMultiplier = 0;\n zoomVelocity = 0;\n } else {\n const target = computedZoomPickPoint ? dist(camera.position, computedZoomPickPoint) : dist(camera.position, center);\n zoomSpeedMultiplier = computeZoomSpeedMultiplier(target);\n }\n\n const eff = effectiveDeltaMs(dt);\n\n panVelocity.x = nextVelocity(panVelocity.x, panAccumulated.x, panInertia, dt);\n panVelocity.y = nextVelocity(panVelocity.y, panAccumulated.y, panInertia, dt);\n panVelocity.z = nextVelocity(panVelocity.z, panAccumulated.z, panInertia, dt);\n const panScale = speed * panSpeed * panSpeedMultiplier * eff;\n panDelta.x = panVelocity.x * panScale;\n panDelta.y = panVelocity.y * panScale;\n panDelta.z = panVelocity.z * panScale;\n\n rotationVelocity.x = nextVelocity(rotationVelocity.x, rotationAccumulated.x, rotationInertia, dt);\n rotationVelocity.y = nextVelocity(rotationVelocity.y, rotationAccumulated.y, rotationInertia, dt);\n rotationDelta.x = rotationVelocity.x * speed * rotationXSpeed * eff;\n rotationDelta.y = rotationVelocity.y * speed * rotationYSpeed * eff;\n\n zoomVelocity = nextVelocity(zoomVelocity, zoomAccumulated, zoomInertia, dt);\n zoomDelta = zoomVelocity * (speed * zoomSpeed * zoomSpeedMultiplier) * eff;\n\n if (dt > 0) {\n prevFrameTimeMs = dt;\n }\n zoomAccumulated = 0;\n panAccumulated.x = panAccumulated.y = panAccumulated.z = 0;\n rotationAccumulated.x = rotationAccumulated.y = 0;\n activeInput = false;\n }\n\n // ── Per-frame loop ──\n\n function onBeforeRenderTick(deltaMs: number): void {\n // Keyboard injects accumulated input before physics.\n pollKeyboard();\n\n const hasInput =\n panAccumulated.x !== 0 || panAccumulated.y !== 0 || panAccumulated.z !== 0 || rotationAccumulated.x !== 0 || rotationAccumulated.y !== 0 || zoomAccumulated !== 0;\n if (hasInput && camera._cancelFly) {\n camera._cancelFly();\n }\n\n computeFrameDeltas(deltaMs);\n\n let isCenterMoving = false;\n if (panDelta.x !== 0 || panDelta.y !== 0 || panDelta.z !== 0) {\n applyGeocentricTranslation();\n isCenterMoving = true;\n }\n if (rotationDelta.x !== 0 || rotationDelta.y !== 0) {\n applyGeocentricRotation();\n }\n if (Math.abs(zoomDelta) > GEO_EPSILON) {\n applyZoom();\n isCenterMoving = true;\n }\n recalculateCenter(isCenterMoving);\n applyCollision();\n }\n\n // ── Keyboard ──\n\n function pollKeyboard(): void {\n if (keysDown.size === 0) {\n return;\n }\n activeInput = true;\n const rotateStep = 6; // pixels-equivalent per frame\n const zoomStep = 4;\n const panStep = camera.radius * 0.0015;\n const ctrl = keysDown.has(\"ControlLeft\") || keysDown.has(\"ControlRight\");\n\n // +/- : zoom along the look vector (no zoom-to-point pick).\n if (keysDown.has(\"Equal\") || keysDown.has(\"NumpadAdd\")) {\n zoomAccumulated += zoomStep;\n computedZoomPickPoint = null;\n }\n if (keysDown.has(\"Minus\") || keysDown.has(\"NumpadSubtract\")) {\n zoomAccumulated -= zoomStep;\n computedZoomPickPoint = null;\n }\n\n if (ctrl) {\n // Ctrl + arrows: tilt (pitch) and yaw, matching Babylon.js.\n if (keysDown.has(\"ArrowLeft\")) {\n rotationAccumulated.y -= rotateStep;\n }\n if (keysDown.has(\"ArrowRight\")) {\n rotationAccumulated.y += rotateStep;\n }\n if (keysDown.has(\"ArrowUp\")) {\n rotationAccumulated.x += rotateStep;\n }\n if (keysDown.has(\"ArrowDown\")) {\n rotationAccumulated.x -= rotateStep;\n }\n return;\n }\n\n // Arrows: pan (a drag from the canvas centre). Move the centre along the\n // local tangent basis; Up = north, Right = east.\n const east: Vec3 = { x: 0, y: 0, z: 0 };\n const north: Vec3 = { x: 0, y: 0, z: 0 };\n const up: Vec3 = { x: 0, y: 0, z: 0 };\n let dn = 0;\n let de = 0;\n if (keysDown.has(\"ArrowUp\")) {\n dn += 1;\n }\n if (keysDown.has(\"ArrowDown\")) {\n dn -= 1;\n }\n if (keysDown.has(\"ArrowRight\")) {\n de += 1;\n }\n if (keysDown.has(\"ArrowLeft\")) {\n de -= 1;\n }\n if (dn !== 0 || de !== 0) {\n // Normalize the (north, east) direction so holding two pan keys at once (e.g. up + left)\n // pans along a diagonal at the same speed as a single direction, instead of the ~1.41x\n // boost (sqrt(2)) that results from applying each axis independently.\n const invLen = 1 / Math.hypot(dn, de);\n dn *= invLen;\n de *= invLen;\n computeLocalBasis(camera.center, east, north, up);\n panAccumulated.x += (north.x * dn + east.x * de) * panStep;\n panAccumulated.y += (north.y * dn + east.y * de) * panStep;\n panAccumulated.z += (north.z * dn + east.z * de) * panStep;\n }\n }\n\n // ── DOM listeners ──\n\n function onPointerDown(e: PointerEvent): void {\n canvas.setPointerCapture(e.pointerId);\n toCanvas(e);\n lastX = e.clientX;\n lastY = e.clientY;\n if (e.button === 0) {\n mode = \"pan\";\n startDrag(pointerX, pointerY);\n } else {\n mode = \"rotate\";\n }\n }\n\n function onPointerMove(e: PointerEvent): void {\n toCanvas(e);\n const dx = e.clientX - lastX;\n const dy = e.clientY - lastY;\n lastX = e.clientX;\n lastY = e.clientY;\n // While two fingers are down the gesture is a pinch (handled by the touch\n // listeners); suppress the pointer-driven pan/rotate the first finger would\n // otherwise trigger. lastX/Y above stay current so the remaining finger\n // doesn't jump when one lifts.\n if (activeTouches.size >= 2) {\n return;\n }\n if (mode === \"none\") {\n return;\n }\n activeInput = true;\n if (mode === \"pan\") {\n handleDrag(pointerX, pointerY);\n } else if (mode === \"rotate\") {\n rotationAccumulated.y += dx; // yaw\n rotationAccumulated.x += dy; // pitch\n }\n }\n\n function onPointerUp(e: PointerEvent): void {\n canvas.releasePointerCapture(e.pointerId);\n if (mode === \"pan\") {\n stopDrag();\n }\n mode = \"none\";\n }\n\n function onWheel(e: WheelEvent): void {\n e.preventDefault();\n toCanvas(e);\n handleZoom(-Math.sign(e.deltaY), true);\n }\n\n function onContextMenu(e: Event): void {\n e.preventDefault();\n }\n\n function onDoubleClick(e: MouseEvent): void {\n // Only respond to a double tap from the primary pointer (left button), and ignore it if\n // any other button is still pressed (e.g. right button held for rotation while double-tapping\n // left). `e.buttons` is a bitmask of currently-pressed buttons. This mirrors Babylon.js's\n // GeospatialCameraPointersInput primary-pointer guard.\n if (e.button !== 0 || e.buttons !== 0) {\n return;\n }\n // Suppress browser defaults for the gesture (text selection / page zoom) now that it\n // is recognised as a primary-pointer double tap.\n e.preventDefault();\n const r = canvas.getBoundingClientRect();\n const pick = pickScreen(e.clientX - r.left, e.clientY - r.top);\n if (pick.hit && pick.point) {\n void flyGeospatialCameraToAsync(camera, scene, {\n center: { x: pick.point.x, y: pick.point.y, z: pick.point.z },\n durationMs: doubleTapAnimationDurationMs,\n ease: doubleTapEasingFunction ?? undefined,\n });\n }\n }\n\n function onKeyDown(e: KeyboardEvent): void {\n keysDown.add(e.code);\n }\n\n function onKeyUp(e: KeyboardEvent): void {\n keysDown.delete(e.code);\n }\n\n // ── Touch (two-finger pinch = zoom toward centroid; ≥20 px centroid drift = pan) ──\n\n function firstTwoTouches(): [{ x: number; y: number }, { x: number; y: number }] {\n const it = activeTouches.values();\n const a = it.next().value as { x: number; y: number };\n const b = it.next().value as { x: number; y: number };\n return [a, b];\n }\n\n function onTouchStart(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n const t = e.changedTouches[i]!;\n activeTouches.set(t.identifier, { x: t.clientX, y: t.clientY });\n }\n if (activeTouches.size >= 2) {\n // A second finger landed: this is a pinch, not a single-finger pan.\n // Cancel any in-progress pointer drag and stop the browser hijacking\n // the gesture as a page zoom (iOS ignores touch-action for pinch).\n e.preventDefault();\n if (mode === \"pan\") {\n stopDrag();\n }\n mode = \"none\";\n const [p0, p1] = firstTwoTouches();\n pinchPrevDist = Math.hypot(p1.x - p0.x, p1.y - p0.y);\n pinchStartCentroidX = (p0.x + p1.x) / 2;\n pinchStartCentroidY = (p0.y + p1.y) / 2;\n pinchPanning = false;\n }\n }\n\n function onTouchMove(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n const t = e.changedTouches[i]!;\n if (activeTouches.has(t.identifier)) {\n activeTouches.set(t.identifier, { x: t.clientX, y: t.clientY });\n }\n }\n if (activeTouches.size < 2) {\n return;\n }\n e.preventDefault();\n activeInput = true;\n const [p0, p1] = firstTwoTouches();\n const dist2 = Math.hypot(p1.x - p0.x, p1.y - p0.y);\n const centroidClientX = (p0.x + p1.x) / 2;\n const centroidClientY = (p0.y + p1.y) / 2;\n const rect = canvas.getBoundingClientRect();\n pointerX = centroidClientX - rect.left;\n pointerY = centroidClientY - rect.top;\n\n const centroidDrift = Math.hypot(centroidClientX - pinchStartCentroidX, centroidClientY - pinchStartCentroidY);\n if (!pinchPanning && centroidDrift > PINCH_PAN_THRESHOLD) {\n pinchPanning = true;\n startDrag(pointerX, pointerY);\n }\n\n if (pinchPanning) {\n // Pan dominates: drag the globe under the centroid (zoom is suppressed\n // while dragging, mirroring the mid-drag zoom lockout).\n handleDrag(pointerX, pointerY);\n } else if (pinchPrevDist > 0) {\n // Zoom toward the centroid: finger-spread Δpx feeds the zoom accumulator.\n const dDist = dist2 - pinchPrevDist;\n if (dDist !== 0) {\n zoomAccumulated += dDist * PINCH_ZOOM_SCALE;\n const pick = pickScreen(pointerX, pointerY);\n computedZoomPickPoint = pick.hit && pick.point && zoomToCursor ? pick.point : pickAlongVector(camera._lookAt);\n }\n }\n pinchPrevDist = dist2;\n }\n\n function onTouchEnd(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n activeTouches.delete(e.changedTouches[i]!.identifier);\n }\n if (activeTouches.size < 2) {\n if (pinchPanning) {\n stopDrag();\n pinchPanning = false;\n }\n pinchPrevDist = 0;\n }\n // One finger remains: re-anchor lastX/Y so its pointer drag doesn't jump.\n if (activeTouches.size === 1) {\n const p = activeTouches.values().next().value as { x: number; y: number };\n lastX = p.x;\n lastY = p.y;\n }\n }\n\n // iOS Safari fires non-standard gesture* events and still page-zooms even with\n // touch-action:none; swallow them so the pinch stays with the camera.\n function onGesture(e: Event): void {\n e.preventDefault();\n }\n\n scene._beforeRender.push(onBeforeRenderTick);\n\n const listeners: [EventTarget, string, EventListener, AddEventListenerOptions?][] = [\n [canvas, \"pointerdown\", onPointerDown as EventListener],\n [canvas, \"pointermove\", onPointerMove as EventListener],\n [canvas, \"pointerup\", onPointerUp as EventListener],\n [canvas, \"wheel\", onWheel as EventListener, { passive: false }],\n [canvas, \"contextmenu\", onContextMenu as EventListener],\n [canvas, \"dblclick\", onDoubleClick as EventListener],\n [canvas, \"touchstart\", onTouchStart as EventListener, { passive: false }],\n [canvas, \"touchmove\", onTouchMove as EventListener, { passive: false }],\n [canvas, \"touchend\", onTouchEnd as EventListener],\n [canvas, \"gesturestart\", onGesture as EventListener, { passive: false }],\n [canvas, \"gesturechange\", onGesture as EventListener, { passive: false }],\n [canvas, \"gestureend\", onGesture as EventListener, { passive: false }],\n [window, \"keydown\", onKeyDown as EventListener],\n [window, \"keyup\", onKeyUp as EventListener],\n ];\n for (const [t, ev, h, opts] of listeners) {\n t.addEventListener(ev, h, opts);\n }\n\n return () => {\n const idx = scene._beforeRender.indexOf(onBeforeRenderTick);\n if (idx >= 0) {\n scene._beforeRender.splice(idx, 1);\n }\n for (const [t, ev, h] of listeners) {\n t.removeEventListener(ev, h);\n }\n };\n}\n\n// ── shared helpers ──\n\nfunction clampNum(v: number, min: number, max: number): number {\n return v < min ? min : v > max ? max : v;\n}\n\nfunction dist(a: Vec3, b: Vec3): number {\n return Math.hypot(a.x - b.x, a.y - b.y, a.z - b.z);\n}\n\n/** Transform a point by a Mat4 (row-vector × column-major matrix, with w divide). */\nfunction transformCoordinates(x: number, y: number, z: number, m: Mat4Storage, out: Vec3): void {\n const rx = x * m[0]! + y * m[4]! + z * m[8]! + m[12]!;\n const ry = x * m[1]! + y * m[5]! + z * m[9]! + m[13]!;\n const rz = x * m[2]! + y * m[6]! + z * m[10]! + m[14]!;\n const rw = x * m[3]! + y * m[7]! + z * m[11]! + m[15]!;\n const inv = rw !== 0 ? 1 / rw : 1;\n out.x = rx * inv;\n out.y = ry * inv;\n out.z = rz * inv;\n}\n"],"names":[],"mappings":"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"}
@@ -40,6 +40,7 @@ function flyGeospatialCameraToAsync(camera, scene, options) {
40
40
  camera._cancelFly?.();
41
41
  const duration = Math.max(1, options.durationMs ?? 1e3);
42
42
  const hopScale = options.centerHopScale ?? 0;
43
+ const ease = options.ease ?? easeInOut;
43
44
  const yaw0 = camera.yaw;
44
45
  const pitch0 = camera.pitch;
45
46
  const radius0 = camera.radius;
@@ -56,7 +57,7 @@ function flyGeospatialCameraToAsync(camera, scene, options) {
56
57
  const driver = (deltaMs) => {
57
58
  elapsed += deltaMs > 0 ? deltaMs : 1e3 / 60;
58
59
  const g = Math.min(1, elapsed / duration);
59
- const e = easeInOut(g);
60
+ const e = g >= 1 ? 1 : ease(g);
60
61
  const yaw = yaw0 + (targetYaw - yaw0) * e;
61
62
  const pitch = pitch0 + (targetPitch - pitch0) * e;
62
63
  const radius = radius0 + (targetRadius - radius0) * e;
@@ -1 +1 @@
1
- {"version":3,"file":"geospatial-camera-fly.js","sources":["../../../src/camera/geospatial-camera-fly.ts"],"sourcesContent":["import type { GeospatialCamera } from \"./geospatial-camera.js\";\nimport { normalizeRadians } from \"./geospatial-camera.js\";\nimport type { SceneContext } from \"./../scene/scene-core.js\";\nimport type { Vec3 } from \"../math/types.js\";\n\n/** Options for {@link flyGeospatialCameraToAsync}. Omitted target fields keep their current value. */\nexport interface GeospatialFlyOptions {\n /** Target yaw (radians). Shortest angular path is taken. */\n yaw?: number;\n /** Target pitch (radians). */\n pitch?: number;\n /** Target radius. */\n radius?: number;\n /** Target centre (ECEF). Animated along a great-circle (slerp). */\n center?: Vec3;\n /** Flight duration in ms. Default 1000. */\n durationMs?: number;\n /** Parabolic \"hop\" height scale for the centre animation (0 = none). */\n centerHopScale?: number;\n}\n\n/** Cubic ease-in-out (matches Babylon.js `CubicEase` with `EASINGMODE_EASEINOUT`). */\nfunction easeInOut(g: number): number {\n if (g >= 0.5) {\n const f = 2 * (1 - g);\n return (1 - f * f * f) * 0.5 + 0.5;\n }\n const f = 2 * g;\n return f * f * f * 0.5;\n}\n\n/** Spherical interpolation of two ECEF positions (great-circle direction + lerped magnitude). */\nfunction slerpEcef(a: Vec3, b: Vec3, t: number, out: Vec3): void {\n const la = Math.hypot(a.x, a.y, a.z) || 1;\n const lb = Math.hypot(b.x, b.y, b.z) || 1;\n const ax = a.x / la;\n const ay = a.y / la;\n const az = a.z / la;\n const bx = b.x / lb;\n const by = b.y / lb;\n const bz = b.z / lb;\n let dot = ax * bx + ay * by + az * bz;\n dot = dot < -1 ? -1 : dot > 1 ? 1 : dot;\n const theta = Math.acos(dot) * t;\n // rel = normalize(b - a*dot)\n let rx = bx - ax * dot;\n let ry = by - ay * dot;\n let rz = bz - az * dot;\n const rlen = Math.hypot(rx, ry, rz);\n if (rlen > 1e-9) {\n rx /= rlen;\n ry /= rlen;\n rz /= rlen;\n }\n const ct = Math.cos(theta);\n const st = Math.sin(theta);\n const len = la + (lb - la) * t;\n out.x = (ax * ct + rx * st) * len;\n out.y = (ay * ct + ry * st) * len;\n out.z = (az * ct + rz * st) * len;\n}\n\n/**\n * Smoothly animate a {@link GeospatialCamera} to new yaw/pitch/radius/centre over\n * `durationMs`, driven by the scene's render loop. Yaw takes the shortest angular\n * path; the centre follows a great-circle (with an optional parabolic hop).\n *\n * The returned promise resolves when the flight completes; it also resolves early\n * if the flight is interrupted (by user input through `attachGeospatialControls`,\n * or by a subsequent `flyGeospatialCameraToAsync` call). Only one flight runs at a time.\n */\nexport function flyGeospatialCameraToAsync(camera: GeospatialCamera, scene: SceneContext, options: GeospatialFlyOptions): Promise<void> {\n // Interrupt any in-flight animation.\n camera._cancelFly?.();\n\n const duration = Math.max(1, options.durationMs ?? 1000);\n const hopScale = options.centerHopScale ?? 0;\n\n const yaw0 = camera.yaw;\n const pitch0 = camera.pitch;\n const radius0 = camera.radius;\n const center0: Vec3 = { x: camera.center.x, y: camera.center.y, z: camera.center.z };\n\n const targetYaw = options.yaw !== undefined ? yaw0 + normalizeRadians(normalizeRadians(options.yaw) - yaw0) : yaw0;\n const targetPitch = options.pitch !== undefined ? normalizeRadians(options.pitch) : pitch0;\n const targetRadius = options.radius ?? radius0;\n const animateCenter = options.center !== undefined;\n const targetCenter: Vec3 = animateCenter ? { x: options.center!.x, y: options.center!.y, z: options.center!.z } : center0;\n const startToEndDist = Math.hypot(targetCenter.x - center0.x, targetCenter.y - center0.y, targetCenter.z - center0.z);\n\n const centerScratch: Vec3 = { x: 0, y: 0, z: 0 };\n let elapsed = 0;\n\n return new Promise<void>((resolve) => {\n const driver = (deltaMs: number): void => {\n elapsed += deltaMs > 0 ? deltaMs : 1000 / 60;\n const g = Math.min(1, elapsed / duration);\n const e = easeInOut(g);\n\n const yaw = yaw0 + (targetYaw - yaw0) * e;\n const pitch = pitch0 + (targetPitch - pitch0) * e;\n const radius = radius0 + (targetRadius - radius0) * e;\n\n let center: Vec3 = center0;\n if (animateCenter) {\n slerpEcef(center0, targetCenter, e, centerScratch);\n if (hopScale > 0) {\n const hopPeak = hopScale * startToEndDist;\n const hop = hopPeak * Math.max(0, (e * e - e) / -0.25);\n const clen = Math.hypot(centerScratch.x, centerScratch.y, centerScratch.z) || 1;\n const k = 1 + hop / clen;\n centerScratch.x *= k;\n centerScratch.y *= k;\n centerScratch.z *= k;\n }\n center = centerScratch;\n }\n\n camera._setOrientation(yaw, pitch, radius, center);\n\n if (g >= 1) {\n finish();\n }\n };\n\n function finish(): void {\n const idx = scene._beforeRender.indexOf(driver);\n if (idx >= 0) {\n scene._beforeRender.splice(idx, 1);\n }\n if (camera._cancelFly === finish) {\n camera._cancelFly = undefined;\n }\n resolve();\n }\n\n camera._cancelFly = finish;\n scene._beforeRender.push(driver);\n });\n}\n"],"names":["f"],"mappings":"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"}
1
+ {"version":3,"file":"geospatial-camera-fly.js","sources":["../../../src/camera/geospatial-camera-fly.ts"],"sourcesContent":["import type { GeospatialCamera } from \"./geospatial-camera.js\";\nimport { normalizeRadians } from \"./geospatial-camera.js\";\nimport type { SceneContext } from \"./../scene/scene-core.js\";\nimport type { Vec3 } from \"../math/types.js\";\n\n/** Options for {@link flyGeospatialCameraToAsync}. Omitted target fields keep their current value. */\nexport interface GeospatialFlyOptions {\n /** Target yaw (radians). Shortest angular path is taken. */\n yaw?: number;\n /** Target pitch (radians). */\n pitch?: number;\n /** Target radius. */\n radius?: number;\n /** Target centre (ECEF). Animated along a great-circle (slerp). */\n center?: Vec3;\n /** Flight duration in ms. Default 1000. */\n durationMs?: number;\n /** Parabolic \"hop\" height scale for the centre animation (0 = none). */\n centerHopScale?: number;\n /** Easing applied to the normalized progress `g` ∈ [0,1]. Default cubic ease-in-out. */\n ease?: (g: number) => number;\n}\n\n/** Cubic ease-in-out (matches Babylon.js `CubicEase` with `EASINGMODE_EASEINOUT`). */\nfunction easeInOut(g: number): number {\n if (g >= 0.5) {\n const f = 2 * (1 - g);\n return (1 - f * f * f) * 0.5 + 0.5;\n }\n const f = 2 * g;\n return f * f * f * 0.5;\n}\n\n/** Spherical interpolation of two ECEF positions (great-circle direction + lerped magnitude). */\nfunction slerpEcef(a: Vec3, b: Vec3, t: number, out: Vec3): void {\n const la = Math.hypot(a.x, a.y, a.z) || 1;\n const lb = Math.hypot(b.x, b.y, b.z) || 1;\n const ax = a.x / la;\n const ay = a.y / la;\n const az = a.z / la;\n const bx = b.x / lb;\n const by = b.y / lb;\n const bz = b.z / lb;\n let dot = ax * bx + ay * by + az * bz;\n dot = dot < -1 ? -1 : dot > 1 ? 1 : dot;\n const theta = Math.acos(dot) * t;\n // rel = normalize(b - a*dot)\n let rx = bx - ax * dot;\n let ry = by - ay * dot;\n let rz = bz - az * dot;\n const rlen = Math.hypot(rx, ry, rz);\n if (rlen > 1e-9) {\n rx /= rlen;\n ry /= rlen;\n rz /= rlen;\n }\n const ct = Math.cos(theta);\n const st = Math.sin(theta);\n const len = la + (lb - la) * t;\n out.x = (ax * ct + rx * st) * len;\n out.y = (ay * ct + ry * st) * len;\n out.z = (az * ct + rz * st) * len;\n}\n\n/**\n * Smoothly animate a {@link GeospatialCamera} to new yaw/pitch/radius/centre over\n * `durationMs`, driven by the scene's render loop. Yaw takes the shortest angular\n * path; the centre follows a great-circle (with an optional parabolic hop).\n *\n * The returned promise resolves when the flight completes; it also resolves early\n * if the flight is interrupted (by user input through `attachGeospatialControls`,\n * or by a subsequent `flyGeospatialCameraToAsync` call). Only one flight runs at a time.\n */\nexport function flyGeospatialCameraToAsync(camera: GeospatialCamera, scene: SceneContext, options: GeospatialFlyOptions): Promise<void> {\n // Interrupt any in-flight animation.\n camera._cancelFly?.();\n\n const duration = Math.max(1, options.durationMs ?? 1000);\n const hopScale = options.centerHopScale ?? 0;\n const ease = options.ease ?? easeInOut;\n\n const yaw0 = camera.yaw;\n const pitch0 = camera.pitch;\n const radius0 = camera.radius;\n const center0: Vec3 = { x: camera.center.x, y: camera.center.y, z: camera.center.z };\n\n const targetYaw = options.yaw !== undefined ? yaw0 + normalizeRadians(normalizeRadians(options.yaw) - yaw0) : yaw0;\n const targetPitch = options.pitch !== undefined ? normalizeRadians(options.pitch) : pitch0;\n const targetRadius = options.radius ?? radius0;\n const animateCenter = options.center !== undefined;\n const targetCenter: Vec3 = animateCenter ? { x: options.center!.x, y: options.center!.y, z: options.center!.z } : center0;\n const startToEndDist = Math.hypot(targetCenter.x - center0.x, targetCenter.y - center0.y, targetCenter.z - center0.z);\n\n const centerScratch: Vec3 = { x: 0, y: 0, z: 0 };\n let elapsed = 0;\n\n return new Promise<void>((resolve) => {\n const driver = (deltaMs: number): void => {\n elapsed += deltaMs > 0 ? deltaMs : 1000 / 60;\n const g = Math.min(1, elapsed / duration);\n // Force the final frame to land exactly on the target even if the easing curve\n // does not satisfy ease(1) === 1, so the flight never resolves short of its goal.\n const e = g >= 1 ? 1 : ease(g);\n\n const yaw = yaw0 + (targetYaw - yaw0) * e;\n const pitch = pitch0 + (targetPitch - pitch0) * e;\n const radius = radius0 + (targetRadius - radius0) * e;\n\n let center: Vec3 = center0;\n if (animateCenter) {\n slerpEcef(center0, targetCenter, e, centerScratch);\n if (hopScale > 0) {\n const hopPeak = hopScale * startToEndDist;\n const hop = hopPeak * Math.max(0, (e * e - e) / -0.25);\n const clen = Math.hypot(centerScratch.x, centerScratch.y, centerScratch.z) || 1;\n const k = 1 + hop / clen;\n centerScratch.x *= k;\n centerScratch.y *= k;\n centerScratch.z *= k;\n }\n center = centerScratch;\n }\n\n camera._setOrientation(yaw, pitch, radius, center);\n\n if (g >= 1) {\n finish();\n }\n };\n\n function finish(): void {\n const idx = scene._beforeRender.indexOf(driver);\n if (idx >= 0) {\n scene._beforeRender.splice(idx, 1);\n }\n if (camera._cancelFly === finish) {\n camera._cancelFly = undefined;\n }\n resolve();\n }\n\n camera._cancelFly = finish;\n scene._beforeRender.push(driver);\n });\n}\n"],"names":["f"],"mappings":"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"}
@@ -302,7 +302,7 @@ function bindingLayoutEntry(layout) {
302
302
  return { binding: layout.binding, visibility, buffer: { type: "uniform" } };
303
303
  }
304
304
  if (layout.kind === "texture") {
305
- return { binding: layout.binding, visibility, texture: { sampleType: layout.textureSampleType ?? "float" } };
305
+ return { binding: layout.binding, visibility, texture: { sampleType: layout.textureSampleType ?? "float", viewDimension: layout.viewDimension ?? "2d" } };
306
306
  }
307
307
  return { binding: layout.binding, visibility, sampler: { type: layout.samplerType ?? "filtering" } };
308
308
  }