diff --git a/app/components/maps/LoadedReplays.tsx b/app/components/maps/LoadedReplays.tsx index 6e51696a..be108eed 100644 --- a/app/components/maps/LoadedReplays.tsx +++ b/app/components/maps/LoadedReplays.tsx @@ -220,6 +220,11 @@ const LoadedReplays = ({ onChange={(e: RadioChangeEvent) => { timeLineGlobal.cameraMode = e.target.value; }} className="flex gap-4" > + {timeLineGlobal.followedReplay && ( + + Lock + + )} Target diff --git a/app/components/viewer/ReplayCars.tsx b/app/components/viewer/ReplayCars.tsx index 5fc65fa6..2557535e 100644 --- a/app/components/viewer/ReplayCars.tsx +++ b/app/components/viewer/ReplayCars.tsx @@ -43,6 +43,9 @@ const ReplayCar = ({ let curSample = replay.samples[0]; const smoothSample: ReplayDataPoint = { ...replay.samples[0] }; + // keep track of the camera mode switches + let prevCamMode = timeLineGlobal.cameraMode; + // Get own material from loaded car model const carMesh: THREE.Mesh = fbx.children[0] as THREE.Mesh; const material: THREE.MeshPhongMaterial = carMesh.material as THREE.MeshPhongMaterial; @@ -109,6 +112,21 @@ const ReplayCar = ({ if (orbitControlsRef && orbitControlsRef.current) { orbitControlsRef.current.target.lerp(smoothSample.position, 0.2); + if (timeLineGlobal.cameraMode === CameraMode.Lock) { + // Set camPosRef to camera position only once + if (prevCamMode !== timeLineGlobal.cameraMode) { + camPosRef.current.position.set( + camera.position.x - mesh.current.position.x, + camera.position.y - mesh.current.position.y, + camera.position.z - mesh.current.position.z, + ); + } + // move camera to camPosMesh world position + const camWorldPos: THREE.Vector3 = new THREE.Vector3(); + camPosRef.current.getWorldPosition(camWorldPos); + camera.position.lerp(camWorldPos, 0.3); + } + if (timeLineGlobal.cameraMode === CameraMode.Follow) { // move camPosMesh to Follow position camPosRef.current.rotation.setFromQuaternion(carRotation); @@ -142,6 +160,7 @@ const ReplayCar = ({ } else { stadiumCarMesh.current.scale.lerp(new THREE.Vector3(0.01, 0.01, 0.01), 0.2); } + prevCamMode = timeLineGlobal.cameraMode; } }); diff --git a/app/lib/contexts/SettingsContext.tsx b/app/lib/contexts/SettingsContext.tsx index f02a9a38..868887ac 100644 --- a/app/lib/contexts/SettingsContext.tsx +++ b/app/lib/contexts/SettingsContext.tsx @@ -6,6 +6,7 @@ import { LineType, LineTypes } from '../../components/viewer/ReplayLines'; export enum CameraMode { Target, Follow, + Lock } export interface SettingsContextProps {