From 7d9b0235155a2799aa510b9ca3dfe622bfb9fbf5 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Wed, 13 May 2026 01:12:32 +0200 Subject: [PATCH] Implement road surface generation and material setup --- src/runtime-three/runtime-host.ts | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/runtime-three/runtime-host.ts b/src/runtime-three/runtime-host.ts index 378ae915..209d6b93 100644 --- a/src/runtime-three/runtime-host.ts +++ b/src/runtime-three/runtime-host.ts @@ -4247,6 +4247,77 @@ export class RuntimeHost { }); } + private configureRoadSurfaceMaterial(material: Material): Material { + material.polygonOffset = true; + material.polygonOffsetFactor = -1; + material.polygonOffsetUnits = -2; + return material; + } + + private createRuntimeRoadSurfaceMaterial(path: RuntimePath): Material { + const material = path.road.material; + + if (material === null) { + return this.configureRoadSurfaceMaterial( + new MeshStandardMaterial({ + color: 0x5f5747, + roughness: 1, + metalness: 0, + side: DoubleSide + }) + ); + } + + const textureSet = this.getOrCreateTextureSet(material); + + return this.configureRoadSurfaceMaterial( + new MeshPhysicalMaterial({ + color: 0xffffff, + map: textureSet.baseColor, + normalMap: textureSet.normal, + roughnessMap: textureSet.roughness, + roughness: 1, + metalnessMap: textureSet.metallic, + metalness: textureSet.metallic === null ? 0.03 : 1, + specularColorMap: textureSet.specular, + specularColor: new Color(0xffffff), + specularIntensity: textureSet.specular === null ? 0.2 : 1, + side: DoubleSide + }) + ); + } + + private rebuildRoadSurfaces(runtimeScene: RuntimeSceneDefinition) { + this.clearRoadSurfaces(); + + for (const path of runtimeScene.paths) { + if (!path.enabled || !path.visible || !path.road.enabled) { + continue; + } + + const geometry = buildSplineRoadMeshGeometry({ + path, + terrains: runtimeScene.foliage.terrains + }); + + if (geometry === null) { + continue; + } + + const mesh = new Mesh(geometry, this.createRuntimeRoadSurfaceMaterial(path)); + mesh.castShadow = false; + mesh.receiveShadow = true; + mesh.userData.pathId = path.id; + applyRendererRenderCategoryFromMaterial(mesh); + this.roadSurfaceGroup.add(mesh); + this.roadSurfaceMeshes.set(path.id, { + mesh + }); + } + + this.applyShadowState(); + } + private createFogMaterialSet( brush: RuntimeBoxBrushInstance, volumeRenderPaths: {