Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-05-24 20:24:52 +00:00
parent 075ad7aeb8
commit bb50821ec5
+54 -2
View File
@@ -88,8 +88,60 @@ function ViewCubeAnimator() {
return null;
}
function LoadingFallback() {
/** Switches between perspective and orthographic projection while keeping
* the visual framing (position, target, on-screen size of the scene). */
function CameraSwitcher() {
const mode = useModelStore((s) => s.cameraMode);
const { size } = useThree();
// Snapshot current view from whichever camera is active right now, before swap.
const snap = useMemo(() => {
const c = mainCameraRef.current;
const ctrl = mainControlsRef.current;
const target = (ctrl?.target ?? new THREE.Vector3()).clone();
const pos = c ? c.position.clone() : new THREE.Vector3(2, 2, 2);
const up = c ? c.up.clone() : new THREE.Vector3(0, 1, 0);
const dist = pos.distanceTo(target);
// Compute ortho zoom that matches current perspective framing.
let zoom = 100;
if (c && (c as THREE.PerspectiveCamera).isPerspectiveCamera) {
const fov = ((c as THREE.PerspectiveCamera).fov ?? 50) * (Math.PI / 180);
const worldHeight = 2 * Math.max(dist, 0.001) * Math.tan(fov / 2);
zoom = Math.max(1, size.height / Math.max(worldHeight, 1e-6));
} else if (c && (c as THREE.OrthographicCamera).isOrthographicCamera) {
zoom = (c as THREE.OrthographicCamera).zoom;
}
return { target, pos, up, zoom };
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mode]);
// Sync OrbitControls target after camera swap.
useEffect(() => {
const ctrl = mainControlsRef.current;
if (ctrl?.target) ctrl.target.copy(snap.target);
ctrl?.update?.();
}, [snap]);
if (mode === 'ortho') {
return (
<OrthographicCamera
makeDefault
position={snap.pos.toArray()}
up={snap.up.toArray()}
zoom={snap.zoom}
near={-1000}
far={1000}
/>
);
}
return (
<PerspectiveCamera
makeDefault
position={snap.pos.toArray()}
up={snap.up.toArray()}
fov={50}
near={0.001}
far={1000}
/>
);
}
return (
<Html center>
<div className="flex items-center gap-2 rounded-lg bg-card px-4 py-2 text-foreground shadow-lg">