feat(viewer): widen first-person walkthrough FOV to 60°
The walkthrough rode the default 50° orbit camera, which feels cramped on foot. Both walkthrough controllers (baked GlbWalkthroughController and the parametric WalkthroughControls fallback) now set a shared WALKTHROUGH_FOV = 60 on enter and restore the prior FOV on exit, leaving orbit framing untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
69c483b5f2
commit
70acf894d1
@@ -15,6 +15,7 @@ import {
|
||||
Mesh,
|
||||
MeshBasicMaterial,
|
||||
type Object3D,
|
||||
type PerspectiveCamera,
|
||||
Quaternion,
|
||||
Vector3,
|
||||
} from 'three'
|
||||
@@ -24,6 +25,7 @@ import { useGLTFKTX2 } from '../../hooks/use-gltf-ktx2'
|
||||
import { SCENE_LAYER } from '../../lib/layers'
|
||||
import useViewer from '../../store/use-viewer'
|
||||
import BVHEcctrl, { type BVHEcctrlApi, type MovementInput } from './bvh-ecctrl'
|
||||
import { WALKTHROUGH_FOV } from './walkthrough-controls'
|
||||
|
||||
// Eye/capsule geometry mirrors the editor's first-person controller so the
|
||||
// baked walkthrough feels identical. The capsule centre sits below the eye; the
|
||||
@@ -264,6 +266,22 @@ export function GlbWalkthroughController({ url }: { url: string }) {
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Widen FOV while walking; the baked walkthrough rides the default 50° orbit
|
||||
// camera, which feels cramped on foot. Keyed on `camera` so it re-applies if
|
||||
// the instance swaps (e.g. the ortho→perspective switch above), restoring the
|
||||
// prior FOV on exit.
|
||||
useEffect(() => {
|
||||
const cam = camera as PerspectiveCamera
|
||||
if (!cam.isPerspectiveCamera) return
|
||||
const prevFov = cam.fov
|
||||
cam.fov = WALKTHROUGH_FOV
|
||||
cam.updateProjectionMatrix()
|
||||
return () => {
|
||||
cam.fov = prevFov
|
||||
cam.updateProjectionMatrix()
|
||||
}
|
||||
}, [camera])
|
||||
|
||||
useEffect(() => {
|
||||
worldRef.current = world
|
||||
if (world) {
|
||||
|
||||
@@ -3,12 +3,18 @@
|
||||
import { PointerLockControls } from '@react-three/drei'
|
||||
import { useFrame, useThree } from '@react-three/fiber'
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import { Vector3 } from 'three'
|
||||
import { type PerspectiveCamera, Vector3 } from 'three'
|
||||
import useViewer from '../../store/use-viewer'
|
||||
|
||||
const MOVE_SPEED = 5
|
||||
const EYE_HEIGHT = 1.6
|
||||
|
||||
// First-person FOV. The orbit camera is 50° (set on the Canvas), which feels
|
||||
// cramped on foot; ~60° vertical (~90° horizontal at 16:9) restores peripheral
|
||||
// awareness without wide-angle distortion. Applied only while walking — both
|
||||
// walkthrough controllers read this and restore the orbit FOV on exit.
|
||||
export const WALKTHROUGH_FOV = 60
|
||||
|
||||
const _direction = new Vector3()
|
||||
const _forward = new Vector3()
|
||||
const _right = new Vector3()
|
||||
@@ -26,6 +32,20 @@ export const WalkthroughControls = () => {
|
||||
}
|
||||
}, [walkthroughMode, camera])
|
||||
|
||||
// Widen FOV while walking; restore the orbit FOV on exit.
|
||||
useEffect(() => {
|
||||
if (!walkthroughMode) return
|
||||
const cam = camera as PerspectiveCamera
|
||||
if (!cam.isPerspectiveCamera) return
|
||||
const prevFov = cam.fov
|
||||
cam.fov = WALKTHROUGH_FOV
|
||||
cam.updateProjectionMatrix()
|
||||
return () => {
|
||||
cam.fov = prevFov
|
||||
cam.updateProjectionMatrix()
|
||||
}
|
||||
}, [walkthroughMode, camera])
|
||||
|
||||
// Keyboard handlers
|
||||
useEffect(() => {
|
||||
if (!walkthroughMode) return
|
||||
|
||||
Reference in New Issue
Block a user