forked from aly/qstbak
124 lines
3.1 KiB
C#
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);
|
|
}
|
|
}
|