@csi-foxbyte/cityjson-to-3d-tiles
Version:
A Node.js library that converts CityJSON files into Cesium 3D Tiles—complete with automatic texture atlas packing, Basis compression, three LOD levels, and customizable threading.
2 lines • 2.29 kB
JavaScript
import P from'sharp';import {MaxRectsPacker}from'maxrects-packer/dist/maxrects-packer.js';async function j(c,M=1,x=8192,U=false,B=true){const R=c.getRoot(),X=c.createMaterial("base"),D=[];for(const e of R.listScenes())e.traverse(g=>{const h=g.getMesh();if(!h)return;const f=h.listPrimitives();for(const a of f){const s=a.getMaterial();if(!s)continue;const t=s.getBaseColorTexture();if(!t)continue;const o=t.getMimeType(),n=t.getSize();!o||!n||(D.push({width:Math.floor(n[0]*M),height:Math.floor(n[1]*M),getImageData:()=>t.getImage(),disposeTexture:()=>t.dispose(),imageName:s.getName(),primitive:a,id:crypto.randomUUID()}),a.setMaterial(X));}});const m=new Map;D.forEach(e=>{m.has(e.imageName)?m.get(e.imageName).primitives.push(e.primitive):m.set(e.imageName,{height:e.height,width:e.width,disposeTexture:e.disposeTexture,getImageData:e.getImageData,primitives:[e.primitive]});});const I=new MaxRectsPacker(x,x,0,{allowRotation:false,pot:B,smart:true,square:false,border:0,logic:1});I.addArray(Array.from(m.values()));let b=[];for(const e of I.bins){const g=[];for(const t of e.rects){const o=P(t.getImageData()).resize({width:t.width,height:t.height});g.push({input:t.rot?await o.rotate(90).toBuffer():await o.toBuffer(),top:t.y,premultiplied:true,left:t.x});}const h=await P({create:{width:e.width,height:e.height,background:{r:128,g:128,b:128,alpha:0},channels:4},limitInputPixels:false}).composite(g).toFormat("png").toBuffer();for(const t of e.rects)t.disposeTexture();const f=crypto.randomUUID(),a=c.createMaterial(f),s=c.createTexture("base");s.setMimeType("image/png"),s.setImage(h),U&&b.push({texture:s,name:f}),a.setBaseColorTexture(s),a.setDoubleSided(true);for(const{primitives:t,x:o,y:n,width:A,height:N,rot:k}of e.rects)for(const u of t){const p=u.getAttribute("TEXCOORD_0");if(!p)continue;const r=p.getArray();if(r){if(k){const l=N/e.height,d=A/e.width,v=n/e.height,w=o/e.width;for(let i=0;i<r.length;i+=2){const T=r[i+1]*l+v,y=r[i]*d+w;r[i]=T,r[i+1]=y;}}else {const l=A/e.width,d=N/e.height,v=o/e.width,w=n/e.height;for(let i=0;i<r.length;i+=2){const T=r[i]*l+v,y=r[i+1]*d+w;r[i]=T,r[i+1]=y;}}u.getMaterial()?.dispose(),p.setArray(r),u.setMaterial(a);}}}return b}export{j as mergeTextures};//# sourceMappingURL=mergeTextures.js.map
//# sourceMappingURL=mergeTextures.js.map