@ericchen1990/pano-view 3.6.4 → 3.6.6

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.
package/dist/index.cjs CHANGED
@@ -2591,7 +2591,136 @@ var PanoEventBusContext = (0, import_react2.createContext)(null);
2591
2591
  var import_fiber = require("@react-three/fiber");
2592
2592
  var import_xr = require("@react-three/xr");
2593
2593
  var import_react3 = require("react");
2594
+ var import_three2 = require("three");
2595
+
2596
+ // src/gyro-orientation.ts
2594
2597
  var import_three = require("three");
2598
+
2599
+ // src/gyro-types.ts
2600
+ var GYRO_POSE_EPSILON = 0.02;
2601
+ var GYRO_DISCONTINUITY_ANGLE_DEG = 15;
2602
+ var GYRO_DISCONTINUITY_SPEED_DEG_PER_S = 1200;
2603
+
2604
+ // src/gyro-orientation.ts
2605
+ var DEVICE_FORWARD_CORRECTION = new import_three.Quaternion().setFromAxisAngle(
2606
+ new import_three.Vector3(1, 0, 0),
2607
+ -Math.PI / 2
2608
+ );
2609
+ var SCREEN_AXIS = new import_three.Vector3(0, 0, 1);
2610
+ var LOOK_LOCAL = new import_three.Vector3(0, 0, -1);
2611
+ var UP_LOCAL = new import_three.Vector3(0, 1, 0);
2612
+ var scratchEuler = new import_three.Euler(0, 0, 0, "YXZ");
2613
+ var scratchScreenCorrection = new import_three.Quaternion();
2614
+ var scratchInvert = new import_three.Quaternion();
2615
+ var scratchWithoutRoll = new import_three.Quaternion();
2616
+ var scratchForward = new import_three.Vector3();
2617
+ var scratchUp = new import_three.Vector3();
2618
+ var scratchExpectedUp = new import_three.Vector3();
2619
+ var ZENITH_PITCH_DEG = 89;
2620
+ function getScreenOrientationAngle() {
2621
+ if (typeof window === "undefined") {
2622
+ return 0;
2623
+ }
2624
+ const angle = window.screen.orientation?.angle;
2625
+ if (Number.isFinite(angle)) {
2626
+ return angle;
2627
+ }
2628
+ const legacyAngle = window.orientation;
2629
+ return Number.isFinite(legacyAngle) ? legacyAngle : 0;
2630
+ }
2631
+ function normalizeGyroYaw(value) {
2632
+ return ((value + 180) % 360 + 360) % 360 - 180;
2633
+ }
2634
+ function shortestGyroYawDelta(from, to) {
2635
+ return normalizeGyroYaw(to - from);
2636
+ }
2637
+ function deviceOrientationToQuaternion(sample, screenOrientation, target) {
2638
+ const alpha = Number.isFinite(sample.compassHeading) ? 360 - sample.compassHeading : sample.alpha;
2639
+ scratchEuler.set(
2640
+ import_three.MathUtils.degToRad(sample.beta),
2641
+ import_three.MathUtils.degToRad(alpha),
2642
+ import_three.MathUtils.degToRad(-sample.gamma),
2643
+ "YXZ"
2644
+ );
2645
+ scratchScreenCorrection.setFromAxisAngle(
2646
+ SCREEN_AXIS,
2647
+ -import_three.MathUtils.degToRad(screenOrientation)
2648
+ );
2649
+ return target.setFromEuler(scratchEuler).multiply(DEVICE_FORWARD_CORRECTION).multiply(scratchScreenCorrection).normalize();
2650
+ }
2651
+ function quaternionToGyroPose(quaternion, previousYaw) {
2652
+ scratchForward.copy(LOOK_LOCAL).applyQuaternion(quaternion);
2653
+ const pitchRad = Math.asin(import_three.MathUtils.clamp(scratchForward.y, -1, 1));
2654
+ const pitch = import_three.MathUtils.radToDeg(pitchRad);
2655
+ const nearZenith = Math.abs(pitch) >= ZENITH_PITCH_DEG;
2656
+ const yaw = nearZenith && previousYaw !== void 0 ? previousYaw : import_three.MathUtils.radToDeg(Math.atan2(scratchForward.x, -scratchForward.z));
2657
+ scratchEuler.set(pitchRad, -import_three.MathUtils.degToRad(yaw), 0, "YXZ");
2658
+ scratchWithoutRoll.setFromEuler(scratchEuler);
2659
+ scratchUp.copy(UP_LOCAL).applyQuaternion(quaternion);
2660
+ scratchExpectedUp.copy(UP_LOCAL).applyQuaternion(scratchWithoutRoll);
2661
+ const look = scratchForward;
2662
+ const crossX = scratchUp.y * scratchExpectedUp.z - scratchUp.z * scratchExpectedUp.y;
2663
+ const crossY = scratchUp.z * scratchExpectedUp.x - scratchUp.x * scratchExpectedUp.z;
2664
+ const crossZ = scratchUp.x * scratchExpectedUp.y - scratchUp.y * scratchExpectedUp.x;
2665
+ const sinTwist = crossX * look.x + crossY * look.y + crossZ * look.z;
2666
+ const cosTwist = import_three.MathUtils.clamp(scratchExpectedUp.dot(scratchUp), -1, 1);
2667
+ const roll = import_three.MathUtils.radToDeg(Math.atan2(sinTwist, cosTwist));
2668
+ return {
2669
+ yaw: normalizeGyroYaw(yaw),
2670
+ pitch,
2671
+ roll
2672
+ };
2673
+ }
2674
+ function createRelativeCalibration(deviceQuaternion, yaw, pitch, target) {
2675
+ scratchInvert.copy(deviceQuaternion).invert();
2676
+ scratchEuler.set(
2677
+ import_three.MathUtils.degToRad(pitch),
2678
+ import_three.MathUtils.degToRad(-yaw),
2679
+ 0,
2680
+ "YXZ"
2681
+ );
2682
+ return target.setFromEuler(scratchEuler).multiply(scratchInvert).normalize();
2683
+ }
2684
+ function applyGyroCalibration(deviceQuaternion, calibration, target, previousYaw) {
2685
+ return quaternionToGyroPose(
2686
+ target.copy(calibration).multiply(deviceQuaternion).normalize(),
2687
+ previousYaw
2688
+ );
2689
+ }
2690
+ function reduceGyroPitchOffset(offset, pitchDelta) {
2691
+ if (offset === 0 || pitchDelta === 0) {
2692
+ return offset;
2693
+ }
2694
+ const absDelta = Math.abs(pitchDelta);
2695
+ if (offset > 0) {
2696
+ return Math.max(0, offset - absDelta);
2697
+ }
2698
+ return Math.min(0, offset + absDelta);
2699
+ }
2700
+ function reclaimGyroOffsets(poseYaw, posePitch, constrainedYaw, constrainedPitch) {
2701
+ return {
2702
+ yaw: shortestGyroYawDelta(poseYaw, constrainedYaw),
2703
+ pitch: constrainedPitch - posePitch
2704
+ };
2705
+ }
2706
+ function gyroPoseAngleDelta(from, to) {
2707
+ return Math.max(
2708
+ Math.abs(shortestGyroYawDelta(from.yaw, to.yaw)),
2709
+ Math.abs(to.pitch - from.pitch),
2710
+ Math.abs(shortestGyroYawDelta(from.roll, to.roll))
2711
+ );
2712
+ }
2713
+ function shouldReanchorGyro(angleDeltaDegrees, deltaSeconds) {
2714
+ if (!(deltaSeconds > 0) || angleDeltaDegrees <= GYRO_DISCONTINUITY_ANGLE_DEG) {
2715
+ return false;
2716
+ }
2717
+ return angleDeltaDegrees / deltaSeconds >= GYRO_DISCONTINUITY_SPEED_DEG_PER_S;
2718
+ }
2719
+ function posesNearlyEqual(a, b, epsilon = GYRO_POSE_EPSILON) {
2720
+ return Math.abs(shortestGyroYawDelta(a.yaw, b.yaw)) < epsilon && Math.abs(a.pitch - b.pitch) < epsilon && Math.abs(a.roll - b.roll) < epsilon;
2721
+ }
2722
+
2723
+ // src/panorama-view-runtime.tsx
2595
2724
  var MAX_PITCH = 90;
2596
2725
  var BOUNCE_OVERSHOOT_PITCH = 12;
2597
2726
  var BOUNCE_OVERSHOOT_FOV_RATIO = 0.15;
@@ -2608,7 +2737,7 @@ function clamp(value, min, max) {
2608
2737
  return Math.max(min, Math.min(max, value));
2609
2738
  }
2610
2739
  function normalizeYaw(yaw) {
2611
- return import_three.MathUtils.euclideanModulo(yaw + 180, 360) - 180;
2740
+ return import_three2.MathUtils.euclideanModulo(yaw + 180, 360) - 180;
2612
2741
  }
2613
2742
  function shortestYawDelta(from, to) {
2614
2743
  return normalizeYaw(to - from);
@@ -2656,6 +2785,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2656
2785
  const interactionLockCountRef = (0, import_react3.useRef)(0);
2657
2786
  const keyboardActiveRef = (0, import_react3.useRef)(false);
2658
2787
  const gyroActiveRef = (0, import_react3.useRef)(false);
2788
+ const gyroPoseDrivingRef = (0, import_react3.useRef)(false);
2659
2789
  const gyroPoseRef = (0, import_react3.useRef)({ yaw: 0, pitch: 0, roll: 0 });
2660
2790
  const gyroOffsetRef = (0, import_react3.useRef)({ yaw: 0, pitch: 0 });
2661
2791
  const gyroTouchModeRef = (0, import_react3.useRef)("full");
@@ -2664,8 +2794,8 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2664
2794
  const optionsRef = (0, import_react3.useRef)(options);
2665
2795
  const eventBusRef = (0, import_react3.useRef)(eventBus);
2666
2796
  const lastEmittedViewRef = (0, import_react3.useRef)(null);
2667
- const eulerRef = (0, import_react3.useRef)(new import_three.Euler(0, 0, 0, "YXZ"));
2668
- const xrEulerRef = (0, import_react3.useRef)(new import_three.Euler(0, 0, 0, "YXZ"));
2797
+ const eulerRef = (0, import_react3.useRef)(new import_three2.Euler(0, 0, 0, "YXZ"));
2798
+ const xrEulerRef = (0, import_react3.useRef)(new import_three2.Euler(0, 0, 0, "YXZ"));
2669
2799
  const baseLimitsRef = (0, import_react3.useRef)(viewLimits);
2670
2800
  const sceneLimitsRef = (0, import_react3.useRef)(void 0);
2671
2801
  const legacyFovRef = (0, import_react3.useRef)({ minFov, maxFov });
@@ -2994,6 +3124,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2994
3124
  gyroOffsetRef.current = { yaw: 0, pitch: 0 };
2995
3125
  stopVelocity();
2996
3126
  if (!active) {
3127
+ gyroPoseDrivingRef.current = false;
2997
3128
  cameraRollRef.current = 0;
2998
3129
  dirtyRef.current = true;
2999
3130
  }
@@ -3003,18 +3134,35 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
3003
3134
  return;
3004
3135
  }
3005
3136
  const previous = gyroPoseRef.current;
3006
- const viewMovement = Math.abs(shortestYawDelta(previous.yaw, pose.yaw)) + Math.abs(previous.pitch - pose.pitch);
3137
+ const pitchDelta = pose.pitch - previous.pitch;
3138
+ const viewMovement = Math.abs(shortestYawDelta(previous.yaw, pose.yaw)) + Math.abs(pitchDelta);
3007
3139
  const movement = viewMovement + Math.abs(previous.roll - pose.roll);
3008
- if (movement < 1e-4) {
3140
+ if (movement < GYRO_POSE_EPSILON) {
3009
3141
  return;
3010
3142
  }
3143
+ if (gyroTouchModeRef.current === "full") {
3144
+ gyroOffsetRef.current.pitch = reduceGyroPitchOffset(
3145
+ gyroOffsetRef.current.pitch,
3146
+ pitchDelta
3147
+ );
3148
+ }
3011
3149
  gyroPoseRef.current = { ...pose };
3012
- targetViewRef.current = hardConstrainView({
3150
+ gyroPoseDrivingRef.current = true;
3151
+ const constrained = hardConstrainView({
3013
3152
  yaw: pose.yaw + gyroOffsetRef.current.yaw,
3014
3153
  pitch: pose.pitch + gyroOffsetRef.current.pitch
3015
3154
  });
3155
+ targetViewRef.current = constrained;
3156
+ const reclaimed = reclaimGyroOffsets(
3157
+ pose.yaw,
3158
+ pose.pitch,
3159
+ constrained.yaw,
3160
+ constrained.pitch
3161
+ );
3162
+ gyroOffsetRef.current.yaw = reclaimed.yaw;
3163
+ gyroOffsetRef.current.pitch = reclaimed.pitch;
3016
3164
  cameraRollRef.current = pose.roll;
3017
- if (viewMovement >= 1e-4) {
3165
+ if (viewMovement >= GYRO_POSE_EPSILON) {
3018
3166
  markDirty();
3019
3167
  } else {
3020
3168
  dirtyRef.current = true;
@@ -3052,7 +3200,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
3052
3200
  setView(initialView);
3053
3201
  }, [initialView.fov, initialView.pitch, initialView.yaw]);
3054
3202
  (0, import_fiber.useFrame)((_, deltaSeconds) => {
3055
- if (!(camera instanceof import_three.PerspectiveCamera)) {
3203
+ if (!(camera instanceof import_three2.PerspectiveCamera)) {
3056
3204
  return;
3057
3205
  }
3058
3206
  if (xrSessionRef.current && gl.xr.isPresenting) {
@@ -3060,9 +3208,9 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
3060
3208
  const xrCamera = gl.xr.getCamera();
3061
3209
  xrEulerRef.current.setFromQuaternion(xrCamera.quaternion, "YXZ");
3062
3210
  const nextView2 = {
3063
- yaw: normalizeYaw(-import_three.MathUtils.radToDeg(xrEulerRef.current.y)),
3211
+ yaw: normalizeYaw(-import_three2.MathUtils.radToDeg(xrEulerRef.current.y)),
3064
3212
  pitch: clamp(
3065
- import_three.MathUtils.radToDeg(xrEulerRef.current.x),
3213
+ import_three2.MathUtils.radToDeg(xrEulerRef.current.x),
3066
3214
  -MAX_PITCH,
3067
3215
  MAX_PITCH
3068
3216
  ),
@@ -3092,14 +3240,16 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
3092
3240
  const completed = progress === 1;
3093
3241
  viewRef.current = completed ? { ...navigation.target } : nextView2;
3094
3242
  eulerRef.current.set(
3095
- import_three.MathUtils.degToRad(viewRef.current.pitch),
3096
- import_three.MathUtils.degToRad(-viewRef.current.yaw),
3097
- import_three.MathUtils.degToRad(cameraRollRef.current),
3243
+ import_three2.MathUtils.degToRad(viewRef.current.pitch),
3244
+ import_three2.MathUtils.degToRad(-viewRef.current.yaw),
3245
+ import_three2.MathUtils.degToRad(cameraRollRef.current),
3098
3246
  "YXZ"
3099
3247
  );
3100
3248
  camera.quaternion.setFromEuler(eulerRef.current);
3101
- camera.fov = viewRef.current.fov;
3102
- camera.updateProjectionMatrix();
3249
+ if (camera.fov !== viewRef.current.fov) {
3250
+ camera.fov = viewRef.current.fov;
3251
+ camera.updateProjectionMatrix();
3252
+ }
3103
3253
  camera.updateMatrixWorld();
3104
3254
  const emittedView = { ...viewRef.current };
3105
3255
  const lastEmitted2 = lastEmittedViewRef.current;
@@ -3168,7 +3318,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
3168
3318
  optionsRef.current.zoomDamping,
3169
3319
  DEFAULT_ZOOM_DAMPING
3170
3320
  );
3171
- const rotationFactor = dampingFactor(rotateDamping, deltaSeconds);
3321
+ const rotationFactor = gyroPoseDrivingRef.current ? 1 : dampingFactor(rotateDamping, deltaSeconds);
3172
3322
  const zoomFactor = dampingFactor(zoomDamping, deltaSeconds);
3173
3323
  const yawDelta = limitedYawDelta(viewRef.current.yaw, targetView.yaw, limitsRef.current.yaw);
3174
3324
  const smoothedView = {
@@ -3179,14 +3329,16 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
3179
3329
  const hasSettled = Math.abs(shortestYawDelta(smoothedView.yaw, targetView.yaw)) < VIEW_SETTLE_EPSILON && Math.abs(smoothedView.pitch - targetView.pitch) < VIEW_SETTLE_EPSILON && Math.abs(smoothedView.fov - targetView.fov) < VIEW_SETTLE_EPSILON;
3180
3330
  viewRef.current = hasSettled ? { ...targetView } : smoothedView;
3181
3331
  eulerRef.current.set(
3182
- import_three.MathUtils.degToRad(viewRef.current.pitch),
3183
- import_three.MathUtils.degToRad(-viewRef.current.yaw),
3184
- import_three.MathUtils.degToRad(cameraRollRef.current),
3332
+ import_three2.MathUtils.degToRad(viewRef.current.pitch),
3333
+ import_three2.MathUtils.degToRad(-viewRef.current.yaw),
3334
+ import_three2.MathUtils.degToRad(cameraRollRef.current),
3185
3335
  "YXZ"
3186
3336
  );
3187
3337
  camera.quaternion.setFromEuler(eulerRef.current);
3188
- camera.fov = viewRef.current.fov;
3189
- camera.updateProjectionMatrix();
3338
+ if (camera.fov !== viewRef.current.fov) {
3339
+ camera.fov = viewRef.current.fov;
3340
+ camera.updateProjectionMatrix();
3341
+ }
3190
3342
  camera.updateMatrixWorld();
3191
3343
  const nextView = { ...viewRef.current };
3192
3344
  const lastEmitted = lastEmittedViewRef.current;
@@ -3738,7 +3890,7 @@ var import_fiber4 = require("@react-three/fiber");
3738
3890
  var import_react9 = require("react");
3739
3891
 
3740
3892
  // src/pointer-drag.ts
3741
- var import_three2 = require("three");
3893
+ var import_three3 = require("three");
3742
3894
  var DEFAULT_POINTER_DRAG_SPEED = 0.35;
3743
3895
  var POINTER_FOLLOW_TIME_SECONDS = 0.01;
3744
3896
  var MIN_VELOCITY_SAMPLE_SECONDS = 1 / 120;
@@ -3767,18 +3919,18 @@ var PointerDragAnchor = class {
3767
3919
  this.origin = origin;
3768
3920
  this.rect = rect;
3769
3921
  this.projection = projection;
3770
- this.local = new import_three2.Vector3();
3771
- this.rotation = new import_three2.Euler(0, 0, 0, "YXZ");
3922
+ this.local = new import_three3.Vector3();
3923
+ this.rotation = new import_three3.Euler(0, 0, 0, "YXZ");
3772
3924
  const startRay = this.ray(start).clone();
3773
3925
  this.baseAzimuth = Math.atan2(startRay.x, -startRay.z);
3774
3926
  this.baseElevation = Math.atan2(startRay.y, -startRay.z);
3775
3927
  this.anchor = startRay.clone().applyEuler(this.rotation.set(
3776
- import_three2.MathUtils.degToRad(origin.pitch),
3777
- import_three2.MathUtils.degToRad(-origin.yaw),
3928
+ import_three3.MathUtils.degToRad(origin.pitch),
3929
+ import_three3.MathUtils.degToRad(-origin.yaw),
3778
3930
  0,
3779
3931
  "YXZ"
3780
3932
  ));
3781
- const originPitch = import_three2.MathUtils.degToRad(origin.pitch);
3933
+ const originPitch = import_three3.MathUtils.degToRad(origin.pitch);
3782
3934
  const roots = this.pitchRoots(startRay, originPitch);
3783
3935
  this.useSupplementary = Math.abs(roots.supplementary - originPitch) + 1e-6 < Math.abs(roots.principal - originPitch);
3784
3936
  }
@@ -3791,7 +3943,7 @@ var PointerDragAnchor = class {
3791
3943
  }
3792
3944
  /** Pitch roots of the level-camera constraint. The supplementary root is unwrapped toward the press. */
3793
3945
  pitchRoots(ray, originPitch) {
3794
- const latitude = Math.asin(import_three2.MathUtils.clamp(
3946
+ const latitude = Math.asin(import_three3.MathUtils.clamp(
3795
3947
  this.anchor.y / Math.max(Math.hypot(ray.y, ray.z), 1e-12),
3796
3948
  -1,
3797
3949
  1
@@ -3811,28 +3963,28 @@ var PointerDragAnchor = class {
3811
3963
  x: this.start.x + (point.x - this.start.x) * multiplier,
3812
3964
  y: this.start.y + (point.y - this.start.y) * multiplier
3813
3965
  });
3814
- const originPitch = import_three2.MathUtils.degToRad(this.origin.pitch);
3966
+ const originPitch = import_three3.MathUtils.degToRad(this.origin.pitch);
3815
3967
  const roots = this.pitchRoots(ray, originPitch);
3816
- const exactPitch = import_three2.MathUtils.clamp(
3968
+ const exactPitch = import_three3.MathUtils.clamp(
3817
3969
  this.useSupplementary ? roots.supplementary : roots.principal,
3818
3970
  -Math.PI / 2,
3819
3971
  Math.PI / 2
3820
3972
  );
3821
3973
  const stablePitch = originPitch - (Math.atan2(ray.y, -ray.z) - this.baseElevation);
3822
3974
  const fromPole = Math.asin(Math.min(1, Math.hypot(this.anchor.x, this.anchor.z)));
3823
- const pointerLock = import_three2.MathUtils.smoothstep(fromPole, import_three2.MathUtils.degToRad(8), import_three2.MathUtils.degToRad(18));
3975
+ const pointerLock = import_three3.MathUtils.smoothstep(fromPole, import_three3.MathUtils.degToRad(8), import_three3.MathUtils.degToRad(18));
3824
3976
  const pitchTurn = Math.atan2(Math.sin(exactPitch - stablePitch), Math.cos(exactPitch - stablePitch));
3825
- const pitch = import_three2.MathUtils.clamp(
3977
+ const pitch = import_three3.MathUtils.clamp(
3826
3978
  pointerLock >= 1 ? exactPitch : stablePitch + pointerLock * pitchTurn,
3827
3979
  -Math.PI / 2,
3828
3980
  Math.PI / 2
3829
3981
  );
3830
3982
  const pitchedZ = Math.sin(exactPitch) * ray.y + Math.cos(exactPitch) * ray.z;
3831
3983
  const exactYaw = Math.atan2(this.anchor.x, -this.anchor.z) - Math.atan2(ray.x, -pitchedZ);
3832
- const stableYaw = import_three2.MathUtils.degToRad(this.origin.yaw) + Math.atan2(ray.x, -ray.z) - this.baseAzimuth;
3984
+ const stableYaw = import_three3.MathUtils.degToRad(this.origin.yaw) + Math.atan2(ray.x, -ray.z) - this.baseAzimuth;
3833
3985
  const yawTurn = Math.atan2(Math.sin(exactYaw - stableYaw), Math.cos(exactYaw - stableYaw));
3834
- const yaw = import_three2.MathUtils.radToDeg(stableYaw + pointerLock * yawTurn);
3835
- return { yaw: normalizeViewYaw(yaw - this.origin.yaw), pitch: import_three2.MathUtils.radToDeg(pitch) - this.origin.pitch };
3986
+ const yaw = import_three3.MathUtils.radToDeg(stableYaw + pointerLock * yawTurn);
3987
+ return { yaw: normalizeViewYaw(yaw - this.origin.yaw), pitch: import_three3.MathUtils.radToDeg(pitch) - this.origin.pitch };
3836
3988
  }
3837
3989
  };
3838
3990
  function createPointerDrag(camera, element, runtime, source) {
@@ -3855,7 +4007,7 @@ function createPointerDrag(camera, element, runtime, source) {
3855
4007
  pending = void 0;
3856
4008
  revision = handle?.getPointerDragState().revision ?? -1;
3857
4009
  anchor = void 0;
3858
- if (!(camera instanceof import_three2.PerspectiveCamera) || !handle?.getPointerDragState().anchored) return;
4010
+ if (!(camera instanceof import_three3.PerspectiveCamera) || !handle?.getPointerDragState().anchored) return;
3859
4011
  const rect = element.getBoundingClientRect();
3860
4012
  projectionKey = key(rect);
3861
4013
  anchor = new PointerDragAnchor(point, handle.getView(), rect, camera.clone());
@@ -5584,10 +5736,10 @@ function usePanoOverlayHost(isFullscreen) {
5584
5736
  // src/panorama-event-surface.tsx
5585
5737
  var import_fiber7 = require("@react-three/fiber");
5586
5738
  var import_react16 = require("react");
5587
- var import_three4 = require("three");
5739
+ var import_three5 = require("three");
5588
5740
 
5589
5741
  // src/hotspot/coordinates.ts
5590
- var import_three3 = require("three");
5742
+ var import_three4 = require("three");
5591
5743
 
5592
5744
  // src/hotspot/types.ts
5593
5745
  var MAX_HOTSPOT_PITCH = 90;
@@ -5610,13 +5762,13 @@ function normalizePanoYaw(yaw) {
5610
5762
  if (!Number.isFinite(yaw)) {
5611
5763
  return 0;
5612
5764
  }
5613
- return import_three3.MathUtils.euclideanModulo(yaw + 180, 360) - 180;
5765
+ return import_three4.MathUtils.euclideanModulo(yaw + 180, 360) - 180;
5614
5766
  }
5615
5767
  function clampPanoPitch(pitch) {
5616
5768
  if (!Number.isFinite(pitch)) {
5617
5769
  return 0;
5618
5770
  }
5619
- const clamped = import_three3.MathUtils.clamp(
5771
+ const clamped = import_three4.MathUtils.clamp(
5620
5772
  pitch,
5621
5773
  -MAX_HOTSPOT_PITCH,
5622
5774
  MAX_HOTSPOT_PITCH
@@ -5633,10 +5785,10 @@ function normalizePanoPosition(position) {
5633
5785
  function panoPositionToVector3(position, radius = 1) {
5634
5786
  const normalized = normalizePanoPosition(position);
5635
5787
  const safeRadius = Number.isFinite(radius) ? Math.max(0, radius) : 1;
5636
- const yaw = import_three3.MathUtils.degToRad(normalized.yaw);
5637
- const pitch = import_three3.MathUtils.degToRad(normalized.pitch);
5788
+ const yaw = import_three4.MathUtils.degToRad(normalized.yaw);
5789
+ const pitch = import_three4.MathUtils.degToRad(normalized.pitch);
5638
5790
  const cosPitch = Math.cos(pitch);
5639
- return new import_three3.Vector3(
5791
+ return new import_three4.Vector3(
5640
5792
  cosPitch * Math.sin(yaw) * safeRadius,
5641
5793
  Math.sin(pitch) * safeRadius,
5642
5794
  -cosPitch * Math.cos(yaw) * safeRadius
@@ -5648,9 +5800,9 @@ function vector3ToPanoPosition(vector) {
5648
5800
  return { yaw: 0, pitch: 0 };
5649
5801
  }
5650
5802
  return normalizePanoPosition({
5651
- yaw: import_three3.MathUtils.radToDeg(Math.atan2(vector.x, -vector.z)),
5652
- pitch: import_three3.MathUtils.radToDeg(
5653
- Math.asin(import_three3.MathUtils.clamp(vector.y / length, -1, 1))
5803
+ yaw: import_three4.MathUtils.radToDeg(Math.atan2(vector.x, -vector.z)),
5804
+ pitch: import_three4.MathUtils.radToDeg(
5805
+ Math.asin(import_three4.MathUtils.clamp(vector.y / length, -1, 1))
5654
5806
  )
5655
5807
  });
5656
5808
  }
@@ -5689,9 +5841,9 @@ function PanoramaEventSurface() {
5689
5841
  return;
5690
5842
  }
5691
5843
  const element = gl.domElement;
5692
- const ndc = new import_three4.Vector2();
5693
- const raycaster = new import_three4.Raycaster();
5694
- const direction = new import_three4.Vector3();
5844
+ const ndc = new import_three5.Vector2();
5845
+ const raycaster = new import_three5.Raycaster();
5846
+ const direction = new import_three5.Vector3();
5695
5847
  const handleContextMenu = (nativeEvent) => {
5696
5848
  const rect = element.getBoundingClientRect();
5697
5849
  if (rect.width <= 0 || rect.height <= 0) {
@@ -5743,7 +5895,7 @@ function PanoramaEventSurface() {
5743
5895
  depthTest: false,
5744
5896
  depthWrite: false,
5745
5897
  opacity: 0,
5746
- side: import_three4.BackSide,
5898
+ side: import_three5.BackSide,
5747
5899
  transparent: true
5748
5900
  }
5749
5901
  )
@@ -7572,12 +7724,12 @@ function WebVRChromeBridge({ host }) {
7572
7724
  }
7573
7725
 
7574
7726
  // src/webvr/stereo-view.ts
7575
- var import_three5 = require("three");
7576
- var PROJECT = new import_three5.Vector3();
7727
+ var import_three6 = require("three");
7728
+ var PROJECT = new import_three6.Vector3();
7577
7729
  function createWebVRStereoView() {
7578
7730
  return {
7579
7731
  active: false,
7580
- stereo: new import_three5.StereoCamera()
7732
+ stereo: new import_three6.StereoCamera()
7581
7733
  };
7582
7734
  }
7583
7735
  function isFallbackStereoMode(mode) {
@@ -7601,11 +7753,11 @@ function projectStereoHtmlPosition(el, camera, size, eye) {
7601
7753
  var import_fiber9 = require("@react-three/fiber");
7602
7754
  var import_xr2 = require("@react-three/xr");
7603
7755
  var import_react26 = require("react");
7604
- var import_three6 = require("three");
7756
+ var import_three7 = require("three");
7605
7757
  var import_jsx_runtime11 = require("react/jsx-runtime");
7606
7758
  function PanoramaXROrigin() {
7607
7759
  const originRef = (0, import_react26.useRef)(null);
7608
- const localHeadPositionRef = (0, import_react26.useRef)(new import_three6.Vector3());
7760
+ const localHeadPositionRef = (0, import_react26.useRef)(new import_three7.Vector3());
7609
7761
  const session2 = (0, import_xr2.useXR)((state) => state.session);
7610
7762
  const gl = (0, import_fiber9.useThree)((state) => state.gl);
7611
7763
  (0, import_fiber9.useFrame)(() => {
@@ -8355,7 +8507,7 @@ var import_react51 = require("react");
8355
8507
  // src/scenes.tsx
8356
8508
  var import_fiber18 = require("@react-three/fiber");
8357
8509
  var import_react38 = require("react");
8358
- var import_three20 = require("three");
8510
+ var import_three21 = require("three");
8359
8511
 
8360
8512
  // src/scene-detail.tsx
8361
8513
  var import_react28 = require("react");
@@ -8427,12 +8579,12 @@ function isSnapshotTransition(preset) {
8427
8579
  // src/scene-transitions/snapshot-hold.tsx
8428
8580
  var import_fiber11 = require("@react-three/fiber");
8429
8581
  var import_react29 = require("react");
8430
- var import_three9 = require("three");
8582
+ var import_three10 = require("three");
8431
8583
 
8432
8584
  // src/scene-transitions/overlay-utils.ts
8433
- var import_three7 = require("three");
8585
+ var import_three8 = require("three");
8434
8586
  var OVERLAY_RENDER_ORDER = 1e4;
8435
- var FULLSCREEN_PLANE = new import_three7.PlaneGeometry(1, 1);
8587
+ var FULLSCREEN_PLANE = new import_three8.PlaneGeometry(1, 1);
8436
8588
  function isPerspectiveCamera(camera) {
8437
8589
  return camera.isPerspectiveCamera === true;
8438
8590
  }
@@ -8451,7 +8603,7 @@ function overlayProgress(elapsedTime, duration, startTime) {
8451
8603
  }
8452
8604
 
8453
8605
  // src/scene-transitions/snapshot-shaders.ts
8454
- var import_three8 = require("three");
8606
+ var import_three9 = require("three");
8455
8607
 
8456
8608
  // src/scene-transitions/glsl.ts
8457
8609
  var GLSL_COMMON = `
@@ -8743,15 +8895,15 @@ var SNAPSHOT_FRAGMENT_SHADERS = {
8743
8895
  `)
8744
8896
  };
8745
8897
  function createSnapshotMaterial(preset, texture) {
8746
- return new import_three8.ShaderMaterial({
8898
+ return new import_three9.ShaderMaterial({
8747
8899
  transparent: true,
8748
8900
  depthTest: false,
8749
8901
  depthWrite: false,
8750
- side: import_three8.DoubleSide,
8902
+ side: import_three9.DoubleSide,
8751
8903
  uniforms: {
8752
8904
  map: { value: texture },
8753
8905
  progress: { value: 0 },
8754
- resolution: { value: new import_three8.Vector2(1, 1) }
8906
+ resolution: { value: new import_three9.Vector2(1, 1) }
8755
8907
  },
8756
8908
  vertexShader: SNAPSHOT_VERTEX_SHADER,
8757
8909
  fragmentShader: SNAPSHOT_FRAGMENT_SHADERS[preset]
@@ -8763,7 +8915,7 @@ var import_jsx_runtime13 = require("react/jsx-runtime");
8763
8915
  function SnapshotHold({ snapshot }) {
8764
8916
  const { camera, gl } = (0, import_fiber11.useThree)();
8765
8917
  const meshRef = (0, import_react29.useRef)(null);
8766
- const directionRef = (0, import_react29.useRef)(new import_three9.Vector3());
8918
+ const directionRef = (0, import_react29.useRef)(new import_three10.Vector3());
8767
8919
  const material = (0, import_react29.useMemo)(
8768
8920
  () => createSnapshotMaterial("crossfade", snapshot.texture),
8769
8921
  [snapshot.texture]
@@ -8847,7 +8999,7 @@ function phaseAfterSnapshot(preset, hold) {
8847
8999
  // src/scene-transitions/particle-overlay.tsx
8848
9000
  var import_fiber12 = require("@react-three/fiber");
8849
9001
  var import_react30 = require("react");
8850
- var import_three10 = require("three");
9002
+ var import_three11 = require("three");
8851
9003
  var import_jsx_runtime14 = require("react/jsx-runtime");
8852
9004
  var PARTICLE_GRID = 48;
8853
9005
  var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
@@ -8901,8 +9053,8 @@ var PARTICLE_FRAGMENT_SHADER = `
8901
9053
  }
8902
9054
  `;
8903
9055
  function createParticleGeometry() {
8904
- const quad = new import_three10.PlaneGeometry(1, 1);
8905
- const geometry = new import_three10.InstancedBufferGeometry();
9056
+ const quad = new import_three11.PlaneGeometry(1, 1);
9057
+ const geometry = new import_three11.InstancedBufferGeometry();
8906
9058
  if (quad.index) {
8907
9059
  geometry.setIndex(quad.index.clone());
8908
9060
  }
@@ -8912,7 +9064,7 @@ function createParticleGeometry() {
8912
9064
  for (let i = 0; i < PARTICLE_COUNT; i += 1) {
8913
9065
  indexes[i] = i;
8914
9066
  }
8915
- geometry.setAttribute("instanceIndex", new import_three10.InstancedBufferAttribute(indexes, 1));
9067
+ geometry.setAttribute("instanceIndex", new import_three11.InstancedBufferAttribute(indexes, 1));
8916
9068
  geometry.instanceCount = PARTICLE_COUNT;
8917
9069
  quad.dispose();
8918
9070
  return geometry;
@@ -8928,18 +9080,18 @@ function ParticleOverlay({
8928
9080
  const meshRef = (0, import_react30.useRef)(null);
8929
9081
  const startRef = (0, import_react30.useRef)(null);
8930
9082
  const finishedRef = (0, import_react30.useRef)(false);
8931
- const directionRef = (0, import_react30.useRef)(new import_three10.Vector3());
9083
+ const directionRef = (0, import_react30.useRef)(new import_three11.Vector3());
8932
9084
  const geometry = (0, import_react30.useMemo)(() => createParticleGeometry(), []);
8933
9085
  const material = (0, import_react30.useMemo)(
8934
- () => new import_three10.ShaderMaterial({
9086
+ () => new import_three11.ShaderMaterial({
8935
9087
  transparent: true,
8936
9088
  depthTest: false,
8937
9089
  depthWrite: false,
8938
- side: import_three10.DoubleSide,
9090
+ side: import_three11.DoubleSide,
8939
9091
  uniforms: {
8940
9092
  map: { value: snapshot.texture },
8941
9093
  progress: { value: 0 },
8942
- grid: { value: new import_three10.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
9094
+ grid: { value: new import_three11.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
8943
9095
  },
8944
9096
  vertexShader: PARTICLE_VERTEX_SHADER,
8945
9097
  fragmentShader: PARTICLE_FRAGMENT_SHADER
@@ -8985,7 +9137,7 @@ function ParticleOverlay({
8985
9137
  // src/scene-transitions/snapshot-overlay.tsx
8986
9138
  var import_fiber13 = require("@react-three/fiber");
8987
9139
  var import_react31 = require("react");
8988
- var import_three11 = require("three");
9140
+ var import_three12 = require("three");
8989
9141
  var import_jsx_runtime15 = require("react/jsx-runtime");
8990
9142
  function SnapshotOverlay({
8991
9143
  snapshot,
@@ -8998,7 +9150,7 @@ function SnapshotOverlay({
8998
9150
  const meshRef = (0, import_react31.useRef)(null);
8999
9151
  const startRef = (0, import_react31.useRef)(null);
9000
9152
  const finishedRef = (0, import_react31.useRef)(false);
9001
- const directionRef = (0, import_react31.useRef)(new import_three11.Vector3());
9153
+ const directionRef = (0, import_react31.useRef)(new import_three12.Vector3());
9002
9154
  const material = (0, import_react31.useMemo)(() => {
9003
9155
  if (!isSnapshotTransition(transition.preset)) {
9004
9156
  return null;
@@ -9089,11 +9241,11 @@ function TransitionOverlay(props) {
9089
9241
  // src/sphere.tsx
9090
9242
  var import_fiber14 = require("@react-three/fiber");
9091
9243
  var import_react33 = require("react");
9092
- var import_three13 = require("three");
9244
+ var import_three14 = require("three");
9093
9245
 
9094
9246
  // src/pano-filter/pano-basic-material.tsx
9095
9247
  var import_react32 = require("react");
9096
- var import_three12 = require("three");
9248
+ var import_three13 = require("three");
9097
9249
 
9098
9250
  // src/pano-filter/shaders.ts
9099
9251
  var GLSL_FILTER_COMMON = `
@@ -9260,7 +9412,7 @@ function injectPanoColorMatrixShader(shader) {
9260
9412
  var import_jsx_runtime17 = require("react/jsx-runtime");
9261
9413
  function matrixUniforms(matrix) {
9262
9414
  return {
9263
- matrix: new import_three12.Matrix4().set(
9415
+ matrix: new import_three13.Matrix4().set(
9264
9416
  matrix[0],
9265
9417
  matrix[1],
9266
9418
  matrix[2],
@@ -9278,7 +9430,7 @@ function matrixUniforms(matrix) {
9278
9430
  matrix[17],
9279
9431
  matrix[18]
9280
9432
  ),
9281
- offset: new import_three12.Vector4(matrix[4], matrix[9], matrix[14], matrix[19])
9433
+ offset: new import_three13.Vector4(matrix[4], matrix[9], matrix[14], matrix[19])
9282
9434
  };
9283
9435
  }
9284
9436
  function PanoBasicMaterial({
@@ -9349,7 +9501,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9349
9501
  return;
9350
9502
  }
9351
9503
  let active = true;
9352
- const loader = new import_three13.TextureLoader();
9504
+ const loader = new import_three14.TextureLoader();
9353
9505
  setTexture(null);
9354
9506
  loader.load(
9355
9507
  url,
@@ -9358,13 +9510,13 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9358
9510
  loadedTexture.dispose();
9359
9511
  return;
9360
9512
  }
9361
- loadedTexture.colorSpace = import_three13.SRGBColorSpace;
9362
- loadedTexture.wrapS = import_three13.RepeatWrapping;
9513
+ loadedTexture.colorSpace = import_three14.SRGBColorSpace;
9514
+ loadedTexture.wrapS = import_three14.RepeatWrapping;
9363
9515
  loadedTexture.repeat.x = -1;
9364
9516
  loadedTexture.offset.x = 1;
9365
9517
  loadedTexture.anisotropy = anisotropy;
9366
- loadedTexture.magFilter = import_three13.LinearFilter;
9367
- loadedTexture.minFilter = generateMipmaps ? import_three13.LinearMipmapLinearFilter : import_three13.LinearFilter;
9518
+ loadedTexture.magFilter = import_three14.LinearFilter;
9519
+ loadedTexture.minFilter = generateMipmaps ? import_three14.LinearMipmapLinearFilter : import_three14.LinearFilter;
9368
9520
  loadedTexture.generateMipmaps = generateMipmaps;
9369
9521
  loadedTexture.needsUpdate = true;
9370
9522
  setTexture(loadedTexture);
@@ -9448,7 +9600,7 @@ function Sphere({
9448
9600
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
9449
9601
  "mesh",
9450
9602
  {
9451
- rotation: [0, import_three13.MathUtils.degToRad(90 + yawOffset2), 0],
9603
+ rotation: [0, import_three14.MathUtils.degToRad(90 + yawOffset2), 0],
9452
9604
  visible,
9453
9605
  children: [
9454
9606
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
@@ -9456,7 +9608,7 @@ function Sphere({
9456
9608
  PanoBasicMaterial,
9457
9609
  {
9458
9610
  map: displayTexture,
9459
- side: import_three13.BackSide,
9611
+ side: import_three14.BackSide,
9460
9612
  toneMapped: false
9461
9613
  }
9462
9614
  )
@@ -9468,10 +9620,10 @@ function Sphere({
9468
9620
  // src/sphere-tile/sphere-tile.tsx
9469
9621
  var import_fiber16 = require("@react-three/fiber");
9470
9622
  var import_react36 = require("react");
9471
- var import_three17 = require("three");
9623
+ var import_three18 = require("three");
9472
9624
 
9473
9625
  // src/tile/texture-manager.ts
9474
- var import_three14 = require("three");
9626
+ var import_three15 = require("three");
9475
9627
  var EMPTY_TEXTURE_SNAPSHOT = {
9476
9628
  status: "idle",
9477
9629
  texture: null,
@@ -9479,7 +9631,7 @@ var EMPTY_TEXTURE_SNAPSHOT = {
9479
9631
  };
9480
9632
  var TileTextureManager = class {
9481
9633
  constructor(options) {
9482
- this.loader = new import_three14.TextureLoader();
9634
+ this.loader = new import_three15.TextureLoader();
9483
9635
  this.entries = /* @__PURE__ */ new Map();
9484
9636
  this.queue = [];
9485
9637
  this.activeLoads = 0;
@@ -9651,11 +9803,11 @@ var TileTextureManager = class {
9651
9803
  }
9652
9804
  }
9653
9805
  configureTexture(texture) {
9654
- texture.colorSpace = import_three14.SRGBColorSpace;
9655
- texture.wrapS = import_three14.ClampToEdgeWrapping;
9656
- texture.wrapT = import_three14.ClampToEdgeWrapping;
9657
- texture.magFilter = import_three14.LinearFilter;
9658
- texture.minFilter = import_three14.LinearFilter;
9806
+ texture.colorSpace = import_three15.SRGBColorSpace;
9807
+ texture.wrapS = import_three15.ClampToEdgeWrapping;
9808
+ texture.wrapT = import_three15.ClampToEdgeWrapping;
9809
+ texture.magFilter = import_three15.LinearFilter;
9810
+ texture.minFilter = import_three15.LinearFilter;
9659
9811
  texture.generateMipmaps = false;
9660
9812
  texture.anisotropy = Math.min(4, this.options.anisotropy);
9661
9813
  texture.needsUpdate = true;
@@ -9728,7 +9880,7 @@ function useSharedTileTextureManager() {
9728
9880
 
9729
9881
  // src/tile/texture-hooks.ts
9730
9882
  var import_react35 = require("react");
9731
- var import_three15 = require("three");
9883
+ var import_three16 = require("three");
9732
9884
  function usePreviewTexture(url, anisotropy, onError) {
9733
9885
  const [texture, setTexture] = (0, import_react35.useState)(null);
9734
9886
  const onErrorRef = (0, import_react35.useRef)(onError);
@@ -9739,7 +9891,7 @@ function usePreviewTexture(url, anisotropy, onError) {
9739
9891
  return;
9740
9892
  }
9741
9893
  let active = true;
9742
- const loader = new import_three15.TextureLoader();
9894
+ const loader = new import_three16.TextureLoader();
9743
9895
  setTexture(null);
9744
9896
  loader.load(
9745
9897
  url,
@@ -9748,11 +9900,11 @@ function usePreviewTexture(url, anisotropy, onError) {
9748
9900
  loadedTexture.dispose();
9749
9901
  return;
9750
9902
  }
9751
- loadedTexture.colorSpace = import_three15.SRGBColorSpace;
9752
- loadedTexture.wrapS = import_three15.ClampToEdgeWrapping;
9753
- loadedTexture.wrapT = import_three15.ClampToEdgeWrapping;
9754
- loadedTexture.magFilter = import_three15.LinearFilter;
9755
- loadedTexture.minFilter = import_three15.LinearFilter;
9903
+ loadedTexture.colorSpace = import_three16.SRGBColorSpace;
9904
+ loadedTexture.wrapS = import_three16.ClampToEdgeWrapping;
9905
+ loadedTexture.wrapT = import_three16.ClampToEdgeWrapping;
9906
+ loadedTexture.magFilter = import_three16.LinearFilter;
9907
+ loadedTexture.minFilter = import_three16.LinearFilter;
9756
9908
  loadedTexture.generateMipmaps = false;
9757
9909
  loadedTexture.anisotropy = Math.min(4, anisotropy);
9758
9910
  loadedTexture.needsUpdate = true;
@@ -9801,7 +9953,7 @@ function useManagedTexture(manager, key, url, address) {
9801
9953
  }
9802
9954
 
9803
9955
  // src/sphere-tile/layout.ts
9804
- var import_three16 = require("three");
9956
+ var import_three17 = require("three");
9805
9957
  function positiveInteger2(value, name) {
9806
9958
  if (!Number.isSafeInteger(value) || value <= 0) {
9807
9959
  throw new Error(`${name} must be a positive safe integer`);
@@ -9872,9 +10024,9 @@ function sphereTileRange(address) {
9872
10024
  };
9873
10025
  }
9874
10026
  function spherePoint(u, v, yawOffset2 = 0, radius = DEFAULT_PANORAMA_RADIUS) {
9875
- const yaw = (u - 0.5) * Math.PI * 2 + import_three16.MathUtils.degToRad(yawOffset2);
10027
+ const yaw = (u - 0.5) * Math.PI * 2 + import_three17.MathUtils.degToRad(yawOffset2);
9876
10028
  const pitch = (0.5 - v) * Math.PI;
9877
- return new import_three16.Vector3(
10029
+ return new import_three17.Vector3(
9878
10030
  Math.sin(yaw) * Math.cos(pitch) * radius,
9879
10031
  Math.sin(pitch) * radius,
9880
10032
  -Math.cos(yaw) * Math.cos(pitch) * radius
@@ -9888,7 +10040,7 @@ function sphereTileBounds(address, yawOffset2) {
9888
10040
  if (u > left && u < right) us.push(u);
9889
10041
  }
9890
10042
  const vs = top < 0.5 && bottom > 0.5 ? [top, 0.5, bottom] : [top, bottom];
9891
- return new import_three16.Box3().setFromPoints(
10043
+ return new import_three17.Box3().setFromPoints(
9892
10044
  us.flatMap((u) => vs.map((v) => spherePoint(u, v, yawOffset2)))
9893
10045
  );
9894
10046
  }
@@ -9914,9 +10066,9 @@ function sphereTileGeometry(address, yawOffset2, radius = DEFAULT_PANORAMA_RADIU
9914
10066
  }
9915
10067
  }
9916
10068
  }
9917
- const geometry = new import_three16.BufferGeometry();
9918
- geometry.setAttribute("position", new import_three16.Float32BufferAttribute(positions, 3));
9919
- geometry.setAttribute("uv", new import_three16.Float32BufferAttribute(uvs, 2));
10069
+ const geometry = new import_three17.BufferGeometry();
10070
+ geometry.setAttribute("position", new import_three17.Float32BufferAttribute(positions, 3));
10071
+ geometry.setAttribute("uv", new import_three17.Float32BufferAttribute(uvs, 2));
9920
10072
  geometry.setIndex(indices);
9921
10073
  geometry.computeBoundingSphere();
9922
10074
  return geometry;
@@ -9962,7 +10114,7 @@ function SpherePatch({
9962
10114
  PanoBasicMaterial,
9963
10115
  {
9964
10116
  map: texture,
9965
- side: import_three17.BackSide,
10117
+ side: import_three18.BackSide,
9966
10118
  depthTest: false,
9967
10119
  depthWrite: false,
9968
10120
  toneMapped: false
@@ -10104,9 +10256,9 @@ function SphereTileSource({
10104
10256
  const targetKeysRef = (0, import_react36.useRef)([]);
10105
10257
  const scratch = (0, import_react36.useMemo)(
10106
10258
  () => ({
10107
- camera: new import_three17.PerspectiveCamera(),
10108
- frustum: new import_three17.Frustum(),
10109
- matrix: new import_three17.Matrix4(),
10259
+ camera: new import_three18.PerspectiveCamera(),
10260
+ frustum: new import_three18.Frustum(),
10261
+ matrix: new import_three18.Matrix4(),
10110
10262
  quaternion: camera.quaternion.clone(),
10111
10263
  fov: NaN,
10112
10264
  width: 0,
@@ -10121,7 +10273,7 @@ function SphereTileSource({
10121
10273
  [camera, candidates]
10122
10274
  );
10123
10275
  (0, import_fiber16.useFrame)(() => {
10124
- if (!(camera instanceof import_three17.PerspectiveCamera)) return;
10276
+ if (!(camera instanceof import_three18.PerspectiveCamera)) return;
10125
10277
  const now = performance.now(), dpr = gl.getPixelRatio();
10126
10278
  const managerChanged = scratch.manager !== manager;
10127
10279
  const loadModeChanged = scratch.loadMode !== loadMode;
@@ -10225,10 +10377,10 @@ function SphereTile({ multires, ...props }) {
10225
10377
  // src/tile/tile.tsx
10226
10378
  var import_fiber17 = require("@react-three/fiber");
10227
10379
  var import_react37 = require("react");
10228
- var import_three19 = require("three");
10380
+ var import_three20 = require("three");
10229
10381
 
10230
10382
  // src/tile/face-layout.ts
10231
- var import_three18 = require("three");
10383
+ var import_three19 = require("three");
10232
10384
  var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
10233
10385
  var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
10234
10386
  var CUBE_RADIUS = DEFAULT_PANORAMA_RADIUS;
@@ -10279,8 +10431,8 @@ function getFaceQuaternion(face) {
10279
10431
  return cached;
10280
10432
  }
10281
10433
  const transform = getFaceTransform(face);
10282
- const quaternion = new import_three18.Quaternion().setFromEuler(
10283
- new import_three18.Euler(...transform.rotation, "XYZ")
10434
+ const quaternion = new import_three19.Quaternion().setFromEuler(
10435
+ new import_three19.Euler(...transform.rotation, "XYZ")
10284
10436
  );
10285
10437
  faceQuaternionCache.set(face, quaternion);
10286
10438
  return quaternion;
@@ -10291,17 +10443,17 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
10291
10443
  const halfWidth = local.width / 2;
10292
10444
  const halfHeight = local.height / 2;
10293
10445
  const quaternion = getFaceQuaternion(address.face);
10294
- const position = new import_three18.Vector3(...transform.position);
10446
+ const position = new import_three19.Vector3(...transform.position);
10295
10447
  const corners = [
10296
- new import_three18.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
10297
- new import_three18.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
10298
- new import_three18.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
10299
- new import_three18.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
10448
+ new import_three19.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
10449
+ new import_three19.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
10450
+ new import_three19.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
10451
+ new import_three19.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
10300
10452
  ];
10301
10453
  for (const corner of corners) {
10302
10454
  corner.applyQuaternion(quaternion).add(position);
10303
10455
  }
10304
- return new import_three18.Box3().setFromPoints(corners);
10456
+ return new import_three19.Box3().setFromPoints(corners);
10305
10457
  }
10306
10458
  function makeTileAddress(face, level, faceSize, tileSize, col, row) {
10307
10459
  const left = (col - 1) * tileSize;
@@ -10371,14 +10523,14 @@ function decideTileLodUpdate(input) {
10371
10523
  }
10372
10524
  var VISIBILITY_FOV_PADDING_DEGREES = 8;
10373
10525
  var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
10374
- var SHARED_TILE_GEOMETRY = new import_three19.PlaneGeometry(1, 1);
10526
+ var SHARED_TILE_GEOMETRY = new import_three20.PlaneGeometry(1, 1);
10375
10527
  function PreviewFace({
10376
10528
  face,
10377
10529
  texture,
10378
10530
  faceOrder
10379
10531
  }) {
10380
10532
  const geometry = (0, import_react37.useMemo)(() => {
10381
- const nextGeometry = new import_three19.PlaneGeometry(
10533
+ const nextGeometry = new import_three20.PlaneGeometry(
10382
10534
  PREVIEW_RADIUS * 2,
10383
10535
  PREVIEW_RADIUS * 2
10384
10536
  );
@@ -10570,8 +10722,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
10570
10722
  return addresses;
10571
10723
  }
10572
10724
  function centerFacingAddress(candidates, camera) {
10573
- const direction = camera.getWorldDirection(new import_three19.Vector3());
10574
- const center = new import_three19.Vector3();
10725
+ const direction = camera.getWorldDirection(new import_three20.Vector3());
10726
+ const center = new import_three20.Vector3();
10575
10727
  let bestCandidate = candidates[0];
10576
10728
  let bestAlignment = -Infinity;
10577
10729
  for (const candidate of candidates) {
@@ -10716,9 +10868,9 @@ function Tile({
10716
10868
  const lastVisibilityQuaternionRef = (0, import_react37.useRef)(camera.quaternion.clone());
10717
10869
  const lastVisibilityFovRef = (0, import_react37.useRef)(Number.NaN);
10718
10870
  const lastViewportRef = (0, import_react37.useRef)({ width: 0, height: 0, dpr: 0 });
10719
- const frustumRef = (0, import_react37.useRef)(new import_three19.Frustum());
10720
- const projectionMatrixRef = (0, import_react37.useRef)(new import_three19.Matrix4());
10721
- const visibilityCameraRef = (0, import_react37.useRef)(new import_three19.PerspectiveCamera());
10871
+ const frustumRef = (0, import_react37.useRef)(new import_three20.Frustum());
10872
+ const projectionMatrixRef = (0, import_react37.useRef)(new import_three20.Matrix4());
10873
+ const visibilityCameraRef = (0, import_react37.useRef)(new import_three20.PerspectiveCamera());
10722
10874
  const trackedLoadModeRef = (0, import_react37.useRef)(loadMode);
10723
10875
  const targetKeysRef = (0, import_react37.useRef)([]);
10724
10876
  const detailTokenRef = (0, import_react37.useRef)("");
@@ -10746,7 +10898,7 @@ function Tile({
10746
10898
  }
10747
10899
  };
10748
10900
  (0, import_fiber17.useFrame)(() => {
10749
- if (!(camera instanceof import_three19.PerspectiveCamera)) {
10901
+ if (!(camera instanceof import_three20.PerspectiveCamera)) {
10750
10902
  return;
10751
10903
  }
10752
10904
  if (loadMode === "preview") {
@@ -10926,14 +11078,14 @@ function SnapshotCapture({
10926
11078
  const scale = Math.min(1, Math.sqrt(maxPixels / (sourceWidth * sourceHeight)));
10927
11079
  const width = Math.max(1, Math.floor(sourceWidth * scale));
10928
11080
  const height = Math.max(1, Math.floor(sourceHeight * scale));
10929
- const nextTarget = new import_three20.WebGLRenderTarget(width, height, {
11081
+ const nextTarget = new import_three21.WebGLRenderTarget(width, height, {
10930
11082
  depthBuffer: false,
10931
11083
  stencilBuffer: false
10932
11084
  });
10933
- nextTarget.texture.colorSpace = import_three20.LinearSRGBColorSpace;
11085
+ nextTarget.texture.colorSpace = import_three21.LinearSRGBColorSpace;
10934
11086
  nextTarget.texture.generateMipmaps = false;
10935
- nextTarget.texture.minFilter = import_three20.LinearFilter;
10936
- nextTarget.texture.magFilter = import_three20.LinearFilter;
11087
+ nextTarget.texture.minFilter = import_three21.LinearFilter;
11088
+ nextTarget.texture.magFilter = import_three21.LinearFilter;
10937
11089
  const previousTarget = gl.getRenderTarget();
10938
11090
  gl.setRenderTarget(nextTarget);
10939
11091
  gl.clear();
@@ -11483,12 +11635,12 @@ function Scenes({
11483
11635
  // src/hotspot/image-hotspot.tsx
11484
11636
  var import_fiber22 = require("@react-three/fiber");
11485
11637
  var import_react43 = require("react");
11486
- var import_three26 = require("three");
11638
+ var import_three27 = require("three");
11487
11639
 
11488
11640
  // src/hotspot/hotspot-anchor.tsx
11489
11641
  var import_fiber21 = require("@react-three/fiber");
11490
11642
  var import_react42 = require("react");
11491
- var import_three24 = require("three");
11643
+ var import_three25 = require("three");
11492
11644
 
11493
11645
  // src/hotspot/drag-session.ts
11494
11646
  var CLICK_SUPPRESS_MS = 1e3;
@@ -11553,6 +11705,7 @@ function trackPointerDrag(source, element, pointerId, onMove, onEnd) {
11553
11705
  element.addEventListener("lostpointercapture", onLostCapture);
11554
11706
  return stop;
11555
11707
  }
11708
+ var CAPTURE = { capture: true };
11556
11709
  function suppressFollowingClick(target) {
11557
11710
  let cleaned = false;
11558
11711
  const cleanup = () => {
@@ -11560,8 +11713,8 @@ function suppressFollowingClick(target) {
11560
11713
  return;
11561
11714
  }
11562
11715
  cleaned = true;
11563
- target.removeEventListener("click", swallowClick, true);
11564
- target.removeEventListener("pointerdown", cancel, true);
11716
+ target.removeEventListener("click", swallowClick, CAPTURE);
11717
+ target.removeEventListener("pointerdown", cancel, CAPTURE);
11565
11718
  };
11566
11719
  const swallowClick = (event) => {
11567
11720
  event.preventDefault();
@@ -11572,8 +11725,8 @@ function suppressFollowingClick(target) {
11572
11725
  const cancel = () => {
11573
11726
  cleanup();
11574
11727
  };
11575
- target.addEventListener("click", swallowClick, true);
11576
- target.addEventListener("pointerdown", cancel, true);
11728
+ target.addEventListener("click", swallowClick, CAPTURE);
11729
+ target.addEventListener("pointerdown", cancel, CAPTURE);
11577
11730
  setTimeout(cleanup, CLICK_SUPPRESS_MS);
11578
11731
  }
11579
11732
 
@@ -11584,7 +11737,7 @@ var import_react40 = require("react");
11584
11737
  var import_fiber19 = require("@react-three/fiber");
11585
11738
  var import_react39 = require("react");
11586
11739
  var import_client = require("react-dom/client");
11587
- var import_three21 = require("three");
11740
+ var import_three22 = require("three");
11588
11741
  var import_jsx_runtime23 = require("react/jsx-runtime");
11589
11742
  function useFallbackStereoView() {
11590
11743
  const runtime = (0, import_react39.useContext)(WebVRRuntimeContext);
@@ -11607,7 +11760,7 @@ function ProjectedHtml({
11607
11760
  const { camera, gl, events, size } = (0, import_fiber19.useThree)();
11608
11761
  const group = (0, import_react39.useRef)(null);
11609
11762
  const overlay = (0, import_react39.useRef)(null);
11610
- const scratch = (0, import_react39.useRef)(new import_three21.Vector3());
11763
+ const scratch = (0, import_react39.useRef)(new import_three22.Vector3());
11611
11764
  const target = events.connected || gl.domElement.parentElement;
11612
11765
  const updatePosition = () => {
11613
11766
  const anchor = group.current;
@@ -11807,18 +11960,18 @@ function HotspotTooltip({
11807
11960
  }
11808
11961
 
11809
11962
  // src/hotspot/transform.ts
11810
- var import_three22 = require("three");
11811
- var LOCAL_FORWARD = new import_three22.Vector3(0, 0, 1);
11812
- var CAMERA_POSITION = new import_three22.Vector3();
11963
+ var import_three23 = require("three");
11964
+ var LOCAL_FORWARD = new import_three23.Vector3(0, 0, 1);
11965
+ var CAMERA_POSITION = new import_three23.Vector3();
11813
11966
  function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight, distance) {
11814
11967
  if (orientation2 === "billboard") {
11815
11968
  group.quaternion.copy(camera.quaternion);
11816
11969
  } else {
11817
11970
  group.quaternion.copy(surfaceQuaternion3);
11818
11971
  }
11819
- group.rotateOnAxis(LOCAL_FORWARD, import_three22.MathUtils.degToRad(-rotation));
11820
- let scaleFactor = scaleMode === "fixed" && camera instanceof import_three22.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
11821
- if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof import_three22.PerspectiveCamera) {
11972
+ group.rotateOnAxis(LOCAL_FORWARD, import_three23.MathUtils.degToRad(-rotation));
11973
+ let scaleFactor = scaleMode === "fixed" && camera instanceof import_three23.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
11974
+ if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof import_three23.PerspectiveCamera) {
11822
11975
  group.updateWorldMatrix(true, false);
11823
11976
  CAMERA_POSITION.setFromMatrixPosition(group.matrixWorld).applyMatrix4(
11824
11977
  camera.matrixWorldInverse
@@ -11833,15 +11986,15 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
11833
11986
  group.updateMatrixWorld();
11834
11987
  }
11835
11988
  function fixedScaleFactor(cameraFov, referenceFov) {
11836
- const safeReferenceFov = import_three22.MathUtils.clamp(referenceFov, 1, 179);
11837
- return Math.tan(import_three22.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three22.MathUtils.degToRad(safeReferenceFov) / 2);
11989
+ const safeReferenceFov = import_three23.MathUtils.clamp(referenceFov, 1, 179);
11990
+ return Math.tan(import_three23.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three23.MathUtils.degToRad(safeReferenceFov) / 2);
11838
11991
  }
11839
11992
  function selectionFrameScale(worldScaleX, worldScaleY, cameraSpaceDepth, fovDegrees, viewportHeight, outsetPixels) {
11840
11993
  const pixels = Number.isFinite(outsetPixels) && outsetPixels > 0 ? outsetPixels : 0;
11841
11994
  const depth = Number.isFinite(cameraSpaceDepth) ? Math.max(cameraSpaceDepth, 1e-4) : 1e-4;
11842
11995
  const height = Number.isFinite(viewportHeight) ? Math.max(viewportHeight, 1) : 1;
11843
- const fov = Number.isFinite(fovDegrees) ? import_three22.MathUtils.clamp(fovDegrees, 1, 179) : 75;
11844
- const pixelsPerWorldUnit = height / (2 * Math.tan(import_three22.MathUtils.degToRad(fov) * 0.5) * depth);
11996
+ const fov = Number.isFinite(fovDegrees) ? import_three23.MathUtils.clamp(fovDegrees, 1, 179) : 75;
11997
+ const pixelsPerWorldUnit = height / (2 * Math.tan(import_three23.MathUtils.degToRad(fov) * 0.5) * depth);
11845
11998
  const axis = (worldScale) => {
11846
11999
  const pixelsPerLocalUnit = pixelsPerWorldUnit * Math.abs(worldScale);
11847
12000
  if (pixelsPerLocalUnit < 1e-4) {
@@ -11856,9 +12009,9 @@ function selectionFrameScale(worldScaleX, worldScaleY, cameraSpaceDepth, fovDegr
11856
12009
  var import_drei = require("@react-three/drei");
11857
12010
  var import_fiber20 = require("@react-three/fiber");
11858
12011
  var import_react41 = require("react");
11859
- var import_three23 = require("three");
12012
+ var import_three24 = require("three");
11860
12013
  var import_jsx_runtime25 = require("react/jsx-runtime");
11861
- var LINE_WORLD_POSITION = new import_three23.Vector3();
12014
+ var LINE_WORLD_POSITION = new import_three24.Vector3();
11862
12015
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
11863
12016
  const material = object?.material;
11864
12017
  if (!object || typeof material?.dashScale !== "number") {
@@ -11866,8 +12019,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
11866
12019
  }
11867
12020
  object.getWorldPosition(LINE_WORLD_POSITION);
11868
12021
  const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
11869
- const fov = camera instanceof import_three23.PerspectiveCamera ? camera.fov : 75;
11870
- material.dashScale = viewportHeight / (2 * Math.tan(import_three23.MathUtils.degToRad(fov) * 0.5) * depth);
12022
+ const fov = camera instanceof import_three24.PerspectiveCamera ? camera.fov : 75;
12023
+ material.dashScale = viewportHeight / (2 * Math.tan(import_three24.MathUtils.degToRad(fov) * 0.5) * depth);
11871
12024
  }
11872
12025
  function resolveDash(dashSize, gapSize) {
11873
12026
  if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
@@ -11936,8 +12089,8 @@ var DRAG_EPSILON_DEGREES = 1e-3;
11936
12089
  var SELECTION_BORDER_WIDTH = 3;
11937
12090
  var SELECTION_BORDER_GAP = 3;
11938
12091
  var SELECTION_BORDER_OUTSET = SELECTION_BORDER_GAP + SELECTION_BORDER_WIDTH / 2;
11939
- var SELECTION_CAMERA_POSITION = new import_three24.Vector3();
11940
- var SELECTION_WORLD_SCALE = new import_three24.Vector3();
12092
+ var SELECTION_CAMERA_POSITION = new import_three25.Vector3();
12093
+ var SELECTION_WORLD_SCALE = new import_three25.Vector3();
11941
12094
  var SELECTION_BORDER_POINTS = [
11942
12095
  [-0.5, -0.5, 1e-3],
11943
12096
  [0.5, -0.5, 1e-3],
@@ -11945,27 +12098,27 @@ var SELECTION_BORDER_POINTS = [
11945
12098
  [-0.5, 0.5, 1e-3],
11946
12099
  [-0.5, -0.5, 1e-3]
11947
12100
  ];
11948
- var TOOLTIP_WORLD_BOX = new import_three24.Box3();
11949
- var TOOLTIP_LOCAL_BOX = new import_three24.Box3();
11950
- var TOOLTIP_CORNER = new import_three24.Vector3();
11951
- var TOOLTIP_INVERSE = new import_three24.Matrix4();
11952
- var TOOLTIP_WORLD_CORNER = new import_three24.Vector3();
11953
- var TOOLTIP_PROJECTED = new import_three24.Vector3();
11954
- var TOOLTIP_RAY_ORIGIN = new import_three24.Vector3();
11955
- var TOOLTIP_RAY_FAR = new import_three24.Vector3();
11956
- var TOOLTIP_RAY_DIRECTION = new import_three24.Vector3();
11957
- var TOOLTIP_RAY = new import_three24.Ray();
11958
- var TOOLTIP_PLANE = new import_three24.Plane();
11959
- var TOOLTIP_INTERSECTION = new import_three24.Vector3();
11960
- var TOOLTIP_PLANE_NORMAL = new import_three24.Vector3();
11961
- var TOOLTIP_PLANE_POINT = new import_three24.Vector3();
12101
+ var TOOLTIP_WORLD_BOX = new import_three25.Box3();
12102
+ var TOOLTIP_LOCAL_BOX = new import_three25.Box3();
12103
+ var TOOLTIP_CORNER = new import_three25.Vector3();
12104
+ var TOOLTIP_INVERSE = new import_three25.Matrix4();
12105
+ var TOOLTIP_WORLD_CORNER = new import_three25.Vector3();
12106
+ var TOOLTIP_PROJECTED = new import_three25.Vector3();
12107
+ var TOOLTIP_RAY_ORIGIN = new import_three25.Vector3();
12108
+ var TOOLTIP_RAY_FAR = new import_three25.Vector3();
12109
+ var TOOLTIP_RAY_DIRECTION = new import_three25.Vector3();
12110
+ var TOOLTIP_RAY = new import_three25.Ray();
12111
+ var TOOLTIP_PLANE = new import_three25.Plane();
12112
+ var TOOLTIP_INTERSECTION = new import_three25.Vector3();
12113
+ var TOOLTIP_PLANE_NORMAL = new import_three25.Vector3();
12114
+ var TOOLTIP_PLANE_POINT = new import_three25.Vector3();
11962
12115
  var HOTSPOT_MODE_RENDERING = {
11963
12116
  surface: { orientation: "surface", placement: "surface" },
11964
12117
  billboard: { orientation: "billboard", placement: "floating" }
11965
12118
  };
11966
12119
  function angularSizeToWorldSize(size, radius) {
11967
- const safeSize = Number.isFinite(size) ? import_three24.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
11968
- return 2 * radius * Math.tan(import_three24.MathUtils.degToRad(safeSize) / 2);
12120
+ const safeSize = Number.isFinite(size) ? import_three25.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
12121
+ return 2 * radius * Math.tan(import_three25.MathUtils.degToRad(safeSize) / 2);
11969
12122
  }
11970
12123
  function resolveScale(scale) {
11971
12124
  return Number.isFinite(scale) && scale > 0 ? scale : 1;
@@ -11978,39 +12131,39 @@ function resolveDistance(placement, distance, width, height) {
11978
12131
  if (!Number.isFinite(distance)) {
11979
12132
  return DEFAULT_FLOATING_DISTANCE;
11980
12133
  }
11981
- return import_three24.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
12134
+ return import_three25.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
11982
12135
  }
11983
12136
  function maximumHotspotDistance(width, height) {
11984
- const safeWidth = import_three24.MathUtils.clamp(
12137
+ const safeWidth = import_three25.MathUtils.clamp(
11985
12138
  Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
11986
12139
  MIN_ANGULAR_SIZE,
11987
12140
  MAX_ANGULAR_SIZE
11988
12141
  );
11989
- const safeHeight = import_three24.MathUtils.clamp(
12142
+ const safeHeight = import_three25.MathUtils.clamp(
11990
12143
  Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
11991
12144
  MIN_ANGULAR_SIZE,
11992
12145
  MAX_ANGULAR_SIZE
11993
12146
  );
11994
12147
  const cornerFactor = Math.hypot(
11995
12148
  1,
11996
- Math.tan(import_three24.MathUtils.degToRad(safeWidth) / 2),
11997
- Math.tan(import_three24.MathUtils.degToRad(safeHeight) / 2)
12149
+ Math.tan(import_three25.MathUtils.degToRad(safeWidth) / 2),
12150
+ Math.tan(import_three25.MathUtils.degToRad(safeHeight) / 2)
11998
12151
  );
11999
12152
  return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
12000
12153
  }
12001
12154
  function createSurfaceQuaternion(position) {
12002
12155
  const outward = panoPositionToVector3(position).normalize();
12003
12156
  const inward = outward.clone().negate();
12004
- const pitch = import_three24.MathUtils.degToRad(position.pitch);
12005
- const yaw = import_three24.MathUtils.degToRad(position.yaw);
12006
- const localUp = new import_three24.Vector3(
12157
+ const pitch = import_three25.MathUtils.degToRad(position.pitch);
12158
+ const yaw = import_three25.MathUtils.degToRad(position.yaw);
12159
+ const localUp = new import_three25.Vector3(
12007
12160
  -Math.sin(pitch) * Math.sin(yaw),
12008
12161
  Math.cos(pitch),
12009
12162
  Math.sin(pitch) * Math.cos(yaw)
12010
12163
  ).normalize();
12011
12164
  const localRight = localUp.clone().cross(inward).normalize();
12012
- const basis = new import_three24.Matrix4().makeBasis(localRight, localUp, inward);
12013
- return new import_three24.Quaternion().setFromRotationMatrix(basis);
12165
+ const basis = new import_three25.Matrix4().makeBasis(localRight, localUp, inward);
12166
+ return new import_three25.Quaternion().setFromRotationMatrix(basis);
12014
12167
  }
12015
12168
  function makeInteractionEvent(id, position, event) {
12016
12169
  return {
@@ -12023,10 +12176,10 @@ function makeInteractionEvent(id, position, event) {
12023
12176
  function angularDistance(a, b) {
12024
12177
  const aVector = panoPositionToVector3(a);
12025
12178
  const bVector = panoPositionToVector3(b);
12026
- return import_three24.MathUtils.radToDeg(aVector.angleTo(bVector));
12179
+ return import_three25.MathUtils.radToDeg(aVector.angleTo(bVector));
12027
12180
  }
12028
- var DRAG_POINTER = new import_three24.Vector2();
12029
- var DRAG_RAYCASTER = new import_three24.Raycaster();
12181
+ var DRAG_POINTER = new import_three25.Vector2();
12182
+ var DRAG_RAYCASTER = new import_three25.Raycaster();
12030
12183
  function aimDragRaycaster(event, element, camera) {
12031
12184
  const rect = element.getBoundingClientRect();
12032
12185
  if (!(rect.width > 0) || !(rect.height > 0)) {
@@ -12260,7 +12413,7 @@ function placeSelectionFrame(frame, group, camera, viewportHeight) {
12260
12413
  SELECTION_WORLD_SCALE.x,
12261
12414
  SELECTION_WORLD_SCALE.y,
12262
12415
  -SELECTION_CAMERA_POSITION.z,
12263
- camera instanceof import_three24.PerspectiveCamera ? camera.fov : DEFAULT_REFERENCE_FOV,
12416
+ camera instanceof import_three25.PerspectiveCamera ? camera.fov : DEFAULT_REFERENCE_FOV,
12264
12417
  viewportHeight,
12265
12418
  SELECTION_BORDER_OUTSET
12266
12419
  );
@@ -12349,8 +12502,8 @@ function HotspotAnchor({
12349
12502
  const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
12350
12503
  const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
12351
12504
  const focusGeometry = (0, import_react42.useMemo)(() => {
12352
- const planeGeometry = new import_three24.PlaneGeometry(1, 1);
12353
- const geometry = new import_three24.EdgesGeometry(planeGeometry);
12505
+ const planeGeometry = new import_three25.PlaneGeometry(1, 1);
12506
+ const geometry = new import_three25.EdgesGeometry(planeGeometry);
12354
12507
  planeGeometry.dispose();
12355
12508
  return geometry;
12356
12509
  }, []);
@@ -12742,10 +12895,10 @@ function HotspotAnchor({
12742
12895
  }
12743
12896
 
12744
12897
  // src/hotspot/hotspot-plane.tsx
12745
- var import_three25 = require("three");
12898
+ var import_three26 = require("three");
12746
12899
  var import_jsx_runtime27 = require("react/jsx-runtime");
12747
12900
  var HOTSPOT_ALPHA_CUTOFF = 0.05;
12748
- var SAMPLE_UV = new import_three25.Vector2();
12901
+ var SAMPLE_UV = new import_three26.Vector2();
12749
12902
  var RAYCAST_HITS = [];
12750
12903
  var IMAGE_DATA_CACHE = /* @__PURE__ */ new WeakMap();
12751
12904
  function clampOpacity(opacity) {
@@ -12819,8 +12972,8 @@ function sampleTextureAlpha(texture, u, v) {
12819
12972
  }
12820
12973
  function hotspotPlaneRaycast(raycaster, intersects2) {
12821
12974
  const material = Array.isArray(this.material) ? this.material[0] : this.material;
12822
- if (!(material instanceof import_three25.MeshBasicMaterial)) {
12823
- import_three25.Mesh.prototype.raycast.call(this, raycaster, intersects2);
12975
+ if (!(material instanceof import_three26.MeshBasicMaterial)) {
12976
+ import_three26.Mesh.prototype.raycast.call(this, raycaster, intersects2);
12824
12977
  return;
12825
12978
  }
12826
12979
  const cutoff = Math.max(material.alphaTest, HOTSPOT_ALPHA_CUTOFF);
@@ -12828,7 +12981,7 @@ function hotspotPlaneRaycast(raycaster, intersects2) {
12828
12981
  return;
12829
12982
  }
12830
12983
  RAYCAST_HITS.length = 0;
12831
- import_three25.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
12984
+ import_three26.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
12832
12985
  const map = material.map;
12833
12986
  for (const hit of RAYCAST_HITS) {
12834
12987
  if (!map || !hit.uv) {
@@ -12854,7 +13007,7 @@ function HotspotPlane({
12854
13007
  alphaTest: HOTSPOT_ALPHA_CUTOFF,
12855
13008
  map,
12856
13009
  opacity: map ? clampOpacity(opacity) : 0,
12857
- side: import_three25.DoubleSide,
13010
+ side: import_three26.DoubleSide,
12858
13011
  toneMapped: false,
12859
13012
  transparent: true
12860
13013
  }
@@ -12879,7 +13032,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
12879
13032
  active = false;
12880
13033
  };
12881
13034
  }
12882
- const loader = new import_three26.TextureLoader();
13035
+ const loader = new import_three27.TextureLoader();
12883
13036
  loader.load(
12884
13037
  src,
12885
13038
  (loadedTexture) => {
@@ -12887,11 +13040,11 @@ function useHotspotImageTexture(src, onLoad, onError) {
12887
13040
  loadedTexture.dispose();
12888
13041
  return;
12889
13042
  }
12890
- loadedTexture.colorSpace = import_three26.SRGBColorSpace;
12891
- loadedTexture.wrapS = import_three26.ClampToEdgeWrapping;
12892
- loadedTexture.wrapT = import_three26.ClampToEdgeWrapping;
12893
- loadedTexture.magFilter = import_three26.LinearFilter;
12894
- loadedTexture.minFilter = import_three26.LinearMipmapLinearFilter;
13043
+ loadedTexture.colorSpace = import_three27.SRGBColorSpace;
13044
+ loadedTexture.wrapS = import_three27.ClampToEdgeWrapping;
13045
+ loadedTexture.wrapT = import_three27.ClampToEdgeWrapping;
13046
+ loadedTexture.magFilter = import_three27.LinearFilter;
13047
+ loadedTexture.minFilter = import_three27.LinearMipmapLinearFilter;
12895
13048
  loadedTexture.generateMipmaps = true;
12896
13049
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
12897
13050
  loadedTexture.needsUpdate = true;
@@ -12932,7 +13085,7 @@ function ImageHotspot({
12932
13085
 
12933
13086
  // src/hotspot/graphic-hotspot.tsx
12934
13087
  var import_react44 = require("react");
12935
- var import_three27 = require("three");
13088
+ var import_three28 = require("three");
12936
13089
  var import_jsx_runtime29 = require("react/jsx-runtime");
12937
13090
  var GRAPHIC_TEXTURE_SIZE = 512;
12938
13091
  function resolveStrokeWidth(value) {
@@ -13111,12 +13264,12 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
13111
13264
  throw new Error("Canvas 2D is unavailable for this graphic hotspot.");
13112
13265
  }
13113
13266
  drawGraphic(context, graphic, aspectWidth, aspectHeight);
13114
- const texture = new import_three27.CanvasTexture(canvas);
13115
- texture.colorSpace = import_three27.SRGBColorSpace;
13116
- texture.wrapS = import_three27.ClampToEdgeWrapping;
13117
- texture.wrapT = import_three27.ClampToEdgeWrapping;
13118
- texture.magFilter = import_three27.LinearFilter;
13119
- texture.minFilter = import_three27.LinearMipmapLinearFilter;
13267
+ const texture = new import_three28.CanvasTexture(canvas);
13268
+ texture.colorSpace = import_three28.SRGBColorSpace;
13269
+ texture.wrapS = import_three28.ClampToEdgeWrapping;
13270
+ texture.wrapT = import_three28.ClampToEdgeWrapping;
13271
+ texture.magFilter = import_three28.LinearFilter;
13272
+ texture.minFilter = import_three28.LinearMipmapLinearFilter;
13120
13273
  texture.generateMipmaps = true;
13121
13274
  texture.needsUpdate = true;
13122
13275
  return texture;
@@ -13167,7 +13320,7 @@ function GraphicHotspot(props) {
13167
13320
  // src/hotspot/sequence-hotspot.tsx
13168
13321
  var import_fiber23 = require("@react-three/fiber");
13169
13322
  var import_react45 = require("react");
13170
- var import_three28 = require("three");
13323
+ var import_three29 = require("three");
13171
13324
  var import_jsx_runtime30 = require("react/jsx-runtime");
13172
13325
  var DEFAULT_SEQUENCE_FPS = 12;
13173
13326
  function resolveFps(value) {
@@ -13197,7 +13350,7 @@ function useSpriteTexture({
13197
13350
  active = false;
13198
13351
  };
13199
13352
  }
13200
- const loader = new import_three28.TextureLoader();
13353
+ const loader = new import_three29.TextureLoader();
13201
13354
  loader.load(
13202
13355
  src,
13203
13356
  (loadedTexture) => {
@@ -13205,11 +13358,11 @@ function useSpriteTexture({
13205
13358
  loadedTexture.dispose();
13206
13359
  return;
13207
13360
  }
13208
- loadedTexture.colorSpace = import_three28.SRGBColorSpace;
13209
- loadedTexture.wrapS = import_three28.ClampToEdgeWrapping;
13210
- loadedTexture.wrapT = import_three28.ClampToEdgeWrapping;
13211
- loadedTexture.magFilter = import_three28.LinearFilter;
13212
- loadedTexture.minFilter = import_three28.LinearMipmapLinearFilter;
13361
+ loadedTexture.colorSpace = import_three29.SRGBColorSpace;
13362
+ loadedTexture.wrapS = import_three29.ClampToEdgeWrapping;
13363
+ loadedTexture.wrapT = import_three29.ClampToEdgeWrapping;
13364
+ loadedTexture.magFilter = import_three29.LinearFilter;
13365
+ loadedTexture.minFilter = import_three29.LinearMipmapLinearFilter;
13213
13366
  loadedTexture.generateMipmaps = true;
13214
13367
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
13215
13368
  loadedTexture.needsUpdate = true;
@@ -13350,7 +13503,7 @@ function SequenceHotspot({
13350
13503
  // src/hotspot/video-hotspot.tsx
13351
13504
  var import_fiber24 = require("@react-three/fiber");
13352
13505
  var import_react46 = require("react");
13353
- var import_three29 = require("three");
13506
+ var import_three30 = require("three");
13354
13507
 
13355
13508
  // src/video/inline-playback.ts
13356
13509
  var INLINE_VIDEO_ATTRIBUTES = [
@@ -13423,7 +13576,7 @@ function usePosterTexture(id, poster, onError) {
13423
13576
  active = false;
13424
13577
  };
13425
13578
  }
13426
- const loader = new import_three29.TextureLoader();
13579
+ const loader = new import_three30.TextureLoader();
13427
13580
  loader.load(
13428
13581
  poster,
13429
13582
  (loadedTexture) => {
@@ -13431,11 +13584,11 @@ function usePosterTexture(id, poster, onError) {
13431
13584
  loadedTexture.dispose();
13432
13585
  return;
13433
13586
  }
13434
- loadedTexture.colorSpace = import_three29.SRGBColorSpace;
13435
- loadedTexture.wrapS = import_three29.ClampToEdgeWrapping;
13436
- loadedTexture.wrapT = import_three29.ClampToEdgeWrapping;
13437
- loadedTexture.magFilter = import_three29.LinearFilter;
13438
- loadedTexture.minFilter = import_three29.LinearMipmapLinearFilter;
13587
+ loadedTexture.colorSpace = import_three30.SRGBColorSpace;
13588
+ loadedTexture.wrapS = import_three30.ClampToEdgeWrapping;
13589
+ loadedTexture.wrapT = import_three30.ClampToEdgeWrapping;
13590
+ loadedTexture.magFilter = import_three30.LinearFilter;
13591
+ loadedTexture.minFilter = import_three30.LinearMipmapLinearFilter;
13439
13592
  loadedTexture.generateMipmaps = true;
13440
13593
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
13441
13594
  loadedTexture.needsUpdate = true;
@@ -13490,12 +13643,12 @@ function useVideoResource({
13490
13643
  }
13491
13644
  applyInlineVideoPlayback(video, playsInline ?? true);
13492
13645
  video.poster = poster ?? "";
13493
- const texture = new import_three29.VideoTexture(video);
13494
- texture.colorSpace = import_three29.SRGBColorSpace;
13495
- texture.wrapS = import_three29.ClampToEdgeWrapping;
13496
- texture.wrapT = import_three29.ClampToEdgeWrapping;
13497
- texture.magFilter = import_three29.LinearFilter;
13498
- texture.minFilter = import_three29.LinearFilter;
13646
+ const texture = new import_three30.VideoTexture(video);
13647
+ texture.colorSpace = import_three30.SRGBColorSpace;
13648
+ texture.wrapS = import_three30.ClampToEdgeWrapping;
13649
+ texture.wrapT = import_three30.ClampToEdgeWrapping;
13650
+ texture.magFilter = import_three30.LinearFilter;
13651
+ texture.minFilter = import_three30.LinearFilter;
13499
13652
  texture.generateMipmaps = false;
13500
13653
  const notifyState = (state) => {
13501
13654
  if (active) {
@@ -13634,13 +13787,13 @@ function VideoHotspot({
13634
13787
  // src/hotspot/audio-hotspot.tsx
13635
13788
  var import_fiber25 = require("@react-three/fiber");
13636
13789
  var import_react47 = require("react");
13637
- var import_three31 = require("three");
13790
+ var import_three32 = require("three");
13638
13791
 
13639
13792
  // src/hotspot/audio-spatial.ts
13640
- var import_three30 = require("three");
13641
- var LOOK_DIR = new import_three30.Vector3();
13642
- var SOURCE_DIR = new import_three30.Vector3();
13643
- var RIGHT_DIR = new import_three30.Vector3();
13793
+ var import_three31 = require("three");
13794
+ var LOOK_DIR = new import_three31.Vector3();
13795
+ var SOURCE_DIR = new import_three31.Vector3();
13796
+ var RIGHT_DIR = new import_three31.Vector3();
13644
13797
  function clampAudioVolume(volume) {
13645
13798
  if (!Number.isFinite(volume)) {
13646
13799
  return 1;
@@ -13665,11 +13818,11 @@ function lookRangeGain(angleDegrees, range) {
13665
13818
  function audioSpatialFromView(camera, position, range) {
13666
13819
  camera.getWorldDirection(LOOK_DIR);
13667
13820
  SOURCE_DIR.copy(panoPositionToVector3(position)).normalize();
13668
- const angleDegrees = import_three30.MathUtils.radToDeg(
13669
- Math.acos(import_three30.MathUtils.clamp(LOOK_DIR.dot(SOURCE_DIR), -1, 1))
13821
+ const angleDegrees = import_three31.MathUtils.radToDeg(
13822
+ Math.acos(import_three31.MathUtils.clamp(LOOK_DIR.dot(SOURCE_DIR), -1, 1))
13670
13823
  );
13671
13824
  RIGHT_DIR.set(1, 0, 0).applyQuaternion(camera.quaternion);
13672
- const pan = import_three30.MathUtils.clamp(
13825
+ const pan = import_three31.MathUtils.clamp(
13673
13826
  Math.atan2(SOURCE_DIR.dot(RIGHT_DIR), SOURCE_DIR.dot(LOOK_DIR)) / (Math.PI / 2),
13674
13827
  -1,
13675
13828
  1
@@ -13734,12 +13887,12 @@ function createSpeakerTexture(state) {
13734
13887
  return exhaustive;
13735
13888
  }
13736
13889
  }
13737
- const texture = new import_three31.CanvasTexture(canvas);
13738
- texture.colorSpace = import_three31.SRGBColorSpace;
13739
- texture.wrapS = import_three31.ClampToEdgeWrapping;
13740
- texture.wrapT = import_three31.ClampToEdgeWrapping;
13741
- texture.magFilter = import_three31.LinearFilter;
13742
- texture.minFilter = import_three31.LinearMipmapLinearFilter;
13890
+ const texture = new import_three32.CanvasTexture(canvas);
13891
+ texture.colorSpace = import_three32.SRGBColorSpace;
13892
+ texture.wrapS = import_three32.ClampToEdgeWrapping;
13893
+ texture.wrapT = import_three32.ClampToEdgeWrapping;
13894
+ texture.magFilter = import_three32.LinearFilter;
13895
+ texture.minFilter = import_three32.LinearMipmapLinearFilter;
13743
13896
  texture.generateMipmaps = true;
13744
13897
  texture.needsUpdate = true;
13745
13898
  return texture;
@@ -13774,7 +13927,7 @@ function useIconTexture(icon, enabled, onError, id) {
13774
13927
  active = false;
13775
13928
  };
13776
13929
  }
13777
- const loader = new import_three31.TextureLoader();
13930
+ const loader = new import_three32.TextureLoader();
13778
13931
  loader.load(
13779
13932
  icon,
13780
13933
  (loadedTexture) => {
@@ -13782,11 +13935,11 @@ function useIconTexture(icon, enabled, onError, id) {
13782
13935
  loadedTexture.dispose();
13783
13936
  return;
13784
13937
  }
13785
- loadedTexture.colorSpace = import_three31.SRGBColorSpace;
13786
- loadedTexture.wrapS = import_three31.ClampToEdgeWrapping;
13787
- loadedTexture.wrapT = import_three31.ClampToEdgeWrapping;
13788
- loadedTexture.magFilter = import_three31.LinearFilter;
13789
- loadedTexture.minFilter = import_three31.LinearMipmapLinearFilter;
13938
+ loadedTexture.colorSpace = import_three32.SRGBColorSpace;
13939
+ loadedTexture.wrapS = import_three32.ClampToEdgeWrapping;
13940
+ loadedTexture.wrapT = import_three32.ClampToEdgeWrapping;
13941
+ loadedTexture.magFilter = import_three32.LinearFilter;
13942
+ loadedTexture.minFilter = import_three32.LinearMipmapLinearFilter;
13790
13943
  loadedTexture.generateMipmaps = true;
13791
13944
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
13792
13945
  loadedTexture.needsUpdate = true;
@@ -13977,7 +14130,7 @@ function AudioHotspot({
13977
14130
  // src/hotspot/text-hotspot.tsx
13978
14131
  var import_react48 = require("react");
13979
14132
  var import_fiber26 = require("@react-three/fiber");
13980
- var import_three32 = require("three");
14133
+ var import_three33 = require("three");
13981
14134
  var import_jsx_runtime33 = require("react/jsx-runtime");
13982
14135
  var TEXT_TEXTURE_LONG_SIDE = 1024;
13983
14136
  var TEXT_RASTER_SUPERSAMPLE = 2;
@@ -14049,7 +14202,7 @@ function projectedDevicePixels(angleDeg, fovDeg, viewportHeight) {
14049
14202
  }
14050
14203
  const fov = Math.min(179, Math.max(1, resolvePositive(fovDeg, DEFAULT_REFERENCE_FOV2)));
14051
14204
  const angle = Math.min(179, Math.max(0.01, Math.abs(angleDeg)));
14052
- return Math.tan(import_three32.MathUtils.degToRad(angle) / 2) / Math.tan(import_three32.MathUtils.degToRad(fov) / 2) * viewportHeight;
14205
+ return Math.tan(import_three33.MathUtils.degToRad(angle) / 2) / Math.tan(import_three33.MathUtils.degToRad(fov) / 2) * viewportHeight;
14053
14206
  }
14054
14207
  function snapRasterLongSide(screenLong, layoutLong) {
14055
14208
  if (!(screenLong > 0)) {
@@ -14238,12 +14391,12 @@ function createTextTexture(text, width, height, style, rasterLong) {
14238
14391
  0
14239
14392
  );
14240
14393
  drawTextHotspot(context, layout.canvasWidth, layout.canvasHeight, text, style);
14241
- const texture = new import_three32.CanvasTexture(canvas);
14242
- texture.colorSpace = import_three32.SRGBColorSpace;
14243
- texture.wrapS = import_three32.ClampToEdgeWrapping;
14244
- texture.wrapT = import_three32.ClampToEdgeWrapping;
14245
- texture.magFilter = import_three32.LinearFilter;
14246
- texture.minFilter = import_three32.LinearFilter;
14394
+ const texture = new import_three33.CanvasTexture(canvas);
14395
+ texture.colorSpace = import_three33.SRGBColorSpace;
14396
+ texture.wrapS = import_three33.ClampToEdgeWrapping;
14397
+ texture.wrapT = import_three33.ClampToEdgeWrapping;
14398
+ texture.magFilter = import_three33.LinearFilter;
14399
+ texture.minFilter = import_three33.LinearFilter;
14247
14400
  texture.generateMipmaps = false;
14248
14401
  texture.needsUpdate = true;
14249
14402
  return texture;
@@ -14255,7 +14408,7 @@ function useRasterLongSide(width, height, scale, scaleMode, referenceFov) {
14255
14408
  const measure = () => {
14256
14409
  const pixelRatio = getPixelRatio();
14257
14410
  const viewportHeight = size.height * (Number.isFinite(pixelRatio) && pixelRatio > 0 ? pixelRatio : 1);
14258
- const cameraFov = camera instanceof import_three32.PerspectiveCamera ? camera.fov : DEFAULT_REFERENCE_FOV2;
14411
+ const cameraFov = camera instanceof import_three33.PerspectiveCamera ? camera.fov : DEFAULT_REFERENCE_FOV2;
14259
14412
  const screenLong = Math.max(
14260
14413
  projectedDevicePixels(
14261
14414
  width * resolveScale2(scale),
@@ -14401,7 +14554,7 @@ function TextHotspot({
14401
14554
 
14402
14555
  // src/hotspot/iframe-hotspot.tsx
14403
14556
  var import_drei2 = require("@react-three/drei");
14404
- var import_three33 = require("three");
14557
+ var import_three34 = require("three");
14405
14558
  var import_jsx_runtime34 = require("react/jsx-runtime");
14406
14559
  var IFRAME_LONG_SIDE = 800;
14407
14560
  var CSS3D_DISTANCE_FACTOR = 400;
@@ -14475,7 +14628,7 @@ function IframeHotspot({
14475
14628
  {
14476
14629
  depthWrite: false,
14477
14630
  opacity: 0,
14478
- side: import_three33.DoubleSide,
14631
+ side: import_three34.DoubleSide,
14479
14632
  toneMapped: false,
14480
14633
  transparent: true
14481
14634
  }
@@ -14519,7 +14672,7 @@ function IframeHotspot({
14519
14672
 
14520
14673
  // src/hotspot/polygon-hotspot.tsx
14521
14674
  var import_react49 = require("react");
14522
- var import_three34 = require("three");
14675
+ var import_three35 = require("three");
14523
14676
  var import_jsx_runtime35 = require("react/jsx-runtime");
14524
14677
  var POLYGON_RADIUS = 990;
14525
14678
  var MAX_FILL_SEGMENT_DEGREES = 7;
@@ -14555,7 +14708,7 @@ function intersects(a, b, c, d) {
14555
14708
  }
14556
14709
  function hasSelfIntersection(vertices) {
14557
14710
  const points = vertices.map(
14558
- (vertex) => new import_three34.Vector2(vertex.unwrappedYaw, vertex.pitch)
14711
+ (vertex) => new import_three35.Vector2(vertex.unwrappedYaw, vertex.pitch)
14559
14712
  );
14560
14713
  for (let index = 0; index < points.length; index += 1) {
14561
14714
  const nextIndex = (index + 1) % points.length;
@@ -14592,7 +14745,7 @@ function polygonContainsDirection(vertices, direction) {
14592
14745
  }
14593
14746
  function fitsHemisphere(vertices) {
14594
14747
  const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
14595
- const candidates = [new import_three34.Vector3()];
14748
+ const candidates = [new import_three35.Vector3()];
14596
14749
  for (const direction of directions) {
14597
14750
  candidates[0].add(direction);
14598
14751
  candidates.push(direction.clone());
@@ -14616,7 +14769,7 @@ function validatePolygonVertices(vertices) {
14616
14769
  if (hasSelfIntersection(unwrapped)) {
14617
14770
  issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
14618
14771
  }
14619
- if (polygonContainsDirection(normalized, new import_three34.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three34.Vector3(0, -1, 0))) {
14772
+ if (polygonContainsDirection(normalized, new import_three35.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three35.Vector3(0, -1, 0))) {
14620
14773
  issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
14621
14774
  }
14622
14775
  if (!fitsHemisphere(normalized)) {
@@ -14627,7 +14780,7 @@ function validatePolygonVertices(vertices) {
14627
14780
  function polygonCenter(vertices) {
14628
14781
  const sum = vertices.reduce(
14629
14782
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14630
- new import_three34.Vector3()
14783
+ new import_three35.Vector3()
14631
14784
  );
14632
14785
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14633
14786
  }
@@ -14636,20 +14789,20 @@ function surfaceQuaternion(position) {
14636
14789
  const inward = outward.clone().negate();
14637
14790
  const pitch = position.pitch * Math.PI / 180;
14638
14791
  const yaw = position.yaw * Math.PI / 180;
14639
- const localUp = new import_three34.Vector3(
14792
+ const localUp = new import_three35.Vector3(
14640
14793
  -Math.sin(pitch) * Math.sin(yaw),
14641
14794
  Math.cos(pitch),
14642
14795
  Math.sin(pitch) * Math.cos(yaw)
14643
14796
  ).normalize();
14644
- return new import_three34.Quaternion().setFromRotationMatrix(
14645
- new import_three34.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14797
+ return new import_three35.Quaternion().setFromRotationMatrix(
14798
+ new import_three35.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14646
14799
  );
14647
14800
  }
14648
14801
  function makeWorldToLocal(center) {
14649
- return new import_three34.Matrix4().compose(
14802
+ return new import_three35.Matrix4().compose(
14650
14803
  panoPositionToVector3(center, POLYGON_RADIUS),
14651
14804
  surfaceQuaternion(center),
14652
- new import_three34.Vector3(1, 1, 1)
14805
+ new import_three35.Vector3(1, 1, 1)
14653
14806
  ).invert();
14654
14807
  }
14655
14808
  function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
@@ -14704,8 +14857,8 @@ function addSubdividedTriangle(positions, indices, a, b, c, worldToLocal, steps)
14704
14857
  }
14705
14858
  function makeFillGeometry(vertices, center) {
14706
14859
  const unwrapped = unwrapPolygonVertices(vertices);
14707
- const contour = unwrapped.map((vertex) => new import_three34.Vector2(vertex.unwrappedYaw, vertex.pitch));
14708
- const triangles = import_three34.ShapeUtils.triangulateShape(contour, []);
14860
+ const contour = unwrapped.map((vertex) => new import_three35.Vector2(vertex.unwrappedYaw, vertex.pitch));
14861
+ const triangles = import_three35.ShapeUtils.triangulateShape(contour, []);
14709
14862
  const positions = [];
14710
14863
  const indices = [];
14711
14864
  const worldToLocal = makeWorldToLocal(center);
@@ -14721,7 +14874,7 @@ function makeFillGeometry(vertices, center) {
14721
14874
  steps
14722
14875
  );
14723
14876
  }
14724
- return new import_three34.BufferGeometry().setAttribute("position", new import_three34.Float32BufferAttribute(positions, 3)).setIndex(indices);
14877
+ return new import_three35.BufferGeometry().setAttribute("position", new import_three35.Float32BufferAttribute(positions, 3)).setIndex(indices);
14725
14878
  }
14726
14879
  function makeStrokePositions(vertices, center) {
14727
14880
  const points = [];
@@ -14851,7 +15004,7 @@ function PolygonHotspot({
14851
15004
  color: fill,
14852
15005
  depthWrite: false,
14853
15006
  opacity: Math.max(0, Math.min(fillOpacity, 1)),
14854
- side: import_three34.DoubleSide,
15007
+ side: import_three35.DoubleSide,
14855
15008
  transparent: true
14856
15009
  }
14857
15010
  ) }),
@@ -14874,7 +15027,7 @@ function PolygonHotspot({
14874
15027
 
14875
15028
  // src/hotspot/polyline-hotspot.tsx
14876
15029
  var import_react50 = require("react");
14877
- var import_three35 = require("three");
15030
+ var import_three36 = require("three");
14878
15031
  var import_jsx_runtime36 = require("react/jsx-runtime");
14879
15032
  var POLYLINE_RADIUS = 990;
14880
15033
  var MAX_SEGMENT_DEGREES = 7;
@@ -14900,29 +15053,29 @@ function unwrapVertices(vertices) {
14900
15053
  function polylineCenter(vertices) {
14901
15054
  const sum = vertices.reduce(
14902
15055
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14903
- new import_three35.Vector3()
15056
+ new import_three36.Vector3()
14904
15057
  );
14905
15058
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14906
15059
  }
14907
15060
  function surfaceQuaternion2(position) {
14908
15061
  const outward = panoPositionToVector3(position).normalize();
14909
15062
  const inward = outward.clone().negate();
14910
- const pitch = import_three35.MathUtils.degToRad(position.pitch);
14911
- const yaw = import_three35.MathUtils.degToRad(position.yaw);
14912
- const localUp = new import_three35.Vector3(
15063
+ const pitch = import_three36.MathUtils.degToRad(position.pitch);
15064
+ const yaw = import_three36.MathUtils.degToRad(position.yaw);
15065
+ const localUp = new import_three36.Vector3(
14913
15066
  -Math.sin(pitch) * Math.sin(yaw),
14914
15067
  Math.cos(pitch),
14915
15068
  Math.sin(pitch) * Math.cos(yaw)
14916
15069
  ).normalize();
14917
- return new import_three35.Quaternion().setFromRotationMatrix(
14918
- new import_three35.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
15070
+ return new import_three36.Quaternion().setFromRotationMatrix(
15071
+ new import_three36.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14919
15072
  );
14920
15073
  }
14921
15074
  function makeWorldToLocal2(center) {
14922
- return new import_three35.Matrix4().compose(
15075
+ return new import_three36.Matrix4().compose(
14923
15076
  panoPositionToVector3(center, POLYLINE_RADIUS),
14924
15077
  surfaceQuaternion2(center),
14925
- new import_three35.Vector3(1, 1, 1)
15078
+ new import_three36.Vector3(1, 1, 1)
14926
15079
  ).invert();
14927
15080
  }
14928
15081
  function subdivisionSteps(vertices) {
@@ -14937,7 +15090,7 @@ function subdivisionSteps(vertices) {
14937
15090
  }
14938
15091
  return Math.min(
14939
15092
  8,
14940
- Math.max(1, Math.ceil(import_three35.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
15093
+ Math.max(1, Math.ceil(import_three36.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
14941
15094
  );
14942
15095
  }
14943
15096
  function makeLinePositions(vertices, center) {
@@ -15702,65 +15855,7 @@ function PanoFilter({
15702
15855
  // src/gyro.tsx
15703
15856
  var import_fiber27 = require("@react-three/fiber");
15704
15857
  var import_react54 = require("react");
15705
-
15706
- // src/gyro-orientation.ts
15707
- var import_three36 = require("three");
15708
- var DEVICE_FORWARD_CORRECTION = new import_three36.Quaternion().setFromAxisAngle(
15709
- new import_three36.Vector3(1, 0, 0),
15710
- -Math.PI / 2
15711
- );
15712
- var SCREEN_AXIS = new import_three36.Vector3(0, 0, 1);
15713
- function getScreenOrientationAngle() {
15714
- if (typeof window === "undefined") {
15715
- return 0;
15716
- }
15717
- const angle = window.screen.orientation?.angle;
15718
- if (Number.isFinite(angle)) {
15719
- return angle;
15720
- }
15721
- const legacyAngle = window.orientation;
15722
- return Number.isFinite(legacyAngle) ? legacyAngle : 0;
15723
- }
15724
- function deviceOrientationToQuaternion(sample, screenOrientation) {
15725
- const alpha = Number.isFinite(sample.compassHeading) ? 360 - sample.compassHeading : sample.alpha;
15726
- const deviceEuler = new import_three36.Euler(
15727
- import_three36.MathUtils.degToRad(sample.beta),
15728
- import_three36.MathUtils.degToRad(alpha),
15729
- import_three36.MathUtils.degToRad(-sample.gamma),
15730
- "YXZ"
15731
- );
15732
- const screenCorrection = new import_three36.Quaternion().setFromAxisAngle(
15733
- SCREEN_AXIS,
15734
- -import_three36.MathUtils.degToRad(screenOrientation)
15735
- );
15736
- return new import_three36.Quaternion().setFromEuler(deviceEuler).multiply(DEVICE_FORWARD_CORRECTION).multiply(screenCorrection).normalize();
15737
- }
15738
- function quaternionToGyroPose(quaternion) {
15739
- const euler = new import_three36.Euler().setFromQuaternion(quaternion, "YXZ");
15740
- return {
15741
- yaw: import_three36.MathUtils.radToDeg(-euler.y),
15742
- pitch: import_three36.MathUtils.radToDeg(euler.x),
15743
- roll: import_three36.MathUtils.radToDeg(euler.z)
15744
- };
15745
- }
15746
- function createRelativeCalibration(deviceQuaternion, yaw, pitch) {
15747
- const targetQuaternion = new import_three36.Quaternion().setFromEuler(
15748
- new import_three36.Euler(
15749
- import_three36.MathUtils.degToRad(pitch),
15750
- import_three36.MathUtils.degToRad(-yaw),
15751
- 0,
15752
- "YXZ"
15753
- )
15754
- );
15755
- return targetQuaternion.multiply(deviceQuaternion.clone().invert()).normalize();
15756
- }
15757
- function applyGyroCalibration(deviceQuaternion, calibration) {
15758
- return quaternionToGyroPose(
15759
- calibration.clone().multiply(deviceQuaternion).normalize()
15760
- );
15761
- }
15762
-
15763
- // src/gyro.tsx
15858
+ var import_three37 = require("three");
15764
15859
  var deviceOrientationPermissionState = "unknown";
15765
15860
  function isMobileDevice() {
15766
15861
  if (typeof navigator === "undefined") {
@@ -15768,12 +15863,6 @@ function isMobileDevice() {
15768
15863
  }
15769
15864
  return /Android|iPad|iPhone|iPod|Mobile/i.test(navigator.userAgent) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
15770
15865
  }
15771
- function normalizeYaw2(value) {
15772
- return ((value + 180) % 360 + 360) % 360 - 180;
15773
- }
15774
- function shortestYawDelta2(from, to) {
15775
- return normalizeYaw2(to - from);
15776
- }
15777
15866
  function finiteOr(value, fallback) {
15778
15867
  return Number.isFinite(value) ? value : fallback;
15779
15868
  }
@@ -15783,9 +15872,6 @@ function resolveFriction(value) {
15783
15872
  function resolveSoftstart(value) {
15784
15873
  return Math.max(finiteOr(value, 0.5), 0);
15785
15874
  }
15786
- function posesNearlyEqual(a, b) {
15787
- return Math.abs(shortestYawDelta2(a.yaw, b.yaw)) < 1e-4 && Math.abs(a.pitch - b.pitch) < 1e-4 && Math.abs(a.roll - b.roll) < 1e-4;
15788
- }
15789
15875
  var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15790
15876
  enabled = false,
15791
15877
  camroll = true,
@@ -15805,19 +15891,30 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15805
15891
  const eventBus = (0, import_react54.useContext)(PanoEventBusContext);
15806
15892
  const { gl } = (0, import_fiber27.useThree)();
15807
15893
  const [internallyDisabled, setInternallyDisabled] = (0, import_react54.useState)(false);
15894
+ const [available, setAvailableState] = (0, import_react54.useState)(false);
15808
15895
  const availableRef = (0, import_react54.useRef)(false);
15809
15896
  const availabilityReportedRef = (0, import_react54.useRef)(null);
15810
15897
  const activeRef = (0, import_react54.useRef)(false);
15811
15898
  const permissionRef = (0, import_react54.useRef)(deviceOrientationPermissionState);
15812
15899
  const absoluteEventSourceRef = (0, import_react54.useRef)(null);
15813
- const rawQuaternionRef = (0, import_react54.useRef)(null);
15814
- const calibrationRef = (0, import_react54.useRef)(null);
15900
+ const rawQuaternionRef = (0, import_react54.useRef)(new import_three37.Quaternion());
15901
+ const hasRawQuaternionRef = (0, import_react54.useRef)(false);
15902
+ const calibrationRef = (0, import_react54.useRef)(new import_three37.Quaternion());
15903
+ const hasCalibrationRef = (0, import_react54.useRef)(false);
15904
+ const calibratedQuaternionRef = (0, import_react54.useRef)(new import_three37.Quaternion());
15815
15905
  const absoluteOffsetRef = (0, import_react54.useRef)({ yaw: 0, pitch: 0 });
15816
15906
  const screenAngleRef = (0, import_react54.useRef)(getScreenOrientationAngle());
15817
15907
  const startPoseRef = (0, import_react54.useRef)(null);
15818
15908
  const enabledAtRef = (0, import_react54.useRef)(0);
15819
15909
  const filteredPoseRef = (0, import_react54.useRef)(null);
15820
15910
  const lastAppliedPoseRef = (0, import_react54.useRef)(null);
15911
+ const lastSamplePoseRef = (0, import_react54.useRef)(null);
15912
+ const lastSampleAtRef = (0, import_react54.useRef)(null);
15913
+ const previousYawRef = (0, import_react54.useRef)(void 0);
15914
+ const absoluteRef = (0, import_react54.useRef)(absolute);
15915
+ const northRef = (0, import_react54.useRef)(north);
15916
+ absoluteRef.current = absolute;
15917
+ northRef.current = north;
15821
15918
  const callbacksRef = (0, import_react54.useRef)({
15822
15919
  onAvailable,
15823
15920
  onUnavailable,
@@ -15863,13 +15960,14 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15863
15960
  [eventBus]
15864
15961
  );
15865
15962
  const setAvailable = (0, import_react54.useCallback)(
15866
- (available) => {
15867
- availableRef.current = available;
15868
- if (availabilityReportedRef.current === available) {
15963
+ (nextAvailable) => {
15964
+ availableRef.current = nextAvailable;
15965
+ setAvailableState(nextAvailable);
15966
+ if (availabilityReportedRef.current === nextAvailable) {
15869
15967
  return;
15870
15968
  }
15871
- availabilityReportedRef.current = available;
15872
- emit(available ? "gyroavailable" : "gyrounavailable");
15969
+ availabilityReportedRef.current = nextAvailable;
15970
+ emit(nextAvailable ? "gyroavailable" : "gyrounavailable");
15873
15971
  },
15874
15972
  [emit]
15875
15973
  );
@@ -15912,37 +16010,54 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15912
16010
  controlsRef.current?.setGyroActive(false);
15913
16011
  emit("gyrodisable");
15914
16012
  }
15915
- rawQuaternionRef.current = null;
16013
+ hasRawQuaternionRef.current = false;
15916
16014
  absoluteEventSourceRef.current = null;
15917
- calibrationRef.current = null;
16015
+ hasCalibrationRef.current = false;
15918
16016
  filteredPoseRef.current = null;
15919
16017
  lastAppliedPoseRef.current = null;
16018
+ lastSamplePoseRef.current = null;
16019
+ lastSampleAtRef.current = null;
16020
+ previousYawRef.current = void 0;
15920
16021
  }, [controlsRef, emit]);
15921
- const resetSensor = (0, import_react54.useCallback)(
16022
+ const anchorToView = (0, import_react54.useCallback)(
15922
16023
  (yaw, pitch) => {
15923
- const rawQuaternion = rawQuaternionRef.current;
15924
- if (!rawQuaternion) {
16024
+ if (!hasRawQuaternionRef.current) {
15925
16025
  return;
15926
16026
  }
15927
- const view = controlsRef.current?.getTargetView();
15928
- const targetYaw = finiteOr(yaw, view?.yaw ?? 0);
15929
- const targetPitch = finiteOr(pitch, view?.pitch ?? 0);
15930
- if (absolute) {
15931
- const rawPose = quaternionToGyroPose(rawQuaternion);
16027
+ if (absoluteRef.current) {
16028
+ const rawPose = quaternionToGyroPose(
16029
+ rawQuaternionRef.current,
16030
+ previousYawRef.current
16031
+ );
16032
+ previousYawRef.current = rawPose.yaw;
15932
16033
  absoluteOffsetRef.current = {
15933
- yaw: shortestYawDelta2(
15934
- rawPose.yaw + finiteOr(north, 0),
15935
- targetYaw
16034
+ yaw: shortestGyroYawDelta(
16035
+ rawPose.yaw + finiteOr(northRef.current, 0),
16036
+ yaw
15936
16037
  ),
15937
- pitch: targetPitch - rawPose.pitch
16038
+ pitch: pitch - rawPose.pitch
15938
16039
  };
15939
16040
  } else {
15940
- calibrationRef.current = createRelativeCalibration(
15941
- rawQuaternion,
15942
- targetYaw,
15943
- targetPitch
16041
+ createRelativeCalibration(
16042
+ rawQuaternionRef.current,
16043
+ yaw,
16044
+ pitch,
16045
+ calibrationRef.current
15944
16046
  );
16047
+ hasCalibrationRef.current = true;
15945
16048
  }
16049
+ },
16050
+ []
16051
+ );
16052
+ const resetSensor = (0, import_react54.useCallback)(
16053
+ (yaw, pitch) => {
16054
+ if (!hasRawQuaternionRef.current) {
16055
+ return;
16056
+ }
16057
+ const view = controlsRef.current?.getTargetView();
16058
+ const targetYaw = finiteOr(yaw, view?.yaw ?? 0);
16059
+ const targetPitch = finiteOr(pitch, view?.pitch ?? 0);
16060
+ anchorToView(targetYaw, targetPitch);
15946
16061
  startPoseRef.current = {
15947
16062
  yaw: targetYaw,
15948
16063
  pitch: targetPitch,
@@ -15950,8 +16065,10 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15950
16065
  };
15951
16066
  enabledAtRef.current = performance.now();
15952
16067
  filteredPoseRef.current = null;
16068
+ lastSamplePoseRef.current = null;
16069
+ lastSampleAtRef.current = null;
15953
16070
  },
15954
- [absolute, controlsRef, north]
16071
+ [anchorToView, controlsRef]
15955
16072
  );
15956
16073
  (0, import_react54.useImperativeHandle)(
15957
16074
  ref,
@@ -15971,9 +16088,6 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15971
16088
  (0, import_react54.useEffect)(() => {
15972
16089
  const supported = typeof window !== "undefined" && window.isSecureContext && typeof DeviceOrientationEvent !== "undefined" && (desktopSupport || isMobileDevice());
15973
16090
  setAvailable(supported);
15974
- return () => {
15975
- availableRef.current = false;
15976
- };
15977
16091
  }, [desktopSupport, setAvailable]);
15978
16092
  (0, import_react54.useEffect)(() => {
15979
16093
  controlsRef.current?.setGyroTouchMode(touchMode);
@@ -15993,7 +16107,7 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15993
16107
  };
15994
16108
  }, [enabled, gl, internallyDisabled, touchMode]);
15995
16109
  (0, import_react54.useEffect)(() => {
15996
- if (!enabled || internallyDisabled || !availableRef.current) {
16110
+ if (!enabled || internallyDisabled || !available) {
15997
16111
  deactivate();
15998
16112
  return;
15999
16113
  }
@@ -16022,10 +16136,12 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16022
16136
  gamma: event.gamma,
16023
16137
  compassHeading: absolute && hasCompassHeading ? compassEvent.webkitCompassHeading : void 0
16024
16138
  };
16025
- rawQuaternionRef.current = deviceOrientationToQuaternion(
16139
+ deviceOrientationToQuaternion(
16026
16140
  sample,
16027
- screenAngleRef.current
16141
+ screenAngleRef.current,
16142
+ rawQuaternionRef.current
16028
16143
  );
16144
+ hasRawQuaternionRef.current = true;
16029
16145
  if (!activeRef.current) {
16030
16146
  const view = controlsRef.current?.getTargetView() ?? {
16031
16147
  yaw: 0,
@@ -16033,11 +16149,13 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16033
16149
  fov: 75
16034
16150
  };
16035
16151
  if (!absolute) {
16036
- calibrationRef.current = createRelativeCalibration(
16152
+ createRelativeCalibration(
16037
16153
  rawQuaternionRef.current,
16038
16154
  view.yaw,
16039
- view.pitch
16155
+ view.pitch,
16156
+ calibrationRef.current
16040
16157
  );
16158
+ hasCalibrationRef.current = true;
16041
16159
  }
16042
16160
  absoluteOffsetRef.current = { yaw: 0, pitch: 0 };
16043
16161
  startPoseRef.current = { ...view, roll: 0 };
@@ -16085,6 +16203,7 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16085
16203
  };
16086
16204
  }, [
16087
16205
  absolute,
16206
+ available,
16088
16207
  controlsRef,
16089
16208
  deactivate,
16090
16209
  emit,
@@ -16093,28 +16212,84 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16093
16212
  requestPermission
16094
16213
  ]);
16095
16214
  (0, import_fiber27.useFrame)((_, deltaSeconds) => {
16096
- const rawQuaternion = rawQuaternionRef.current;
16097
- if (!activeRef.current || !rawQuaternion) {
16215
+ if (!activeRef.current || !hasRawQuaternionRef.current) {
16098
16216
  return;
16099
16217
  }
16100
16218
  let targetPose;
16101
16219
  if (absolute) {
16102
- const rawPose = quaternionToGyroPose(rawQuaternion);
16220
+ const rawPose = quaternionToGyroPose(
16221
+ rawQuaternionRef.current,
16222
+ previousYawRef.current
16223
+ );
16224
+ previousYawRef.current = rawPose.yaw;
16103
16225
  targetPose = {
16104
16226
  yaw: rawPose.yaw + finiteOr(north, 0) + absoluteOffsetRef.current.yaw,
16105
16227
  pitch: rawPose.pitch + absoluteOffsetRef.current.pitch,
16106
16228
  roll: rawPose.roll
16107
16229
  };
16108
16230
  } else {
16109
- const calibration = calibrationRef.current;
16110
- if (!calibration) {
16231
+ if (!hasCalibrationRef.current) {
16111
16232
  return;
16112
16233
  }
16113
- targetPose = applyGyroCalibration(rawQuaternion, calibration);
16234
+ targetPose = applyGyroCalibration(
16235
+ rawQuaternionRef.current,
16236
+ calibrationRef.current,
16237
+ calibratedQuaternionRef.current,
16238
+ previousYawRef.current
16239
+ );
16240
+ previousYawRef.current = targetPose.yaw;
16114
16241
  }
16115
16242
  if (!camroll) {
16116
16243
  targetPose.roll = 0;
16117
16244
  }
16245
+ const sampleAt = performance.now();
16246
+ const previousSample = lastSamplePoseRef.current;
16247
+ const previousSampleAt = lastSampleAtRef.current;
16248
+ if (previousSample && previousSampleAt !== null) {
16249
+ const angleDelta = gyroPoseAngleDelta(previousSample, targetPose);
16250
+ const sampleDeltaSeconds = Math.max(
16251
+ (sampleAt - previousSampleAt) / 1e3,
16252
+ deltaSeconds
16253
+ );
16254
+ if (shouldReanchorGyro(angleDelta, sampleDeltaSeconds)) {
16255
+ const view = controlsRef.current?.getTargetView() ?? {
16256
+ yaw: targetPose.yaw,
16257
+ pitch: targetPose.pitch,
16258
+ fov: 75
16259
+ };
16260
+ anchorToView(view.yaw, view.pitch);
16261
+ if (absolute) {
16262
+ const rawPose = quaternionToGyroPose(
16263
+ rawQuaternionRef.current,
16264
+ previousYawRef.current
16265
+ );
16266
+ previousYawRef.current = rawPose.yaw;
16267
+ targetPose = {
16268
+ yaw: rawPose.yaw + finiteOr(north, 0) + absoluteOffsetRef.current.yaw,
16269
+ pitch: rawPose.pitch + absoluteOffsetRef.current.pitch,
16270
+ roll: rawPose.roll
16271
+ };
16272
+ } else {
16273
+ targetPose = applyGyroCalibration(
16274
+ rawQuaternionRef.current,
16275
+ calibrationRef.current,
16276
+ calibratedQuaternionRef.current,
16277
+ previousYawRef.current
16278
+ );
16279
+ previousYawRef.current = targetPose.yaw;
16280
+ }
16281
+ if (!camroll) {
16282
+ targetPose.roll = 0;
16283
+ }
16284
+ filteredPoseRef.current = {
16285
+ yaw: view.yaw,
16286
+ pitch: view.pitch,
16287
+ roll: targetPose.roll
16288
+ };
16289
+ }
16290
+ }
16291
+ lastSamplePoseRef.current = { ...targetPose };
16292
+ lastSampleAtRef.current = sampleAt;
16118
16293
  const softstartMs = resolveSoftstart(softstart) * 1e3;
16119
16294
  const startPose = startPoseRef.current;
16120
16295
  if (startPose && softstartMs > 0) {
@@ -16123,9 +16298,9 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16123
16298
  1
16124
16299
  );
16125
16300
  targetPose = {
16126
- yaw: startPose.yaw + shortestYawDelta2(startPose.yaw, targetPose.yaw) * progress,
16301
+ yaw: startPose.yaw + shortestGyroYawDelta(startPose.yaw, targetPose.yaw) * progress,
16127
16302
  pitch: startPose.pitch + (targetPose.pitch - startPose.pitch) * progress,
16128
- roll: startPose.roll + shortestYawDelta2(startPose.roll, targetPose.roll) * progress
16303
+ roll: startPose.roll + shortestGyroYawDelta(startPose.roll, targetPose.roll) * progress
16129
16304
  };
16130
16305
  if (progress === 1) {
16131
16306
  startPoseRef.current = null;
@@ -16135,9 +16310,9 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16135
16310
  const retention = resolveFriction(friction);
16136
16311
  const follow = retention === 0 ? 1 : 1 - Math.pow(retention, deltaSeconds * 60);
16137
16312
  const filteredPose = previous ? {
16138
- yaw: previous.yaw + shortestYawDelta2(previous.yaw, targetPose.yaw) * follow,
16313
+ yaw: previous.yaw + shortestGyroYawDelta(previous.yaw, targetPose.yaw) * follow,
16139
16314
  pitch: previous.pitch + (targetPose.pitch - previous.pitch) * follow,
16140
- roll: previous.roll + shortestYawDelta2(previous.roll, targetPose.roll) * follow
16315
+ roll: previous.roll + shortestGyroYawDelta(previous.roll, targetPose.roll) * follow
16141
16316
  } : targetPose;
16142
16317
  filteredPoseRef.current = filteredPose;
16143
16318
  if (controlsRef.current?.isInteractionLocked()) {
@@ -16148,7 +16323,7 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16148
16323
  lastAppliedPoseRef.current = { ...filteredPose };
16149
16324
  controlsRef.current?.setGyroPose(filteredPose);
16150
16325
  }
16151
- });
16326
+ }, -1);
16152
16327
  return null;
16153
16328
  });
16154
16329
 
@@ -16178,9 +16353,9 @@ async function detectWebVRCapabilities() {
16178
16353
  // src/webvr/reticle.tsx
16179
16354
  var import_fiber28 = require("@react-three/fiber");
16180
16355
  var import_react55 = require("react");
16181
- var import_three37 = require("three");
16356
+ var import_three38 = require("three");
16182
16357
  var import_jsx_runtime38 = require("react/jsx-runtime");
16183
- var CENTER_NDC = new import_three37.Vector2(0, 0);
16358
+ var CENTER_NDC = new import_three38.Vector2(0, 0);
16184
16359
  var HUD_DISTANCE = 2;
16185
16360
  var RETICLE_SCALE = 1;
16186
16361
  var RETICLE_RENDER_ORDER = 1e5;
@@ -16265,8 +16440,8 @@ function WebVRReticle({
16265
16440
  }) {
16266
16441
  const groupRef = (0, import_react55.useRef)(null);
16267
16442
  const ringMeshRef = (0, import_react55.useRef)(null);
16268
- const directionRef = (0, import_react55.useRef)(new import_three37.Vector3());
16269
- const raycasterRef = (0, import_react55.useRef)(new import_three37.Raycaster());
16443
+ const directionRef = (0, import_react55.useRef)(new import_three38.Vector3());
16444
+ const raycasterRef = (0, import_react55.useRef)(new import_three38.Raycaster());
16270
16445
  const hoveredRef = (0, import_react55.useRef)(null);
16271
16446
  const dwellRef = (0, import_react55.useRef)(0);
16272
16447
  const clickedRef = (0, import_react55.useRef)(false);
@@ -16417,7 +16592,7 @@ function WebVRReticle({
16417
16592
  color: "#ffffff",
16418
16593
  depthTest: false,
16419
16594
  depthWrite: false,
16420
- side: import_three37.DoubleSide,
16595
+ side: import_three38.DoubleSide,
16421
16596
  toneMapped: false,
16422
16597
  transparent: true
16423
16598
  }
@@ -16433,7 +16608,7 @@ function WebVRReticle({
16433
16608
  // src/webvr/stereo.tsx
16434
16609
  var import_fiber29 = require("@react-three/fiber");
16435
16610
  var import_react56 = require("react");
16436
- var import_three38 = require("three");
16611
+ var import_three39 = require("three");
16437
16612
  var vertexShader = `
16438
16613
  varying vec2 vUv;
16439
16614
  void main() {
@@ -16458,26 +16633,26 @@ void main() {
16458
16633
  }
16459
16634
  `;
16460
16635
  function createDistortionResources() {
16461
- const target = new import_three38.WebGLRenderTarget(1, 1, {
16636
+ const target = new import_three39.WebGLRenderTarget(1, 1, {
16462
16637
  depthBuffer: true,
16463
16638
  stencilBuffer: false
16464
16639
  });
16465
- const geometry = new import_three38.PlaneGeometry(2, 2);
16466
- const material = new import_three38.ShaderMaterial({
16640
+ const geometry = new import_three39.PlaneGeometry(2, 2);
16641
+ const material = new import_three39.ShaderMaterial({
16467
16642
  depthTest: false,
16468
16643
  depthWrite: false,
16469
16644
  fragmentShader,
16470
16645
  uniforms: {
16471
- distortion: { value: new import_three38.Vector2() },
16646
+ distortion: { value: new import_three39.Vector2() },
16472
16647
  sourceTexture: { value: target.texture }
16473
16648
  },
16474
16649
  vertexShader
16475
16650
  });
16476
- const mesh = new import_three38.Mesh(geometry, material);
16477
- const scene = new import_three38.Scene();
16651
+ const mesh = new import_three39.Mesh(geometry, material);
16652
+ const scene = new import_three39.Scene();
16478
16653
  scene.add(mesh);
16479
16654
  return {
16480
- camera: new import_three38.OrthographicCamera(-1, 1, 1, -1, 0, 1),
16655
+ camera: new import_three39.OrthographicCamera(-1, 1, 1, -1, 0, 1),
16481
16656
  geometry,
16482
16657
  material,
16483
16658
  mesh,
@@ -16510,15 +16685,15 @@ function WebVRStereoRenderer({
16510
16685
  const runtime = (0, import_react56.useContext)(WebVRRuntimeContext);
16511
16686
  const fallbackStereoRef = (0, import_react56.useRef)(null);
16512
16687
  if (!fallbackStereoRef.current) {
16513
- fallbackStereoRef.current = new import_three38.StereoCamera();
16688
+ fallbackStereoRef.current = new import_three39.StereoCamera();
16514
16689
  }
16515
16690
  const stereo = runtime?.stereoView.stereo ?? fallbackStereoRef.current;
16516
16691
  const stereoRef = (0, import_react56.useRef)(stereo);
16517
16692
  stereoRef.current = stereo;
16518
16693
  const resources = (0, import_react56.useMemo)(createDistortionResources, []);
16519
- const drawingSizeRef = (0, import_react56.useRef)(new import_three38.Vector2());
16520
- const viewportRef = (0, import_react56.useRef)(new import_three38.Vector4());
16521
- const scissorRef = (0, import_react56.useRef)(new import_three38.Vector4());
16694
+ const drawingSizeRef = (0, import_react56.useRef)(new import_three39.Vector2());
16695
+ const viewportRef = (0, import_react56.useRef)(new import_three39.Vector4());
16696
+ const scissorRef = (0, import_react56.useRef)(new import_three39.Vector4());
16522
16697
  const originalFovRef = (0, import_react56.useRef)(null);
16523
16698
  const stereoActiveRef = (0, import_react56.useRef)(false);
16524
16699
  const profileRef = (0, import_react56.useRef)(profile);
@@ -16536,7 +16711,7 @@ function WebVRStereoRenderer({
16536
16711
  (0, import_react56.useEffect)(() => {
16537
16712
  const originalRender = gl.render.bind(gl);
16538
16713
  gl.render = (sceneToRender, cameraToRender) => {
16539
- if (!stereoActiveRef.current || !(cameraToRender instanceof import_three38.PerspectiveCamera)) {
16714
+ if (!stereoActiveRef.current || !(cameraToRender instanceof import_three39.PerspectiveCamera)) {
16540
16715
  originalRender(sceneToRender, cameraToRender);
16541
16716
  return;
16542
16717
  }
@@ -16611,7 +16786,7 @@ function WebVRStereoRenderer({
16611
16786
  if (runtime) {
16612
16787
  runtime.stereoView.active = fallback;
16613
16788
  }
16614
- if (fallback && camera instanceof import_three38.PerspectiveCamera) {
16789
+ if (fallback && camera instanceof import_three39.PerspectiveCamera) {
16615
16790
  syncStereoCameras(
16616
16791
  stereoRef.current,
16617
16792
  camera,
@@ -16622,7 +16797,7 @@ function WebVRStereoRenderer({
16622
16797
  );
16623
16798
  return;
16624
16799
  }
16625
- if (originalFovRef.current !== null && camera instanceof import_three38.PerspectiveCamera) {
16800
+ if (originalFovRef.current !== null && camera instanceof import_three39.PerspectiveCamera) {
16626
16801
  camera.fov = originalFovRef.current;
16627
16802
  camera.updateProjectionMatrix();
16628
16803
  originalFovRef.current = null;
@@ -17304,7 +17479,7 @@ function usePanoViewer() {
17304
17479
  // src/video/pano-video.tsx
17305
17480
  var import_fiber31 = require("@react-three/fiber");
17306
17481
  var import_react61 = require("react");
17307
- var import_three39 = require("three");
17482
+ var import_three40 = require("three");
17308
17483
  var import_jsx_runtime40 = require("react/jsx-runtime");
17309
17484
  var EMPTY_TRACKS = [];
17310
17485
  var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
@@ -17381,8 +17556,8 @@ function findTextTrack(video, tracks, trackId) {
17381
17556
  return list.length > 0 ? list[0] : null;
17382
17557
  }
17383
17558
  function applyEquirectangularLayout(texture, anisotropy) {
17384
- texture.colorSpace = import_three39.SRGBColorSpace;
17385
- texture.wrapS = import_three39.RepeatWrapping;
17559
+ texture.colorSpace = import_three40.SRGBColorSpace;
17560
+ texture.wrapS = import_three40.RepeatWrapping;
17386
17561
  texture.repeat.x = -1;
17387
17562
  texture.offset.x = 1;
17388
17563
  texture.anisotropy = anisotropy;
@@ -17401,7 +17576,7 @@ function usePosterTexture2(poster, onError) {
17401
17576
  active = false;
17402
17577
  };
17403
17578
  }
17404
- const loader = new import_three39.TextureLoader();
17579
+ const loader = new import_three40.TextureLoader();
17405
17580
  loader.load(
17406
17581
  poster,
17407
17582
  (loadedTexture) => {
@@ -17413,9 +17588,9 @@ function usePosterTexture2(poster, onError) {
17413
17588
  loadedTexture,
17414
17589
  gl.capabilities.getMaxAnisotropy()
17415
17590
  );
17416
- loadedTexture.wrapT = import_three39.RepeatWrapping;
17417
- loadedTexture.magFilter = import_three39.LinearFilter;
17418
- loadedTexture.minFilter = import_three39.LinearMipmapLinearFilter;
17591
+ loadedTexture.wrapT = import_three40.RepeatWrapping;
17592
+ loadedTexture.magFilter = import_three40.LinearFilter;
17593
+ loadedTexture.minFilter = import_three40.LinearMipmapLinearFilter;
17419
17594
  loadedTexture.generateMipmaps = true;
17420
17595
  setTexture(loadedTexture);
17421
17596
  },
@@ -17569,10 +17744,10 @@ function PanoVideo({
17569
17744
  video.muted = true;
17570
17745
  applyInlineVideoPlayback(video, true);
17571
17746
  video.preload = "metadata";
17572
- const texture = new import_three39.VideoTexture(video);
17747
+ const texture = new import_three40.VideoTexture(video);
17573
17748
  applyEquirectangularLayout(texture, 1);
17574
- texture.magFilter = import_three39.LinearFilter;
17575
- texture.minFilter = import_three39.LinearFilter;
17749
+ texture.magFilter = import_three40.LinearFilter;
17750
+ texture.minFilter = import_three40.LinearFilter;
17576
17751
  texture.generateMipmaps = false;
17577
17752
  return { video, texture };
17578
17753
  }, []);
@@ -18008,7 +18183,7 @@ function PanoVideo({
18008
18183
  activeTexture ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
18009
18184
  "mesh",
18010
18185
  {
18011
- rotation: [0, import_three39.MathUtils.degToRad(90 + yawOffset2), 0],
18186
+ rotation: [0, import_three40.MathUtils.degToRad(90 + yawOffset2), 0],
18012
18187
  visible,
18013
18188
  children: [
18014
18189
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
@@ -18016,7 +18191,7 @@ function PanoVideo({
18016
18191
  PanoBasicMaterial,
18017
18192
  {
18018
18193
  map: activeTexture,
18019
- side: import_three39.BackSide,
18194
+ side: import_three40.BackSide,
18020
18195
  toneMapped: false
18021
18196
  }
18022
18197
  )