diff --git a/src/editor/engine/GameplayKits.js b/src/editor/engine/GameplayKits.js index 8573630..6c80889 100644 --- a/src/editor/engine/GameplayKits.js +++ b/src/editor/engine/GameplayKits.js @@ -304,18 +304,23 @@ for (const nm of decorNames) { } } +// Поворот локального вектора (lx,lz) вокруг оси Y на angle — согласованно с +// тем, как Babylon поворачивает меш при rotation.y=angle (левосторонняя СК). +function rotY(lx, lz, a) { + const s = Math.sin(a), c = Math.cos(a); + return { x: lx * c + lz * s, z: -lx * s + lz * c }; +} function place(angle) { - const s = Math.sin(angle), c = Math.cos(angle); - // Полотно: его центр на дуге вокруг петли. - const cx = hingeX + s * halfW; - const cz = hingeZ + c * halfW; + // Полотно: центр = петля + повёрнутый локальный вектор (0, +halfW). + const pc = rotY(0, halfW, angle); + const cx = hingeX + pc.x; + const cz = hingeZ + pc.z; game.self.move(cx, p0.y, cz); game.self.rotate(angle); - // Декор: позиция центра полотна + повёрнутое локальное смещение. + // Декор: центр полотна + повёрнутое локальное смещение (той же формулой). for (const d of decor) { - const rx = d.dx * c - d.dz * s; // поворот смещения вокруг Y - const rz = d.dx * s + d.dz * c; - d.obj.move(cx + rx, p0.y + d.dy, cz + rz); + const r = rotY(d.dx, d.dz, angle); + d.obj.move(cx + r.x, p0.y + d.dy, cz + r.z); if (d.obj.rotate) d.obj.rotate(angle); } }