Three.js中如何通过平面将3D模型切割为两个独立部分?
Three.js 平面切割3D几何体为独立两部分落地实现方案
之前参考的Y平面裁剪方案无法得到预期效果,核心原因是材质层的clippingPlanes只做渲染层面的像素丢弃,不会真的把几何体拆成两个独立的网格实体,自然拿不到可单独操作的两部分模型。
要实现真正的几何拆分,直接按下面的方案做,稳定性和效果都能达到参考要求:
核心实现思路
- 放弃渲染裁剪方案,直接对几何体的三角面数据做空间计算,优先用成熟的实体布尔运算库完成切割,避免手写几何相交逻辑出现破面、法线错误问题
- 切割完成后自动补全断面封盖,保证切出来的两个模型都是封闭实体,不会出现空心漏面
可直接复用的实现步骤
- 依赖准备
引入Three.js生态维护的three-bvh-csg库,这个库用BVH结构加速布尔运算,比旧版CSG库性能高几个量级,切割复杂模型也不会卡顿。 - 基础初始化
import * as THREE from 'three'; import { Brush, Evaluator, SUBTRACTION } from 'three-bvh-csg'; // 初始化布尔运算计算器 const evaluator = new Evaluator(); - 切割逻辑实现
// 把待切割的原模型转为布尔运算支持的Brush类型 const originalModel = new Brush(targetModel.geometry, targetModel.material); // 定义切割平面,示例为Y=2位置的水平切割面,可自行修改法向量实现任意方向切割 const cutPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), -2); // 生成尺寸足够覆盖待切模型的切割刀具,厚度设为极小值即可 const cutterGeo = new THREE.BoxGeometry(200, 0.001, 200); // 将刀具对齐到切割平面位置 cutterGeo.translate(0, cutPlane.constant, 0); const cutter = new Brush(cutterGeo); // 计算得到平面正侧的模型部分 cutter.position.y = -1000; const partPositive = evaluator.evaluate(originalModel, cutter, SUBTRACTION); // 计算得到平面负侧的模型部分 cutter.position.y = 1000; const partNegative = evaluator.evaluate(originalModel, cutter, SUBTRACTION); // 两个部分都是独立的Mesh对象,可单独添加材质、移动、绑定交互 scene.add(partPositive, partNegative);
避坑提示
- 切割前先对原模型几何体执行
geometry.mergeVertices()、geometry.computeVertexNormals(),避免因顶点重复、法线缺失导致切割后出现黑面、破面 - 切割刀具的尺寸只要比待切模型的包围盒大即可,不用设得过大,避免不必要的性能消耗
- 如果需要给断面单独上材质,可以在布尔运算完成后遍历两个模型的几何体,给断面生成的三角面设置独立的材质分组
- 带骨骼动画、变形动画的模型不适合直接做静态几何切割,需要先把当前帧的蒙皮结果烘焙为静态几何体再执行切割
内容的提问来源于stack exchange,提问作者Kamenskyh
相关产品推荐
相关产品推荐

