150 lines
3.8 KiB
C#
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];
|
|
}
|
|
}
|
|
}
|
|
}
|