You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 01:02:45