using System; using Luneraria.Core; using UnityEngine; namespace Luneraria.View { /// /// Map and Godot coordinates in Unity. The core works on the map plane (x, y); Godot shows a /// map point at (x, height, y) in a right-handed frame. Unity is left-handed, so x flips: /// Unity = (-x, height, y). The FBX pipeline uses the same conversion (docs/port/U2-WORLD.md), /// so models, world and camera line up, and the picture is Godot's, not its mirror image. /// public static class LuneSpace { public static Vector3 World(Vec2 map, float height) { return new Vector3(-map.X, height, map.Y); } public static Vec2 Map(Vector3 world) { return new Vec2(-world.x, world.z); } public static Vector3 FromGodot(Vector3 godot) { return new Vector3(-godot.x, godot.y, godot.z); } public static Vector3 Direction(Vec2 map) { return new Vector3(-map.X, 0f, map.Y); } /// Rotation that turns a model's front (+Z) towards a map direction. public static Quaternion Facing(Vec2 direction) { Vector3 v = Direction(direction); return v.sqrMagnitude < 1e-12f ? Quaternion.identity : Quaternion.LookRotation(v.normalized, Vector3.up); } /// The core's facing angle (atan2(dx, dy), Godot's rotation.y) as a rotation. public static Quaternion Facing(double angle) { return Facing(new Vec2(Math.Sin(angle), Math.Cos(angle))); } /// /// A Godot transform (basis columns x, y, z and origin, as written by the world bake) in /// Unity: S M S with S = diag(-1, 1, 1). Returns position, rotation and scale; the bake /// only contains rotations with positive scale along the basis axes. /// public static void FromGodot(float[] t, int offset, out Vector3 position, out Quaternion rotation, out Vector3 scale) { var x = new Vector3(t[offset + 0], t[offset + 1], t[offset + 2]); var y = new Vector3(t[offset + 3], t[offset + 4], t[offset + 5]); var z = new Vector3(t[offset + 6], t[offset + 7], t[offset + 8]); // Columns of S B S: -(S bx), S by, S bz. Vector3 ux = -FromGodot(x); Vector3 uy = FromGodot(y); Vector3 uz = FromGodot(z); scale = new Vector3(ux.magnitude, uy.magnitude, uz.magnitude); rotation = Quaternion.LookRotation(uz / Mathf.Max(scale.z, 1e-8f), uy / Mathf.Max(scale.y, 1e-8f)); position = FromGodot(new Vector3(t[offset + 9], t[offset + 10], t[offset + 11])); } } }