@ericchen1990/pano-view 3.6.4 → 3.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +604 -429
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +435 -260
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2537,7 +2537,136 @@ import {
|
|
|
2537
2537
|
useLayoutEffect,
|
|
2538
2538
|
useRef
|
|
2539
2539
|
} from "react";
|
|
2540
|
-
import { Euler, MathUtils, PerspectiveCamera } from "three";
|
|
2540
|
+
import { Euler as Euler2, MathUtils as MathUtils2, PerspectiveCamera } from "three";
|
|
2541
|
+
|
|
2542
|
+
// src/gyro-orientation.ts
|
|
2543
|
+
import { Euler, MathUtils, Quaternion, Vector3 } from "three";
|
|
2544
|
+
|
|
2545
|
+
// src/gyro-types.ts
|
|
2546
|
+
var GYRO_POSE_EPSILON = 0.02;
|
|
2547
|
+
var GYRO_DISCONTINUITY_ANGLE_DEG = 15;
|
|
2548
|
+
var GYRO_DISCONTINUITY_SPEED_DEG_PER_S = 1200;
|
|
2549
|
+
|
|
2550
|
+
// src/gyro-orientation.ts
|
|
2551
|
+
var DEVICE_FORWARD_CORRECTION = new Quaternion().setFromAxisAngle(
|
|
2552
|
+
new Vector3(1, 0, 0),
|
|
2553
|
+
-Math.PI / 2
|
|
2554
|
+
);
|
|
2555
|
+
var SCREEN_AXIS = new Vector3(0, 0, 1);
|
|
2556
|
+
var LOOK_LOCAL = new Vector3(0, 0, -1);
|
|
2557
|
+
var UP_LOCAL = new Vector3(0, 1, 0);
|
|
2558
|
+
var scratchEuler = new Euler(0, 0, 0, "YXZ");
|
|
2559
|
+
var scratchScreenCorrection = new Quaternion();
|
|
2560
|
+
var scratchInvert = new Quaternion();
|
|
2561
|
+
var scratchWithoutRoll = new Quaternion();
|
|
2562
|
+
var scratchForward = new Vector3();
|
|
2563
|
+
var scratchUp = new Vector3();
|
|
2564
|
+
var scratchExpectedUp = new Vector3();
|
|
2565
|
+
var ZENITH_PITCH_DEG = 89;
|
|
2566
|
+
function getScreenOrientationAngle() {
|
|
2567
|
+
if (typeof window === "undefined") {
|
|
2568
|
+
return 0;
|
|
2569
|
+
}
|
|
2570
|
+
const angle = window.screen.orientation?.angle;
|
|
2571
|
+
if (Number.isFinite(angle)) {
|
|
2572
|
+
return angle;
|
|
2573
|
+
}
|
|
2574
|
+
const legacyAngle = window.orientation;
|
|
2575
|
+
return Number.isFinite(legacyAngle) ? legacyAngle : 0;
|
|
2576
|
+
}
|
|
2577
|
+
function normalizeGyroYaw(value) {
|
|
2578
|
+
return ((value + 180) % 360 + 360) % 360 - 180;
|
|
2579
|
+
}
|
|
2580
|
+
function shortestGyroYawDelta(from, to) {
|
|
2581
|
+
return normalizeGyroYaw(to - from);
|
|
2582
|
+
}
|
|
2583
|
+
function deviceOrientationToQuaternion(sample, screenOrientation, target) {
|
|
2584
|
+
const alpha = Number.isFinite(sample.compassHeading) ? 360 - sample.compassHeading : sample.alpha;
|
|
2585
|
+
scratchEuler.set(
|
|
2586
|
+
MathUtils.degToRad(sample.beta),
|
|
2587
|
+
MathUtils.degToRad(alpha),
|
|
2588
|
+
MathUtils.degToRad(-sample.gamma),
|
|
2589
|
+
"YXZ"
|
|
2590
|
+
);
|
|
2591
|
+
scratchScreenCorrection.setFromAxisAngle(
|
|
2592
|
+
SCREEN_AXIS,
|
|
2593
|
+
-MathUtils.degToRad(screenOrientation)
|
|
2594
|
+
);
|
|
2595
|
+
return target.setFromEuler(scratchEuler).multiply(DEVICE_FORWARD_CORRECTION).multiply(scratchScreenCorrection).normalize();
|
|
2596
|
+
}
|
|
2597
|
+
function quaternionToGyroPose(quaternion, previousYaw) {
|
|
2598
|
+
scratchForward.copy(LOOK_LOCAL).applyQuaternion(quaternion);
|
|
2599
|
+
const pitchRad = Math.asin(MathUtils.clamp(scratchForward.y, -1, 1));
|
|
2600
|
+
const pitch = MathUtils.radToDeg(pitchRad);
|
|
2601
|
+
const nearZenith = Math.abs(pitch) >= ZENITH_PITCH_DEG;
|
|
2602
|
+
const yaw = nearZenith && previousYaw !== void 0 ? previousYaw : MathUtils.radToDeg(Math.atan2(scratchForward.x, -scratchForward.z));
|
|
2603
|
+
scratchEuler.set(pitchRad, -MathUtils.degToRad(yaw), 0, "YXZ");
|
|
2604
|
+
scratchWithoutRoll.setFromEuler(scratchEuler);
|
|
2605
|
+
scratchUp.copy(UP_LOCAL).applyQuaternion(quaternion);
|
|
2606
|
+
scratchExpectedUp.copy(UP_LOCAL).applyQuaternion(scratchWithoutRoll);
|
|
2607
|
+
const look = scratchForward;
|
|
2608
|
+
const crossX = scratchUp.y * scratchExpectedUp.z - scratchUp.z * scratchExpectedUp.y;
|
|
2609
|
+
const crossY = scratchUp.z * scratchExpectedUp.x - scratchUp.x * scratchExpectedUp.z;
|
|
2610
|
+
const crossZ = scratchUp.x * scratchExpectedUp.y - scratchUp.y * scratchExpectedUp.x;
|
|
2611
|
+
const sinTwist = crossX * look.x + crossY * look.y + crossZ * look.z;
|
|
2612
|
+
const cosTwist = MathUtils.clamp(scratchExpectedUp.dot(scratchUp), -1, 1);
|
|
2613
|
+
const roll = MathUtils.radToDeg(Math.atan2(sinTwist, cosTwist));
|
|
2614
|
+
return {
|
|
2615
|
+
yaw: normalizeGyroYaw(yaw),
|
|
2616
|
+
pitch,
|
|
2617
|
+
roll
|
|
2618
|
+
};
|
|
2619
|
+
}
|
|
2620
|
+
function createRelativeCalibration(deviceQuaternion, yaw, pitch, target) {
|
|
2621
|
+
scratchInvert.copy(deviceQuaternion).invert();
|
|
2622
|
+
scratchEuler.set(
|
|
2623
|
+
MathUtils.degToRad(pitch),
|
|
2624
|
+
MathUtils.degToRad(-yaw),
|
|
2625
|
+
0,
|
|
2626
|
+
"YXZ"
|
|
2627
|
+
);
|
|
2628
|
+
return target.setFromEuler(scratchEuler).multiply(scratchInvert).normalize();
|
|
2629
|
+
}
|
|
2630
|
+
function applyGyroCalibration(deviceQuaternion, calibration, target, previousYaw) {
|
|
2631
|
+
return quaternionToGyroPose(
|
|
2632
|
+
target.copy(calibration).multiply(deviceQuaternion).normalize(),
|
|
2633
|
+
previousYaw
|
|
2634
|
+
);
|
|
2635
|
+
}
|
|
2636
|
+
function reduceGyroPitchOffset(offset, pitchDelta) {
|
|
2637
|
+
if (offset === 0 || pitchDelta === 0) {
|
|
2638
|
+
return offset;
|
|
2639
|
+
}
|
|
2640
|
+
const absDelta = Math.abs(pitchDelta);
|
|
2641
|
+
if (offset > 0) {
|
|
2642
|
+
return Math.max(0, offset - absDelta);
|
|
2643
|
+
}
|
|
2644
|
+
return Math.min(0, offset + absDelta);
|
|
2645
|
+
}
|
|
2646
|
+
function reclaimGyroOffsets(poseYaw, posePitch, constrainedYaw, constrainedPitch) {
|
|
2647
|
+
return {
|
|
2648
|
+
yaw: shortestGyroYawDelta(poseYaw, constrainedYaw),
|
|
2649
|
+
pitch: constrainedPitch - posePitch
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
function gyroPoseAngleDelta(from, to) {
|
|
2653
|
+
return Math.max(
|
|
2654
|
+
Math.abs(shortestGyroYawDelta(from.yaw, to.yaw)),
|
|
2655
|
+
Math.abs(to.pitch - from.pitch),
|
|
2656
|
+
Math.abs(shortestGyroYawDelta(from.roll, to.roll))
|
|
2657
|
+
);
|
|
2658
|
+
}
|
|
2659
|
+
function shouldReanchorGyro(angleDeltaDegrees, deltaSeconds) {
|
|
2660
|
+
if (!(deltaSeconds > 0) || angleDeltaDegrees <= GYRO_DISCONTINUITY_ANGLE_DEG) {
|
|
2661
|
+
return false;
|
|
2662
|
+
}
|
|
2663
|
+
return angleDeltaDegrees / deltaSeconds >= GYRO_DISCONTINUITY_SPEED_DEG_PER_S;
|
|
2664
|
+
}
|
|
2665
|
+
function posesNearlyEqual(a, b, epsilon = GYRO_POSE_EPSILON) {
|
|
2666
|
+
return Math.abs(shortestGyroYawDelta(a.yaw, b.yaw)) < epsilon && Math.abs(a.pitch - b.pitch) < epsilon && Math.abs(a.roll - b.roll) < epsilon;
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
// src/panorama-view-runtime.tsx
|
|
2541
2670
|
var MAX_PITCH = 90;
|
|
2542
2671
|
var BOUNCE_OVERSHOOT_PITCH = 12;
|
|
2543
2672
|
var BOUNCE_OVERSHOOT_FOV_RATIO = 0.15;
|
|
@@ -2554,7 +2683,7 @@ function clamp(value, min, max) {
|
|
|
2554
2683
|
return Math.max(min, Math.min(max, value));
|
|
2555
2684
|
}
|
|
2556
2685
|
function normalizeYaw(yaw) {
|
|
2557
|
-
return
|
|
2686
|
+
return MathUtils2.euclideanModulo(yaw + 180, 360) - 180;
|
|
2558
2687
|
}
|
|
2559
2688
|
function shortestYawDelta(from, to) {
|
|
2560
2689
|
return normalizeYaw(to - from);
|
|
@@ -2602,6 +2731,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
|
|
|
2602
2731
|
const interactionLockCountRef = useRef(0);
|
|
2603
2732
|
const keyboardActiveRef = useRef(false);
|
|
2604
2733
|
const gyroActiveRef = useRef(false);
|
|
2734
|
+
const gyroPoseDrivingRef = useRef(false);
|
|
2605
2735
|
const gyroPoseRef = useRef({ yaw: 0, pitch: 0, roll: 0 });
|
|
2606
2736
|
const gyroOffsetRef = useRef({ yaw: 0, pitch: 0 });
|
|
2607
2737
|
const gyroTouchModeRef = useRef("full");
|
|
@@ -2610,8 +2740,8 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
|
|
|
2610
2740
|
const optionsRef = useRef(options);
|
|
2611
2741
|
const eventBusRef = useRef(eventBus);
|
|
2612
2742
|
const lastEmittedViewRef = useRef(null);
|
|
2613
|
-
const eulerRef = useRef(new
|
|
2614
|
-
const xrEulerRef = useRef(new
|
|
2743
|
+
const eulerRef = useRef(new Euler2(0, 0, 0, "YXZ"));
|
|
2744
|
+
const xrEulerRef = useRef(new Euler2(0, 0, 0, "YXZ"));
|
|
2615
2745
|
const baseLimitsRef = useRef(viewLimits);
|
|
2616
2746
|
const sceneLimitsRef = useRef(void 0);
|
|
2617
2747
|
const legacyFovRef = useRef({ minFov, maxFov });
|
|
@@ -2940,6 +3070,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
|
|
|
2940
3070
|
gyroOffsetRef.current = { yaw: 0, pitch: 0 };
|
|
2941
3071
|
stopVelocity();
|
|
2942
3072
|
if (!active) {
|
|
3073
|
+
gyroPoseDrivingRef.current = false;
|
|
2943
3074
|
cameraRollRef.current = 0;
|
|
2944
3075
|
dirtyRef.current = true;
|
|
2945
3076
|
}
|
|
@@ -2949,18 +3080,35 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
|
|
|
2949
3080
|
return;
|
|
2950
3081
|
}
|
|
2951
3082
|
const previous = gyroPoseRef.current;
|
|
2952
|
-
const
|
|
3083
|
+
const pitchDelta = pose.pitch - previous.pitch;
|
|
3084
|
+
const viewMovement = Math.abs(shortestYawDelta(previous.yaw, pose.yaw)) + Math.abs(pitchDelta);
|
|
2953
3085
|
const movement = viewMovement + Math.abs(previous.roll - pose.roll);
|
|
2954
|
-
if (movement <
|
|
3086
|
+
if (movement < GYRO_POSE_EPSILON) {
|
|
2955
3087
|
return;
|
|
2956
3088
|
}
|
|
3089
|
+
if (gyroTouchModeRef.current === "full") {
|
|
3090
|
+
gyroOffsetRef.current.pitch = reduceGyroPitchOffset(
|
|
3091
|
+
gyroOffsetRef.current.pitch,
|
|
3092
|
+
pitchDelta
|
|
3093
|
+
);
|
|
3094
|
+
}
|
|
2957
3095
|
gyroPoseRef.current = { ...pose };
|
|
2958
|
-
|
|
3096
|
+
gyroPoseDrivingRef.current = true;
|
|
3097
|
+
const constrained = hardConstrainView({
|
|
2959
3098
|
yaw: pose.yaw + gyroOffsetRef.current.yaw,
|
|
2960
3099
|
pitch: pose.pitch + gyroOffsetRef.current.pitch
|
|
2961
3100
|
});
|
|
3101
|
+
targetViewRef.current = constrained;
|
|
3102
|
+
const reclaimed = reclaimGyroOffsets(
|
|
3103
|
+
pose.yaw,
|
|
3104
|
+
pose.pitch,
|
|
3105
|
+
constrained.yaw,
|
|
3106
|
+
constrained.pitch
|
|
3107
|
+
);
|
|
3108
|
+
gyroOffsetRef.current.yaw = reclaimed.yaw;
|
|
3109
|
+
gyroOffsetRef.current.pitch = reclaimed.pitch;
|
|
2962
3110
|
cameraRollRef.current = pose.roll;
|
|
2963
|
-
if (viewMovement >=
|
|
3111
|
+
if (viewMovement >= GYRO_POSE_EPSILON) {
|
|
2964
3112
|
markDirty();
|
|
2965
3113
|
} else {
|
|
2966
3114
|
dirtyRef.current = true;
|
|
@@ -3006,9 +3154,9 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
|
|
|
3006
3154
|
const xrCamera = gl.xr.getCamera();
|
|
3007
3155
|
xrEulerRef.current.setFromQuaternion(xrCamera.quaternion, "YXZ");
|
|
3008
3156
|
const nextView2 = {
|
|
3009
|
-
yaw: normalizeYaw(-
|
|
3157
|
+
yaw: normalizeYaw(-MathUtils2.radToDeg(xrEulerRef.current.y)),
|
|
3010
3158
|
pitch: clamp(
|
|
3011
|
-
|
|
3159
|
+
MathUtils2.radToDeg(xrEulerRef.current.x),
|
|
3012
3160
|
-MAX_PITCH,
|
|
3013
3161
|
MAX_PITCH
|
|
3014
3162
|
),
|
|
@@ -3038,14 +3186,16 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
|
|
|
3038
3186
|
const completed = progress === 1;
|
|
3039
3187
|
viewRef.current = completed ? { ...navigation.target } : nextView2;
|
|
3040
3188
|
eulerRef.current.set(
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3189
|
+
MathUtils2.degToRad(viewRef.current.pitch),
|
|
3190
|
+
MathUtils2.degToRad(-viewRef.current.yaw),
|
|
3191
|
+
MathUtils2.degToRad(cameraRollRef.current),
|
|
3044
3192
|
"YXZ"
|
|
3045
3193
|
);
|
|
3046
3194
|
camera.quaternion.setFromEuler(eulerRef.current);
|
|
3047
|
-
camera.fov
|
|
3048
|
-
|
|
3195
|
+
if (camera.fov !== viewRef.current.fov) {
|
|
3196
|
+
camera.fov = viewRef.current.fov;
|
|
3197
|
+
camera.updateProjectionMatrix();
|
|
3198
|
+
}
|
|
3049
3199
|
camera.updateMatrixWorld();
|
|
3050
3200
|
const emittedView = { ...viewRef.current };
|
|
3051
3201
|
const lastEmitted2 = lastEmittedViewRef.current;
|
|
@@ -3114,7 +3264,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
|
|
|
3114
3264
|
optionsRef.current.zoomDamping,
|
|
3115
3265
|
DEFAULT_ZOOM_DAMPING
|
|
3116
3266
|
);
|
|
3117
|
-
const rotationFactor = dampingFactor(rotateDamping, deltaSeconds);
|
|
3267
|
+
const rotationFactor = gyroPoseDrivingRef.current ? 1 : dampingFactor(rotateDamping, deltaSeconds);
|
|
3118
3268
|
const zoomFactor = dampingFactor(zoomDamping, deltaSeconds);
|
|
3119
3269
|
const yawDelta = limitedYawDelta(viewRef.current.yaw, targetView.yaw, limitsRef.current.yaw);
|
|
3120
3270
|
const smoothedView = {
|
|
@@ -3125,14 +3275,16 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
|
|
|
3125
3275
|
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;
|
|
3126
3276
|
viewRef.current = hasSettled ? { ...targetView } : smoothedView;
|
|
3127
3277
|
eulerRef.current.set(
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3278
|
+
MathUtils2.degToRad(viewRef.current.pitch),
|
|
3279
|
+
MathUtils2.degToRad(-viewRef.current.yaw),
|
|
3280
|
+
MathUtils2.degToRad(cameraRollRef.current),
|
|
3131
3281
|
"YXZ"
|
|
3132
3282
|
);
|
|
3133
3283
|
camera.quaternion.setFromEuler(eulerRef.current);
|
|
3134
|
-
camera.fov
|
|
3135
|
-
|
|
3284
|
+
if (camera.fov !== viewRef.current.fov) {
|
|
3285
|
+
camera.fov = viewRef.current.fov;
|
|
3286
|
+
camera.updateProjectionMatrix();
|
|
3287
|
+
}
|
|
3136
3288
|
camera.updateMatrixWorld();
|
|
3137
3289
|
const nextView = { ...viewRef.current };
|
|
3138
3290
|
const lastEmitted = lastEmittedViewRef.current;
|
|
@@ -3692,7 +3844,7 @@ import { useFrame as useFrame4, useThree as useThree3 } from "@react-three/fiber
|
|
|
3692
3844
|
import { useContext as useContext5, useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
3693
3845
|
|
|
3694
3846
|
// src/pointer-drag.ts
|
|
3695
|
-
import { Euler as
|
|
3847
|
+
import { Euler as Euler3, MathUtils as MathUtils3, PerspectiveCamera as PerspectiveCamera2, Vector3 as Vector32 } from "three";
|
|
3696
3848
|
var DEFAULT_POINTER_DRAG_SPEED = 0.35;
|
|
3697
3849
|
var POINTER_FOLLOW_TIME_SECONDS = 0.01;
|
|
3698
3850
|
var MIN_VELOCITY_SAMPLE_SECONDS = 1 / 120;
|
|
@@ -3721,18 +3873,18 @@ var PointerDragAnchor = class {
|
|
|
3721
3873
|
this.origin = origin;
|
|
3722
3874
|
this.rect = rect;
|
|
3723
3875
|
this.projection = projection;
|
|
3724
|
-
this.local = new
|
|
3725
|
-
this.rotation = new
|
|
3876
|
+
this.local = new Vector32();
|
|
3877
|
+
this.rotation = new Euler3(0, 0, 0, "YXZ");
|
|
3726
3878
|
const startRay = this.ray(start).clone();
|
|
3727
3879
|
this.baseAzimuth = Math.atan2(startRay.x, -startRay.z);
|
|
3728
3880
|
this.baseElevation = Math.atan2(startRay.y, -startRay.z);
|
|
3729
3881
|
this.anchor = startRay.clone().applyEuler(this.rotation.set(
|
|
3730
|
-
|
|
3731
|
-
|
|
3882
|
+
MathUtils3.degToRad(origin.pitch),
|
|
3883
|
+
MathUtils3.degToRad(-origin.yaw),
|
|
3732
3884
|
0,
|
|
3733
3885
|
"YXZ"
|
|
3734
3886
|
));
|
|
3735
|
-
const originPitch =
|
|
3887
|
+
const originPitch = MathUtils3.degToRad(origin.pitch);
|
|
3736
3888
|
const roots = this.pitchRoots(startRay, originPitch);
|
|
3737
3889
|
this.useSupplementary = Math.abs(roots.supplementary - originPitch) + 1e-6 < Math.abs(roots.principal - originPitch);
|
|
3738
3890
|
}
|
|
@@ -3745,7 +3897,7 @@ var PointerDragAnchor = class {
|
|
|
3745
3897
|
}
|
|
3746
3898
|
/** Pitch roots of the level-camera constraint. The supplementary root is unwrapped toward the press. */
|
|
3747
3899
|
pitchRoots(ray, originPitch) {
|
|
3748
|
-
const latitude = Math.asin(
|
|
3900
|
+
const latitude = Math.asin(MathUtils3.clamp(
|
|
3749
3901
|
this.anchor.y / Math.max(Math.hypot(ray.y, ray.z), 1e-12),
|
|
3750
3902
|
-1,
|
|
3751
3903
|
1
|
|
@@ -3765,28 +3917,28 @@ var PointerDragAnchor = class {
|
|
|
3765
3917
|
x: this.start.x + (point.x - this.start.x) * multiplier,
|
|
3766
3918
|
y: this.start.y + (point.y - this.start.y) * multiplier
|
|
3767
3919
|
});
|
|
3768
|
-
const originPitch =
|
|
3920
|
+
const originPitch = MathUtils3.degToRad(this.origin.pitch);
|
|
3769
3921
|
const roots = this.pitchRoots(ray, originPitch);
|
|
3770
|
-
const exactPitch =
|
|
3922
|
+
const exactPitch = MathUtils3.clamp(
|
|
3771
3923
|
this.useSupplementary ? roots.supplementary : roots.principal,
|
|
3772
3924
|
-Math.PI / 2,
|
|
3773
3925
|
Math.PI / 2
|
|
3774
3926
|
);
|
|
3775
3927
|
const stablePitch = originPitch - (Math.atan2(ray.y, -ray.z) - this.baseElevation);
|
|
3776
3928
|
const fromPole = Math.asin(Math.min(1, Math.hypot(this.anchor.x, this.anchor.z)));
|
|
3777
|
-
const pointerLock =
|
|
3929
|
+
const pointerLock = MathUtils3.smoothstep(fromPole, MathUtils3.degToRad(8), MathUtils3.degToRad(18));
|
|
3778
3930
|
const pitchTurn = Math.atan2(Math.sin(exactPitch - stablePitch), Math.cos(exactPitch - stablePitch));
|
|
3779
|
-
const pitch =
|
|
3931
|
+
const pitch = MathUtils3.clamp(
|
|
3780
3932
|
pointerLock >= 1 ? exactPitch : stablePitch + pointerLock * pitchTurn,
|
|
3781
3933
|
-Math.PI / 2,
|
|
3782
3934
|
Math.PI / 2
|
|
3783
3935
|
);
|
|
3784
3936
|
const pitchedZ = Math.sin(exactPitch) * ray.y + Math.cos(exactPitch) * ray.z;
|
|
3785
3937
|
const exactYaw = Math.atan2(this.anchor.x, -this.anchor.z) - Math.atan2(ray.x, -pitchedZ);
|
|
3786
|
-
const stableYaw =
|
|
3938
|
+
const stableYaw = MathUtils3.degToRad(this.origin.yaw) + Math.atan2(ray.x, -ray.z) - this.baseAzimuth;
|
|
3787
3939
|
const yawTurn = Math.atan2(Math.sin(exactYaw - stableYaw), Math.cos(exactYaw - stableYaw));
|
|
3788
|
-
const yaw =
|
|
3789
|
-
return { yaw: normalizeViewYaw(yaw - this.origin.yaw), pitch:
|
|
3940
|
+
const yaw = MathUtils3.radToDeg(stableYaw + pointerLock * yawTurn);
|
|
3941
|
+
return { yaw: normalizeViewYaw(yaw - this.origin.yaw), pitch: MathUtils3.radToDeg(pitch) - this.origin.pitch };
|
|
3790
3942
|
}
|
|
3791
3943
|
};
|
|
3792
3944
|
function createPointerDrag(camera, element, runtime, source) {
|
|
@@ -5561,10 +5713,10 @@ function usePanoOverlayHost(isFullscreen) {
|
|
|
5561
5713
|
// src/panorama-event-surface.tsx
|
|
5562
5714
|
import { useThree as useThree6 } from "@react-three/fiber";
|
|
5563
5715
|
import { useContext as useContext12, useEffect as useEffect10 } from "react";
|
|
5564
|
-
import { BackSide, Raycaster, Vector2, Vector3 as
|
|
5716
|
+
import { BackSide, Raycaster, Vector2, Vector3 as Vector34 } from "three";
|
|
5565
5717
|
|
|
5566
5718
|
// src/hotspot/coordinates.ts
|
|
5567
|
-
import { MathUtils as
|
|
5719
|
+
import { MathUtils as MathUtils4, Vector3 as Vector33 } from "three";
|
|
5568
5720
|
|
|
5569
5721
|
// src/hotspot/types.ts
|
|
5570
5722
|
var MAX_HOTSPOT_PITCH = 90;
|
|
@@ -5587,13 +5739,13 @@ function normalizePanoYaw(yaw) {
|
|
|
5587
5739
|
if (!Number.isFinite(yaw)) {
|
|
5588
5740
|
return 0;
|
|
5589
5741
|
}
|
|
5590
|
-
return
|
|
5742
|
+
return MathUtils4.euclideanModulo(yaw + 180, 360) - 180;
|
|
5591
5743
|
}
|
|
5592
5744
|
function clampPanoPitch(pitch) {
|
|
5593
5745
|
if (!Number.isFinite(pitch)) {
|
|
5594
5746
|
return 0;
|
|
5595
5747
|
}
|
|
5596
|
-
const clamped =
|
|
5748
|
+
const clamped = MathUtils4.clamp(
|
|
5597
5749
|
pitch,
|
|
5598
5750
|
-MAX_HOTSPOT_PITCH,
|
|
5599
5751
|
MAX_HOTSPOT_PITCH
|
|
@@ -5610,10 +5762,10 @@ function normalizePanoPosition(position) {
|
|
|
5610
5762
|
function panoPositionToVector3(position, radius = 1) {
|
|
5611
5763
|
const normalized = normalizePanoPosition(position);
|
|
5612
5764
|
const safeRadius = Number.isFinite(radius) ? Math.max(0, radius) : 1;
|
|
5613
|
-
const yaw =
|
|
5614
|
-
const pitch =
|
|
5765
|
+
const yaw = MathUtils4.degToRad(normalized.yaw);
|
|
5766
|
+
const pitch = MathUtils4.degToRad(normalized.pitch);
|
|
5615
5767
|
const cosPitch = Math.cos(pitch);
|
|
5616
|
-
return new
|
|
5768
|
+
return new Vector33(
|
|
5617
5769
|
cosPitch * Math.sin(yaw) * safeRadius,
|
|
5618
5770
|
Math.sin(pitch) * safeRadius,
|
|
5619
5771
|
-cosPitch * Math.cos(yaw) * safeRadius
|
|
@@ -5625,9 +5777,9 @@ function vector3ToPanoPosition(vector) {
|
|
|
5625
5777
|
return { yaw: 0, pitch: 0 };
|
|
5626
5778
|
}
|
|
5627
5779
|
return normalizePanoPosition({
|
|
5628
|
-
yaw:
|
|
5629
|
-
pitch:
|
|
5630
|
-
Math.asin(
|
|
5780
|
+
yaw: MathUtils4.radToDeg(Math.atan2(vector.x, -vector.z)),
|
|
5781
|
+
pitch: MathUtils4.radToDeg(
|
|
5782
|
+
Math.asin(MathUtils4.clamp(vector.y / length, -1, 1))
|
|
5631
5783
|
)
|
|
5632
5784
|
});
|
|
5633
5785
|
}
|
|
@@ -5668,7 +5820,7 @@ function PanoramaEventSurface() {
|
|
|
5668
5820
|
const element = gl.domElement;
|
|
5669
5821
|
const ndc = new Vector2();
|
|
5670
5822
|
const raycaster = new Raycaster();
|
|
5671
|
-
const direction = new
|
|
5823
|
+
const direction = new Vector34();
|
|
5672
5824
|
const handleContextMenu = (nativeEvent) => {
|
|
5673
5825
|
const rect = element.getBoundingClientRect();
|
|
5674
5826
|
if (rect.width <= 0 || rect.height <= 0) {
|
|
@@ -7558,8 +7710,8 @@ function WebVRChromeBridge({ host }) {
|
|
|
7558
7710
|
}
|
|
7559
7711
|
|
|
7560
7712
|
// src/webvr/stereo-view.ts
|
|
7561
|
-
import { StereoCamera, Vector3 as
|
|
7562
|
-
var PROJECT = new
|
|
7713
|
+
import { StereoCamera, Vector3 as Vector35 } from "three";
|
|
7714
|
+
var PROJECT = new Vector35();
|
|
7563
7715
|
function createWebVRStereoView() {
|
|
7564
7716
|
return {
|
|
7565
7717
|
active: false,
|
|
@@ -7587,11 +7739,11 @@ function projectStereoHtmlPosition(el, camera, size, eye) {
|
|
|
7587
7739
|
import { useFrame as useFrame7, useThree as useThree8 } from "@react-three/fiber";
|
|
7588
7740
|
import { useXR as useXR2, XROrigin } from "@react-three/xr";
|
|
7589
7741
|
import { useRef as useRef12 } from "react";
|
|
7590
|
-
import { Vector3 as
|
|
7742
|
+
import { Vector3 as Vector36 } from "three";
|
|
7591
7743
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
7592
7744
|
function PanoramaXROrigin() {
|
|
7593
7745
|
const originRef = useRef12(null);
|
|
7594
|
-
const localHeadPositionRef = useRef12(new
|
|
7746
|
+
const localHeadPositionRef = useRef12(new Vector36());
|
|
7595
7747
|
const session2 = useXR2((state) => state.session);
|
|
7596
7748
|
const gl = useThree8((state) => state.gl);
|
|
7597
7749
|
useFrame7(() => {
|
|
@@ -8429,7 +8581,7 @@ function isSnapshotTransition(preset) {
|
|
|
8429
8581
|
// src/scene-transitions/snapshot-hold.tsx
|
|
8430
8582
|
import { useFrame as useFrame8, useThree as useThree9 } from "@react-three/fiber";
|
|
8431
8583
|
import { useEffect as useEffect14, useMemo as useMemo9, useRef as useRef14 } from "react";
|
|
8432
|
-
import { Vector3 as
|
|
8584
|
+
import { Vector3 as Vector38 } from "three";
|
|
8433
8585
|
|
|
8434
8586
|
// src/scene-transitions/overlay-utils.ts
|
|
8435
8587
|
import { PlaneGeometry } from "three";
|
|
@@ -8765,7 +8917,7 @@ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
|
8765
8917
|
function SnapshotHold({ snapshot }) {
|
|
8766
8918
|
const { camera, gl } = useThree9();
|
|
8767
8919
|
const meshRef = useRef14(null);
|
|
8768
|
-
const directionRef = useRef14(new
|
|
8920
|
+
const directionRef = useRef14(new Vector38());
|
|
8769
8921
|
const material = useMemo9(
|
|
8770
8922
|
() => createSnapshotMaterial("crossfade", snapshot.texture),
|
|
8771
8923
|
[snapshot.texture]
|
|
@@ -8856,7 +9008,7 @@ import {
|
|
|
8856
9008
|
PlaneGeometry as PlaneGeometry2,
|
|
8857
9009
|
ShaderMaterial as ShaderMaterial2,
|
|
8858
9010
|
Vector2 as Vector23,
|
|
8859
|
-
Vector3 as
|
|
9011
|
+
Vector3 as Vector39
|
|
8860
9012
|
} from "three";
|
|
8861
9013
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
8862
9014
|
var PARTICLE_GRID = 48;
|
|
@@ -8938,7 +9090,7 @@ function ParticleOverlay({
|
|
|
8938
9090
|
const meshRef = useRef15(null);
|
|
8939
9091
|
const startRef = useRef15(null);
|
|
8940
9092
|
const finishedRef = useRef15(false);
|
|
8941
|
-
const directionRef = useRef15(new
|
|
9093
|
+
const directionRef = useRef15(new Vector39());
|
|
8942
9094
|
const geometry = useMemo10(() => createParticleGeometry(), []);
|
|
8943
9095
|
const material = useMemo10(
|
|
8944
9096
|
() => new ShaderMaterial2({
|
|
@@ -8995,7 +9147,7 @@ function ParticleOverlay({
|
|
|
8995
9147
|
// src/scene-transitions/snapshot-overlay.tsx
|
|
8996
9148
|
import { useFrame as useFrame10, useThree as useThree11 } from "@react-three/fiber";
|
|
8997
9149
|
import { useEffect as useEffect16, useMemo as useMemo11, useRef as useRef16 } from "react";
|
|
8998
|
-
import { Vector3 as
|
|
9150
|
+
import { Vector3 as Vector310 } from "three";
|
|
8999
9151
|
import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
9000
9152
|
function SnapshotOverlay({
|
|
9001
9153
|
snapshot,
|
|
@@ -9008,7 +9160,7 @@ function SnapshotOverlay({
|
|
|
9008
9160
|
const meshRef = useRef16(null);
|
|
9009
9161
|
const startRef = useRef16(null);
|
|
9010
9162
|
const finishedRef = useRef16(false);
|
|
9011
|
-
const directionRef = useRef16(new
|
|
9163
|
+
const directionRef = useRef16(new Vector310());
|
|
9012
9164
|
const material = useMemo11(() => {
|
|
9013
9165
|
if (!isSnapshotTransition(transition.preset)) {
|
|
9014
9166
|
return null;
|
|
@@ -9103,7 +9255,7 @@ import {
|
|
|
9103
9255
|
BackSide as BackSide2,
|
|
9104
9256
|
LinearFilter,
|
|
9105
9257
|
LinearMipmapLinearFilter,
|
|
9106
|
-
MathUtils as
|
|
9258
|
+
MathUtils as MathUtils5,
|
|
9107
9259
|
RepeatWrapping,
|
|
9108
9260
|
SRGBColorSpace,
|
|
9109
9261
|
TextureLoader
|
|
@@ -9469,7 +9621,7 @@ function Sphere({
|
|
|
9469
9621
|
return /* @__PURE__ */ jsxs9(
|
|
9470
9622
|
"mesh",
|
|
9471
9623
|
{
|
|
9472
|
-
rotation: [0,
|
|
9624
|
+
rotation: [0, MathUtils5.degToRad(90 + yawOffset2), 0],
|
|
9473
9625
|
visible,
|
|
9474
9626
|
children: [
|
|
9475
9627
|
/* @__PURE__ */ jsx18("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
|
|
@@ -9841,8 +9993,8 @@ import {
|
|
|
9841
9993
|
Box3,
|
|
9842
9994
|
BufferGeometry,
|
|
9843
9995
|
Float32BufferAttribute,
|
|
9844
|
-
MathUtils as
|
|
9845
|
-
Vector3 as
|
|
9996
|
+
MathUtils as MathUtils6,
|
|
9997
|
+
Vector3 as Vector311
|
|
9846
9998
|
} from "three";
|
|
9847
9999
|
function positiveInteger2(value, name) {
|
|
9848
10000
|
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
@@ -9914,9 +10066,9 @@ function sphereTileRange(address) {
|
|
|
9914
10066
|
};
|
|
9915
10067
|
}
|
|
9916
10068
|
function spherePoint(u, v, yawOffset2 = 0, radius = DEFAULT_PANORAMA_RADIUS) {
|
|
9917
|
-
const yaw = (u - 0.5) * Math.PI * 2 +
|
|
10069
|
+
const yaw = (u - 0.5) * Math.PI * 2 + MathUtils6.degToRad(yawOffset2);
|
|
9918
10070
|
const pitch = (0.5 - v) * Math.PI;
|
|
9919
|
-
return new
|
|
10071
|
+
return new Vector311(
|
|
9920
10072
|
Math.sin(yaw) * Math.cos(pitch) * radius,
|
|
9921
10073
|
Math.sin(pitch) * radius,
|
|
9922
10074
|
-Math.cos(yaw) * Math.cos(pitch) * radius
|
|
@@ -10272,15 +10424,15 @@ import {
|
|
|
10272
10424
|
Matrix4 as Matrix43,
|
|
10273
10425
|
PlaneGeometry as PlaneGeometry3,
|
|
10274
10426
|
PerspectiveCamera as PerspectiveCamera5,
|
|
10275
|
-
Vector3 as
|
|
10427
|
+
Vector3 as Vector313
|
|
10276
10428
|
} from "three";
|
|
10277
10429
|
|
|
10278
10430
|
// src/tile/face-layout.ts
|
|
10279
10431
|
import {
|
|
10280
10432
|
Box3 as Box32,
|
|
10281
|
-
Euler as
|
|
10282
|
-
Quaternion,
|
|
10283
|
-
Vector3 as
|
|
10433
|
+
Euler as Euler4,
|
|
10434
|
+
Quaternion as Quaternion2,
|
|
10435
|
+
Vector3 as Vector312
|
|
10284
10436
|
} from "three";
|
|
10285
10437
|
var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
|
|
10286
10438
|
var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
|
|
@@ -10332,8 +10484,8 @@ function getFaceQuaternion(face) {
|
|
|
10332
10484
|
return cached;
|
|
10333
10485
|
}
|
|
10334
10486
|
const transform = getFaceTransform(face);
|
|
10335
|
-
const quaternion = new
|
|
10336
|
-
new
|
|
10487
|
+
const quaternion = new Quaternion2().setFromEuler(
|
|
10488
|
+
new Euler4(...transform.rotation, "XYZ")
|
|
10337
10489
|
);
|
|
10338
10490
|
faceQuaternionCache.set(face, quaternion);
|
|
10339
10491
|
return quaternion;
|
|
@@ -10344,12 +10496,12 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
|
|
|
10344
10496
|
const halfWidth = local.width / 2;
|
|
10345
10497
|
const halfHeight = local.height / 2;
|
|
10346
10498
|
const quaternion = getFaceQuaternion(address.face);
|
|
10347
|
-
const position = new
|
|
10499
|
+
const position = new Vector312(...transform.position);
|
|
10348
10500
|
const corners = [
|
|
10349
|
-
new
|
|
10350
|
-
new
|
|
10351
|
-
new
|
|
10352
|
-
new
|
|
10501
|
+
new Vector312(local.x - halfWidth, local.y - halfHeight, 0),
|
|
10502
|
+
new Vector312(local.x + halfWidth, local.y - halfHeight, 0),
|
|
10503
|
+
new Vector312(local.x - halfWidth, local.y + halfHeight, 0),
|
|
10504
|
+
new Vector312(local.x + halfWidth, local.y + halfHeight, 0)
|
|
10353
10505
|
];
|
|
10354
10506
|
for (const corner of corners) {
|
|
10355
10507
|
corner.applyQuaternion(quaternion).add(position);
|
|
@@ -10623,8 +10775,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
|
|
|
10623
10775
|
return addresses;
|
|
10624
10776
|
}
|
|
10625
10777
|
function centerFacingAddress(candidates, camera) {
|
|
10626
|
-
const direction = camera.getWorldDirection(new
|
|
10627
|
-
const center = new
|
|
10778
|
+
const direction = camera.getWorldDirection(new Vector313());
|
|
10779
|
+
const center = new Vector313();
|
|
10628
10780
|
let bestCandidate = candidates[0];
|
|
10629
10781
|
let bestAlignment = -Infinity;
|
|
10630
10782
|
for (const candidate of candidates) {
|
|
@@ -11557,16 +11709,16 @@ import {
|
|
|
11557
11709
|
import {
|
|
11558
11710
|
Box3 as Box34,
|
|
11559
11711
|
EdgesGeometry,
|
|
11560
|
-
MathUtils as
|
|
11712
|
+
MathUtils as MathUtils9,
|
|
11561
11713
|
Matrix4 as Matrix44,
|
|
11562
11714
|
PerspectiveCamera as PerspectiveCamera8,
|
|
11563
11715
|
Plane,
|
|
11564
11716
|
PlaneGeometry as PlaneGeometry4,
|
|
11565
|
-
Quaternion as
|
|
11717
|
+
Quaternion as Quaternion4,
|
|
11566
11718
|
Ray,
|
|
11567
11719
|
Raycaster as Raycaster2,
|
|
11568
11720
|
Vector2 as Vector24,
|
|
11569
|
-
Vector3 as
|
|
11721
|
+
Vector3 as Vector317
|
|
11570
11722
|
} from "three";
|
|
11571
11723
|
|
|
11572
11724
|
// src/hotspot/drag-session.ts
|
|
@@ -11632,6 +11784,7 @@ function trackPointerDrag(source, element, pointerId, onMove, onEnd) {
|
|
|
11632
11784
|
element.addEventListener("lostpointercapture", onLostCapture);
|
|
11633
11785
|
return stop;
|
|
11634
11786
|
}
|
|
11787
|
+
var CAPTURE = { capture: true };
|
|
11635
11788
|
function suppressFollowingClick(target) {
|
|
11636
11789
|
let cleaned = false;
|
|
11637
11790
|
const cleanup = () => {
|
|
@@ -11639,8 +11792,8 @@ function suppressFollowingClick(target) {
|
|
|
11639
11792
|
return;
|
|
11640
11793
|
}
|
|
11641
11794
|
cleaned = true;
|
|
11642
|
-
target.removeEventListener("click", swallowClick,
|
|
11643
|
-
target.removeEventListener("pointerdown", cancel,
|
|
11795
|
+
target.removeEventListener("click", swallowClick, CAPTURE);
|
|
11796
|
+
target.removeEventListener("pointerdown", cancel, CAPTURE);
|
|
11644
11797
|
};
|
|
11645
11798
|
const swallowClick = (event) => {
|
|
11646
11799
|
event.preventDefault();
|
|
@@ -11651,8 +11804,8 @@ function suppressFollowingClick(target) {
|
|
|
11651
11804
|
const cancel = () => {
|
|
11652
11805
|
cleanup();
|
|
11653
11806
|
};
|
|
11654
|
-
target.addEventListener("click", swallowClick,
|
|
11655
|
-
target.addEventListener("pointerdown", cancel,
|
|
11807
|
+
target.addEventListener("click", swallowClick, CAPTURE);
|
|
11808
|
+
target.addEventListener("pointerdown", cancel, CAPTURE);
|
|
11656
11809
|
setTimeout(cleanup, CLICK_SUPPRESS_MS);
|
|
11657
11810
|
}
|
|
11658
11811
|
|
|
@@ -11668,7 +11821,7 @@ import {
|
|
|
11668
11821
|
useSyncExternalStore as useSyncExternalStore7
|
|
11669
11822
|
} from "react";
|
|
11670
11823
|
import { createRoot } from "react-dom/client";
|
|
11671
|
-
import { Vector3 as
|
|
11824
|
+
import { Vector3 as Vector314 } from "three";
|
|
11672
11825
|
import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
11673
11826
|
function useFallbackStereoView() {
|
|
11674
11827
|
const runtime = useContext20(WebVRRuntimeContext);
|
|
@@ -11691,7 +11844,7 @@ function ProjectedHtml({
|
|
|
11691
11844
|
const { camera, gl, events, size } = useThree17();
|
|
11692
11845
|
const group = useRef23(null);
|
|
11693
11846
|
const overlay = useRef23(null);
|
|
11694
|
-
const scratch = useRef23(new
|
|
11847
|
+
const scratch = useRef23(new Vector314());
|
|
11695
11848
|
const target = events.connected || gl.domElement.parentElement;
|
|
11696
11849
|
const updatePosition = () => {
|
|
11697
11850
|
const anchor = group.current;
|
|
@@ -11892,19 +12045,19 @@ function HotspotTooltip({
|
|
|
11892
12045
|
|
|
11893
12046
|
// src/hotspot/transform.ts
|
|
11894
12047
|
import {
|
|
11895
|
-
MathUtils as
|
|
12048
|
+
MathUtils as MathUtils7,
|
|
11896
12049
|
PerspectiveCamera as PerspectiveCamera6,
|
|
11897
|
-
Vector3 as
|
|
12050
|
+
Vector3 as Vector315
|
|
11898
12051
|
} from "three";
|
|
11899
|
-
var LOCAL_FORWARD = new
|
|
11900
|
-
var CAMERA_POSITION = new
|
|
12052
|
+
var LOCAL_FORWARD = new Vector315(0, 0, 1);
|
|
12053
|
+
var CAMERA_POSITION = new Vector315();
|
|
11901
12054
|
function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight, distance) {
|
|
11902
12055
|
if (orientation2 === "billboard") {
|
|
11903
12056
|
group.quaternion.copy(camera.quaternion);
|
|
11904
12057
|
} else {
|
|
11905
12058
|
group.quaternion.copy(surfaceQuaternion3);
|
|
11906
12059
|
}
|
|
11907
|
-
group.rotateOnAxis(LOCAL_FORWARD,
|
|
12060
|
+
group.rotateOnAxis(LOCAL_FORWARD, MathUtils7.degToRad(-rotation));
|
|
11908
12061
|
let scaleFactor = scaleMode === "fixed" && camera instanceof PerspectiveCamera6 ? fixedScaleFactor(camera.fov, referenceFov) : 1;
|
|
11909
12062
|
if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof PerspectiveCamera6) {
|
|
11910
12063
|
group.updateWorldMatrix(true, false);
|
|
@@ -11921,15 +12074,15 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
|
|
|
11921
12074
|
group.updateMatrixWorld();
|
|
11922
12075
|
}
|
|
11923
12076
|
function fixedScaleFactor(cameraFov, referenceFov) {
|
|
11924
|
-
const safeReferenceFov =
|
|
11925
|
-
return Math.tan(
|
|
12077
|
+
const safeReferenceFov = MathUtils7.clamp(referenceFov, 1, 179);
|
|
12078
|
+
return Math.tan(MathUtils7.degToRad(cameraFov) / 2) / Math.tan(MathUtils7.degToRad(safeReferenceFov) / 2);
|
|
11926
12079
|
}
|
|
11927
12080
|
function selectionFrameScale(worldScaleX, worldScaleY, cameraSpaceDepth, fovDegrees, viewportHeight, outsetPixels) {
|
|
11928
12081
|
const pixels = Number.isFinite(outsetPixels) && outsetPixels > 0 ? outsetPixels : 0;
|
|
11929
12082
|
const depth = Number.isFinite(cameraSpaceDepth) ? Math.max(cameraSpaceDepth, 1e-4) : 1e-4;
|
|
11930
12083
|
const height = Number.isFinite(viewportHeight) ? Math.max(viewportHeight, 1) : 1;
|
|
11931
|
-
const fov = Number.isFinite(fovDegrees) ?
|
|
11932
|
-
const pixelsPerWorldUnit = height / (2 * Math.tan(
|
|
12084
|
+
const fov = Number.isFinite(fovDegrees) ? MathUtils7.clamp(fovDegrees, 1, 179) : 75;
|
|
12085
|
+
const pixelsPerWorldUnit = height / (2 * Math.tan(MathUtils7.degToRad(fov) * 0.5) * depth);
|
|
11933
12086
|
const axis = (worldScale) => {
|
|
11934
12087
|
const pixelsPerLocalUnit = pixelsPerWorldUnit * Math.abs(worldScale);
|
|
11935
12088
|
if (pixelsPerLocalUnit < 1e-4) {
|
|
@@ -11945,12 +12098,12 @@ import { Line } from "@react-three/drei";
|
|
|
11945
12098
|
import { useFrame as useFrame15, useThree as useThree18 } from "@react-three/fiber";
|
|
11946
12099
|
import { useLayoutEffect as useLayoutEffect6, useRef as useRef24 } from "react";
|
|
11947
12100
|
import {
|
|
11948
|
-
MathUtils as
|
|
12101
|
+
MathUtils as MathUtils8,
|
|
11949
12102
|
PerspectiveCamera as PerspectiveCamera7,
|
|
11950
|
-
Vector3 as
|
|
12103
|
+
Vector3 as Vector316
|
|
11951
12104
|
} from "three";
|
|
11952
12105
|
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
11953
|
-
var LINE_WORLD_POSITION = new
|
|
12106
|
+
var LINE_WORLD_POSITION = new Vector316();
|
|
11954
12107
|
function applyScreenSpaceDashScale(object, camera, viewportHeight) {
|
|
11955
12108
|
const material = object?.material;
|
|
11956
12109
|
if (!object || typeof material?.dashScale !== "number") {
|
|
@@ -11959,7 +12112,7 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
|
|
|
11959
12112
|
object.getWorldPosition(LINE_WORLD_POSITION);
|
|
11960
12113
|
const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
|
|
11961
12114
|
const fov = camera instanceof PerspectiveCamera7 ? camera.fov : 75;
|
|
11962
|
-
material.dashScale = viewportHeight / (2 * Math.tan(
|
|
12115
|
+
material.dashScale = viewportHeight / (2 * Math.tan(MathUtils8.degToRad(fov) * 0.5) * depth);
|
|
11963
12116
|
}
|
|
11964
12117
|
function resolveDash(dashSize, gapSize) {
|
|
11965
12118
|
if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
|
|
@@ -12028,8 +12181,8 @@ var DRAG_EPSILON_DEGREES = 1e-3;
|
|
|
12028
12181
|
var SELECTION_BORDER_WIDTH = 3;
|
|
12029
12182
|
var SELECTION_BORDER_GAP = 3;
|
|
12030
12183
|
var SELECTION_BORDER_OUTSET = SELECTION_BORDER_GAP + SELECTION_BORDER_WIDTH / 2;
|
|
12031
|
-
var SELECTION_CAMERA_POSITION = new
|
|
12032
|
-
var SELECTION_WORLD_SCALE = new
|
|
12184
|
+
var SELECTION_CAMERA_POSITION = new Vector317();
|
|
12185
|
+
var SELECTION_WORLD_SCALE = new Vector317();
|
|
12033
12186
|
var SELECTION_BORDER_POINTS = [
|
|
12034
12187
|
[-0.5, -0.5, 1e-3],
|
|
12035
12188
|
[0.5, -0.5, 1e-3],
|
|
@@ -12039,25 +12192,25 @@ var SELECTION_BORDER_POINTS = [
|
|
|
12039
12192
|
];
|
|
12040
12193
|
var TOOLTIP_WORLD_BOX = new Box34();
|
|
12041
12194
|
var TOOLTIP_LOCAL_BOX = new Box34();
|
|
12042
|
-
var TOOLTIP_CORNER = new
|
|
12195
|
+
var TOOLTIP_CORNER = new Vector317();
|
|
12043
12196
|
var TOOLTIP_INVERSE = new Matrix44();
|
|
12044
|
-
var TOOLTIP_WORLD_CORNER = new
|
|
12045
|
-
var TOOLTIP_PROJECTED = new
|
|
12046
|
-
var TOOLTIP_RAY_ORIGIN = new
|
|
12047
|
-
var TOOLTIP_RAY_FAR = new
|
|
12048
|
-
var TOOLTIP_RAY_DIRECTION = new
|
|
12197
|
+
var TOOLTIP_WORLD_CORNER = new Vector317();
|
|
12198
|
+
var TOOLTIP_PROJECTED = new Vector317();
|
|
12199
|
+
var TOOLTIP_RAY_ORIGIN = new Vector317();
|
|
12200
|
+
var TOOLTIP_RAY_FAR = new Vector317();
|
|
12201
|
+
var TOOLTIP_RAY_DIRECTION = new Vector317();
|
|
12049
12202
|
var TOOLTIP_RAY = new Ray();
|
|
12050
12203
|
var TOOLTIP_PLANE = new Plane();
|
|
12051
|
-
var TOOLTIP_INTERSECTION = new
|
|
12052
|
-
var TOOLTIP_PLANE_NORMAL = new
|
|
12053
|
-
var TOOLTIP_PLANE_POINT = new
|
|
12204
|
+
var TOOLTIP_INTERSECTION = new Vector317();
|
|
12205
|
+
var TOOLTIP_PLANE_NORMAL = new Vector317();
|
|
12206
|
+
var TOOLTIP_PLANE_POINT = new Vector317();
|
|
12054
12207
|
var HOTSPOT_MODE_RENDERING = {
|
|
12055
12208
|
surface: { orientation: "surface", placement: "surface" },
|
|
12056
12209
|
billboard: { orientation: "billboard", placement: "floating" }
|
|
12057
12210
|
};
|
|
12058
12211
|
function angularSizeToWorldSize(size, radius) {
|
|
12059
|
-
const safeSize = Number.isFinite(size) ?
|
|
12060
|
-
return 2 * radius * Math.tan(
|
|
12212
|
+
const safeSize = Number.isFinite(size) ? MathUtils9.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
|
|
12213
|
+
return 2 * radius * Math.tan(MathUtils9.degToRad(safeSize) / 2);
|
|
12061
12214
|
}
|
|
12062
12215
|
function resolveScale(scale) {
|
|
12063
12216
|
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
@@ -12070,39 +12223,39 @@ function resolveDistance(placement, distance, width, height) {
|
|
|
12070
12223
|
if (!Number.isFinite(distance)) {
|
|
12071
12224
|
return DEFAULT_FLOATING_DISTANCE;
|
|
12072
12225
|
}
|
|
12073
|
-
return
|
|
12226
|
+
return MathUtils9.clamp(Math.abs(distance), 0.1, maximumDistance);
|
|
12074
12227
|
}
|
|
12075
12228
|
function maximumHotspotDistance(width, height) {
|
|
12076
|
-
const safeWidth =
|
|
12229
|
+
const safeWidth = MathUtils9.clamp(
|
|
12077
12230
|
Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
|
|
12078
12231
|
MIN_ANGULAR_SIZE,
|
|
12079
12232
|
MAX_ANGULAR_SIZE
|
|
12080
12233
|
);
|
|
12081
|
-
const safeHeight =
|
|
12234
|
+
const safeHeight = MathUtils9.clamp(
|
|
12082
12235
|
Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
|
|
12083
12236
|
MIN_ANGULAR_SIZE,
|
|
12084
12237
|
MAX_ANGULAR_SIZE
|
|
12085
12238
|
);
|
|
12086
12239
|
const cornerFactor = Math.hypot(
|
|
12087
12240
|
1,
|
|
12088
|
-
Math.tan(
|
|
12089
|
-
Math.tan(
|
|
12241
|
+
Math.tan(MathUtils9.degToRad(safeWidth) / 2),
|
|
12242
|
+
Math.tan(MathUtils9.degToRad(safeHeight) / 2)
|
|
12090
12243
|
);
|
|
12091
12244
|
return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
|
|
12092
12245
|
}
|
|
12093
12246
|
function createSurfaceQuaternion(position) {
|
|
12094
12247
|
const outward = panoPositionToVector3(position).normalize();
|
|
12095
12248
|
const inward = outward.clone().negate();
|
|
12096
|
-
const pitch =
|
|
12097
|
-
const yaw =
|
|
12098
|
-
const localUp = new
|
|
12249
|
+
const pitch = MathUtils9.degToRad(position.pitch);
|
|
12250
|
+
const yaw = MathUtils9.degToRad(position.yaw);
|
|
12251
|
+
const localUp = new Vector317(
|
|
12099
12252
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
12100
12253
|
Math.cos(pitch),
|
|
12101
12254
|
Math.sin(pitch) * Math.cos(yaw)
|
|
12102
12255
|
).normalize();
|
|
12103
12256
|
const localRight = localUp.clone().cross(inward).normalize();
|
|
12104
12257
|
const basis = new Matrix44().makeBasis(localRight, localUp, inward);
|
|
12105
|
-
return new
|
|
12258
|
+
return new Quaternion4().setFromRotationMatrix(basis);
|
|
12106
12259
|
}
|
|
12107
12260
|
function makeInteractionEvent(id, position, event) {
|
|
12108
12261
|
return {
|
|
@@ -12115,7 +12268,7 @@ function makeInteractionEvent(id, position, event) {
|
|
|
12115
12268
|
function angularDistance(a, b) {
|
|
12116
12269
|
const aVector = panoPositionToVector3(a);
|
|
12117
12270
|
const bVector = panoPositionToVector3(b);
|
|
12118
|
-
return
|
|
12271
|
+
return MathUtils9.radToDeg(aVector.angleTo(bVector));
|
|
12119
12272
|
}
|
|
12120
12273
|
var DRAG_POINTER = new Vector24();
|
|
12121
12274
|
var DRAG_RAYCASTER = new Raycaster2();
|
|
@@ -13760,10 +13913,10 @@ import {
|
|
|
13760
13913
|
} from "three";
|
|
13761
13914
|
|
|
13762
13915
|
// src/hotspot/audio-spatial.ts
|
|
13763
|
-
import { MathUtils as
|
|
13764
|
-
var LOOK_DIR = new
|
|
13765
|
-
var SOURCE_DIR = new
|
|
13766
|
-
var RIGHT_DIR = new
|
|
13916
|
+
import { MathUtils as MathUtils10, Vector3 as Vector318 } from "three";
|
|
13917
|
+
var LOOK_DIR = new Vector318();
|
|
13918
|
+
var SOURCE_DIR = new Vector318();
|
|
13919
|
+
var RIGHT_DIR = new Vector318();
|
|
13767
13920
|
function clampAudioVolume(volume) {
|
|
13768
13921
|
if (!Number.isFinite(volume)) {
|
|
13769
13922
|
return 1;
|
|
@@ -13788,11 +13941,11 @@ function lookRangeGain(angleDegrees, range) {
|
|
|
13788
13941
|
function audioSpatialFromView(camera, position, range) {
|
|
13789
13942
|
camera.getWorldDirection(LOOK_DIR);
|
|
13790
13943
|
SOURCE_DIR.copy(panoPositionToVector3(position)).normalize();
|
|
13791
|
-
const angleDegrees =
|
|
13792
|
-
Math.acos(
|
|
13944
|
+
const angleDegrees = MathUtils10.radToDeg(
|
|
13945
|
+
Math.acos(MathUtils10.clamp(LOOK_DIR.dot(SOURCE_DIR), -1, 1))
|
|
13793
13946
|
);
|
|
13794
13947
|
RIGHT_DIR.set(1, 0, 0).applyQuaternion(camera.quaternion);
|
|
13795
|
-
const pan =
|
|
13948
|
+
const pan = MathUtils10.clamp(
|
|
13796
13949
|
Math.atan2(SOURCE_DIR.dot(RIGHT_DIR), SOURCE_DIR.dot(LOOK_DIR)) / (Math.PI / 2),
|
|
13797
13950
|
-1,
|
|
13798
13951
|
1
|
|
@@ -14104,7 +14257,7 @@ import {
|
|
|
14104
14257
|
CanvasTexture as CanvasTexture3,
|
|
14105
14258
|
ClampToEdgeWrapping as ClampToEdgeWrapping8,
|
|
14106
14259
|
LinearFilter as LinearFilter10,
|
|
14107
|
-
MathUtils as
|
|
14260
|
+
MathUtils as MathUtils11,
|
|
14108
14261
|
PerspectiveCamera as PerspectiveCamera9,
|
|
14109
14262
|
SRGBColorSpace as SRGBColorSpace9
|
|
14110
14263
|
} from "three";
|
|
@@ -14179,7 +14332,7 @@ function projectedDevicePixels(angleDeg, fovDeg, viewportHeight) {
|
|
|
14179
14332
|
}
|
|
14180
14333
|
const fov = Math.min(179, Math.max(1, resolvePositive(fovDeg, DEFAULT_REFERENCE_FOV2)));
|
|
14181
14334
|
const angle = Math.min(179, Math.max(0.01, Math.abs(angleDeg)));
|
|
14182
|
-
return Math.tan(
|
|
14335
|
+
return Math.tan(MathUtils11.degToRad(angle) / 2) / Math.tan(MathUtils11.degToRad(fov) / 2) * viewportHeight;
|
|
14183
14336
|
}
|
|
14184
14337
|
function snapRasterLongSide(screenLong, layoutLong) {
|
|
14185
14338
|
if (!(screenLong > 0)) {
|
|
@@ -14654,10 +14807,10 @@ import {
|
|
|
14654
14807
|
DoubleSide as DoubleSide5,
|
|
14655
14808
|
Float32BufferAttribute as Float32BufferAttribute2,
|
|
14656
14809
|
Matrix4 as Matrix45,
|
|
14657
|
-
Quaternion as
|
|
14810
|
+
Quaternion as Quaternion5,
|
|
14658
14811
|
ShapeUtils,
|
|
14659
14812
|
Vector2 as Vector26,
|
|
14660
|
-
Vector3 as
|
|
14813
|
+
Vector3 as Vector319
|
|
14661
14814
|
} from "three";
|
|
14662
14815
|
import { jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
14663
14816
|
var POLYGON_RADIUS = 990;
|
|
@@ -14731,7 +14884,7 @@ function polygonContainsDirection(vertices, direction) {
|
|
|
14731
14884
|
}
|
|
14732
14885
|
function fitsHemisphere(vertices) {
|
|
14733
14886
|
const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
|
|
14734
|
-
const candidates = [new
|
|
14887
|
+
const candidates = [new Vector319()];
|
|
14735
14888
|
for (const direction of directions) {
|
|
14736
14889
|
candidates[0].add(direction);
|
|
14737
14890
|
candidates.push(direction.clone());
|
|
@@ -14755,7 +14908,7 @@ function validatePolygonVertices(vertices) {
|
|
|
14755
14908
|
if (hasSelfIntersection(unwrapped)) {
|
|
14756
14909
|
issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
|
|
14757
14910
|
}
|
|
14758
|
-
if (polygonContainsDirection(normalized, new
|
|
14911
|
+
if (polygonContainsDirection(normalized, new Vector319(0, 1, 0)) || polygonContainsDirection(normalized, new Vector319(0, -1, 0))) {
|
|
14759
14912
|
issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
|
|
14760
14913
|
}
|
|
14761
14914
|
if (!fitsHemisphere(normalized)) {
|
|
@@ -14766,7 +14919,7 @@ function validatePolygonVertices(vertices) {
|
|
|
14766
14919
|
function polygonCenter(vertices) {
|
|
14767
14920
|
const sum = vertices.reduce(
|
|
14768
14921
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
14769
|
-
new
|
|
14922
|
+
new Vector319()
|
|
14770
14923
|
);
|
|
14771
14924
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
14772
14925
|
}
|
|
@@ -14775,12 +14928,12 @@ function surfaceQuaternion(position) {
|
|
|
14775
14928
|
const inward = outward.clone().negate();
|
|
14776
14929
|
const pitch = position.pitch * Math.PI / 180;
|
|
14777
14930
|
const yaw = position.yaw * Math.PI / 180;
|
|
14778
|
-
const localUp = new
|
|
14931
|
+
const localUp = new Vector319(
|
|
14779
14932
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
14780
14933
|
Math.cos(pitch),
|
|
14781
14934
|
Math.sin(pitch) * Math.cos(yaw)
|
|
14782
14935
|
).normalize();
|
|
14783
|
-
return new
|
|
14936
|
+
return new Quaternion5().setFromRotationMatrix(
|
|
14784
14937
|
new Matrix45().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
14785
14938
|
);
|
|
14786
14939
|
}
|
|
@@ -14788,7 +14941,7 @@ function makeWorldToLocal(center) {
|
|
|
14788
14941
|
return new Matrix45().compose(
|
|
14789
14942
|
panoPositionToVector3(center, POLYGON_RADIUS),
|
|
14790
14943
|
surfaceQuaternion(center),
|
|
14791
|
-
new
|
|
14944
|
+
new Vector319(1, 1, 1)
|
|
14792
14945
|
).invert();
|
|
14793
14946
|
}
|
|
14794
14947
|
function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
|
|
@@ -15014,10 +15167,10 @@ function PolygonHotspot({
|
|
|
15014
15167
|
// src/hotspot/polyline-hotspot.tsx
|
|
15015
15168
|
import { useEffect as useEffect32, useMemo as useMemo21, useRef as useRef33 } from "react";
|
|
15016
15169
|
import {
|
|
15017
|
-
MathUtils as
|
|
15170
|
+
MathUtils as MathUtils12,
|
|
15018
15171
|
Matrix4 as Matrix46,
|
|
15019
|
-
Quaternion as
|
|
15020
|
-
Vector3 as
|
|
15172
|
+
Quaternion as Quaternion6,
|
|
15173
|
+
Vector3 as Vector320
|
|
15021
15174
|
} from "three";
|
|
15022
15175
|
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
15023
15176
|
var POLYLINE_RADIUS = 990;
|
|
@@ -15044,21 +15197,21 @@ function unwrapVertices(vertices) {
|
|
|
15044
15197
|
function polylineCenter(vertices) {
|
|
15045
15198
|
const sum = vertices.reduce(
|
|
15046
15199
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
15047
|
-
new
|
|
15200
|
+
new Vector320()
|
|
15048
15201
|
);
|
|
15049
15202
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
15050
15203
|
}
|
|
15051
15204
|
function surfaceQuaternion2(position) {
|
|
15052
15205
|
const outward = panoPositionToVector3(position).normalize();
|
|
15053
15206
|
const inward = outward.clone().negate();
|
|
15054
|
-
const pitch =
|
|
15055
|
-
const yaw =
|
|
15056
|
-
const localUp = new
|
|
15207
|
+
const pitch = MathUtils12.degToRad(position.pitch);
|
|
15208
|
+
const yaw = MathUtils12.degToRad(position.yaw);
|
|
15209
|
+
const localUp = new Vector320(
|
|
15057
15210
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
15058
15211
|
Math.cos(pitch),
|
|
15059
15212
|
Math.sin(pitch) * Math.cos(yaw)
|
|
15060
15213
|
).normalize();
|
|
15061
|
-
return new
|
|
15214
|
+
return new Quaternion6().setFromRotationMatrix(
|
|
15062
15215
|
new Matrix46().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
15063
15216
|
);
|
|
15064
15217
|
}
|
|
@@ -15066,7 +15219,7 @@ function makeWorldToLocal2(center) {
|
|
|
15066
15219
|
return new Matrix46().compose(
|
|
15067
15220
|
panoPositionToVector3(center, POLYLINE_RADIUS),
|
|
15068
15221
|
surfaceQuaternion2(center),
|
|
15069
|
-
new
|
|
15222
|
+
new Vector320(1, 1, 1)
|
|
15070
15223
|
).invert();
|
|
15071
15224
|
}
|
|
15072
15225
|
function subdivisionSteps(vertices) {
|
|
@@ -15081,7 +15234,7 @@ function subdivisionSteps(vertices) {
|
|
|
15081
15234
|
}
|
|
15082
15235
|
return Math.min(
|
|
15083
15236
|
8,
|
|
15084
|
-
Math.max(1, Math.ceil(
|
|
15237
|
+
Math.max(1, Math.ceil(MathUtils12.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
|
|
15085
15238
|
);
|
|
15086
15239
|
}
|
|
15087
15240
|
function makeLinePositions(vertices, center) {
|
|
@@ -15854,65 +16007,7 @@ import {
|
|
|
15854
16007
|
useRef as useRef35,
|
|
15855
16008
|
useState as useState22
|
|
15856
16009
|
} from "react";
|
|
15857
|
-
|
|
15858
|
-
// src/gyro-orientation.ts
|
|
15859
|
-
import { Euler as Euler4, MathUtils as MathUtils12, Quaternion as Quaternion6, Vector3 as Vector320 } from "three";
|
|
15860
|
-
var DEVICE_FORWARD_CORRECTION = new Quaternion6().setFromAxisAngle(
|
|
15861
|
-
new Vector320(1, 0, 0),
|
|
15862
|
-
-Math.PI / 2
|
|
15863
|
-
);
|
|
15864
|
-
var SCREEN_AXIS = new Vector320(0, 0, 1);
|
|
15865
|
-
function getScreenOrientationAngle() {
|
|
15866
|
-
if (typeof window === "undefined") {
|
|
15867
|
-
return 0;
|
|
15868
|
-
}
|
|
15869
|
-
const angle = window.screen.orientation?.angle;
|
|
15870
|
-
if (Number.isFinite(angle)) {
|
|
15871
|
-
return angle;
|
|
15872
|
-
}
|
|
15873
|
-
const legacyAngle = window.orientation;
|
|
15874
|
-
return Number.isFinite(legacyAngle) ? legacyAngle : 0;
|
|
15875
|
-
}
|
|
15876
|
-
function deviceOrientationToQuaternion(sample, screenOrientation) {
|
|
15877
|
-
const alpha = Number.isFinite(sample.compassHeading) ? 360 - sample.compassHeading : sample.alpha;
|
|
15878
|
-
const deviceEuler = new Euler4(
|
|
15879
|
-
MathUtils12.degToRad(sample.beta),
|
|
15880
|
-
MathUtils12.degToRad(alpha),
|
|
15881
|
-
MathUtils12.degToRad(-sample.gamma),
|
|
15882
|
-
"YXZ"
|
|
15883
|
-
);
|
|
15884
|
-
const screenCorrection = new Quaternion6().setFromAxisAngle(
|
|
15885
|
-
SCREEN_AXIS,
|
|
15886
|
-
-MathUtils12.degToRad(screenOrientation)
|
|
15887
|
-
);
|
|
15888
|
-
return new Quaternion6().setFromEuler(deviceEuler).multiply(DEVICE_FORWARD_CORRECTION).multiply(screenCorrection).normalize();
|
|
15889
|
-
}
|
|
15890
|
-
function quaternionToGyroPose(quaternion) {
|
|
15891
|
-
const euler = new Euler4().setFromQuaternion(quaternion, "YXZ");
|
|
15892
|
-
return {
|
|
15893
|
-
yaw: MathUtils12.radToDeg(-euler.y),
|
|
15894
|
-
pitch: MathUtils12.radToDeg(euler.x),
|
|
15895
|
-
roll: MathUtils12.radToDeg(euler.z)
|
|
15896
|
-
};
|
|
15897
|
-
}
|
|
15898
|
-
function createRelativeCalibration(deviceQuaternion, yaw, pitch) {
|
|
15899
|
-
const targetQuaternion = new Quaternion6().setFromEuler(
|
|
15900
|
-
new Euler4(
|
|
15901
|
-
MathUtils12.degToRad(pitch),
|
|
15902
|
-
MathUtils12.degToRad(-yaw),
|
|
15903
|
-
0,
|
|
15904
|
-
"YXZ"
|
|
15905
|
-
)
|
|
15906
|
-
);
|
|
15907
|
-
return targetQuaternion.multiply(deviceQuaternion.clone().invert()).normalize();
|
|
15908
|
-
}
|
|
15909
|
-
function applyGyroCalibration(deviceQuaternion, calibration) {
|
|
15910
|
-
return quaternionToGyroPose(
|
|
15911
|
-
calibration.clone().multiply(deviceQuaternion).normalize()
|
|
15912
|
-
);
|
|
15913
|
-
}
|
|
15914
|
-
|
|
15915
|
-
// src/gyro.tsx
|
|
16010
|
+
import { Quaternion as Quaternion7 } from "three";
|
|
15916
16011
|
var deviceOrientationPermissionState = "unknown";
|
|
15917
16012
|
function isMobileDevice() {
|
|
15918
16013
|
if (typeof navigator === "undefined") {
|
|
@@ -15920,12 +16015,6 @@ function isMobileDevice() {
|
|
|
15920
16015
|
}
|
|
15921
16016
|
return /Android|iPad|iPhone|iPod|Mobile/i.test(navigator.userAgent) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
|
|
15922
16017
|
}
|
|
15923
|
-
function normalizeYaw2(value) {
|
|
15924
|
-
return ((value + 180) % 360 + 360) % 360 - 180;
|
|
15925
|
-
}
|
|
15926
|
-
function shortestYawDelta2(from, to) {
|
|
15927
|
-
return normalizeYaw2(to - from);
|
|
15928
|
-
}
|
|
15929
16018
|
function finiteOr(value, fallback) {
|
|
15930
16019
|
return Number.isFinite(value) ? value : fallback;
|
|
15931
16020
|
}
|
|
@@ -15935,9 +16024,6 @@ function resolveFriction(value) {
|
|
|
15935
16024
|
function resolveSoftstart(value) {
|
|
15936
16025
|
return Math.max(finiteOr(value, 0.5), 0);
|
|
15937
16026
|
}
|
|
15938
|
-
function posesNearlyEqual(a, b) {
|
|
15939
|
-
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;
|
|
15940
|
-
}
|
|
15941
16027
|
var Gyro = forwardRef3(function Gyro2({
|
|
15942
16028
|
enabled = false,
|
|
15943
16029
|
camroll = true,
|
|
@@ -15957,19 +16043,30 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
15957
16043
|
const eventBus = useContext25(PanoEventBusContext);
|
|
15958
16044
|
const { gl } = useThree25();
|
|
15959
16045
|
const [internallyDisabled, setInternallyDisabled] = useState22(false);
|
|
16046
|
+
const [available, setAvailableState] = useState22(false);
|
|
15960
16047
|
const availableRef = useRef35(false);
|
|
15961
16048
|
const availabilityReportedRef = useRef35(null);
|
|
15962
16049
|
const activeRef = useRef35(false);
|
|
15963
16050
|
const permissionRef = useRef35(deviceOrientationPermissionState);
|
|
15964
16051
|
const absoluteEventSourceRef = useRef35(null);
|
|
15965
|
-
const rawQuaternionRef = useRef35(
|
|
15966
|
-
const
|
|
16052
|
+
const rawQuaternionRef = useRef35(new Quaternion7());
|
|
16053
|
+
const hasRawQuaternionRef = useRef35(false);
|
|
16054
|
+
const calibrationRef = useRef35(new Quaternion7());
|
|
16055
|
+
const hasCalibrationRef = useRef35(false);
|
|
16056
|
+
const calibratedQuaternionRef = useRef35(new Quaternion7());
|
|
15967
16057
|
const absoluteOffsetRef = useRef35({ yaw: 0, pitch: 0 });
|
|
15968
16058
|
const screenAngleRef = useRef35(getScreenOrientationAngle());
|
|
15969
16059
|
const startPoseRef = useRef35(null);
|
|
15970
16060
|
const enabledAtRef = useRef35(0);
|
|
15971
16061
|
const filteredPoseRef = useRef35(null);
|
|
15972
16062
|
const lastAppliedPoseRef = useRef35(null);
|
|
16063
|
+
const lastSamplePoseRef = useRef35(null);
|
|
16064
|
+
const lastSampleAtRef = useRef35(null);
|
|
16065
|
+
const previousYawRef = useRef35(void 0);
|
|
16066
|
+
const absoluteRef = useRef35(absolute);
|
|
16067
|
+
const northRef = useRef35(north);
|
|
16068
|
+
absoluteRef.current = absolute;
|
|
16069
|
+
northRef.current = north;
|
|
15973
16070
|
const callbacksRef = useRef35({
|
|
15974
16071
|
onAvailable,
|
|
15975
16072
|
onUnavailable,
|
|
@@ -16015,13 +16112,14 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16015
16112
|
[eventBus]
|
|
16016
16113
|
);
|
|
16017
16114
|
const setAvailable = useCallback9(
|
|
16018
|
-
(
|
|
16019
|
-
availableRef.current =
|
|
16020
|
-
|
|
16115
|
+
(nextAvailable) => {
|
|
16116
|
+
availableRef.current = nextAvailable;
|
|
16117
|
+
setAvailableState(nextAvailable);
|
|
16118
|
+
if (availabilityReportedRef.current === nextAvailable) {
|
|
16021
16119
|
return;
|
|
16022
16120
|
}
|
|
16023
|
-
availabilityReportedRef.current =
|
|
16024
|
-
emit(
|
|
16121
|
+
availabilityReportedRef.current = nextAvailable;
|
|
16122
|
+
emit(nextAvailable ? "gyroavailable" : "gyrounavailable");
|
|
16025
16123
|
},
|
|
16026
16124
|
[emit]
|
|
16027
16125
|
);
|
|
@@ -16064,37 +16162,54 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16064
16162
|
controlsRef.current?.setGyroActive(false);
|
|
16065
16163
|
emit("gyrodisable");
|
|
16066
16164
|
}
|
|
16067
|
-
|
|
16165
|
+
hasRawQuaternionRef.current = false;
|
|
16068
16166
|
absoluteEventSourceRef.current = null;
|
|
16069
|
-
|
|
16167
|
+
hasCalibrationRef.current = false;
|
|
16070
16168
|
filteredPoseRef.current = null;
|
|
16071
16169
|
lastAppliedPoseRef.current = null;
|
|
16170
|
+
lastSamplePoseRef.current = null;
|
|
16171
|
+
lastSampleAtRef.current = null;
|
|
16172
|
+
previousYawRef.current = void 0;
|
|
16072
16173
|
}, [controlsRef, emit]);
|
|
16073
|
-
const
|
|
16174
|
+
const anchorToView = useCallback9(
|
|
16074
16175
|
(yaw, pitch) => {
|
|
16075
|
-
|
|
16076
|
-
if (!rawQuaternion) {
|
|
16176
|
+
if (!hasRawQuaternionRef.current) {
|
|
16077
16177
|
return;
|
|
16078
16178
|
}
|
|
16079
|
-
|
|
16080
|
-
|
|
16081
|
-
|
|
16082
|
-
|
|
16083
|
-
|
|
16179
|
+
if (absoluteRef.current) {
|
|
16180
|
+
const rawPose = quaternionToGyroPose(
|
|
16181
|
+
rawQuaternionRef.current,
|
|
16182
|
+
previousYawRef.current
|
|
16183
|
+
);
|
|
16184
|
+
previousYawRef.current = rawPose.yaw;
|
|
16084
16185
|
absoluteOffsetRef.current = {
|
|
16085
|
-
yaw:
|
|
16086
|
-
rawPose.yaw + finiteOr(
|
|
16087
|
-
|
|
16186
|
+
yaw: shortestGyroYawDelta(
|
|
16187
|
+
rawPose.yaw + finiteOr(northRef.current, 0),
|
|
16188
|
+
yaw
|
|
16088
16189
|
),
|
|
16089
|
-
pitch:
|
|
16190
|
+
pitch: pitch - rawPose.pitch
|
|
16090
16191
|
};
|
|
16091
16192
|
} else {
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
|
|
16193
|
+
createRelativeCalibration(
|
|
16194
|
+
rawQuaternionRef.current,
|
|
16195
|
+
yaw,
|
|
16196
|
+
pitch,
|
|
16197
|
+
calibrationRef.current
|
|
16096
16198
|
);
|
|
16199
|
+
hasCalibrationRef.current = true;
|
|
16097
16200
|
}
|
|
16201
|
+
},
|
|
16202
|
+
[]
|
|
16203
|
+
);
|
|
16204
|
+
const resetSensor = useCallback9(
|
|
16205
|
+
(yaw, pitch) => {
|
|
16206
|
+
if (!hasRawQuaternionRef.current) {
|
|
16207
|
+
return;
|
|
16208
|
+
}
|
|
16209
|
+
const view = controlsRef.current?.getTargetView();
|
|
16210
|
+
const targetYaw = finiteOr(yaw, view?.yaw ?? 0);
|
|
16211
|
+
const targetPitch = finiteOr(pitch, view?.pitch ?? 0);
|
|
16212
|
+
anchorToView(targetYaw, targetPitch);
|
|
16098
16213
|
startPoseRef.current = {
|
|
16099
16214
|
yaw: targetYaw,
|
|
16100
16215
|
pitch: targetPitch,
|
|
@@ -16102,8 +16217,10 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16102
16217
|
};
|
|
16103
16218
|
enabledAtRef.current = performance.now();
|
|
16104
16219
|
filteredPoseRef.current = null;
|
|
16220
|
+
lastSamplePoseRef.current = null;
|
|
16221
|
+
lastSampleAtRef.current = null;
|
|
16105
16222
|
},
|
|
16106
|
-
[
|
|
16223
|
+
[anchorToView, controlsRef]
|
|
16107
16224
|
);
|
|
16108
16225
|
useImperativeHandle3(
|
|
16109
16226
|
ref,
|
|
@@ -16123,9 +16240,6 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16123
16240
|
useEffect35(() => {
|
|
16124
16241
|
const supported = typeof window !== "undefined" && window.isSecureContext && typeof DeviceOrientationEvent !== "undefined" && (desktopSupport || isMobileDevice());
|
|
16125
16242
|
setAvailable(supported);
|
|
16126
|
-
return () => {
|
|
16127
|
-
availableRef.current = false;
|
|
16128
|
-
};
|
|
16129
16243
|
}, [desktopSupport, setAvailable]);
|
|
16130
16244
|
useEffect35(() => {
|
|
16131
16245
|
controlsRef.current?.setGyroTouchMode(touchMode);
|
|
@@ -16145,7 +16259,7 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16145
16259
|
};
|
|
16146
16260
|
}, [enabled, gl, internallyDisabled, touchMode]);
|
|
16147
16261
|
useEffect35(() => {
|
|
16148
|
-
if (!enabled || internallyDisabled || !
|
|
16262
|
+
if (!enabled || internallyDisabled || !available) {
|
|
16149
16263
|
deactivate();
|
|
16150
16264
|
return;
|
|
16151
16265
|
}
|
|
@@ -16174,10 +16288,12 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16174
16288
|
gamma: event.gamma,
|
|
16175
16289
|
compassHeading: absolute && hasCompassHeading ? compassEvent.webkitCompassHeading : void 0
|
|
16176
16290
|
};
|
|
16177
|
-
|
|
16291
|
+
deviceOrientationToQuaternion(
|
|
16178
16292
|
sample,
|
|
16179
|
-
screenAngleRef.current
|
|
16293
|
+
screenAngleRef.current,
|
|
16294
|
+
rawQuaternionRef.current
|
|
16180
16295
|
);
|
|
16296
|
+
hasRawQuaternionRef.current = true;
|
|
16181
16297
|
if (!activeRef.current) {
|
|
16182
16298
|
const view = controlsRef.current?.getTargetView() ?? {
|
|
16183
16299
|
yaw: 0,
|
|
@@ -16185,11 +16301,13 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16185
16301
|
fov: 75
|
|
16186
16302
|
};
|
|
16187
16303
|
if (!absolute) {
|
|
16188
|
-
|
|
16304
|
+
createRelativeCalibration(
|
|
16189
16305
|
rawQuaternionRef.current,
|
|
16190
16306
|
view.yaw,
|
|
16191
|
-
view.pitch
|
|
16307
|
+
view.pitch,
|
|
16308
|
+
calibrationRef.current
|
|
16192
16309
|
);
|
|
16310
|
+
hasCalibrationRef.current = true;
|
|
16193
16311
|
}
|
|
16194
16312
|
absoluteOffsetRef.current = { yaw: 0, pitch: 0 };
|
|
16195
16313
|
startPoseRef.current = { ...view, roll: 0 };
|
|
@@ -16237,6 +16355,7 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16237
16355
|
};
|
|
16238
16356
|
}, [
|
|
16239
16357
|
absolute,
|
|
16358
|
+
available,
|
|
16240
16359
|
controlsRef,
|
|
16241
16360
|
deactivate,
|
|
16242
16361
|
emit,
|
|
@@ -16245,28 +16364,84 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16245
16364
|
requestPermission
|
|
16246
16365
|
]);
|
|
16247
16366
|
useFrame20((_, deltaSeconds) => {
|
|
16248
|
-
|
|
16249
|
-
if (!activeRef.current || !rawQuaternion) {
|
|
16367
|
+
if (!activeRef.current || !hasRawQuaternionRef.current) {
|
|
16250
16368
|
return;
|
|
16251
16369
|
}
|
|
16252
16370
|
let targetPose;
|
|
16253
16371
|
if (absolute) {
|
|
16254
|
-
const rawPose = quaternionToGyroPose(
|
|
16372
|
+
const rawPose = quaternionToGyroPose(
|
|
16373
|
+
rawQuaternionRef.current,
|
|
16374
|
+
previousYawRef.current
|
|
16375
|
+
);
|
|
16376
|
+
previousYawRef.current = rawPose.yaw;
|
|
16255
16377
|
targetPose = {
|
|
16256
16378
|
yaw: rawPose.yaw + finiteOr(north, 0) + absoluteOffsetRef.current.yaw,
|
|
16257
16379
|
pitch: rawPose.pitch + absoluteOffsetRef.current.pitch,
|
|
16258
16380
|
roll: rawPose.roll
|
|
16259
16381
|
};
|
|
16260
16382
|
} else {
|
|
16261
|
-
|
|
16262
|
-
if (!calibration) {
|
|
16383
|
+
if (!hasCalibrationRef.current) {
|
|
16263
16384
|
return;
|
|
16264
16385
|
}
|
|
16265
|
-
targetPose = applyGyroCalibration(
|
|
16386
|
+
targetPose = applyGyroCalibration(
|
|
16387
|
+
rawQuaternionRef.current,
|
|
16388
|
+
calibrationRef.current,
|
|
16389
|
+
calibratedQuaternionRef.current,
|
|
16390
|
+
previousYawRef.current
|
|
16391
|
+
);
|
|
16392
|
+
previousYawRef.current = targetPose.yaw;
|
|
16266
16393
|
}
|
|
16267
16394
|
if (!camroll) {
|
|
16268
16395
|
targetPose.roll = 0;
|
|
16269
16396
|
}
|
|
16397
|
+
const sampleAt = performance.now();
|
|
16398
|
+
const previousSample = lastSamplePoseRef.current;
|
|
16399
|
+
const previousSampleAt = lastSampleAtRef.current;
|
|
16400
|
+
if (previousSample && previousSampleAt !== null) {
|
|
16401
|
+
const angleDelta = gyroPoseAngleDelta(previousSample, targetPose);
|
|
16402
|
+
const sampleDeltaSeconds = Math.max(
|
|
16403
|
+
(sampleAt - previousSampleAt) / 1e3,
|
|
16404
|
+
deltaSeconds
|
|
16405
|
+
);
|
|
16406
|
+
if (shouldReanchorGyro(angleDelta, sampleDeltaSeconds)) {
|
|
16407
|
+
const view = controlsRef.current?.getTargetView() ?? {
|
|
16408
|
+
yaw: targetPose.yaw,
|
|
16409
|
+
pitch: targetPose.pitch,
|
|
16410
|
+
fov: 75
|
|
16411
|
+
};
|
|
16412
|
+
anchorToView(view.yaw, view.pitch);
|
|
16413
|
+
if (absolute) {
|
|
16414
|
+
const rawPose = quaternionToGyroPose(
|
|
16415
|
+
rawQuaternionRef.current,
|
|
16416
|
+
previousYawRef.current
|
|
16417
|
+
);
|
|
16418
|
+
previousYawRef.current = rawPose.yaw;
|
|
16419
|
+
targetPose = {
|
|
16420
|
+
yaw: rawPose.yaw + finiteOr(north, 0) + absoluteOffsetRef.current.yaw,
|
|
16421
|
+
pitch: rawPose.pitch + absoluteOffsetRef.current.pitch,
|
|
16422
|
+
roll: rawPose.roll
|
|
16423
|
+
};
|
|
16424
|
+
} else {
|
|
16425
|
+
targetPose = applyGyroCalibration(
|
|
16426
|
+
rawQuaternionRef.current,
|
|
16427
|
+
calibrationRef.current,
|
|
16428
|
+
calibratedQuaternionRef.current,
|
|
16429
|
+
previousYawRef.current
|
|
16430
|
+
);
|
|
16431
|
+
previousYawRef.current = targetPose.yaw;
|
|
16432
|
+
}
|
|
16433
|
+
if (!camroll) {
|
|
16434
|
+
targetPose.roll = 0;
|
|
16435
|
+
}
|
|
16436
|
+
filteredPoseRef.current = {
|
|
16437
|
+
yaw: view.yaw,
|
|
16438
|
+
pitch: view.pitch,
|
|
16439
|
+
roll: targetPose.roll
|
|
16440
|
+
};
|
|
16441
|
+
}
|
|
16442
|
+
}
|
|
16443
|
+
lastSamplePoseRef.current = { ...targetPose };
|
|
16444
|
+
lastSampleAtRef.current = sampleAt;
|
|
16270
16445
|
const softstartMs = resolveSoftstart(softstart) * 1e3;
|
|
16271
16446
|
const startPose = startPoseRef.current;
|
|
16272
16447
|
if (startPose && softstartMs > 0) {
|
|
@@ -16275,9 +16450,9 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16275
16450
|
1
|
|
16276
16451
|
);
|
|
16277
16452
|
targetPose = {
|
|
16278
|
-
yaw: startPose.yaw +
|
|
16453
|
+
yaw: startPose.yaw + shortestGyroYawDelta(startPose.yaw, targetPose.yaw) * progress,
|
|
16279
16454
|
pitch: startPose.pitch + (targetPose.pitch - startPose.pitch) * progress,
|
|
16280
|
-
roll: startPose.roll +
|
|
16455
|
+
roll: startPose.roll + shortestGyroYawDelta(startPose.roll, targetPose.roll) * progress
|
|
16281
16456
|
};
|
|
16282
16457
|
if (progress === 1) {
|
|
16283
16458
|
startPoseRef.current = null;
|
|
@@ -16287,9 +16462,9 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16287
16462
|
const retention = resolveFriction(friction);
|
|
16288
16463
|
const follow = retention === 0 ? 1 : 1 - Math.pow(retention, deltaSeconds * 60);
|
|
16289
16464
|
const filteredPose = previous ? {
|
|
16290
|
-
yaw: previous.yaw +
|
|
16465
|
+
yaw: previous.yaw + shortestGyroYawDelta(previous.yaw, targetPose.yaw) * follow,
|
|
16291
16466
|
pitch: previous.pitch + (targetPose.pitch - previous.pitch) * follow,
|
|
16292
|
-
roll: previous.roll +
|
|
16467
|
+
roll: previous.roll + shortestGyroYawDelta(previous.roll, targetPose.roll) * follow
|
|
16293
16468
|
} : targetPose;
|
|
16294
16469
|
filteredPoseRef.current = filteredPose;
|
|
16295
16470
|
if (controlsRef.current?.isInteractionLocked()) {
|
|
@@ -16300,7 +16475,7 @@ var Gyro = forwardRef3(function Gyro2({
|
|
|
16300
16475
|
lastAppliedPoseRef.current = { ...filteredPose };
|
|
16301
16476
|
controlsRef.current?.setGyroPose(filteredPose);
|
|
16302
16477
|
}
|
|
16303
|
-
});
|
|
16478
|
+
}, -1);
|
|
16304
16479
|
return null;
|
|
16305
16480
|
});
|
|
16306
16481
|
|