Support terrain grid resize directions for terrain manipulation functions

This commit is contained in:
2026-05-13 14:10:26 +02:00
parent 215569cf96
commit 3e2808f18a
2 changed files with 79 additions and 15 deletions

View File

@@ -292,6 +292,8 @@ import {
import { import {
areTerrainsEqual, areTerrainsEqual,
createTerrain, createTerrain,
DEFAULT_TERRAIN_GRID_RESIZE_DIRECTION_X,
DEFAULT_TERRAIN_GRID_RESIZE_DIRECTION_Z,
getTerrainBounds, getTerrainBounds,
getTerrainFootprintDepth, getTerrainFootprintDepth,
getTerrainFootprintWidth, getTerrainFootprintWidth,
@@ -301,6 +303,8 @@ import {
MAX_TERRAIN_LAYER_COUNT, MAX_TERRAIN_LAYER_COUNT,
MIN_TERRAIN_SAMPLE_COUNT, MIN_TERRAIN_SAMPLE_COUNT,
resizeTerrainGrid, resizeTerrainGrid,
type TerrainGridResizeDirectionX,
type TerrainGridResizeDirectionZ,
type Terrain type Terrain
} from "../document/terrains"; } from "../document/terrains";
import { BUNDLED_FOLIAGE_PROTOTYPES } from "../foliage/bundled-foliage-manifest"; import { BUNDLED_FOLIAGE_PROTOTYPES } from "../foliage/bundled-foliage-manifest";
@@ -3488,6 +3492,14 @@ export function App({
const [terrainSampleCountXDraft, setTerrainSampleCountXDraft] = useState("9"); const [terrainSampleCountXDraft, setTerrainSampleCountXDraft] = useState("9");
const [terrainSampleCountZDraft, setTerrainSampleCountZDraft] = useState("9"); const [terrainSampleCountZDraft, setTerrainSampleCountZDraft] = useState("9");
const [terrainCellSizeDraft, setTerrainCellSizeDraft] = useState("1"); const [terrainCellSizeDraft, setTerrainCellSizeDraft] = useState("1");
const [terrainResizeDirectionXDraft, setTerrainResizeDirectionXDraft] =
useState<TerrainGridResizeDirectionX>(
DEFAULT_TERRAIN_GRID_RESIZE_DIRECTION_X
);
const [terrainResizeDirectionZDraft, setTerrainResizeDirectionZDraft] =
useState<TerrainGridResizeDirectionZ>(
DEFAULT_TERRAIN_GRID_RESIZE_DIRECTION_Z
);
const [terrainLodGridVisibleTerrainIds, setTerrainLodGridVisibleTerrainIds] = const [terrainLodGridVisibleTerrainIds, setTerrainLodGridVisibleTerrainIds] =
useState<readonly string[]>([]); useState<readonly string[]>([]);
const [activeFoliageLayerId, setActiveFoliageLayerId] = useState< const [activeFoliageLayerId, setActiveFoliageLayerId] = useState<

View File

@@ -1573,9 +1573,15 @@ function createLocalPositionResampledTerrainFoliageBlockerMask(
export function changeTerrainCellSizePreservingFootprint( export function changeTerrainCellSizePreservingFootprint(
terrain: Terrain, terrain: Terrain,
requestedCellSize: number requestedCellSize: number,
resizeDirectionX: TerrainGridResizeDirectionX = DEFAULT_TERRAIN_GRID_RESIZE_DIRECTION_X,
resizeDirectionZ: TerrainGridResizeDirectionZ = DEFAULT_TERRAIN_GRID_RESIZE_DIRECTION_Z
): Terrain { ): Terrain {
const cellSize = normalizeTerrainCellSize(requestedCellSize); const cellSize = normalizeTerrainCellSize(requestedCellSize);
const normalizedResizeDirectionX =
normalizeTerrainGridResizeDirectionX(resizeDirectionX);
const normalizedResizeDirectionZ =
normalizeTerrainGridResizeDirectionZ(resizeDirectionZ);
const sampleCountX = getTerrainSampleCountForFootprint( const sampleCountX = getTerrainSampleCountForFootprint(
getTerrainFootprintWidth(terrain), getTerrainFootprintWidth(terrain),
cellSize cellSize
@@ -1584,10 +1590,18 @@ export function changeTerrainCellSizePreservingFootprint(
getTerrainFootprintDepth(terrain), getTerrainFootprintDepth(terrain),
cellSize cellSize
); );
const nextPosition = getTerrainPositionForResize(
terrain,
sampleCountX,
sampleCountZ,
cellSize,
normalizedResizeDirectionX,
normalizedResizeDirectionZ
);
return createTerrain({ return createTerrain({
...terrain, ...terrain,
position: cloneVec3(terrain.position), position: nextPosition,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize, cellSize,
@@ -1595,25 +1609,29 @@ export function changeTerrainCellSizePreservingFootprint(
terrain, terrain,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize cellSize,
nextPosition
), ),
paintWeights: createLocalPositionResampledTerrainPaintWeights( paintWeights: createLocalPositionResampledTerrainPaintWeights(
terrain, terrain,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize cellSize,
nextPosition
), ),
foliageMasks: createLocalPositionResampledTerrainFoliageMasks( foliageMasks: createLocalPositionResampledTerrainFoliageMasks(
terrain, terrain,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize cellSize,
nextPosition
), ),
foliageBlockerMask: createLocalPositionResampledTerrainFoliageBlockerMask( foliageBlockerMask: createLocalPositionResampledTerrainFoliageBlockerMask(
terrain, terrain,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize cellSize,
nextPosition
) )
}); });
} }
@@ -1621,7 +1639,9 @@ export function changeTerrainCellSizePreservingFootprint(
export function changeTerrainSampleCountsByExtendingOrCropping( export function changeTerrainSampleCountsByExtendingOrCropping(
terrain: Terrain, terrain: Terrain,
requestedSampleCountX: number, requestedSampleCountX: number,
requestedSampleCountZ: number requestedSampleCountZ: number,
resizeDirectionX: TerrainGridResizeDirectionX = DEFAULT_TERRAIN_GRID_RESIZE_DIRECTION_X,
resizeDirectionZ: TerrainGridResizeDirectionZ = DEFAULT_TERRAIN_GRID_RESIZE_DIRECTION_Z
): Terrain { ): Terrain {
const sampleCountX = normalizeTerrainSampleCount( const sampleCountX = normalizeTerrainSampleCount(
requestedSampleCountX, requestedSampleCountX,
@@ -1632,10 +1652,22 @@ export function changeTerrainSampleCountsByExtendingOrCropping(
"Terrain sampleCountZ" "Terrain sampleCountZ"
); );
const cellSize = terrain.cellSize; const cellSize = terrain.cellSize;
const normalizedResizeDirectionX =
normalizeTerrainGridResizeDirectionX(resizeDirectionX);
const normalizedResizeDirectionZ =
normalizeTerrainGridResizeDirectionZ(resizeDirectionZ);
const nextPosition = getTerrainPositionForResize(
terrain,
sampleCountX,
sampleCountZ,
cellSize,
normalizedResizeDirectionX,
normalizedResizeDirectionZ
);
return createTerrain({ return createTerrain({
...terrain, ...terrain,
position: cloneVec3(terrain.position), position: nextPosition,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize, cellSize,
@@ -1643,43 +1675,63 @@ export function changeTerrainSampleCountsByExtendingOrCropping(
terrain, terrain,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize cellSize,
nextPosition
), ),
paintWeights: createLocalPositionResampledTerrainPaintWeights( paintWeights: createLocalPositionResampledTerrainPaintWeights(
terrain, terrain,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize cellSize,
nextPosition
), ),
foliageMasks: createLocalPositionResampledTerrainFoliageMasks( foliageMasks: createLocalPositionResampledTerrainFoliageMasks(
terrain, terrain,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize cellSize,
nextPosition
), ),
foliageBlockerMask: createLocalPositionResampledTerrainFoliageBlockerMask( foliageBlockerMask: createLocalPositionResampledTerrainFoliageBlockerMask(
terrain, terrain,
sampleCountX, sampleCountX,
sampleCountZ, sampleCountZ,
cellSize cellSize,
nextPosition
) )
}); });
} }
export function resizeTerrainGrid( export function resizeTerrainGrid(
terrain: Terrain, terrain: Terrain,
options: Pick<Terrain, "sampleCountX" | "sampleCountZ" | "cellSize"> options: Pick<Terrain, "sampleCountX" | "sampleCountZ" | "cellSize"> & {
resizeDirectionX?: TerrainGridResizeDirectionX;
resizeDirectionZ?: TerrainGridResizeDirectionZ;
}
): Terrain { ): Terrain {
const cellSize = normalizeTerrainCellSize(options.cellSize); const cellSize = normalizeTerrainCellSize(options.cellSize);
const resizeDirectionX = normalizeTerrainGridResizeDirectionX(
options.resizeDirectionX
);
const resizeDirectionZ = normalizeTerrainGridResizeDirectionZ(
options.resizeDirectionZ
);
if (cellSize !== terrain.cellSize) { if (cellSize !== terrain.cellSize) {
return changeTerrainCellSizePreservingFootprint(terrain, cellSize); return changeTerrainCellSizePreservingFootprint(
terrain,
cellSize,
resizeDirectionX,
resizeDirectionZ
);
} }
return changeTerrainSampleCountsByExtendingOrCropping( return changeTerrainSampleCountsByExtendingOrCropping(
terrain, terrain,
options.sampleCountX, options.sampleCountX,
options.sampleCountZ options.sampleCountZ,
resizeDirectionX,
resizeDirectionZ
); );
} }