Hello, I am sort of new to using boolean
I am using three.bvh.csg
and i have this
what I am wondering is if it is possible to boolean the meshes, and then extract each split so that i have separate meshes?
I looked into groups but I dont think thats the way. Any one know how to do this?
drcmda
2
const calcParts = (result: THREE.Mesh) => {
let parts: THREE.BufferGeometry[] = []
const posMap = {}
const positions = result.geometry.attributes.position
if (positions.count === 0) return []
const normals = result.geometry.attributes.normal
const uvs = result.geometry.attributes.uv
const cache = {}
const hashify = (i) => {
if (cache[i]) return cache[i]
cache[i] = positions.getX(i).toFixed(2) + positions.getY(i).toFixed(2) + positions.getZ(i).toFixed(2)
return cache[i]
}
for (let i = 0; i < positions.count; i += 3) {
const vert1 = hashify(i)
const vert2 = hashify(i + 1)
const vert3 = hashify(i + 2)
if (!posMap[vert1]) posMap[vert1] = []
if (!posMap[vert2]) posMap[vert2] = []
if (!posMap[vert3]) posMap[vert3] = []
posMap[vert1].push(vert2, vert3)
posMap[vert2].push(vert1, vert3)
posMap[vert3].push(vert1, vert2)
}
let noPoses = {}
while (Object.keys(noPoses).length < positions.count) {
const availableIs: number[] = [] //Array(positions.length).fill()
for (let i = 0; i < positions.count; i++) {
if (!noPoses[hashify(i)]) availableIs.push(i)
}
if (availableIs.length === 0) break
const randomPos = hashify(availableIs[0])
const posesCollected = {}
const posesToGoThrough = [randomPos]
while (true) {
if (posesToGoThrough.length === 0) break
const pos = posesToGoThrough.pop()
posesCollected[pos] = true
const cs = posMap[pos]
for (let i = 0; i < cs.length; i++) {
if (!posesCollected[cs[i]]) posesToGoThrough.push(cs[i])
}
}
const part = new THREE.BufferGeometry()
const newPositions: number[] = []
const newNormals: number[] = []
const newUvs: number[] = []
const madeTries: { [key: string]: boolean } = {}
for (let i = 0; i < positions.count; i += 3) {
const vert1 = hashify(i)
const vert2 = hashify(i + 1)
const vert3 = hashify(i + 2)
const combined = vert1 + vert2 + vert3
if (posesCollected[vert1] && posesCollected[vert2] && posesCollected[vert3] && !madeTries[combined]) {
madeTries[vert1 + vert2 + vert3] = true
madeTries[vert2 + vert3 + vert1] = true
madeTries[vert3 + vert1 + vert2] = true
noPoses[vert1] = true
noPoses[vert2] = true
noPoses[vert3] = true
newPositions.push(positions.getX(i), positions.getY(i), positions.getZ(i))
newPositions.push(positions.getX(i + 1), positions.getY(i + 1), positions.getZ(i + 1))
newPositions.push(positions.getX(i + 2), positions.getY(i + 2), positions.getZ(i + 2))
newNormals.push(normals.getX(i), normals.getY(i), normals.getZ(i))
newNormals.push(normals.getX(i + 1), normals.getY(i + 1), normals.getZ(i + 1))
newNormals.push(normals.getX(i + 2), normals.getY(i + 2), normals.getZ(i + 2))
newUvs.push(uvs.getX(i), uvs.getY(i))
newUvs.push(uvs.getX(i + 1), uvs.getY(i + 1))
newUvs.push(uvs.getX(i + 2), uvs.getY(i + 2))
}
}
part.setAttribute('position', new THREE.BufferAttribute(new Float32Array(newPositions), 3))
part.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(newNormals), 3))
part.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(newUvs), 3))
parts.push(part)
}
return parts
}
you use it like this:
const meshes = calcParts(mergedMesh)
real world example, it’s using csg to slice suzi, and then uses calcParts to obtain the resulting fragments:
https://codesandbox.io/p/sandbox/csg-slice-k4qfiz?file=%2Fsrc%2Fparts.tsx
2 Likes