Threejs给物体最外圈加线框(被挖洞或者被切的物体都可以)
// 物体最外圈加线框(被挖洞或者被切的物体都可以)
addEdge(mesh: THREE.Mesh) {
let allVertices = [];
let vertices: THREE.Vector3[] = [];
// 物体最高点
let height = GlobalApi.mDangQianLouCeng.mCabinetClass.mCurUnit.H / 10;
for (let i = 0; i < mesh.geometry.attributes.position.array.length; i += 3) {
allVertices.push(new THREE.Vector3(mesh.geometry.attributes.position.array[i], mesh.geometry.attributes.position.array[i + 1], mesh.geometry.attributes.position.array[i + 2]));
}
// 此处每次提一个面的三个点,判断这三个点的y值是否等于最高点,如果是,就把这三个点放到vertices数组中(取mesh的最高面)
for (let i = 0; i < allVertices.length; i += 3) {
if (allVertices[i].y == height && allVertices[i + 1].y == height && allVertices[i + 2].y == height) {
vertices.push(allVertices[i], allVertices[i + 1], allVertices[i + 2]);
}
}
//转换成polybool需要的数据
let polyPos = [];
for (let i = 0; i < vertices.length; i += 3) {
polyPos.push([
[vertices[i].x, vertices[i].z],
[vertices[i + 1].x, vertices[i + 1].z],
[vertices[i + 2].x, vertices[i + 2].z]
])
}
let polyBool = require('polybooljs');
let resultPolyPos = polyPos[0];
//计算,并将结果保存到resultPolyPos中
//得到结果为外轮廓的点位
//TODO:当墙面被完全截断为两个或多个区域时,该方法会死循环
for (let i = 1; i < polyPos.length; i++) {
let result: any = polyBool.union({
regions: [resultPolyPos],
inverted: false
}, {
regions: [polyPos[i]],
inverted: false
});
// console.log(result.regions)
resultPolyPos = result.regions[0];
//当regions的长度大于1时,说明有多个区域,需要将多余的区域重新存储到polyPos中
if (result.regions.length > 1) {
polyPos.push(...(result.regions.splice(1)));
}
}
let resultVectors = [];
for (let i = 0; i < resultPolyPos.length; i++) {
resultVectors.push(new THREE.Vector3(resultPolyPos[i][0], height, resultPolyPos[i][1]));
}
let geoVertices = [];
for (let i = 0; i < resultVectors.length; i++) {
geoVertices.push(resultVectors[i].x, resultVectors[i].y, resultVectors[i].z);
}
geoVertices.push(geoVertices[0], geoVertices[1], geoVertices[2])
let edgeLineGeo = new THREE.BufferGeometry();
edgeLineGeo.setAttribute('position', new THREE.Float32BufferAttribute(geoVertices, 3));
let edgeLine = new THREE.Line(edgeLineGeo,
new THREE.LineBasicMaterial({
color: 0x00000,
opacity: 1,
}));
return edgeLine;
}