diff --git a/src/geometry/spline-road-mesh.ts b/src/geometry/spline-road-mesh.ts index 4c2ab955..419d21e7 100644 --- a/src/geometry/spline-road-mesh.ts +++ b/src/geometry/spline-road-mesh.ts @@ -512,6 +512,7 @@ export function buildSplineRoadEdgeMeshData(options: { path: SplineRoadPathLike; side: ScenePathRoadEdgeSide; terrains?: readonly Terrain[]; + clipIntervals?: readonly SplineCorridorPathClipInterval[]; }): SplineRoadEdgeMeshData | null { const { path, side } = options; const edge = path.road.edges[side]; @@ -542,64 +543,80 @@ export function buildSplineRoadEdgeMeshData(options: { const uvs: number[] = []; const indices: number[] = []; const profileLastIndex = Math.max(1, profile.length - 1); + const stationRuns = buildVisibleRoadStationRuns( + stations, + options.clipIntervals ?? [] + ); + let stationCount = 0; - for (let stationIndex = 0; stationIndex < stations.length; stationIndex += 1) { - const station = stations[stationIndex]!; - const tangent = resolveStationTangent(stations, stationIndex); + for (const run of stationRuns) { + const runVertexOffset = positions.length / 3; - if (tangent === null) { - return null; - } + for (let stationIndex = 0; stationIndex < run.length; stationIndex += 1) { + const station = run[stationIndex]!; + const tangent = resolveStationTangent(run, stationIndex); - const leftDirection = { - x: -tangent.z, - y: 0, - z: tangent.x - }; + if (tangent === null) { + return null; + } - for (let profileIndex = 0; profileIndex < profile.length; profileIndex += 1) { - const profilePoint = profile[profileIndex]!; - const edgePoint = addVec3(station.center, { - x: leftDirection.x * profilePoint.offset, + const leftDirection = { + x: -tangent.z, y: 0, - z: leftDirection.z * profilePoint.offset - }); - const vertex = resolveRoadVertexPosition({ - path, - terrains, - point: edgePoint, - fallbackY: station.center.y - }); + z: tangent.x + }; - positions.push( - vertex.x, - vertex.y + profilePoint.heightOffset, - vertex.z - ); - uvs.push(profileIndex / profileLastIndex, station.distance); + for (let profileIndex = 0; profileIndex < profile.length; profileIndex += 1) { + const profilePoint = profile[profileIndex]!; + const edgePoint = addVec3(station.center, { + x: leftDirection.x * profilePoint.offset, + y: 0, + z: leftDirection.z * profilePoint.offset + }); + const vertex = resolveRoadVertexPosition({ + path, + terrains, + point: edgePoint, + fallbackY: station.center.y + }); + + positions.push( + vertex.x, + vertex.y + profilePoint.heightOffset, + vertex.z + ); + uvs.push(profileIndex / profileLastIndex, station.distance); + } } + + for (let stationIndex = 0; stationIndex < run.length - 1; stationIndex += 1) { + const currentRow = runVertexOffset + stationIndex * profile.length; + const nextRow = currentRow + profile.length; + + for (let profileIndex = 0; profileIndex < profile.length - 1; profileIndex += 1) { + const current = currentRow + profileIndex; + const currentNext = current + 1; + const next = nextRow + profileIndex; + const nextNext = next + 1; + + indices.push(current, currentNext, next, next, currentNext, nextNext); + } + } + + if (edge.kind !== "softShoulder") { + addEdgeProfileCaps({ + indices, + profileVertexCount: profile.length, + vertexOffset: runVertexOffset, + stationCount: run.length + }); + } + + stationCount += run.length; } - for (let stationIndex = 0; stationIndex < stations.length - 1; stationIndex += 1) { - const currentRow = stationIndex * profile.length; - const nextRow = currentRow + profile.length; - - for (let profileIndex = 0; profileIndex < profile.length - 1; profileIndex += 1) { - const current = currentRow + profileIndex; - const currentNext = current + 1; - const next = nextRow + profileIndex; - const nextNext = next + 1; - - indices.push(current, currentNext, next, next, currentNext, nextNext); - } - } - - if (edge.kind !== "softShoulder") { - addEdgeProfileCaps({ - indices, - profileVertexCount: profile.length, - stationCount: stations.length - }); + if (positions.length === 0) { + return null; } return { @@ -608,7 +625,7 @@ export function buildSplineRoadEdgeMeshData(options: { positions: new Float32Array(positions), uvs: new Float32Array(uvs), indices: new Uint32Array(indices), - stationCount: stations.length, + stationCount, totalLength: stations[stations.length - 1]?.distance ?? 0 }; } @@ -617,6 +634,7 @@ export function buildSplineRoadEdgeMeshGeometry(options: { path: SplineRoadPathLike; side: ScenePathRoadEdgeSide; terrains?: readonly Terrain[]; + clipIntervals?: readonly SplineCorridorPathClipInterval[]; }): BufferGeometry | null { const meshData = buildSplineRoadEdgeMeshData(options);