Spaces:
Sleeping
Sleeping
| /** | |
| * @license | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import * as THREE from "three"; | |
| import { Pilot, AircraftSpecs } from "../types"; | |
| // AXIS CONTRACT (shared across all physics and rendering modules) | |
| // Aircraft local +Z = nose / forward / guns | |
| // Aircraft local +Y = up | |
| // Aircraft local +X = right wing | |
| export const LOCAL_FORWARD = new THREE.Vector3(0, 0, 1); | |
| export const LOCAL_UP = new THREE.Vector3(0, 1, 0); | |
| export const LOCAL_RIGHT = new THREE.Vector3(1, 0, 0); | |
| export function generateId(): string { | |
| return Math.random().toString(36).substring(2, 11); | |
| } | |
| const abTmp = new THREE.Vector3(); | |
| const apTmp = new THREE.Vector3(); | |
| export function closestPointOnSegment( | |
| a: THREE.Vector3, | |
| b: THREE.Vector3, | |
| p: THREE.Vector3, | |
| out: THREE.Vector3 = new THREE.Vector3() | |
| ): THREE.Vector3 { | |
| abTmp.copy(b).sub(a); | |
| const denom = abTmp.lengthSq(); | |
| if (denom < 1e-8) { | |
| return out.copy(a); | |
| } | |
| apTmp.copy(p).sub(a); | |
| const t = THREE.MathUtils.clamp(apTmp.dot(abTmp) / denom, 0, 1); | |
| return out.copy(a).addScaledVector(abTmp, t); | |
| } | |
| export function getPlaneHitRadius(specs: AircraftSpecs): number { | |
| if (specs.class === "HeavyFighter") return 34; | |
| if (specs.class === "Attacker") return 36; | |
| if (specs.class === "Turnfighter") return 24; | |
| return 28; | |
| } | |
| export function getForwardVector(pilot: Pilot): THREE.Vector3 { | |
| const q = new THREE.Quaternion(pilot.qx, pilot.qy, pilot.qz, pilot.qw); | |
| return LOCAL_FORWARD.clone().applyQuaternion(q).normalize(); | |
| } | |
| export function airDensityAtAltitude(altitudeMeters: number): number { | |
| return 1.225 * Math.exp(-Math.max(0, altitudeMeters) / 8500); | |
| } | |
| export function safeNormalize(v: THREE.Vector3, fallback: THREE.Vector3): THREE.Vector3 { | |
| if (v.lengthSq() < 1e-8) return fallback.clone(); | |
| return v.normalize(); | |
| } | |