Files
DTrierFlood_New/Assets/FloodSWE/Scripts/Streaming/HeightmapInterpolator.cs

150 lines
3.8 KiB
C#

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