-
-
Notifications
You must be signed in to change notification settings - Fork 36.2k
Description
Description
ExtrudeGeometry currently calls computeFrenetFrames(segments, false) with a hardcoded closed = false, even when the provided extrudePath has .closed === true.
When a closed spline is used as the extrudePath, the generated Frenet frames are computed as if the path were open. This produces a visible twist or discontinuity at the seam of the extruded geometry.
There is a TODO in the source about this behavior. The fix is to pass the curve's closed flag through to computeFrenetFrames so closed curves get closed Frenet frames.
Suggested minimal change:
Replace:
const frames = extrudePath.computeFrenetFrames( segments, false );
With:
const frames = extrudePath.computeFrenetFrames( segments, !!extrudePath.closed );
Reproduction steps
- Create a closed CatmullRomCurve3 (or other closed curve) and set
curve.closed = true. - Create a simple 2D Shape to extrude (e.g. a rectangle or small path).
- Create an ExtrudeGeometry with the closed curve as
extrudePathand a reasonably highsteps(e.g. 100). - Render the geometry and inspect the seam where the path closes — you will see a twist or discontinuity in the surface normals/UVs that disappears when the Frenet frames are computed in closed mode.
Code
// Minimal reproducible example
const shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.lineTo(1, 0);
shape.lineTo(1, 1);
shape.lineTo(0, 1);
shape.closePath();
const points = [
new THREE.Vector3(1, 0, 0),
new THREE.Vector3(0, 1, 0),
new THREE.Vector3(-1, 0, 0),
new THREE.Vector3(0, -1, 0)
];
const curve = new THREE.CatmullRomCurve3(points);
curve.closed = true; // important: mark curve closed
const extrudeSettings = {
steps: 100,
bevelEnabled: false,
extrudePath: curve
};
const geom = new THREE.ExtrudeGeometry(shape, extrudeSettings);
const mat = new THREE.MeshStandardMaterial({ color: 0x88ccff, side: THREE.DoubleSide });
const mesh = new THREE.Mesh(geom, mat);
scene.add(mesh);
Live example
(If possible, please add a live fiddle or codepen demonstrating the issue. Example template links from the project are below — you can fork one and paste your reproduction)
- [jsfiddle-latest-release WebGLRenderer] (use the project's template)
- [jsfiddle-dev WebGLRenderer] (use the project's template)
- [jsfiddle-latest-release WebGPURenderer] (optional)
- [jsfiddle-dev WebGPURenderer] (optional)
If you want, I can prepare a ready-to-paste jsfiddle snippet from the code above.
Screenshots
No response
Version
Observed on: r152 and main branch (tested locally as of 2025-11-25). (Please update this if you can reproduce on a different release. The bug is present in current main in my tests.)
Device
No response
Browser
No response
OS
No response