feat: start of pitch yaw limits

This commit is contained in:
TrèsAbhi committed 2025-12-20 19:03:57 -06:00
1 parent 57702d8a43
commit ad9f2d8609
5 files changed
+127 -14

No files matched your search

+1
View File
@@ -3,6 +3,7 @@ export * from "./fisherYates";
export * from "./formatCompact";
export * from "./isNumber";
export * from "./NaNFallback";
export * from "./normalizeAngleDeg";
export * from "./normalizeAngleRad";
export * from "./normalToEuler";
export * from "./numberToRomanNumeral";
@@ -0,0 +1,6 @@
export function normalizeAngleDeg(angle: number) {
const newAngle = angle % 360;
if (newAngle > 360) return newAngle - 360;
if (newAngle < -360) return newAngle + 360;
return newAngle;
}
@@ -0,0 +1,102 @@
import { normalizeAngleDeg } from "@blitzkit/core";
import type { PitchLimit } from "@protos/blitz_static_tank_upgrade_single_stage";
import { clamp, degToRad, lerp, radToDeg } from "three/src/math/MathUtils.js";
export function applyPitchYawLimits(
givenPitch: number,
givenYaw: number,
pitchLimitsUp: PitchLimit[],
pitchLimitsDown: PitchLimit[]
) {
const givenYawDeg = normalizeAngleDeg(radToDeg(givenYaw));
const givenPitchDeg = normalizeAngleDeg(radToDeg(givenPitch));
const yawDeg = givenYawDeg;
const yaw = degToRad(givenYawDeg);
let leftLimitUp: PitchLimit | undefined;
let rightLimitUp: PitchLimit | undefined;
let leftLimitDown: PitchLimit | undefined;
let rightLimitDown: PitchLimit | undefined;
for (const limit of pitchLimitsUp) {
const normalizedAngle = normalizeAngleDeg(limit.angle);
if (normalizedAngle <= yawDeg) {
if (
!leftLimitUp ||
normalizeAngleDeg(yawDeg - normalizedAngle) <
normalizeAngleDeg(yawDeg - leftLimitUp.angle)
) {
leftLimitUp = limit;
}
}
if (normalizedAngle >= yawDeg) {
if (
!rightLimitUp ||
normalizeAngleDeg(normalizedAngle - yawDeg) <
normalizeAngleDeg(rightLimitUp.angle - yawDeg)
) {
rightLimitUp = limit;
}
}
}
for (const limit of pitchLimitsDown) {
const normalizedAngle = normalizeAngleDeg(limit.angle);
if (normalizedAngle <= yawDeg) {
if (
!leftLimitDown ||
normalizeAngleDeg(yawDeg - normalizedAngle) <
normalizeAngleDeg(yawDeg - leftLimitDown.angle)
) {
leftLimitDown = limit;
}
}
if (normalizedAngle >= yawDeg) {
if (
!rightLimitDown ||
normalizeAngleDeg(normalizedAngle - yawDeg) <
normalizeAngleDeg(rightLimitDown.angle - yawDeg)
) {
rightLimitDown = limit;
}
}
}
if (!leftLimitUp || !rightLimitUp || !leftLimitDown || !rightLimitDown) {
throw new Error("Pitch limits not found");
}
const spanUp = normalizeAngleDeg(rightLimitUp.angle - leftLimitUp.angle);
const spanDown = normalizeAngleDeg(
rightLimitDown.angle - leftLimitDown.angle
);
let limitUp: number;
let limitDown: number;
if (spanUp === 0) {
limitUp = leftLimitUp.limit;
} else {
const delta = normalizeAngleDeg(givenYawDeg - leftLimitUp.angle);
const t = delta / spanUp;
limitUp = lerp(leftLimitUp.limit, rightLimitUp.limit, t);
}
if (spanDown === 0) {
limitDown = leftLimitDown.limit;
} else {
const delta = normalizeAngleDeg(givenYawDeg - leftLimitDown.angle);
const t = delta / spanDown;
limitDown = lerp(leftLimitDown.limit, rightLimitDown.limit, t);
}
const pitchDeg = clamp(givenPitchDeg, limitUp, -limitDown);
const pitch = degToRad(pitchDeg);
return { pitch, yaw };
}
@@ -4,6 +4,8 @@ import {
StageParameters,
TankAttributeChange_AttributeName,
} from "@protos/blitz_static_tank_upgrade_single_stage";
import { radToDeg } from "three/src/math/MathUtils.js";
import { applyPitchYawLimits } from "./applyPitchYawLimits";
import type { TankState } from "./tankState";
export type CharacteristicOutput = number | null;
@@ -213,23 +215,25 @@ export const characteristics = {
},
gun_depression({ parameters }) {
const pitchLimit = parameters.pitch_limits_down.find(
(pitchLimit) => pitchLimit.angle === 0
return radToDeg(
applyPitchYawLimits(
-Math.PI / 2,
0,
parameters.pitch_limits_up,
parameters.pitch_limits_down
).pitch
);
if (!pitchLimit) throw new Error("No angle 0 depression pitch limit found");
return pitchLimit.limit;
},
gun_elevation({ parameters }) {
const pitchLimit = parameters.pitch_limits_up.find(
(pitchLimit) => pitchLimit.angle === 0
return radToDeg(
applyPitchYawLimits(
Math.PI / 2,
0,
parameters.pitch_limits_up,
parameters.pitch_limits_down
).pitch
);
if (!pitchLimit) throw new Error("No angle 0 elevation pitch limit found");
return pitchLimit.limit;
},
engine_power({ attribute }) {
@@ -50,8 +50,8 @@ export const characteristicsOrder: CharacteristicsOrder = [
{ name: "dispersion", decimals: 3, units: "m" },
{ name: "gun_depression", units: "deg" },
{ name: "gun_elevation", units: "deg" },
{ name: "gun_depression", decimals: 0, units: "deg" },
{ name: "gun_elevation", decimals: 0, units: "deg" },
{ toy: "flexibility" },
],