From 96aee46ab4fae84a318d53136968a57d5ebc291b Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Wed, 13 May 2026 13:22:35 +0200 Subject: [PATCH] Implement spline corridor junction support and refine road geometry generation --- src/runtime-three/runtime-host.ts | 51 ++++++++++++++++++++++-- src/runtime-three/runtime-scene-build.ts | 4 +- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/runtime-three/runtime-host.ts b/src/runtime-three/runtime-host.ts index cae5cbbc..de8afaa0 100644 --- a/src/runtime-three/runtime-host.ts +++ b/src/runtime-three/runtime-host.ts @@ -82,6 +82,7 @@ import { buildSplineRoadEdgeMeshGeometry, buildSplineRoadMeshGeometry } from "../geometry/spline-road-mesh"; +import { buildSplineCorridorJunctionMeshGeometry } from "../geometry/spline-corridor-junction-mesh"; import { createStarterMaterialSignature, createStarterMaterialTextureSet, @@ -4334,6 +4335,18 @@ export class RuntimeHost { ); } + private createRuntimeJunctionMaterial( + runtimeScene: RuntimeSceneDefinition, + materialId: string | null + ): Material { + const material = + materialId === null + ? null + : (runtimeScene.materials?.[materialId] ?? null); + + return this.createRuntimeRoadGeneratedMaterial(material, 0x6f624d); + } + private rebuildRoadSurfaces(runtimeScene: RuntimeSceneDefinition) { this.clearRoadSurfaces(); @@ -4344,7 +4357,10 @@ export class RuntimeHost { const surfaceGeometry = buildSplineRoadMeshGeometry({ path, - terrains: runtimeScene.foliage.terrains + terrains: runtimeScene.foliage.terrains, + clipIntervals: runtimeScene.splineCorridorClipIntervalsByPath.get( + path.id + ) }); const meshes: Array> = []; @@ -4365,7 +4381,10 @@ export class RuntimeHost { const edgeGeometry = buildSplineRoadEdgeMeshGeometry({ path, side, - terrains: runtimeScene.foliage.terrains + terrains: runtimeScene.foliage.terrains, + clipIntervals: runtimeScene.splineCorridorClipIntervalsByPath.get( + path.id + ) }); if (edgeGeometry === null) { @@ -4395,13 +4414,39 @@ export class RuntimeHost { }); } + for (const junction of runtimeScene.splineCorridorJunctions) { + const geometry = buildSplineCorridorJunctionMeshGeometry({ + junction, + paths: runtimeScene.paths, + terrains: runtimeScene.foliage.terrains + }); + + if (geometry === null) { + continue; + } + + const mesh = new Mesh( + geometry, + this.createRuntimeJunctionMaterial(runtimeScene, junction.materialId) + ); + mesh.castShadow = false; + mesh.receiveShadow = true; + mesh.userData.splineCorridorJunctionId = junction.id; + applyRendererRenderCategoryFromMaterial(mesh); + this.roadSurfaceGroup.add(mesh); + this.roadSurfaceMeshes.set(`junction:${junction.id}`, { + meshes: [mesh] + }); + } + this.applyShadowState(); } private rebuildSplineRepeaters(runtimeScene: RuntimeSceneDefinition) { this.splineRepeaterRenderer.sync({ paths: runtimeScene.paths, - terrains: runtimeScene.foliage.terrains + terrains: runtimeScene.foliage.terrains, + clipIntervalsByPath: runtimeScene.splineCorridorClipIntervalsByPath }); } diff --git a/src/runtime-three/runtime-scene-build.ts b/src/runtime-three/runtime-scene-build.ts index dc7e1664..d0c37274 100644 --- a/src/runtime-three/runtime-scene-build.ts +++ b/src/runtime-three/runtime-scene-build.ts @@ -546,7 +546,9 @@ export interface RuntimePath { } export interface RuntimeSplineCorridorJunction - extends SplineCorridorJunction {} + extends SplineCorridorJunction { + material: MaterialDef | null; +} export interface RuntimeFoliageDefinition { terrains: Terrain[];