Klima 3D: Flugzeug fliegt nase-vorwärts + Banking in der Kurve
Aus plane-test.html-Kalibrierung bestätigt: Flugzeug soll Nase in airport-lokalem +X halten, Bewegung in +X. updateSinglePlane komplett neu: - Parken am -X-Ende der Runway (vorher +X) - Takeoff rollt -X → +X (vom Vulkan weg, da airport.rotation.y = atan2(-dz, dx) das +X in die Away-Richtung dreht) - Climb-Out in +X-Richtung - Ab der zweiten Climb-Hälfte bankt es leicht (rotation.z wächst) zeigt Seitwärts-Kippen in die Kurve bevor es verschwindet - Approach kommt aus -X-Ferne zurück, Banking löst sich auf - Landung in +X-Richtung (wie Takeoff) - Taxi zurück zur Parkposition: unsichtbar (Teleport OK) Nase-Ausrichtung: rotation.y = airport.rotation.y (kein π-Offset mehr — entspricht der Test-Seite). Pitch für Start/Landung, Roll für Kurvenmanöver. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+37
-35
@@ -4082,55 +4082,57 @@ function updateSingleHeli(v, tNow, airportMesh) {
|
||||
function updateSinglePlane(v, tNow, airportMesh) {
|
||||
const plane = v.plane;
|
||||
const rotY = airportMesh.rotation.y;
|
||||
const RUNWAY_END = 2.2; // lokal, nach 2x-Scale also 4.4 in Welt
|
||||
const RUNWAY_Y = 0.50; // auf Plateau-Oberkante (LIFT+Scale²≈0.26)
|
||||
const RUNWAY_END = 2.2;
|
||||
const RUNWAY_Y = 0.50;
|
||||
|
||||
// Zyklus-Phase — beginnt sofort in Phase 0 (Plane steht auf Runway),
|
||||
// damit beim Bau des Airports das Flugzeug direkt sichtbar ist.
|
||||
const tPhase = (tNow + v.phaseOffset) % PLANE_CYCLE;
|
||||
plane.visible = true;
|
||||
const prop = plane.userData.propRef;
|
||||
|
||||
// Hilfsfunktion: Plane an lokal (lx, ly, lz) mit Rotation-Offset um Y
|
||||
function place(lx, ly, lz, pitch, extraYaw) {
|
||||
// place: Nase zeigt IMMER in Airport-lokales +X (= Start- und Lande-
|
||||
// Richtung, vom Vulkan weg). Banking via roll (rotation.z).
|
||||
function place(lx, ly, lz, pitch, roll) {
|
||||
const w = airportLocalToWorld(airportMesh, lx, ly, lz);
|
||||
plane.position.set(w.x, w.y, w.z);
|
||||
// Basis-Yaw = airportRotY + extraYaw (π für Rollen nach -X, 0 für +X)
|
||||
plane.rotation.set(pitch || 0, rotY + (extraYaw || 0), 0);
|
||||
plane.rotation.set(pitch || 0, rotY, roll || 0);
|
||||
}
|
||||
|
||||
if (tPhase < 14) {
|
||||
// Parken am Runway-Anfang (+X-Ende lokal), Nase zeigt nach Startrichtung (-X)
|
||||
place(RUNWAY_END - 0.3, RUNWAY_Y, 0, 0, Math.PI);
|
||||
// Parken am Runway-Anfang (-X-Ende), Nase zeigt +X
|
||||
place(-(RUNWAY_END - 0.3), RUNWAY_Y, 0, 0, 0);
|
||||
} else if (tPhase < 18) {
|
||||
// Takeoff-Roll: rollt von +X nach -X, hebt am Ende leicht ab
|
||||
// Takeoff-Roll: -X → +X, am Ende leicht abheben
|
||||
const t = (tPhase - 14) / 4;
|
||||
const lx = (RUNWAY_END - 0.3) - t * (2 * RUNWAY_END - 0.6);
|
||||
const ly = RUNWAY_Y + (t > 0.75 ? (t - 0.75) * 0.6 : 0);
|
||||
place(lx, ly, 0, -t * 0.2, Math.PI);
|
||||
} else if (tPhase < 26) {
|
||||
// Climb-Out: steigt auf, entfernt sich weiter in -X-lokal
|
||||
const t = (tPhase - 18) / 8;
|
||||
const lx = -(RUNWAY_END - 0.3) - t * 18;
|
||||
const ly = RUNWAY_Y + 0.15 + t * 4.0;
|
||||
place(lx, ly, 0, -0.28, Math.PI);
|
||||
} else if (tPhase < 80) {
|
||||
// Unterwegs — unsichtbar (kommt von weit draußen zurück)
|
||||
plane.visible = false;
|
||||
} else if (tPhase < 90) {
|
||||
// Approach: kommt in -X-lokal auf die Landung zu, sinkt
|
||||
const t = (tPhase - 80) / 10;
|
||||
const lx = -22 + t * (22 - (RUNWAY_END + 0.3));
|
||||
const ly = 4.2 - t * 3.7; // 4.2 → 0.5
|
||||
place(lx, ly, 0, 0.15 - t * 0.15, Math.PI);
|
||||
} else if (tPhase < 94) {
|
||||
// Landing-Roll: von -X nach +X mit leichtem Pitch-Up am Anfang, dann flach
|
||||
const t = (tPhase - 90) / 4;
|
||||
const lx = -(RUNWAY_END - 0.3) + t * (2 * RUNWAY_END - 0.6);
|
||||
place(lx, RUNWAY_Y, 0, 0, Math.PI);
|
||||
const ly = RUNWAY_Y + (t > 0.75 ? (t - 0.75) * 0.6 : 0);
|
||||
place(lx, ly, 0, -t * 0.2, 0);
|
||||
} else if (tPhase < 26) {
|
||||
// Climb-Out: weiter +X, steigt auf, ab t=0.5 bankt es leicht für die
|
||||
// Kurve (rotation.z Roll, sichtbar seitwärts kippend vorm Abtauchen)
|
||||
const t = (tPhase - 18) / 8;
|
||||
const lx = (RUNWAY_END - 0.3) + t * 18;
|
||||
const ly = RUNWAY_Y + 0.15 + t * 4.0;
|
||||
const roll = t > 0.5 ? (t - 0.5) * 0.9 : 0;
|
||||
place(lx, ly, 0, -0.28, roll);
|
||||
} else if (tPhase < 76) {
|
||||
// Unterwegs — unsichtbar (fliegt irgendwo in der Ferne den Bogen)
|
||||
plane.visible = false;
|
||||
} else if (tPhase < 84) {
|
||||
// Approach: von -X-Ferne zurück zum Landeanflug, Banking löst sich
|
||||
// langsam auf (Kurveneinleitung rückwärts interpretiert)
|
||||
const t = (tPhase - 76) / 8;
|
||||
const lx = -22 + t * (22 - (RUNWAY_END + 0.3)); // -22 → -2.5
|
||||
const ly = 4.2 - t * 3.7;
|
||||
const roll = t < 0.5 ? -(0.5 - t) * 0.9 : 0; // Linkskurven-Roll raus
|
||||
place(lx, ly, 0, 0.15 - t * 0.15, roll);
|
||||
} else if (tPhase < 88) {
|
||||
// Landing-Roll: -X-Ende → +X-Ende (selbe Richtung wie Takeoff)
|
||||
const t = (tPhase - 84) / 4;
|
||||
const lx = -(RUNWAY_END - 0.3) + t * (2 * RUNWAY_END - 0.6);
|
||||
place(lx, RUNWAY_Y, 0, 0, 0);
|
||||
} else {
|
||||
// Taxi + parken (zurück in Startposition)
|
||||
place(RUNWAY_END - 0.3, RUNWAY_Y, 0, 0, Math.PI);
|
||||
// Taxi zurück zur Parkposition — unsichtbar (Teleport OK, kurz)
|
||||
plane.visible = false;
|
||||
}
|
||||
if (prop && plane.visible) prop.rotation.x = tPhase * 22;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user