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]));
}
}
}