97 lines
3.0 KiB
C#
97 lines
3.0 KiB
C#
namespace Sand.ChunkPrototype;
|
|
|
|
internal sealed class ChunkFieldPage
|
|
{
|
|
public ChunkFieldPage(int width, int height)
|
|
{
|
|
Width = width;
|
|
Height = height;
|
|
WindX = new float[width * height];
|
|
WindY = new float[width * height];
|
|
ForceX = new float[width * height];
|
|
ForceY = new float[width * height];
|
|
Pressure = new float[width * height];
|
|
}
|
|
|
|
public int Width { get; }
|
|
public int Height { get; }
|
|
public float[] WindX { get; }
|
|
public float[] WindY { get; }
|
|
public float[] ForceX { get; }
|
|
public float[] ForceY { get; }
|
|
public float[] Pressure { get; }
|
|
public int ActiveCellCount { get; private set; }
|
|
public int LastDecayedFrame { get; set; }
|
|
|
|
public bool TryGetCell(int localX, int localY, out FieldCellData cell)
|
|
{
|
|
var index = GetIndex(localX, localY);
|
|
cell = new FieldCellData(WindX[index], WindY[index], ForceX[index], ForceY[index], Pressure[index]);
|
|
return !cell.IsEffectivelyZero;
|
|
}
|
|
|
|
public FieldCellData GetCell(int localX, int localY)
|
|
{
|
|
var index = GetIndex(localX, localY);
|
|
return new FieldCellData(WindX[index], WindY[index], ForceX[index], ForceY[index], Pressure[index]);
|
|
}
|
|
|
|
public void SetCell(int localX, int localY, FieldCellData value)
|
|
{
|
|
var index = GetIndex(localX, localY);
|
|
var wasZero = IsEffectivelyZero(index);
|
|
var nowZero = value.IsEffectivelyZero;
|
|
WindX[index] = value.WindX;
|
|
WindY[index] = value.WindY;
|
|
ForceX[index] = value.ForceX;
|
|
ForceY[index] = value.ForceY;
|
|
Pressure[index] = value.Pressure;
|
|
if (wasZero && !nowZero)
|
|
{
|
|
ActiveCellCount++;
|
|
}
|
|
else if (!wasZero && nowZero)
|
|
{
|
|
ActiveCellCount--;
|
|
}
|
|
}
|
|
|
|
public bool IsEmpty() => ActiveCellCount == 0;
|
|
|
|
public IEnumerable<(int LocalX, int LocalY, FieldCellData Cell)> EnumerateActiveCells()
|
|
{
|
|
for (var y = 0; y < Height; y++)
|
|
{
|
|
for (var x = 0; x < Width; x++)
|
|
{
|
|
var index = GetIndex(x, y);
|
|
if (IsEffectivelyZero(index))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
yield return (x, y, new FieldCellData(WindX[index], WindY[index], ForceX[index], ForceY[index], Pressure[index]));
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool IsEffectivelyZero(int index) =>
|
|
MathF.Abs(WindX[index]) < 0.01f &&
|
|
MathF.Abs(WindY[index]) < 0.01f &&
|
|
MathF.Abs(ForceX[index]) < 0.01f &&
|
|
MathF.Abs(ForceY[index]) < 0.01f &&
|
|
MathF.Abs(Pressure[index]) < 0.01f;
|
|
|
|
private int GetIndex(int localX, int localY) => (localY * Width) + localX;
|
|
}
|
|
|
|
internal readonly record struct FieldCellData(float WindX, float WindY, float ForceX, float ForceY, float Pressure)
|
|
{
|
|
public bool IsEffectivelyZero =>
|
|
MathF.Abs(WindX) < 0.01f &&
|
|
MathF.Abs(WindY) < 0.01f &&
|
|
MathF.Abs(ForceX) < 0.01f &&
|
|
MathF.Abs(ForceY) < 0.01f &&
|
|
MathF.Abs(Pressure) < 0.01f;
|
|
}
|