Spaces:
Sleeping
Sleeping
| //import*as THREE from "./lib/three.module.js"; | |
| import * as THREE from "three" //"https://threejs.org/build/three.module.js"; | |
| let { BufferGeometry, Vector3, Vector2} = THREE; | |
| import {CSG, Vertex, Vector, Polygon} from "./csglib.js"; | |
| //import {Geometry} from "../three.js-dev/examples/jsm/deprecated/Geometry.js"; | |
| CSG.fromGeometry = function(geom,objectIndex) { | |
| let polys = [] | |
| if (geom.isGeometry) { | |
| let fs = geom.faces; | |
| let vs = geom.vertices; | |
| let fm = ['a', 'b', 'c'] | |
| for (let i = 0; i < fs.length; i++) { | |
| let f = fs[i]; | |
| let vertices = [] | |
| for (let j = 0; j < 3; j++) | |
| vertices.push(new Vertex(vs[f[fm[j]]],f.vertexNormals[j],geom.faceVertexUvs[0][i][j])) | |
| polys.push(new Polygon(vertices, objectIndex)) | |
| } | |
| } else if (geom.isBufferGeometry) { | |
| let vertices, normals, uvs | |
| 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 | |
| },uvattr&&{ | |
| x: uvattr.array[vt], | |
| y: uvattr.array[vt+1], | |
| z: 0 | |
| },colorattr&&{x:colorattr.array[vt],y:colorattr.array[vt+1],z:colorattr.array[vt+2]}); | |
| } | |
| polys[pli] = new Polygon(vertices,objectIndex) | |
| } | |
| } else | |
| console.error("Unsupported CSG input type:" + geom.type) | |
| 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.toGeometry = function(csg, buffered=true) { | |
| let ps = csg.polygons; | |
| let geom; | |
| let g2; | |
| if(!buffered) //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; | |
| }else { //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){ | |
| if(pvs[0].color!==undefined){ | |
| if(!colors)colors = nbuf3(triCount*3*3); | |
| } | |
| if(pvs[0].uv!==undefined){ | |
| if(!uvs)uvs = nbuf2(triCount * 2 * 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&&(pvs[0].uv)&&(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)); | |
| uvs && 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; | |
| } | |
| return geom; | |
| } | |
| CSG.toMesh = function(csg, toMatrix=new THREE.Matrix4(), toMaterial) { | |
| let geom = CSG.toGeometry(csg); | |
| 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 | |
| } | |
| import "./csgworker.js"; | |
| export {CSG} |