Refactor path smoothing logic and remove unused functions

This commit is contained in:
2026-04-15 11:21:17 +02:00
parent a3eb94a9a2
commit 66d1aa7299

View File

@@ -219,109 +219,56 @@ function findNonZeroSegmentTangent(
}; };
} }
const SMOOTH_PATH_SEGMENT_SUBDIVISIONS = 16; const SMOOTH_PATH_CORNER_CUTTING_PASSES = 3;
function getPathSamplePoint( function lerpVec3(start: Vec3, end: Vec3, t: number): Vec3 {
path: ResolvedPathLike, return {
index: number x: start.x + (end.x - start.x) * t,
): Vec3 { y: start.y + (end.y - start.y) * t,
const points = path.points; z: start.z + (end.z - start.z) * t
const pointCount = points.length; };
if (pointCount === 0) {
return {
x: 0,
y: 0,
z: 0
};
}
if (path.loop) {
const wrappedIndex = ((index % pointCount) + pointCount) % pointCount;
return cloneVec3(points[wrappedIndex]!.position);
}
if (index <= 0) {
return cloneVec3(points[0]!.position);
}
if (index >= pointCount - 1) {
return cloneVec3(points[pointCount - 1]!.position);
}
return cloneVec3(points[index]!.position);
} }
function evaluateCatmullRomPosition( function buildSmoothedPolylinePoints(path: ResolvedPathLike): Vec3[] {
p0: Vec3, let points = path.points.map((point) => cloneVec3(point.position));
p1: Vec3,
p2: Vec3,
p3: Vec3,
t: number
): Vec3 {
const t2 = t * t;
const t3 = t2 * t;
return scaleVec3( for (
addVec3( let passIndex = 0;
addVec3( passIndex < SMOOTH_PATH_CORNER_CUTTING_PASSES;
scaleVec3(p1, 2), passIndex += 1
scaleVec3(subtractVec3(p2, p0), t) ) {
), if (points.length < 2) {
addVec3( return points;
scaleVec3( }
addVec3(
addVec3(scaleVec3(p0, 2), scaleVec3(p1, -5)),
addVec3(scaleVec3(p2, 4), scaleVec3(p3, -1))
),
t2
),
scaleVec3(
addVec3(
addVec3(scaleVec3(p0, -1), scaleVec3(p1, 3)),
addVec3(scaleVec3(p2, -3), p3)
),
t3
)
)
),
0.5
);
}
function evaluateCatmullRomTangent( const refined: Vec3[] = [];
p0: Vec3,
p1: Vec3,
p2: Vec3,
p3: Vec3,
t: number
): Vec3 {
const t2 = t * t;
return normalizeDelta( if (path.loop) {
scaleVec3( for (let pointIndex = 0; pointIndex < points.length; pointIndex += 1) {
addVec3( const start = points[pointIndex]!;
subtractVec3(p2, p0), const end = points[(pointIndex + 1) % points.length]!;
addVec3(
scaleVec3( refined.push(lerpVec3(start, end, 0.25));
addVec3( refined.push(lerpVec3(start, end, 0.75));
addVec3(scaleVec3(p0, 4), scaleVec3(p1, -10)), }
addVec3(scaleVec3(p2, 8), scaleVec3(p3, -2)) } else {
), refined.push(cloneVec3(points[0]!));
t
), for (let pointIndex = 0; pointIndex < points.length - 1; pointIndex += 1) {
scaleVec3( const start = points[pointIndex]!;
addVec3( const end = points[pointIndex + 1]!;
addVec3(scaleVec3(p0, -3), scaleVec3(p1, 9)),
addVec3(scaleVec3(p2, -9), scaleVec3(p3, 3)) refined.push(lerpVec3(start, end, 0.25));
), refined.push(lerpVec3(start, end, 0.75));
t2 }
)
) refined.push(cloneVec3(points[points.length - 1]!));
), }
0.5
) points = refined;
); }
return points;
} }
function buildSmoothedPathSamples(path: ResolvedPathLike): SmoothedPathSample[] { function buildSmoothedPathSamples(path: ResolvedPathLike): SmoothedPathSample[] {
@@ -358,36 +305,34 @@ function buildSmoothedPathSamples(path: ResolvedPathLike): SmoothedPathSample[]
} }
const samples: SmoothedPathSample[] = []; const samples: SmoothedPathSample[] = [];
const segmentCount = path.loop ? path.points.length : path.points.length - 1; const points = buildSmoothedPolylinePoints(path);
const segmentCount = path.loop ? points.length : points.length - 1;
let cumulativeDistance = 0; let cumulativeDistance = 0;
let previousPosition: Vec3 | null = null; let previousPosition = cloneVec3(points[0]!);
samples.push({
distance: 0,
position: previousPosition,
tangent: {
x: 0,
y: 0,
z: 0
}
});
for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex += 1) { for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex += 1) {
const p0 = getPathSamplePoint(path, segmentIndex - 1); const nextPosition = cloneVec3(
const p1 = getPathSamplePoint(path, segmentIndex); points[(segmentIndex + 1) % points.length]!
const p2 = getPathSamplePoint(path, segmentIndex + 1); );
const p3 = getPathSamplePoint(path, segmentIndex + 2); cumulativeDistance += getVec3Distance(previousPosition, nextPosition);
for ( samples.push({
let subdivisionIndex = segmentIndex === 0 ? 0 : 1; distance: cumulativeDistance,
subdivisionIndex <= SMOOTH_PATH_SEGMENT_SUBDIVISIONS; position: nextPosition,
subdivisionIndex += 1 tangent: normalizeDelta(subtractVec3(nextPosition, previousPosition))
) { });
const t = subdivisionIndex / SMOOTH_PATH_SEGMENT_SUBDIVISIONS;
const position = evaluateCatmullRomPosition(p0, p1, p2, p3, t);
const tangent = evaluateCatmullRomTangent(p0, p1, p2, p3, t);
if (previousPosition !== null) { previousPosition = nextPosition;
cumulativeDistance += getVec3Distance(previousPosition, position);
}
samples.push({
distance: cumulativeDistance,
position,
tangent
});
previousPosition = position;
}
} }
return samples; return samples;