using Luneraria.Core; using UnityEngine; namespace Luneraria.View { /// /// Heights of the G1 world for placing figures and buildings (presentation only; the rules are /// flat). Baked from the Godot reference by tools/godot-golden/world_export.gd: /// the terrain walk height (1 m grid, lane decks instead of the river bed) and the height a /// figure stands on including plaza, dais steps and grotto terrace (0.5 m grid). /// public sealed class LuneGround : ScriptableObject { public float WalkExtent; public float WalkStep; public int WalkSize; public float[] Walk; public float StandExtent; public float StandStep; public int StandSize; public float[] Stand; /// LuneTerrain.walk_height: lane decks, ford and platform instead of the river bed. public float WalkHeight(Vec2 map) { return Bilinear(Walk, WalkSize, WalkExtent, WalkStep, map); } /// LuneWorld.height_at: walk height plus plaza, dais and grotto lifts. public float StandHeight(Vec2 map) { return Bilinear(Stand, StandSize, StandExtent, StandStep, map); } // Godot LuneTerrain._bilinear, in map coordinates. static float Bilinear(float[] field, int size, float extent, float step, Vec2 p) { if (field == null || field.Length == 0) return 0f; float fx = Mathf.Clamp((p.X + extent) / step, 0f, size - 1.001f); float fz = Mathf.Clamp((p.Y + extent) / step, 0f, size - 1.001f); int i = (int)fx; int j = (int)fz; float tx = fx - i; float tz = fz - j; float a = Mathf.Lerp(field[j * size + i], field[j * size + i + 1], tx); float b = Mathf.Lerp(field[(j + 1) * size + i], field[(j + 1) * size + i + 1], tx); return Mathf.Lerp(a, b, tz); } } }