@ericchen1990/pano-view 3.6.5 → 3.6.7

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;
@@ -11585,7 +11737,7 @@ var import_react40 = require("react");
11585
11737
  var import_fiber19 = require("@react-three/fiber");
11586
11738
  var import_react39 = require("react");
11587
11739
  var import_client = require("react-dom/client");
11588
- var import_three21 = require("three");
11740
+ var import_three22 = require("three");
11589
11741
  var import_jsx_runtime23 = require("react/jsx-runtime");
11590
11742
  function useFallbackStereoView() {
11591
11743
  const runtime = (0, import_react39.useContext)(WebVRRuntimeContext);
@@ -11608,7 +11760,7 @@ function ProjectedHtml({
11608
11760
  const { camera, gl, events, size } = (0, import_fiber19.useThree)();
11609
11761
  const group = (0, import_react39.useRef)(null);
11610
11762
  const overlay = (0, import_react39.useRef)(null);
11611
- const scratch = (0, import_react39.useRef)(new import_three21.Vector3());
11763
+ const scratch = (0, import_react39.useRef)(new import_three22.Vector3());
11612
11764
  const target = events.connected || gl.domElement.parentElement;
11613
11765
  const updatePosition = () => {
11614
11766
  const anchor = group.current;
@@ -11808,18 +11960,18 @@ function HotspotTooltip({
11808
11960
  }
11809
11961
 
11810
11962
  // src/hotspot/transform.ts
11811
- var import_three22 = require("three");
11812
- var LOCAL_FORWARD = new import_three22.Vector3(0, 0, 1);
11813
- 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();
11814
11966
  function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight, distance) {
11815
11967
  if (orientation2 === "billboard") {
11816
11968
  group.quaternion.copy(camera.quaternion);
11817
11969
  } else {
11818
11970
  group.quaternion.copy(surfaceQuaternion3);
11819
11971
  }
11820
- group.rotateOnAxis(LOCAL_FORWARD, import_three22.MathUtils.degToRad(-rotation));
11821
- let scaleFactor = scaleMode === "fixed" && camera instanceof import_three22.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
11822
- 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) {
11823
11975
  group.updateWorldMatrix(true, false);
11824
11976
  CAMERA_POSITION.setFromMatrixPosition(group.matrixWorld).applyMatrix4(
11825
11977
  camera.matrixWorldInverse
@@ -11834,15 +11986,15 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
11834
11986
  group.updateMatrixWorld();
11835
11987
  }
11836
11988
  function fixedScaleFactor(cameraFov, referenceFov) {
11837
- const safeReferenceFov = import_three22.MathUtils.clamp(referenceFov, 1, 179);
11838
- 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);
11839
11991
  }
11840
11992
  function selectionFrameScale(worldScaleX, worldScaleY, cameraSpaceDepth, fovDegrees, viewportHeight, outsetPixels) {
11841
11993
  const pixels = Number.isFinite(outsetPixels) && outsetPixels > 0 ? outsetPixels : 0;
11842
11994
  const depth = Number.isFinite(cameraSpaceDepth) ? Math.max(cameraSpaceDepth, 1e-4) : 1e-4;
11843
11995
  const height = Number.isFinite(viewportHeight) ? Math.max(viewportHeight, 1) : 1;
11844
- const fov = Number.isFinite(fovDegrees) ? import_three22.MathUtils.clamp(fovDegrees, 1, 179) : 75;
11845
- 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);
11846
11998
  const axis = (worldScale) => {
11847
11999
  const pixelsPerLocalUnit = pixelsPerWorldUnit * Math.abs(worldScale);
11848
12000
  if (pixelsPerLocalUnit < 1e-4) {
@@ -11857,9 +12009,9 @@ function selectionFrameScale(worldScaleX, worldScaleY, cameraSpaceDepth, fovDegr
11857
12009
  var import_drei = require("@react-three/drei");
11858
12010
  var import_fiber20 = require("@react-three/fiber");
11859
12011
  var import_react41 = require("react");
11860
- var import_three23 = require("three");
12012
+ var import_three24 = require("three");
11861
12013
  var import_jsx_runtime25 = require("react/jsx-runtime");
11862
- var LINE_WORLD_POSITION = new import_three23.Vector3();
12014
+ var LINE_WORLD_POSITION = new import_three24.Vector3();
11863
12015
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
11864
12016
  const material = object?.material;
11865
12017
  if (!object || typeof material?.dashScale !== "number") {
@@ -11867,8 +12019,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
11867
12019
  }
11868
12020
  object.getWorldPosition(LINE_WORLD_POSITION);
11869
12021
  const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
11870
- const fov = camera instanceof import_three23.PerspectiveCamera ? camera.fov : 75;
11871
- 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);
11872
12024
  }
11873
12025
  function resolveDash(dashSize, gapSize) {
11874
12026
  if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
@@ -11937,8 +12089,8 @@ var DRAG_EPSILON_DEGREES = 1e-3;
11937
12089
  var SELECTION_BORDER_WIDTH = 3;
11938
12090
  var SELECTION_BORDER_GAP = 3;
11939
12091
  var SELECTION_BORDER_OUTSET = SELECTION_BORDER_GAP + SELECTION_BORDER_WIDTH / 2;
11940
- var SELECTION_CAMERA_POSITION = new import_three24.Vector3();
11941
- 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();
11942
12094
  var SELECTION_BORDER_POINTS = [
11943
12095
  [-0.5, -0.5, 1e-3],
11944
12096
  [0.5, -0.5, 1e-3],
@@ -11946,27 +12098,27 @@ var SELECTION_BORDER_POINTS = [
11946
12098
  [-0.5, 0.5, 1e-3],
11947
12099
  [-0.5, -0.5, 1e-3]
11948
12100
  ];
11949
- var TOOLTIP_WORLD_BOX = new import_three24.Box3();
11950
- var TOOLTIP_LOCAL_BOX = new import_three24.Box3();
11951
- var TOOLTIP_CORNER = new import_three24.Vector3();
11952
- var TOOLTIP_INVERSE = new import_three24.Matrix4();
11953
- var TOOLTIP_WORLD_CORNER = new import_three24.Vector3();
11954
- var TOOLTIP_PROJECTED = new import_three24.Vector3();
11955
- var TOOLTIP_RAY_ORIGIN = new import_three24.Vector3();
11956
- var TOOLTIP_RAY_FAR = new import_three24.Vector3();
11957
- var TOOLTIP_RAY_DIRECTION = new import_three24.Vector3();
11958
- var TOOLTIP_RAY = new import_three24.Ray();
11959
- var TOOLTIP_PLANE = new import_three24.Plane();
11960
- var TOOLTIP_INTERSECTION = new import_three24.Vector3();
11961
- var TOOLTIP_PLANE_NORMAL = new import_three24.Vector3();
11962
- 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();
11963
12115
  var HOTSPOT_MODE_RENDERING = {
11964
12116
  surface: { orientation: "surface", placement: "surface" },
11965
12117
  billboard: { orientation: "billboard", placement: "floating" }
11966
12118
  };
11967
12119
  function angularSizeToWorldSize(size, radius) {
11968
- const safeSize = Number.isFinite(size) ? import_three24.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
11969
- 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);
11970
12122
  }
11971
12123
  function resolveScale(scale) {
11972
12124
  return Number.isFinite(scale) && scale > 0 ? scale : 1;
@@ -11979,39 +12131,39 @@ function resolveDistance(placement, distance, width, height) {
11979
12131
  if (!Number.isFinite(distance)) {
11980
12132
  return DEFAULT_FLOATING_DISTANCE;
11981
12133
  }
11982
- return import_three24.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
12134
+ return import_three25.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
11983
12135
  }
11984
12136
  function maximumHotspotDistance(width, height) {
11985
- const safeWidth = import_three24.MathUtils.clamp(
12137
+ const safeWidth = import_three25.MathUtils.clamp(
11986
12138
  Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
11987
12139
  MIN_ANGULAR_SIZE,
11988
12140
  MAX_ANGULAR_SIZE
11989
12141
  );
11990
- const safeHeight = import_three24.MathUtils.clamp(
12142
+ const safeHeight = import_three25.MathUtils.clamp(
11991
12143
  Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
11992
12144
  MIN_ANGULAR_SIZE,
11993
12145
  MAX_ANGULAR_SIZE
11994
12146
  );
11995
12147
  const cornerFactor = Math.hypot(
11996
12148
  1,
11997
- Math.tan(import_three24.MathUtils.degToRad(safeWidth) / 2),
11998
- 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)
11999
12151
  );
12000
12152
  return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
12001
12153
  }
12002
12154
  function createSurfaceQuaternion(position) {
12003
12155
  const outward = panoPositionToVector3(position).normalize();
12004
12156
  const inward = outward.clone().negate();
12005
- const pitch = import_three24.MathUtils.degToRad(position.pitch);
12006
- const yaw = import_three24.MathUtils.degToRad(position.yaw);
12007
- 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(
12008
12160
  -Math.sin(pitch) * Math.sin(yaw),
12009
12161
  Math.cos(pitch),
12010
12162
  Math.sin(pitch) * Math.cos(yaw)
12011
12163
  ).normalize();
12012
12164
  const localRight = localUp.clone().cross(inward).normalize();
12013
- const basis = new import_three24.Matrix4().makeBasis(localRight, localUp, inward);
12014
- 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);
12015
12167
  }
12016
12168
  function makeInteractionEvent(id, position, event) {
12017
12169
  return {
@@ -12024,10 +12176,10 @@ function makeInteractionEvent(id, position, event) {
12024
12176
  function angularDistance(a, b) {
12025
12177
  const aVector = panoPositionToVector3(a);
12026
12178
  const bVector = panoPositionToVector3(b);
12027
- return import_three24.MathUtils.radToDeg(aVector.angleTo(bVector));
12179
+ return import_three25.MathUtils.radToDeg(aVector.angleTo(bVector));
12028
12180
  }
12029
- var DRAG_POINTER = new import_three24.Vector2();
12030
- var DRAG_RAYCASTER = new import_three24.Raycaster();
12181
+ var DRAG_POINTER = new import_three25.Vector2();
12182
+ var DRAG_RAYCASTER = new import_three25.Raycaster();
12031
12183
  function aimDragRaycaster(event, element, camera) {
12032
12184
  const rect = element.getBoundingClientRect();
12033
12185
  if (!(rect.width > 0) || !(rect.height > 0)) {
@@ -12261,7 +12413,7 @@ function placeSelectionFrame(frame, group, camera, viewportHeight) {
12261
12413
  SELECTION_WORLD_SCALE.x,
12262
12414
  SELECTION_WORLD_SCALE.y,
12263
12415
  -SELECTION_CAMERA_POSITION.z,
12264
- camera instanceof import_three24.PerspectiveCamera ? camera.fov : DEFAULT_REFERENCE_FOV,
12416
+ camera instanceof import_three25.PerspectiveCamera ? camera.fov : DEFAULT_REFERENCE_FOV,
12265
12417
  viewportHeight,
12266
12418
  SELECTION_BORDER_OUTSET
12267
12419
  );
@@ -12350,8 +12502,8 @@ function HotspotAnchor({
12350
12502
  const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
12351
12503
  const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
12352
12504
  const focusGeometry = (0, import_react42.useMemo)(() => {
12353
- const planeGeometry = new import_three24.PlaneGeometry(1, 1);
12354
- const geometry = new import_three24.EdgesGeometry(planeGeometry);
12505
+ const planeGeometry = new import_three25.PlaneGeometry(1, 1);
12506
+ const geometry = new import_three25.EdgesGeometry(planeGeometry);
12355
12507
  planeGeometry.dispose();
12356
12508
  return geometry;
12357
12509
  }, []);
@@ -12743,10 +12895,10 @@ function HotspotAnchor({
12743
12895
  }
12744
12896
 
12745
12897
  // src/hotspot/hotspot-plane.tsx
12746
- var import_three25 = require("three");
12898
+ var import_three26 = require("three");
12747
12899
  var import_jsx_runtime27 = require("react/jsx-runtime");
12748
12900
  var HOTSPOT_ALPHA_CUTOFF = 0.05;
12749
- var SAMPLE_UV = new import_three25.Vector2();
12901
+ var SAMPLE_UV = new import_three26.Vector2();
12750
12902
  var RAYCAST_HITS = [];
12751
12903
  var IMAGE_DATA_CACHE = /* @__PURE__ */ new WeakMap();
12752
12904
  function clampOpacity(opacity) {
@@ -12820,8 +12972,8 @@ function sampleTextureAlpha(texture, u, v) {
12820
12972
  }
12821
12973
  function hotspotPlaneRaycast(raycaster, intersects2) {
12822
12974
  const material = Array.isArray(this.material) ? this.material[0] : this.material;
12823
- if (!(material instanceof import_three25.MeshBasicMaterial)) {
12824
- 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);
12825
12977
  return;
12826
12978
  }
12827
12979
  const cutoff = Math.max(material.alphaTest, HOTSPOT_ALPHA_CUTOFF);
@@ -12829,7 +12981,7 @@ function hotspotPlaneRaycast(raycaster, intersects2) {
12829
12981
  return;
12830
12982
  }
12831
12983
  RAYCAST_HITS.length = 0;
12832
- import_three25.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
12984
+ import_three26.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
12833
12985
  const map = material.map;
12834
12986
  for (const hit of RAYCAST_HITS) {
12835
12987
  if (!map || !hit.uv) {
@@ -12855,7 +13007,7 @@ function HotspotPlane({
12855
13007
  alphaTest: HOTSPOT_ALPHA_CUTOFF,
12856
13008
  map,
12857
13009
  opacity: map ? clampOpacity(opacity) : 0,
12858
- side: import_three25.DoubleSide,
13010
+ side: import_three26.DoubleSide,
12859
13011
  toneMapped: false,
12860
13012
  transparent: true
12861
13013
  }
@@ -12880,7 +13032,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
12880
13032
  active = false;
12881
13033
  };
12882
13034
  }
12883
- const loader = new import_three26.TextureLoader();
13035
+ const loader = new import_three27.TextureLoader();
12884
13036
  loader.load(
12885
13037
  src,
12886
13038
  (loadedTexture) => {
@@ -12888,11 +13040,11 @@ function useHotspotImageTexture(src, onLoad, onError) {
12888
13040
  loadedTexture.dispose();
12889
13041
  return;
12890
13042
  }
12891
- loadedTexture.colorSpace = import_three26.SRGBColorSpace;
12892
- loadedTexture.wrapS = import_three26.ClampToEdgeWrapping;
12893
- loadedTexture.wrapT = import_three26.ClampToEdgeWrapping;
12894
- loadedTexture.magFilter = import_three26.LinearFilter;
12895
- 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;
12896
13048
  loadedTexture.generateMipmaps = true;
12897
13049
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
12898
13050
  loadedTexture.needsUpdate = true;
@@ -12933,7 +13085,7 @@ function ImageHotspot({
12933
13085
 
12934
13086
  // src/hotspot/graphic-hotspot.tsx
12935
13087
  var import_react44 = require("react");
12936
- var import_three27 = require("three");
13088
+ var import_three28 = require("three");
12937
13089
  var import_jsx_runtime29 = require("react/jsx-runtime");
12938
13090
  var GRAPHIC_TEXTURE_SIZE = 512;
12939
13091
  function resolveStrokeWidth(value) {
@@ -13112,12 +13264,12 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
13112
13264
  throw new Error("Canvas 2D is unavailable for this graphic hotspot.");
13113
13265
  }
13114
13266
  drawGraphic(context, graphic, aspectWidth, aspectHeight);
13115
- const texture = new import_three27.CanvasTexture(canvas);
13116
- texture.colorSpace = import_three27.SRGBColorSpace;
13117
- texture.wrapS = import_three27.ClampToEdgeWrapping;
13118
- texture.wrapT = import_three27.ClampToEdgeWrapping;
13119
- texture.magFilter = import_three27.LinearFilter;
13120
- 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;
13121
13273
  texture.generateMipmaps = true;
13122
13274
  texture.needsUpdate = true;
13123
13275
  return texture;
@@ -13168,7 +13320,7 @@ function GraphicHotspot(props) {
13168
13320
  // src/hotspot/sequence-hotspot.tsx
13169
13321
  var import_fiber23 = require("@react-three/fiber");
13170
13322
  var import_react45 = require("react");
13171
- var import_three28 = require("three");
13323
+ var import_three29 = require("three");
13172
13324
  var import_jsx_runtime30 = require("react/jsx-runtime");
13173
13325
  var DEFAULT_SEQUENCE_FPS = 12;
13174
13326
  function resolveFps(value) {
@@ -13198,7 +13350,7 @@ function useSpriteTexture({
13198
13350
  active = false;
13199
13351
  };
13200
13352
  }
13201
- const loader = new import_three28.TextureLoader();
13353
+ const loader = new import_three29.TextureLoader();
13202
13354
  loader.load(
13203
13355
  src,
13204
13356
  (loadedTexture) => {
@@ -13206,11 +13358,11 @@ function useSpriteTexture({
13206
13358
  loadedTexture.dispose();
13207
13359
  return;
13208
13360
  }
13209
- loadedTexture.colorSpace = import_three28.SRGBColorSpace;
13210
- loadedTexture.wrapS = import_three28.ClampToEdgeWrapping;
13211
- loadedTexture.wrapT = import_three28.ClampToEdgeWrapping;
13212
- loadedTexture.magFilter = import_three28.LinearFilter;
13213
- 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;
13214
13366
  loadedTexture.generateMipmaps = true;
13215
13367
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
13216
13368
  loadedTexture.needsUpdate = true;
@@ -13351,7 +13503,7 @@ function SequenceHotspot({
13351
13503
  // src/hotspot/video-hotspot.tsx
13352
13504
  var import_fiber24 = require("@react-three/fiber");
13353
13505
  var import_react46 = require("react");
13354
- var import_three29 = require("three");
13506
+ var import_three30 = require("three");
13355
13507
 
13356
13508
  // src/video/inline-playback.ts
13357
13509
  var INLINE_VIDEO_ATTRIBUTES = [
@@ -13424,7 +13576,7 @@ function usePosterTexture(id, poster, onError) {
13424
13576
  active = false;
13425
13577
  };
13426
13578
  }
13427
- const loader = new import_three29.TextureLoader();
13579
+ const loader = new import_three30.TextureLoader();
13428
13580
  loader.load(
13429
13581
  poster,
13430
13582
  (loadedTexture) => {
@@ -13432,11 +13584,11 @@ function usePosterTexture(id, poster, onError) {
13432
13584
  loadedTexture.dispose();
13433
13585
  return;
13434
13586
  }
13435
- loadedTexture.colorSpace = import_three29.SRGBColorSpace;
13436
- loadedTexture.wrapS = import_three29.ClampToEdgeWrapping;
13437
- loadedTexture.wrapT = import_three29.ClampToEdgeWrapping;
13438
- loadedTexture.magFilter = import_three29.LinearFilter;
13439
- 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;
13440
13592
  loadedTexture.generateMipmaps = true;
13441
13593
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
13442
13594
  loadedTexture.needsUpdate = true;
@@ -13491,12 +13643,12 @@ function useVideoResource({
13491
13643
  }
13492
13644
  applyInlineVideoPlayback(video, playsInline ?? true);
13493
13645
  video.poster = poster ?? "";
13494
- const texture = new import_three29.VideoTexture(video);
13495
- texture.colorSpace = import_three29.SRGBColorSpace;
13496
- texture.wrapS = import_three29.ClampToEdgeWrapping;
13497
- texture.wrapT = import_three29.ClampToEdgeWrapping;
13498
- texture.magFilter = import_three29.LinearFilter;
13499
- 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;
13500
13652
  texture.generateMipmaps = false;
13501
13653
  const notifyState = (state) => {
13502
13654
  if (active) {
@@ -13635,13 +13787,13 @@ function VideoHotspot({
13635
13787
  // src/hotspot/audio-hotspot.tsx
13636
13788
  var import_fiber25 = require("@react-three/fiber");
13637
13789
  var import_react47 = require("react");
13638
- var import_three31 = require("three");
13790
+ var import_three32 = require("three");
13639
13791
 
13640
13792
  // src/hotspot/audio-spatial.ts
13641
- var import_three30 = require("three");
13642
- var LOOK_DIR = new import_three30.Vector3();
13643
- var SOURCE_DIR = new import_three30.Vector3();
13644
- 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();
13645
13797
  function clampAudioVolume(volume) {
13646
13798
  if (!Number.isFinite(volume)) {
13647
13799
  return 1;
@@ -13666,11 +13818,11 @@ function lookRangeGain(angleDegrees, range) {
13666
13818
  function audioSpatialFromView(camera, position, range) {
13667
13819
  camera.getWorldDirection(LOOK_DIR);
13668
13820
  SOURCE_DIR.copy(panoPositionToVector3(position)).normalize();
13669
- const angleDegrees = import_three30.MathUtils.radToDeg(
13670
- 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))
13671
13823
  );
13672
13824
  RIGHT_DIR.set(1, 0, 0).applyQuaternion(camera.quaternion);
13673
- const pan = import_three30.MathUtils.clamp(
13825
+ const pan = import_three31.MathUtils.clamp(
13674
13826
  Math.atan2(SOURCE_DIR.dot(RIGHT_DIR), SOURCE_DIR.dot(LOOK_DIR)) / (Math.PI / 2),
13675
13827
  -1,
13676
13828
  1
@@ -13735,12 +13887,12 @@ function createSpeakerTexture(state) {
13735
13887
  return exhaustive;
13736
13888
  }
13737
13889
  }
13738
- const texture = new import_three31.CanvasTexture(canvas);
13739
- texture.colorSpace = import_three31.SRGBColorSpace;
13740
- texture.wrapS = import_three31.ClampToEdgeWrapping;
13741
- texture.wrapT = import_three31.ClampToEdgeWrapping;
13742
- texture.magFilter = import_three31.LinearFilter;
13743
- 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;
13744
13896
  texture.generateMipmaps = true;
13745
13897
  texture.needsUpdate = true;
13746
13898
  return texture;
@@ -13775,7 +13927,7 @@ function useIconTexture(icon, enabled, onError, id) {
13775
13927
  active = false;
13776
13928
  };
13777
13929
  }
13778
- const loader = new import_three31.TextureLoader();
13930
+ const loader = new import_three32.TextureLoader();
13779
13931
  loader.load(
13780
13932
  icon,
13781
13933
  (loadedTexture) => {
@@ -13783,11 +13935,11 @@ function useIconTexture(icon, enabled, onError, id) {
13783
13935
  loadedTexture.dispose();
13784
13936
  return;
13785
13937
  }
13786
- loadedTexture.colorSpace = import_three31.SRGBColorSpace;
13787
- loadedTexture.wrapS = import_three31.ClampToEdgeWrapping;
13788
- loadedTexture.wrapT = import_three31.ClampToEdgeWrapping;
13789
- loadedTexture.magFilter = import_three31.LinearFilter;
13790
- 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;
13791
13943
  loadedTexture.generateMipmaps = true;
13792
13944
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
13793
13945
  loadedTexture.needsUpdate = true;
@@ -13978,7 +14130,7 @@ function AudioHotspot({
13978
14130
  // src/hotspot/text-hotspot.tsx
13979
14131
  var import_react48 = require("react");
13980
14132
  var import_fiber26 = require("@react-three/fiber");
13981
- var import_three32 = require("three");
14133
+ var import_three33 = require("three");
13982
14134
  var import_jsx_runtime33 = require("react/jsx-runtime");
13983
14135
  var TEXT_TEXTURE_LONG_SIDE = 1024;
13984
14136
  var TEXT_RASTER_SUPERSAMPLE = 2;
@@ -14050,7 +14202,7 @@ function projectedDevicePixels(angleDeg, fovDeg, viewportHeight) {
14050
14202
  }
14051
14203
  const fov = Math.min(179, Math.max(1, resolvePositive(fovDeg, DEFAULT_REFERENCE_FOV2)));
14052
14204
  const angle = Math.min(179, Math.max(0.01, Math.abs(angleDeg)));
14053
- 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;
14054
14206
  }
14055
14207
  function snapRasterLongSide(screenLong, layoutLong) {
14056
14208
  if (!(screenLong > 0)) {
@@ -14239,12 +14391,12 @@ function createTextTexture(text, width, height, style, rasterLong) {
14239
14391
  0
14240
14392
  );
14241
14393
  drawTextHotspot(context, layout.canvasWidth, layout.canvasHeight, text, style);
14242
- const texture = new import_three32.CanvasTexture(canvas);
14243
- texture.colorSpace = import_three32.SRGBColorSpace;
14244
- texture.wrapS = import_three32.ClampToEdgeWrapping;
14245
- texture.wrapT = import_three32.ClampToEdgeWrapping;
14246
- texture.magFilter = import_three32.LinearFilter;
14247
- 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;
14248
14400
  texture.generateMipmaps = false;
14249
14401
  texture.needsUpdate = true;
14250
14402
  return texture;
@@ -14256,7 +14408,7 @@ function useRasterLongSide(width, height, scale, scaleMode, referenceFov) {
14256
14408
  const measure = () => {
14257
14409
  const pixelRatio = getPixelRatio();
14258
14410
  const viewportHeight = size.height * (Number.isFinite(pixelRatio) && pixelRatio > 0 ? pixelRatio : 1);
14259
- 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;
14260
14412
  const screenLong = Math.max(
14261
14413
  projectedDevicePixels(
14262
14414
  width * resolveScale2(scale),
@@ -14402,7 +14554,7 @@ function TextHotspot({
14402
14554
 
14403
14555
  // src/hotspot/iframe-hotspot.tsx
14404
14556
  var import_drei2 = require("@react-three/drei");
14405
- var import_three33 = require("three");
14557
+ var import_three34 = require("three");
14406
14558
  var import_jsx_runtime34 = require("react/jsx-runtime");
14407
14559
  var IFRAME_LONG_SIDE = 800;
14408
14560
  var CSS3D_DISTANCE_FACTOR = 400;
@@ -14476,7 +14628,7 @@ function IframeHotspot({
14476
14628
  {
14477
14629
  depthWrite: false,
14478
14630
  opacity: 0,
14479
- side: import_three33.DoubleSide,
14631
+ side: import_three34.DoubleSide,
14480
14632
  toneMapped: false,
14481
14633
  transparent: true
14482
14634
  }
@@ -14520,7 +14672,7 @@ function IframeHotspot({
14520
14672
 
14521
14673
  // src/hotspot/polygon-hotspot.tsx
14522
14674
  var import_react49 = require("react");
14523
- var import_three34 = require("three");
14675
+ var import_three35 = require("three");
14524
14676
  var import_jsx_runtime35 = require("react/jsx-runtime");
14525
14677
  var POLYGON_RADIUS = 990;
14526
14678
  var MAX_FILL_SEGMENT_DEGREES = 7;
@@ -14556,7 +14708,7 @@ function intersects(a, b, c, d) {
14556
14708
  }
14557
14709
  function hasSelfIntersection(vertices) {
14558
14710
  const points = vertices.map(
14559
- (vertex) => new import_three34.Vector2(vertex.unwrappedYaw, vertex.pitch)
14711
+ (vertex) => new import_three35.Vector2(vertex.unwrappedYaw, vertex.pitch)
14560
14712
  );
14561
14713
  for (let index = 0; index < points.length; index += 1) {
14562
14714
  const nextIndex = (index + 1) % points.length;
@@ -14593,7 +14745,7 @@ function polygonContainsDirection(vertices, direction) {
14593
14745
  }
14594
14746
  function fitsHemisphere(vertices) {
14595
14747
  const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
14596
- const candidates = [new import_three34.Vector3()];
14748
+ const candidates = [new import_three35.Vector3()];
14597
14749
  for (const direction of directions) {
14598
14750
  candidates[0].add(direction);
14599
14751
  candidates.push(direction.clone());
@@ -14617,7 +14769,7 @@ function validatePolygonVertices(vertices) {
14617
14769
  if (hasSelfIntersection(unwrapped)) {
14618
14770
  issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
14619
14771
  }
14620
- 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))) {
14621
14773
  issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
14622
14774
  }
14623
14775
  if (!fitsHemisphere(normalized)) {
@@ -14628,7 +14780,7 @@ function validatePolygonVertices(vertices) {
14628
14780
  function polygonCenter(vertices) {
14629
14781
  const sum = vertices.reduce(
14630
14782
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14631
- new import_three34.Vector3()
14783
+ new import_three35.Vector3()
14632
14784
  );
14633
14785
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14634
14786
  }
@@ -14637,20 +14789,20 @@ function surfaceQuaternion(position) {
14637
14789
  const inward = outward.clone().negate();
14638
14790
  const pitch = position.pitch * Math.PI / 180;
14639
14791
  const yaw = position.yaw * Math.PI / 180;
14640
- const localUp = new import_three34.Vector3(
14792
+ const localUp = new import_three35.Vector3(
14641
14793
  -Math.sin(pitch) * Math.sin(yaw),
14642
14794
  Math.cos(pitch),
14643
14795
  Math.sin(pitch) * Math.cos(yaw)
14644
14796
  ).normalize();
14645
- return new import_three34.Quaternion().setFromRotationMatrix(
14646
- 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)
14647
14799
  );
14648
14800
  }
14649
14801
  function makeWorldToLocal(center) {
14650
- return new import_three34.Matrix4().compose(
14802
+ return new import_three35.Matrix4().compose(
14651
14803
  panoPositionToVector3(center, POLYGON_RADIUS),
14652
14804
  surfaceQuaternion(center),
14653
- new import_three34.Vector3(1, 1, 1)
14805
+ new import_three35.Vector3(1, 1, 1)
14654
14806
  ).invert();
14655
14807
  }
14656
14808
  function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
@@ -14705,8 +14857,8 @@ function addSubdividedTriangle(positions, indices, a, b, c, worldToLocal, steps)
14705
14857
  }
14706
14858
  function makeFillGeometry(vertices, center) {
14707
14859
  const unwrapped = unwrapPolygonVertices(vertices);
14708
- const contour = unwrapped.map((vertex) => new import_three34.Vector2(vertex.unwrappedYaw, vertex.pitch));
14709
- 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, []);
14710
14862
  const positions = [];
14711
14863
  const indices = [];
14712
14864
  const worldToLocal = makeWorldToLocal(center);
@@ -14722,7 +14874,7 @@ function makeFillGeometry(vertices, center) {
14722
14874
  steps
14723
14875
  );
14724
14876
  }
14725
- 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);
14726
14878
  }
14727
14879
  function makeStrokePositions(vertices, center) {
14728
14880
  const points = [];
@@ -14852,7 +15004,7 @@ function PolygonHotspot({
14852
15004
  color: fill,
14853
15005
  depthWrite: false,
14854
15006
  opacity: Math.max(0, Math.min(fillOpacity, 1)),
14855
- side: import_three34.DoubleSide,
15007
+ side: import_three35.DoubleSide,
14856
15008
  transparent: true
14857
15009
  }
14858
15010
  ) }),
@@ -14875,7 +15027,7 @@ function PolygonHotspot({
14875
15027
 
14876
15028
  // src/hotspot/polyline-hotspot.tsx
14877
15029
  var import_react50 = require("react");
14878
- var import_three35 = require("three");
15030
+ var import_three36 = require("three");
14879
15031
  var import_jsx_runtime36 = require("react/jsx-runtime");
14880
15032
  var POLYLINE_RADIUS = 990;
14881
15033
  var MAX_SEGMENT_DEGREES = 7;
@@ -14901,29 +15053,29 @@ function unwrapVertices(vertices) {
14901
15053
  function polylineCenter(vertices) {
14902
15054
  const sum = vertices.reduce(
14903
15055
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14904
- new import_three35.Vector3()
15056
+ new import_three36.Vector3()
14905
15057
  );
14906
15058
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14907
15059
  }
14908
15060
  function surfaceQuaternion2(position) {
14909
15061
  const outward = panoPositionToVector3(position).normalize();
14910
15062
  const inward = outward.clone().negate();
14911
- const pitch = import_three35.MathUtils.degToRad(position.pitch);
14912
- const yaw = import_three35.MathUtils.degToRad(position.yaw);
14913
- 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(
14914
15066
  -Math.sin(pitch) * Math.sin(yaw),
14915
15067
  Math.cos(pitch),
14916
15068
  Math.sin(pitch) * Math.cos(yaw)
14917
15069
  ).normalize();
14918
- return new import_three35.Quaternion().setFromRotationMatrix(
14919
- 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)
14920
15072
  );
14921
15073
  }
14922
15074
  function makeWorldToLocal2(center) {
14923
- return new import_three35.Matrix4().compose(
15075
+ return new import_three36.Matrix4().compose(
14924
15076
  panoPositionToVector3(center, POLYLINE_RADIUS),
14925
15077
  surfaceQuaternion2(center),
14926
- new import_three35.Vector3(1, 1, 1)
15078
+ new import_three36.Vector3(1, 1, 1)
14927
15079
  ).invert();
14928
15080
  }
14929
15081
  function subdivisionSteps(vertices) {
@@ -14938,7 +15090,7 @@ function subdivisionSteps(vertices) {
14938
15090
  }
14939
15091
  return Math.min(
14940
15092
  8,
14941
- 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))
14942
15094
  );
14943
15095
  }
14944
15096
  function makeLinePositions(vertices, center) {
@@ -15703,65 +15855,7 @@ function PanoFilter({
15703
15855
  // src/gyro.tsx
15704
15856
  var import_fiber27 = require("@react-three/fiber");
15705
15857
  var import_react54 = require("react");
15706
-
15707
- // src/gyro-orientation.ts
15708
- var import_three36 = require("three");
15709
- var DEVICE_FORWARD_CORRECTION = new import_three36.Quaternion().setFromAxisAngle(
15710
- new import_three36.Vector3(1, 0, 0),
15711
- -Math.PI / 2
15712
- );
15713
- var SCREEN_AXIS = new import_three36.Vector3(0, 0, 1);
15714
- function getScreenOrientationAngle() {
15715
- if (typeof window === "undefined") {
15716
- return 0;
15717
- }
15718
- const angle = window.screen.orientation?.angle;
15719
- if (Number.isFinite(angle)) {
15720
- return angle;
15721
- }
15722
- const legacyAngle = window.orientation;
15723
- return Number.isFinite(legacyAngle) ? legacyAngle : 0;
15724
- }
15725
- function deviceOrientationToQuaternion(sample, screenOrientation) {
15726
- const alpha = Number.isFinite(sample.compassHeading) ? 360 - sample.compassHeading : sample.alpha;
15727
- const deviceEuler = new import_three36.Euler(
15728
- import_three36.MathUtils.degToRad(sample.beta),
15729
- import_three36.MathUtils.degToRad(alpha),
15730
- import_three36.MathUtils.degToRad(-sample.gamma),
15731
- "YXZ"
15732
- );
15733
- const screenCorrection = new import_three36.Quaternion().setFromAxisAngle(
15734
- SCREEN_AXIS,
15735
- -import_three36.MathUtils.degToRad(screenOrientation)
15736
- );
15737
- return new import_three36.Quaternion().setFromEuler(deviceEuler).multiply(DEVICE_FORWARD_CORRECTION).multiply(screenCorrection).normalize();
15738
- }
15739
- function quaternionToGyroPose(quaternion) {
15740
- const euler = new import_three36.Euler().setFromQuaternion(quaternion, "YXZ");
15741
- return {
15742
- yaw: import_three36.MathUtils.radToDeg(-euler.y),
15743
- pitch: import_three36.MathUtils.radToDeg(euler.x),
15744
- roll: import_three36.MathUtils.radToDeg(euler.z)
15745
- };
15746
- }
15747
- function createRelativeCalibration(deviceQuaternion, yaw, pitch) {
15748
- const targetQuaternion = new import_three36.Quaternion().setFromEuler(
15749
- new import_three36.Euler(
15750
- import_three36.MathUtils.degToRad(pitch),
15751
- import_three36.MathUtils.degToRad(-yaw),
15752
- 0,
15753
- "YXZ"
15754
- )
15755
- );
15756
- return targetQuaternion.multiply(deviceQuaternion.clone().invert()).normalize();
15757
- }
15758
- function applyGyroCalibration(deviceQuaternion, calibration) {
15759
- return quaternionToGyroPose(
15760
- calibration.clone().multiply(deviceQuaternion).normalize()
15761
- );
15762
- }
15763
-
15764
- // src/gyro.tsx
15858
+ var import_three37 = require("three");
15765
15859
  var deviceOrientationPermissionState = "unknown";
15766
15860
  function isMobileDevice() {
15767
15861
  if (typeof navigator === "undefined") {
@@ -15769,12 +15863,6 @@ function isMobileDevice() {
15769
15863
  }
15770
15864
  return /Android|iPad|iPhone|iPod|Mobile/i.test(navigator.userAgent) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
15771
15865
  }
15772
- function normalizeYaw2(value) {
15773
- return ((value + 180) % 360 + 360) % 360 - 180;
15774
- }
15775
- function shortestYawDelta2(from, to) {
15776
- return normalizeYaw2(to - from);
15777
- }
15778
15866
  function finiteOr(value, fallback) {
15779
15867
  return Number.isFinite(value) ? value : fallback;
15780
15868
  }
@@ -15784,9 +15872,6 @@ function resolveFriction(value) {
15784
15872
  function resolveSoftstart(value) {
15785
15873
  return Math.max(finiteOr(value, 0.5), 0);
15786
15874
  }
15787
- function posesNearlyEqual(a, b) {
15788
- 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;
15789
- }
15790
15875
  var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15791
15876
  enabled = false,
15792
15877
  camroll = true,
@@ -15806,19 +15891,30 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15806
15891
  const eventBus = (0, import_react54.useContext)(PanoEventBusContext);
15807
15892
  const { gl } = (0, import_fiber27.useThree)();
15808
15893
  const [internallyDisabled, setInternallyDisabled] = (0, import_react54.useState)(false);
15894
+ const [available, setAvailableState] = (0, import_react54.useState)(false);
15809
15895
  const availableRef = (0, import_react54.useRef)(false);
15810
15896
  const availabilityReportedRef = (0, import_react54.useRef)(null);
15811
15897
  const activeRef = (0, import_react54.useRef)(false);
15812
15898
  const permissionRef = (0, import_react54.useRef)(deviceOrientationPermissionState);
15813
15899
  const absoluteEventSourceRef = (0, import_react54.useRef)(null);
15814
- const rawQuaternionRef = (0, import_react54.useRef)(null);
15815
- 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());
15816
15905
  const absoluteOffsetRef = (0, import_react54.useRef)({ yaw: 0, pitch: 0 });
15817
15906
  const screenAngleRef = (0, import_react54.useRef)(getScreenOrientationAngle());
15818
15907
  const startPoseRef = (0, import_react54.useRef)(null);
15819
15908
  const enabledAtRef = (0, import_react54.useRef)(0);
15820
15909
  const filteredPoseRef = (0, import_react54.useRef)(null);
15821
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;
15822
15918
  const callbacksRef = (0, import_react54.useRef)({
15823
15919
  onAvailable,
15824
15920
  onUnavailable,
@@ -15864,13 +15960,14 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15864
15960
  [eventBus]
15865
15961
  );
15866
15962
  const setAvailable = (0, import_react54.useCallback)(
15867
- (available) => {
15868
- availableRef.current = available;
15869
- if (availabilityReportedRef.current === available) {
15963
+ (nextAvailable) => {
15964
+ availableRef.current = nextAvailable;
15965
+ setAvailableState(nextAvailable);
15966
+ if (availabilityReportedRef.current === nextAvailable) {
15870
15967
  return;
15871
15968
  }
15872
- availabilityReportedRef.current = available;
15873
- emit(available ? "gyroavailable" : "gyrounavailable");
15969
+ availabilityReportedRef.current = nextAvailable;
15970
+ emit(nextAvailable ? "gyroavailable" : "gyrounavailable");
15874
15971
  },
15875
15972
  [emit]
15876
15973
  );
@@ -15913,37 +16010,54 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15913
16010
  controlsRef.current?.setGyroActive(false);
15914
16011
  emit("gyrodisable");
15915
16012
  }
15916
- rawQuaternionRef.current = null;
16013
+ hasRawQuaternionRef.current = false;
15917
16014
  absoluteEventSourceRef.current = null;
15918
- calibrationRef.current = null;
16015
+ hasCalibrationRef.current = false;
15919
16016
  filteredPoseRef.current = null;
15920
16017
  lastAppliedPoseRef.current = null;
16018
+ lastSamplePoseRef.current = null;
16019
+ lastSampleAtRef.current = null;
16020
+ previousYawRef.current = void 0;
15921
16021
  }, [controlsRef, emit]);
15922
- const resetSensor = (0, import_react54.useCallback)(
16022
+ const anchorToView = (0, import_react54.useCallback)(
15923
16023
  (yaw, pitch) => {
15924
- const rawQuaternion = rawQuaternionRef.current;
15925
- if (!rawQuaternion) {
16024
+ if (!hasRawQuaternionRef.current) {
15926
16025
  return;
15927
16026
  }
15928
- const view = controlsRef.current?.getTargetView();
15929
- const targetYaw = finiteOr(yaw, view?.yaw ?? 0);
15930
- const targetPitch = finiteOr(pitch, view?.pitch ?? 0);
15931
- if (absolute) {
15932
- const rawPose = quaternionToGyroPose(rawQuaternion);
16027
+ if (absoluteRef.current) {
16028
+ const rawPose = quaternionToGyroPose(
16029
+ rawQuaternionRef.current,
16030
+ previousYawRef.current
16031
+ );
16032
+ previousYawRef.current = rawPose.yaw;
15933
16033
  absoluteOffsetRef.current = {
15934
- yaw: shortestYawDelta2(
15935
- rawPose.yaw + finiteOr(north, 0),
15936
- targetYaw
16034
+ yaw: shortestGyroYawDelta(
16035
+ rawPose.yaw + finiteOr(northRef.current, 0),
16036
+ yaw
15937
16037
  ),
15938
- pitch: targetPitch - rawPose.pitch
16038
+ pitch: pitch - rawPose.pitch
15939
16039
  };
15940
16040
  } else {
15941
- calibrationRef.current = createRelativeCalibration(
15942
- rawQuaternion,
15943
- targetYaw,
15944
- targetPitch
16041
+ createRelativeCalibration(
16042
+ rawQuaternionRef.current,
16043
+ yaw,
16044
+ pitch,
16045
+ calibrationRef.current
15945
16046
  );
16047
+ hasCalibrationRef.current = true;
15946
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);
15947
16061
  startPoseRef.current = {
15948
16062
  yaw: targetYaw,
15949
16063
  pitch: targetPitch,
@@ -15951,8 +16065,10 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15951
16065
  };
15952
16066
  enabledAtRef.current = performance.now();
15953
16067
  filteredPoseRef.current = null;
16068
+ lastSamplePoseRef.current = null;
16069
+ lastSampleAtRef.current = null;
15954
16070
  },
15955
- [absolute, controlsRef, north]
16071
+ [anchorToView, controlsRef]
15956
16072
  );
15957
16073
  (0, import_react54.useImperativeHandle)(
15958
16074
  ref,
@@ -15972,9 +16088,6 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15972
16088
  (0, import_react54.useEffect)(() => {
15973
16089
  const supported = typeof window !== "undefined" && window.isSecureContext && typeof DeviceOrientationEvent !== "undefined" && (desktopSupport || isMobileDevice());
15974
16090
  setAvailable(supported);
15975
- return () => {
15976
- availableRef.current = false;
15977
- };
15978
16091
  }, [desktopSupport, setAvailable]);
15979
16092
  (0, import_react54.useEffect)(() => {
15980
16093
  controlsRef.current?.setGyroTouchMode(touchMode);
@@ -15994,7 +16107,7 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
15994
16107
  };
15995
16108
  }, [enabled, gl, internallyDisabled, touchMode]);
15996
16109
  (0, import_react54.useEffect)(() => {
15997
- if (!enabled || internallyDisabled || !availableRef.current) {
16110
+ if (!enabled || internallyDisabled || !available) {
15998
16111
  deactivate();
15999
16112
  return;
16000
16113
  }
@@ -16023,10 +16136,12 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16023
16136
  gamma: event.gamma,
16024
16137
  compassHeading: absolute && hasCompassHeading ? compassEvent.webkitCompassHeading : void 0
16025
16138
  };
16026
- rawQuaternionRef.current = deviceOrientationToQuaternion(
16139
+ deviceOrientationToQuaternion(
16027
16140
  sample,
16028
- screenAngleRef.current
16141
+ screenAngleRef.current,
16142
+ rawQuaternionRef.current
16029
16143
  );
16144
+ hasRawQuaternionRef.current = true;
16030
16145
  if (!activeRef.current) {
16031
16146
  const view = controlsRef.current?.getTargetView() ?? {
16032
16147
  yaw: 0,
@@ -16034,11 +16149,13 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16034
16149
  fov: 75
16035
16150
  };
16036
16151
  if (!absolute) {
16037
- calibrationRef.current = createRelativeCalibration(
16152
+ createRelativeCalibration(
16038
16153
  rawQuaternionRef.current,
16039
16154
  view.yaw,
16040
- view.pitch
16155
+ view.pitch,
16156
+ calibrationRef.current
16041
16157
  );
16158
+ hasCalibrationRef.current = true;
16042
16159
  }
16043
16160
  absoluteOffsetRef.current = { yaw: 0, pitch: 0 };
16044
16161
  startPoseRef.current = { ...view, roll: 0 };
@@ -16086,6 +16203,7 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16086
16203
  };
16087
16204
  }, [
16088
16205
  absolute,
16206
+ available,
16089
16207
  controlsRef,
16090
16208
  deactivate,
16091
16209
  emit,
@@ -16094,28 +16212,84 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16094
16212
  requestPermission
16095
16213
  ]);
16096
16214
  (0, import_fiber27.useFrame)((_, deltaSeconds) => {
16097
- const rawQuaternion = rawQuaternionRef.current;
16098
- if (!activeRef.current || !rawQuaternion) {
16215
+ if (!activeRef.current || !hasRawQuaternionRef.current) {
16099
16216
  return;
16100
16217
  }
16101
16218
  let targetPose;
16102
16219
  if (absolute) {
16103
- const rawPose = quaternionToGyroPose(rawQuaternion);
16220
+ const rawPose = quaternionToGyroPose(
16221
+ rawQuaternionRef.current,
16222
+ previousYawRef.current
16223
+ );
16224
+ previousYawRef.current = rawPose.yaw;
16104
16225
  targetPose = {
16105
16226
  yaw: rawPose.yaw + finiteOr(north, 0) + absoluteOffsetRef.current.yaw,
16106
16227
  pitch: rawPose.pitch + absoluteOffsetRef.current.pitch,
16107
16228
  roll: rawPose.roll
16108
16229
  };
16109
16230
  } else {
16110
- const calibration = calibrationRef.current;
16111
- if (!calibration) {
16231
+ if (!hasCalibrationRef.current) {
16112
16232
  return;
16113
16233
  }
16114
- 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;
16115
16241
  }
16116
16242
  if (!camroll) {
16117
16243
  targetPose.roll = 0;
16118
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;
16119
16293
  const softstartMs = resolveSoftstart(softstart) * 1e3;
16120
16294
  const startPose = startPoseRef.current;
16121
16295
  if (startPose && softstartMs > 0) {
@@ -16124,9 +16298,9 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16124
16298
  1
16125
16299
  );
16126
16300
  targetPose = {
16127
- yaw: startPose.yaw + shortestYawDelta2(startPose.yaw, targetPose.yaw) * progress,
16301
+ yaw: startPose.yaw + shortestGyroYawDelta(startPose.yaw, targetPose.yaw) * progress,
16128
16302
  pitch: startPose.pitch + (targetPose.pitch - startPose.pitch) * progress,
16129
- roll: startPose.roll + shortestYawDelta2(startPose.roll, targetPose.roll) * progress
16303
+ roll: startPose.roll + shortestGyroYawDelta(startPose.roll, targetPose.roll) * progress
16130
16304
  };
16131
16305
  if (progress === 1) {
16132
16306
  startPoseRef.current = null;
@@ -16136,9 +16310,9 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16136
16310
  const retention = resolveFriction(friction);
16137
16311
  const follow = retention === 0 ? 1 : 1 - Math.pow(retention, deltaSeconds * 60);
16138
16312
  const filteredPose = previous ? {
16139
- yaw: previous.yaw + shortestYawDelta2(previous.yaw, targetPose.yaw) * follow,
16313
+ yaw: previous.yaw + shortestGyroYawDelta(previous.yaw, targetPose.yaw) * follow,
16140
16314
  pitch: previous.pitch + (targetPose.pitch - previous.pitch) * follow,
16141
- roll: previous.roll + shortestYawDelta2(previous.roll, targetPose.roll) * follow
16315
+ roll: previous.roll + shortestGyroYawDelta(previous.roll, targetPose.roll) * follow
16142
16316
  } : targetPose;
16143
16317
  filteredPoseRef.current = filteredPose;
16144
16318
  if (controlsRef.current?.isInteractionLocked()) {
@@ -16149,7 +16323,7 @@ var Gyro = (0, import_react54.forwardRef)(function Gyro2({
16149
16323
  lastAppliedPoseRef.current = { ...filteredPose };
16150
16324
  controlsRef.current?.setGyroPose(filteredPose);
16151
16325
  }
16152
- });
16326
+ }, -1);
16153
16327
  return null;
16154
16328
  });
16155
16329
 
@@ -16179,9 +16353,9 @@ async function detectWebVRCapabilities() {
16179
16353
  // src/webvr/reticle.tsx
16180
16354
  var import_fiber28 = require("@react-three/fiber");
16181
16355
  var import_react55 = require("react");
16182
- var import_three37 = require("three");
16356
+ var import_three38 = require("three");
16183
16357
  var import_jsx_runtime38 = require("react/jsx-runtime");
16184
- var CENTER_NDC = new import_three37.Vector2(0, 0);
16358
+ var CENTER_NDC = new import_three38.Vector2(0, 0);
16185
16359
  var HUD_DISTANCE = 2;
16186
16360
  var RETICLE_SCALE = 1;
16187
16361
  var RETICLE_RENDER_ORDER = 1e5;
@@ -16266,8 +16440,8 @@ function WebVRReticle({
16266
16440
  }) {
16267
16441
  const groupRef = (0, import_react55.useRef)(null);
16268
16442
  const ringMeshRef = (0, import_react55.useRef)(null);
16269
- const directionRef = (0, import_react55.useRef)(new import_three37.Vector3());
16270
- 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());
16271
16445
  const hoveredRef = (0, import_react55.useRef)(null);
16272
16446
  const dwellRef = (0, import_react55.useRef)(0);
16273
16447
  const clickedRef = (0, import_react55.useRef)(false);
@@ -16418,7 +16592,7 @@ function WebVRReticle({
16418
16592
  color: "#ffffff",
16419
16593
  depthTest: false,
16420
16594
  depthWrite: false,
16421
- side: import_three37.DoubleSide,
16595
+ side: import_three38.DoubleSide,
16422
16596
  toneMapped: false,
16423
16597
  transparent: true
16424
16598
  }
@@ -16434,7 +16608,7 @@ function WebVRReticle({
16434
16608
  // src/webvr/stereo.tsx
16435
16609
  var import_fiber29 = require("@react-three/fiber");
16436
16610
  var import_react56 = require("react");
16437
- var import_three38 = require("three");
16611
+ var import_three39 = require("three");
16438
16612
  var vertexShader = `
16439
16613
  varying vec2 vUv;
16440
16614
  void main() {
@@ -16459,26 +16633,26 @@ void main() {
16459
16633
  }
16460
16634
  `;
16461
16635
  function createDistortionResources() {
16462
- const target = new import_three38.WebGLRenderTarget(1, 1, {
16636
+ const target = new import_three39.WebGLRenderTarget(1, 1, {
16463
16637
  depthBuffer: true,
16464
16638
  stencilBuffer: false
16465
16639
  });
16466
- const geometry = new import_three38.PlaneGeometry(2, 2);
16467
- const material = new import_three38.ShaderMaterial({
16640
+ const geometry = new import_three39.PlaneGeometry(2, 2);
16641
+ const material = new import_three39.ShaderMaterial({
16468
16642
  depthTest: false,
16469
16643
  depthWrite: false,
16470
16644
  fragmentShader,
16471
16645
  uniforms: {
16472
- distortion: { value: new import_three38.Vector2() },
16646
+ distortion: { value: new import_three39.Vector2() },
16473
16647
  sourceTexture: { value: target.texture }
16474
16648
  },
16475
16649
  vertexShader
16476
16650
  });
16477
- const mesh = new import_three38.Mesh(geometry, material);
16478
- const scene = new import_three38.Scene();
16651
+ const mesh = new import_three39.Mesh(geometry, material);
16652
+ const scene = new import_three39.Scene();
16479
16653
  scene.add(mesh);
16480
16654
  return {
16481
- camera: new import_three38.OrthographicCamera(-1, 1, 1, -1, 0, 1),
16655
+ camera: new import_three39.OrthographicCamera(-1, 1, 1, -1, 0, 1),
16482
16656
  geometry,
16483
16657
  material,
16484
16658
  mesh,
@@ -16511,15 +16685,15 @@ function WebVRStereoRenderer({
16511
16685
  const runtime = (0, import_react56.useContext)(WebVRRuntimeContext);
16512
16686
  const fallbackStereoRef = (0, import_react56.useRef)(null);
16513
16687
  if (!fallbackStereoRef.current) {
16514
- fallbackStereoRef.current = new import_three38.StereoCamera();
16688
+ fallbackStereoRef.current = new import_three39.StereoCamera();
16515
16689
  }
16516
16690
  const stereo = runtime?.stereoView.stereo ?? fallbackStereoRef.current;
16517
16691
  const stereoRef = (0, import_react56.useRef)(stereo);
16518
16692
  stereoRef.current = stereo;
16519
16693
  const resources = (0, import_react56.useMemo)(createDistortionResources, []);
16520
- const drawingSizeRef = (0, import_react56.useRef)(new import_three38.Vector2());
16521
- const viewportRef = (0, import_react56.useRef)(new import_three38.Vector4());
16522
- 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());
16523
16697
  const originalFovRef = (0, import_react56.useRef)(null);
16524
16698
  const stereoActiveRef = (0, import_react56.useRef)(false);
16525
16699
  const profileRef = (0, import_react56.useRef)(profile);
@@ -16537,7 +16711,7 @@ function WebVRStereoRenderer({
16537
16711
  (0, import_react56.useEffect)(() => {
16538
16712
  const originalRender = gl.render.bind(gl);
16539
16713
  gl.render = (sceneToRender, cameraToRender) => {
16540
- if (!stereoActiveRef.current || !(cameraToRender instanceof import_three38.PerspectiveCamera)) {
16714
+ if (!stereoActiveRef.current || !(cameraToRender instanceof import_three39.PerspectiveCamera)) {
16541
16715
  originalRender(sceneToRender, cameraToRender);
16542
16716
  return;
16543
16717
  }
@@ -16612,7 +16786,7 @@ function WebVRStereoRenderer({
16612
16786
  if (runtime) {
16613
16787
  runtime.stereoView.active = fallback;
16614
16788
  }
16615
- if (fallback && camera instanceof import_three38.PerspectiveCamera) {
16789
+ if (fallback && camera instanceof import_three39.PerspectiveCamera) {
16616
16790
  syncStereoCameras(
16617
16791
  stereoRef.current,
16618
16792
  camera,
@@ -16623,7 +16797,7 @@ function WebVRStereoRenderer({
16623
16797
  );
16624
16798
  return;
16625
16799
  }
16626
- if (originalFovRef.current !== null && camera instanceof import_three38.PerspectiveCamera) {
16800
+ if (originalFovRef.current !== null && camera instanceof import_three39.PerspectiveCamera) {
16627
16801
  camera.fov = originalFovRef.current;
16628
16802
  camera.updateProjectionMatrix();
16629
16803
  originalFovRef.current = null;
@@ -17305,7 +17479,7 @@ function usePanoViewer() {
17305
17479
  // src/video/pano-video.tsx
17306
17480
  var import_fiber31 = require("@react-three/fiber");
17307
17481
  var import_react61 = require("react");
17308
- var import_three39 = require("three");
17482
+ var import_three40 = require("three");
17309
17483
  var import_jsx_runtime40 = require("react/jsx-runtime");
17310
17484
  var EMPTY_TRACKS = [];
17311
17485
  var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
@@ -17382,8 +17556,8 @@ function findTextTrack(video, tracks, trackId) {
17382
17556
  return list.length > 0 ? list[0] : null;
17383
17557
  }
17384
17558
  function applyEquirectangularLayout(texture, anisotropy) {
17385
- texture.colorSpace = import_three39.SRGBColorSpace;
17386
- texture.wrapS = import_three39.RepeatWrapping;
17559
+ texture.colorSpace = import_three40.SRGBColorSpace;
17560
+ texture.wrapS = import_three40.RepeatWrapping;
17387
17561
  texture.repeat.x = -1;
17388
17562
  texture.offset.x = 1;
17389
17563
  texture.anisotropy = anisotropy;
@@ -17402,7 +17576,7 @@ function usePosterTexture2(poster, onError) {
17402
17576
  active = false;
17403
17577
  };
17404
17578
  }
17405
- const loader = new import_three39.TextureLoader();
17579
+ const loader = new import_three40.TextureLoader();
17406
17580
  loader.load(
17407
17581
  poster,
17408
17582
  (loadedTexture) => {
@@ -17414,9 +17588,9 @@ function usePosterTexture2(poster, onError) {
17414
17588
  loadedTexture,
17415
17589
  gl.capabilities.getMaxAnisotropy()
17416
17590
  );
17417
- loadedTexture.wrapT = import_three39.RepeatWrapping;
17418
- loadedTexture.magFilter = import_three39.LinearFilter;
17419
- loadedTexture.minFilter = import_three39.LinearMipmapLinearFilter;
17591
+ loadedTexture.wrapT = import_three40.RepeatWrapping;
17592
+ loadedTexture.magFilter = import_three40.LinearFilter;
17593
+ loadedTexture.minFilter = import_three40.LinearMipmapLinearFilter;
17420
17594
  loadedTexture.generateMipmaps = true;
17421
17595
  setTexture(loadedTexture);
17422
17596
  },
@@ -17570,10 +17744,10 @@ function PanoVideo({
17570
17744
  video.muted = true;
17571
17745
  applyInlineVideoPlayback(video, true);
17572
17746
  video.preload = "metadata";
17573
- const texture = new import_three39.VideoTexture(video);
17747
+ const texture = new import_three40.VideoTexture(video);
17574
17748
  applyEquirectangularLayout(texture, 1);
17575
- texture.magFilter = import_three39.LinearFilter;
17576
- texture.minFilter = import_three39.LinearFilter;
17749
+ texture.magFilter = import_three40.LinearFilter;
17750
+ texture.minFilter = import_three40.LinearFilter;
17577
17751
  texture.generateMipmaps = false;
17578
17752
  return { video, texture };
17579
17753
  }, []);
@@ -18009,7 +18183,7 @@ function PanoVideo({
18009
18183
  activeTexture ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
18010
18184
  "mesh",
18011
18185
  {
18012
- rotation: [0, import_three39.MathUtils.degToRad(90 + yawOffset2), 0],
18186
+ rotation: [0, import_three40.MathUtils.degToRad(90 + yawOffset2), 0],
18013
18187
  visible,
18014
18188
  children: [
18015
18189
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
@@ -18017,7 +18191,7 @@ function PanoVideo({
18017
18191
  PanoBasicMaterial,
18018
18192
  {
18019
18193
  map: activeTexture,
18020
- side: import_three39.BackSide,
18194
+ side: import_three40.BackSide,
18021
18195
  toneMapped: false
18022
18196
  }
18023
18197
  )