ThreeJS使用CSG对拉伸几何体做交集运算出现多余漂浮部件
多视图轮廓拉伸后CSG交集运算产生多余漂浮部件问题
问题描述
对多个视图轮廓执行拉伸(extrude)操作后进行交集运算,期望生成最终多边形,但运算结果不符合预期,存在多处漂浮的多余部件。需要找到对应问题修复方案,可检测并删除这些多余漂浮部件的方案也可接受。
实现代码
使用three-csg-ts@3.1.10库执行交集布尔运算,暂不确定是库本身存在bug还是使用方式有误,已尝试调整多种extrudeSettings拉伸配置参数,问题仍存在。相关实现代码如下:
import './style.css' import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' import { CSG } from 'three-csg-ts' // Canvas const canvas = document.querySelector('canvas.webgl') /** * Sizes */ const sizes = { width: 1677, height: 1287 } // Scene const scene = new THREE.Scene() // View Points const view_1 = [1019, 516, 1005, 502, 968, 481, 944, 482, 911, 492, 902, 505, 892, 510, 879, 522, 880, 595, 889, 612, 899, 619, 941, 621, 998, 620, 1011, 615, 1018, 599, 1017, 594, 1022, 575, 1023, 541] const view_2 = [874.9, 221, 878.4, 274.3, 888.2, 296.3, 893.9, 306.1, 902.5, 320.9, 916.5, 327.1, 937.6, 337.1, 960, 329.6, 973.8, 323.1, 983.5, 314.6, 994.3, 307.3, 1008.4, 297.5, 1018, 271, 1019, 253, 1019.1, 239.5, 1006.5, 230, 996.6, 225.2, 987.8, 218.9, 958.8, 204.1, 939.5, 198.9, 892.7, 203.7] const view_3 = [1002, 867, 985.9, 885.3, 984.7, 918.4, 986.7, 931, 994.9, 941.1, 1001.2, 957.6, 1015, 970.1, 1028.9, 980.9, 1046, 982.2, 1061.3, 980.9, 1077.6, 968.8, 1100.4, 945.5, 1103.4, 900.7, 1093.1, 879.7, 1077.1, 864, 1064.4, 855.6, 1053, 856.9, 1046, 853.7, 1025.7, 856.9, 1012, 859.4] const view_4 = [619, 648, 592, 681, 597, 702, 607, 719.3, 624.5, 725.9, 646.2, 731.7, 658.2, 735.7, 669.3, 739.3, 680, 742.3, 690.3, 737.5, 697.1, 726.6, 690.1, 711.5, 686, 706, 683, 694, 683, 682, 674, 663, 668, 660, 659, 649, 650, 647, 644, 642, 629, 643] const view_5 = [1282, 499, 1261, 504, 1256, 509, 1255.7, 508.2, 1251.4, 509.9, 1240, 515.5, 1227.7, 527.7, 1212.2, 587.7, 1210.9, 609, 1213.9, 615.8, 1216, 617.8, 1219.7, 623.3, 1226, 628.6, 1259.3, 625.1, 1267, 615, 1280, 561] const views = [view_1,view_2,view_3, view_4, view_5] //Split array in pairs function chunk(arr, size) { return Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size)) } //Shape constructor and extruder const extrudeSettings = { steps: 8, depth: 600, bevelEnabled: false, bevelThickness: 1, bevelSize: 0, bevelOffset: 0, bevelSegments: 1 }; var degree = 0 var pos = 0 var meshes = [] for(let view in views){ var point_list = [] var pair_array = chunk(views[view],2) //separate in pairs for (let pair in pair_array){ point_list.push(new THREE.Vector2(-pair_array[pair][0]+sizes.width/2,-pair_array[pair][1]+sizes.height/2)) //creating vectors } console.log(point_list) var shape = new THREE.Shape(point_list); //constructing the Shape extrudeSettings.depth = 600 var shapeGeom = new THREE.ExtrudeGeometry( shape, extrudeSettings ); //Extruding the shape //position transformations shapeGeom.rotateX(Math.PI * 0.5); shapeGeom.rotateZ(THREE.MathUtils.degToRad(degree)); degree += 45 const shapeMat = new THREE.MeshPhongMaterial({color: "aqua"}); shapeMat.side = THREE.DoubleSide var shapeMesh = new THREE.Mesh(shapeGeom, shapeMat); //more position transformations shapeMesh.geometry.computeBoundingBox(); var boundingBox = new THREE.Box3(); boundingBox.copy( shapeMesh.geometry.boundingBox ); shapeMesh.updateMatrixWorld( true ); // ensure world matrix is up to date boundingBox.applyMatrix4( shapeMesh.matrixWorld ); shapeMesh.position.x = shapeMesh.position.x - (boundingBox.min.x + boundingBox.max.x)/2 shapeMesh.position.y = shapeMesh.position.y - (boundingBox.min.y + boundingBox.max.y)/2 shapeMesh.position.z = shapeMesh.position.z - (boundingBox.min.z + boundingBox.max.z)/2 //adding to the scene shapeMesh.updateMatrix() meshes.push(shapeMesh) scene.add(shapeMesh); //comment if doesn't want to show the extruded shapes, but only the final result } //Intersection var intersection = meshes[0] for (let mesh in meshes){ meshes[mesh].updateMatrix() intersection = CSG.intersect(intersection,meshes[mesh]) } intersection.material = new THREE.MeshNormalMaterial() scene.add(intersection) // Lights scene.add( new THREE.HemisphereLight(0xffffbb,0x080820,2) ); /** * Camera */ // Base camera const camera = new THREE.OrthographicCamera( sizes.width / - 2, sizes.width / 2, sizes.height / 2, sizes.height / - 2, 0.1, 3000 ); camera.position.set( 0, 800, 0 ); camera.up = new THREE.Vector3( 0, 0, 1 ); scene.add(camera) var camera_pivot = new THREE.Object3D() scene.add( camera_pivot ); camera.lookAt( camera_pivot.position ); // Controls const controls = new OrbitControls(camera, canvas) controls.enableDamping = true /** * Renderer */ const renderer = new THREE.WebGLRenderer({ canvas: canvas, preserveDrawingBuffer: true }) renderer.setSize(sizes.width, sizes.height) renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) /** * Animate */ const clock = new THREE.Clock() const tick = () => { const elapsedTime = clock.getElapsedTime() // Update Orbital Controls controls.update() // Render renderer.render(scene, camera) // Call tick again on the next frame window.requestAnimationFrame(tick) } tick()
问题效果截图
- 拉伸后的各形状效果:

- 交集运算异常结果(存在漂浮多余部件):

已尝试排查操作
- 调整多种
extrudeSettings拉伸配置参数,问题未解决 - 调整交集运算顺序,尝试两两运算后再对交集结果做合并运算,问题未解决
- 初步推测问题可能出在拉伸方法的使用上,但暂未找到正确实现方式
内容的提问来源于stack exchange,提问作者Matheus Chaves
相关产品推荐
相关产品推荐

