THREEJS中GLB模型CSG雕刻导致页面冻结问题咨询
页面冻结问题分析与修复
核心原因
你生成的TextGeometry包含大量字符(20多个"A"),即便curveSegments设为2,总面数也会异常庞大。CSG布尔运算是计算密集型操作,直接阻塞了浏览器主线程,导致页面冻结。此外还有几个潜在问题放大了这个问题。
具体修复步骤
- 削减文本复杂度:先将文本改为1-2个字符测试,确认功能正常后再逐步扩展。比如把
"AAAAAAAAAAAAAAAAAAAAAAAA"改成"A"。 - 降低TextGeometry面数:调小
size、height参数,把curveSegments设为1(最小值),减少单字符的几何细分:newGeometry = new TextGeometry("A", { font: font, size: 1, height: 0.5, curveSegments: 1, }) - 正确应用模型变换矩阵:GLB子节点
engravedMesh继承了父节点的变换,CSG运算时必须传入模型的世界矩阵,否则会出现位置偏移,甚至额外增加计算量:// 替换原有的CSG.fromMesh调用 engravedCSG = CSG.fromMesh(engravedMesh, engravedMesh.matrixWorld) // 生成最终Mesh时也要传入矩阵 engravedMesh.geometry = CSG.toMesh( engraved, engravedMesh.matrixWorld ).geometry - 避免重复触发运算:确保
regenerateGeometry只执行一次,不要在动画循环或频繁事件中调用。 - 复杂场景用Web Worker:如果必须处理大量字符或复杂模型,把CSG运算放到Web Worker中,避免阻塞主线程。
修改后的关键代码片段
const loader = new GLTFLoader(); let sword loader.load("scene/glb/object.glb", function (gltf) { sword = gltf.scene; sword.scale.set(1, 1, 1); sword.position.set(0, 0, 0); engravedMesh = sword.children[0] // 传入世界矩阵 engravedCSG = CSG.fromMesh(engravedMesh, engravedMesh.matrixWorld) scene.add(sword); engraving() }); let font function engraving() { const loaderFont = new FontLoader() loaderFont.load('fonts/helvetiker_regular.typeface.json', function (f) { font = f regenerateGeometry() }) } function regenerateGeometry() { let newGeometry = new TextGeometry("A", { font: font, size: 1, height: 0.5, curveSegments: 1, }) newGeometry.center() const textCSG = CSG.fromGeometry(newGeometry) var engraved = engravedCSG.subtract(textCSG) engravedMesh.geometry.dispose() engravedMesh.geometry = CSG.toMesh( engraved, engravedMesh.matrixWorld ).geometry }
内容的提问来源于stack exchange,提问作者Arnaud Coutant
相关产品推荐
相关产品推荐

