1
0
Fork 0
forked from aly/qstbak
qstbak/Auspex/Auspex/AxTerrainMap.cs
2026-08-17 20:25:32 +10:00

124 lines
3.1 KiB
C#

using System;
using System.Numerics;
namespace Auspex;
public sealed class AxTerrainMap
{
private readonly float[] _heights;
public float WorldMinX { get; }
public float WorldMinZ { get; }
public int GridWidth { get; }
public int GridHeight { get; }
public float CellSize { get; }
public bool IsEmpty { get; }
private AxTerrainMap(float[] heights, float worldMinX, float worldMinZ, int gridWidth, int gridHeight, float cellSize, bool isEmpty)
{
_heights = heights;
WorldMinX = worldMinX;
WorldMinZ = worldMinZ;
GridWidth = gridWidth;
GridHeight = gridHeight;
CellSize = cellSize;
IsEmpty = isEmpty;
}
public static AxTerrainMap Generate(Vector3 center, float halfExtentX, float halfExtentZ, float cellSize = 1f)
{
float num = center.X - halfExtentX;
float num2 = center.Z - halfExtentZ;
int num3 = (int)MathF.Ceiling(halfExtentX * 2f / cellSize);
int num4 = (int)MathF.Ceiling(halfExtentZ * 2f / cellSize);
if (num3 <= 0 || num4 <= 0)
{
return new AxTerrainMap(Array.Empty<float>(), 0f, 0f, 0, 0, cellSize, isEmpty: true);
}
float[] array = new float[num3 * num4];
int num5 = num3;
int num6 = num4;
int num7 = -1;
int num8 = -1;
for (int i = 0; i < num4; i++)
{
float z = num2 + ((float)i + 0.5f) * cellSize;
for (int j = 0; j < num3; j++)
{
if (!float.IsNaN(array[i * num3 + j] = AxTerrainQuery.GetTerrainYRaw(num + ((float)j + 0.5f) * cellSize, z)))
{
if (j < num5)
{
num5 = j;
}
if (j > num7)
{
num7 = j;
}
if (i < num6)
{
num6 = i;
}
if (i > num8)
{
num8 = i;
}
}
}
}
if (num7 < 0)
{
return new AxTerrainMap(Array.Empty<float>(), 0f, 0f, 0, 0, cellSize, isEmpty: true);
}
int num9 = num7 - num5 + 1;
int num10 = num8 - num6 + 1;
float[] array2 = new float[num9 * num10];
for (int k = 0; k < num10; k++)
{
int sourceIndex = (k + num6) * num3 + num5;
Array.Copy(array, sourceIndex, array2, k * num9, num9);
}
float worldMinX = num + (float)num5 * cellSize;
float worldMinZ = num2 + (float)num6 * cellSize;
return new AxTerrainMap(array2, worldMinX, worldMinZ, num9, num10, cellSize, isEmpty: false);
}
public float GetHeight(int cellX, int cellZ)
{
if ((uint)cellX >= (uint)GridWidth || (uint)cellZ >= (uint)GridHeight)
{
return float.NaN;
}
return _heights[cellZ * GridWidth + cellX];
}
public bool IsWalkable(int cellX, int cellZ)
{
return !float.IsNaN(GetHeight(cellX, cellZ));
}
public bool IsWalkable(float worldX, float worldZ)
{
var (cellX, cellZ) = WorldToCell(worldX, worldZ);
return IsWalkable(cellX, cellZ);
}
public (int cellX, int cellZ) WorldToCell(float worldX, float worldZ)
{
int item = (int)MathF.Floor((worldX - WorldMinX) / CellSize);
int item2 = (int)MathF.Floor((worldZ - WorldMinZ) / CellSize);
return (cellX: item, cellZ: item2);
}
public (float worldX, float worldZ) CellToWorld(int cellX, int cellZ)
{
float item = WorldMinX + ((float)cellX + 0.5f) * CellSize;
float item2 = WorldMinZ + ((float)cellZ + 0.5f) * CellSize;
return (worldX: item, worldZ: item2);
}
}