Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified apps/editor/public/items/ceiling-fan/model.glb
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Mesh,
MeshBasicMaterial,
type Object3D,
type PerspectiveCamera,
Quaternion,
Vector3,
} from 'three'
Expand All @@ -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
Expand Down Expand Up @@ -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])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stacked FOV restores wrong value

Medium Severity

When WalkthroughControls and GlbWalkthroughController are both in the canvas, each FOV effect saves whatever cam.fov is at run time. If the GLB effect runs after the parametric one, its cleanup restores 60° instead of the original orbit FOV, leaving wide-angle framing after walkthrough ends.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 70acf89. Configure here.


useEffect(() => {
worldRef.current = world
if (world) {
Expand Down
22 changes: 21 additions & 1 deletion packages/viewer/src/components/viewer/walkthrough-controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
Expand Down