Refactor terrain brush logic to dynamically support variable layer counts
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
|||||||
getTerrainPaintWeightSampleOffset,
|
getTerrainPaintWeightSampleOffset,
|
||||||
getTerrainSampleIndex,
|
getTerrainSampleIndex,
|
||||||
getTerrainSampleLayerWeights,
|
getTerrainSampleLayerWeights,
|
||||||
TERRAIN_LAYER_COUNT,
|
getTerrainStoredPaintWeightCount,
|
||||||
type Terrain
|
type Terrain
|
||||||
} from "../document/terrains";
|
} from "../document/terrains";
|
||||||
|
|
||||||
@@ -232,22 +232,20 @@ function getTerrainSmoothTargetHeight(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createTerrainPaintTargetWeights(
|
function createTerrainPaintTargetWeights(
|
||||||
|
terrain: Terrain,
|
||||||
layerIndex: number
|
layerIndex: number
|
||||||
): [number, number, number, number] {
|
): number[] {
|
||||||
if (
|
if (
|
||||||
!Number.isInteger(layerIndex) ||
|
!Number.isInteger(layerIndex) ||
|
||||||
layerIndex < 0 ||
|
layerIndex < 0 ||
|
||||||
layerIndex >= TERRAIN_LAYER_COUNT
|
layerIndex >= terrain.layers.length
|
||||||
) {
|
) {
|
||||||
throw new Error(`Terrain paint layer index ${layerIndex} is out of range.`);
|
throw new Error(`Terrain paint layer index ${layerIndex} is out of range.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return terrain.layers.map((_, currentLayerIndex) =>
|
||||||
layerIndex === 0 ? 1 : 0,
|
currentLayerIndex === layerIndex ? 1 : 0
|
||||||
layerIndex === 1 ? 1 : 0,
|
);
|
||||||
layerIndex === 2 ? 1 : 0,
|
|
||||||
layerIndex === 3 ? 1 : 0
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTerrainSamplePaintWeights(
|
function setTerrainSamplePaintWeights(
|
||||||
@@ -255,16 +253,15 @@ function setTerrainSamplePaintWeights(
|
|||||||
terrain: Terrain,
|
terrain: Terrain,
|
||||||
sampleX: number,
|
sampleX: number,
|
||||||
sampleZ: number,
|
sampleZ: number,
|
||||||
weights: readonly [number, number, number, number]
|
weights: readonly number[]
|
||||||
): number[] {
|
): number[] {
|
||||||
const offset = getTerrainPaintWeightSampleOffset(terrain, sampleX, sampleZ);
|
const offset = getTerrainPaintWeightSampleOffset(terrain, sampleX, sampleZ);
|
||||||
|
const storedWeightCount = getTerrainStoredPaintWeightCount(
|
||||||
|
terrain.layers.length
|
||||||
|
);
|
||||||
const changedIndices: number[] = [];
|
const changedIndices: number[] = [];
|
||||||
|
|
||||||
for (
|
for (let layerOffset = 0; layerOffset < storedWeightCount; layerOffset += 1) {
|
||||||
let layerOffset = 0;
|
|
||||||
layerOffset < TERRAIN_LAYER_COUNT - 1;
|
|
||||||
layerOffset += 1
|
|
||||||
) {
|
|
||||||
const paintWeightIndex = offset + layerOffset;
|
const paintWeightIndex = offset + layerOffset;
|
||||||
const nextWeight = weights[layerOffset + 1] ?? 0;
|
const nextWeight = weights[layerOffset + 1] ?? 0;
|
||||||
|
|
||||||
@@ -437,20 +434,31 @@ export function applyTerrainBrushStampInPlace(options: {
|
|||||||
sampleX,
|
sampleX,
|
||||||
sampleZ
|
sampleZ
|
||||||
);
|
);
|
||||||
const targetWeights = createTerrainPaintTargetWeights(layerIndex);
|
const targetWeights = createTerrainPaintTargetWeights(
|
||||||
|
terrain,
|
||||||
|
layerIndex
|
||||||
|
);
|
||||||
const blend = clamp01(smoothingStrength * weight);
|
const blend = clamp01(smoothingStrength * weight);
|
||||||
const nextWeights: [number, number, number, number] = [
|
const nextWeights = currentWeights.map((currentWeight, weightIndex) =>
|
||||||
lerp(currentWeights[0], targetWeights[0], blend),
|
lerp(currentWeight, targetWeights[weightIndex] ?? 0, blend)
|
||||||
lerp(currentWeights[1], targetWeights[1], blend),
|
);
|
||||||
lerp(currentWeights[2], targetWeights[2], blend),
|
const storedWeightCount = getTerrainStoredPaintWeightCount(
|
||||||
lerp(currentWeights[3], targetWeights[3], blend)
|
terrain.layers.length
|
||||||
];
|
);
|
||||||
|
let storedWeightsChanged = false;
|
||||||
|
|
||||||
if (
|
for (
|
||||||
nextWeights[1] !== currentWeights[1] ||
|
let layerOffset = 0;
|
||||||
nextWeights[2] !== currentWeights[2] ||
|
layerOffset < storedWeightCount;
|
||||||
nextWeights[3] !== currentWeights[3]
|
layerOffset += 1
|
||||||
) {
|
) {
|
||||||
|
if (nextWeights[layerOffset + 1] !== currentWeights[layerOffset + 1]) {
|
||||||
|
storedWeightsChanged = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storedWeightsChanged) {
|
||||||
const changedPaintWeightIndices = setTerrainSamplePaintWeights(
|
const changedPaintWeightIndices = setTerrainSamplePaintWeights(
|
||||||
terrain.paintWeights,
|
terrain.paintWeights,
|
||||||
terrain,
|
terrain,
|
||||||
|
|||||||
Reference in New Issue
Block a user