From e680d7118ea69807d8daed083c84f46162706b48 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Wed, 13 May 2026 13:21:29 +0200 Subject: [PATCH] Integrate spline corridor junction support for terrain patching and scene building --- .../apply-spline-road-to-terrain-command.ts | 60 ++++++++++++++++--- src/runtime-three/runtime-scene-build.ts | 5 ++ 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/commands/apply-spline-road-to-terrain-command.ts b/src/commands/apply-spline-road-to-terrain-command.ts index 4ecef571..d1a98bd1 100644 --- a/src/commands/apply-spline-road-to-terrain-command.ts +++ b/src/commands/apply-spline-road-to-terrain-command.ts @@ -7,7 +7,11 @@ import { getTerrains, type Terrain } from "../document/terrains"; -import { createSplineRoadTerrainPatch } from "../geometry/spline-road-terrain"; +import { + createSplineCorridorJunctionTerrainPatch, + createSplineRoadTerrainPatch +} from "../geometry/spline-road-terrain"; +import { getSplineCorridorJunctionsConnectedToPath } from "../spline-corridor/spline-corridor-junctions"; import { applyTerrainBrushPatchToDocument, @@ -71,10 +75,26 @@ function createAppliedTerrainRoads( } const before = cloneTerrain(terrain); - const terrainWithMaterialLayer = + let terrainWithMaterialLayer = path.road.materialId === null ? terrain : ensureTerrainMaterialLayer(terrain, path.road.materialId).terrain; + const connectedJunctions = getSplineCorridorJunctionsConnectedToPath({ + junctions: document.splineCorridorJunctions, + pathId + }).filter((junction) => junction.enabled); + + for (const junction of connectedJunctions) { + if (junction.materialId === null) { + continue; + } + + terrainWithMaterialLayer = ensureTerrainMaterialLayer( + terrainWithMaterialLayer, + junction.materialId + ).terrain; + } + let tempDocument = { ...document, terrains: { @@ -82,20 +102,44 @@ function createAppliedTerrainRoads( [terrain.id]: cloneTerrain(terrainWithMaterialLayer) } }; + let changed = false; const patch = createSplineRoadTerrainPatch({ path, terrain: tempDocument.terrains[terrain.id]! }); - if (patch === null || isTerrainBrushPatchEmpty(patch)) { + if (patch !== null && !isTerrainBrushPatchEmpty(patch)) { + tempDocument = applyTerrainBrushPatchToDocument( + tempDocument, + patch, + "forward" + ); + changed = true; + } + + for (const junction of connectedJunctions) { + const junctionPatch = createSplineCorridorJunctionTerrainPatch({ + junction, + paths: Object.values(document.paths), + terrain: tempDocument.terrains[terrain.id]! + }); + + if (junctionPatch === null || isTerrainBrushPatchEmpty(junctionPatch)) { + continue; + } + + tempDocument = applyTerrainBrushPatchToDocument( + tempDocument, + junctionPatch, + "forward" + ); + changed = true; + } + + if (!changed) { continue; } - tempDocument = applyTerrainBrushPatchToDocument( - tempDocument, - patch, - "forward" - ); appliedTerrains.push({ terrainId: terrain.id, before, diff --git a/src/runtime-three/runtime-scene-build.ts b/src/runtime-three/runtime-scene-build.ts index 7bd4063c..705cce9e 100644 --- a/src/runtime-three/runtime-scene-build.ts +++ b/src/runtime-three/runtime-scene-build.ts @@ -67,6 +67,10 @@ import { type ScenePathRoadSettings, type ScenePathPoint } from "../document/paths"; +import { + getSplineCorridorJunctions, + type SplineCorridorJunction +} from "../document/spline-corridor-junctions"; import { cloneTerrain, createEmptyTerrainFoliageBlockerMask, @@ -86,6 +90,7 @@ import { deriveSplineCorridorBoxColliders, type SplineCorridorBoxCollider } from "../spline-corridor/spline-corridor-colliders"; +import { resolveSplineCorridorJunctionClipIntervals } from "../spline-corridor/spline-corridor-junctions"; import { cloneWorldSettings, type WorldSettings