Add utilities for managing and sampling terrain foliage masks

This commit is contained in:
2026-05-02 04:09:55 +02:00
parent 3fff634981
commit f1bd573ea1

View File

@@ -856,6 +856,72 @@ function getStoredTerrainPaintWeightAtSample(
return terrain.paintWeights[offset + layerOffset] ?? 0; return terrain.paintWeights[offset + layerOffset] ?? 0;
} }
export function getTerrainFoliageMaskSampleIndex(
mask: Pick<TerrainFoliageMask, "resolutionX" | "resolutionZ">,
sampleX: number,
sampleZ: number
): number {
if (
!Number.isInteger(sampleX) ||
sampleX < 0 ||
sampleX >= mask.resolutionX
) {
throw new Error(`Terrain foliage mask sampleX ${sampleX} is out of range.`);
}
if (
!Number.isInteger(sampleZ) ||
sampleZ < 0 ||
sampleZ >= mask.resolutionZ
) {
throw new Error(`Terrain foliage mask sampleZ ${sampleZ} is out of range.`);
}
return sampleZ * mask.resolutionX + sampleX;
}
export function getTerrainFoliageMaskValueAtSample(
mask: TerrainFoliageMask,
sampleX: number,
sampleZ: number
): number {
return (
mask.values[getTerrainFoliageMaskSampleIndex(mask, sampleX, sampleZ)] ?? 0
);
}
export function getTerrainFoliageMask(
terrain: Pick<Terrain, "foliageMasks">,
layerId: string
): TerrainFoliageMask | null {
return terrain.foliageMasks[layerId] ?? null;
}
export function getOrCreateTerrainFoliageMask(
terrain: Terrain,
layerId: string
): TerrainFoliageMask {
const normalizedLayerId = normalizeTerrainFoliageLayerId(
layerId,
"Terrain foliage mask layerId"
);
const currentMask = terrain.foliageMasks[normalizedLayerId];
if (currentMask !== undefined) {
return currentMask;
}
const nextMask = createEmptyTerrainFoliageMask(terrain, normalizedLayerId);
terrain.foliageMasks[normalizedLayerId] = nextMask;
return nextMask;
}
export function isTerrainFoliageMaskEmpty(
mask: TerrainFoliageMask
): boolean {
return mask.values.every((value) => value === 0);
}
function sampleTerrainPaintWeightAtGridCoordinate( function sampleTerrainPaintWeightAtGridCoordinate(
terrain: Terrain, terrain: Terrain,
sampleX: number, sampleX: number,