Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/flo-bit/shapecraft. flo-bit.dev/shapecraft
Something went wrong. Try again.
1.9 kB · 44 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445import * as THREE from 'three'import { Evaluator, Brush, ADDITION, SUBTRACTION, INTERSECTION } from 'three-bvh-csg'import { Mesh } from '../core/mesh'
// Constructive solid geometry via three-bvh-csg (BVH-accelerated, robust). Carries// position/normal/color through cuts so baked vertex colors survive.
const evaluator = new Evaluator()evaluator.attributes = ['position', 'normal', 'color']evaluator.useGroups = false
/** three-bvh-csg requires both operands to share the same attribute set. */function prep(mesh: Mesh): THREE.BufferGeometry { let geo = mesh.geometry.clone() if (geo.getIndex()) geo = geo.toNonIndexed() if (!geo.getAttribute('normal')) geo.computeVertexNormals() if (!geo.getAttribute('color')) { const colors = new Float32Array(geo.getAttribute('position').count * 3) colors.fill(1) geo.setAttribute('color', new THREE.BufferAttribute(colors, 3)) } return geo}
export type BooleanOp = 'union' | 'subtract' | 'intersect'
/** Combine two meshes with a constructive-solid-geometry operation. */export function boolean(a: Mesh, b: Mesh, op: BooleanOp): Mesh { const brushA = new Brush(prep(a)) brushA.updateMatrixWorld() const brushB = new Brush(prep(b)) brushB.updateMatrixWorld()
const csgOp = op === 'union' ? ADDITION : op === 'subtract' ? SUBTRACTION : INTERSECTION const result = evaluator.evaluate(brushA, brushB, csgOp) return new Mesh((result.geometry as THREE.BufferGeometry).clone())}
/** Boolean union — the outer shell of both volumes. */export function union(a: Mesh, b: Mesh): Mesh { return boolean(a, b, 'union') }/** Boolean difference — `a` with `b` carved out of it. */export function subtract(a: Mesh, b: Mesh): Mesh { return boolean(a, b, 'subtract') }/** Boolean intersection — only the volume shared by both. */export function intersect(a: Mesh, b: Mesh): Mesh { return boolean(a, b, 'intersect') }