auto-git:

[change] src/geometry/spline-road-mesh.ts
This commit is contained in:
2026-05-13 13:19:08 +02:00
parent 5a0f9f1245
commit c774026e2c

View File

@@ -512,6 +512,7 @@ export function buildSplineRoadEdgeMeshData(options: {
path: SplineRoadPathLike; path: SplineRoadPathLike;
side: ScenePathRoadEdgeSide; side: ScenePathRoadEdgeSide;
terrains?: readonly Terrain[]; terrains?: readonly Terrain[];
clipIntervals?: readonly SplineCorridorPathClipInterval[];
}): SplineRoadEdgeMeshData | null { }): SplineRoadEdgeMeshData | null {
const { path, side } = options; const { path, side } = options;
const edge = path.road.edges[side]; const edge = path.road.edges[side];
@@ -542,64 +543,80 @@ export function buildSplineRoadEdgeMeshData(options: {
const uvs: number[] = []; const uvs: number[] = [];
const indices: number[] = []; const indices: number[] = [];
const profileLastIndex = Math.max(1, profile.length - 1); 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) { for (const run of stationRuns) {
const station = stations[stationIndex]!; const runVertexOffset = positions.length / 3;
const tangent = resolveStationTangent(stations, stationIndex);
if (tangent === null) { for (let stationIndex = 0; stationIndex < run.length; stationIndex += 1) {
return null; const station = run[stationIndex]!;
} const tangent = resolveStationTangent(run, stationIndex);
const leftDirection = { if (tangent === null) {
x: -tangent.z, return null;
y: 0, }
z: tangent.x
};
for (let profileIndex = 0; profileIndex < profile.length; profileIndex += 1) { const leftDirection = {
const profilePoint = profile[profileIndex]!; x: -tangent.z,
const edgePoint = addVec3(station.center, {
x: leftDirection.x * profilePoint.offset,
y: 0, y: 0,
z: leftDirection.z * profilePoint.offset z: tangent.x
}); };
const vertex = resolveRoadVertexPosition({
path,
terrains,
point: edgePoint,
fallbackY: station.center.y
});
positions.push( for (let profileIndex = 0; profileIndex < profile.length; profileIndex += 1) {
vertex.x, const profilePoint = profile[profileIndex]!;
vertex.y + profilePoint.heightOffset, const edgePoint = addVec3(station.center, {
vertex.z x: leftDirection.x * profilePoint.offset,
); y: 0,
uvs.push(profileIndex / profileLastIndex, station.distance); 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) { if (positions.length === 0) {
const currentRow = stationIndex * profile.length; return null;
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
});
} }
return { return {
@@ -608,7 +625,7 @@ export function buildSplineRoadEdgeMeshData(options: {
positions: new Float32Array(positions), positions: new Float32Array(positions),
uvs: new Float32Array(uvs), uvs: new Float32Array(uvs),
indices: new Uint32Array(indices), indices: new Uint32Array(indices),
stationCount: stations.length, stationCount,
totalLength: stations[stations.length - 1]?.distance ?? 0 totalLength: stations[stations.length - 1]?.distance ?? 0
}; };
} }
@@ -617,6 +634,7 @@ export function buildSplineRoadEdgeMeshGeometry(options: {
path: SplineRoadPathLike; path: SplineRoadPathLike;
side: ScenePathRoadEdgeSide; side: ScenePathRoadEdgeSide;
terrains?: readonly Terrain[]; terrains?: readonly Terrain[];
clipIntervals?: readonly SplineCorridorPathClipInterval[];
}): BufferGeometry | null { }): BufferGeometry | null {
const meshData = buildSplineRoadEdgeMeshData(options); const meshData = buildSplineRoadEdgeMeshData(options);