如何用THREE.js的ExtrudeGeometry实现倾斜挤出效果?
在Three.js中实现倾斜式挤出的方案
ExtrudeGeometry的默认参数无法直接通过修改depth实现倾斜挤出,因为它是沿固定轴(默认Z轴)进行等距挤出的。不过有两种可靠的方法可以实现你要的顶部倾斜效果:
方法1:手动修改挤出后的顶点位置
这种方法适合简单的线性倾斜,直接调整顶部顶点的坐标来实现倾斜角度。核心思路是识别出ExtrudeGeometry挤出后的顶部顶点,按计算好的偏移量修改它们的位置:
const shape = new THREE.Shape() .moveTo(0,0) .lineTo(1, 0.5) .lineTo(2, 1) .lineTo(0, 0); const extrudeSettings = { steps:16, depth:10, bevelEnabled: false }; const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); const positions = geometry.attributes.position.array; const depth = extrudeSettings.depth; const tiltAngle = Math.PI / 6; // 30度倾斜角 const slope = Math.tan(tiltAngle); // 计算斜率,对应每单位X轴的Y轴偏移量 // 遍历所有顶点,修改顶部区域的顶点坐标 for (let i = 0; i < positions.length; i += 3) { const z = positions[i + 2]; // 判断是否为顶部顶点(Z坐标等于挤出深度),用近似值避免浮点精度问题 if (Math.abs(z - depth) < 0.001) { // 这里以沿X轴倾斜为例,X值越大,Y值越高 positions[i + 1] += positions[i] * slope; } } // 标记位置属性需要更新 geometry.attributes.position.needsUpdate = true; // 重新计算法线,确保光照显示正常 geometry.computeVertexNormals(); const material = new THREE.MeshStandardMaterial({color: 0xFF00FF}); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh);
方法2:使用自定义挤出路径(extrudePath)
如果需要更灵活的倾斜路径(比如非线性倾斜),可以利用ExtrudeGeometry的extrudePath参数,自定义一条倾斜的路径来引导挤出方向:
const shape = new THREE.Shape() .moveTo(0,0) .lineTo(1, 0.5) .lineTo(2, 1) .lineTo(0, 0); // 创建倾斜的挤出路径,这里实现沿Y轴倾斜30度 const tiltAngle = Math.PI / 6; const slope = Math.tan(tiltAngle); const extrudePath = new THREE.CurvePath(); // 路径起点为(0,0,0),终点为(0, slope*10, 10),对应深度10的倾斜 extrudePath.add(new THREE.LineCurve3( new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, slope * 10, 10) )); const extrudeSettings = { steps:16, extrudePath: extrudePath, // 使用自定义路径替代固定depth bevelEnabled: false }; const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); const material = new THREE.MeshStandardMaterial({color: 0xFF00FF}); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh);
注意事项
- 方法1中要注意浮点精度问题,判断顶点是否为顶部时不要直接用
===,而是用近似值比较。 - 修改顶点后必须调用
computeVertexNormals(),否则模型的光照会出现异常。 - 方法2的路径可以是任意Curve3类型,比如Bezier曲线,适合实现复杂的挤出形态。
内容的提问来源于stack exchange,提问作者liminalFrog
相关产品推荐
相关产品推荐

