2024-09-22 21:12:18 -05:00
|
|
|
import {
|
|
|
|
|
normalizeAngleRad,
|
|
|
|
|
type PitchLimits,
|
|
|
|
|
type YawLimits,
|
|
|
|
|
} from '@blitzkit/core';
|
2024-09-14 19:43:14 -05:00
|
|
|
import { clamp } from 'lodash-es';
|
2024-09-22 21:12:18 -05:00
|
|
|
import { degToRad } from 'three/src/math/MathUtils.js';
|
2024-01-06 13:21:11 -06:00
|
|
|
|
2025-08-08 12:29:21 -05:00
|
|
|
export const DEFAULT_PITCH_TRANSITION = 15;
|
|
|
|
|
|
2024-01-06 13:21:11 -06:00
|
|
|
export function applyPitchYawLimits(
|
|
|
|
|
pitch: number, // rad
|
|
|
|
|
yaw: number, // rad
|
|
|
|
|
pitchLimits: PitchLimits, // deg
|
|
|
|
|
yawLimits?: YawLimits, // deg
|
2024-03-12 18:00:00 -05:00
|
|
|
verticalStabilizer = false,
|
2025-03-11 10:13:02 -05:00
|
|
|
downVerticalStabilizer = false,
|
2024-01-06 13:21:11 -06:00
|
|
|
) {
|
|
|
|
|
let newPitch = pitch;
|
|
|
|
|
let newYaw = yaw;
|
|
|
|
|
|
|
|
|
|
if (yawLimits) {
|
2024-03-08 20:43:30 -06:00
|
|
|
newYaw = normalizeAngleRad(
|
2024-03-12 18:00:00 -05:00
|
|
|
clamp(newYaw, -degToRad(yawLimits.max), -degToRad(yawLimits.min)),
|
2024-01-06 13:21:11 -06:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-11 10:13:02 -05:00
|
|
|
const depressionBuff =
|
|
|
|
|
verticalStabilizer || downVerticalStabilizer ? degToRad(3) : 0;
|
2024-08-01 14:16:42 -05:00
|
|
|
const elevationBuff = verticalStabilizer ? degToRad(4) : 0;
|
2024-05-22 13:04:39 -05:00
|
|
|
let lowerPitch = -degToRad(pitchLimits.max) - depressionBuff;
|
|
|
|
|
let upperPitch = -degToRad(pitchLimits.min) + elevationBuff;
|
2025-08-08 12:29:21 -05:00
|
|
|
const transition = degToRad(
|
|
|
|
|
pitchLimits.transition ?? DEFAULT_PITCH_TRANSITION,
|
|
|
|
|
);
|
2024-01-06 13:21:11 -06:00
|
|
|
|
|
|
|
|
if (pitchLimits.back) {
|
2024-03-12 18:00:00 -05:00
|
|
|
const range = degToRad(pitchLimits.back.range);
|
2024-03-08 20:43:30 -06:00
|
|
|
const yawRotatedAbs = Math.abs(normalizeAngleRad(newYaw - Math.PI));
|
2024-01-06 13:21:11 -06:00
|
|
|
|
2025-08-18 11:05:10 -05:00
|
|
|
if (yawRotatedAbs <= range / 2 + transition) {
|
|
|
|
|
if (yawRotatedAbs <= range / 2) {
|
2024-01-06 13:21:11 -06:00
|
|
|
// inside range
|
2024-03-12 18:00:00 -05:00
|
|
|
lowerPitch = -degToRad(pitchLimits.back.max);
|
|
|
|
|
upperPitch = -degToRad(pitchLimits.back.min);
|
2024-01-06 13:21:11 -06:00
|
|
|
} else {
|
|
|
|
|
// inside transition
|
2025-08-18 11:05:10 -05:00
|
|
|
const transitionProgress = (yawRotatedAbs - range / 2) / transition;
|
|
|
|
|
// console.log(transitionProgress);
|
2024-01-06 13:21:11 -06:00
|
|
|
const maxInterpolatedPitch =
|
|
|
|
|
(1 - transitionProgress) * pitchLimits.back.max +
|
|
|
|
|
transitionProgress * pitchLimits.max;
|
|
|
|
|
const minInterpolatedPitch =
|
|
|
|
|
(1 - transitionProgress) * pitchLimits.back.min +
|
|
|
|
|
transitionProgress * pitchLimits.min;
|
|
|
|
|
|
2024-03-12 18:00:00 -05:00
|
|
|
lowerPitch = -degToRad(maxInterpolatedPitch);
|
|
|
|
|
upperPitch = -degToRad(minInterpolatedPitch);
|
2024-01-06 13:21:11 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pitchLimits.front) {
|
2024-03-12 18:00:00 -05:00
|
|
|
const range = degToRad(pitchLimits.front.range);
|
2024-03-08 20:43:30 -06:00
|
|
|
const yawAbs = Math.abs(normalizeAngleRad(newYaw));
|
2024-01-06 13:21:11 -06:00
|
|
|
|
2025-08-18 11:05:10 -05:00
|
|
|
if (yawAbs <= range / 2 + transition) {
|
|
|
|
|
if (yawAbs <= range / 2) {
|
2024-01-06 13:21:11 -06:00
|
|
|
// inside range
|
2024-03-12 18:00:00 -05:00
|
|
|
lowerPitch = -degToRad(pitchLimits.front.max);
|
|
|
|
|
upperPitch = -degToRad(pitchLimits.front.min);
|
2024-01-06 13:21:11 -06:00
|
|
|
} else {
|
|
|
|
|
// inside transition
|
2025-08-18 11:05:10 -05:00
|
|
|
const transitionProgress = (yawAbs - range / 2) / transition;
|
2024-01-06 13:21:11 -06:00
|
|
|
const maxInterpolatedPitch =
|
|
|
|
|
(1 - transitionProgress) * pitchLimits.front.max +
|
|
|
|
|
transitionProgress * pitchLimits.max;
|
|
|
|
|
const minInterpolatedPitch =
|
|
|
|
|
(1 - transitionProgress) * pitchLimits.front.min +
|
|
|
|
|
transitionProgress * pitchLimits.min;
|
|
|
|
|
|
2024-03-12 18:00:00 -05:00
|
|
|
lowerPitch = -degToRad(maxInterpolatedPitch);
|
|
|
|
|
upperPitch = -degToRad(minInterpolatedPitch);
|
2024-01-06 13:21:11 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newPitch = clamp(newPitch, lowerPitch, upperPitch);
|
|
|
|
|
|
2025-08-09 13:30:53 -05:00
|
|
|
return [newPitch, newYaw] as const;
|
2024-01-06 13:21:11 -06:00
|
|
|
}
|