Refactor terrain weight calculation to support variable layer counts

This commit is contained in:
2026-05-13 00:43:29 +02:00
parent ae3c35cd00
commit 48f441a99d

View File

@@ -632,27 +632,30 @@ export function cloneTerrainFoliageMasks(
} }
export function getTerrainSampleLayerWeights( export function getTerrainSampleLayerWeights(
terrain: Pick<Terrain, "sampleCountX" | "sampleCountZ" | "paintWeights">, terrain: Pick<Terrain, "sampleCountX" | "sampleCountZ" | "layers" | "paintWeights">,
sampleX: number, sampleX: number,
sampleZ: number sampleZ: number
): [number, number, number, number] { ): number[] {
const offset = getTerrainPaintWeightSampleOffset(terrain, sampleX, sampleZ); const offset = getTerrainPaintWeightSampleOffset(terrain, sampleX, sampleZ);
const layer1 = terrain.paintWeights[offset] ?? 0; const layerCount = terrain.layers.length;
const layer2 = terrain.paintWeights[offset + 1] ?? 0; const weights = new Array<number>(layerCount).fill(0);
const layer3 = terrain.paintWeights[offset + 2] ?? 0; let explicitWeightSum = 0;
const baseLayer = Math.max(0, 1 - (layer1 + layer2 + layer3));
const weightSum = baseLayer + layer1 + layer2 + layer3;
if (weightSum <= 0) { for (let layerIndex = 1; layerIndex < layerCount; layerIndex += 1) {
return [1, 0, 0, 0]; const weight = terrain.paintWeights[offset + layerIndex - 1] ?? 0;
weights[layerIndex] = weight;
explicitWeightSum += weight;
} }
return [ weights[0] = Math.max(0, 1 - explicitWeightSum);
baseLayer / weightSum, const weightSum = weights.reduce((sum, weight) => sum + weight, 0);
layer1 / weightSum,
layer2 / weightSum, if (weightSum <= 0) {
layer3 / weightSum weights[0] = 1;
]; return weights;
}
return weights.map((weight) => weight / weightSum);
} }
export function getTerrainWorldSamplePosition( export function getTerrainWorldSamplePosition(
@@ -1337,8 +1340,11 @@ function createResampledTerrainPaintWeights(
sampleCountX: number, sampleCountX: number,
sampleCountZ: number sampleCountZ: number
): number[] { ): number[] {
const storedWeightCount = getTerrainStoredPaintWeightCount(
terrain.layers.length
);
const paintWeights = new Array<number>( const paintWeights = new Array<number>(
sampleCountX * sampleCountZ * (TERRAIN_LAYER_COUNT - 1) sampleCountX * sampleCountZ * storedWeightCount
); );
for (let sampleZ = 0; sampleZ < sampleCountZ; sampleZ += 1) { for (let sampleZ = 0; sampleZ < sampleCountZ; sampleZ += 1) {
@@ -1351,13 +1357,9 @@ function createResampledTerrainPaintWeights(
sampleCountX === 1 ? 0 : sampleX / (sampleCountX - 1); sampleCountX === 1 ? 0 : sampleX / (sampleCountX - 1);
const sourceSampleX = normalizedSampleX * (terrain.sampleCountX - 1); const sourceSampleX = normalizedSampleX * (terrain.sampleCountX - 1);
const offset = const offset =
(sampleZ * sampleCountX + sampleX) * (TERRAIN_LAYER_COUNT - 1); (sampleZ * sampleCountX + sampleX) * storedWeightCount;
for ( for (let layerOffset = 0; layerOffset < storedWeightCount; layerOffset += 1) {
let layerOffset = 0;
layerOffset < TERRAIN_LAYER_COUNT - 1;
layerOffset += 1
) {
paintWeights[offset + layerOffset] = paintWeights[offset + layerOffset] =
sampleTerrainPaintWeightAtGridCoordinate( sampleTerrainPaintWeightAtGridCoordinate(
terrain, terrain,
@@ -1554,6 +1556,7 @@ export function createTerrain(
const paintWeights = normalizeTerrainPaintWeights( const paintWeights = normalizeTerrainPaintWeights(
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
layers.length,
overrides.paintWeights overrides.paintWeights
); );
const foliageMasks = normalizeTerrainFoliageMasks( const foliageMasks = normalizeTerrainFoliageMasks(