Implement terrain-aware path resolution and geometry adjustments
This commit is contained in:
@@ -798,6 +798,96 @@ function createResolvedPathSegment(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sampleHighestTerrainWorldY(
|
||||||
|
terrains: readonly Terrain[] | undefined,
|
||||||
|
position: Vec3,
|
||||||
|
terrainOffset: number
|
||||||
|
): number | null {
|
||||||
|
if (terrains === undefined || terrains.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let highestWorldY: number | null = null;
|
||||||
|
|
||||||
|
for (const terrain of terrains) {
|
||||||
|
const terrainHeight = sampleTerrainHeightAtWorldPosition(
|
||||||
|
terrain,
|
||||||
|
position.x,
|
||||||
|
position.z,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
if (terrainHeight === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const worldY = terrain.position.y + terrainHeight + terrainOffset;
|
||||||
|
|
||||||
|
if (highestWorldY === null || worldY > highestWorldY) {
|
||||||
|
highestWorldY = worldY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return highestWorldY;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTerrainGlueToPosition(
|
||||||
|
position: Vec3,
|
||||||
|
options: ResolveScenePathOptions,
|
||||||
|
terrainOffset: number
|
||||||
|
): Vec3 {
|
||||||
|
const terrainWorldY = sampleHighestTerrainWorldY(
|
||||||
|
options.terrains,
|
||||||
|
position,
|
||||||
|
terrainOffset
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: position.x,
|
||||||
|
y: terrainWorldY ?? position.y,
|
||||||
|
z: position.z
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTerrainGlueToPoint(
|
||||||
|
point: ScenePathPoint,
|
||||||
|
options: ResolveScenePathOptions,
|
||||||
|
terrainOffset: number
|
||||||
|
): ScenePathPoint {
|
||||||
|
return {
|
||||||
|
...point,
|
||||||
|
position: applyTerrainGlueToPosition(point.position, options, terrainOffset)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTerrainGlueToSegments(
|
||||||
|
segments: ResolvedScenePathSegment[],
|
||||||
|
options: ResolveScenePathOptions,
|
||||||
|
terrainOffset: number
|
||||||
|
): ResolvedScenePathSegment[] {
|
||||||
|
let totalLength = 0;
|
||||||
|
|
||||||
|
return segments.map((segment, index) => {
|
||||||
|
const nextSegment = createResolvedPathSegment(
|
||||||
|
{
|
||||||
|
index,
|
||||||
|
startPointId: segment.startPointId,
|
||||||
|
endPointId: segment.endPointId,
|
||||||
|
start: applyTerrainGlueToPosition(
|
||||||
|
segment.start,
|
||||||
|
options,
|
||||||
|
terrainOffset
|
||||||
|
),
|
||||||
|
end: applyTerrainGlueToPosition(segment.end, options, terrainOffset)
|
||||||
|
},
|
||||||
|
totalLength
|
||||||
|
);
|
||||||
|
|
||||||
|
totalLength = nextSegment.distanceEnd;
|
||||||
|
return nextSegment;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function buildLinearResolvedPathSegments(
|
function buildLinearResolvedPathSegments(
|
||||||
points: ScenePathPoint[],
|
points: ScenePathPoint[],
|
||||||
loop: boolean
|
loop: boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user