Skip to content
Source
Sign inSign up

deviceViewSnap.ts

25 lines881 Bytes

1import { Quaternion, Vector3 } from "three";
2const y = new Vector3(0, 1, 0);
3​
4export function nearestDeviceView<T extends { rotation: Quaternion; yawLimit: number }>(
5 rotation: Quaternion,
6 snaps: readonly T[],
7) {
8 let closest: T | null = null;
9 let distance = Infinity;
10 for (const snap of snaps) {
11 const relative = rotation.clone().multiply(snap.rotation.clone().invert());
12 const turn = 2 * Math.atan2(relative.y, relative.w);
13 const yaw = Math.max(
14 -snap.yawLimit,
15 Math.min(snap.yawLimit, Math.atan2(Math.sin(turn), Math.cos(turn))),
16 );
17 const candidate = snap.rotation.clone().premultiply(new Quaternion().setFromAxisAngle(y, yaw));
18 const nextDistance = candidate.angleTo(rotation);
19 if (nextDistance < distance - 1e-8) {
20 distance = nextDistance;
21 closest = { ...snap, rotation: candidate };
22 }
23 }
24 return closest;