using UnityEngine; namespace FloodSWE.Streaming { public sealed class HeightmapInterpolator { public float FrameDurationSeconds = 0.5f; private HeightmapPacket previousPacket; private HeightmapPacket nextPacket; private float[] previousHeights; private float[] nextHeights; private float[] blendedHeights; private bool hasPrevious; private bool hasNext; private float blendTime; public void Reset() { previousPacket = default; nextPacket = default; previousHeights = null; nextHeights = null; blendedHeights = null; hasPrevious = false; hasNext = false; blendTime = 0.0f; } public void PushPacket(HeightmapPacket packet) { if (!packet.TryDecodeHeights(out float[] heights)) { return; } if (!hasPrevious) { previousPacket = packet; previousHeights = heights; hasPrevious = true; blendTime = 0.0f; return; } if (packet.Resolution != previousPacket.Resolution) { Reset(); previousPacket = packet; previousHeights = heights; hasPrevious = true; return; } if (packet.FrameId <= previousPacket.FrameId) { if (packet.FrameId == previousPacket.FrameId) { previousPacket = packet; previousHeights = heights; blendTime = 0.0f; } return; } if (hasNext && packet.FrameId > nextPacket.FrameId) { PromoteNext(); } nextPacket = packet; nextHeights = heights; hasNext = true; blendTime = 0.0f; } public void Step(float deltaTime) { if (!hasPrevious || !hasNext) { return; } if (FrameDurationSeconds <= 0.0f) { PromoteNext(); return; } blendTime += Mathf.Max(0.0f, deltaTime); if (blendTime >= FrameDurationSeconds) { PromoteNext(); blendTime = Mathf.Max(0.0f, blendTime - FrameDurationSeconds); } } public bool TryGetHeights(out float[] heights) { heights = null; if (!hasPrevious) { return false; } if (!hasNext || FrameDurationSeconds <= 0.0f) { heights = previousHeights; return true; } float alpha = Mathf.Clamp01(blendTime / FrameDurationSeconds); EnsureBlendBuffer(previousHeights.Length); for (int i = 0; i < previousHeights.Length; i++) { blendedHeights[i] = Mathf.Lerp(previousHeights[i], nextHeights[i], alpha); } heights = blendedHeights; return true; } private void PromoteNext() { if (!hasNext) { return; } previousPacket = nextPacket; previousHeights = nextHeights; nextPacket = default; nextHeights = null; hasNext = false; blendTime = 0.0f; } private void EnsureBlendBuffer(int length) { if (blendedHeights == null || blendedHeights.Length != length) { blendedHeights = new float[length]; } } } }