50 lines
1.4 KiB
TypeScript
50 lines
1.4 KiB
TypeScript
export interface CameraOrbitState {
|
|
yaw: number;
|
|
pitch: number;
|
|
}
|
|
|
|
export interface PlanarMovement {
|
|
x: number;
|
|
z: number;
|
|
}
|
|
|
|
export const DEFAULT_CAMERA_YAW = 0;
|
|
export const DEFAULT_CAMERA_PITCH = Math.atan2(4.45, 7.7);
|
|
export const CAMERA_ORBIT_DISTANCE = Math.hypot(4.45, 7.7);
|
|
export const CAMERA_FOCUS_HEIGHT = 0.65;
|
|
export const CAMERA_LOOK_AHEAD = 2.8;
|
|
export const CAMERA_YAW_SPEED = 2.25;
|
|
export const CAMERA_PITCH_SPEED = 1.25;
|
|
export const MIN_CAMERA_PITCH = 0.24;
|
|
export const MAX_CAMERA_PITCH = 0.9;
|
|
|
|
/** Updates one reusable orbit state without allocating in the render loop. */
|
|
export function updateCameraOrbit(
|
|
orbit: CameraOrbitState,
|
|
lookX: number,
|
|
lookY: number,
|
|
deltaSeconds: number,
|
|
) {
|
|
orbit.yaw -= lookX * CAMERA_YAW_SPEED * deltaSeconds;
|
|
orbit.pitch = Math.min(
|
|
MAX_CAMERA_PITCH,
|
|
Math.max(MIN_CAMERA_PITCH, orbit.pitch + lookY * CAMERA_PITCH_SPEED * deltaSeconds),
|
|
);
|
|
if (orbit.yaw > Math.PI || orbit.yaw < -Math.PI) {
|
|
orbit.yaw = Math.atan2(Math.sin(orbit.yaw), Math.cos(orbit.yaw));
|
|
}
|
|
}
|
|
|
|
/** Converts left-stick input into world movement relative to current camera yaw. */
|
|
export function setCameraRelativeMovement(
|
|
output: PlanarMovement,
|
|
moveX: number,
|
|
moveY: number,
|
|
cameraYaw: number,
|
|
) {
|
|
const sinYaw = Math.sin(cameraYaw);
|
|
const cosYaw = Math.cos(cameraYaw);
|
|
output.x = moveX * cosYaw + moveY * sinYaw;
|
|
output.z = -moveX * sinYaw + moveY * cosYaw;
|
|
}
|