using UnityEngine;
namespace Luneraria.View
{
///
/// The game camera of the reference (scripts/luneraria/view/lune_camera.gd): a perspective
/// three-quarter view whose angle steepens as it zooms out. `zoom` is the visible ground height
/// at the focus; yaw 0 shows Blau's base bottom-left and Rot's top-right, as in Godot.
/// Positions are computed in Godot's frame and converted, so the picture matches Godot's.
///
public static class LuneCameraMath
{
public const float FieldOfView = 34f;
public const float MinZoom = 11f;
public const float MaxZoom = 100f;
public const float DefaultZoom = 34f;
public const float OverviewZoom = 92f;
public const float PitchNear = -48f;
public const float PitchFar = -70f;
public const float FocusLimit = 42f;
public static float PitchFor(float zoom)
{
return Mathf.Lerp(PitchNear, PitchFar, SmoothStep(14f, MaxZoom, zoom)) * Mathf.Deg2Rad;
}
public static float DistanceFor(float zoom)
{
return zoom / (2f * Mathf.Tan(FieldOfView * .5f * Mathf.Deg2Rad));
}
/// Camera position and rotation for a Unity focus point, zoom and Godot yaw (radians).
public static void Pose(Vector3 focus, float zoom, float yaw, out Vector3 position, out Quaternion rotation)
{
float pitch = PitchFor(zoom);
// Godot: Vector3(0, 0, 1).rotated(RIGHT, pitch).rotated(UP, yaw).
var back = new Vector3(0f, -Mathf.Sin(pitch), Mathf.Cos(pitch));
back = new Vector3(back.x * Mathf.Cos(yaw) + back.z * Mathf.Sin(yaw), back.y, -back.x * Mathf.Sin(yaw) + back.z * Mathf.Cos(yaw));
Vector3 godotFocus = LuneSpace.FromGodot(focus);
Vector3 godotPosition = godotFocus + back * DistanceFor(zoom);
position = LuneSpace.FromGodot(godotPosition);
rotation = Quaternion.LookRotation(focus - position, Vector3.up);
}
static float SmoothStep(float from, float to, float value)
{
float t = Mathf.Clamp01((value - from) / (to - from));
return t * t * (3f - 2f * t);
}
}
}