using UnityEngine;
namespace Heroes.Battle
{
///
/// Converts a facing direction expressed in the flat 2D battlefield plane
/// into the 3D rotation a unit model must have to look like it stands on a
/// virtual ground plane viewed by an orthographic camera pitched by
/// pitchDegrees.
///
/// The unit's *position* stays 2D (it is placed at the hex's on-screen point).
/// Only its *rotation* uses the virtual plane, which is what makes moves up /
/// down / diagonally turn the model believably.
///
/// Math: a camera pitched by φ below the horizon maps a ground direction
/// (gx, gz) to the screen as (gx, gz·sinφ). Inverting it, a screen direction
/// (sx, sy) corresponds to the ground direction (sx, sy / sinφ). The model is
/// yawed around the ground normal to face that ground direction, then tilted
/// by R_x(-φ) so that the ordinary (un-pitched) battle camera reproduces the
/// image a pitched camera would see of an upright model.
///
public static class BattleProjection
{
///
/// Local rotation for a unit model that should face
/// (a direction in battlefield-local 2D space; +x right, +y up).
///
/// Facing direction in the 2D battlefield plane.
/// Pitch of the virtual viewing camera below the horizon.
/// If false, only yaw is applied (no standing lean).
/// Correction if the prefab's forward axis is not +Z.
public static Quaternion FacingRotation(Vector2 boardDir, float pitchDegrees, bool applyViewTilt, float yawOffsetDegrees)
{
float sin = Mathf.Sin(pitchDegrees * Mathf.Deg2Rad);
if (Mathf.Abs(sin) < 1e-3f) sin = sin < 0f ? -1e-3f : 1e-3f;
Vector3 ground = new Vector3(boardDir.x, 0f, boardDir.y / sin);
if (ground.sqrMagnitude < 1e-6f) ground = Vector3.forward;
float yaw = Mathf.Atan2(ground.x, ground.z) * Mathf.Rad2Deg + yawOffsetDegrees;
Quaternion rotation = Quaternion.AngleAxis(yaw, Vector3.up);
if (applyViewTilt)
{
rotation = Quaternion.AngleAxis(-pitchDegrees, Vector3.right) * rotation;
}
return rotation;
}
}
}