CultLib/src/CultMath/PlanetaryPatch.cs

45 lines
2 KiB
C#

using System;
using System.Linq;
namespace CultMath;
public readonly record struct PlanetaryPatchVertex(float2 LocalCoordinate, float3 UnitDirection);
public readonly record struct PlanetaryPatchMesh(
PlanetaryCubeFace Face,
int CellsPerAxis,
PlanetaryPatchVertex[] Vertices,
int[] Indices);
public static class PlanetaryPatch
{
public static PlanetaryPatchMesh CreateFace(PlanetaryCubeFace face, int cellsPerAxis)
{
if (!Enum.IsDefined(typeof(PlanetaryCubeFace), face)) throw new ArgumentOutOfRangeException(nameof(face));
if (cellsPerAxis < 1 || cellsPerAxis > 4096) throw new ArgumentOutOfRangeException(nameof(cellsPerAxis));
var axisVertices = cellsPerAxis + 1;
var vertices = new PlanetaryPatchVertex[checked(axisVertices * axisVertices)];
for (var y = 0; y < axisVertices; y++)
for (var x = 0; x < axisVertices; x++)
{
var local = new float2(x / (float)cellsPerAxis, y / (float)cellsPerAxis);
vertices[y * axisVertices + x] = new(local, PlanetaryTopology.Direction(new(face, local.x * 2 - 1, local.y * 2 - 1)));
}
var indices = new int[checked(cellsPerAxis * cellsPerAxis * 6)];
var write = 0;
for (var y = 0; y < cellsPerAxis; y++)
for (var x = 0; x < cellsPerAxis; x++)
{
var lowerLeft = y * axisVertices + x;
var lowerRight = lowerLeft + 1;
var upperLeft = lowerLeft + axisVertices;
var upperRight = upperLeft + 1;
indices[write++] = lowerLeft; indices[write++] = lowerRight; indices[write++] = upperRight;
indices[write++] = lowerLeft; indices[write++] = upperRight; indices[write++] = upperLeft;
}
return new(face, cellsPerAxis, vertices, indices);
}
public static PlanetaryPatchMesh[] CreateCubeSphere(int cellsPerAxis)
=> ((PlanetaryCubeFace[])Enum.GetValues(typeof(PlanetaryCubeFace))).Select(face => CreateFace(face, cellsPerAxis)).ToArray();
}