"use strict" import * as THREE from '../node_modules/three/src/Three'; import { CSG, Vertex, Polygon } from "./csg-lib.js" CSG.fromGeometry = function (geom, objectIndex) { if (!geom.isBufferGeometry) { console.error("Unsupported CSG input type:" + geom.type) return } let polys = [] let posattr = geom.attributes.position let normalattr = geom.attributes.normal let uvattr = geom.attributes.uv let colorattr = geom.attributes.color let index; if (geom.index) index = geom.index.array; else { index = new Array((posattr.array.length / posattr.itemSize) | 0); for (let i = 0; i < index.length; i++) index[i] = i } let triCount = (index.length / 3) | 0 polys = new Array(triCount) for (let i = 0, pli = 0, l = index.length; i < l; i += 3, pli++) { let vertices = new Array(3) for (let j = 0; j < 3; j++) { let vi = index[i + j] let vp = vi * 3; let vt = vi * 2; let x = posattr.array[vp] let y = posattr.array[vp + 1] let z = posattr.array[vp + 2] let nx = normalattr.array[vp] let ny = normalattr.array[vp + 1] let nz = normalattr.array[vp + 2] let u = uvattr.array[vt] let v = uvattr.array[vt + 1] vertices[j] = new Vertex({ x, y, z }, { x: nx, y: ny, z: nz }, { x: u, y: v, z: 0 }, colorattr && { x: colorattr.array[vt], y: colorattr.array[vt + 1], z: colorattr.array[vt + 2] }); } polys[pli] = new Polygon(vertices, objectIndex) } return CSG.fromPolygons(polys) } let ttvv0 = new THREE.Vector3() let tmpm3 = new THREE.Matrix3(); CSG.fromMesh = function (mesh, objectIndex) { let csg = CSG.fromGeometry(mesh.geometry, objectIndex) tmpm3.getNormalMatrix(mesh.matrix); for (let i = 0; i < csg.polygons.length; i++) { let p = csg.polygons[i] for (let j = 0; j < p.vertices.length; j++) { let v = p.vertices[j] v.pos.copy(ttvv0.copy(v.pos).applyMatrix4(mesh.matrix)); v.normal.copy(ttvv0.copy(v.normal).applyMatrix3(tmpm3)) } } return csg; } let nbuf3 = (ct) => { return { top: 0, array: new Float32Array(ct), write: function (v) { (this.array[this.top++] = v.x); (this.array[this.top++] = v.y); (this.array[this.top++] = v.z); } } } let nbuf2 = (ct) => { return { top: 0, array: new Float32Array(ct), write: function (v) { (this.array[this.top++] = v.x); (this.array[this.top++] = v.y) } } } CSG.toMesh = function (csg, toMatrix, toMaterial) { let ps = csg.polygons; let geom; let g2; if (0) //Old geometry path... { geom = new Geometry(); let vs = geom.vertices; let fvuv = geom.faceVertexUvs[0] for (let i = 0; i < ps.length; i++) { let p = ps[i] let pvs = p.vertices; let v0 = vs.length; let pvlen = pvs.length for (let j = 0; j < pvlen; j++) vs.push(new THREE.Vector3().copy(pvs[j].pos)) for (let j = 3; j <= pvlen; j++) { let fc = new THREE.Face3(); let fuv = [] fvuv.push(fuv) let fnml = fc.vertexNormals; fc.a = v0; fc.b = v0 + j - 2; fc.c = v0 + j - 1; fnml.push(new THREE.Vector3().copy(pvs[0].normal)) fnml.push(new THREE.Vector3().copy(pvs[j - 2].normal)) fnml.push(new THREE.Vector3().copy(pvs[j - 1].normal)) fuv.push(new THREE.Vector3().copy(pvs[0].uv)) fuv.push(new THREE.Vector3().copy(pvs[j - 2].uv)) fuv.push(new THREE.Vector3().copy(pvs[j - 1].uv)) fc.normal = new THREE.Vector3().copy(p.plane.normal) geom.faces.push(fc) } } geom = new THREE.BufferGeometry().fromGeometry(geom) geom.verticesNeedUpdate = geom.elementsNeedUpdate = geom.normalsNeedUpdate = true; } if (1) { //BufferGeometry path let triCount = 0; ps.forEach(p => triCount += (p.vertices.length - 2)) geom = new THREE.BufferGeometry() let vertices = nbuf3(triCount * 3 * 3) let normals = nbuf3(triCount * 3 * 3) let uvs = nbuf2(triCount * 2 * 3) let colors; let grps = [] ps.forEach(p => { let pvs = p.vertices let pvlen = pvs.length if (p.shared !== undefined) { if (!grps[p.shared]) grps[p.shared] = [] } if (pvlen && pvs[0].color !== undefined) { if (!colors) colors = nbuf3(triCount * 3 * 3); } for (let j = 3; j <= pvlen; j++) { (p.shared !== undefined) && (grps[p.shared].push(vertices.top / 3, (vertices.top / 3) + 1, (vertices.top / 3) + 2)); vertices.write(pvs[0].pos) vertices.write(pvs[j - 2].pos) vertices.write(pvs[j - 1].pos) normals.write(pvs[0].normal) normals.write(pvs[j - 2].normal) normals.write(pvs[j - 1].normal) uvs.write(pvs[0].uv) uvs.write(pvs[j - 2].uv) uvs.write(pvs[j - 1].uv) colors && (colors.write(pvs[0].color) || colors.write(pvs[j - 2].color) || colors.write(pvs[j - 1].color)) } } ) geom.setAttribute('position', new THREE.BufferAttribute(vertices.array, 3)); geom.setAttribute('normal', new THREE.BufferAttribute(normals.array, 3)); geom.setAttribute('uv', new THREE.BufferAttribute(uvs.array, 2)); colors && geom.setAttribute('color', new THREE.BufferAttribute(colors.array, 3)); if (grps.length) { let index = [] let gbase = 0; for (let gi = 0; gi < grps.length; gi++) { geom.addGroup(gbase, grps[gi].length, gi) gbase += grps[gi].length index = index.concat(grps[gi]); } geom.setIndex(index) } g2 = geom; } let inv = new THREE.Matrix4().copy(toMatrix).invert(); geom.applyMatrix4(inv); geom.computeBoundingSphere(); geom.computeBoundingBox(); let m = new THREE.Mesh(geom, toMaterial); m.matrix.copy(toMatrix); m.matrix.decompose(m.position, m.quaternion, m.scale) m.rotation.setFromQuaternion(m.quaternion) m.updateMatrixWorld(); m.castShadow = m.receiveShadow = true; return m } export default CSG